diff --git a/CRC_HBAT1.npy b/CRC_HBAT1.npy new file mode 100644 index 0000000000000000000000000000000000000000..c737267e6ea48a415beb618f8d8abbf5b3050a98 Binary files /dev/null and b/CRC_HBAT1.npy differ diff --git a/config/HBAT2.yaml b/config/HBAT2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d0e6c6871fb99fb6283160b38f3273fa41190bfd --- /dev/null +++ b/config/HBAT2.yaml @@ -0,0 +1,110 @@ +version: "1.0" +description: "1234" + +drivers: + - name: hbaio #TCA9548 + type: hbat_pico_io + parameters: ['COM3'] #serial port number + - name: hbat2 + type: i2c_array #An array of similar devices connected to an I2C switch + parent: hbaio + parameters: [1,4] #start,number of RCUs + status: HBAT2_COMM_STATUS + +#This is the I2C devices in the RCU +device_registers: + - name: BF + description: [BF board] + driver: hbaio + registers: + - name: X1 + address: 0x0 + store: True + - name: X2 + address: 0x1 + store: True + - name: X3 + address: 0x2 + store: True + - name: X4 + address: 0x3 + store: True + - name: Y + address: 0x4 + store: True + - name: SWX + address: 0x8 + store: True + - name: SWY + address: 0x9 + store: True + - name: FE_FE_PWR + address: 0xA + store: True + - name: FE_BF_PWR + address: 0xB + store: True + - name: ID + address: 0x10 + - name: VERSION + address: 0x14 + - name: ADDR + address: 0x20 + - name: VSENSE + address: 0x34 + - name: SAVE_EEPROM + address: 0x40 + - name: LOAD_EEPROM + address: 0x41 + + +variables: + - name: HBAT2_ANT_mask + description: Only masked RCUs are updated + driver: hbat2 + rw: variable #server RW variable, not linked to IO + dtype: boolean + dim: 16 + + - name: HBAT2_BF_mask + description: Only masked RCUs are updated + driver: hbat2 + rw: variable #server RW variable, not linked to IO + dtype: boolean + dim: 4 + + - name: HBAT2_COMM_STATUS + description: 0=Good, 1=No communication, 2=error + driver: hbat2 + rw: ro #server RW variable, not linked to IO + dtype: uint8 + mask: HBAT2_BF_mask + dim: 4 + + - name: DELAYS_X_G1 + description: Group1 delays + driver: hbat2 + devreg: [BF.X1,BF.X2,BF.X3,BF.X4] + bitoffset: 0 + width: 4 + rw: rw + dtype: uint8 + dim: 16 + mask: HBAT2_ANT_mask + + - name: DELAYS_X_G2 + description: Group2 delays + driver: hbat2 + devreg: [BF.X1] + bitoffset: 4 + width: 4 + rw: rw + dtype: uint8 + dim: 4 + mask: HBAT2_BF_mask + +methods: + - name: LOAD_EEPROM + driver: hbat2 + instructions: + - BF1.LOAD_EEPROM: 0 diff --git a/i2cserv/hbat2_array.py b/i2cserv/hbat2_array.py new file mode 100644 index 0000000000000000000000000000000000000000..28866d3679c49628d125cdac628ec391e8fd04f7 --- /dev/null +++ b/i2cserv/hbat2_array.py @@ -0,0 +1,16 @@ +import numpy as np +import logging +from queuetypes import * +from .hwdev import hwdev +from .i2c_dev import i2c_dev + +class hbat2_array(i2c_dev): + def __init__(self,config): + i2c_dev.__init__(self,config); + self.addr=config['parameters']; + self.N=len(self.addr); + self.I2Cmask=[0]*self.N +# self.disableI2ConError=True; + self.I2Cmaskid=config.get('maskid',None) + if self.I2Cmaskid is None: logging.warn(config['name']+" mask not found!") + diff --git a/i2cserv/hbat2raw.py b/i2cserv/hbat2raw.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/i2cserv/hbat_pico_io.py b/i2cserv/hbat_pico_io.py new file mode 100644 index 0000000000000000000000000000000000000000..c04e1020c5e19315fe4c66fe6d3e035161c8ab49 --- /dev/null +++ b/i2cserv/hbat_pico_io.py @@ -0,0 +1,169 @@ +from .hwdev import hwdev; +import logging +import serial +import numpy as np + +def NormDelays(D,offset=19,scale=20): + return [(d+offset)//scale for d in D] #shorter (inbetween) delay = waiting for FIFO + +def Decode(D2): + previous="0"; + res='' + for b in D2[:]: + if b>=6: #Start a new packet + #n=(8-len(res)%8)%8 + n=(len(res)//8)*8 + #res+=n*"0" + res=res[:n] + previous="0" +# print(n,res,previous) + else: + if previous=="0": + bit="0" if b<=2 else "01" + else: + if b==2: bit="1" + elif b==3: bit="0" + else: bit="01" +# print(previous,b,bit) + previous=bit[-1]; + res+=bit; +#print(res) + res=res[2:] +# print("len",len(res)//8) + S=[] + for x in range(len(res)//8): + v1=int(res[x*8:x*8+8],2) +# print(x,res[x*8:x*8+8],v1) + S.append(v1) + return(S) + +CRCtab=np.load("CRC_HBAT1.npy") +CRCtabl=[d%256 for d in CRCtab] +CRCtabh=[d//256 for d in CRCtab] +def CRCcheck(S1): + crcl=0;crch=0; + for b in S1: + i=crcl ^ b + crcl=crch ^ CRCtabl[i] + crch=CRCtabh[i] +# print(i,CRCtabh[i]) +# crch=crcl ^ CRCtabh[i] +# crcl= CRCtabl[i] + return crch*256+crcl + + +def MakeBroadcast(data,func=4,reg=0,serv1=1,serv2=16): + assert(len(data)==32) + data2=[func,reg,serv1,serv2]+data + l=len(data2)+1 + data2=[0,l]+data2 + CRC=CRCcheck(data2) + data2=data2+[CRC%256,CRC//256] + assert(CRCcheck(data2)==0) + return data2 + +def MakeRequest(serv,data=[],func=5,reg=0): + data2=[func,reg]+data + l=len(data2)+1 + data2=[serv,l]+data2 + CRC=CRCcheck(data2) + data2=data2+[CRC%256,CRC//256] + assert(CRCcheck(data2)==0) + return data2 + +#Mlookup=[0x55,0x56,0x59,0x5A,0x65,0x66,0x69,0x6A,0x95,0x96,0x99,0x9A,0xA5,0xA6,0xA9,0xAA] +Mlookup=[0xAA,0x6A,0x9A,0x5A,0xA6,0x66,0x96,0x56,0xA9,0x69,0x99,0x59,0xA5,0x65,0x95,0x55] + +def ManchesterEncode(data): +# Inverted: 0=input=high, 1=output=low. Applied at end. +# Data clocked out MSB first, send on wire LSB first! + data2=[0xff,0x0f,0xa8] #------------_______-_- Start sequence + for d in data: + data2+=[Mlookup[d//16]] + data2+=[Mlookup[d%16]] + data2+=[0xfd] + return [255-d for d in data2] + +def Loopback(TX2): + #Calculte time between edges + S='' + for b in TX2: + S+="{0:08b}".format(255-b)[::-1] + print("Loopback bits:",S[:30]) + T=[0] + for i in range(len(S)-1): + if (S[i]=='1') and (S[i+1]=="0"): T+=[i] + T=np.array(T[1:]) + T=T[1:]-T[:-1] + print("Loopback delay:",T[:30]) + return T + +class hbat_pico_io(hwdev): + def __init__(self,config): + hwdev.__init__(self,config); + port=str(config['parameters'][0]); + self.ser = serial.Serial(port,115200,timeout=0.1) # open serial port + logging.info("hba-pico connecting to: "+self.ser.name) # check which port was really used + self.CurrentChannel=0; + + def SetSW1(self,channel): + if (channel)==self.CurrentChannel: return True; + logging.debug("SetChannelbit=%i" % channel) + self.CurrentChannel=channel + return True + + def SetChannel(self,channel): + if (channel)==self.CurrentChannel: return True; + logging.debug("SetChannel=%i" % channel) + self.CurrentChannel=channel + return True + + def i2csetget(self,addr,data,reg=None,read=0): + #addr = BF address + print("I2cget",addr,data,reg,read) + try: + if read==3: + time.sleep(data[0]/1000.) + return True + if read==1: + func=len(data)*2+1; + TX1=MakeRequest(addr,[],func,reg); + logging.debug(str(("Packet to TX",TX1))) + TX2=ManchesterEncode(TX1) + self.ser.write(bytearray(TX2)) + data2=self.GetPackets() + logging.debug(str(("Data RX",data2))) + data[:len(data2)]=data2 + return len(data2)==len(data); +# print("I2C read",addr,reg,data,read) + else: + func=len(data)*2; + TX1=MakeRequest(addr,data,func,reg); + logging.debug(str(("Packet to TX",TX1))) + TX2=ManchesterEncode(TX1) + self.ser.write(bytearray(TX2)) + self.GetPackets(); + return True; + except: + logging.debug("I2C failed!") + return False; + + def GetDelay(self,Start=0x1000): + a=0; + D=[] + Start=0x1000 + while a!=b'': + s=self.ser.readline() +# print(s) + if len(s)==2: continue; + a=s[:8] +# print(a) + if a==b'': break; + a=str(a,'UTF-8') + a=Start-int(a,16) +# print(a) + if (a==0): continue; + D.append(a) + return D; + + diff --git a/i2cserv/i2c_array.py b/i2cserv/i2c_array.py index b2b31de5ea8d78fe1e865c5e0901eb7587e5f90b..14a6c207094d27cfc36101e9ed47aa939d9a748b 100644 --- a/i2cserv/i2c_array.py +++ b/i2cserv/i2c_array.py @@ -56,7 +56,7 @@ class i2c_array(i2c_dev): if (len(mask)==self.N): mask=[m for m in mask for x in range(Step)] if not(len(mask)==Step*self.N): - print("Check mask length!"); + print("Check mask length!",len(mask),Step,self.N); return; # if (len(value1)==V1.nVars) and (self.N>1): value1=(value1*self.N); # logging.debug(str(("Step=",Step,"Mask=",mask))) diff --git a/testHBA2_pico.py b/testHBA2_pico.py new file mode 100644 index 0000000000000000000000000000000000000000..4bf71f68ff27ea96170e98ff87306d41250fdad6 --- /dev/null +++ b/testHBA2_pico.py @@ -0,0 +1,72 @@ +import logging +import argparse +from opcuaserv import opcuaserv +from opcuaserv import i2client +from opcuaserv import yamlreader +#from opcuaserv import pypcc2 +from i2cserv import i2cthread +import threading +import time +import sys +import signal +from yamlconfig import Find; + +logging.basicConfig(level="DEBUG",format='%(asctime)s [%(levelname)-8s,%(filename)-20s:%(lineno)-3d] %(message)s') + +if __name__ == '__main__': + RunTimer=True; +#def signal_handler(sig, frame): +# logging.warn('Stop signal received!') +# global RunTimer; +# RunTimer=False +#signal.signal(signal.SIGINT, signal_handler) + + logging.info("Start I2C processes") + threads=[] + I2Cclients=[] + name='HBAT2' + RCU_I2C=i2client.i2client(name=name) + thread1=i2cthread.start(*RCU_I2C.GetInfo()) + threads.append(thread1) + I2Cclients.append(RCU_I2C) + +#Load yaml so that we know the variable names + RCU_conf=yamlreader.yamlreader(RCU_I2C,yamlfile=name) +#RCU_conf.CallInit() + + var1=RCU_conf.getmethodid('LOAD_EEPROM'); +#var1=RCU_conf.getmethodid('RCU_on'); +#N=32; +#mask=[i<2 for i in range(N)]; +#RCU_I2C.callmethod(var1,[]) + + var1=RCU_conf.getvarid('DELAYS_X_G1'); + N=16; + data=[0,1,2,3]*4; + mask=[(i//4)==2 for i in range(N)]; + print(mask,data) + RCU_I2C.setvar(var1,data,mask); + + var1=RCU_conf.getvarid('DELAYS_X_G2'); + N=4; + data=[0,0,0,0]; + mask=[i==2 for i in range(N)]; + print(mask,data) + RCU_I2C.setvar(var1,data,mask); + + +#RCU_I2C.readvar(var1,mask); + + + time.sleep(3); + + while RCU_I2C.data_waiting(): + varid,data,mask=RCU_I2C.readdata() + print("Results:",RCU_conf.getvar1(varid)['name'],data[:12],mask[:12]) + + + logging.info("Stop threads") + for i2c in I2Cclients: + i2c.stop() + for thread1 in threads: + thread1.join()