diff --git a/I2Cbitbang.py b/I2Cbitbang.py
deleted file mode 100644
index ad03b4343636726b04c73cb5b89480a4cf8bf775..0000000000000000000000000000000000000000
--- a/I2Cbitbang.py
+++ /dev/null
@@ -1,134 +0,0 @@
-from I2Cdevices import *;
-import numpy as np
-import logging
-
-class I2Cbitbang(I2Cdevices):
-   def I2CSet(self,dev,reg,value,I2Ccallback,width=8,bitoffset=0):
-#   def I2Cset(self,D,name,reg,data,I2Ccallback,dev_number=0):
-          Dev=Find(self.D['I2C_devices'],'dev_name',dev)    
-          Reg=Find(Dev['dev_registers'],'reg_name',reg)  
-          regnr=Reg['reg_addr']
-          Addr=Dev['dev_address'];
-#          data2=[Addr<<1,regnr]+data;
-          data2=[Addr<<1]+int2bytes(regnr)+value
-#          logging.info("%s",data2)
-          I2Ccallback('SDO',0) 
-          I2Ccallback('SCL',1) 
-          if not(I2CbbTX(data2,I2Ccallback)): return False;
-          data2=[(Addr<<1)+1];
-          data3=[0]
-          if not(I2CbbRX(data2,data3,I2Ccallback)): return False;
-          if data3[0]!=0x80:
-              logging.error("Expected Ack 0x80, received: %s",data3); 
-              return False;
-          logging.info("Si4012 TX success!")
-          return True;
-   def I2CGet(self,dev,reg,value,I2Ccallback,width=8,bitoffset=0):
-          SPI=Find(self.D['I2C_devices'],'dev_name',dev)
-          dev_number=0;
-          Reg=Find(SPI['dev_registers'],'reg_name',reg)  
-          Addr=SPI['dev_address'];
-          regnr=Reg['reg_addr']
-          data2=[Addr<<1]+int2bytes(regnr)
-          if (len(data2)==3) and (data2[1]==17): 
-                     data2[1]=18; #SI4012 hack as get is one higher than set
-                     width+=1; #hack to ignore first ack byte
-#          while regnr>255: 
-#              data2=[regnr%256]+data2;
-#              regnr=int(regnr/256);
-#          data2=[Addr<<1,regnr]+data2;
-#          logging.info("%s %s %s",data2,Addr,Reg['reg_addr']);
-          if not(I2CbbTX(data2,I2Ccallback)): return False;
-#          return False;
-          data2=[(Addr<<1)+1];
-          l1=int(np.floor((width+bitoffset+7)/8))
-          makesinglevalue=((len(value)==1) and (l1>1));
-          if makesinglevalue: data3=[0 for x in range(l1)]
-          else: data3=value
-          if not(I2CbbRX(data2,data3,I2Ccallback)): return False;
-          if makesinglevalue: value[0]=bytes2int(data3)
-          else: value[:]=data3[:];
-          if (width!=l1*8) or (bitoffset>0): 
-            value[0]=UnMask(value[0],width,bitoffset)      
-          #logging.info("Received: %s",data3); 
-          return True;
-
-
-def I2CbbTX(data2,SetBit):
-          SetBit('SDIOdir',1) #Input, should be high
-          if SetBit('SDI',0,True)==0: 
-                      logging.error("I2C line low!")
-                      return False;
-          #Start
-          SetBit('SDIOdir',0) #Output = low
-          SetBit('SCL',0) 
-
-          for b in data2:
-             bit_array = "{0:{fill}8b}".format(b, fill='0')
-             #logging.info(bit_array)
-             for bit in bit_array:
-                 SetBit('SDIOdir',int(bit)) #input=high, output=low 
-                 SetBit('SCL',1) 
-                 SetBit('SCL',0)
-             SetBit('SDIOdir',1) #Input
-             #logging.info(GetBit(SDI))
-             if SetBit('SDI',0,True)==1: 
-                      logging.error("I2C: Not ACK")
-                      return False;
-             SetBit('SCL',1)
-             #logging.info(GetBit(SDI))
-             SetBit('SCL',0)
-#             SetBit(SDIOdir,0) #Output
- 
-          #Stop
-          SetBit('SDIOdir',0) #Low
-          SetBit('SCL',1) 
-          SetBit('SDIOdir',1) #High
-          return True
-
-def I2CbbRX(data1,data2,SetBit):
-          SetBit('SDIOdir',1) #Input, should be high
-          if SetBit('SDI',0,True)==0: 
-                      logging.error("I2C ack: line low!")
-                      return False;
-          #Start
-          SetBit('SDIOdir',0) #Output = low
-          SetBit('SCL',0) 
-
-
-          for b in data1:
-             bit_array = "{0:{fill}8b}".format(b, fill='0')
-             #logging.info(bit_array)
-             for bit in bit_array:
-                 SetBit('SDIOdir',int(bit)) #input=high, output=low 
-                 SetBit('SCL',1) 
-                 SetBit('SCL',0)
-             SetBit('SDIOdir',1) #Input
-             #logging.info(GetBit(SDI))
-             if SetBit('SDI',0,True)==1: 
-                      logging.error("I2C: Not ACK")
-                      return False;
-             SetBit('SCL',1)
-             #logging.info(GetBit(SDI))
-             SetBit('SCL',0)
-
-          for x in range(len(data2)):
-            readbit='';
-            SetBit('SDIOdir',1) #Input
-            for bit in range(8):
-              SetBit('SCL',1)
-              readbit+=str(SetBit('SDI',0,True))
-              SetBit('SCL',0)
-            if x<len(data2)-1:       
-               SetBit('SDIOdir',0) #Output
-            else:  #last one = not-ack
-               SetBit('SDIOdir',1) #Output
-            SetBit('SCL',1)
-            SetBit('SCL',0)
-            data2[x]=int(readbit,2)
-
-          #Stop
-          SetBit('SDIOdir',0) #Output = low
-          SetBit('SCL',1) 
-          SetBit('SDIOdir',1) #Input = high
-          return True;
diff --git a/I2Cdevices.py b/I2Cdevices.py
deleted file mode 100644
index 58fc0d5b41e9e908a803ec5ed205a9d9a9204c27..0000000000000000000000000000000000000000
--- a/I2Cdevices.py
+++ /dev/null
@@ -1,249 +0,0 @@
-from hwdev import *;
-import numpy as np
-import logging
-
-
-def GetField(D,name,dev_number):
-    X=D.get(name)
-    return X[dev_number] if isinstance(X,list) else X;
-
-
-def bytes2int(bts):
-   x=0;
-   for b in bts:
-     x=x*256+b;
-   return x;
-def int2bytes(i):
-   b=[];
-   while i>255: 
-        b=[i%256]+b;
-        i>>=8;
-   return [i]+b;
-   
-
-def I2CName2pin(s):
-    dev,reg,pin=s.split('.')
-    return dev,reg,int(pin)
-
-
-def ApplyMask(value,width=8,bitoffset=0,previous=0):
-    mask=(1<<width)-1
-    if bitoffset>0:
-      value<<=bitoffset;
-      mask<<=bitoffset;
-    return (value & mask) + (previous - (previous & mask));
-def UnMask(value,width=8,bitoffset=0):
-    mask=(1<<width)-1
-    if bitoffset>0:
-      value>>=bitoffset;
-    value=value&mask;
-    return value;
-
-
-class I2Cdevices(hwdev):
-      def GetVarValues(names,value,I2Ccallback):
-        return True  
- 
-      def CallMethod(self,name,params,I2Ccallback):
-#        logging.info("RCU1 call method %s",name)
-        for Mth in self.D['Methods']:
-          if Mth['method_name']==name:
-             logging.info("RCU1 Run method %s",name)
-             for regs in Mth['registers']:
-                for key,value in regs.items():
-                  self.SetVarValue(key,value,I2Ccallback)
-             return True
-        return hwdev.CallMethod(self,name,params,I2Ccallback)
-
-      def SetChildValue(self,D,child,name,value,I2Ccallback):
-         Pins={}
-         for p in D['child_GPIO']:
-            for key,regvalue in p.items():
-              Pins[key]=I2CName2pin(regvalue)
-         def SetGetPin(pin,value,Get=False):
-           Pin=Pins[pin]
-           if not(Get): return self.I2CSet(Pin[0],Pin[1],[value],I2Ccallback,1,Pin[2])
-           a=[0]
-           self.I2CGet(Pin[0],Pin[1],a,I2Ccallback,1,Pin[2])
-           return a[0];
-         return child.SetVarValue(name,value,SetGetPin)
-      def GetChildValue(self,D,child,name,value,I2Ccallback):
-         Pins={}
-         for p in D['child_GPIO']:
-            for key,regvalue in p.items():
-              Pins[key]=I2CName2pin(regvalue)
-         def SetGetPin(pin,value,Get=False):
-           Pin=Pins[pin]
-           if not(Get): return self.I2CSet(Pin[0],Pin[1],[value],I2Ccallback,1,Pin[2])
-           a=[0]
-           self.I2CGet(Pin[0],Pin[1],a,I2Ccallback,1,Pin[2])
-           return a[0];
-         logging.info("Set Child %s",child)
-         return child.GetVarValue(name,value,SetGetPin)
-
-      def SetVarValue(self,name,value,I2Ccallback):
-            logging.info("RCU1 Set %s=%s",name,value)
-            D=self.D
-            Var1=Find(D['Variables'],'var_name',name)
-
-            if (Var1): 
-              dev_number=0
-              Dev=GetField(Var1,'var_dev',dev_number)
-              Dev=Dev.split('.')
-
-              vmax=GetField(Var1,'var_max',dev_number)
-              if vmax:
-                  if value[0]>vmax: value[0]=vmax;
-              vmin=GetField(Var1,'var_min',dev_number)
-              if vmin:
-                  if value[0]<vmin: value[0]=vmin;
-                  value[0]=value-vmin;   
-              width=GetField(Var1,'var_width',dev_number)
-              bitoffset=GetField(Var1,'var_bitoffset',dev_number)
-              scale=GetField(Var1,'var_scale',dev_number)
-            elif (Find(D['Methods'],'method_name',name)):
-               return self.CallMethod(name,value,I2Ccallback)
-            elif len(name.split('.'))==2:
-                   Dev=name.split('.');
-                   width=False;
-                   bitoffset=False;
-                   scale=False;
-            else:
-                   childname=name.split('_')[0]
-                   for c in self.D['dev_children']:
-                         if childname==c['child_name']: 
-                             return self.SetChildValue(c,c['obj'],name[len(childname)+1:],value,I2Ccallback)
-#                   return hwdev.SetVarValue(self,name,value,I2Ccallback)
-                   logging.error("Unknown variable %s",name);
-                   return False;
-            logging.info("%s",Dev)
-            if scale: value=int2bytes(int(value[0]/float(scale)))
-            if Find(D['I2C_devices'],'dev_name',Dev[0]):
-              if not(width): width=8
-              if not(bitoffset): bitoffset=0
-              logging.info('SetVar %s I2C %s to %s (width=%s bitoffset=%s)',name,Dev,value,width,bitoffset)
-              return self.I2CSet(Dev[0],Dev[1],value,I2Ccallback,width,bitoffset)
-
-            if Find(D['SPI_devices'],'dev_name',Dev[0]):
-              logging.info('SetVar %s SPI %S to %s',name,Dev,value)
-              return SPIset(D,Dev[0],Dev[1],value,I2Ccallback,dev_number)
-            hwdev.SetVarValue(self,name,value,I2Ccallback)
-#        return SetVar(self.D,name,value,I2Ccallback)
-
-      def GetVarValue(self,name,value,I2Ccallback):
-#def GetVar(D,name,value,I2Ccallback,dev_number=0):
-            dev_number=0;D=self.D
-            logging.info("RCU1 Get %s=%s",name,value)
-            Var1=Find(D['Variables'],'var_name',name)
-            if (Var1): 
-              Dev=GetField(Var1,'var_dev',dev_number)
-              Dev=Dev.split('.')
-              width=GetField(Var1,'var_width',dev_number)
-              bitoffset=GetField(Var1,'var_bitoffset',dev_number)
-              scale=GetField(Var1,'var_scale',dev_number)
-            elif len(name.split('.'))==2:
-                   Dev=name.split('.');
-                   width=False;
-                   bitoffset=False;
-                   scale=False;
-            else:
-                   childname=name.split('_')[0]
-                   for c in self.D['dev_children']:
-                         if childname==c['child_name']: 
-                             return self.GetChildValue(c,c['obj'],name[len(childname)+1:],value,I2Ccallback)
-#                   return hwdev.SetVarValue(self,name,value,I2Ccallback)
-                   logging.error("Unknown variable %s",name);
-                   return False
-
-            logging.info("%s",Dev)
-            if not(width): width=8
-            if not(bitoffset): bitoffset=0
-            if Find(D['I2C_devices'],'dev_name',Dev[0]):
-              logging.info('GetVar %s I2C %s value %s (width=%s bitoffset=%s)',name,Dev,value,width,bitoffset)
-              result=self.I2CGet(Dev[0],Dev[1],value,I2Ccallback,width,bitoffset)
-              if not(result): return False;
-              if scale: value[0]=float(value[0])*float(scale);
-              return True
-            if Find(D['SPI_devices'],'dev_name',Dev[0]):
-              logging.info('GetVar %s SPI %s value %s',name,Dev,value)
-              return SPIget(D,Dev[0],Dev[1],value,I2Ccallback,dev_number)
-            if Find(D['I2C_bitbang'],'dev_name',Dev[0]):
-              logging.info('GetVar %s I2C bb %s value %s',name,Dev,value)
-              if not(I2Cbbget(D,Dev[0],Dev[1],value,I2Ccallback,dev_number,width,bitoffset)): return False
-              if scale: value[0]=float(value[0])*float(scale);
-              return True;
-            logging.error("Unknown variable %s",name)
-            return False;
-
-#        return GetVar(self.D,name,value,I2Ccallback)
-
-      def GetVarNames(self,parentname,callback):
-          for V in self.D['Variables']:
-            dtype=(1 if V.get('var_scale') else 0)
-            RWs={'RO' : 1,'WO' : 2,'RW' : 3}
-            RW=(RWs[V.get('var_R/W')] if V.get('var_R/W') else 0)
-            callback(parentname+V['var_name'],dtype,RW)
-          return hwdev.GetVarNames(self,parentname,callback);
-
-      def GetMethodNames(self,parentname,callback):
-          for V in self.D['Methods']:
-            if not(V.get('method_invisible')): callback(parentname+V['method_name'])
-          return hwdev.GetMethodNames(self,parentname,callback);
-
-      def I2CSet(self,dev,reg,value,I2Ccallback,width=8,bitoffset=0):
-      #remember of values, add new ones with mask
-      #  logging.info('I2CSet: %s=%s (mask=%s)',dev,value,mask)
-        Dev=Find(self.D['I2C_devices'],'dev_name',dev)    
-        Addr=Dev['dev_address']
-        Reg=Find(Dev['dev_registers'],'reg_name',reg)    
-      #  logging.info("%s %s %s",dev,reg,value)
-        if (width<8) or (bitoffset>0):
-          previous=Reg.get('previous')
-          if not(previous):
-              previous=Reg.get('reg_default')
-          if not(previous):
-              previous=0;
-          value[0]=ApplyMask(value[0],width,bitoffset,previous);
-      #    logging.info('masked to %s',value)
-      #  logging.info("Set %s %s to %s",dev,reg,value)    
-        result=I2Ccallback(Addr,value,reg=Reg['reg_addr'],)
-        #if result:        
-        Reg['previous']=value[0]
-        return result 
-
-      def I2CGet(self,dev,reg,value,I2Ccallback,width=8,bitoffset=0):
-        Dev=Find(self.D['I2C_devices'],'dev_name',dev)    
-        Addr=Dev['dev_address']
-        Reg=Find(Dev['dev_registers'],'reg_name',reg)  
-        l1=int(np.floor((width+bitoffset+7)/8))
-#        logging.info("%s %s %s",width,bitoffset,l1)
-        makesinglevalue=((len(value)==1) and (l1>1));
-        if makesinglevalue: value2=[0 for x in range(l1)]
-        else: value2=value
-        reg=Reg['reg_addr']
-        if reg>255: #This is for the monitor ADC
-          if not(I2Ccallback(Addr,int2bytes(reg),read=2)): return False;
-          I2Ccallback(Addr,[250],read=3)
-          if not(I2Ccallback(Addr,value2,read=1)): return False;
-        else:
-          if not(I2Ccallback(Addr,value2,reg=Reg['reg_addr'],read=1)): return False;
-        if value2[0] is None:  return False
-        if makesinglevalue: value[0]=bytes2int(value2)
-        else: value[:]=value2[:];
-        Reg['previous']=value[0]
-        if (width!=l1*8) or (bitoffset>0): 
-            value[0]=UnMask(value[0],width,bitoffset)      
-        else: value[0]=value2[0]
-        return True;
-
-#def I2CGetBuff(D,dev,reg,value,I2Ccallback,width=8,bitoffset=0):
-#        Dev=Find(D['I2C_devices'],'dev_name',dev)    
-#        Addr=Dev['dev_address']
-#        Reg=Find(Dev['dev_registers'],'reg_name',reg)  
-#        value[0]=Reg.get('previous')
-#        logging.info("Get Value=%s",value[0])
-#        if (width<8) or (bitoffset>0): 
-#            value[0]=UnMask(value[0],width,bitoffset)      
-#        return True;
-
-
diff --git a/I2Cswitch.py b/I2Cswitch.py
deleted file mode 100644
index 004b62fe0b7c2a61c8462f2f76f0f2c203334684..0000000000000000000000000000000000000000
--- a/I2Cswitch.py
+++ /dev/null
@@ -1,131 +0,0 @@
-from hwdev import *;
-import numpy as np
-import logging
-
-def I2C_dummy(addr,data,reg=None,read=0):
-#            logging.info("I2C dummy addr=%s data=%s",addr,data)
-            return True;
-
-class I2Cswitch(hwdev):
-    def SetChannel(self,channel,I2Ccallback):
-        if not(hasattr(self,'CurrentChannel')): self.CurrentChannel=0
-        logging.info("SetChannel %s %s",channel,self.CurrentChannel)
-        if (channel)==self.CurrentChannel: return True;
-        self.CurrentChannel=channel
-        return I2Ccallback(self.D['dev_address'],[channel])
-        
-#    def GetVarNames(self,parentname,callback):
-#        for c in self.D['dev_children']:
-#            c['obj'].GetVarNames(parentname+c['name']+'_',callback)
-#        return True;
-
-#    def GetMethodNames(self,parentname,callback):
-#        for c in self.D['dev_children']:
-#            c['obj'].GetMethodNames(parentname+c['name']+'_',callback)
-#        return True;
-
-    def GetVarValue(self,name,value,I2Ccallback):
-        def I2Ccallback2(addr,data,reg=None,read=0):
-#            logging.info("Getvarcallback %s",x)
-            if (read==2):
-                if (cnt>0): return True;
-                if not(self.SetChannel(gchannel,I2Ccallback)): return False;
-            elif (read==3):
-                if (cnt>0): return True;
-                return I2Ccallback(addr,data,reg,read)
-            elif not(self.SetChannel(cchannel,I2Ccallback)): return False;
-            return I2Ccallback(addr,data,reg,read)
-
-        childname=name.split('_')[0]
-        child=Find(self.D['dev_children'],'child_name',childname)
-        if child:
-              if not(self.SetChannel(1<<child['child_addr'],I2Ccallback)): return False; 
-              return child['obj'].GetVarValue(name[len(childname)+1:],value,I2Ccallback)
-        group=Find(self.D['dev_groups'],'group_name',childname)
-        if group:
-              devcnt=len(group['group_members'])
-              stride=len(value)//devcnt;
-              gchannel=0;
-              for childname2 in group['group_members']:
-                   gchannel+=1<<(Find(self.D['dev_children'],'child_name',childname2)['child_addr'])
-
-              for cnt,childname2 in enumerate(group['group_members']):
-                    child=Find(self.D['dev_children'],'child_name',childname2)
-                    if not(child): return False;
-                    logging.info("Get: %s",childname2)
-                    cchannel=1<<child['child_addr']
-                    value2=value[cnt*stride:(cnt+1)*stride]
-                    if not(child['obj'].GetVarValue(name[len(childname)+1:],value2,I2Ccallback2)): return False; 
-                    value[cnt*stride:(cnt+1)*stride]=value2
-              return True;
-        return False
-
-    def SetVarValue(self,name,value,I2Ccallback):
-        childname=name.split('_')[0]
-        child=Find(self.D['dev_children'],'child_name',childname)
-        if child:
-              if not(self.SetChannel(1<<child['child_addr'],I2Ccallback)): return False; 
-              return child['obj'].SetVarValue(name[len(childname)+1:],value,I2Ccallback)
-        group=Find(self.D['dev_groups'],'group_name',childname)
-        if group:
-              devcnt=len(group['group_members'])
-              stride=len(value)//devcnt;
-              AllSame=True;
-              for x in range(devcnt-1):
-                  for y in range(stride):
-                      if value[x*stride+y]!=value[(x+1)*stride+y]: AllSame=False;
-              if AllSame: 
-                logging.info("Allsame");              
-                channel=0;
-                for childname2 in group['group_members']:
-                    channel+=1<<(Find(self.D['dev_children'],'child_name',childname2)['child_addr'])
-                logging.info("%s",channel)
-                if not(self.SetChannel(channel,I2Ccallback)): return False; 
-                for x,childname2 in enumerate(group['group_members']):
-                    child=Find(self.D['dev_children'],'child_name',childname2)
-                    if not(child): return False;
-                    callback=(I2Ccallback if x==0 else I2C_dummy)
-                    if not(child['obj'].SetVarValue(name[len(childname)+1:],value[:stride],callback)): return false; 
-                return True;
-              else:
-                for x,childname2 in enumerate(group['group_members']):
-                    child=Find(self.D['dev_children'],'child_name',childname2)
-                    if not(child): return False;
-                    logging.info("Set: %s",childname2)
-                    if not(self.SetChannel(1<<child['child_addr'],I2Ccallback)): return False; 
-                    if not(child['obj'].SetVarValue(name[len(childname)+1:],value[x*stride:(x+1)*stride],I2Ccallback)): return false; 
-                return True;
-        return False
-
-    def CallMethod(self,name,params,I2Ccallback):
-        childname=name.split('_')[0]
-        child=Find(self.D['dev_children'],'child_name',childname)
-        if child:
-            if not(self.SetChannel(1<<child['child_addr'],I2Ccallback)): return False; 
-            return child['obj'].CallMethod(name[len(childname)+1:],params,I2Ccallback)
-        group=Find(self.D['dev_groups'],'group_name',childname)
-        if group:
-              channel=0;
-              for childname2 in group['group_members']:
-                 channel+=1<<(Find(self.D['dev_children'],'child_name',childname2)['child_addr'])
-              if not(self.SetChannel(channel,I2Ccallback)): return False; 
-              for x,childname2 in enumerate(group['group_members']):
-                 child=Find(self.D['dev_children'],'child_name',childname2)
-                 if not(child): return False;
-                 callback=(I2Ccallback if x==0 else I2C_dummy)
-                 if not(child['obj'].CallMethod(name[len(childname)+1:],params,callback)): return false; 
-              return True;
-        return False;
-
-    def GetVarNames(self,parentname,callback):
-        if not(hwdev.GetVarNames(self,parentname,callback)): return False;
-        def AddVar(name,dtype=0,RW=3,cnt=1):
-            callback(name,dtype,RW,cnt*devcnt)
-        for group in self.D['dev_groups']:
-                childname=group['group_members'][0]
-                devcnt=len(group['group_members'])
-                child=Find(self.D['dev_children'],'child_name',childname)
-                if not(child): return False;
-                child['obj'].GetVarNames(parentname+group['group_name']+'_',AddVar)
-        return True;
-     
diff --git a/README.md b/README.md
index afb32b2b2ad7924a923fd8cb301722bba3b9553f..23ec5e0a9d302f8159fd7b5fadf5bc64cd5faf19 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ Python OPC-UA server to control the I2C devices in the LTS.
 This Python3 code uses other Python3 modules:
 
 - opcua
-- pyyaml
+- recordclass
 - numpy
 
 We recommend to install a virtual environment and then install the dependencies there.  For convenience we have added the relevant modules to the file `requirements.txt` that can be used to install them with pip3: `python3 -m pip install -r requirements.txt`
@@ -39,10 +39,10 @@ The software can be simply executed with Python3:  `python3 opcuaserv.py`
 Optional parameters are explained when the `-h` or `--help` parameter is supplied:
 
 ```bash
-python3 opcuaserv.py --help
+python3 pypcc2.py --help
 cryptography is not installed, use of crypto disabled
 cryptography is not installed, use of crypto disabled
-usage: opcuaserv.py [-h] [-s] [--no-lib-hack] [-p PORT]
+usage: pypcc2.py [-h] [-s] [--no-lib-hack] [-p PORT]
 
 optional arguments:
   -h, --help            show this help message and exit
@@ -51,19 +51,3 @@ optional arguments:
   -p PORT, --port PORT  Port number to listen on [4842].
 ```
 
-# LTS structure
-
-Raspberry pi (LTS_pypcc.yaml -> I2C controller on raspberry pi)
-
-> Control PCB (LTS_switch.yaml -> I2C switch)
->
-> > RCU2 PCB   (LTS_RCUx.yaml  -> I2C devices)
-> >
-> > > RCU2 Dither source (LTS_RCU2_dither.yaml -> I2C bitbang)
-> >
-> > > ADC (LTS_RCU2_ADC.yaml -> SPI bitbang2)
-> >
-> > Clock PCB (LTS_clk.yaml -> I2C device)
-> >
-> > > PLL (LTS_clkPLL.yaml -> SPI bitbang1)
-
diff --git a/SPIbitbang1.py b/SPIbitbang1.py
deleted file mode 100644
index 196a5a8ab1c75fabe03e64f251424a133e6b504a..0000000000000000000000000000000000000000
--- a/SPIbitbang1.py
+++ /dev/null
@@ -1,68 +0,0 @@
-from I2Cdevices import *;
-import numpy as np
-import logging
-
-class SPIbitbang1(I2Cdevices):
-    def I2CSet(self,dev,reg,value,I2Ccallback,width=8,bitoffset=0):
-          SPI=Find(self.D['I2C_devices'],'dev_name',dev)
-          Reg=Find(SPI['dev_registers'],'reg_name',reg)  
-          ADC_address=Reg['reg_addr']
-          SetBit=I2Ccallback
-
-          ADC_bytes = 0x00
-          ADC_rw    = 0x00 # 0 for write, 1 for read
-          data2 = ( ADC_rw << 23 ) + ( ADC_bytes << 21 ) + ( ADC_address << 8 ) + value[0]
-          
-          bit_array = "{0:{fill}24b}".format(data2, fill='0')
-      #    logging.debug("%s",bit_array)
-          SetBit('CS',0) #enable
-          for bit in bit_array:
-              SetBit('SDO',int(bit)) 
-              SetBit('CLK',1) 
-              SetBit('CLK',0) 
-          SetBit('CS',1) 
-          return True;
-          
-
-    def I2CGet(self,dev,reg,value,I2Ccallback,width=8,bitoffset=0):
-          
-          SPI=Find(self.D['I2C_devices'],'dev_name',dev)
-          Reg=Find(SPI['dev_registers'],'reg_name',reg)  
-          ADC_reg_address=Reg['reg_addr']
-#          logging.debug("%s %s %s %s %s %s",ADC_reg_address,CS,SDIOdir,SDI,SDO,CLK)
-          SetBit=I2Ccallback
-
-          ADC_bytes = 0x00
-          ADC_rw    = 0x01 # 0 for write, 1 for read
-        
-          data = ( ADC_rw << 15) + ( ADC_bytes << 13 ) + ADC_reg_address
-          
-          SetBit('CS',0) #enable
-
-          bit_array = "{0:{fill}16b}".format(data, fill='0')
-          for bit in bit_array:
-              SetBit('SDO',int(bit))
-              SetBit('CLK',1)
-              SetBit('CLK',0)
-
-          SetBit('CS',1) #disable
-
-          #    logging.debug("read byte")
-          SetBit('SDIOdir',1) #inpute
-          SetBit('CS',0) #enable
-          a=[0]
-          read_bit = ''
-          for cnt in range(8*(ADC_bytes+1)):
-              ret_value=SetBit('SDI',0,True)
-              read_bit += str(ret_value)
-              SetBit('CLK',1)
-              SetBit('CLK',0) #read after falling edge
-          SetBit('CS',1) #disable
-          SetBit('SDIOdir',0) #output
-#          SetBit(SDO,1) 
-#          SetBit(CLK,1) 
-#          logging.debug("%s",read_bit)
-#          stri = "Read back data is: {0:2x} ".format(int(read_bit, 2))
-#          logging.debug("%s",stri)
-          value[0]=int(read_bit, 2)
-          return True;
diff --git a/SPIbitbang2.py b/SPIbitbang2.py
deleted file mode 100644
index edbdc9e45613a6178a0c86f2f55cc8672daf8f87..0000000000000000000000000000000000000000
--- a/SPIbitbang2.py
+++ /dev/null
@@ -1,66 +0,0 @@
-from I2Cdevices import *;
-import numpy as np
-import logging
-
-class SPIbitbang2(I2Cdevices):
-    def I2CSet(self,dev,reg,value,I2Ccallback,width=8,bitoffset=0):
-          SPI=Find(self.D['I2C_devices'],'dev_name',dev)
-          Reg=Find(SPI['dev_registers'],'reg_name',reg)  
-          reg_address=(Reg['reg_addr'] if Reg else int(reg))
-          SetBit=I2Ccallback
-
-#          dev_rw    = 0x00 # 0 for write, 1 for read
-#          data2 =  ( reg_address << 9 ) + ( dev_rw << 8 ) + value[0]
-          data2 =  ( reg_address << 9 ) + value[0]
-          
-          bit_array = "{0:{fill}16b}".format(data2, fill='0')
-      #    logging.info("%s",bit_array)
-          SetBit('CS',0) #enable
-          for bit in bit_array:
-              SetBit('SDI',int(bit)) 
-              SetBit('CLK',1) 
-              SetBit('CLK',0) 
-          SetBit('CS',1) 
-          return True;
-          
-
-    def I2CGet(self,dev,reg,value,I2Ccallback,width=8,bitoffset=0):
-          
-          SPI=Find(self.D['I2C_devices'],'dev_name',dev)
-          Reg=Find(SPI['dev_registers'],'reg_name',reg)  
-          reg_address=(Reg['reg_addr'] if Reg else int(reg))
-#          logging.info("%s %s %s %s %s %s",ADC_reg_address,CS,SDIOdir,SDI,SDO,CLK)
-          SetBit=I2Ccallback
-          ADC_bytes = 0x00
-
-#          ADC_rw    = 0x01 # 0 for write, 1 for read
-          data =  ( reg_address << 7 ) +  1
-        
-          SetBit('CS',0) #enable
-
-          bit_array = "{0:{fill}8b}".format(data, fill='0')
-          for bit in bit_array:
-              SetBit('SDI',int(bit))
-              SetBit('CLK',1)
-              SetBit('CLK',0)
-
-#          SetBit('CS',1) #disable
-
-          #    logging.info("read byte")
-#          SetBit('SDIOdir',1) #inpute
-#          SetBit('CS',0) #enable
-          a=[0]
-          read_bit = ''
-          for cnt in range(8*(ADC_bytes+1)):
-              ret_value=SetBit('SDO',0,True)
-              read_bit += str(ret_value)
-              SetBit('CLK',1)
-              SetBit('CLK',0) #read after falling edge
-          SetBit('CS',1) #disable
-#          SetBit(SDO,1) 
-#          SetBit(CLK,1) 
-#          logging.info("%s",read_bit)
-          stri = "Read back data is: {0:2x} ".format(int(read_bit, 2))
-          logging.info("%s",stri)
-          value[0]=int(read_bit, 2)
-          return True;
diff --git a/YAML/LTS_RCU2L.yaml b/YAML/LTS_RCU2L.yaml
deleted file mode 100644
index 03ce80441325522d175a29a6a123e8bba371947c..0000000000000000000000000000000000000000
--- a/YAML/LTS_RCU2L.yaml
+++ /dev/null
@@ -1,272 +0,0 @@
-dev_children:
-     - child_name: Dither3
-       child_dev : I2Cbitbang
-       child_conf: LTS_RCU2_dither
-       child_GPIO:
-         - SCL     : IO1.OUT1.6 
-         - SDO     : IO2.OUT2.3 
-         - SDI     : IO2.IN2.3  
-         - SDIOdir : IO2.CONF2.3
-     - child_name: Dither2
-       child_dev : I2Cbitbang
-       child_conf: LTS_RCU2_dither
-       child_GPIO:
-         - SCL     : IO1.OUT2.7 
-         - SDO     : IO1.OUT1.7 
-         - SDI     : IO1.IN1.7  
-         - SDIOdir : IO1.CONF1.7
-     - child_name: ADC1
-       child_dev : SPIbitbang1
-       child_conf: LTS_RCU2_ADC
-       child_GPIO:
-         - CLK     : IO3.OUT1.1 
-         - SDO     : IO3.OUT1.0 
-         - SDI     : IO3.IN1.0  
-         - SDIOdir: IO3.CONF1.0
-         - CS      : IO3.OUT2.0 
-     - child_name: ADC2
-       child_dev : SPIbitbang1
-       child_conf: LTS_RCU2_ADC
-       child_GPIO:
-         - CLK     : IO3.OUT1.3 
-         - SDO     : IO3.OUT1.2 
-         - SDI     : IO3.IN1.2  
-         - SDIOdir: IO3.CONF1.2
-         - CS      : IO3.OUT2.1 
-     - child_name: ADC3
-       child_dev : SPIbitbang1
-       child_conf: LTS_RCU2_ADC
-       child_GPIO:
-         - CLK     : IO3.OUT1.5 
-         - SDO     : IO3.OUT1.4 
-         - SDI     : IO3.IN1.4  
-         - SDIOdir: IO3.CONF1.4
-         - CS      : IO3.OUT2.2 
-
-#This is the I2C devices in the RCU
-I2C_devices:
- - dev_name: IO1
-   dev_description: IO-Expander for filter selection
-   dev_address: 0x75
-   dev_device: TCA9539
-   dev_registers:
-   - reg_name: CONF1
-     reg_addr: 6
-   - reg_name: CONF2
-     reg_addr: 7
-   - reg_name: OUT1
-     reg_addr: 2
-     ref_default: 0
-   - reg_name: OUT2
-     reg_addr: 3
-     ref_default: 0
-   - reg_name: IN1
-     reg_addr: 0
-   - reg_name: IN2
-     reg_addr: 1
-
- - dev_name: IO3
-   dev_description: IO-Expander for ADC control
-   dev_address: 0x20
-   dev_device: TCA6416
-   dev_registers:
-   - reg_name: CONF1
-     reg_description: Direction of IO pins 0..7
-     reg_addr: 6
-   - reg_name: CONF2
-     reg_description: Direction of IO pints 8..15
-     reg_addr: 7
-   - reg_name: IN1
-     reg_description: Ouput port register 0..7
-     reg_addr: 0
-   - reg_name: IN2
-     reg_description: Ouput port register 0..7
-     reg_addr: 1
-   - reg_name: OUT1
-     reg_description: Ouput port register 0..7
-     reg_addr: 2
-     reg_default: 0x0F
-   - reg_name: OUT2
-     reg_description: Ouput port register 8..15
-     reg_addr: 3
-     reg_default: 0x0F
-
- - dev_name: IO2
-   dev_description: IO-Expander for ON/OFF, Band, BUFx2
-   dev_address: 0x76
-   dev_device: TCA9539
-   dev_registers:
-   - reg_name: CONF1
-     reg_addr: 6
-   - reg_name: CONF2
-     reg_addr: 7
-   - reg_name: OUT1
-     reg_addr: 2
-     ref_default: 0
-   - reg_name: OUT2
-     reg_addr: 3
-     ref_default: 0
-   - reg_name: IN1
-     reg_addr: 0
-   - reg_name: IN2
-     reg_addr: 1
-
- - dev_name: UC
-   dev_description: RCU microcontroller 
-   dev_address: 0x40
-   dev_registers:
-   - reg_name: ID
-     reg_description: Device ID
-     reg_addr: 0
-
- - dev_name: ROM
-   dev_description: EEPROM memory
-   dev_address: 0x53
-   dev_registers:
-   - reg_name: ctr_len
-     reg_description: Length of control data
-     reg_addr: 0
-   - reg_name: ctr_dat
-     reg_description: Control data (protocol buffers)
-     reg_addr: 2
-
-
- - dev_name: AN
-   dev_description: Monitor ADC on RCU
-   dev_address: 0x14
-   dev_device: LTC2495
-   dev_registers:
-   - reg_name: Ch0
-     reg_addr: 0xB080
-   - reg_name: Ch1
-     reg_addr: 0xB8
-   - reg_name: Ch2
-     reg_addr: 0xB1
-   - reg_name: Ch3
-     reg_addr: 0xB9
-   - reg_name: Ch4
-     reg_addr: 0xB2
-   - reg_name: Ch5
-     reg_addr: 0xBA
-   - reg_name: Ch6
-     reg_addr: 0xB3
-   - reg_name: Ch7
-     reg_addr: 0xBB
-   - reg_name: Temp
-     reg_addr: 0xA0C0
-
-Variables:
-   - var_name: Attenuator1
-     var_dev:  IO1.OUT1
-     var_width: 5
-     var_max:  21
-     var_R/W:  RW
-   - var_name: Attenuator2
-     var_dev:  IO1.OUT2
-     var_width: 5
-     var_max:  21
-     var_R/W:  RW
-   - var_name: Attenuator3
-     var_dev:  IO2.OUT1
-     var_width: 5
-     var_max:  24
-     var_R/W:  RW
-
-   - var_name: Pwr_dig
-     var_description: Enable LDOs
-     var_dict: {0 : Off, 1 : On}
-     var_dev:  IO2.OUT1
-     var_width: 1
-     var_bitoffset: 6
-     var_R/W:  RO
-
-   - var_name: Band3
-     var_dev:  IO2.OUT2
-     var_dict: {0 : 10MHz, 1 : 30MHz}
-     var_width: 1
-     var_bitoffset: 0
-     var_R/W:  RW
-
-   - var_name: Band1
-     var_dev:  IO2.OUT2
-     var_dict: {0 : 10MHz, 1 : 30MHz}
-     var_width: 1
-     var_bitoffset: 1
-     var_R/W:  RW
-
-   - var_name: Band2
-     var_dev:  IO2.OUT2
-     var_dict: {0 : 10MHz, 1 : 30MHz}
-     var_width: 1
-     var_bitoffset: 4
-     var_R/W:  RW
-
-   - var_name: LED0
-     var_description: Front panel LEDs, 0=On
-     var_dict: {0 : Off, 1 : Yellow, 2: Red, 3: Orange}
-     var_dev:  IO2.OUT2
-     var_width: 2
-     var_bitoffset: 6
-     var_R/W:  RW
-
-   - var_name: Temperature
-     var_dev:  AN.Temp
-     var_width: 23
-     var_scale: 4.21e-3
-     var_R/W:  RO
-
-   - var_name: Dth3_Pwr
-     var_dev:  IO2.OUT2
-     var_width: 1
-     var_bitoffset: 2
-
-   - var_name: Dth2_Pwr
-     var_dev:  IO1.OUT2
-     var_width: 1
-     var_bitoffset: 6
-
-          
-Methods:
-   - method_name: RCU_on
-     registers:
-        - IO2.CONF1: [0]    #Setup IO expanders to output with default values
-        - IO2.OUT1: [0x4A]
-        - IO2.OUT2: [0x55]
-        - IO3.OUT1: [0x7f]
-        - IO3.OUT2: [0x47]
-        - IO1.OUT1: [0xCA]
-        - IO1.OUT2: [0xCA]
-        - IO2.CONF2: [0]
-        - IO3.CONF1: [0]
-        - IO3.CONF2: [0]
-        - IO1.CONF1: [0]
-        - IO1.CONF2: [0]
-        - ADC1_Setup: 1
-        - ADC2_Setup: 1
-        - ADC3_Setup: 1
-
-   - method_name: RCU_off
-     registers:
-        - IO2.OUT1: [0x00] #Switch all off
-        - IO2.OUT2: [0x00]
-        - IO3.OUT1: [0x00]
-        - IO3.OUT2: [0x00]
-        - IO1.OUT1: [0x00]
-        - IO1.OUT2: [0x00]
-
-   - method_name: Dither_on
-     method_invisible: 1
-     registers:
-        - Dth3_Pwr: [1]
-        - Dth2_Pwr: [1]
-        - Dither3_Setup: 1
-        - Dither2_Setup: 1
-
-   - method_name: Dither_off
-     method_invisible: 1
-     registers:
-        - Dth3_Pwr: [0]
-        - Dth2_Pwr: [0]
-
-
-
diff --git a/YAML/LTS_RCU2_ADC.yaml b/YAML/LTS_RCU2_ADC.yaml
deleted file mode 100644
index 111f6d900601827e176d2ea29491aad67835f9e0..0000000000000000000000000000000000000000
--- a/YAML/LTS_RCU2_ADC.yaml
+++ /dev/null
@@ -1,45 +0,0 @@
-I2C_devices:
- - dev_name: ADC1
-   dev_description: I2C-SPI bridge to ADC
-   dev_device: AD9683
-   dev_registers:
-    - reg_name: PLL_stat
-      reg_description: PLL locked status
-      reg_addr: 0x0A
-    - reg_name: JESD_control1
-      reg_description: JESD link control, ILAS mode
-      reg_addr: 0x5F
-    - reg_name: CML_level
-      reg_description: CML output adjust
-      reg_addr: 0x15
-    - reg_name: SYNC_control
-      reg_description: SYNC / SYSREF control
-      reg_addr: 0x3A
-    - reg_name: Update
-      reg_description: Global device update
-      reg_addr: 0xFF
-
-Variables:
-   - var_name: locked
-     var_dev:  ADC1.PLL_stat
-     var_width: 8
-#     var_R/W:  RO
-   - var_name: SYNC
-     var_dev:  ADC1.SYNC_control
-     var_width: 8
-   - var_name: CML
-     var_dev:  ADC1.CML_level
-     var_width: 8
-   - var_name: JESD
-     var_dev:  ADC1.JESD_control1
-     var_width: 8
-     var_R/W:  RO
-
-Methods:
-   - method_name: Setup
-     method_invisible: 1
-     registers:
-        - ADC1.JESD_control1: [14]  #Setup ADCs
-        - ADC1.SYNC_control: [1]  #Setup ADCs
-        - ADC1.CML_level: [0x7]
-        - ADC1.Update: [1]       #Needed to update ADC registers
diff --git a/YAML/LTS_RCU2_dither.yaml b/YAML/LTS_RCU2_dither.yaml
deleted file mode 100644
index aa21250ea19d56284ef2c72cb91c1ca7ab6eac21..0000000000000000000000000000000000000000
--- a/YAML/LTS_RCU2_dither.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
-I2C_devices:
- - dev_name: DS1
-   dev_description: Dither Source, SI4010
-   dev_address: 0x70
-   dev_registers:
-   - reg_name: TX_Stop
-     reg_addr: 0x67
-   - reg_name: TX_Start
-     reg_addr: 0x62
-   - reg_name: property
-     reg_addr: 0x11
-   - reg_name: TX_FREQ
-     reg_addr: 0x1140
-
-Variables:
-   - var_name: Frequency
-     var_dev:  DS1.TX_FREQ
-     var_width: 32
-     var_scale: 1e-6
-     var_bitoffset: 0
-
-Methods:
-   - method_name: Setup
-     method_invisible: 1
-     registers:
-        - DS1.property: [0x60,1,0,0,0,125,127]     #Power level (1,0)
-        - DS1.property: [0x40,0x06,0x0c,0xc4,0x60] #Frequency 101.5MHz
-        - DS1.property: [0x21,0,0]     #tuning off
-        - DS1.TX_Start: [0,0,0,0,1]
diff --git a/YAML/LTS_RCU2dig.yaml b/YAML/LTS_RCU2dig.yaml
deleted file mode 100644
index 2f9c9ee5f16e668149a517872752236a8a4f59fb..0000000000000000000000000000000000000000
--- a/YAML/LTS_RCU2dig.yaml
+++ /dev/null
@@ -1,212 +0,0 @@
-dev_children:
-     - child_name: ADC1
-       child_dev : SPIbitbang1
-       child_conf: LTS_RCU2_ADC
-       child_GPIO:
-         - CLK     : IO3.OUT1.1 
-         - SDO     : IO3.OUT1.0 
-         - SDI     : IO3.IN1.0  
-         - SDIOdir: IO3.CONF1.0
-         - CS      : IO3.OUT2.0 
-     - child_name: ADC2
-       child_dev : SPIbitbang1
-       child_conf: LTS_RCU2_ADC
-       child_GPIO:
-         - CLK     : IO3.OUT1.3 
-         - SDO     : IO3.OUT1.2 
-         - SDI     : IO3.IN1.2  
-         - SDIOdir: IO3.CONF1.2
-         - CS      : IO3.OUT2.1 
-     - child_name: ADC3
-       child_dev : SPIbitbang1
-       child_conf: LTS_RCU2_ADC
-       child_GPIO:
-         - CLK     : IO3.OUT1.5 
-         - SDO     : IO3.OUT1.4 
-         - SDI     : IO3.IN1.4  
-         - SDIOdir: IO3.CONF1.4
-         - CS      : IO3.OUT2.2 
-
-#This is the I2C devices in the RCU
-I2C_devices:
- - dev_name: IO1
-   dev_description: IO-Expander for filter selection
-   dev_address: 0x75
-   dev_device: TCA9539
-   dev_registers:
-   - reg_name: CONF1
-     reg_addr: 6
-   - reg_name: CONF2
-     reg_addr: 7
-   - reg_name: OUT1
-     reg_addr: 2
-     ref_default: 0
-   - reg_name: OUT2
-     reg_addr: 3
-     ref_default: 0
-   - reg_name: IN1
-     reg_addr: 0
-   - reg_name: IN2
-     reg_addr: 1
-
- - dev_name: IO3
-   dev_description: IO-Expander for ADC control
-   dev_address: 0x20
-   dev_device: TCA6416
-   dev_registers:
-   - reg_name: CONF1
-     reg_description: Direction of IO pins 0..7
-     reg_addr: 6
-   - reg_name: CONF2
-     reg_description: Direction of IO pints 8..15
-     reg_addr: 7
-   - reg_name: IN1
-     reg_description: Ouput port register 0..7
-     reg_addr: 0
-   - reg_name: IN2
-     reg_description: Ouput port register 0..7
-     reg_addr: 1
-   - reg_name: OUT1
-     reg_description: Ouput port register 0..7
-     reg_addr: 2
-     reg_default: 0x0F
-   - reg_name: OUT2
-     reg_description: Ouput port register 8..15
-     reg_addr: 3
-     reg_default: 0x0F
-
- - dev_name: IO2
-   dev_description: IO-Expander for ON/OFF, Band, BUFx2
-   dev_address: 0x76
-   dev_device: TCA9539
-   dev_registers:
-   - reg_name: CONF1
-     reg_addr: 6
-   - reg_name: CONF2
-     reg_addr: 7
-   - reg_name: OUT1
-     reg_addr: 2
-     ref_default: 0
-   - reg_name: OUT2
-     reg_addr: 3
-     ref_default: 0
-   - reg_name: IN1
-     reg_addr: 0
-   - reg_name: IN2
-     reg_addr: 1
-
- - dev_name: UC
-   dev_description: RCU microcontroller 
-   dev_address: 0x40
-   dev_registers:
-   - reg_name: ID
-     reg_description: Device ID
-     reg_addr: 0
-
- - dev_name: ROM
-   dev_description: EEPROM memory
-   dev_address: 0x53
-   dev_registers:
-   - reg_name: ctr_len
-     reg_description: Length of control data
-     reg_addr: 0
-   - reg_name: ctr_dat
-     reg_description: Control data (protocol buffers)
-     reg_addr: 2
-
-
- - dev_name: AN
-   dev_description: Monitor ADC on RCU
-   dev_address: 0x14
-   dev_device: LTC2495
-   dev_registers:
-   - reg_name: Ch0
-     reg_addr: 0xB080
-   - reg_name: Ch1
-     reg_addr: 0xB8
-   - reg_name: Ch2
-     reg_addr: 0xB1
-   - reg_name: Ch3
-     reg_addr: 0xB9
-   - reg_name: Ch4
-     reg_addr: 0xB2
-   - reg_name: Ch5
-     reg_addr: 0xBA
-   - reg_name: Ch6
-     reg_addr: 0xB3
-   - reg_name: Ch7
-     reg_addr: 0xBB
-   - reg_name: Temp
-     reg_addr: 0xA0C0
-
-Variables:
-   - var_name: Attenuator1
-     var_dev:  IO1.OUT1
-     var_width: 5
-     var_max:  21
-     var_R/W:  RW
-   - var_name: Attenuator2
-     var_dev:  IO1.OUT2
-     var_width: 5
-     var_max:  21
-     var_R/W:  RW
-   - var_name: Attenuator3
-     var_dev:  IO2.OUT1
-     var_width: 5
-     var_max:  24
-     var_R/W:  RW
-
-   - var_name: Pwr_dig
-     var_description: Enable LDOs
-     var_dict: {0 : Off, 1 : On}
-     var_dev:  IO2.OUT1
-     var_width: 1
-     var_bitoffset: 6
-     var_R/W:  RO
-
-   - var_name: LED0
-     var_description: Front panel LEDs, 0=On
-     var_dict: {0 : Off, 1 : Yellow, 2: Red, 3: Orange}
-     var_dev:  IO2.OUT2
-     var_width: 2
-     var_bitoffset: 6
-     var_R/W:  RW
-
-   - var_name: Temperature
-     var_dev:  AN.Temp
-     var_width: 23
-     var_scale: 4.21e-3
-     var_R/W:  RO
-
-
-          
-Methods:
-   - method_name: RCU_on
-     registers:
-        - IO2.CONF1: [0]    #Setup IO expanders to output with default values
-        - IO2.OUT1: [0x4A]
-        - IO2.OUT2: [0x55]
-        - IO3.OUT1: [0x7f]
-        - IO3.OUT2: [0x47]
-        - IO1.OUT1: [0xCA]
-        - IO1.OUT2: [0xCA]
-        - IO2.CONF2: [0]
-        - IO3.CONF1: [0]
-        - IO3.CONF2: [0]
-        - IO1.CONF1: [0]
-        - IO1.CONF2: [0]
-        - ADC1_Setup: 1
-        - ADC2_Setup: 1
-        - ADC3_Setup: 1
-
-   - method_name: RCU_off
-     registers:
-        - IO2.OUT1: [0x00] #Switch all off
-        - IO2.OUT2: [0x00]
-        - IO3.OUT1: [0x00]
-        - IO3.OUT2: [0x00]
-        - IO1.OUT1: [0x00]
-        - IO1.OUT2: [0x00]
-
-
-
diff --git a/YAML/LTS_clk.yaml b/YAML/LTS_clk.yaml
deleted file mode 100644
index 58ae764f2450bfe0eb7c1be8ace23df2842e28c4..0000000000000000000000000000000000000000
--- a/YAML/LTS_clk.yaml
+++ /dev/null
@@ -1,84 +0,0 @@
-dev_children:
-     - child_name: PLL
-       child_dev : SPIbitbang2
-       child_conf: LTS_clkPLL
-       child_GPIO:
-         - CLK     : IO3.OUT1.4
-         - SDO     : IO3.IN1.5
-         - SDI     : IO3.OUT1.7
-         - CS      : IO3.OUT1.6
-
-#This is the I2C devices in the RCU
-I2C_devices:
- - dev_name: IO3
-   dev_description: IO-Expander
-   dev_address: 0x20
-   dev_device: TCA6416
-   dev_registers:
-   - reg_name: CONF1
-     reg_addr: 6
-   - reg_name: CONF2
-     reg_addr: 7
-   - reg_name: IN1
-     reg_addr: 0
-   - reg_name: IN2
-     reg_addr: 1
-   - reg_name: OUT1
-     reg_addr: 2
-     reg_default: 0x0F
-   - reg_name: OUT2
-     reg_addr: 3
-     reg_default: 0x0F
-
-Variables:
-   - var_name: IGNORE_PPS
-     var_dev:  IO3.OUT1
-     var_width: 1
-     var_bitoffset: 6
-#     var_R/W:  RW
-
-   - var_name: ENABLE_PWR
-     var_dev:  IO3.OUT1
-     var_width: 1
-     var_bitoffset: 7
-#     var_R/W:  RW
-
-   - var_name: STAT1
-     var_dev:  IO3.OUT1
-     var_width: 1
-     var_bitoffset: 4
-#     var_R/W:  RO
-
-#  - var_name: STAT2
-#     var_dev:  IO3.OUT1
-#     var_width: 1
-#     var_bitoffset: 5
-#     var_R/W:  RO
-
-   - var_name: CONF
-     var_dev:  IO3.CONF1
-     var_width: 8
-
-   - var_name: OUT
-     var_dev:  IO3.OUT1
-     var_width: 8
-
-   - var_name: IN
-     var_dev:  IO3.IN1
-     var_width: 8
-
-          
-Methods:
-   - method_name: on1
-     registers:
-        - IO3.CONF1: [0x2C]
-        - IO3.OUT1: [0x42]     
-   - method_name: off1
-     method_invisible: 1
-     registers:
-        - IO3.CONF1: [0x2C]
-        - IO3.OUT1: [0x40] 
-
-#Output High=SDI(x2), PPS (0x40)  #Read 0x42, 
-# IN=0x46: High: SDI, CLK, Enable_PWR
-
diff --git a/YAML/LTS_clkPLL.yaml b/YAML/LTS_clkPLL.yaml
deleted file mode 100644
index c6e99bb74ccc33cc5454bbc8b10766e1f8948d44..0000000000000000000000000000000000000000
--- a/YAML/LTS_clkPLL.yaml
+++ /dev/null
@@ -1,43 +0,0 @@
-I2C_devices:
- - dev_name: PLL1
-   dev_description: I2C-SPI bridge to PLL
-   dev_device: LTC6950
-   dev_registers:
-    - reg_name: a0
-      reg_addr: 0x00
-
-Variables:
-   - var_name: locked
-     var_dev:  PLL1.a0
-     var_R/W:  RO
-     var_width: 23
-
-Methods:
-   - method_name: Power_off
-     method_invisible: 1
-     registers:
-        - PLL1.3: [0x88] 
-   - method_name: Power_on
-     method_invisible: 1
-     registers:
-        - PLL1.3: [0x08] 
-   - method_name: Reset
-     method_invisible: 1
-     registers:
-        - PLL1.3: [0x0C] 
-   - method_name: Setup
-     method_invisible: 1
-     registers:
-        - PLL1.3: [0x08] 
-        - PLL1.5: [0x97] 
-        - PLL1.6: [0x10] 
-        - PLL1.7: [0x04] 
-        - PLL1.8: [0x01] 
-        - PLL1.7: [0x00] 
-        - PLL1.9: [0x10] 
-        - PLL1.10: [0x14] #0x0A
-        - PLL1.9: [0x00] 
-        - PLL1.13: [0x01] #0x0D 
-        - PLL1.15: [0x01] #0x0F
-        - PLL1.17: [0x01] #0x11
-        - PLL1.19: [0x01] #0x13
diff --git a/YAML/LTS_pypcc.yaml b/YAML/LTS_pypcc.yaml
deleted file mode 100644
index a059a312ba6e84e319a4a0eb09d9743a7b0e7e4d..0000000000000000000000000000000000000000
--- a/YAML/LTS_pypcc.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-dev_name: PCC_I2C
-dev_children:
-     - child_dev : I2Cswitch
-       child_conf: LTS_switch
-       child_addr: 1 #I2C port on raspberry pi
\ No newline at end of file
diff --git a/YAML/LTS_switch.yaml b/YAML/LTS_switch.yaml
deleted file mode 100644
index eec8a3935bb327201e51b6d337abf968df45fd72..0000000000000000000000000000000000000000
--- a/YAML/LTS_switch.yaml
+++ /dev/null
@@ -1,26 +0,0 @@
-dev_name: Switch1
-dev_address: 0x70 
-dev_device: TCA9548
-# LTS midplane: I2C 0-5 = RCU 0-5, I2C 6 = UNB2_N0, I2C 7 = UNB2
-dev_children:
-     - child_name: RCU01
-       child_dev: I2Cdevices
-       child_conf:  LTS_RCU2L
-       child_addr: 1
-     - child_name: RCU02
-       child_dev: I2Cdevices
-       child_conf:  LTS_RCU2L
-       child_addr: 2
-     - child_name: RCU03
-       child_dev: I2Cdevices
-       child_conf:  LTS_RCU2L
-       child_addr: 3
-     - child_name: CLK
-       child_dev: I2Cdevices
-       child_conf:  LTS_clk
-       child_addr: 7
-
-dev_groups: #Must have the same config!
- - group_name: RCUs
-   group_members: [RCU01,RCU02,RCU03]
-#   group_members: [RCU01]
diff --git a/clk/CLK.py b/clk/CLK.py
new file mode 100644
index 0000000000000000000000000000000000000000..a7dee31b6e9fe9ff0a80860d2d55ce7195d057eb
--- /dev/null
+++ b/clk/CLK.py
@@ -0,0 +1,303 @@
+from . import Vars
+import numpy as np
+import logging
+#from .spibitbang1 import *
+import threading
+
+
+def ApplyMask(value,width=8,bitoffset=0,previous=0):
+    mask=(1<<width)-1
+    if bitoffset>0:
+      value<<=bitoffset;
+      mask<<=bitoffset;
+    return (value & mask) + (previous - (previous & mask));
+def UnMask(value,width=8,bitoffset=0):
+    mask=(1<<width)-1
+    if bitoffset>0:
+      value>>=bitoffset;
+    value=value&mask;
+    return value;
+
+def bytes2int(bts):
+   x=0;
+   for b in bts:
+     x=x*256+b;
+   return x;
+def int2bytes(i):
+   b=[];
+   while i>255: 
+        b=[i%256]+b;
+        i>>=8;
+   return [i]+b;
+
+class RCU1():
+    def __init__(self,number,I2Ccallback,Switchcallback):
+        self.N=number;
+        self.I2Ccallback=I2Ccallback
+        self.SWcallback=Switchcallback
+        self.previous=np.zeros([number,Vars.RCU_storeReg],dtype='int')
+
+    def load(self):
+        Inst1=Vars.Instr(Vars.DevType.Instr,Vars.RCU_init,0,[])  #Read the current status of GPIO IOs
+        self.SetVar(Inst1)
+      
+#Vars.RCU_mask.OPCW.get_data_value().Value.Value=[1,1,0,0]
+#Vars.Ant_mask.OPCW.get_data_value().Value.Value=[1,1,0,0,0,0,0,0,0,0,1,0]
+
+#Inst1=Vars.Instr(Vars.DevType.Instr,Vars.RCU_init,0,[])  #Read the current status of GPIO IOs
+#RCU.SetVar(Inst1)
+
+#Inst1=Vars.Instr(Vars.DevType.Var,Vars.RCU_att,12,[0,1,2,3,4,5,6,7,8,9,11])
+#RCU.SetVar(Inst1)
+
+#Inst1=Vars.Instr(Vars.DevType.Instr,Vars.RCU_off,0,[])
+#RCU.SetVar(Inst1)
+
+#Inst1=Vars.Instr(Vars.DevType.Instr,Vars.RCU_on,0,[])
+#RCU.SetVar(Inst1)
+
+#Inst1=Vars.Instr(Vars.DevType.Instr,Vars.ADC1_on,0,[])
+#RCU.SetVar(Inst1)
+
+#print(Vars.RCU)
+
+    def SetVar(self,Instr):
+        if Instr.type==Vars.DevType.Instr:
+              #Execute instructions
+              Iset=Instr.dev;
+              for i in Iset.instr:
+                  logging.debug(str(("Inst",i)))
+                  self.SetVar(i)
+              return;
+        if Instr.type in [Vars.DevType.I2C,Vars.DevType.SPIbb,Vars.DevType.I2Cbb]:
+            RCU0=-1;
+            mask=0
+            for RCUi in range(self.N):
+                      mask|=1<<Vars.RCU_MPaddr.Switch[RCUi]
+                      if RCU0<0: RCU0=RCUi;
+            if RCU0<0: return; #Mask all zero
+            self.SWcallback(mask)
+            if Instr.type==Vars.DevType.I2C:
+              logging.info(str(('** Set I2C:',Instr.dev,Instr.value)))
+              self.SetI2C(RCU0,Instr.dev,8,0,Instr.value)
+              return;
+            elif Instr.type==Vars.DevType.SPIbb:
+              logging.debug(str(('** Set SPIbb:',Instr.dev,Instr.value)))
+              SetSPIbb(self.SetI2C,RCU0,Instr.dev,Instr.value)
+              return;
+            elif Instr.type==Vars.DevType.I2Cbb:
+              logging.info(str(('** Set I2Cbb:',Instr.dev,Instr.value)))
+#              self.SetI2C(RCUi,Instr.dev,8,0,Instr.value)
+              return;
+        V1=Instr.dev
+        if not((Instr.nvalue==V1.nVars) and (Instr.type==Vars.DevType.VarUpdate)) and not(Instr.nvalue==V1.nVars*self.N):
+             logging.error("Wrong size of value")
+             return False
+        if V1.Vars[0].type==Vars.DevType.Internal:
+          Instr.dev.OPCW.get_data_value().Value.Value=Instr.value
+          logging.debug("Update internal variable")
+          return
+#        if V1.Vars[0].type==Vars.DevType.Internal: return;
+        Step=V1.nVars
+        value1=Instr.value if V1.OPCR is None else V1.OPCR.get_data_value().Value.Value
+        if (len(value1)==V1.nVars) and (self.N>1):  value1=(value1*self.N);
+        if Instr.type==Vars.DevType.Var:
+          logging.info(str(('** Set Var:',V1.name,value1)))
+          for RCUi in range(self.N):
+            for Vari in range(Step):
+                self.SetVarValue(RCUi,V1.Vars[Vari],Instr.value[RCUi*Step+Vari:RCUi*Step+Vari+1])
+                value2=value1[RCUi*Step+Vari:RCUi*Step+Vari+1]
+                self.GetVarValue(RCUi,V1.Vars[Vari],value2)
+                value1[RCUi*Step+Vari:RCUi*Step+Vari+1]=value2
+          if not(V1.OPCR is None): V1.OPCR.get_data_value().Value.Value=value1
+
+        elif Instr.type==Vars.DevType.VarUpdate:
+          self.GetVarValueAll(V1,value1)
+          if not(V1.OPCR is None): V1.OPCR.get_data_value().Value.Value=value1
+#          V1.OPCR.get_data_value().Value.Value=value1
+
+        logging.info(str(('** Readback:',V1.name,value1)))
+
+    def GetVarValue(self,RCUi,var,value):
+            logging.info(str(("RCU1 Get ",RCUi,var,value)))
+            if var.type==Vars.DevType.I2C:
+                self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi])
+                self.GetI2C(RCUi,var.devreg,var.width,var.bitoffset,value)
+            elif var.type==Vars.DevType.I2Cbb:
+                logging.error("I2Cbb Implemented")
+            elif var.type==Vars.DevType.SPIbb:
+                logging.error("SPIbb Implemented")
+            else:
+                logging.error("Not Implemented")
+
+    def GetVarValueAll(self,V1,value1):
+            mask=0;
+            for RCUi in range(self.N):
+                mask|=1<<Vars.RCU_MPaddr.Switch[RCUi]
+            Step=V1.nVars
+            if V1.Vars[0].type==Vars.DevType.I2C:
+              for Vari in range(Step):  
+                DevReg=V1.Vars[Vari].devreg
+                self.SWcallback(mask)
+                self.SetI2CAddr(self,DevReg)
+                if DevReg.Register_R>255: self.I2Ccallback(DevReg.Addr,[250],read=3) #Wait for ADC
+                for RCUi in range(self.N):
+                    self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi])
+                    value2=value1[RCUi*Step+Vari:RCUi*Step+Vari+1]
+                    var=V1.Vars[Vari]
+                    self.GetI2Cnoreg(RCUi,var.devreg,var.width,var.bitoffset,value2)
+                    if (var.Scale!=0): value2[0]*=var.Scale;
+                    value1[RCUi*Step+Vari:RCUi*Step+Vari+1]=value2
+            elif V1.Vars[0].type==Vars.DevType.SPIbb:
+              self.GetBBValueAll(V1,value1,mask)
+#              logging.info("SPIbb all not implemented yet")
+            else:
+               logging.error("Type not implemented")
+    def GetBBValueAll(self,V1,value1,mask):
+        def SetBit(RCUi,dev,width,bitoffset,value,buffer=False):
+            if not(buffer): self.SWcallback(mask)
+            self.SetI2C(RCUi,dev,width,bitoffset,value,buffer=buffer)
+        def GetBit(RCUixx,dev,width,bitoffset,buffer=False):
+            value=[0 for RCUi in range(self.N)]
+            value2=[0]
+            if buffer: 
+                for RCUi in range(self.N):
+                  self.GetI2Cbuffer(RCUi,dev,width,bitoffset,value2)
+                  value[RCUi]=value2[0]
+                return value
+            self.SWcallback(mask)
+            self.SetI2CAddr(self,dev)
+            for RCUi in range(self.N):
+                self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi])
+                self.GetI2Cnoreg(RCUi,dev,width,bitoffset,value2)
+                value[RCUi]=value2[0]
+            return value;
+        devs=[V1.Vars[Vari].devreg for Vari in range(V1.nVars)]
+        GetSPIbb2(SetBit,GetBit,0,devs,value1)
+
+
+    def SetVarValue(self,RCUi,var,value):
+            if var.devreg.Register_W==-1: return True; #We can not set it, only read it e.g. temperature
+            logging.debug(str(("RCU1 Set ",RCUi,var,value)))
+            if var.type==Vars.DevType.I2C:
+                self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi])
+                self.SetI2C(RCUi,var.devreg,var.width,var.bitoffset,value)
+            elif var.type==Vars.DevType.I2Cbb:
+                logging.error("I2Cbb Implemented")
+            elif var.type==Vars.DevType.SPIbb:
+                logging.error("SPIbb Implemented")
+            else:
+                logging.error("Not Implemented")
+
+    def SetI2C(self,RCUi,dev,width,bitoffset,value,buffer=False):
+        if dev.store>0:
+            previous=self.previous[RCUi,dev.store-1];
+            value[0]=ApplyMask(value[0],width,bitoffset,previous);
+            self.previous[RCUi,dev.store-1]=value[0]
+#            logging.debug(str(('masked to',value)))
+#            logging.debug(str(("Store buffer",RCUi,dev.store,value[0])))
+        if buffer: return True;
+        return self.I2Ccallback(dev.Addr,value,reg=dev.Register_W)
+
+    def GetI2Cbuffer(self,RCUi,dev,width,bitoffset,value):
+        if not(dev.store>0): return False;
+        value[0]=self.previous[RCUi,dev.store-1];
+#        logging.debug(str(("GetI2Cbuffer",RCUi,dev.store,value)))
+        l1=int(np.floor((width+bitoffset+7)/8))
+        if (width!=l1*8) or (bitoffset>0): 
+            value[0]=UnMask(value[0],width,bitoffset)      
+        return True
+
+    def GetI2C(self,RCUi,dev,width,bitoffset,value):
+#        if dev.store>0:
+#            value[0]=self.previous[RCUi,dev.store-1]
+#        return True          
+        l1=int(np.floor((width+bitoffset+7)/8))
+#        print(width,bitoffset,l1)
+        makesinglevalue=((len(value)==1) and (l1>1));
+        if makesinglevalue: value2=[0 for x in range(l1)]
+        else: value2=value
+        reg=dev.Register_R
+        if reg>255: #This is for the monitor ADC
+          if not(self.I2Ccallback(dev.Addr,int2bytes(reg),read=2)): return False;
+          I2Ccallback(Addr,[250],read=3)
+          if not(self.I2Ccallback(dev.Addr,value2,read=1)): return False;
+        else:
+          if not(self.I2Ccallback(dev.Addr,value2,reg=reg,read=1)): return False;
+        if value2[0] is None:  return False
+        if makesinglevalue: value[0]=bytes2int(value2)
+        else: value[:]=value2[:];
+        if dev.store>0:
+            self.previous[RCUi,dev.store-1]=value[0]
+#            logging.debug(str(("Store buffer",RCUi,dev.store,value[0])))
+        if (width!=l1*8) or (bitoffset>0): 
+            value[0]=UnMask(value[0],width,bitoffset)      
+        else: value[0]=value2[0]
+        return True;
+    def GetI2Cbit(self,RCUi,dev,pin):
+           value2=[value]
+           self.I2CGet(RCUi,dev,1,1<<pin,value2)
+           return value2[0]
+
+
+    def SetI2CAddr(self,RCUi,dev):
+        return self.I2Ccallback(dev.Addr,int2bytes(dev.Register_R),read=2)
+
+
+
+    def GetI2Cnoreg(self,RCUi,dev,width,bitoffset,value):
+        l1=int(np.floor((width+bitoffset+7)/8))
+        makesinglevalue=((len(value)==1) and (l1>1));
+        if makesinglevalue: value2=[0 for x in range(l1)]
+        else: value2=value
+        reg=dev.Register_R
+        if not(self.I2Ccallback(dev.Addr,value2,read=1)): return False;
+        if value2[0] is None:  return False
+        if makesinglevalue: value[0]=bytes2int(value2)
+        else: value[:]=value2[:];
+        if dev.store>0:
+            self.previous[RCUi,dev.store-1]=value[0]
+#            logging.debug(str(("Store buffer",RCUi,dev.store,value[0])))
+        if (width!=l1*8) or (bitoffset>0): 
+            value[0]=UnMask(value[0],width,bitoffset)      
+        #else: value[0]=value2[0]
+        return True;
+
+    def start(self,Q1):
+      def RCUthread(Q1):
+         while True:
+           item = Q1.get()
+           if item is None: break;
+           self.SetVar(item)
+         logging.info("End RCU thread")
+
+      RCUthread1 = threading.Thread(target=RCUthread, args=(Q1,))
+      RCUthread1.start()
+      
+      return RCUthread1 
+ 
+#    def Queue_Monitor(self,Q1):
+#         Inst1=Vars.Instr(Vars.DevType.VarUpdate,Vars.RCU_temp,32,[0]*32)
+#         Q1.put(Inst1)
+#         Inst1=Vars.Instr(Vars.DevType.VarUpdate,Vars.RCU_ADC_lock,96,[0]*96)
+#         Q1.put(Inst1)
+
+
+    def AddVars(self,Q1,AddVarR,AddVarW):
+     for v in Vars.OPC_devvars:
+        dim=Vars.RCU_MPaddr.nI2C*Vars.RCU_MPaddr.nSwitch*v.nVars
+        varvalue2=(dim*[0.0] if v.type==Vars.datatype.dfloat else dim*[0])
+        if v.RW in [Vars.RW.ReadOnly,Vars.RW.ReadWrite]:
+            var1=AddVarR(v.name+"_R",varvalue2,v)
+            v.OPCR=var1
+            Inst=Vars.Instr(Vars.DevType.VarUpdate,v,dim,varvalue2)
+            Q1.put(Inst)
+
+        if v.RW in [Vars.RW.WriteOnly,Vars.RW.ReadWrite]:
+            var1=AddVarW(v.name+"_RW",varvalue2,v,Q1)
+            v.OPCW=var1
+
+    def AddMethod(self,Q1,Addmethod):
+      for v in Vars.OPC_methods:
+        Inst1=Vars.Instr(Vars.DevType.Instr,v,0,[])
+        Addmethod(v.name,Inst1,Q1)
diff --git a/clk/HWconf.py b/clk/HWconf.py
new file mode 100644
index 0000000000000000000000000000000000000000..95060df28f62ae6bded8f6af65a5f839014ae14d
--- /dev/null
+++ b/clk/HWconf.py
@@ -0,0 +1,13 @@
+#from collections import namedtuple
+#from enum import Enum
+from pcctypes import *
+
+#Mid plane address
+RCU_MPaddr=MPaddr(1,[1],1,[7])
+
+CLK_IO3_OUT1=DevReg(0x20,0,2,1)
+CLK_IO3_OUT2=DevReg(0x20,1,3,2)
+CLK_IO3_CONF1=DevReg(0x20,6,6,3)
+CLK_IO3_CONF2=DevReg(0x20,7,7,4)
+
+RCU_storeReg=4; #Number of stored registers
diff --git a/clk/Vars.py b/clk/Vars.py
new file mode 100644
index 0000000000000000000000000000000000000000..4127783f96e4d23dc5ca8fe9d2bb7f88a1c2bdcc
--- /dev/null
+++ b/clk/Vars.py
@@ -0,0 +1,24 @@
+from .HWconf import *
+
+CLK_IGNORE_PPS= VarArray("CLK_Ignore_PPS",1,[Var2dev("",I2Cmodules.CLK,DevType.I2C,CLK_IO3_OUT1,1 ,6,1)],RW.ReadOnly,datatype.dInt,1,None,None)
+CLK_Enable_PWR= VarArray("CLK_Enable_PWR",1,[Var2dev("",I2Cmodules.CLK,DevType.I2C,CLK_IO3_OUT1,1 ,7,1)],RW.ReadOnly,datatype.dInt,1,None,None)
+CLK_Stat1     = VarArray("CLK_Stat"      ,1,[Var2dev("",I2Cmodules.CLK,DevType.I2C,CLK_IO3_OUT1,1 ,4,1)],RW.ReadOnly,datatype.dInt,1,None,None)
+
+OPC_devvars=[CLK_IGNORE_PPS,CLK_Enable_PWR,CLK_Stat1]
+
+RCU_init=Instrs("ReadRegisters",2,[
+   Instr(DevType.VarUpdate,CLK_IGNORE_PPS,1,[0]),
+   Instr(DevType.VarUpdate,CLK_Enable_PWR,1,[0])
+])
+
+CLK_on=Instrs("CLK_on",2,[
+   Instr(DevType.I2C,CLK_IO3_CONF1,1,[0x2C]),
+   Instr(DevType.I2C,CLK_IO3_OUT1 ,1,[0x42]),
+])
+
+CLK_off=Instrs("CLK_off",2,[
+   Instr(DevType.I2C,CLK_IO3_CONF1,1,[0x2C]),
+   Instr(DevType.I2C,CLK_IO3_OUT1 ,1,[0x40]),
+])
+
+OPC_methods=[CLK_on]
diff --git a/clk/__init__.py b/clk/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/hwdev.py b/hwdev.py
deleted file mode 100644
index fb98964a03ba06559df8a18cc833ba51c17746d1..0000000000000000000000000000000000000000
--- a/hwdev.py
+++ /dev/null
@@ -1,63 +0,0 @@
-import yaml;
-import importlib
-import sys, inspect
-import logging
-
-YAMLDIR='YAML/'
-class hwdev:
-    def __init__(self,configfile):
-        logging.info("Loading: %s",configfile)
-        self.D=yaml.load(open(YAMLDIR+configfile))
-        self.loadchildren(self.D)
-    def loadchildren(self,D):
-      self.children=[]
-      self.childnames=[]
-      if "dev_children" in D:
-        for c in D['dev_children']:
-          childname=(c['child_name']+"_" if c.get('child_name') else '');
-          objnm=c['child_dev']
-          yamlname=c['child_conf']
-          logging.info("Add child: %s %s %s",childname,objnm,yamlname)
-          i = importlib.import_module(objnm)
-          for name, obj in inspect.getmembers(i,inspect.isclass):
-              if name==objnm:
-#                  yamlname=(c['conf_name'] if c.get('conf_name') else nm)
-#                  logging.debug("  Load child: %s conf=%s.yaml",childname,yamlname)
-                  c['obj']=obj(yamlname+".yaml")
-                  self.children.append([childname,c['obj']])
-
-    def GetVarNames(self,parentname,callback):
-        for name,child in self.children:
-            child.GetVarNames(parentname+name,callback)
-        return True;
-
-    def GetMethodNames(self,parentname,callback):
-        for name,child in self.children:
-            child.GetMethodNames(parentname+name,callback)
-        return True;
-
-    def GetVarValue(self,name,value,I2Ccallback):
-        return False
-
-    def SetVarValue(self,name,value,I2Ccallback):
-        return False
-
-#    def CallMethod(self,name,params,I2Ccallback):
-#        for name,child in self.children:
-#            child.CallMethod(name,params,I2Ccallback)
-#        return True;
-
-
-    def CallMethod(self,name,params,I2Ccallback):
-        childname=name.split('_')[0]
-        for cname,child in self.children:
-#            logging.debug("hwdev callmethod %s %s",cname,childname)
-            if cname=="": child.CallMethod(name,params,I2Ccallback)
-            elif cname[:-1]==childname: return child.CallMethod(name[len(childname)+1:],params,I2Ccallback)
-        return False
-
-def Find(L,name,value):
-  for x in L:
-    if x[name]==value:
-        return x;
-  return False;
diff --git a/pypcc.py b/i2c/I2C.py
similarity index 55%
rename from pypcc.py
rename to i2c/I2C.py
index 29961e7c101751142296280a06d4f2a63cfe7273..1abf950ecc4c569dd746cbee4ab8b467a9ab822c 100644
--- a/pypcc.py
+++ b/i2c/I2C.py
@@ -1,4 +1,3 @@
-from hwdev import hwdev;
 import pylibi2c;
 import time
 import logging
@@ -7,12 +6,17 @@ import logging
 #read=1: read from register
 #read=2: write to register (common in group)
 #read=3: wait ms second
+I2Ccounter=0;
+
 def I2C1server(addr,data,reg=None,read=0):
   try:
        if read==3:
            time.sleep(data[0]/1000.)
            return True
-#       logging.debug("I2C addr=%s reg=%s data=%s read=%s",addr,reg,data,read)
+       logging.debug(str(("I2C",addr,reg,data,read)))
+
+#       print("I2C",addr,reg,data,read)
+#       return True;
        bus=pylibi2c.I2CDevice('/dev/i2c-1',addr)
        if read==1:
          length=len(data)
@@ -25,23 +29,10 @@ def I2C1server(addr,data,reg=None,read=0):
                bus.iaddr_bytes=0
                reg=0;
             bus.ioctl_write(reg,str(bytearray(data)))
+       bus.close()
        return True;
   except:
+       if bus: bus.close()
+#       data[0]=0
        return False;
 
-class pypcc(hwdev):
-    def GetVarValue(self,name,value):
-        for cname,child in self.children:
-            if not(child.GetVarValue(name,value,I2C1server)): return False
-        return True  
-
-    def SetVarValue(self,name,value):
-        for cname,child in self.children:
-            if not(child.SetVarValue(name,value,I2C1server)): return False
-        return True  
-
-   
-    def CallMethod(self,name,params):
-        for cname,child in self.children:
-            child.CallMethod(name,params,I2C1server)
-        return True;
diff --git a/i2c/I2C_dummy.py b/i2c/I2C_dummy.py
new file mode 100644
index 0000000000000000000000000000000000000000..63000d09c6f1c0a5b9ad3c49bbadb58da5d64833
--- /dev/null
+++ b/i2c/I2C_dummy.py
@@ -0,0 +1,21 @@
+#import pylibi2c;
+import time
+import logging
+#bus = pylibi2c.I2CDevice('/dev/i2c-1'
+#read=0: write to register
+#read=1: read from register
+#read=2: write to register (common in group)
+#read=3: wait ms second
+I2Ccounter=0;
+def I2C1server(addr,data,reg=None,read=0):
+       global I2Ccounter;
+       logging.debug(str(("I2C",addr,reg,data,read)))
+       if read==3:
+           time.sleep(data[0]/1000.)
+           return True
+       if read==1:
+           data[0]=0
+       if reg: I2Ccounter+=1;
+       I2Ccounter+=len(data)
+#       logging.debug(str(("I2C",addr,reg,data,read)))
+       return True
diff --git a/i2c/I2Cswitch1.py b/i2c/I2Cswitch1.py
new file mode 100644
index 0000000000000000000000000000000000000000..87382d058750dae14f50100d0fca3a1f1e55458a
--- /dev/null
+++ b/i2c/I2Cswitch1.py
@@ -0,0 +1,18 @@
+import numpy as np
+import logging
+#import HWconf
+SWaddr=0x70
+class I2Cswitch1():
+    def __init__(self,callback1):
+        self.callback1=callback1;
+        self.CurrentChannel=0;
+
+    def SetChannel(self,channel):
+        if (channel)==self.CurrentChannel: return True;
+        logging.debug(str(("SetChannel",channel,self.CurrentChannel)))
+        self.CurrentChannel=channel
+        return self.callback1(SWaddr,[channel])
+
+    def I2Ccallback(self,RCU,addr,data,reg=None,read=0):
+        self.callback1(addr,data,reg,read)    
+        
diff --git a/i2c/__init__.py b/i2c/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/i2c/setRCUversion.py b/i2c/setRCUversion.py
new file mode 100644
index 0000000000000000000000000000000000000000..4771de66e197be6a9f94861bcf39c8c4b2baa3ce
--- /dev/null
+++ b/i2c/setRCUversion.py
@@ -0,0 +1,34 @@
+from I2C import *
+import time
+RCU=1
+Ver="RCU2H v0.2"
+R1=0
+ROM=0x50
+
+#Set switch
+print("Set switch")
+if not(I2C1server(0x70,[1<<RCU],reg=None,read=0)): exit() #select RCU
+#exit()
+#Get ID
+print("Get ID")
+ID=[0]*4
+if not(I2C1server(ROM,ID,reg=0xFC,read=1)): exit() #select RCU
+print(ID)
+exit()
+
+#Upload version
+Ver2=[(c.encode('utf-8')[0]) for c in Ver]
+print(len(Ver),Ver,Ver2)
+V2=[0]
+for i,v in enumerate(Ver2):
+ time.sleep(0.1)
+ I2C1server(ROM,[v],reg=R1+i,read=0) #select RCU
+# I2C1server(ROM,[v],reg=None,read=0) #select RCU
+ time.sleep(0.1)
+ I2C1server(ROM,V2,reg=R1+i,read=1) #select RCU
+ print(i,v,V2)
+
+#Download version
+Ver2=[0]*10
+I2C1server(ROM,Ver2,reg=R1,read=1) #select RCU
+print(Ver2)
diff --git a/opcuaserv.py b/opcuaserv.py
index be0d9a9dfd12edbf2184c71f29d760470864959d..f38b8acb5a4ced13f3e49bb6d45c1897de1de520 100644
--- a/opcuaserv.py
+++ b/opcuaserv.py
@@ -5,33 +5,81 @@ sys.path.insert(0, "..")
 import time
 from opcua import ua, Server
 from datetime import datetime;
-import argparse
 import logging
+#import Vars
+#import HWconf
+from pcctypes import *
 
-parser = argparse.ArgumentParser()
-parser.add_argument("-s", "--simulator", help="Do not connect to I2c, but simulate behaviour.", action="store_true")
-parser.add_argument("--no-lib-hack", help="Do not require a hacked opcua library. Breaks behaviour.", action="store_true")
-parser.add_argument("-p", "--port", help="Port number to listen on [%(default)s].", type=int, default=4842)
-parser.add_argument("-l", "--loglevel", help="Log level [%(default)s].", type=str, choices=["DEBUG","INFO","WARNING","ERROR"], default="DEBUG")
-args = parser.parse_args()
+Vars_R={}
+Vars_W={}
+running=False
 
-# set log level
-loglevel_nr = getattr(logging, args.loglevel.upper(), None)
-if not isinstance(loglevel_nr, int):
-    raise ValueError('Invalid log level: %s' % args.loglevel)
-logging.basicConfig(level=loglevel_nr, format="%(asctime)s [%(levelname)8s] %(message)s")
+class SubHandler(object):
+    """
+    Subscription Handler. To receive events from server for a subscription
+    """
+    def datachange_notification(self, node, val, data):
+#        print("Python: New data change event", node, val,data)
+        if not(running): return
+        vname,myvar,VarD,Q1=Vars_W[node.nodeid.Identifier]
+#        val=(val if isinstance(val, list) else [val] )
+        logging.info(str(("Datachange callback",vname,val)))
+#        myvar2.Value.Value=val
+#        myvar2.SourceTimestamp = datetime.utcnow()
+
+        Inst=Instr(DevType.Var,VarD,len(val),val)
+        Q1.put(Inst)
+ #       P1.SetVarValue(vname,val)
+        #readback
+#        if True:
+#        print(Vars_R,Vars_R.values())
+#        for vname2,myvar2,oldvalue in Vars_R.values():
+#            if vname2==vname:
+#              res=P1.GetVarValue(vname,val)
+#              print("Read callback",vname,": Result:",res,oldvalue)
+#              if res:
 
-if args.simulator:
-    import pypcc_test as pypcc
-else:
-    import pypcc
+    def event_notification(self, event):
+        logging.info(str(("Python: New event", event)))
 
-P1=pypcc.pypcc("LTS_pypcc.yaml")
 
-if True:
+def CallMethod(ObjectID,name,Inst1,Q1):
+        logging.info(str(("Callmethod",ObjectID,name)))
+#        Inst1=Vars.Instr(Vars.DevType.Instr,instrs,0,[])
+        Q1.put(Inst1)
+
+#        P1.CallMethod(name,None)
+
+def AddVar(name,value):
+    myvar2 = PCCobj.add_variable(idx, name, value)
+    myvar2.set_writable()
+    return myvar2
+
+def AddVarR(vname,varvalue2,v):
+    myvar = PCCobj.add_variable(idx, vname, varvalue2)
+    logging.info(str(("Variable added: ",vname,len(varvalue2))))
+    Vars_R[myvar.nodeid.Identifier]=[v.name,myvar.get_data_value(),varvalue2,v]
+    return myvar
+
+def AddVarW(vname,varvalue2,v,Q1):
+    logging.info(str(("Variable added: ",vname)))#,'=',varvalue2)
+    myvar2 = PCCobj.add_variable(idx, vname, varvalue2)
+    myvar2.set_writable()
+    Vars_W[myvar2.nodeid.Identifier]=[v.name,myvar2.get_data_value(),v,Q1]
+    handle = sub.subscribe_data_change(myvar2)
+    return myvar2
+
+
+def Addmethod(vname,v,Q1):
+    myvar = PCCobj.add_method(idx, vname, lambda ObjectId,name=vname,inst=v,Q1=Q1 : CallMethod(ObjectId,name,inst,Q1), [],[] )
+    logging.info(str(("AddMethod:",vname)))
+
+def InitServer(port=4840):
+
 # setup our server
+    global server,running,PCCobj,idx,sub;
     server = Server()
-    server.set_endpoint("opc.tcp://0.0.0.0:{}/PCC/".format(args.port))
+    server.set_endpoint("opc.tcp://0.0.0.0:{}/PCC/".format(port))
 
     idx = server.register_namespace("http://lofar.eu")
 #    uri = "http://examples.freeopcua.github.io"
@@ -41,141 +89,32 @@ if True:
 
     # populating our address space
     PCCobj = objects.add_object(idx, "PCC")
+#    self.PCCobj=PCCobj
     
-    #    myvar = myobj.add_variable(idx, "MyVariable", 6.7)
-#    myvar.set_writable()    # Set MyVariable to be writable by clients
-
     # starting!
-
-#Vars={}
-#Vars[1]='123'
-#logging.info("%s", Vars)
+    logging.info("Start server");
+    server.start()
+    handler = SubHandler()
+    sub = server.create_subscription(500, handler)
+    running=False;
+    logging.info("Add variables:")
+#P1.GetVarNames("",AddVar);
+
+#    time.sleep(1)
+#    running=True
+#    return Vars_R,Vars_W
+    return
 #exit()
-def ValCallback(nodeid,force=False):
-    vname,myvar,oldvalue=Vars_R[nodeid.Identifier]
-#    logging.info("Value callback %s",vname)
-#    vname=vname[vname.find('_')+1:]
-#    logging.info("RCU variable: %s=%s",vname,oldvalue)
-#    X=RCU1.Getvar2(vname)
-#    if not(running): 
-    if False: 
-        myvar.Value.Value=(oldvalue[0] if len(oldvalue)==1 else oldvalue)
-        myvar.SourceTimestamp = datetime.utcnow()
-        return myvar
-    timenow=datetime.utcnow()
-    timediff=(timenow-myvar.SourceTimestamp).total_seconds()
-#    logging.info("%s",timediff)
-    if not(force) and timediff<90: return myvar;
-    res=P1.GetVarValue(vname,oldvalue)
-    logging.info("Read callback %s: Result: %s Value: %s",vname,res,oldvalue)
-    if res:
-        myvar.Value.Value=(oldvalue[0] if len(oldvalue)==1 else oldvalue)
-        myvar.SourceTimestamp = datetime.utcnow()
-#        Vars_R[nodeid.Identifier][3]=oldvalue
-    return myvar
 
+def start():
+    global running
+    running=True
 
+#print("Add modes:")
+#P1.GetMethodNames("",AddMethod);
 
-class SubHandler(object):
-    """
-    Subscription Handler. To receive events from server for a subscription
-    """
-
-    def datachange_notification(self, node, val, data):
-        #        logging.info("Python: New data change event: %s %s %s", node, val,data)
-        if not(running): return
-        vname,myvar=Vars_W[node.nodeid.Identifier]
-        val=(val if isinstance(val, list) else [val] )
-        logging.info("Write callback %s=%s",vname,val)
-        P1.SetVarValue(vname,val)
-        #readback
-#        if True:
-#        logging.info(Vars_R,Vars_R.values())
-        for vname2,myvar2,oldvalue in Vars_R.values():
-            if vname2==vname:
-              if args.simulator:
-                res=True
-                logging.info("Simulating fallthrough _RW->_R for",vname,": Result:",res,oldvalue)
-              else:
-                res=P1.GetVarValue(vname,val)
-                logging.info("Read callback",vname,": Result:",res,oldvalue)
-              if res:
-                myvar2.Value.Value=(val[0] if len(val)==1 else val)
-                myvar2.SourceTimestamp = datetime.utcnow()
 
 
-    def event_notification(self, event):
-        logging.debug("Python: New event %s", event)
-
-
-def CallMethod(ObjectID,name):
-        logging.debug("Callmethod %s",name)
-        P1.CallMethod(name,None)
-
-
-
-#P1.RunMethod("RCU_on",None)
-#P1.SetVarValue("Band1",3)
-Vars_R={}
-Vars_W={}
-def AddVar(name,dtype=0,RW=0,cnt=1):
-   if dtype==1:
-          varvalue2=([0.0] if cnt<=1 else cnt*[0.0])
-   else:
-          varvalue2=([0] if cnt<=1 else cnt*[0])
-   if RW in [1,3]:
-        vname=name+"_R";
-        if dtype==1:
-            myvar = (PCCobj.add_variable(idx, vname, 0.0) if cnt<=1 else PCCobj.add_variable(idx, vname, cnt*[0.0]))
-        else:
-            myvar = (PCCobj.add_variable(idx, vname, 0)   if cnt<=1 else PCCobj.add_variable(idx, vname, cnt*[0]))
-        logging.info("Variable added: %s",vname)
-        Vars_R[myvar.nodeid.Identifier]=[name,myvar.get_data_value(),varvalue2]
-        ValCallback(myvar.nodeid,force=True)
-#        logging.info("%s",myvar.get_value())
-        if not args.no_lib_hack:
-            server.set_attribute_callback(myvar.nodeid, ValCallback)
-#        varvalue=myvar.get_data_value().Value
-#        Vars_R[myvar.nodeid.Identifier][2]=varvalue
-#        logging.info("%s %s",varvalue2,varvalue)
-
-   if RW in [2,3]:
-        vname=name+"_RW";
-        logging.info("Variable added: %s",vname)#,'=',varvalue2)
-        myvar2 = PCCobj.add_variable(idx, vname, (varvalue2[0] if len(varvalue2)==1 else varvalue2))
-        myvar2.set_writable()
-        Vars_W[myvar2.nodeid.Identifier]=[name,myvar2.get_data_value()]
-        handle = sub.subscribe_data_change(myvar2)
-
-
-def AddMethod(name):
-        vname=name;
-        myvar = PCCobj.add_method(idx, vname, lambda ObjectId : CallMethod(ObjectId,name), [],[] )
-        logging.info("AddMethod: %s",vname)
-
-logging.info("Start server");
-server.start()
-handler = SubHandler()
-sub = server.create_subscription(500, handler)
-running=False;
-logging.info("Add variables:")
-P1.GetVarNames("",AddVar);
-
-logging.info("Add modes:")
-P1.GetMethodNames("",AddMethod);
-
-time.sleep(1)
-running=True;
-
-logging.info("Server started")   
-    
-try:
-    while True:
-        time.sleep(1)
-finally:
-        logging.info("Stop server");
-        server.stop()
-
 
 
 
@@ -198,16 +137,16 @@ finally:
 #RCU.Setvar2('Power_Ant1',[0])
 
 
-#logging.info(RCU.Getvar2('Amp_Gain0'))
+#print(RCU.Getvar2('Amp_Gain0'))
 
 
-#logging.info(RCU.Getvar2('ID'))
+#print(RCU.Getvar2('ID'))
 
 
-#logging.info(RCU.Getvar2('ADC_lock1'))
+#print(RCU.Getvar2('ADC_lock1'))
 
 
-#logging.info(RCU.Getvar2('HBA_DelayX1',element=1))
+#print(RCU.Getvar2('HBA_DelayX1',element=1))
 
 
 
diff --git a/pcctypes.py b/pcctypes.py
new file mode 100644
index 0000000000000000000000000000000000000000..1450ec4701ec6f76d6a96a1141b592e874666fc2
--- /dev/null
+++ b/pcctypes.py
@@ -0,0 +1,79 @@
+#For capnproto
+from collections import namedtuple
+from enum import Enum
+from recordclass import recordclass
+
+#I2C ports & Switch addresses of device
+MPaddr=namedtuple("MPaddr","nI2C I2C nSwitch Switch"); 
+
+#Device registers
+DevReg=namedtuple("DevReg","Addr Register_R Register_W store"); 
+#Addr: Byte (I2C) or *BBdev
+#Register_R/W: Byte (I2C register)
+#store: Byte 0=not stored else store index
+
+#Bitbang devices
+BBdev=namedtuple("BBdev","nPins devs pins addr")
+# devs: *DevReg[nPins]
+# pins:  Byte[nPins]
+# addr:  Byte (SPI device address)
+
+
+class I2Cmodules(Enum):
+   Switch = 0
+   RCU = 1
+   CLK = 2
+   UNB2 = 3
+
+class DevType(Enum):
+    Var = 0
+    I2C  = 1
+    SPIbb= 2
+    I2Cbb= 3
+    Instr =4
+    VarUpdate = 5
+    Internal = 6
+    HBA1 = 7
+    HBA2 = 8
+
+class RW(Enum):
+    Hidden = 0  #Not an OPC_UA variable
+    ReadOnly = 1  #OPC_variable name_R
+    WriteOnly = 2 #OPC_variable name_RW
+    ReadWrite = 3  #both of above
+
+class datatype(Enum):
+   dInt = 0
+   dfloat = 1
+   dstring = 2
+
+#Variable two device link
+Var2dev=namedtuple("Var2dev","name module type devreg width bitoffset Scale")
+#name: string (Currently unused!)
+#module: I2Cmodules
+#Type: DevType
+#DevReg: *DevReg
+#Width: Byte (# of bits)
+#Bitoffset: Byte
+#Scale: Float (=1 means no scaling i.e. integer)
+
+#OPC-UA variable: Array of similar variables
+VarArray=recordclass("VarArray","name nVars Vars RW type size OPCR OPCW") #OPCR and OPCW linked at runtime
+#name: string
+#Vars: *Var2dev[nVars]
+#RW: RW
+#type: datatype
+#size: =nVars (default), but x16/32 for HBA antennas
+#OPCR/W: pointer to variable in OPC-UA server (linked during runtime)
+
+#Instruction
+Instr=namedtuple("DevInstr","type dev nvalue value")
+#Type: DevType
+#dev: pointer to vararray / DevReg / etc depending on type
+#value: Bytes[nvalue]
+
+#List of instructions
+Instrs=namedtuple("Instr","name ninstr instr")
+#name: string
+#inst: Instr[ninstr]
+
diff --git a/pypcc.code-workspace b/pypcc.code-workspace
deleted file mode 100644
index 362d7c25bb405a5cc76d0c7518cc240999a574f4..0000000000000000000000000000000000000000
--- a/pypcc.code-workspace
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-	"folders": [
-		{
-			"path": "."
-		}
-	]
-}
\ No newline at end of file
diff --git a/pypcc2.py b/pypcc2.py
new file mode 100644
index 0000000000000000000000000000000000000000..7d7b53ec12842885482d182d89dd585a05290016
--- /dev/null
+++ b/pypcc2.py
@@ -0,0 +1,107 @@
+import opcuaserv
+try:
+ import queue
+except ImportError:
+ import Queue as queue;
+from rcu import RCU
+from clk import CLK
+from i2c import I2Cswitch1
+import threading
+import signal
+import sys
+import time
+#import Vars
+import logging
+import argparse
+
+parser = argparse.ArgumentParser()
+parser.add_argument("-s", "--simulator", help="Do not connect to I2c, but simulate behaviour.", action="store_true")
+parser.add_argument("-p", "--port", help="Port number to listen on [%(default)s].", type=int, default=4842)
+parser.add_argument("-l", "--loglevel", help="Log level [%(default)s].", type=str, choices=["DEBUG","INFO","WARNING","ERROR"], default="INFO")
+args = parser.parse_args()
+
+# set log level
+loglevel_nr = getattr(logging, args.loglevel.upper(), None)
+if not isinstance(loglevel_nr, int):
+    raise ValueError('Invalid log level: %s' % args.loglevel)
+#logging.basicConfig(level=loglevel_nr, format="%(asctime)s [%(levelname)8s] %(message)s")
+
+logging.basicConfig(level=loglevel_nr,format='%(asctime)s [%(levelname)-8s,%(filename)-20s:%(lineno)-3d] %(message)s')
+if args.simulator:
+    from i2c import I2C_dummy as I2C
+else:
+    from i2c import I2C
+
+#Queue used to pass instructions from opc-ua server to RCU
+Q1=queue.Queue() #RCUs
+Q2=queue.Queue() #CLK
+
+#Setup OPCUA server (running in its own thread)
+opcuaserv.InitServer(port=args.port)
+logging.info("OPC-UA Server started")   
+
+SW1=I2Cswitch1.I2Cswitch1(I2C.I2C1server)
+
+RCU=RCU.RCU1(32,I2C.I2C1server,SW1.SetChannel)
+RCU.AddVars(Q1,opcuaserv.AddVarR,opcuaserv.AddVarW)
+RCU.AddMethod(Q1,opcuaserv.Addmethod)
+RCU.load() #Load current register values from HW
+
+#CLK=CLK.RCU1(1,I2C.I2C1server,SW1.SetChannel)
+#CLK.AddVars(Q2,opcuaserv.AddVarR,opcuaserv.AddVarW)
+#CLK.AddMethod(Q2,opcuaserv.Addmethod)
+#CLK.load() #Load current register values from HW
+
+#logging.debug(str(("I2C bytes=",I2C.I2Ccounter)))
+
+if False:
+  opcuaserv.server.stop()
+  exit()
+
+RCUthread1=RCU.start(Q1)
+#CLKthread1=CLK.start(Q2)
+
+RunTimer=True;
+def TimerThread(Q1,RCU):
+    V1=opcuaserv.AddVar("RCU_monitor_rate_RW",30)
+    cnt=0;#Count second ticks
+    while RunTimer:
+       time.sleep(1)
+       T1=V1.get_data_value().Value.Value
+       if T1==0:
+           continue;
+       cnt+=1;
+       if cnt>=T1:
+         if Q1.qsize()>3: continue;
+         cnt=0;
+         logging.debug(str(("I2C bytes=",I2C.I2Ccounter," Qlength=",Q1.qsize())))
+         RCU.Queue_Monitor(Q1)
+
+    logging.info("End Timer thread")
+
+Timerthread1 = threading.Thread(target=TimerThread, args=(Q1,RCU))
+Timerthread1.start()
+
+# on SIGINT: stop thread(s) by adding None to instruction queue(s)
+def signal_handler(sig, frame):
+    logging.info('Stop RCU thread')
+    Q1.put(None)
+    Q2.put(None)
+    logging.info('Stop timer thread')
+    global RunTimer; 
+    RunTimer=False
+signal.signal(signal.SIGINT, signal_handler)
+
+time.sleep(1)
+opcuaserv.start()
+
+try:
+#Do nothing.
+ while RunTimer:
+    time.sleep(1)
+finally:
+        logging.info("Stop OPC-UA server")
+        opcuaserv.server.stop()
+        RCUthread1.join()
+#        CLKthread1.join()
+        Timerthread1.join()
diff --git a/pypcc_test.py b/pypcc_test.py
deleted file mode 100644
index ee5a8f09dac088fbba4738dc8e3f259f0e1d469e..0000000000000000000000000000000000000000
--- a/pypcc_test.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from hwdev import hwdev;
-import time
-import logging
-
-def I2C1server(addr,data,reg=None,read=0):
-       logging.info("I2C: addr=%s data=%s reg=%s read=%s",addr,data,reg,read)
-       return True;
-
-class pypcc(hwdev):
-    def GetVarValue(self,name,value):
-        for cname,child in self.children:
-            if not(child.GetVarValue(name,value,I2C1server)): return False
-        return True  
-
-    def SetVarValue(self,name,value):
-        for cname,child in self.children:
-            if not(child.SetVarValue(name,value,I2C1server)): return False
-        return True  
-
-   
-    def CallMethod(self,name,params):
-        for cname,child in self.children:
-            child.CallMethod(name,params,I2C1server)
-        return True;
diff --git a/rcu/HWconf.py b/rcu/HWconf.py
new file mode 100644
index 0000000000000000000000000000000000000000..8f9323da309bfa5e3fc21896738e93c3592e4240
--- /dev/null
+++ b/rcu/HWconf.py
@@ -0,0 +1,102 @@
+#from collections import namedtuple
+#from enum import Enum
+from pcctypes import *
+#Mid plane address
+#MPaddr=namedtuple("MPaddr","nI2C I2C nSwitch Switch"); 
+RCU_MPaddr=MPaddr(1,[1],32,[0,1,2,3,4,5,6,7,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5])
+#CLK_MPaddr=MPaddr(1,[1],1,[7])
+
+#DevReg=namedtuple("DevReg","Addr Register_R Register_W store"); 
+#I2C:Addr=I2C addr (int)
+#BBdev: Addr=BBdev (pointer)
+
+#Control board switch
+#dev: TCA9548
+SW1_ch=DevReg(0x70,0,0,0) 
+#I2C IO-Expanders
+#Device: TCA9539
+RCU_IO1_OUT1=DevReg(0x75,0,2,1)
+RCU_IO1_OUT2=DevReg(0x75,1,3,2)
+RCU_IO1_CONF1=DevReg(0x75,6,6,3)
+RCU_IO1_CONF2=DevReg(0x75,7,7,4)
+#Device: TCA9539
+RCU_IO2_OUT1=DevReg(0x76,0,2,5)
+RCU_IO2_OUT2=DevReg(0x76,1,3,6)
+RCU_IO2_CONF1=DevReg(0x76,6,6,7)
+RCU_IO2_CONF2=DevReg(0x76,7,7,8)
+#Device: TCA6416
+RCU_IO3_OUT1=DevReg(0x20,0,2,9)
+RCU_IO3_OUT2=DevReg(0x20,1,3,10)
+RCU_IO3_CONF1=DevReg(0x20,6,6,11)
+RCU_IO3_CONF2=DevReg(0x20,7,7,12)
+
+RCU_storeReg=13; #Number of stored registers
+
+#I2C monitor ADC
+RCU_AN_Ch0=DevReg(0x14,0xB080,-1,0)
+RCU_AN_Ch1=DevReg(0x14,0xB880,-1,0)
+RCU_AN_Ch2=DevReg(0x14,0xB180,-1,0)
+#etc
+RCU_AN_Temp=DevReg(0x14,0xA0C0,-1,0)
+
+#HBA1
+RCU_HBA1=DevReg(0x41,0,0,1)
+RCU_HBA2=DevReg(0x42,0,0,2)
+RCU_HBA3=DevReg(0x43,0,0,3)
+
+
+RCU_ROM_ID =DevReg(0x50,0xfc,0xfc,0) #32 bit ID=4 bytes
+RCU_ROM_Ver=DevReg(0x50,0,0,0) #String
+
+#Bitbang devices
+#BBdev=namedtuple("BBdev","nPins devs pins addr")
+I2CBB_dth3=BBdev(3,[RCU_IO1_OUT1,RCU_IO2_OUT2,RCU_IO2_CONF2],[6,3,3],0x70); #SCL,SDIO,SDIOdir
+I2CBB_dth2=BBdev(3,[RCU_IO1_OUT2,RCU_IO2_OUT1,RCU_IO1_CONF1],[7,7,7],0x70);
+I2CBB_dth1=BBdev(3,[RCU_IO1_OUT2,RCU_IO2_OUT1,RCU_IO1_CONF1],[7,7,7],0x70);
+SPIBB_ADC1=BBdev(4,[RCU_IO3_OUT1,RCU_IO3_OUT1,RCU_IO3_CONF1,RCU_IO3_OUT2],[1,0,0,0],0) #CLK,SDIO,SDIOdir,CS
+SPIBB_ADC2=BBdev(4,[RCU_IO3_OUT1,RCU_IO3_OUT1,RCU_IO3_CONF1,RCU_IO3_OUT2],[3,2,2,1],0) #CLK,SDIO,SDIOdir,CS
+SPIBB_ADC3=BBdev(4,[RCU_IO3_OUT1,RCU_IO3_OUT1,RCU_IO3_CONF1,RCU_IO3_OUT2],[5,4,4,2],0) #CLK,SDIO,SDIOdir,CS
+
+#SPI ADC 
+#Dev: AD9683 
+RCU_ADC1_PLL_stat =DevReg(SPIBB_ADC1,0X0A,0X0A,0) # PLL locked status
+RCU_ADC1_JESD_ctr =DevReg(SPIBB_ADC1,0X5F,0X5F,0) #JESD link control, ILAS mode
+RCU_ADC1_CML_level=DevReg(SPIBB_ADC1,0X15,0X15,0) #CML output adjust
+RCU_ADC1_SYNC_ctr =DevReg(SPIBB_ADC1,0X3A,0X3A,0) #SYNC / SYSREF control
+RCU_ADC1_update   =DevReg(SPIBB_ADC1,0XFF,0xFF,0)    # Global device update
+
+RCU_ADC2_PLL_stat =DevReg(SPIBB_ADC2,0X0A,0X0A,0) # PLL locked status
+RCU_ADC2_JESD_ctr =DevReg(SPIBB_ADC2,0X5F,0X5F,0) #JESD link control, ILAS mode
+RCU_ADC2_CML_level=DevReg(SPIBB_ADC2,0X15,0X15,0) #CML output adjust
+RCU_ADC2_SYNC_ctr =DevReg(SPIBB_ADC2,0X3A,0X3A,0) #SYNC / SYSREF control
+RCU_ADC2_update   =DevReg(SPIBB_ADC2,0XFF,0xFF,0)    # Global device update
+
+RCU_ADC3_PLL_stat =DevReg(SPIBB_ADC3,0X0A,0X0A,0) # PLL locked status
+RCU_ADC3_JESD_ctr =DevReg(SPIBB_ADC3,0X5F,0X5F,0) #JESD link control, ILAS mode
+RCU_ADC3_CML_level=DevReg(SPIBB_ADC3,0X15,0X15,0) #CML output adjust
+RCU_ADC3_SYNC_ctr =DevReg(SPIBB_ADC3,0X3A,0X3A,0) #SYNC / SYSREF control
+RCU_ADC3_update   =DevReg(SPIBB_ADC3,0XFF,0xFF,0)    # Global device update
+
+#I2C_dither 
+#Dev: SI4010
+RCU_Dth1_Freq =DevReg(I2CBB_dth1,0x1140,0x1141,0) ##TBC
+RCU_Dth1_Prop =DevReg(I2CBB_dth1,0x11  ,0x11,0) 
+RCU_Dth1_Start=DevReg(I2CBB_dth1,0x62  ,0x62,0) 
+RCU_Dth1_Stop =DevReg(I2CBB_dth1,0x67  ,0x67,0) 
+RCU_Dth2_Freq =DevReg(I2CBB_dth2,0x1140,0x1141,0) ##TBC
+RCU_Dth2_Prop =DevReg(I2CBB_dth2,0x11  ,0x11,0) 
+RCU_Dth2_Start=DevReg(I2CBB_dth2,0x62  ,0x62,0) 
+RCU_Dth2_Stop =DevReg(I2CBB_dth2,0x67  ,0x67,0) 
+RCU_Dth3_Freq =DevReg(I2CBB_dth3,0x1140,0x1141,0) ##TBC
+RCU_Dth3_Prop =DevReg(I2CBB_dth3,0x11  ,0x11,0) 
+RCU_Dth3_Start=DevReg(I2CBB_dth3,0x62  ,0x62,0) 
+RCU_Dth3_Stop =DevReg(I2CBB_dth3,0x67  ,0x67,0) 
+
+#class DevType(Enum):
+#    Var = 0
+#    I2C  = 1
+#    SPIbb= 2
+#    I2Cbb= 3
+#    Instr =4
+#    VarUpdate = 5
+#    Internal = 6
diff --git a/rcu/RCU.py b/rcu/RCU.py
new file mode 100644
index 0000000000000000000000000000000000000000..2c0511a932f9d4796f9cf18ec2c8d1a41ca56d9d
--- /dev/null
+++ b/rcu/RCU.py
@@ -0,0 +1,348 @@
+from . import Vars
+import numpy as np
+import logging
+from .spibitbang1 import *
+import threading
+
+
+def ApplyMask(value,width=8,bitoffset=0,previous=0):
+    mask=(1<<width)-1
+    if bitoffset>0:
+      value<<=bitoffset;
+      mask<<=bitoffset;
+    return (value & mask) + (previous - (previous & mask));
+def UnMask(value,width=8,bitoffset=0):
+    mask=(1<<width)-1
+    if bitoffset>0:
+      value>>=bitoffset;
+    value=value&mask;
+    return value;
+
+def bytes2int(bts):
+   x=0;
+   for b in bts:
+     x=x*256+b;
+   return x;
+def int2bytes(i):
+   b=[];
+   while i>255: 
+        b=[i%256]+b;
+        i>>=8;
+   return [i]+b;
+
+def strs2bytes(var):
+#    print("str2bytes",var)
+    if len(var)==0: return var;
+    if isinstance(var[0],str): #make string a byte array
+#            return [ord(c.encode('utf-8')[0]) for s in var for c in s]
+            return [c.encode('utf-8')[0] for s in var for c in s]
+    return var
+
+def bytes2strs(var,step,dtype):
+    if not(dtype==Vars.datatype.dstring): return var
+    cnt=int(len(var)/step)
+    print(var)
+    return [(bytearray(var[i*step:(i+1)*step]).decode("utf-8")) for i in range(cnt)]
+
+class RCU1():
+    def __init__(self,number,I2Ccallback,Switchcallback):
+        self.N=number;
+        self.I2Ccallback=I2Ccallback
+        self.SWcallback=Switchcallback
+        self.previous=np.zeros([number,Vars.RCU_storeReg],dtype='int')
+
+    def load(self):
+        Inst1=Vars.Instr(Vars.DevType.Instr,Vars.RCU_init,0,[])  #Read the current status of GPIO IOs
+        self.SetVar(Inst1)
+#Vars.RCU_mask.OPCW.get_data_value().Value.Value=[1,1,0,0]
+#Vars.Ant_mask.OPCW.get_data_value().Value.Value=[1,1,0,0,0,0,0,0,0,0,1,0]
+
+#Inst1=Vars.Instr(Vars.DevType.Instr,Vars.RCU_init,0,[])  #Read the current status of GPIO IOs
+#RCU.SetVar(Inst1)
+
+#Inst1=Vars.Instr(Vars.DevType.Var,Vars.RCU_att,12,[0,1,2,3,4,5,6,7,8,9,11])
+#RCU.SetVar(Inst1)
+
+#Inst1=Vars.Instr(Vars.DevType.Instr,Vars.RCU_off,0,[])
+#RCU.SetVar(Inst1)
+
+#Inst1=Vars.Instr(Vars.DevType.Instr,Vars.RCU_on,0,[])
+#RCU.SetVar(Inst1)
+
+#Inst1=Vars.Instr(Vars.DevType.Instr,Vars.ADC1_on,0,[])
+#RCU.SetVar(Inst1)
+
+#print(Vars.RCU)
+
+    def SetVar(self,Instr,Mask=[]):
+#        Instr.value=strs2bytes(Instr.value) #Alwast be an array of bytes
+        if Instr.type==Vars.DevType.Instr:
+              #Execute instructions
+              Iset=Instr.dev;
+              if len(Mask)==0:  Mask=Vars.RCU_mask.OPCW.get_data_value().Value.Value
+              for i in Iset.instr:
+                  logging.debug(str(("Inst",i)))
+                  self.SetVar(i,Mask=Mask)
+              return;
+        if Instr.type in [Vars.DevType.I2C,Vars.DevType.SPIbb,Vars.DevType.I2Cbb]:
+            if len(Mask)==0:  Mask=Vars.RCU_mask.OPCW.get_data_value().Value.Value
+            mask=0;
+            RCU0=-1;
+            for RCUi in range(self.N):
+                 if (Mask[RCUi]): 
+                      mask|=1<<Vars.RCU_MPaddr.Switch[RCUi]
+                      if RCU0<0: RCU0=RCUi;
+            if RCU0<0: return; #Mask all zero
+            self.SWcallback(mask)
+            if Instr.type==Vars.DevType.I2C:
+              logging.info(str(('** Set I2C:',Instr.dev,Instr.value)))
+              self.SetI2C(RCU0,Instr.dev,8,0,strs2bytes(Instr.value))
+              return;
+            elif Instr.type==Vars.DevType.SPIbb:
+              logging.debug(str(('** Set SPIbb:',Instr.dev,Instr.value)))
+              SetSPIbb(self.SetI2C,RCU0,Instr.dev,strs2bytes(Instr.value))
+              return;
+            elif Instr.type==Vars.DevType.I2Cbb:
+              logging.info(str(('** Set I2Cbb:',Instr.dev,Instr.value)))
+#              self.SetI2C(RCUi,Instr.dev,8,0,strs2bytes(Instr.value))
+              return;
+        V1=Instr.dev
+        if not((Instr.nvalue==V1.nVars) and (Instr.type==Vars.DevType.VarUpdate)) and not(Instr.nvalue==V1.size*self.N):
+             logging.error("Wrong size of value")
+             return False
+        if V1.Vars[0].type==Vars.DevType.Internal:
+          Instr.dev.OPCW.get_data_value().Value.Value=Instr.value
+          logging.debug("Update internal variable")
+          return
+#        if V1.Vars[0].type==Vars.DevType.Internal: return;
+        Step=V1.nVars
+        Step2=int(V1.size/V1.nVars)
+        Mask=(Vars.RCU_mask if Step==1 else Vars.Ant_mask)
+        Mask=Mask.OPCW.get_data_value().Value.Value
+        value1=strs2bytes(Instr.value) if V1.OPCR is None else strs2bytes(V1.OPCR.get_data_value().Value.Value)
+        if (len(value1)==V1.nVars) and (self.N>1):  value1=(value1*self.N);
+        if Instr.type==Vars.DevType.Var:
+          logging.info(str(('** Set Var:',V1.name,value1)))
+          for RCUi in range(self.N):
+            for Vari in range(Step):
+                if not(Mask[RCUi*Step+Vari]): continue
+                i0=(RCUi*Step+    Vari)*Step2
+                i1=(RCUi*Step+(Vari+1))*Step2
+                self.SetVarValue(RCUi,V1.Vars[Vari],Instr.value[i0:i1])
+                value2=value1[i0:i1]
+                self.GetVarValue(RCUi,V1.Vars[Vari],value2)
+                value1[i0:i1]=value2
+          if not(V1.OPCR is None): V1.OPCR.get_data_value().Value.Value=bytes2strs(value1,Step2,V1.type)
+
+        elif Instr.type==Vars.DevType.VarUpdate:
+          self.GetVarValueAll(V1,value1)
+          if not(V1.OPCR is None): V1.OPCR.get_data_value().Value.Value=bytes2strs(value1,Step2,V1.type)
+#          V1.OPCR.get_data_value().Value.Value=value1
+
+        logging.info(str(('** Readback:',V1.name,value1)))
+
+    def GetVarValue(self,RCUi,var,value):
+            logging.info(str(("RCU1 Get ",RCUi,var,value)))
+            if var.type==Vars.DevType.I2C:
+                self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi])
+                self.GetI2C(RCUi,var.devreg,var.width,var.bitoffset,value)
+            elif var.type==Vars.DevType.I2Cbb:
+                logging.error("I2Cbb Implemented")
+            elif var.type==Vars.DevType.SPIbb:
+                logging.error("SPIbb Implemented")
+            else:
+                logging.error("Not Implemented")
+
+    def GetVarValueAll(self,V1,value1):
+            mask=0;
+            for RCUi in range(self.N):
+                mask|=1<<Vars.RCU_MPaddr.Switch[RCUi]
+            Step=V1.nVars
+            Step2=int(V1.size/V1.nVars)
+            if V1.Vars[0].type==Vars.DevType.I2C:
+              for Vari in range(Step):  
+                DevReg=V1.Vars[Vari].devreg
+                self.SWcallback(mask)
+                self.SetI2CAddr(self,DevReg)
+                if DevReg.Register_R>255: self.I2Ccallback(DevReg.Addr,[250],read=3) #Wait for ADC
+                for RCUi in range(self.N):
+                    self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi])
+                    i0=(RCUi*Step+    Vari)*Step2
+                    i1=(RCUi*Step+(Vari+1))*Step2
+                    value2=value1[i0:i1]
+                    var=V1.Vars[Vari]
+#                    print(Step,Step2,i0,i1,value2,len(value1))
+                    self.GetI2Cnoreg(RCUi,var.devreg,var.width,var.bitoffset,value2)
+#                    print(value2)
+                    if (var.Scale!=0): value2[0]*=var.Scale;
+                    value1[i0:i1]=value2
+            elif V1.Vars[0].type==Vars.DevType.SPIbb:
+              self.GetBBValueAll(V1,value1,mask)
+#              logging.info("SPIbb all not implemented yet")
+            else:
+               logging.error("Type not implemented")
+#            print(value1)
+    def GetBBValueAll(self,V1,value1,mask):
+        def SetBit(RCUi,dev,width,bitoffset,value,buffer=False):
+            if not(buffer): self.SWcallback(mask)
+            self.SetI2C(RCUi,dev,width,bitoffset,value,buffer=buffer)
+        def GetBit(RCUixx,dev,width,bitoffset,buffer=False):
+            value=[0 for RCUi in range(self.N)]
+            value2=[0]
+            if buffer: 
+                for RCUi in range(self.N):
+                  self.GetI2Cbuffer(RCUi,dev,width,bitoffset,value2)
+                  value[RCUi]=value2[0]
+                return value
+            self.SWcallback(mask)
+            self.SetI2CAddr(self,dev)
+            for RCUi in range(self.N):
+                self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi])
+                #for i in range(len(value2)): value2[i]*=0;
+                value2[0]=0
+                self.GetI2Cnoreg(RCUi,dev,width,bitoffset,value2)
+                value[RCUi]=value2[0]
+            return value;
+        devs=[V1.Vars[Vari].devreg for Vari in range(V1.nVars)]
+        GetSPIbb2(SetBit,GetBit,0,devs,value1)
+
+
+    def SetVarValue(self,RCUi,var,value):
+            if var.devreg.Register_W==-1: return True; #We can not set it, only read it e.g. temperature
+            logging.debug(str(("RCU1 Set ",RCUi,var,value)))
+            if var.type==Vars.DevType.I2C:
+                self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi])
+                self.SetI2C(RCUi,var.devreg,var.width,var.bitoffset,value)
+            elif var.type==Vars.DevType.I2Cbb:
+                logging.error("I2Cbb Implemented")
+            elif var.type==Vars.DevType.SPIbb:
+                logging.error("SPIbb Implemented")
+            else:
+                logging.error("Not Implemented")
+
+    def SetI2C(self,RCUi,dev,width,bitoffset,value,buffer=False):
+        if dev.store>0:
+            previous=self.previous[RCUi,dev.store-1];
+            value[0]=ApplyMask(value[0],width,bitoffset,previous);
+            self.previous[RCUi,dev.store-1]=value[0]
+#            logging.debug(str(('masked to',value)))
+#            logging.debug(str(("Store buffer",RCUi,dev.store,value[0])))
+        if buffer: return True;
+        return self.I2Ccallback(dev.Addr,value,reg=dev.Register_W)
+
+    def GetI2Cbuffer(self,RCUi,dev,width,bitoffset,value):
+        if not(dev.store>0): return False;
+        value[0]=self.previous[RCUi,dev.store-1];
+#        logging.debug(str(("GetI2Cbuffer",RCUi,dev.store,value)))
+        l1=int(np.floor((width+bitoffset+7)/8))
+        if (width!=l1*8) or (bitoffset>0): 
+          for i in range(len(value)):
+             value[i]=UnMask(value[i],width,bitoffset)      
+        return True
+
+    def GetI2C(self,RCUi,dev,width,bitoffset,value):
+#        if dev.store>0:
+#            value[0]=self.previous[RCUi,dev.store-1]
+#        return True          
+        l1=int(np.floor((width+bitoffset+7)/8))
+#        print(width,bitoffset,l1)
+        makesinglevalue=((len(value)==1) and (l1>1));
+        if makesinglevalue: value2=[0 for x in range(l1)]
+        else: value2=value
+        reg=dev.Register_R
+        if reg>255: #This is for the monitor ADC
+          if not(self.I2Ccallback(dev.Addr,int2bytes(reg),read=2)): return False;
+          I2Ccallback(Addr,[250],read=3)
+          if not(self.I2Ccallback(dev.Addr,value2,read=1)): return False;
+        else:
+          if not(self.I2Ccallback(dev.Addr,value2,reg=reg,read=1)): return False;
+        if value2[0] is None:  return False
+        if makesinglevalue: value[0]=bytes2int(value2)
+        else: value[:]=value2[:];
+        if dev.store>0:
+            self.previous[RCUi,dev.store-1]=value[0]
+#            logging.debug(str(("Store buffer",RCUi,dev.store,value[0])))
+        if (width!=l1*8) or (bitoffset>0): 
+            for i in range(len(value)):
+              value[i]=UnMask(value[i],width,bitoffset)      
+        else: value[0]=value2[0]
+        return True;
+    def GetI2Cbit(self,RCUi,dev,pin):
+           value2=[value]
+           self.I2CGet(RCUi,dev,1,1<<pin,value2)
+           return value2[0]
+
+
+    def SetI2CAddr(self,RCUi,dev):
+        return self.I2Ccallback(dev.Addr,int2bytes(dev.Register_R),read=2)
+
+
+
+    def GetI2Cnoreg(self,RCUi,dev,width,bitoffset,value):
+        #print(width,len(value))
+        l1=int(np.floor((width+bitoffset+7)/8))
+        makesinglevalue=((len(value)==1) and (l1>1));
+        if makesinglevalue: value2=[0 for x in range(l1)]
+        else: value2=value
+        reg=dev.Register_R
+        if not(self.I2Ccallback(dev.Addr,value2,read=1)): return False;
+        if value2[0] is None:  return False
+        if makesinglevalue: value[0]=bytes2int(value2)
+        else: value[:]=value2[:];
+        if dev.store>0:
+            self.previous[RCUi,dev.store-1]=value[0]
+#            logging.debug(str(("Store buffer",RCUi,dev.store,value[0])))
+#        if width<8:
+        if (width!=l1*8) or (bitoffset>0):
+            for i in range(len(value)): 
+              value[i]=UnMask(value[i],width,bitoffset)      
+#              value[0]=UnMask(value[0],width,bitoffset)      
+        #else: value[0]=value2[0]
+        #if (len(value)>1) and (width<8): print value
+        return True;
+
+    def start(self,Q1):
+      def RCUthread(Q1):
+         while True:
+           item = Q1.get()
+           if item is None: break;
+           self.SetVar(item)
+         logging.info("End RCU thread")
+
+      RCUthread1 = threading.Thread(target=RCUthread, args=(Q1,))
+      RCUthread1.start()
+      
+      return RCUthread1 
+ 
+    def Queue_Monitor(self,Q1):
+         Inst1=Vars.Instr(Vars.DevType.VarUpdate,Vars.RCU_temp,32,[0]*32)
+         Q1.put(Inst1)
+#         Inst1=Vars.Instr(Vars.DevType.VarUpdate,Vars.RCU_ADC_lock,96,[0]*96)
+#         Q1.put(Inst1)
+
+    def AddVars(self,Q1,AddVarR,AddVarW):
+     for v in Vars.OPC_devvars:
+        dim1=Vars.RCU_MPaddr.nI2C*Vars.RCU_MPaddr.nSwitch*v.nVars
+        dim2=Vars.RCU_MPaddr.nI2C*Vars.RCU_MPaddr.nSwitch*v.size
+        dim3=int(v.size/v.nVars)
+        #print(v.name,dim)
+        varvalue2=0
+        if   v.type==Vars.datatype.dInt:    varvalue2=dim2*[0]
+        elif v.type==Vars.datatype.dfloat:  varvalue2=dim2*[0.0] 
+        elif v.type==Vars.datatype.dstring: varvalue2=dim1*[" "*dim3]
+        print(len(varvalue2),varvalue2)
+        if v.RW in [Vars.RW.ReadOnly,Vars.RW.ReadWrite]:
+            var1=AddVarR(v.name+"_R",varvalue2,v)
+#            print(len(varvalue1),len(varvalue2),v.size,dim2)
+            v.OPCR=var1
+            Inst=Vars.Instr(Vars.DevType.VarUpdate,v,dim2,varvalue2)
+            Q1.put(Inst)
+
+        if v.RW in [Vars.RW.WriteOnly,Vars.RW.ReadWrite]:
+            var1=AddVarW(v.name+"_RW",varvalue2,v,Q1)
+            v.OPCW=var1
+
+    def AddMethod(self,Q1,Addmethod):
+      for v in Vars.OPC_methods:
+        Inst1=Vars.Instr(Vars.DevType.Instr,v,0,[])
+        Addmethod(v.name,Inst1,Q1)
diff --git a/rcu/Vars.py b/rcu/Vars.py
new file mode 100644
index 0000000000000000000000000000000000000000..32ad2346108388fea36cf617818049cca5989b64
--- /dev/null
+++ b/rcu/Vars.py
@@ -0,0 +1,181 @@
+#from collections import namedtuple
+from recordclass import recordclass
+#from enum import Enum
+from .HWconf import *
+
+#OPCUA variables
+RCUmod=I2Cmodules.RCU
+
+#Var2dev=namedtuple("Var2dev","name MPaddr type devreg width bitoffset Scale")
+#VarArray=recordclass("VarArray","name nVars Vars RW type OPCR OPCW") #OPCR and OPCW linked at runtime
+RCU_att1= Var2dev("RCU_att1" ,RCUmod,DevType.I2C,RCU_IO1_OUT1,5 ,0,1)
+RCU_att2= Var2dev("RCU_att2" ,RCUmod,DevType.I2C,RCU_IO1_OUT2,5 ,0,1)
+RCU_att3= Var2dev("RCU_att3" ,RCUmod,DevType.I2C,RCU_IO2_OUT1,5 ,0,1)
+RCU_band1=Var2dev("RCU_band1",RCUmod,DevType.I2C,RCU_IO2_OUT2,2 ,0,1)
+RCU_band2=Var2dev("RCU_band2",RCUmod,DevType.I2C,RCU_IO2_OUT2,2 ,2,1)
+RCU_band3=Var2dev("RCU_band3",RCUmod,DevType.I2C,RCU_IO2_OUT2,2 ,4,1)
+RCU_led0= Var2dev("RCU_led0" ,RCUmod,DevType.I2C,RCU_IO2_OUT2,2 ,6,1)
+RCU_pwrd1=Var2dev("RCU_pwrd1",RCUmod,DevType.I2C,RCU_IO2_OUT1,1 ,6,1)
+RCU_temp1=Var2dev("RCU_temp1",RCUmod,DevType.I2C,RCU_AN_Temp ,23,0,4.21e-3)
+
+dummy=Var2dev("Dummy",RCUmod,DevType.Internal,None,8,0,1)
+
+
+Ant_mask=VarArray("Ant_mask"       ,3,[dummy,dummy,dummy]            ,RW.WriteOnly,datatype.dInt,3,None,None)
+RCU_att =VarArray("RCU_attenuator" ,3,[RCU_att1 ,RCU_att2 ,RCU_att3] ,RW.ReadWrite,datatype.dInt,3,None,None)
+RCU_band=VarArray("RCU_band"       ,3,[RCU_band1,RCU_band2,RCU_band3],RW.ReadWrite,datatype.dInt,3,None,None)
+
+RCU_mask=VarArray("RCU_mask"       ,1,[dummy]    ,RW.WriteOnly,datatype.dInt  ,1,None,None)
+RCU_temp=VarArray("RCU_temperature",1,[RCU_temp1],RW.ReadOnly ,datatype.dfloat,1,None,None)
+RCU_pwrd=VarArray("RCU_Pwr_dig"    ,1,[RCU_pwrd1],RW.ReadOnly ,datatype.dInt  ,1,None,None)
+RCU_LED =VarArray("RCU_LED0"       ,1,[RCU_led0] ,RW.ReadWrite,datatype.dInt  ,1,None,None)
+
+RCU_Dth3_freq=Var2dev("RCU_dth1_freq",RCUmod,DevType.I2Cbb,RCU_Dth3_Freq,32,0,1e-6)
+RCU_Dth2_freq=Var2dev("RCU_dth1_freq",RCUmod,DevType.I2Cbb,RCU_Dth2_Freq,32,0,1e-6)
+RCU_Dth1_freq=Var2dev("RCU_dth1_freq",RCUmod,DevType.I2Cbb,RCU_Dth1_Freq,32,0,1e-6)
+RCU_dth_freq=VarArray("RCU_dither_freq",3,[RCU_Dth1_freq,RCU_Dth2_freq,RCU_Dth3_freq],RW.ReadWrite,datatype.dfloat,3,None,None)
+
+HBA1_Delay=Var2dev("",RCUmod,DevType.HBA1,RCU_HBA1,5,2,1)
+HBA1_Pwr  =Var2dev("",RCUmod,DevType.HBA1,RCU_HBA1,1,1,1)
+HBA2_Delay=Var2dev("",RCUmod,DevType.HBA1,RCU_HBA2,5,2,1)
+HBA2_Pwr  =Var2dev("",RCUmod,DevType.HBA1,RCU_HBA2,1,1,1)
+HBA3_Delay=Var2dev("",RCUmod,DevType.HBA1,RCU_HBA3,5,2,1)
+HBA3_Pwr  =Var2dev("",RCUmod,DevType.HBA1,RCU_HBA3,1,1,1)
+HBA1_Delay=VarArray("HBA_element_beamformer_delays",3,[HBA1_Delay,HBA2_Delay,HBA3_Delay],RW.ReadWrite,datatype.dInt,96,None,None)
+HBA1_Pwr  =VarArray("HBA_element_pwr"  ,3,[HBA1_Pwr  ,HBA2_Pwr  ,HBA3_Pwr  ],RW.ReadWrite,datatype.dInt,96,None,None)
+
+#RCU_ID0=Var2dev("",RCUmod,DevType.I2C,RCU_ROM,8,0,1)
+#RCU_ID=VarArray("RCU_ID",1,[RCU_ID0],RW.ReadOnly,datatype.dInt,4,None,None)
+
+RCU_ID0=Var2dev("",RCUmod,DevType.I2C,RCU_ROM_ID,32,0,1)
+RCU_ID=VarArray("RCU_ID",1,[RCU_ID0],RW.ReadOnly,datatype.dInt,1,None,None)
+RCU_Ver0=Var2dev("",RCUmod,DevType.I2C,RCU_ROM_Ver,7,0,1)
+RCU_VER=VarArray("RCU_version",1,[RCU_Ver0],RW.ReadOnly,datatype.dstring,10,None,None)
+
+
+RCU_ADC1_lock=Var2dev("RCU_ADC1_lock",RCUmod,DevType.SPIbb,RCU_ADC1_PLL_stat,8,0,1)
+RCU_ADC2_lock=Var2dev("RCU_ADC2_lock",RCUmod,DevType.SPIbb,RCU_ADC2_PLL_stat,8,0,1)
+RCU_ADC3_lock=Var2dev("RCU_ADC3_lock",RCUmod,DevType.SPIbb,RCU_ADC3_PLL_stat,8,0,1)
+RCU_ADC_lock=VarArray("RCU_ADC_lock",3,[RCU_ADC1_lock,RCU_ADC2_lock,RCU_ADC3_lock],RW.ReadOnly,datatype.dInt,3,None,None)
+
+RCU_ADC1_SYNC=Var2dev("RCU_ADC1_SYNC",RCUmod,DevType.SPIbb,RCU_ADC1_SYNC_ctr,8,0,1)
+RCU_ADC2_SYNC=Var2dev("RCU_ADC2_SYNC",RCUmod,DevType.SPIbb,RCU_ADC2_SYNC_ctr,8,0,1)
+RCU_ADC3_SYNC=Var2dev("RCU_ADC3_SYNC",RCUmod,DevType.SPIbb,RCU_ADC3_SYNC_ctr,8,0,1)
+RCU_ADC_SYNC=VarArray("RCU_ADC_SYNC",3,[RCU_ADC1_SYNC,RCU_ADC2_SYNC,RCU_ADC3_SYNC],RW.ReadOnly,datatype.dInt,3,None,None)
+
+RCU_ADC1_JESD=Var2dev("RCU_ADC1_SYNC",RCUmod,DevType.SPIbb,RCU_ADC1_JESD_ctr,8,0,1)
+RCU_ADC2_JESD=Var2dev("RCU_ADC2_SYNC",RCUmod,DevType.SPIbb,RCU_ADC2_JESD_ctr,8,0,1)
+RCU_ADC3_JESD=Var2dev("RCU_ADC3_SYNC",RCUmod,DevType.SPIbb,RCU_ADC3_JESD_ctr,8,0,1)
+RCU_ADC_JESD=VarArray("RCU_ADC_JESD",3,[RCU_ADC1_JESD,RCU_ADC2_JESD,RCU_ADC3_JESD],RW.ReadOnly,datatype.dInt,3,None,None)
+
+RCU_ADC1_CML=Var2dev("RCU_ADC1_SYNC",RCUmod,DevType.SPIbb,RCU_ADC1_CML_level,8,0,1)
+RCU_ADC2_CML=Var2dev("RCU_ADC2_SYNC",RCUmod,DevType.SPIbb,RCU_ADC2_CML_level,8,0,1)
+RCU_ADC3_CML=Var2dev("RCU_ADC3_SYNC",RCUmod,DevType.SPIbb,RCU_ADC3_CML_level,8,0,1)
+RCU_ADC_CML=VarArray("RCU_ADC_CML",3,[RCU_ADC1_CML,RCU_ADC2_CML,RCU_ADC3_CML],RW.ReadOnly,datatype.dInt,3,None,None)
+
+
+RCU_IO1_1= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO1_OUT1,8,0,1)
+RCU_IO1_2= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO1_OUT2,8,0,1)
+#RCU_IO1_3= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO1_CONF1,8,0,1)
+#RCU_IO1_4= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO1_CONF2,8,0,1)
+#RCU_IO1=VarArray("RCU_IO1",3,[RCU_IO1_1,RCU_IO1_2,RCU_IO1_3],RW.ReadOnly,datatype.dInt,None,None)
+RCU_IO2_1= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO2_OUT1,8,0,1)
+RCU_IO2_2= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO2_OUT2,8,0,1)
+#RCU_IO2_3= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO2_CONF1,8,0,1)
+#RCU_IO2_4= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO2_CONF2,8,0,1)
+#RCU_IO2=VarArray("RCU_IO2",3,[RCU_IO2_1,RCU_IO2_2,RCU_IO2_3],RW.ReadOnly,datatype.dInt,None,None)
+RCU_IO3_1= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO3_OUT1,8,0,1)
+RCU_IO3_2= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO3_OUT2,8,0,1)
+#RCU_IO3_3= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO3_CONF1,8,0,1)
+#RCU_IO3_4= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO3_CONF2,8,0,1)
+#RCU_IO3=VarArray("RCU_IO3",3,[RCU_IO3_1,RCU_IO3_2,RCU_IO3_3],RW.ReadOnly,datatype.dInt,None,None)
+
+RCU_OUT1=VarArray("RCU_OUT1",3,[RCU_IO1_1,RCU_IO2_1,RCU_IO3_1],RW.ReadOnly,datatype.dInt,3,None,None)
+RCU_OUT2=VarArray("RCU_OUT2",3,[RCU_IO1_2,RCU_IO2_2,RCU_IO3_2],RW.ReadOnly,datatype.dInt,3,None,None)
+#RCU_CNF1=VarArray("RCU_CONF1",3,[RCU_IO1_3,RCU_IO2_3,RCU_IO3_3],RW.ReadOnly,datatype.dInt,None,None)
+#RCU_CNF2=VarArray("RCU_CONF2",3,[RCU_IO1_4,RCU_IO2_4,RCU_IO3_4],RW.ReadOnly,datatype.dInt,None,None)
+
+
+
+OPC_devvars=[RCU_mask,Ant_mask,RCU_att,RCU_band,RCU_temp,RCU_pwrd,RCU_LED,RCU_ADC_lock,RCU_ADC_SYNC,RCU_ADC_JESD,RCU_ADC_CML,RCU_OUT1,RCU_OUT2,RCU_ID,RCU_VER]#,HBA1_Delay,HBA1_Pwr]#,RCU_CNF1,RCU_CNF2]
+
+
+
+
+
+
+#Instr=namedtuple("DevInstr","type dev nvalue value")
+#Instrs=namedtuple("Instr","name ninstr instr")
+
+#OPCUA methods
+
+RCU_init=Instrs("ReadRegisters",2,[
+   Instr(DevType.VarUpdate,RCU_OUT1,3,[0,0,0]),
+   Instr(DevType.VarUpdate,RCU_OUT2,3,[0,0,0])
+])
+
+ADC_on=Instrs("ADC_on",16,[
+   Instr(DevType.SPIbb,RCU_ADC1_JESD_ctr,1,[0x14]),
+   Instr(DevType.SPIbb,RCU_ADC1_CML_level,1,[0x7]),
+   Instr(DevType.SPIbb,RCU_ADC1_SYNC_ctr,1,[1]),
+   Instr(DevType.SPIbb,RCU_ADC1_update,1,[1]),
+   Instr(DevType.SPIbb,RCU_ADC2_JESD_ctr,1,[0x14]),
+   Instr(DevType.SPIbb,RCU_ADC2_CML_level,1,[0x7]),
+   Instr(DevType.SPIbb,RCU_ADC2_SYNC_ctr,1,[1]),
+   Instr(DevType.SPIbb,RCU_ADC2_update,1,[1]),
+   Instr(DevType.SPIbb,RCU_ADC3_JESD_ctr,1,[0x14]),
+   Instr(DevType.SPIbb,RCU_ADC3_CML_level,1,[0x7]),
+   Instr(DevType.SPIbb,RCU_ADC3_SYNC_ctr,1,[1]),
+   Instr(DevType.SPIbb,RCU_ADC3_update,1,[1]),
+   Instr(DevType.VarUpdate,RCU_ADC_SYNC,3,[0,0,0]),
+   Instr(DevType.VarUpdate,RCU_ADC_JESD,3,[0,0,0]),
+   Instr(DevType.VarUpdate,RCU_ADC_CML,3,[0,0,0]),
+   Instr(DevType.VarUpdate,RCU_ADC_lock,3,[0,0,0])
+])
+
+RCU_on=Instrs("RCU_on",12,[
+   Instr(DevType.I2C,RCU_IO2_CONF1,1,[0]),
+   Instr(DevType.I2C,RCU_IO2_CONF2,1,[0]),
+   Instr(DevType.I2C,RCU_IO3_CONF1,1,[0]),
+   Instr(DevType.I2C,RCU_IO3_CONF2,1,[0]),
+   Instr(DevType.I2C,RCU_IO1_CONF1,1,[0]),
+   Instr(DevType.I2C,RCU_IO1_CONF2,1,[0]),
+   Instr(DevType.I2C,RCU_IO2_OUT1,1,[0x4A]),
+   Instr(DevType.I2C,RCU_IO2_OUT2,1,[0x55]),
+   Instr(DevType.I2C,RCU_IO3_OUT1,1,[0x15]),
+   Instr(DevType.I2C,RCU_IO3_OUT2,1,[0x47]),
+   Instr(DevType.I2C,RCU_IO1_OUT1,1,[0xCA]),
+   Instr(DevType.I2C,RCU_IO1_OUT2,1,[0xCA]),
+#   Instr(DevType.VarUpdate,RCU_att,3,[0,0,0]),
+   Instr(DevType.VarUpdate,RCU_pwrd,1,[0]),
+   Instr(DevType.VarUpdate,RCU_OUT1,3,[0,0,0]),
+   Instr(DevType.VarUpdate,RCU_OUT2,3,[0,0,0]),
+#   Instr(DevType.Instr,ADC1_on,0,[]),
+#   Instr(DevType.Instr,ADC2_on,0,[]),
+#   Instr(DevType.Instr,ADC3_on,0,[])
+#   Instr(DevType.VarUpdate,RCU_ADC_lock,3,[0,0,0])
+])
+
+RCU_off=Instrs("RCU_off",1,[
+#   Instr(DevType.Var,RCU_mask,4,[1,1,1,1]),
+   Instr(DevType.Var,RCU_pwrd,32,[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
+#   Instr(DevType.Var,RCU_mask,4,[0,0,0,0])
+])
+
+RCU_update=Instrs("RCU_update",11,[
+   Instr(DevType.VarUpdate,RCU_pwrd,1,[0]),
+   Instr(DevType.VarUpdate,RCU_OUT1,3,[0,0,0]),
+   Instr(DevType.VarUpdate,RCU_OUT2,3,[0,0,0]),
+   Instr(DevType.VarUpdate,RCU_ID,1,[0]),
+#   Instr(DevType.VarUpdate,RCU_VER,1,[0]*10),
+   Instr(DevType.VarUpdate,RCU_att,3,[0,0,0]),
+   Instr(DevType.VarUpdate,RCU_band,3,[0,0,0]),
+   Instr(DevType.VarUpdate,RCU_LED,3,[0,0,0]),
+   Instr(DevType.VarUpdate,RCU_ADC_SYNC,3,[0,0,0]),
+   Instr(DevType.VarUpdate,RCU_ADC_JESD,3,[0,0,0]),
+   Instr(DevType.VarUpdate,RCU_ADC_CML,3,[0,0,0]),
+   Instr(DevType.VarUpdate,RCU_ADC_lock,3,[0,0,0])
+])
+
+
+OPC_methods=[RCU_on,RCU_off,ADC_on,RCU_update]
diff --git a/rcu/__init__.py b/rcu/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/rcu/spibitbang1.py b/rcu/spibitbang1.py
new file mode 100644
index 0000000000000000000000000000000000000000..14541d75b70c1961a206a5c39533afccccec0d6e
--- /dev/null
+++ b/rcu/spibitbang1.py
@@ -0,0 +1,138 @@
+from enum import Enum
+import logging
+import numpy as np
+
+class SPIBB_pins(Enum):
+    CLK = 0  
+    SDIO = 1  
+    SDIOdir = 2 
+    CS = 3  
+
+def SetSPIbb(SetI2C,RCUi,dev,value):
+        ADC_address=dev.Register_W
+        CSdev=dev.Addr.devs[SPIBB_pins.CS.value]
+        CSpin=dev.Addr.pins[SPIBB_pins.CS.value]
+        SDOdev=dev.Addr.devs[SPIBB_pins.SDIO.value]
+        SDOpin=dev.Addr.pins[SPIBB_pins.SDIO.value]
+        CLKdev=dev.Addr.devs[SPIBB_pins.CLK.value]
+        CLKpin=dev.Addr.pins[SPIBB_pins.CLK.value]
+
+        logging.info(str(("SPIbb set",ADC_address,value)))
+
+        ADC_bytes = 0x00
+        ADC_rw    = 0x00 # 0 for write, 1 for read
+        data2 = ( ADC_rw << 23 ) + ( ADC_bytes << 21 ) + ( ADC_address << 8 ) + value[0]
+          
+        bit_array = "{0:{fill}24b}".format(data2, fill='0')
+      #    print(bit_array)
+        SetI2C(RCUi,CSdev,1,CSpin,[0]) #enable
+        for bit in bit_array:
+              SetI2C(RCUi,SDOdev,1,SDOpin,[int(bit)]) 
+              SetI2C(RCUi,CLKdev,1,CLKpin,[1]) 
+              SetI2C(RCUi,CLKdev,1,CLKpin,[0]) 
+        SetI2C(RCUi,CSdev,1,CSpin,[1]) #disable
+        SetI2C(RCUi,SDOdev,1,SDOpin,[1]) #high when finished
+        return True;
+
+def GetSPIbb(SetI2C,GetI2C,RCUi,dev,value):
+        ADC_reg_address=dev.Register_R
+        CSdev=dev.Addr.devs[Vars.SPIBB_pins.CS.value]
+        CSpin=dev.Addr.pins[Vars.SPIBB_pins.CS.value]
+        SDOdev=dev.Addr.devs[Vars.SPIBB_pins.SDIO.value]
+        SDOpin=dev.Addr.pins[Vars.SPIBB_pins.SDIO.value]
+        CLKdev=dev.Addr.devs[Vars.SPIBB_pins.CLK.value]
+        CLKpin=dev.Addr.pins[Vars.SPIBB_pins.CLK.value]
+        SDIOdirdev=dev.Addr.devs[Vars.SPIBB_pins.SDIOdir.value]
+        SDIOdirpin=dev.Addr.pins[Vars.SPIBB_pins.SDIOdir.value]
+
+        logging.info(str(("SPIbb get",ADC_reg_address)))
+          
+        ADC_bytes = 0x00
+        ADC_rw    = 0x01 # 0 for write, 1 for read
+        
+        data = ( ADC_rw << 15) + ( ADC_bytes << 13 ) + ADC_reg_address
+          
+        SetI2C(RCUi,CSdev,1,CSpin,[0]) #enable
+
+
+        bit_array = "{0:{fill}16b}".format(data, fill='0')
+        for bit in bit_array:
+              SetI2C(RCUi,SDOdev,1,SDOpin,[int(bit)]) 
+              SetI2C(RCUi,CLKdev,1,CLKpin,[1]) 
+              SetI2C(RCUi,CLKdev,1,CLKpin,[0]) 
+
+        SetI2C(RCUi,CSdev,1,CSpin,[1]) #disable
+
+          #    print("read byte")
+        SetI2C(RCUi,SDIOdirdev,1,SDIOdirpin,[1]) #input
+        SetI2C(RCUi,CSdev,1,CSpin,[0]) #enable
+        a=[0]
+        N=len(value)
+        for i in range(N): value[i]=0
+        for cnt in range(8*(ADC_bytes+1)):
+              ret_value=GetI2C(RCUi,SDOdev,1,SDOpin) #enable
+              for i in range(N): value[i]=(value[i]<<1)+ ret_value[i]
+              SetI2C(RCUi,CLKdev,1,CLKpin,[1]) 
+              SetI2C(RCUi,CLKdev,1,CLKpin,[0])  #read after falling edge
+        SetI2C(RCUi,CSdev,1,CSpin,[1]) #disable
+        SetI2C(RCUi,SDIOdirdev,1,SDIOdirpin,[0]) #output
+        return True;
+
+def GetSPIbb2(SetI2C,GetI2C,RCUi,devs,value):
+        ADC_reg_address=devs[0].Register_R
+        def Setbit(pintype,value):
+           for dev in devs:
+             dev1=dev.Addr.devs[pintype.value]
+             pin1=dev.Addr.pins[pintype.value]
+             SetI2C(RCUi,dev1,1,pin1,[value],buffer=True) 
+           SetI2C(RCUi,dev1,1,pin1,[value]) 
+        def Getbit(pintype):
+           retvalue=np.zeros_like(value)
+           step=len(devs)
+           dev1=devs[0].Addr.devs[pintype.value]
+           pin1=devs[0].Addr.pins[pintype.value]
+           retvalue[0::step]=GetI2C(RCUi,dev1,1,pin1)
+           for i,dev in enumerate(devs[1:]):
+             dev1=dev.Addr.devs[pintype.value]
+             pin1=dev.Addr.pins[pintype.value]
+             retvalue[i+1::step]=GetI2C(RCUi,dev1,1,pin1,buffer=True)
+           return retvalue
+           
+        CS=SPIBB_pins.CS
+        SDIO=SPIBB_pins.SDIO
+        CLK=SPIBB_pins.CLK
+        SDIOdir=SPIBB_pins.SDIOdir
+
+        logging.debug(str(("SPIbb get",ADC_reg_address)))
+          
+        ADC_bytes = 0x00
+        ADC_rw    = 0x01 # 0 for write, 1 for read
+        
+        data = ( ADC_rw << 15) + ( ADC_bytes << 13 ) + ADC_reg_address
+          
+        Setbit(CS,0) #enable
+
+        bit_array = "{0:{fill}16b}".format(data, fill='0')
+        logging.debug(str(("SPI TX",bit_array)))
+        for bit in bit_array:
+              Setbit(SDIO,int(bit)) 
+              Setbit(CLK,1) 
+              Setbit(CLK,0) 
+
+        Setbit(CS,1) #disable
+
+          #    print("read byte")
+        Setbit(SDIOdir,1) #input
+        Setbit(CS,0) #enable
+        a=[0]
+        N=len(value)
+        for i in range(N): value[i]=0
+        for cnt in range(8*(ADC_bytes+1)):
+              ret_value=Getbit(SDIO)
+              for i in range(N): value[i]=(value[i]<<1)+ ret_value[i]
+              Setbit(CLK,1) 
+              Setbit(CLK,0)  #read after falling edge
+        Setbit(CS,1) #disable
+        Setbit(SDIO,1)#High when finished 
+        Setbit(SDIOdir,0) #output
+        return True;
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index a0a74090325423b55cce129fd7d729190c3cedbb..818caf7311d7521391980a3a53c5a8b2397feef1 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
+pylibi2c (github.com/amaork/libi2c)
 opcua
-pyyaml
 numpy
+recordclass
diff --git a/test/test1.py b/test/test1.py
deleted file mode 100644
index ece510b6697587a741c470b62b45b4f744511f44..0000000000000000000000000000000000000000
--- a/test/test1.py
+++ /dev/null
@@ -1,29 +0,0 @@
-import pypcc;
-
-P1=pypcc.pypcc("pypcc.yaml")
-
-def AddMethod(name):
-    print("Method:",name)
-P1.GetMethodNames("",AddMethod);
-
-P1.CallMethod("RCU01_RCU_on",None)
-P1.CallMethod("RCU02_RCU_on",None)
-
-def AddVar(name,dtype=0):
-    print("Var:",name)
-P1.GetVarNames("",AddVar);
-
-
-a=[0]
-print(P1.GetVarValue("RCU01_Band1",a))
-assert(a[0]==1)
-print(P1.GetVarValue("RCU02_Band1",a))
-assert(a[0]==1)
-print(P1.SetVarValue("RCU01_Band1",3))
-print(P1.SetVarValue("RCU02_Band1",0))
-print(P1.GetVarValue("RCU01_Band1",a))
-assert(a[0]==3)
-print(P1.GetVarValue("RCU02_Band1",a))
-assert(a[0]==0)
-
-
diff --git a/test/test2.py b/test/test2.py
deleted file mode 100644
index b780d8ccd71c9334c46a6112a83ab0dc628a9d65..0000000000000000000000000000000000000000
--- a/test/test2.py
+++ /dev/null
@@ -1,116 +0,0 @@
-#import pypcc;
-import pypcc_test as pypcc;
-
-P1=pypcc.pypcc("LTS_pypcc.yaml")
-
-def Getvalue(name):
-  a=[0]
-  P1.GetVarValue("RCU01_"+name,a)
-  print("GET:",name,a[0])
-
-def Setvalue(name,value):
-  P1.SetVarValue("RCU01_"+name,[value])
-  print("SET:",name,value)
-
-
-def AddMethod(name):
-    print("Method:",name)
-P1.GetMethodNames("",AddMethod);
-
-def AddVar(name,dtype=0,RW=3):
-    Types={0:'int',1:'float'}
-    RWs={0:'hidden',1:'RO',2:'WO',3:'RW'}
-    print("Var:",name,Types[dtype],RWs[RW])
-P1.GetVarNames("",AddVar);
-exit()
-#P1.CallMethod("RCU01_RCU_on",None)
-#P1.CallMethod("RCU01_Dither_on",None)
-#P1.CallMethod("RCU02_RCU_on",None)
-exit()
-if False:
-  P1.CallMethod("RCU01_Init_ADCR",None)
-  Getvalue("ADC_lock1")
-
-if False:
- Setvalue("Band1",1)
- Setvalue("Band2",0)
- Setvalue("Band3",1)
- Getvalue("Band1")
- Getvalue("Band2")
- Getvalue("Band3")
-#exit()
-
-if False:
-#  Setvalue("Dth3_Pwr",0)
-#  Setvalue("Dth2_Pwr",0)
-#  Setvalue("Dth3_Pwr",1)
-#  Setvalue("Dth2_Pwr",1)
-  P1.CallMethod("RCU01_Dither1_Setup",None)
-  P1.CallMethod("RCU01_Dither2_Setup",None)
-  P1.CallMethod("RCU01_Dither3_Setup",None)
-
-#  a=[0,0,0,0]
-#  P1.GetVarValue("RCU01_Dth1_FREQ",a)
-#  print("GET:",a[0])
-#  Getvalue("Dither1_Frequency")
-  Setvalue("Dither1_Frequency",101.0)
-  Setvalue("Dither2_Frequency",101.2)
-  Getvalue("Dither1_Frequency")
-  Getvalue("Dither2_Frequency")
-#  Getvalue("Dth1_FREQ")
-
-if False:
-#  a=[0,0,0]
-#  P1.GetVarValue("RCU01_V_x",a)
-#  print("GET:",a[0])
-#  import time
-#  time.sleep(0.2)
-#  Setvalue("V_x",0xC0)
-#  time.sleep(0.2)
-#  a=[0,0,0]
-#  P1.GetVarValue("RCU01_Temp",a)
-#  print("GET:",a[0])
-  Getvalue("Temp")
-#exit()
-if False:
-  P1.CallMethod("RCU01_ADC1_Switch_on",None)
-  Getvalue("ADC1_locked")
-  Getvalue("ADC2_locked")
-  Getvalue("ADC3_locked")
-#Getvalue("ADC_lock3")
-#Getvalue("ADC_lock1")
-#Setvalue("LED0",1)
-#Getvalue("LED0")
-#Setvalue("Band2",1)
-#Getvalue("Band2")
-#Getvalue("LED0")
-exit()
-
-#Setvalue("Dth3_Pwr",1)
-Setvalue("Dth2_Pwr",0)
-Setvalue("Dth2_SDA",0)
-Setvalue("Dth2_SCL",0)
-Setvalue("Dth3_Pwr",0)
-Setvalue("Dth3_SDA",0)
-Setvalue("Dth3_SCL",0)
-
-Setvalue("LED0",2)
-
-Setvalue("Att1",10)
-Setvalue("Att2",10)
-Setvalue("Att3",10)
-
-
-#Setvalue("Dth3_Pwr",1)
-#Setvalue("Dth2_SCL",1)
-
-#assert(a[0]==1)
-#print(P1.SetVarValue("RCU01_Band1",3))
-#print(P1.SetVarValue("RCU02_Band1",0))
-#print(P1.GetVarValue("RCU01_Band1",a))
-#print(a[0])
-#assert(a[0]==3)
-#print(P1.GetVarValue("RCU02_Band1",a))
-#assert(a[0]==0)
-
-
diff --git a/test/test3.py b/test/test3.py
deleted file mode 100644
index d6bdca5b37e9d898a45f90c9581c68b0b9e56185..0000000000000000000000000000000000000000
--- a/test/test3.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import pypcc;
-
-P1=pypcc.pypcc("pypcc.yaml")
-
-def AddMethod(name):
-    print("Method:",name)
-P1.GetMethodNames("",AddMethod);
-
-P1.CallMethod("RCU01_RCU_on",None)
-P1.CallMethod("RCU02_RCU_on",None)
-#a=[0]
-#print(P1.GetVarValue("RCU01_ADC_lock",a))
-#print("ADC lock=",a[0])
-
-
-
-def AddVar(name,dtype=0):
-    print("Var:",name)
-P1.GetVarNames("",AddVar);
-
-#print(P1.SetVarValue("RCU01_LED0",0))
-
-exit()
-a=[0]
-print(P1.GetVarValue("RCU01_Band1",a))
-print(a[0])
-#assert(a[0]==1)
-print(P1.SetVarValue("RCU01_Band1",3))
-#print(P1.SetVarValue("RCU02_Band1",0))
-print(P1.GetVarValue("RCU01_Band1",a))
-print(a[0])
-#assert(a[0]==3)
-#print(P1.GetVarValue("RCU02_Band1",a))
-#assert(a[0]==0)
-
-
diff --git a/test/test_ADCs.py b/test/test_ADCs.py
deleted file mode 100644
index 3be2fa979f976cb867efa14f351deaaeae88914e..0000000000000000000000000000000000000000
--- a/test/test_ADCs.py
+++ /dev/null
@@ -1,47 +0,0 @@
-import pypcc;
-#import pypcc_test as pypcc;
-
-P1=pypcc.pypcc("LTS_pypcc.yaml")
-
-##Print all the visible methods
-def AddMethod(name):
-    print("Method:",name)
-P1.GetMethodNames("",AddMethod);
-
-##Print all the visible variables
-def AddVar(name,dtype=0,RW=3,cnt=1):
-    Types={0:'int',1:'float'}
-    RWs={0:'hidden',1:'RO',2:'WO',3:'RW'}
-    print("Var:",name,Types[dtype],RWs[RW],cnt)
-P1.GetVarNames("",AddVar);
-
-a=[0]
-##Setup ADC RCU1
-P1.CallMethod("RCU01_RCU_off",None)
-P1.CallMethod("RCU01_RCU_on",None)
-#P1.GetVarValue("RCU01_ADC1_locked",a);print(a[0]);
-P1.GetVarValue("RCU01_ADC1_SYNC",a);print(a[0]);
-P1.GetVarValue("RCU01_ADC1_CML",a);print(a[0]);
-P1.GetVarValue("RCU01_ADC1_JESD",a);print(a[0]);
-P1.GetVarValue("RCU01_ADC2_SYNC",a);print(a[0]);
-P1.GetVarValue("RCU01_ADC2_CML",a);print(a[0]);
-P1.GetVarValue("RCU01_ADC2_JESD",a);print(a[0]);
-P1.GetVarValue("RCU01_ADC3_SYNC",a);print(a[0]);
-P1.GetVarValue("RCU01_ADC3_CML",a);print(a[0]);
-P1.GetVarValue("RCU01_ADC3_JESD",a);print(a[0]);
-#P1.GetVarValue("RCU01_ADC1_JESD_control1",a);print(a[0]);
-#P1.GetVarValue("RCU01_ADC1_CML_level",a);print(a[0]);
-#P1.GetVarValue("RCU01_ADC1_locked",a);print(a[0]);
-#P1.GetVarValue("RCU01_ADC1_locked",a);print(a[0]);
-#        - ADC1.SYNC_control: [1]  #Setup ADCs
-#        - ADC1.JESD_control1: [14]  #Setup ADCs
-#        - ADC1.CML_level: [0x7]
-#        - ADC1.Update: [1]       #Needed to update ADC registers
-
-exit()
-##Setup ADC RCU3
-P1.CallMethod("RCU01_RCU_off",None)
-P1.CallMethod("RCU03_RCU_on",None)
-P1.GetVarValue("RCU03_ADC1_locked",a);print(a[0]);
-P1.GetVarValue("RCU03_ADC2_locked",a);print(a[0]);
-P1.GetVarValue("RCU03_ADC3_locked",a);print(a[0]);
diff --git a/test/test_clk.py b/test/test_clk.py
deleted file mode 100644
index da3e84bb7e72045d7ad03530f7438515958298eb..0000000000000000000000000000000000000000
--- a/test/test_clk.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#import pypcc;
-import pypcc_test as pypcc;
-
-P1=pypcc.pypcc("LTS_pypcc.yaml")
-
-def Getvalue(name):
-  a=[0]
-  P1.GetVarValue("CLK_"+name,a)
-  print("GET:",name,a[0])
-
-def Setvalue(name,value):
-  P1.SetVarValue("CLK_"+name,[value])
-  print("SET:",name,value)
-
-
-def AddMethod(name):
-    print("Method:",name)
-P1.GetMethodNames("",AddMethod);
-
-def AddVar(name,dtype=0,RW=3,cnt=1):
-    Types={0:'int',1:'float'}
-    RWs={0:'hidden',1:'RO',2:'WO',3:'RW'}
-    print("Var:",name,Types[dtype],RWs[RW],cnt)
-
-P1.GetVarNames("",AddVar);
-#exit()
-#P1.CallMethod("RCU01_RCU_on",None)
-#P1.CallMethod("RCU01_Dither_on",None)
-#P1.CallMethod("RCU02_RCU_on",None)
-if True:
-  Getvalue("CONF")
-  Getvalue("OUT")
-  Getvalue("IN")
-  P1.CallMethod("CLK_on1",None)
-  Getvalue("CONF")
-  Getvalue("OUT")
-  Getvalue("IN")
-  Getvalue("PLL_locked")
-#  P1.CallMethod("CLK_PLL_Setup",None)
-  Getvalue("PLL_locked")
-
diff --git a/test/test_dither.py b/test/test_dither.py
deleted file mode 100644
index 9a904f08c27e5ffd2efd8a2428d36f40b25752fa..0000000000000000000000000000000000000000
--- a/test/test_dither.py
+++ /dev/null
@@ -1,47 +0,0 @@
-import pypcc;
-
-P1=pypcc.pypcc("LTS_pypcc.yaml")
-
-def Getvalue(name):
-  a=[0]
-  P1.GetVarValue("RCU01_"+name,a)
-  print("GET:",name,a[0])
-
-def Setvalue(name,value):
-  P1.SetVarValue("RCU01_"+name,[value])
-  print("SET:",name,value)
-
-
-def AddMethod(name):
-    print("Method:",name)
-P1.GetMethodNames("",AddMethod);
-
-def AddVar(name,dtype=0,RW=3):
-    Types={0:'int',1:'float'}
-    RWs={0:'hidden',1:'RO',2:'WO',3:'RW'}
-    print("Var:",name,Types[dtype],RWs[RW])
-P1.GetVarNames("",AddVar);
-
-#P1.CallMethod("RCU01_RCU_on",None)
-#P1.CallMethod("RCU01_Dither_on",None)
-#P1.CallMethod("RCU02_RCU_on",None)
-
-if True:
-#  Setvalue("Dth3_Pwr",0)
-#  Setvalue("Dth2_Pwr",0)
-  Setvalue("Dth3_Pwr",1)
-  Setvalue("Dth2_Pwr",1)
-  P1.CallMethod("RCU01_Dither1_Setup",None)
-  P1.CallMethod("RCU01_Dither2_Setup",None)
-  P1.CallMethod("RCU01_Dither3_Setup",None)
-
-#  a=[0,0,0,0]
-#  P1.GetVarValue("RCU01_Dth1_FREQ",a)
-#  print("GET:",a[0])
-#  Getvalue("Dither1_Frequency")
-  Setvalue("Dither1_Frequency",101.0)
-  Setvalue("Dither2_Frequency",101.2)
-  Getvalue("Dither1_Frequency")
-  Getvalue("Dither2_Frequency")
-#  Getvalue("Dth1_FREQ")
-
diff --git a/test_array.py b/test_array.py
deleted file mode 100644
index b2f785208a089edd788b20e169afa8bda6e3997d..0000000000000000000000000000000000000000
--- a/test_array.py
+++ /dev/null
@@ -1,127 +0,0 @@
-import pypcc;
-#import pypcc_test as pypcc;
-
-P1=pypcc.pypcc("LTS_pypcc.yaml")
-
-def Getvalue(name):
-  a=[0]
-  P1.GetVarValue("RCU01_"+name,a)
-  print("GET:",name,a[0])
-
-def Setvalue(name,value):
-  P1.SetVarValue("RCU01_"+name,[value])
-  print("SET:",name,value)
-
-
-def AddMethod(name):
-    print("Method:",name)
-P1.GetMethodNames("",AddMethod);
-
-def AddVar(name,dtype=0,RW=3,cnt=1):
-    Types={0:'int',1:'float'}
-    RWs={0:'hidden',1:'RO',2:'WO',3:'RW'}
-    print("Var:",name,Types[dtype],RWs[RW],cnt)
-P1.GetVarNames("",AddVar);
-#P1.CallMethod("RCUx_RCU_on",None)
-a=[1.,2.,3.]
-#assert(P1.SetVarValue("RCUx_LED0",[0,0,0]))
-#assert(P1.SetVarValue("RCUx_LED0",[0,0,1]))
-P1.GetVarValue("RCUx_Temperature",a)
-print(a)
-
-#a=[1,2,3]
-#assert(P1.SetVarValue("RCUx_LED0",[0,0,0]))
-#assert(P1.SetVarValue("RCUx_LED0",[0,0,1]))
-#P1.GetVarValue("RCUx_LED0",a)
-#print(a)
-exit()
-#P1.CallMethod("RCU01_Dither_on",None)
-#P1.CallMethod("RCU02_RCU_on",None)
-exit()
-if False:
-  P1.CallMethod("RCU01_Init_ADCR",None)
-  Getvalue("ADC_lock1")
-
-if False:
- Setvalue("Band1",1)
- Setvalue("Band2",0)
- Setvalue("Band3",1)
- Getvalue("Band1")
- Getvalue("Band2")
- Getvalue("Band3")
-#exit()
-
-if False:
-#  Setvalue("Dth3_Pwr",0)
-#  Setvalue("Dth2_Pwr",0)
-#  Setvalue("Dth3_Pwr",1)
-#  Setvalue("Dth2_Pwr",1)
-  P1.CallMethod("RCU01_Dither1_Setup",None)
-  P1.CallMethod("RCU01_Dither2_Setup",None)
-  P1.CallMethod("RCU01_Dither3_Setup",None)
-
-#  a=[0,0,0,0]
-#  P1.GetVarValue("RCU01_Dth1_FREQ",a)
-#  print("GET:",a[0])
-#  Getvalue("Dither1_Frequency")
-  Setvalue("Dither1_Frequency",101.0)
-  Setvalue("Dither2_Frequency",101.2)
-  Getvalue("Dither1_Frequency")
-  Getvalue("Dither2_Frequency")
-#  Getvalue("Dth1_FREQ")
-
-if False:
-#  a=[0,0,0]
-#  P1.GetVarValue("RCU01_V_x",a)
-#  print("GET:",a[0])
-#  import time
-#  time.sleep(0.2)
-#  Setvalue("V_x",0xC0)
-#  time.sleep(0.2)
-#  a=[0,0,0]
-#  P1.GetVarValue("RCU01_Temp",a)
-#  print("GET:",a[0])
-  Getvalue("Temp")
-#exit()
-if False:
-  P1.CallMethod("RCU01_ADC1_Switch_on",None)
-  Getvalue("ADC1_locked")
-  Getvalue("ADC2_locked")
-  Getvalue("ADC3_locked")
-#Getvalue("ADC_lock3")
-#Getvalue("ADC_lock1")
-#Setvalue("LED0",1)
-#Getvalue("LED0")
-#Setvalue("Band2",1)
-#Getvalue("Band2")
-#Getvalue("LED0")
-exit()
-
-#Setvalue("Dth3_Pwr",1)
-Setvalue("Dth2_Pwr",0)
-Setvalue("Dth2_SDA",0)
-Setvalue("Dth2_SCL",0)
-Setvalue("Dth3_Pwr",0)
-Setvalue("Dth3_SDA",0)
-Setvalue("Dth3_SCL",0)
-
-Setvalue("LED0",2)
-
-Setvalue("Att1",10)
-Setvalue("Att2",10)
-Setvalue("Att3",10)
-
-
-#Setvalue("Dth3_Pwr",1)
-#Setvalue("Dth2_SCL",1)
-
-#assert(a[0]==1)
-#print(P1.SetVarValue("RCU01_Band1",3))
-#print(P1.SetVarValue("RCU02_Band1",0))
-#print(P1.GetVarValue("RCU01_Band1",a))
-#print(a[0])
-#assert(a[0]==3)
-#print(P1.GetVarValue("RCU02_Band1",a))
-#assert(a[0]==0)
-
-