diff --git a/pypcc/config/RECVTR_HB.yaml b/pypcc/config/RECVTR_HB.yaml index 52745e356ddd292bd97600c47011357b139bfbf7..c930a92934ef51048e6d440b39c4846efdeb43c5 100644 --- a/pypcc/config/RECVTR_HB.yaml +++ b/pypcc/config/RECVTR_HB.yaml @@ -6,6 +6,7 @@ drivers: - name: I2C1 #TCA9548 type: i2c_switch devreg: [0x70,0x71,0x72,0x73] +# devreg: [] parameters: [1] #I2C port number parent: I2C_reset_GPIO - name: I2C_reset_GPIO @@ -14,6 +15,7 @@ drivers: - name: I2C_RCU type: i2c_array #An array of similar devices connected to an I2C switch parent: I2C1 +# parameters: [0,32,32,32, 32,32,32,32, 32,32,32,32, 32,32,32,32, 32,32,32,32, 32,32,32,32, 32,32,32,32, 32,32,32,32] #RCU lookup table parameters: [20,22,0,2, 4,6,10,12, 14,16,18,24, 26,28,30,8, 7,5,3,1, 23,21,19,13, 11,9,15,17, 31,29,27,25] #RCU lookup table I2Ccut: 35 #error count to disable I2C (14 for LTS?) status: RECVTR_I2C_error @@ -21,7 +23,10 @@ drivers: type: hba1 #Special driver to manage HBAT1s. parent: I2C_RCU devreg: [0x40.0xFF] #I2C broadcast register - parameters: [24] #PPS GPIO pin + parameters: [24] #PPS GPIO pin + - name: I2C_AHBAT + type: hba2 #Special driver to manage AHBATs. + parent: I2C_RCU - name: I2Cbb1 type: i2cbitbangp #I2C bitbang via GPIO expander devreg: [IO3.GPIO2,IO3.GPIO2,IO3.CONF2] @@ -180,6 +185,20 @@ device_registers: address: 127 description: HBAT server version + - name: AHBAT + dim: 3 + address: [0x41,0x42,0x43] + description: Virtual AHBAT interface + driver: I2C_AHBAT + registers: + - {name: UID,address: 0x04} + - {name: SW_version,address: 0x0C} + - {name: config,address: 0x10} + - {name: config2,address: 0x18} + - {name: PCB_version,address: 0x24} + - {name: PCB_number,address: 0x32} + - {name: ADC,address: 0x50} + - name: ADC dim: 3 description: ADC SPI control @@ -255,20 +274,20 @@ variables: rw: variable dtype: uint8 - - name: ANT_mask - description: Only RF chains with a true mask is set + - name: RCU_mask + description: Only RCUs with a true mask is set driver: I2C_RCU rw: variable #server RW variable, not linked to IO dtype: boolean - dim: 96 - dim2: [3,32] + dim: 32 - - name: RCU_mask - description: Only RCUs with a true mask is set + - name: ANT_mask + description: Only RF chains with a true mask is set driver: I2C_RCU rw: variable #server RW variable, not linked to IO dtype: boolean - dim: 32 + dim: 96 + dim2: [3,32] - name: RECVTR_I2C_error description: 0=Good, >0 communication error @@ -729,6 +748,7 @@ variables: dim2: [32,96] mask: ANT_mask wait: 1000 + - name: HBAT_PWR_LNA_on description: HBA frontend LNA driver: I2C_HBAT @@ -740,7 +760,8 @@ variables: dim: 3072 dim2: [32,96] mask: ANT_mask - wait: 1000 + wait: 0 + - name: HBAT_PWR_on description: HBA frontend power driver: I2C_HBAT @@ -753,18 +774,136 @@ variables: dim: 3072 dim2: [32,96] mask: ANT_mask - wait: 1000 + wait: 0 -# - name: [RCU_uC_VPP,RCU_uC_PGC,RCU_uC_PGD] -# driver: I2C_RCU -# devreg: IO4.GPIO2 -# bitoffset: [0,3,0] -# width: 3 -# rw: rw -# dtype: uint8 -# dim: 96 -# dim2: [3,32] -# mask: ANT_mask + - name: [RCU_uC_VPP,RCU_uC_PGC,RCU_uC_PGD] + driver: I2C_RCU + devreg: IO4.GPIO2 + bitoffset: [0,3,0] + width: 3 + rw: rw + dtype: uint8 + debug: true + dim: 96 + dim2: [3,32] + mask: ANT_mask + +#DANTE points + - name: AHBAT_mask + description: DANTE tiles + driver: I2C_RCU + rw: variable #server RW variable, not linked to IO + dtype: boolean + dim: 96 + dim2: [3,32] + + - name: AHBAT_config1 + description: DANTE UID 8bytes + driver: I2C_AHBAT + devreg: [AHBAT1.config,AHBAT2.config,AHBAT3.config] + width: 64 + rw: ro + dtype: uint64 + dim: 1536 + dim2: [16,96] + mask: AHBAT_mask + wait: 700 + + - name: AHBAT_config2 + description: DANTE UID 8bytes + driver: I2C_AHBAT + devreg: [AHBAT1.config2,AHBAT2.config2,AHBAT3.config2] + width: 64 + rw: ro + dtype: uint64 + dim: 1536 + dim2: [16,96] + mask: AHBAT_mask + wait: 700 + + - name: AHBAT_UID + description: DANTE UID 8bytes + driver: I2C_AHBAT + devreg: [AHBAT1.UID,AHBAT2.UID,AHBAT3.UID] + width: 64 + rw: ro + dtype: uint64 + dim: 1536 + dim2: [16,96] + endian: "<" + mask: AHBAT_mask + wait: 700 + + - name: AHBAT_software_version + description: DANTE software version + driver: I2C_AHBAT + devreg: [AHBAT1.SW_version,AHBAT2.SW_version,AHBAT3.SW_version] + width: 32 + rw: ro + dtype: uint32 + dim: 1536 + dim2: [16,96] + endian: "<" + mask: AHBAT_mask + wait: 700 + + - name: AHBAT_PCB_version + description: DANTE PCB version + driver: I2C_AHBAT + devreg: [AHBAT1.PCB_version,AHBAT2.PCB_version,AHBAT3.PCB_version] + width: 80 + rw: ro + dtype: string + dim: 1536 + dim2: [16,96] + mask: AHBAT_mask + wait: 1000 + + - name: AHBAT_PCB_number + description: DANTE PCB number + driver: I2C_AHBAT + devreg: [AHBAT1.PCB_number,AHBAT2.PCB_number,AHBAT3.PCB_number] + width: 80 + rw: ro + dtype: string + dim: 1536 + dim2: [16,96] + mask: AHBAT_mask + wait: 1000 + + - name: AHBAT_ADC + description: DANTE ADC values + driver: I2C_AHBAT + devreg: [AHBAT1.ADC,AHBAT2.ADC,AHBAT3.ADC] + width: 64 + rw: ro + dtype: uint64 + dim: 1536 + dim2: [16,96] + mask: AHBAT_mask + endian: "<" + wait: 700 + + - name: AHBAT_ADC_trigger + description: DANTE ADC trigger + driver: I2C_AHBAT + devreg: [AHBAT1.ADC,AHBAT2.ADC,AHBAT3.ADC] + width: 8 + rw: ro + dtype: uint8 + dim: 96 + dim2: [1,96] + mask: AHBAT_mask + wait: 700 + + - name: AHBAT_dummy + description: nothing + driver: I2C_RCU + rw: variable #server RW variable, not linked to IO + dtype: boolean + debug: true + dim: 96 + dim2: [3,32] methods: @@ -794,6 +933,26 @@ methods: - RCU_IO4_GPIO1: Update #should be last, as it will fail for low-band - RCU_IO4_GPIO2: Update + - name: AHBAT_update + description: Read AHBAT settings (UID, ...) + driver: I2C_RCU + mask: AHBAT_mask + instructions: + - AHBAT_UID: Update + - AHBAT_software_version: Update + - AHBAT_config1: Update + - AHBAT_config2: Update + - AHBAT_PCB_version: Update + - AHBAT_PCB_number: Update + + - name: AHBAT_read_ADC + description: Read AHBAT ADCs + driver: I2C_RCU + mask: AHBAT_mask + instructions: + - AHBAT_ADC_trigger: [0xFF,0xFF,0xFF] + - AHBAT_ADC: Update + - name: RCU_on description: Initialize RCU and put it in the ON state driver: I2C_RCU @@ -849,17 +1008,18 @@ methods: - IO4.CONF2: 0xF8 #Configure registers on RCU microcontroller - HB_UC.waitPPS: 1 #wait for PPS - - HBAT1.XY : [0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80] - - HBAT2.XY : [0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80] - - HBAT3.XY : [0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80] - - HBAT_PWR_LNA_on : Update - - HBAT_PWR_on : Update # - HB_UC.VREF: 0x0C -# - HB_UC.VREF: 8 #lower for DANTE + - HB_UC.VREF: 8 #lower for DANTE # - HB_UC.TXdelay : 32 #delay for broken DANTE frontend -# - HB_UC.0x0b : 0xf0 #timeouts for DANTE -# - HB_UC.0x09 : 0x0a #timeouts for DANTE -# - HB_UC.0x05 : 0 #auto readback off +## - HB_UC.0x0b : 0xf0 #timeouts for DANTE +## - HB_UC.0x09 : 0x0a #timeouts for DANTE +# - HB_UC.0x05 : 0 #auto readback 0=off +## - HB_UC.0x12 : 32 #start high +# - HBAT1.XY : [0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80] +# - HBAT2.XY : [0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80] +# - HBAT3.XY : [0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80] + - HBAT_PWR_LNA_on : 1 + - HBAT_PWR_on : 0 - RCU_update: 0 # - RCU_GPIO1: Update diff --git a/pypcc/i2cserv/hba1.py b/pypcc/i2cserv/hba1.py index 22be0356ef9b0c8034b0992dbfe4d45099f5513b..f86fe4d8a2bc57d6f1e23c2b9b9e37507591a327 100644 --- a/pypcc/i2cserv/hba1.py +++ b/pypcc/i2cserv/hba1.py @@ -27,6 +27,13 @@ class hba1(hwdev): def OPCUASetVariable(self,varid,var1,data,mask): logging.info(str(("HBA set Var",var1['name'],len(data),len(mask),data[:32*3],mask[:12]))) + if var1.get('wait')==0: #Do not send, only update stored register + if len(data)<var1.get("dim"): + N=var1.get("dim")//len(data) + data=data*N + self.conf['parentcls'].SetStoredValue(var1,data,mask) + return self.OPCUAReadVariable(varid,var1,mask) + self.conf['parentcls'].SetGetVarValueMask(var1,data,mask,getalso=False) if len(mask)>0: RCUmask=[(mask[i*3] | mask[i*3+1] | mask[i*3+2]) for i in range(32)] @@ -72,20 +79,20 @@ class hba1(hwdev): logging.debug("SetHba addr=0x%x reg=0x%x",addr,reg) I2Ccallback=self.conf['parentcls'].i2csetget I2Ccallback(0x40,[0],read=1)#wakeup, do nothing -# sleep(0.005) + sleep(0.005) retry=0; - while not(I2Ccallback(addr,data[:16],reg=reg)) and (retry<2): retry+=1; + while not(I2Ccallback(addr,data,reg=reg)) and (retry<2): retry+=1; if retry==2: logging.warn("uC BF comm error"); - if len(data)>16: +# if len(data)>16: # sleep(0.005) - while not(I2Ccallback(addr,data[16:],reg=reg+16)) and (retry<2): retry+=1; - if retry>=2: logging.warn("uC BF comm error2"); - #sleep(0.01) +# while not(I2Ccallback(addr,data[16:],reg=reg+16)) and (retry<2): retry+=1; +# if retry>=2: logging.warn("uC BF comm error2"); + sleep(0.01) return True def gethba(self,addr,reg,data): I2Ccallback=self.conf['parentcls'].i2csetget -# logging.debug("getHba addr=0x%x reg=0x%x",addr,reg) + logging.debug("getHba addr=0x%x reg=0x%x",addr,reg) if not(I2Ccallback(addr,data,read=1)): return False; # I2Ccallback(addr,data,read=1); logging.debug("getHba addr=0x%x reg=0x%x data=%s",addr,reg,str((data))) diff --git a/pypcc/i2cserv/hba2.py b/pypcc/i2cserv/hba2.py new file mode 100644 index 0000000000000000000000000000000000000000..be12945c524d41d7a09c2ca0d01268bd37329853 --- /dev/null +++ b/pypcc/i2cserv/hba2.py @@ -0,0 +1,59 @@ +import numpy as np +from .hwdev import hwdev +import logging +from .i2c_array import ApplyMask +from time import sleep +from pypcc.queuetypes import * +import signal +try: + import RPi.GPIO as GPIO +except: + GPIO=False; + +class hba2(hwdev): + def __init__(self,config): + hwdev.__init__(self,config); + logging.info("HBA2 driver loaded") +# self.previousHBA=np.zeros([32,3,32],dtype='int') + self.sleep=1 #sec + + def OPCUASetVariable(self,varid,var1,data,mask): + logging.info(str(("AHBA set Var",var1['name'],len(data),len(mask),data[:32*3],mask[:12]))) + self.conf['parentcls'].SetGetVarValueMask(var1,data,mask,getalso=False) + if var1.get('wait'): + sleep(float(var1.get('wait'))/1000.) + return []; + + def OPCUAReadVariable(self,varid,var1,mask): + logging.warn(self.conf['name']+" HBAT2 ReadVariable %i %s",varid,var1["name"]) + if var1.get('wait'): + self.sleep=float(var1.get('wait'))/1000. + data,mask2=self.conf['parentcls'].GetVarValueMask(var1,mask) + Data=OPCUAset(varid,InstType.varSet,data.copy(),mask2.copy()) + return [Data] + + + def i2csetget(self,addr,data,reg=None,read=0): + if read==0: return self.sethba(addr,reg,data) + elif read==1: return self.gethba(addr,reg,data) + else: logging.warn("Not implemented!") + return False; + + def sethba(self,addr,reg,data): +# logging.warning("SetHba2 not implemented") + logging.info("setHba2 addr=0x%x reg=0x%x len=%i",addr,reg,len(data)) + I2Ccallback=self.conf['parentcls'].i2csetget + if not(I2Ccallback(addr,[reg,1,data[0]],reg=0x0e)): return False; + return True + + def gethba(self,addr,reg,data): + I2Ccallback=self.conf['parentcls'].i2csetget + logging.info("getHba2 addr=0x%x reg=0x%x len=%i",addr,reg,len(data)//16) + #request data + if not(I2Ccallback(addr,[reg,len(data)//16],reg=0x0C)): return False; + sleep(self.sleep) + I2Ccallback(addr,data,read=1); + logging.info("getHba addr=0x%x reg=0x%x data=%s",addr,reg,str((data))) +## if data is None: return False +# data[:]=[255]*len(data) + return True; diff --git a/pypcc/i2cserv/i2c_array.py b/pypcc/i2cserv/i2c_array.py index 6abe6f476de42aa7d1caab9fe30e18949c046fd8..21548141282c3733cff4ad5b97f6f33acc0bf159 100644 --- a/pypcc/i2cserv/i2c_array.py +++ b/pypcc/i2cserv/i2c_array.py @@ -243,6 +243,40 @@ class i2c_array(i2c_dev): logging.warn(str(("Identify RCUs:",check_val,self.enablemask))) return value1,mask + + def SetStoredValue(self,var1,data,mask): + Step,Step2=GetSteps(var1); + Step2//=self.N + if len(mask)==0: + mask=self.enablemask.copy() + if (len(mask)==self.N): + mask=[m for m in mask for x in range(Step)] + if not(len(mask)==Step*self.N): + logging.warning(str(("Check mask length!",len(mask),Step,self.N))); + return False +# print(self.N,Step,Step2,len(mask),len(data),mask) + for Vari in range(Step): + devreg=var1['devreg'][Vari]; + width=var1.get('width',8) + bitoffset=GetField(var1,'bitoffset',Vari,0) + if not(devreg.get('store')): continue + storearray=self.getstorearray(devreg); + for RCUi in self.RCUorder: + if not(mask[RCUi*Step+Vari]): continue + i0=(RCUi*Step+ Vari)*Step2 +# i1=(RCUi*Step+(Vari+1))*Step2 +# value2=data[i0:i1] + + previous=storearray[RCUi]; +# print(RCUi,previous,data[i0:i0+Step2]) +# for x in range(len(value2)): + value2=[ApplyMask(data[i0+x],width,bitoffset,(previous[x] if isinstance(previous,list) else previous)) for x in range(Step2)] + storearray[RCUi]=(value2[0] if len(value2)==1 else value2[:]) + logging.info(str(("Stored values:",self.getstorearray(devreg),'*',storearray[RCUi]))) + return True + + + def GetStoredValue(self,var1): Step,Step2=GetSteps(var1); value1=[0]*Step*Step2; @@ -261,7 +295,7 @@ class i2c_array(i2c_dev): try: value2[:]=storearray[RCUi] except: - logging.warning("RCU%iWrong size (no data?) in stored array"%(RCUi)) + logging.debug("RCU%i Wrong size (no data?) in stored array"%(RCUi)) # of len(storearray[RCUi]==0) # storearray[self.RCUi]=(value[0] if len(value)==1 else value[:]) l1=int(np.floor((width+bitoffset+7)/8)) diff --git a/pypcc/i2cserv/i2c_switch.py b/pypcc/i2cserv/i2c_switch.py index 7555621a6e63e29aa53660069617fa9de69fc87d..de7ca217bdc9f27bb57a437b16d6fee18ec651dd 100644 --- a/pypcc/i2cserv/i2c_switch.py +++ b/pypcc/i2cserv/i2c_switch.py @@ -45,6 +45,7 @@ class i2c_switch(i2c): self.newChannel=[0 for x in self.SWaddrs]+[0];#last one is a dummy def AddNewChannel(self,channelbit): + if self.NoSwitch: return True; SWn=(channelbit>>3); channel=1<<(channelbit & 0x07) self.newChannel[SWn]|=channel; diff --git a/scripts/AHBAT_test.py b/scripts/AHBAT_test.py new file mode 100644 index 0000000000000000000000000000000000000000..b3bf6dee874d70258f643f375cc8b098280839a0 --- /dev/null +++ b/scripts/AHBAT_test.py @@ -0,0 +1,115 @@ +from test_common import * +busy="RECVTR_translator_busy_R" +RCU=0 +AntMask=[False,True,False] + +connect() +set_value("RECVTR_monitor_rate_RW",0) + +if False: + setRCUmask([RCU]) + callmethod("RCU_on") + wait_not_busy(busy,timeout_sec=4) + + +setAntmask([RCU],AntMask) +wait_not_busy(busy,timeout_sec=4) + +#val,tp=get_value_type(name+"_R") +#set_value("HBAT_PWR_on_RW",[False]*(32*96)) +#set_value("HBAT_PWR_LNA_on_RW",[False]*(32*96)) +if False: + print("LEDs on") + set_value("HBAT_LED_on_RW",[True]*(32*96)) + wait_not_busy(busy,timeout_sec=4) + +setAntmask([RCU],AntMask,name="AHBAT_mask_RW") +wait_not_busy(busy,timeout_sec=4) + +sinr=1 + +if True: + print("Configuration:") + callmethod("AHBAT_update") + wait_not_busy(busy,timeout_sec=8) + +#print("UID",get_value("AHBAT_UID_R")[16*sinr:16*(sinr+1)]) + uid=get_value("AHBAT_UID_R")[16*sinr:16*(sinr+1)] +#print("UID",[hex(x) for x in uid]) + + swver=get_value("AHBAT_software_version_R")[16*sinr:16*(sinr+1)] +#print("SW ver",[('%08x'%x)[::-1] for x in swver]) + + PCBver=get_value("AHBAT_PCB_version_R")[16*sinr:16*(sinr+1)] + PCBnr=get_value("AHBAT_PCB_number_R")[16*sinr:16*(sinr+1)] +#print("PCB ver",PCBver) + config=get_value("AHBAT_config1_R")[16*sinr:16*(sinr+1)] + config2=get_value("AHBAT_config2_R")[16*sinr:16*(sinr+1)] + + for cnt,u1,s1,p1,c1,c2,n1 in zip(range(16),uid,swver,PCBver,config,config2,PCBnr): + print('%2i %016x %08x %016x%016x %s %s'%(cnt+1,u1,s1,c1,c2,p1,n1)) + +if True: + print("ADC values:") + callmethod("AHBAT_read_ADC") + wait_not_busy(busy,timeout_sec=8) + + uid=get_value("AHBAT_ADC_R")[16*sinr:16*(sinr+1)] + for cnt,val in enumerate(uid): + print('%2i %6i %6i %6i %6i'%(cnt+1,val&0xfff,(val>>16)&0xfff,(val>>32)&0xfff,(val>>48)&0xfff)) +# print("ADC",['%016x'%x for x in uid]) + +disconnect() +exit() + + + +name="HBAT_BF_delay_steps" +NewVal1=range(32) +NewVal2=[1]*32 +#NewValues=[NewVal1,NewVal2,NewVal1,NewVal2,NewVal1,NewVal2,NewVal1,NewVal2,NewVal1,NewVal2] +NewValues=[NewVal1,NewVal2] +DEBUG=True + +from test_common import * +import numpy as np +connect() + +i=(RCU*3)*32 + +val,tp=get_value_type(name+"_R") +if DEBUG: + print("Current values:"); + for x in range(3): print(val[i+x*32:i+(x+1)*32]) + +for cnt,NewVal in enumerate(NewValues): + + for x in range(3): val[i+x*32:i+(x+1)*32]=NewVal + + set_value(name+"_RW",val,tp) + if DEBUG: + print("set:") + for x in range(3): print(val[i+x*32:i+(x+1)*32]) + time.sleep(1) + wait_not_busy(busy,timeout_sec=4) +# time.sleep(0.1) + val=get_value(name+"_R") + if DEBUG: + print("readback:") + for x in range(3): print(val[i+x*32:i+(x+1)*32]) + + same=True; + for x in range(3): + for y in range(32): + if not(val[i+x*32+y]==NewVal[y]): same=False; + print(cnt+1,"Success" if same else "FAILED!") +#time.sleep(5) +#val[i:i+64]=[0]*64 + +#set_value(name+"_RW",val) +#print("set:",val[i:i+64]) +#time.sleep(1) +#val=get_value(name+"_R") +#print("new:",val[i:i+64]) + +disconnect() diff --git a/scripts/test_common.py b/scripts/test_common.py index df859d7c3044b7358475706ee8570f34d883cdb4..0d44120c302692af5601934896ccd67fd9f754f2 100644 --- a/scripts/test_common.py +++ b/scripts/test_common.py @@ -76,8 +76,7 @@ def setRCUmask(rcu=[]): set_value(name,M) # print(name," new:",get_value(name)) -def setAntmask(rcu=[],ant=[True,True,True]): - name="ANT_mask_RW" +def setAntmask(rcu=[],ant=[True,True,True],name="ANT_mask_RW"): M=get_value(name) # print(name," old:",M) for i,j in enumerate(M):