diff --git a/config/CLK.yaml b/config/CLK.yaml
index 5d702976b2f9f88e96d7ec6fe29a2cdc1cffeaa1..00eaa2824e8bc4011d631f7e3a171e629355a7d6 100644
--- a/config/CLK.yaml
+++ b/config/CLK.yaml
@@ -6,9 +6,9 @@ drivers:
    type: i2c
    parameters: [1] #I2C port number
  - name: I2C_CLK
-   type: i2c_devs #I2C devices
+   type: i2c_array #I2C devices
    parent: I2C
-   parameters:  [32] #number of RCUs
+   parameters:  [0,0] #number of RCUs
  - name: SPIbb1 
    type: spibitbang2 #SPI bitbang via GPIO expander: CLK, SDI,SDO,CS
    parent: I2C_CLK
diff --git a/config/RCU.yaml b/config/RCU.yaml
index c63bd7074ef20db17a1eee1544912290079b78ca..aac519d77a8d804ab74e462509ce18479d2d8c43 100644
--- a/config/RCU.yaml
+++ b/config/RCU.yaml
@@ -2,18 +2,14 @@ version: "1.0"
 description: "1234"
 
 drivers:
- - name: I2C1
-   type: RCU_switch
-   devreg: [SWITCH.MASK]
+ - name: I2C1 #TCA9548
+   type: i2c_switch
+   devreg: [0x70]
    parameters: [1] #I2C port number
  - name: I2C_RCU 
    type: i2c_array #An array of similar devices connected to an I2C switch
    parent: I2C1
    parameters: [1,32] #start,number of RCUs
- - name: I2C_RFCHAIN
-   type: i2c_array2 #Array of similar devices with different address on same I2C line e.g. 3 rf chains on 1 RCU
-   parameters: [3] #number of RCUs
-   parent: I2C_RCU
  - name: I2C_HBAT 
    type: hba1 #Special driver to manage HBAT1s.
    parent: I2C_RCU
@@ -74,15 +70,6 @@ device_registers:
      address: [1,3]
      store: True
 
- - name: SWITCH
-   description: RCU selection switch
-   address: 0x70
-   device: TCA9548
-   driver: I2C1
-   registers:
-   - name: MASK
-     description: I2C select mask
-
  - name: ROM
    description: IO-Expander for filter selection
    address: 0x50
@@ -187,7 +174,7 @@ device_registers:
 variables:
    - name: Ant_mask
      description: Only masked RF chains are updated
-     driver: I2C_RFCHAIN
+     driver: I2C_RCU
      rw:  variable #server RW variable, not linked to IO
      dtype: boolean
      dim: 96
@@ -208,7 +195,7 @@ variables:
 
    - name: RCU_attenuator
      description: Attenuator before ADC
-     driver: I2C_RFCHAIN
+     driver: I2C_RCU
      devreg:  [IO1.GPIO1,IO1.GPIO2,IO2.GPIO1]
      bitoffset: [0,0,0]
      width: 5
@@ -219,7 +206,7 @@ variables:
 
    - name: RCU_band
      description: Band select switch 1=10MHz,2=30MHz
-     driver: I2C_RFCHAIN
+     driver: I2C_RCU
      devreg:  [IO2.GPIO2,IO2.GPIO2,IO2.GPIO2]
      bitoffset: [0,2,4]
      width: 2
@@ -229,7 +216,7 @@ variables:
      mask: Ant_mask
 
    - name: RCU_GPIO1
-     driver: I2C_RFCHAIN
+     driver: I2C_RCU
      devreg:  [IO1.GPIO1,IO2.GPIO1,IO3.GPIO1]
      width: 8
      rw:  ro
@@ -239,7 +226,7 @@ variables:
      debug: True
 
    - name: RCU_GPIO2
-     driver: I2C_RFCHAIN
+     driver: I2C_RCU
      devreg:  [IO1.GPIO2,IO2.GPIO2,IO3.GPIO2]
      width: 8
      rw:  ro
@@ -324,7 +311,7 @@ variables:
      
    - name: RCU_ADC_lock
      description: 0x81=locked
-     driver: I2C_RFCHAIN
+     driver: I2C_RCU
      devreg:  [ADC1.PLL_stat,ADC2.PLL_stat,ADC3.PLL_stat]
      width: 8
      rw:  ro
@@ -333,7 +320,7 @@ variables:
      mask: Ant_mask
 
    - name: RCU_dth1_freq
-     driver: I2C_RFCHAIN
+     driver: I2C_RCU
      devreg:  [DTH1.Freq,DTH2.Freq,DTH3.Freq]
      width: 32
      rw:  rw
@@ -349,6 +336,7 @@ methods:
      - RCU_ADC_lock: Update
 
   - name: RCU_on
+    driver: I2C_RCU
     mask: RCU_mask
     instructions:
      - IO2.CONF1: 0    #Set device register, can also specify a register adress direction e.g. OIO2.0: 0
@@ -370,7 +358,9 @@ methods:
      - ADC2_on: 0
      - WAIT: 500         #ms to wait
      - RCU_ADC_lock: Update
+
   - name: ADC1_on
+    driver: I2C_RCU
     debug: True
 #    rw: hidden
     instructions:
@@ -379,6 +369,7 @@ methods:
 #     - ADC1.CML_level: 0x7
      - ADC1.Update: 1       #Needed to update ADC registers
   - name: ADC2_on
+    driver: I2C_RCU
     debug: True
 #    rw: hidden
     instructions:
diff --git a/i2cserv/CLK.py b/i2cserv/CLK.py
deleted file mode 100644
index a775b70b969ee2b37b7bd070c07139be2021b3a3..0000000000000000000000000000000000000000
--- a/i2cserv/CLK.py
+++ /dev/null
@@ -1,414 +0,0 @@
-#from . import Vars
-import numpy as np
-import logging
-from .spibitbang2 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')
-        self.previousHBA=np.zeros([number,3,32],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 (self.N==1): Mask=[True]
-        if Instr.type==Vars.DevType.Instr:
-              #Execute instructions
-              Iset=Instr.dev;
-              if len(Mask)==0:  Mask=Vars.RCU_mask.OPCW.get_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_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.set_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)
-        if (self.N>1):
-           Mask=(Vars.RCU_mask if Step==1 else Vars.Ant_mask)
-           Mask=Mask.OPCW.get_value()
-        value1=strs2bytes(Instr.value) if V1.OPCR is None else strs2bytes(V1.OPCR.get_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.set_value(bytes2strs(value1,Step2,V1.type))
-
-        elif Instr.type==Vars.DevType.VarUpdate:
-          if self.N==1:
-             for Vari in range(Step):
-                i0=(Vari)*Step2
-                i1=(Vari+1)*Step2
-                value2=value1[i0:i1]
-                self.GetVarValue(0,V1.Vars[Vari],value2)
-                value1[i0:i1]=value2
-             if not(V1.OPCR is None): V1.OPCR.set_value(bytes2strs(value1,Step2,V1.type))
-          else:
-             self.GetVarValueAll(V1,value1)
-#            if not(V1.OPCR is None): V1.OPCR.get_data_value().Value.Value=bytes2strs(value1,Step2,V1.type)
-             if not(V1.OPCR is None): V1.OPCR.set_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.HBA1:
-                self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi])
-                self.GetI2CHBA1(RCUi,var.devreg,var.width,var.bitoffset,value)
-            elif var.type==Vars.DevType.I2Cbb:
-                logging.error("I2Cbb Implemented")
-            elif var.type==Vars.DevType.SPIbb:
-                self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi])
-                GetSPIbb(self.SetI2C,self.GetI2C,RCUi,var.devreg,value)
-            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")
-            elif V1.Vars[0].type==Vars.DevType.HBA1:
-              for Vari in range(Step):  
-                var=V1.Vars[Vari]
-                for RCUi in range(self.N):
-                    self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi])
-#                    print(Step,Step2,len(value1),V1.size)
-                    i0=(RCUi*Step+    Vari)*Step2
-                    i1=(RCUi*Step+(Vari+1))*Step2
-                    value2=value1[i0:i1]
-                    self.GetI2CHBA1(RCUi,var.devreg,var.width,var.bitoffset,value2)
-                    value1[i0:i1]=value2
-#                    i0=(RCUi*Step+    Vari)*Step2+16
-#                    i1=(RCUi*Step+(Vari+1))*Step2
-#                    value2=value1[i0:i1]
-#                    self.GetI2Cnoreg(RCUi,var.devreg,var.width,var.bitoffset,value2)
-#                    value1[i0:i1]=value2
-            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.HBA1:
-                self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi])
-                self.SetHBA1I2C(RCUi,var.devreg,var.width,var.bitoffset,value)
-#                 print("RCU1 Set",RCUi,var,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 SetHBA1I2C(self,RCUi,dev,width,bitoffset,value,buffer=False):
-#        if dev.store>0:
-        previous=self.previousHBA[RCUi,dev.store-1];
-        L=len(value)
-        for i in range(L):
-          value[i]=ApplyMask(value[i],width,bitoffset,previous[i]);
-        self.previousHBA[RCUi,dev.store-1]=value
-#        if buffer: return True;
-        self.I2Ccallback(dev.Addr,value[:16],reg=dev.Register_W)
-        if L>16: self.I2Ccallback(dev.Addr,value[16:],reg=dev.Register_W+16)
-        self.I2Ccallback(dev.Addr,[500],reg=dev.Register_W,read=3) #Wait 500ms
-        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 GetI2CHBA1(self,RCUi,dev,width,bitoffset,value):
-        #print(width,len(value))
-        value2=value
-        reg=dev.Register_R
-        if not(self.I2Ccallback(dev.Addr,value2,read=1)): return False;
-        if value2[0] is None:  return False
-        value[:]=value2[:];
-        if dev.store>0:
-            self.previousHBA[RCUi,dev.store-1]=value
-        for i in range(len(value)): 
-              value[i]=UnMask(value[i],width,bitoffset)      
-        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,NRCU):
-#          Inst1=Vars.Instr(Vars.DevType.VarUpdate,Vars.RCU_temp,NRCU,[0]*NRCU)
-#          Q1.put(Inst1)
-#         Inst1=Vars.Instr(Vars.DevType.VarUpdate,Vars.RCU_ADC_lock,96,[0]*96)
-#         Q1.put(Inst1)
-          return 
-    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.dbool:   varvalue2=dim2*[False]
-        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/i2cserv/I2C.py b/i2cserv/I2C.py
deleted file mode 100644
index d3a60c9655f3b77cb094800511f99f5b6b41dd3b..0000000000000000000000000000000000000000
--- a/i2cserv/I2C.py
+++ /dev/null
@@ -1,100 +0,0 @@
-if os.sys.platform is 'linux':
-    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):
-#  print("I2C",addr,reg,data,read)
-  try:
-       if read==3:
-           time.sleep(data[0]/1000.)
-           return True
-       logging.debug(str(("I2C",addr,reg,data,read)))
-
-#       return True;
-       bus=pylibi2c.I2CDevice('/dev/i2c-1',addr)
-       if read==1:
-         length=len(data)
-         bus.iaddr_bytes=0
-         if not(reg is None):
-             bus.ioctl_write(0,str(bytearray([reg])))
-         data[:]=[int(x) for x in bus.ioctl_read(0,length)]
-#         print("I2C read",addr,reg,data,read)
-       else:
-            if reg is None: 
-               bus.iaddr_bytes=0
-               reg=0;
-            bus.ioctl_write(reg,str(bytearray(data)))
-       bus.close()
-       return True;
-  except:
-       if bus: bus.close()
-#       data[0]=0xff
-       return False;
-
-def I2C4server(addr,data,reg=None,read=0):
-#  print("I2C4",addr,reg,data,read)
-  try:
-       if read==3:
-           time.sleep(data[0]/1000.)
-           return True
-       logging.debug(str(("I2C",addr,reg,data,read)))
-
-#       print("I2C",addr,reg,data,read)
-#       return True;
-       bus=pylibi2c.I2CDevice('/dev/i2c-4',addr)
-       if read==1:
-         length=len(data)
-         bus.iaddr_bytes=0
-         if not(reg is None):
-             bus.ioctl_write(0,str(bytearray([reg])))
-         data[:]=[int(x) for x in bus.ioctl_read(0,length)]
-#         print(data)
-       else:
-            if reg is None:
-               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;
-
-
-def I2C2server(addr,data,reg=None,read=0):
-  try:
-       if read==3:
-           time.sleep(data[0]/1000.)
-           return True
-       logging.debug(str(("I2C2",addr,reg,data,read)))
-
-#       print("I2C",addr,reg,data,read)
-#       return True;
-       bus=pylibi2c.I2CDevice('/dev/i2c-2',addr)
-       if read==1:
-         length=len(data)
-         bus.iaddr_bytes=0
-         if not(reg is None):
-             bus.ioctl_write(0,str(bytearray([reg])))
-         data[:]=[int(x) for x in bus.ioctl_read(0,length)]
-       else:
-            if reg is None: 
-               bus.iaddr_bytes=0
-               reg=0;
-            bus.ioctl_write(reg,str(bytearray(data)))
-       bus.close()
-       return True;
-  except:
-       if bus: bus.close()
-       print("I2C4 error")
-#       data[0]=0xff
-       return False;
-
diff --git a/i2cserv/I2C_dummy.py b/i2cserv/I2C_dummy.py
deleted file mode 100644
index a085ae1eed655c14d45a6ca19687d78c16060659..0000000000000000000000000000000000000000
--- a/i2cserv/I2C_dummy.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#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.warn(str(("I2C",addr,reg,data,read)))
-       return True
-
-def I2C4server(addr,data,reg=None,read=0):
-       global I2Ccounter;
-       logging.debug(str(("I2C4",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/i2cserv/I2Cswitch1.py b/i2cserv/I2Cswitch1.py
deleted file mode 100644
index 187456b1d6cc9eb2d15330d216ff89e72fe42a18..0000000000000000000000000000000000000000
--- a/i2cserv/I2Cswitch1.py
+++ /dev/null
@@ -1,27 +0,0 @@
-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)    
-        
-class I2Cswitch0():
-    def __init__(self,callback1):
-       return
-   
-    def SetChannel(self,channel):
-        return True
-
-    def I2Ccallback(self,RCU,addr,data,reg=None,read=0):
-        return
\ No newline at end of file
diff --git a/i2cserv/RCU.py b/i2cserv/RCU.py
deleted file mode 100644
index b0678b8ccb7213ca7babe3c34f7eba40ea3941dd..0000000000000000000000000000000000000000
--- a/i2cserv/RCU.py
+++ /dev/null
@@ -1,535 +0,0 @@
-#from . import Vars
-import numpy as np
-import logging
-from .spibitbang1 import *
-#import threading
-import time
-#from multiprocessing import Process
-from pcctypes import *
-from queuetypes import *
-
-RCU_Switch=[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]
-
-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)]
-def GetField(D,name,dev_number,default=None):
-    X=D.get(name,default)
-    return X[dev_number] if isinstance(X,list) else X;
-def Find(L,name,value):
-  for x in L:
-    if x[name]==value:
-        return x;
-  return False;
-
-class AttrDict(dict):
-  def __init__(self,*args,**kwargs):
-    super(AttrDict,self).__init__(*args,**kwargs)
-    self.__dict__=self
-
-def DevRegList(D):
-  for i,dev in enumerate(D.drivers):
-    dev['drv_id']=i;
-  devreglist={}
-  store=0;
-  for dev in D.device_registers:
-    N=dev.get('dim',1)
-    name=dev['name']    
-    for n in range(N):
-      addr=GetField(dev,'address',n,0)
-      devtype=GetField(dev,'driver',n)
-      print(addr,devtype)
-      devid=0;
-      if devtype:
-        devid=Find(D.drivers,'name',devtype)['drv_id']
-        devtype=Find(D.drivers,'name',devtype)['type']
-      else: devtype=0;
-      if N>1: name2=name+str(n+1)
-      else:   name2=name;
-      for reg in dev['registers']:
-         regR=GetField(reg,'address',0,0)
-         regW=GetField(reg,'address',1,0)
-         if reg.get('store',False):
-            store+=1;
-            storex=store
-         else:
-            storex=0
-#         hf.write("const devreg %s {%i,%i,%i,%i,%i};\n" % (name2+'_'+reg['name'],addr,regR,regW,storex,devtype) )
-         devregname=name2+'.'+reg['name'];
-         devreglist[devregname]=AttrDict({"Addr":addr,"Register_R":regR,"Register_W":regW,"store":storex,"devtype":devtype,"devid":devid});
-         print(devregname,devreglist[devregname]);
-#         hf.write("inline const t_devreg %s {.address=%i,.register_R=%i,.register_W=%i,.store=%i,.driver=%i};\n" % (devregname,addr,regR,regW,storex,devtype) )
-#hf.write("#define NumberStoreReg %i"%store)
-#  print(devreglist)
-  return devreglist,store
-
-def GetSteps(V1):
-              if isinstance(V1['devreg'],list): Step=len(V1['devreg']) 
-              else: Step=1; #V1.nVars
-              Step2=V1['dim']*((V1.get('width',8)+7)//8)//Step #int(V1.size/V1.nVars)
-              print(Step,Step2,V1);
-              return Step,Step2
-
-
-class RCU1():
-    def __init__(self,number,I2Ccallback,Switchcallback,config,Qin,Qout):
-        self.Qout=Qout;
-        self.Qin=Qin;
-        self.conf=config
-        self.devregs,RCU_storeReg=DevRegList(config)
-        self.N=number;
-        self.I2Ccallback=I2Ccallback
-        self.SWcallback=Switchcallback
-        self.previous   =np.zeros([number,RCU_storeReg],dtype='int')
-        self.previousHBA=np.zeros([number,3,32],dtype='int')
-
-    def load(self):
-        print("TODO: load")
-        #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 OPCUASetVariable(self,varid,var1,data,mask):
-       if var1['rw']=='variable': return;
-       print("Set Var",var1)
-       data=self.SetGetVarValueMask(var1,data,mask);
-       Data=OPCUAset(varid,InstType.varSet,data,mask)
-       self.Qout.put(Data);
-
-    def OPCUAReadVariable(self,varid,var1,data,mask):
-      print("Read Var",var1,data,mask)
-      if len(mask)==0:  data=self.GetVarValueAll(var1)
-      else:             data=self.GetVarValueMask(var1,mask);
-      Data=OPCUAset(varid,InstType.varSet,data,mask)
-      self.Qout.put(Data);
-
-    def OPCUAcallMethod(self,var1,data,mask):
-       print("Call Method",var1)
-
-    def SetGetVarValueMask(self,var1,data,mask):
-        Step,Step2=GetSteps(var1);
-        value1=[0]*Step*Step2;
-        if not(len(data)==Step*Step2):
-            print("Check data length!");
-            return;
-        Step2//=self.N
-        if not(len(mask)==Step*self.N):
-            print("Check mask length!");
-            return;
-#        if (len(value1)==V1.nVars) and (self.N>1):  value1=(value1*self.N);
-        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
-                devreg=self.GetDevReg(var1['devreg'],Vari);
-                width=var1.get('width',8)
-                bitoffset=GetField(var1,'bitoffset',Vari,0)
-                self.SetVarValue(RCUi,devreg,width,bitoffset,data[i0:i1])
-                value2=value1[i0:i1]
-                self.GetVarValue(RCUi,devreg,width,bitoffset,value2)
-                value1[i0:i1]=value2
-        return value1
-
-    def SetVarValue(self,RCUi,devreg,width,bitoffset,value):
-            if devreg.Register_W==-1: return True; #We can not set it, only read it e.g. temperature
-            logging.debug(str(("RCU1 Set ",RCUi,devreg,value)))
-            if devreg.devid==0:
-                self.SWcallback(1<<RCU_Switch[RCUi])
-                self.SetI2C(RCUi,devreg,width,bitoffset,value)
-            elif devreg.devtype[:3]=='hba':
-                self.SWcallback(1<<RCU_Switch[RCUi])
-                self.SetHBA1I2C(RCUi,devreg,width,bitoffset,value)
-#                 print("RCU1 Set",RCUi,var,value)
-            elif devreg.devtype[:4]=='i2cb':
-                logging.error("I2Cbb Implemented")
-            elif devreg.devtype[:3]=='spi':
-                logging.error("SPIbb Implemented")
-            else:
-                logging.error("Not Implemented")
-
-    def GetVarValue(self,RCUi,devreg,width,bitoffset,value):
-            logging.info(str(("RCU1 Get ",RCUi,devreg,value)))
-            if devreg.devid==0:
-                self.SWcallback(1<<RCU_Switch[RCUi])
-                self.GetI2C(RCUi,devreg,width,bitoffset,value)
-            elif devreg.devtype[:3]=='hba':
-                self.SWcallback(1<<RCU_Switch[RCUi])
-                self.GetI2CHBA1(RCUi,devreg,width,bitoffset,value)
-            elif devreg.devtype[:4]=='i2cb':
-                logging.error("I2Cbb Implemented")
-            elif devreg.devtype[:3]=='spi':
-                logging.error("SPIbb Implemented")
-            else:
-                logging.error("Not Implemented")
-
-
-    def SetVar(self,Instr,Mask=[]):
-#        Instr.value=strs2bytes(Instr.value) #Alwast be an array of bytes
-        if Instr.type==Vars.DevType.Wait:
-#            time.sleep(Instr.value[0]/1000.)
-            print("Sleep",Instr.value[0]/1000.,"s")
-            return;
-        if Instr.type==Vars.DevType.Instr:
-              #Execute instructions
-              Iset=Instr.dev;
-              #if len(Mask)==0:  Mask=Vars.RCU_mask.OPCW.get_value()
-              print("TODO: Lenmask=0");
-              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_value()
-            print("TODO: Lenmask=0");
-            mask=0;
-            RCU0=-1;
-            for RCUi in range(self.N):
-                 if (Mask[RCUi]):
-                      mask|=1<<RCU_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
-#        print(Instr.nvalue,V1.nVars,V1.size)
-        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.set_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_value()
-        print("TODO: check mask");
-        value1=strs2bytes(Instr.value) if V1.OPCR is None else strs2bytes(V1.OPCR.get_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.set_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)
-          if not(V1.OPCR is None): V1.OPCR.set_value(bytes2strs(value1,Step2,V1.type))
-#          V1.OPCR.get_data_value().Value.Value=value1
-
-        logging.info(str(('** Readback:',V1.name,value1)))
-
-
-    def GetDevReg(self,devreg1,n):
-                if isinstance(devreg1,list): devreg1=devreg1[n];
-                devreg=self.devregs[devreg1];
-#                print(devreg);
-                return(devreg);
-#                devreg=Find(self.conf.device_registers,'name',devreg)
-#                if devreg: return devreg;
-#                devreg=Find(self.conf.device_registers,'name',devreg[-1])
-
-
-    def GetVarValueAll(self,V1):
-            mask=0;
-            for RCUi in range(self.N):
-                mask|=1<<RCU_Switch[RCUi]
-            Step,Step2=GetSteps(V1);
-            value1=[0]*Step*Step2;
-            Step2//=self.N
-            devreg1=self.GetDevReg(V1['devreg'],0);
-#            return
-            if devreg1.devid==0:  #I2C
-              for Vari in range(Step):
-                DevReg=self.GetDevReg(V1['devreg'],Vari);
-                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<<RCU_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,DevReg,V1.get('width',8),GetField(V1,'bitoffset',Vari,0),value2)
-                    #print(value2)
-                    value1[i0:i1]=value2
-            elif devreg1.devtype[:3]=='spi':
-              self.GetBBValueAll(V1,value1,mask)
-#              logging.info("SPIbb all not implemented yet")
-            elif devreg1.devtype=='hba1':
-              logging.info("HBA1 all not implemented yet")
-              return
-              for Vari in range(Step):
-                var=V1.Vars[Vari]
-#                self.SWcallback(mask)
-#                self.SetI2CAddr(self,DevReg)
-                for RCUi in range(self.N):
-                    self.SWcallback(1<<RCU_Switch[RCUi])
-#                    print(Step,Step2,len(value1),V1.size)
-                    WX=[0]
-                    self.I2Ccallback(0x40,WX,reg=0,read=1)#wakeup, do nothing
-                    self.I2Ccallback(0x40,[10],read=3)
-                    i0=(RCUi*Step+    Vari)*Step2
-                    i1=(RCUi*Step+(Vari+1))*Step2
-                    value2=value1[i0:i1]
-                    self.GetI2CHBA1(RCUi,var.devreg,var.width,var.bitoffset,value2)
-                    value1[i0:i1]=value2
-#                    i0=(RCUi*Step+    Vari)*Step2+16
-#                    i1=(RCUi*Step+(Vari+1))*Step2
-#                    value2=value1[i0:i1]
-#                    self.GetI2Cnoreg(RCUi,var.devreg,var.width,var.bitoffset,value2)
-#                    value1[i0:i1]=value2
-            else:
-               logging.error("Type not implemented")
-#            print(value1)
-            return 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<<RCU_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;
-        Step,Step2=GetSteps(V1);
-        SPIdevs=[self.GetDevReg(V1['devreg'],Vari) for Vari in range(Step)]
-        I2Cdevs=[self.conf.drivers[d['devid']]['devreg'] for d in SPIdevs]
-        I2Cpins=[self.conf.drivers[d['devid']]['parameters'] for d in SPIdevs]
-        I2Cdevs=[[self.devregs[dr1] for dr1 in dr2] for dr2 in I2Cdevs]
-#        I2Cpins=np.array(I2Cpins).T
-        #for parallel acces, we assume devs and devs2 are the same, only pins are different
-        GetSPIbb2(SetBit,GetBit,0,SPIdevs,I2Cdevs,I2Cpins,value1)
-
-    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 SetHBA1I2C(self,RCUi,dev,width,bitoffset,value,buffer=False):
-#        if dev.store>0:
-        previous=self.previousHBA[RCUi,dev.store-1];
-        L=len(value)
-        for i in range(L):
-          value[i]=ApplyMask(value[i],width,bitoffset,previous[i]);
-        self.previousHBA[RCUi,dev.store-1]=value
-#        if buffer: return True;
-        print("HBA set:",value);
-        XX=[0]
-        self.I2Ccallback(0x40,XX,reg=0,read=1)#wakeup, do nothing
-        self.I2Ccallback(dev.Addr,[10],read=3)
-        self.I2Ccallback(dev.Addr,value[:16],reg=dev.Register_W)
-        if L>16:
-              self.I2Ccallback(dev.Addr,[10],read=3)
-              self.I2Ccallback(dev.Addr,value[16:],reg=dev.Register_W+16)
-        self.I2Ccallback(dev.Addr,[600],read=3) #Wait 500ms
-        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 GetI2CHBA1(self,RCUi,dev,width,bitoffset,value):
-        #print(width,len(value))
-        value2=value
-        reg=dev.Register_R
-#        if not(self.I2Ccallback(dev.Addr,[],reg=0x0)): return False;
-        if not(self.I2Ccallback(dev.Addr,value2,read=1)): return False;
-        if value2[0] is None:  return False
-        value[:]=value2[:];
-        print("HBA ",RCUi,dev.Addr," received:",value);
-#        if dev.store>0: #This is disabled due to noise on readback
-#            self.previousHBA[RCUi,dev.store-1]=value[:]
-        for i in range(len(value)):
-              value[i]=UnMask(value[i],width,bitoffset)
-        return True;
-
-
-    def RCUthread(self,Qin):
-         while True:
-           item = Qin.get()
-           if item is None: break;
-#           print("TODO: Set busy")
-#           self.statevar.set_value("busy");
-           print("RCU SetVar",item)#,self.conf.variables[item.id])
-           if (item.type==InstType.varSet):
-               var1=self.conf.variables[item.id]
-               self.OPCUASetVariable(item.id,var1,item.data,item.mask)
-           elif (item.type==InstType.varRead):
-               var1=self.conf.variables[item.id]
-               self.OPCUAReadVariable(item.id,var1,item.data,item.mask)
-           elif (item.type==InstType.method):
-               var1=self.conf.methods[item.id]
-               self.OPCUACallMethod(var1,item.data,item.mask)
-           else: print("Unknown OPCUA call");
-#           print("TODO: Set ready")
-#           if Qin.qsize()==0: self.statevar.set_value("ready");
-         logging.info("End RCU thread")
-
-    def Queue_Monitor(self,Q1,NRCU):
-        Inst1=Vars.Instr(Vars.DevType.VarUpdate,Vars.RCU_temp,NRCU,[0]*NRCU)
-        Q1.put(Inst1)
-        Inst1=Vars.Instr(Vars.DevType.VarUpdate,Vars.RCU_ADC_lock,96,[0]*96)
-        Q1.put(Inst1)
-        return
diff --git a/i2cserv/hba1.py b/i2cserv/hba1.py
new file mode 100644
index 0000000000000000000000000000000000000000..41637ccc1e9d86d2a81351db05bd1839a4215580
--- /dev/null
+++ b/i2cserv/hba1.py
@@ -0,0 +1,8 @@
+import numpy as np
+from .hwdev import hwdev;
+import logging
+class hba1(hwdev):
+  def __init__(self,config):
+    hwdev.__init__(self,config);
+    logging.info("HBA1 todo")
+    self.previousHBA=np.zeros([32,3,32],dtype='int')
diff --git a/i2cserv/hwdev.py b/i2cserv/hwdev.py
new file mode 100644
index 0000000000000000000000000000000000000000..a365a1c16a3508e729ef86f2d9101d338b78c4a8
--- /dev/null
+++ b/i2cserv/hwdev.py
@@ -0,0 +1,17 @@
+
+import logging
+class hwdev():
+  def __init__(self,config):
+        #print("Init",config['name'])  
+        self.conf=config
+
+  def OPCUASetVariable(self,varid,var1,data,mask):
+      logging.warn(self.conf['name']+" OPCUASetVariable Not implemented!")
+
+  def OPCUAReadVariable(self,varid,var1,mask):
+      logging.warn(self.conf['name']+" OPCUAReadVariable Not implemented!")
+      return []
+
+  def OPCUAcallMethod(self,var1,data,mask):
+      logging.warn(self.conf['name']+" OPCUAcallVariable Not implemented!")
+      return []
diff --git a/i2cserv/i2c.py b/i2cserv/i2c.py
new file mode 100644
index 0000000000000000000000000000000000000000..490d20cbc71f8f17c7caad7826a54a499483af61
--- /dev/null
+++ b/i2cserv/i2c.py
@@ -0,0 +1,48 @@
+import os
+if os.sys.platform is 'linux':
+    import pylibi2c;
+import time
+import logging
+#read=0: write to register
+#read=1: read from register
+#read=2: write to register (common in group)
+#read=3: wait ms second
+from .hwdev import hwdev;
+
+class i2c(hwdev):
+    def __init__(self,config):
+       hwdev.__init__(self,config);
+       self.I2Cdev='/dev/i2c-'+str(config['parameters'][0]);
+       logging.info("i2c driver on port "+str(self.I2Cdev))
+       self.I2Ccounter=0
+
+    def i2csetget(self,addr,data,reg=None,read=0):
+#       print("I2C",addr,reg,data,read)
+       bus=None;
+       try:
+              if read==3:
+                     time.sleep(data[0]/1000.)
+                     return True
+              logging.debug(str(("I2C",addr,reg,data,read)))
+
+#       return True;
+              bus=pylibi2c.I2CDevice(self.I2Cdev,addr)
+              if read==1:
+                     length=len(data)
+                     bus.iaddr_bytes=0
+                     if not(reg is None):
+                            bus.ioctl_write(0,str(bytearray([reg])))
+                     data[:]=[int(x) for x in bus.ioctl_read(0,length)]
+#         print("I2C read",addr,reg,data,read)
+              else:
+                     if reg is None: 
+                            bus.iaddr_bytes=0
+                     reg=0;
+                     bus.ioctl_write(reg,str(bytearray(data)))
+              bus.close()
+              return True;
+       except:
+              if bus: bus.close()
+#       data[0]=0xff
+              return False;
+
diff --git a/i2cserv/i2c_array.py b/i2cserv/i2c_array.py
new file mode 100644
index 0000000000000000000000000000000000000000..a134256d1c97c3f8ef1abb85e47abc26c6d396a5
--- /dev/null
+++ b/i2cserv/i2c_array.py
@@ -0,0 +1,282 @@
+#from . import Vars
+import numpy as np
+import logging
+from .spibitbang1 import *
+#import threading
+import time
+#from multiprocessing import Process
+#from pcctypes import *
+from queuetypes import *
+from .hwdev import hwdev;
+
+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 int2bytes(i):
+   b=[];
+   while i>255:
+        b=[i%256]+b;
+        i>>=8;
+   return [i]+b;
+
+def GetField(D,name,dev_number,default=None):
+    X=D.get(name,default)
+    return X[dev_number] if isinstance(X,list) else X;
+def Find(L,name,value):
+  for x in L:
+    if x[name]==value:
+        return x;
+  return False;
+
+class AttrDict(dict):
+  def __init__(self,*args,**kwargs):
+    super(AttrDict,self).__init__(*args,**kwargs)
+    self.__dict__=self
+
+def DevRegList(D):
+  #todo only count the drivers registers!!
+  for i,dev in enumerate(D.drivers):
+    dev['drv_id']=i;
+  devreglist={}
+  store=0;
+  for dev in D.device_registers:
+    N=dev.get('dim',1)
+    name=dev['name']    
+    for n in range(N):
+      addr=GetField(dev,'address',n,0)
+      devtype=GetField(dev,'driver',n)
+#      print(addr,devtype)
+      devid=0;
+      if devtype:
+        devid=Find(D.drivers,'name',devtype)['drv_id']
+        devtype=Find(D.drivers,'name',devtype)['type']
+      else: devtype=0;
+      if N>1: name2=name+str(n+1)
+      else:   name2=name;
+      for reg in dev['registers']:
+         regR=GetField(reg,'address',0,0)
+         regW=GetField(reg,'address',1,0)
+         if reg.get('store',False):
+            store+=1;
+            storex=store
+         else:
+            storex=0
+#         hf.write("const devreg %s {%i,%i,%i,%i,%i};\n" % (name2+'_'+reg['name'],addr,regR,regW,storex,devtype) )
+         devregname=name2+'.'+reg['name'];
+         devreglist[devregname]=AttrDict({"Addr":addr,"Register_R":regR,"Register_W":regW,"store":storex,"devtype":devtype,"devid":devid});
+#         print(devregname,devreglist[devregname]);
+#         hf.write("inline const t_devreg %s {.address=%i,.register_R=%i,.register_W=%i,.store=%i,.driver=%i};\n" % (devregname,addr,regR,regW,storex,devtype) )
+#hf.write("#define NumberStoreReg %i"%store)
+#  print(devreglist)
+  return devreglist,store
+
+def GetSteps(V1):
+              if isinstance(V1['devreg'],list): Step=len(V1['devreg']) 
+              else: Step=1; #V1.nVars
+              Step2=V1['dim']*((V1.get('width',8)+7)//8)//Step #int(V1.size/V1.nVars)
+              #print(Step,Step2,V1);
+              return Step,Step2
+
+
+class i2c_array(hwdev):
+    def __init__(self,config):
+        hwdev.__init__(self,config);
+#        self.Qout=Qout;
+#        self.Qin=Qin;
+#        self.I2Ccallback=I2Ccallback
+#        self.SWcallback=Switchcallback
+#        self.previousHBA=np.zeros([number,3,32],dtype='int')
+        pars=config['parameters'];
+        self.RCU_Switch1=range(pars[0],pars[1]+1);
+        self.N=len(self.RCU_Switch1);
+#        self.devregs,RCU_storeReg=DevRegList(yaml)
+#        print("Init",config['name'],'len=',len(self.RCU_Switch1),' stored reg=',RCU_storeReg)
+#        self.previous   =np.zeros([self.N,RCU_storeReg],dtype='int')
+
+    def load(self):
+        print("TODO: load")
+        #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 OPCUASetVariable(self,varid,var1,data,mask):
+       if var1['rw']=='variable': return;
+       logging.info(str(("Set Var",var1['name'],data,mask)))
+       data=self.SetGetVarValueMask(var1,data,mask);
+       Data=OPCUAset(varid,InstType.varSet,data,mask)
+       return [Data]
+
+    def OPCUAReadVariable(self,varid,var1,mask):
+      logging.info(str(("Read Var",var1['name'],mask)))
+      if len(mask)==0: mask=[True]*self.N; 
+      #data=self.GetVarValueAll(var1)
+      #else:             
+      data=self.GetVarValueMask(var1,mask);
+      Data=OPCUAset(varid,InstType.varSet,data,mask)
+      return [Data]
+
+    def OPCUAcallMethod(self,var1,data,mask):
+       print("Call Method",var1)
+    
+    def SetSwitch(self,RCUi):
+        self.conf['parentcls'].SetChannel(1<<self.RCU_Switch1[RCUi]);
+
+    def SetSwitchMask(self,mask):
+        m=0;
+        for RCUi in range(self.N):
+           if mask[RCUi]: m|=1<<self.RCU_Switch1[RCUi];
+        self.conf['parentcls'].SetChannel(m);
+
+    def SetGetVarValueMask(self,var1,data,mask):
+        Step,Step2=GetSteps(var1);
+        value1=[0]*Step*Step2;
+        if len(data)==Step:
+           data=data*self.N;
+        if not(len(data)==Step*Step2):
+            print("Check data length!");
+            return;
+        Step2//=self.N
+        if (len(mask)==self.N):
+          mask=[m for m in mask for x in range(Step)]
+        if not(len(mask)==Step*self.N):
+            print("Check mask length!");
+            return;
+#        if (len(value1)==V1.nVars) and (self.N>1):  value1=(value1*self.N);
+        i2c=self.conf['parentcls'];
+        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
+                devreg=var1['devreg'][Vari];
+                width=var1.get('width',8)
+                bitoffset=GetField(var1,'bitoffset',Vari,0)
+                self.SetSwitch(RCUi);
+                self.RCUi=RCUi;
+                self.SetVarValue(devreg,width,bitoffset,data[i0:i1])
+                value2=value1[i0:i1]
+                self.GetVarValue(devreg,width,bitoffset,value2)
+                value1[i0:i1]=value2
+        return value1
+
+
+
+    def GetVarValueMask(self,var1,mask):
+        Step,Step2=GetSteps(var1);
+        value1=[0]*Step*Step2;
+        Step2//=self.N
+        if (len(mask)==self.N):
+          mask=[m for m in mask for x in range(Step)]
+        if not(len(mask)==Step*self.N):
+            print("Check mask length!");
+            return;
+#        if (len(value1)==V1.nVars) and (self.N>1):  value1=(value1*self.N);
+        i2c=self.conf['parentcls'];
+        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
+                devreg=var1['devreg'][Vari];
+                width=var1.get('width',8)
+                bitoffset=GetField(var1,'bitoffset',Vari,0)
+                self.SetSwitch(RCUi);
+                value2=value1[i0:i1]
+                self.RCUi=RCUi;
+                self.GetVarValue(devreg,width,bitoffset,value2)
+                value1[i0:i1]=value2
+        return value1
+
+
+    def getstorearray(self,devreg):
+          storearray=devreg.get('storearray')
+          if not(storearray):
+                devreg['storearray']=[0]*self.N;
+                storearray=devreg.get('storearray');
+          return storearray;
+
+    def Setdevreg(self,devreg,value,mask=[]):
+ #       if devreg.get('store')>0: logging.warn("Setdevreg not working correctly for stored registers!")
+        if devreg['store']>0:
+                storearray=self.getstorearray(devreg);
+                for RCUi in range(self.N):
+                  if mask[RCUi]:   
+                      storearray[RCUi]=value[0]
+                      self.RCUi=RCUi;
+#                print("Stored values:",self.getstorearray(devreg))
+        self.SetSwitchMask(mask)
+        self.SetVarValue(devreg,8,0,value)
+        return True;
+        
+
+    def SetVarValue(self,devreg,width,bitoffset,value):
+            if devreg['register_W']==-1: return True; #We can not set it, only read it e.g. temperature
+            logging.debug(str(("RCU1 Set ",self.RCUi,devreg['addr'],value)))
+            #self.parentcls.SetChannel(1<<RCU_Switch[RCUi]);
+            if devreg['store']>0:
+                storearray=self.getstorearray(devreg);
+                previous=storearray[self.RCUi];
+                value[0]=ApplyMask(value[0],width,bitoffset,previous);
+                storearray[self.RCUi]=value[0]
+#                print("Stored values:",self.getstorearray(devreg))
+            #  devreg['drivercls'].i2csetget
+            return devreg['drivercls'].i2csetget(devreg['addr'],value,reg=devreg['register_W'])
+
+    def GetVarValue(self,devreg,width,bitoffset,value):
+        logging.debug(str(("RCU1 Get ",self.RCUi,devreg['addr'],value)))
+#                self.GetI2C(RCUi,devreg,width,bitoffset,value)
+#        if dev.store>0:
+#            value[0]=self.previous[RCUi,dev.store-1]
+#        return True
+        callback=devreg['drivercls'].i2csetget;
+        l1=int(np.floor((width+bitoffset+7)/8))
+#        print(width,bitoffset,l1)
+        value2=value
+        reg=devreg['register_R']
+        if reg>255: #This is for the monitor ADC
+          if not(callback(devreg['addr'],int2bytes(reg),read=2)): return False;
+          callback(0,[250],read=3)
+          if not(callback(devreg['addr'],value2,read=1)): return False;
+        else:
+          if not(callback(devreg['addr'],value2,reg=reg,read=1)): return False;
+        if value2[0] is None:  return False
+        value[:]=value2[:];
+        if devreg['store']>0:
+             storearray=self.getstorearray(devreg);
+             storearray[self.RCUi]=value[0]
+             logging.debug(str(("Store buffer",self.RCUi,value[0])))
+ #            print("Stored values:",self.getstorearray(devreg))
+        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;
+
+
diff --git a/i2cserv/i2c_switch.py b/i2cserv/i2c_switch.py
new file mode 100644
index 0000000000000000000000000000000000000000..1574fc41c6b770297aa48da440a1f2872a57ba4a
--- /dev/null
+++ b/i2cserv/i2c_switch.py
@@ -0,0 +1,20 @@
+import logging
+from .i2c import i2c
+
+#import HWconf
+#SWaddr=0x70
+class i2c_switch(i2c):
+    def __init__(self,config):
+        i2c.__init__(self,config)
+        self.SWaddr=config['devreg'][0]['addr']
+        self.CurrentChannel=0
+        logging.info("i2c switch at address "+str(self.SWaddr))
+
+    def SetChannel(self,channel):
+        if (channel)==self.CurrentChannel: return True;
+        logging.debug("SetChannel=%i" % channel)
+        self.CurrentChannel=channel
+        return self.i2csetget(self.SWaddr,[channel])
+
+#    def I2Ccallback(self,RCU,addr,data,reg=None,read=0):
+#        self.callback1(addr,data,reg,read)    
diff --git a/i2cserv/i2cbitbang1.py b/i2cserv/i2cbitbang1.py
new file mode 100644
index 0000000000000000000000000000000000000000..8aacf743f7fe6f395dfdfb6ab6d1fc7238da1bbb
--- /dev/null
+++ b/i2cserv/i2cbitbang1.py
@@ -0,0 +1,147 @@
+from enum import Enum
+import logging
+import numpy as np
+from .hwdev import hwdev
+#This is copy of spibitbang. Need to be updated!!
+class SPIBB_pins(Enum):
+    CLK = 0  
+    SDIO = 1  
+    SDIOdir = 2 
+    CS = 3  
+
+class i2cbitbang1(hwdev):
+  def __init__(self,config):
+    hwdev.__init__(self,config)
+    logging.info("i2cbitbang todo")
+
+  def i2csetget(self,addr,data,reg=None,read=0):
+    logging.info("i2cbitbang todo")
+    return False;
+
+
+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,SPIdev,I2Cdev,I2Cpins,value):
+#Read 3 SPI devices in parallel from same IOexpander
+        ADC_reg_address=SPIdev[0].Register_R
+        Nv=len(SPIdev)
+        def Setbit(pintype,value):
+           for i in range(1,Nv):
+             SetI2C(RCUi,I2Cdev[i][pintype],1,I2Cpins[i][pintype],[value],buffer=True) 
+           SetI2C(RCUi,I2Cdev[0][pintype],1,I2Cpins[0][pintype],[value]) 
+        def Getbit(pintype):
+           print("N=",Nv,len(value))
+           retvalue=np.zeros_like(value)
+           retvalue[0::Nv]=GetI2C(RCUi,I2Cdev[0][pintype],1,I2Cpins[0][pintype])
+           for i in range(1,Nv):
+             retvalue[i::Nv]=GetI2C(RCUi,I2Cdev[i][pintype],1,I2Cpins[i][pintype],buffer=True)
+           return retvalue
+           
+        CLK=0
+        SDIO=1
+        SDIOdir=2
+        CS=3
+
+        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(CLK,0) 
+          
+        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(CLK,0) 
+              Setbit(SDIO,int(bit)) 
+              Setbit(CLK,1) 
+
+#        Setbit(CS,1) #disable
+        Setbit(SDIOdir,1) #input
+        Setbit(CLK,0) 
+
+          #    print("read byte")
+#        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/i2cserv/i2cthread.py b/i2cserv/i2cthread.py
index 308c5a3815aae45c4c33b21bded791244fcd1ec2..c76a1ece5da3c7022ceb77b404c302b36eeaf438 100644
--- a/i2cserv/i2cthread.py
+++ b/i2cserv/i2cthread.py
@@ -1,13 +1,15 @@
 #Start the correct I2C server connect to the pipes on a new process
 import logging
 from multiprocessing import Process
+from queuetypes import *
+from time import sleep
+#from i2cserv import I2Cswitch1
+#from i2cserv import I2C_dummy as I2C
 
-from i2cserv import I2Cswitch1
-from i2cserv import I2C_dummy as I2C
-
-from i2cserv import RCU
-from i2cserv import CLK
+#from i2cserv import RCU
+#from i2cserv import CLK
 
+import yamlconfig as yc
 
 import yaml
 class AttrDict(object):
@@ -26,25 +28,101 @@ class AttrDict(object):
         except KeyError:
             raise AttributeError
 
+def runmethod(conf,Qout,methodid,mask):
+#    print("Run method",methodid,mask)
+    var1=conf.getmethod(methodid)
+    drv=var1.get('drivercls');
+    for inst in var1['instructions']:
+        for key,value in inst.items():
+            if not(isinstance(value,list)): value=[value]
+            logging.info(str(("Run instruction",key,value)));
+            if (key=='WAIT'):
+                sleep(value[0]/1000.)
+                continue;
+            v1=conf.getvarid(key)
+            if v1: 
+                if value[0]=='Update':
+                   getvar(conf,Qout,v1,mask)
+                else:
+                   setvar(conf,Qout,v1,value,mask)
+                continue;
+            v1=conf.getmethodid(key)
+            if v1: 
+                runmethod(conf,Qout,v1,mask)
+                continue;
+            v1=conf.getdevreg(key)
+            if v1:
+                drv2=v1['drivercls']
+                if drv:  drv.Setdevreg(v1,value,mask)
+                elif drv2: drv2.Setdevreg(v1,value,mask)
+                else: logging.warn("Driver not specified for instruction"+key)
+                continue;
+#    def Setdevreg(self,devreg,value,mask=[],width=8,bitoffset=0):
+            logging.warn("Unknown instruction "+key)
+#               drv=var1.get('drivercls');
+#               if not(drv): 
+#                   logging.warn(var1['name']+" driver not found!")
+#                   continue;
+#               for data in drv.OPCUAcallMethod(item.id,var1,item.data,item.mask):
+#                   Qout.put(data)
+def setvar(conf,Qout,varid,data,mask):
+    var1=conf.getvars()[varid]
+    drv=var1.get('drivercls');
+    if not(drv): 
+        logging.warn(var1['name']+" driver not found!")
+        return;
+    for data in drv.OPCUASetVariable(varid,var1,data,mask):
+        Qout.put(data)
+
+def getvar(conf,Qout,varid,mask):
+    var1=conf.getvars()[varid]
+    drv=var1.get('drivercls');
+    if not(drv): 
+        logging.warn(var1['name']+" driver not found!")
+        return;
+    for data in drv.OPCUAReadVariable(varid,var1,mask):
+        Qout.put(data)
+
+
 def I2Cserver(Qin,Qout,name):
-        logging.info(str(("New thread",name)))
-        with open("config/RCU.yaml", "r") as f:
-             settings = AttrDict(yaml.load(f))
-        if name=='RCU':
-          SW1=I2Cswitch1.I2Cswitch1(I2C.I2C1server)
-          RCU1=RCU.RCU1(32,I2C.I2C1server,SW1.SetChannel,settings,Qin,Qout)
-        elif name=='CLK':
-          SW0=I2Cswitch1.I2Cswitch0(None) #Dummy switch as their is no switch on LTS
-          RCU1=CLK.RCU1(1,I2C.I2C4server,SW0.SetChannel)
-        else:
-          logging.warn(str(("Unknown name",name," thread stopping")))
-          return
-        RCU1.load() #Load current register values from HW
-        RCU1.RCUthread(Qin)
+        logging.info("New i2c process "+name)
+        conf=yc.yamlconfig(name)
+        conf.linkdevices()
+        conf.loaddrivers()
+        conf.linkdrivers()
+        while True:
+           item = Qin.get()
+           if item is None: break;
+#           print("TODO: Set busy")
+#           self.statevar.set_value("busy");
+           #print("SetVar",item)#,self.conf.variables[item.id])
+           if (item.type==InstType.varSet):
+               setvar(conf,Qout,item.id,item.data,item.mask)
+           #    self.OPCUASetVariable(item.id,var1,item.data,item.mask)
+           elif (item.type==InstType.varRead):
+               getvar(conf,Qout,item.id,item.mask)
+           #    var1=self.conf.variables[item.id]
+           #    self.OPCUAReadVariable(item.id,var1,item.data,item.mask)
+           elif (item.type==InstType.method): runmethod(conf,Qout,item.id,item.mask)
+           else: print("OPCUA call not implemented!");
+#           print("TODO: Set ready")
+#           if Qin.qsize()==0: self.statevar.set_value("ready");
+        logging.info("End i2c process "+name)
+
+#        if name=='RCU':
+#          SW1=I2Cswitch1.I2Cswitch1(I2C.I2C1server)
+#          RCU1=RCU.RCU1(32,I2C.I2C1server,SW1.SetChannel,settings,Qin,Qout)
+#        elif name=='CLK':
+#          SW0=I2Cswitch1.I2Cswitch0(None) #Dummy switch as their is no switch on LTS
+#          RCU1=CLK.RCU1(1,I2C.I2C4server,SW0.SetChannel)
+#        else:
+#          logging.warn(str(("Unknown name",name," thread stopping")))
+#          return
+#        RCU1.load() #Load current register values from HW
+#        RCU1.RCUthread(Qin)
 
 def start(Qout,Qin,name):  
         thread1 = Process(target=I2Cserver, args=(Qin,Qout,name))
         thread1.start()
         return thread1
 
-
diff --git a/i2cserv/spibitbang1.py b/i2cserv/spibitbang1.py
index 7b5f4e6dbb93d80e427f529c82a9b974dc8379b7..7db2517fba2567c8da1b509dda61d6d08ca0a3c9 100644
--- a/i2cserv/spibitbang1.py
+++ b/i2cserv/spibitbang1.py
@@ -1,6 +1,7 @@
 from enum import Enum
 import logging
 import numpy as np
+from .hwdev import hwdev
 
 class SPIBB_pins(Enum):
     CLK = 0  
@@ -8,42 +9,54 @@ class SPIBB_pins(Enum):
     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]
+class spibitbang1(hwdev):
+  def __init__(self,config):
+    hwdev.__init__(self,config)
+#    logging.info("spibitbang todo")
 
-        logging.info(str(("SPIbb set",ADC_address,value)))
+  def i2csetget(self,addr,data,reg=None,read=0):
+    if read==0: return self.SetSPIbb(addr,data)
+    elif read==1: return self.GetSPIbb(addr,data)
+    else: logging.warn("Not implemented!")
+    return False;
+
+  def SetSPIbb(self,ADC_address,value):
+         
+        CSdev=self.conf['devreg'][SPIBB_pins.CS.value]
+        CSpin=self.conf['parameters'][SPIBB_pins.CS.value]
+        SDOdev=self.conf['devreg'][SPIBB_pins.SDIO.value]
+        SDOpin=self.conf['parameters'][SPIBB_pins.SDIO.value]
+        CLKdev=self.conf['devreg'][SPIBB_pins.CLK.value]
+        CLKpin=self.conf['parameters'][SPIBB_pins.CLK.value]
+#        SDIOdirdev=self.conf['devreg'][SPIBB_pins.SDIOdir.value]
+#        SDIOdirpin=self.conf['parameters'][SPIBB_pins.SDIOdir.value]
 
+        logging.info(str(("SPIbb set",ADC_address,value)))
+        SetI2C=self.conf['parentcls'].SetVarValue
         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
+        SetI2C(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
+              SetI2C(SDOdev,1,SDOpin,[int(bit)]) 
+              SetI2C(CLKdev,1,CLKpin,[1]) 
+              SetI2C(CLKdev,1,CLKpin,[0]) 
+        SetI2C(CSdev,1,CSpin,[1]) #disable
+        SetI2C(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]
+  def GetSPIbb(self,ADC_reg_address,value):
+        CSdev=self.conf['devreg'][SPIBB_pins.CS.value]
+        CSpin=self.conf['parameters'][SPIBB_pins.CS.value]
+        SDOdev=self.conf['devreg'][SPIBB_pins.SDIO.value]
+        SDOpin=self.conf['parameters'][SPIBB_pins.SDIO.value]
+        CLKdev=self.conf['devreg'][SPIBB_pins.CLK.value]
+        CLKpin=self.conf['parameters'][SPIBB_pins.CLK.value]
+        SDIOdirdev=self.conf['devreg'][SPIBB_pins.SDIOdir.value]
+        SDIOdirpin=self.conf['parameters'][SPIBB_pins.SDIOdir.value]
 
         logging.info(str(("SPIbb get",ADC_reg_address)))
           
@@ -51,31 +64,34 @@ def GetSPIbb(SetI2C,GetI2C,RCUi,dev,value):
         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
+
+        SetI2C=self.conf['parentcls'].SetVarValue
+        GetI2C=self.conf['parentcls'].GetVarValue
+        SetI2C(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(SDOdev,1,SDOpin,[int(bit)]) 
+              SetI2C(CLKdev,1,CLKpin,[1]) 
+              SetI2C(CLKdev,1,CLKpin,[0]) 
 
-        SetI2C(RCUi,CSdev,1,CSpin,[1]) #disable
+        SetI2C(CSdev,1,CSpin,[1]) #disable
 
           #    print("read byte")
-        SetI2C(RCUi,SDIOdirdev,1,SDIOdirpin,[1]) #input
-        SetI2C(RCUi,CSdev,1,CSpin,[0]) #enable
+        SetI2C(SDIOdirdev,1,SDIOdirpin,[1]) #input
+        SetI2C(CSdev,1,CSpin,[0]) #enable
         a=[0]
-        N=len(value)
+        N=1;#len(value)
+        ret_value=[0];
         for i in range(N): value[i]=0
         for cnt in range(8*(ADC_bytes+1)):
-              ret_value=GetI2C(RCUi,SDOdev,1,SDOpin) #enable
+              GetI2C(SDOdev,1,SDOpin,ret_value) #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
+              SetI2C(CLKdev,1,CLKpin,[1]) 
+              SetI2C(CLKdev,1,CLKpin,[0])  #read after falling edge
+        SetI2C(CSdev,1,CSpin,[1]) #disable
+        SetI2C(SDIOdirdev,1,SDIOdirpin,[0]) #output
         return True;
 
 def GetSPIbb2(SetI2C,GetI2C,RCUi,SPIdev,I2Cdev,I2Cpins,value):
diff --git a/opcuaserv/i2client.py b/opcuaserv/i2client.py
index e644ecdcf988fc8a795963942ebbcf26d04022a2..813700b0ad658f85389b9ff6126efac8f38c8491 100644
--- a/opcuaserv/i2client.py
+++ b/opcuaserv/i2client.py
@@ -29,7 +29,7 @@ class i2client():
         self.Qout.put(Data);
 
     def callmethod(self,id1,mask=[]):
-        Data=OPCUAset(id1,InstType.method,[],[])
+        Data=OPCUAset(id1,InstType.method,[],mask)
         self.Qout.put(Data);
 
     def data_waiting(self):
diff --git a/opcuaserv/yamlconfig.py b/opcuaserv/yamlconfig.py
deleted file mode 100644
index bd2bf4481a610a08af41f529957438bd327a9f4b..0000000000000000000000000000000000000000
--- a/opcuaserv/yamlconfig.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import yaml
-import struct
-import time
-
-def Find(L,name,value):
-  for x in L:
-    if x[name]==value:
-        return x;
-  return False;
-
-
-def GetField(D,name,dev_number,default=None):
-    X=D.get(name,default)
-    return X[dev_number] if isinstance(X,list) else X;
-
-
-class yamlconfig():
-    def __init__(self,yamlfile='RCU'):
-        self.conf=yaml.load(open("config/"+yamlfile+'.yaml'))
-        var1=self.conf['variables']
-        N=len(var1)
-#        print([v['name'] for v in self.conf['variables']])
-        for i in range(N-1,-1,-1):
-            #print(var1[i])
-            if isinstance(var1[i]['name'],list):
-                for x,name in enumerate(var1[i]['name']):
-                    var2=var1[i].copy()
-                    var2['name']=name
-                    var2['devreg']=GetField(var1[i],'devreg',x)
-                    var2['scale']=GetField(var1[i],'scale',x,1)
-                    var1.append(var2)
-                    N+=1;
-                var1.remove(var1[i])
-                N-=1;
-#        print([[v['name'],v.get('devreg')] for v in var1])
-#        print(len(self.conf['variables']),N)
-        for i,v in enumerate(self.conf['variables']):
-            v['id']=i
-        for i,v in enumerate(self.conf['methods']):
-            v['id']=i
-
-    
diff --git a/opcuaserv/yamlreader.py b/opcuaserv/yamlreader.py
index 1c51537ecf3e6eb02d3f6f0bb9cc64418ae32717..0697006a22c737e684938826379ae4e29bba01f9 100644
--- a/opcuaserv/yamlreader.py
+++ b/opcuaserv/yamlreader.py
@@ -1,8 +1,8 @@
 import yaml
 import struct
 import time
-from opcuaserv.yamlconfig import *
-
+from yamlconfig import *
+import logging
 def bytes2int(bts):
    x=0;
    for b in bts:
@@ -25,7 +25,7 @@ class yamlreader(yamlconfig):
     
     def AddVars(self,AddVarR,AddVarW):
      for v in self.conf['variables']:
-        print(v)
+#        print(v)
         dim1=v.get('dim',1);
         name=v.get('name');
         datatype=v.get('dtype','integer')
@@ -42,7 +42,7 @@ class yamlreader(yamlconfig):
         if v.get('rw') in ['ro','rw']:
             var1=AddVarR(name+"_R",varvalue2,v['id'],v.get('debug'))
             v['OPCR']=var1
-            print("Var added:"+name+"_R")
+            logging.debug("Var added:"+name+"_R")
             self.server.readvar(v['id'])
             time.sleep(0.1);
 #            Inst=Vars.Instr(Vars.DevType.VarUpdate,v,dim2,varvalue2)
@@ -51,7 +51,7 @@ class yamlreader(yamlconfig):
         if v.get('rw') in ['wo','rw','variable']:
             var1=AddVarW(name+"_RW",varvalue2,v['id'],self,v.get('debug'))
             v['OPCW']=var1
-            print("Var added:"+name+"_RW")
+            logging.debug("Var added:"+name+"_RW")
      for v in self.conf['variables']:
         mask=v.get('mask');
         if not(mask): continue;
@@ -64,7 +64,7 @@ class yamlreader(yamlconfig):
     def AddMethod(self,Addmethod):
       for v in self.conf['methods']:
           if v.get('rw','')=='hidden': continue;
-          print(v)
+#          print(v)
 #        Inst1=Vars.Instr(Vars.DevType.Instr,v,0,[])
           Addmethod(v['name'],v['id'],self,v.get('debug'))
           mask=v.get('mask');
@@ -77,7 +77,7 @@ class yamlreader(yamlconfig):
 
     def callMethod(self,id1):
         v=self.conf['methods'][id1];
-        print("Method called!",v['name'])
+        logging.debug("Method called!"+v['name'])
         mask=v.get('maskOPC',None);
         mask=mask.get_value() if (mask!=None) else [];
         self.server.callmethod(id1,mask) 
@@ -87,7 +87,7 @@ class yamlreader(yamlconfig):
         if v['rw']=='variable': return;
         mask=v.get('maskOPC',None);
         mask=mask.get_value() if (mask!=None) else [];
-        print("M2:",mask)
+#        print("M2:",mask)
         dtype=v.get('dtype','integer');
         width=(v.get('width',8)-1)//8+1
         if (dtype=="double"): 
@@ -108,17 +108,17 @@ class yamlreader(yamlconfig):
             elif width==8:
                 data2 = struct.pack('>%sQ' % len(data), *data)
             else:
-                print("setvar",v['name']," unsupported width!",width)
+                logging.warn("setvar"+v['name']+" unsupported width!"+str(width))
                 return;
         elif (dtype=="string"):
                 data2=bytearray() 
                 for s in data:
                     data2.extend('{s:>{width}'.format(s=s[:width],width=width).encode('ascii'));
         else:
-                print("setvar unsupported type");
+                logging.warn("setvar unsupported type");
                 return;
         data2=[d for d in data2]
-        print("setvar ",v['name'],data2,mask);
+        logging.debug(str(("setvar ",v['name'],data2,mask)));
         self.server.setvar(id1,data2,mask) 
 
     def getvar(self):
@@ -130,7 +130,7 @@ class yamlreader(yamlconfig):
             item=self.server.readdata()
             if item is None: break;
             id1,data,mask=item; 
-            print("**getvar",id1,data,mask);
+            logging.debug(str(("**getvar",id1,data,mask)));
             if len(data)==0: continue;
 #           except:
 #              print('finished')
@@ -141,7 +141,7 @@ class yamlreader(yamlconfig):
         v=self.conf['variables'][id1];
         dtype=v.get('dtype','integer');
         width=(v.get('width',8)-1)//8+1
-        print("OPCset",width,data)
+        logging.debug(str(("OPCset",width,data)))
         if dtype=="boolean": 
                 data2=[d==1 for d in data];
         elif (dtype in ['uint8','uint16','uint32','uint64','double']): 
@@ -157,14 +157,14 @@ class yamlreader(yamlconfig):
             elif width==8:
                 data2 = struct.unpack('>%sQ' % (len(data)//8), data)
             else:
-                print("OPCset",v['name']," unsupported width!",width)
+                logging.warn("OPCset"+v['name']+" unsupported width!"+str(width))
                 return;
         elif dtype=="string": 
                 cnt=int(len(data)/width)
 #                data2=[(bytearray(data[i*width:(i+1)*width]).decode("utf-8")) for i in range(cnt)]
                 data2=[bytearray(data)[i*width:(i+1)*width].decode("utf-8") for i in range(cnt)]
         else:
-                print("OPCset unsupported type");
+                logging.warn("OPCset unsupported type");
                 return;
         if dtype=="double": 
                 scale=float(v.get('scale',1.))
@@ -173,11 +173,11 @@ class yamlreader(yamlconfig):
 #        print("OPCset",v['name'],data3,mask)
         if mask: #Only update masked values
             step=len(data2)//len(mask)
-            print("mask step=",step)
+            #print("mask step=",step)
             for i in range(len(data2)):
                 if mask[i//step]: data3[i]=data2[i]
         else:
             data3=data2;
-        print("OPCset",v['name'],data3)
+        logging.debug(str(("OPCset",v['name'],data3)))
         v['OPCR'].set_value(data3);
 
diff --git a/pcctypes.py b/pcctypes.py
deleted file mode 100644
index a980fdd5602787d7d6944ca80197b6b74b379ca3..0000000000000000000000000000000000000000
--- a/pcctypes.py
+++ /dev/null
@@ -1,83 +0,0 @@
-
-#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
-    Wait = 9
-
-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
-   dbool = 3
-
-#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/pypcc2.py b/pypcc2.py
index 6bc05a25f2fd464fbf55d8ff7c647a5b0743c572..2fadc3efd85a2db5c4681d7a5c54a8b59ccf6970 100644
--- a/pypcc2.py
+++ b/pypcc2.py
@@ -12,6 +12,7 @@ import signal
 
 parser = argparse.ArgumentParser()
 parser.add_argument("-s", "--simulator", help="Do not connect to I2c, but simulate behaviour.", action="store_true")
+parser.add_argument("-t", "--test", help="Do not start OPC-UA server.", 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")
 parser.add_argument("-c", "--config", help="YAML config files, comma seperated [%(default)s]",type=str, default='RCU')
@@ -45,35 +46,37 @@ for name in I2Cports:
         thread1=i2cthread.start(*RCU_I2C.GetInfo())
         threads.append(thread1)
     I2Cclients.append(RCU_I2C)
-#Initialise OPCUA server
-logging.info("Initialised OPC-UA Server")   
-opcuaserv.InitServer(port=args.port)
 
-logging.info("Load OPCUA variables & start i2c listing thread")   
-for i,name in enumerate(I2Cports):
-    RCU_I2C=I2Cclients[i]
-    RCU_conf=yamlreader.yamlreader(RCU_I2C,yamlfile=name)
-    RCU_conf.AddVars(opcuaserv.AddVarR,opcuaserv.AddVarW)
-    RCU_conf.AddMethod(opcuaserv.Addmethod)
+#Initialise OPCUA server and load variables
+logging.info("Initialised OPC-UA Server")   
+if not(args.test):  
+    opcuaserv.InitServer(port=args.port)
+    logging.info("Load OPCUA variables & start i2c listing thread")   
+    for i,name in enumerate(I2Cports):
+        RCU_I2C=I2Cclients[i]
+        RCU_conf=yamlreader.yamlreader(RCU_I2C,yamlfile=name)
+        RCU_conf.AddVars(opcuaserv.AddVarR,opcuaserv.AddVarW)
+        RCU_conf.AddMethod(opcuaserv.Addmethod)
 
-    thread2=threading.Thread(target=RCU_conf.getvar); #Thread on OPC-UA side of pipe
-    thread2.start()
-    threads.append(thread2)
+        thread2=threading.Thread(target=RCU_conf.getvar); #Thread on OPC-UA side of pipe
+        thread2.start()
+        threads.append(thread2)
+    time.sleep(1)
+    logging.info("Start OPC-UA server")
+    opcuaserv.start()
 
 if False:
    opcuaserv.server.stop()
    exit()
 
-time.sleep(1)
-logging.info("Start OPC-UA server")
-opcuaserv.start()
  
 try:
  while RunTimer:
     time.sleep(1)
 finally:
-   logging.info("Stop OPC-UA server")
-   opcuaserv.server.stop()
+   if not(args.test):
+       logging.info("Stop OPC-UA server")
+       opcuaserv.server.stop()
 
 logging.info("Stop threads")
 for i2c in I2Cclients:
diff --git a/testCLK.py b/testCLK.py
new file mode 100644
index 0000000000000000000000000000000000000000..392732524bc94e3cef27ebe02493ecbfe433d4c8
--- /dev/null
+++ b/testCLK.py
@@ -0,0 +1,69 @@
+import logging
+import argparse
+from opcuaserv import opcuaserv
+from opcuaserv import i2client
+from opcuaserv import yamlreader
+#from opcuaserv import pypcc2
+from i2cserv import i2cthread
+import threading
+import time
+import sys
+import signal
+from yamlconfig import Find;
+
+logging.basicConfig(level="INFO",format='%(asctime)s [%(levelname)-8s,%(filename)-20s:%(lineno)-3d] %(message)s')
+
+RunTimer=True;
+#def signal_handler(sig, frame):
+#    logging.warn('Stop signal received!')
+#    global RunTimer; 
+#    RunTimer=False
+#signal.signal(signal.SIGINT, signal_handler)
+
+logging.info("Start I2C processes")   
+threads=[]
+I2Cclients=[]
+name='CLK'
+RCU_I2C=i2client.i2client(name=name)
+thread1=i2cthread.start(*RCU_I2C.GetInfo())
+threads.append(thread1)
+I2Cclients.append(RCU_I2C)
+
+#Load yaml so that we know the variable names
+RCU_conf=yamlreader.yamlreader(RCU_I2C,yamlfile=name)
+
+if True:
+    var1=RCU_conf.getvarid('RCU_LED0');
+    N=32;
+    mask=[i<2 for i in range(N)];
+    data=[0]*N;
+elif True:
+    var1=RCU_conf.getvarid('RCU_attenuator');
+    N=32*3;
+    mask=[i<6 for i in range(N)];
+    data=[10]*N;
+    data[:6]=[0,1,2,3,4,5]
+#print(var1)
+print("mask=",mask);
+print("data=",data);
+RCU_I2C.setvar(var1,data,mask);
+#def setvar(self,id1,data=[],mask=[]):
+
+var1=RCU_conf.getmethodid('RCU_on');
+N=32;
+mask=[i<2 for i in range(N)];
+RCU_I2C.callmethod(var1,mask)
+
+
+time.sleep(2);
+
+while RCU_I2C.data_waiting():
+    varid,data,mask=RCU_I2C.readdata()
+    print("Results:",RCU_conf.getvar1(varid)['name'],data)
+
+
+logging.info("Stop threads")
+for i2c in I2Cclients:
+    i2c.stop()
+for thread1 in threads:
+    thread1.join()
diff --git a/testRCU.py b/testRCU.py
new file mode 100644
index 0000000000000000000000000000000000000000..0ced60e8ab3e83f74879d5a737f545c64660500f
--- /dev/null
+++ b/testRCU.py
@@ -0,0 +1,69 @@
+import logging
+import argparse
+from opcuaserv import opcuaserv
+from opcuaserv import i2client
+from opcuaserv import yamlreader
+#from opcuaserv import pypcc2
+from i2cserv import i2cthread
+import threading
+import time
+import sys
+import signal
+from yamlconfig import Find;
+
+logging.basicConfig(level="INFO",format='%(asctime)s [%(levelname)-8s,%(filename)-20s:%(lineno)-3d] %(message)s')
+
+RunTimer=True;
+#def signal_handler(sig, frame):
+#    logging.warn('Stop signal received!')
+#    global RunTimer; 
+#    RunTimer=False
+#signal.signal(signal.SIGINT, signal_handler)
+
+logging.info("Start I2C processes")   
+threads=[]
+I2Cclients=[]
+name='RCU'
+RCU_I2C=i2client.i2client(name=name)
+thread1=i2cthread.start(*RCU_I2C.GetInfo())
+threads.append(thread1)
+I2Cclients.append(RCU_I2C)
+
+#Load yaml so that we know the variable names
+RCU_conf=yamlreader.yamlreader(RCU_I2C,yamlfile=name)
+
+if True:
+    var1=RCU_conf.getvarid('RCU_LED0');
+    N=32;
+    mask=[i<2 for i in range(N)];
+    data=[0]*N;
+elif True:
+    var1=RCU_conf.getvarid('RCU_attenuator');
+    N=32*3;
+    mask=[i<6 for i in range(N)];
+    data=[10]*N;
+    data[:6]=[0,1,2,3,4,5]
+#print(var1)
+print("mask=",mask);
+print("data=",data);
+RCU_I2C.setvar(var1,data,mask);
+#def setvar(self,id1,data=[],mask=[]):
+
+var1=RCU_conf.getmethodid('RCU_on');
+N=32;
+mask=[i<2 for i in range(N)];
+RCU_I2C.callmethod(var1,mask)
+
+
+time.sleep(2);
+
+while RCU_I2C.data_waiting():
+    varid,data,mask=RCU_I2C.readdata()
+    print("Results:",RCU_conf.getvar1(varid)['name'],data)
+
+
+logging.info("Stop threads")
+for i2c in I2Cclients:
+    i2c.stop()
+for thread1 in threads:
+    thread1.join()
diff --git a/yamlconfig.py b/yamlconfig.py
new file mode 100644
index 0000000000000000000000000000000000000000..fb3201338e2fdd4b3e1c45a78b96ae8ac1c5cc32
--- /dev/null
+++ b/yamlconfig.py
@@ -0,0 +1,205 @@
+import yaml
+import struct
+import time
+import logging
+
+def Find(L,name,value):
+  for x in L:
+    if x[name]==value:
+        return x;
+  return False;
+
+
+def GetField(D,name,dev_number,default=None):
+    X=D.get(name,default)
+    return X[dev_number] if isinstance(X,list) else X;
+
+#class AttrDict(dict):
+# def __init__(self,*args,**kwargs):
+#   super(AttrDict,self).__init__(*args,**kwargs)
+#   self.__dict__=self
+
+def str2int(x):
+    return (int(x,16) if x.find('x')>0 else int(x));
+
+class yamlconfig():
+    def __init__(self,yamlfile='RCU'):
+        self.conf=yaml.load(open("config/"+yamlfile+'.yaml'))
+        self.expand_variables()
+#        print([[v['name'],v.get('devreg')] for v in var1])
+#        print(len(self.conf['variables']),N)
+        for i,v in enumerate(self.conf['variables']):
+            v['id']=i
+        for i,v in enumerate(self.conf['methods']):
+            v['id']=i
+
+    def getvars(self):
+        return self.conf['variables'];
+    def getvar1(self,varid):
+        return self.conf['variables'][varid];
+    def getvarid(self,name):
+        var1=Find(self.conf['variables'],'name',name);
+        return (var1['id'] if var1 else var1);
+
+    def getmethod(self,methodid):
+        return self.conf['methods'][methodid];
+#        return Find(self.conf['methods'],'id',methodid);
+    def getmethodid(self,name):
+        var1=Find(self.conf['methods'],'name',name);
+        return (var1['id'] if var1 else var1);
+
+    def expand_variables(self):
+        #expand variables that are combined in single array
+        var1=self.conf['variables']
+        N=len(var1)
+#        print([v['name'] for v in self.conf['variables']])
+        for i in range(N-1,-1,-1):
+            #print(var1[i])
+            if isinstance(var1[i]['name'],list):
+                for x,name in enumerate(var1[i]['name']):
+                    var2=var1[i].copy()
+                    var2['name']=name
+                    var2['devreg']=GetField(var1[i],'devreg',x)
+                    var2['scale']=GetField(var1[i],'scale',x,1)
+                    var1.append(var2)
+                    N+=1;
+                var1.remove(var1[i])
+                N-=1;
+
+    def getdevreg(self,name):
+        try:
+          dr=self.devreglist.get(name);
+          if dr: return dr;
+          if isinstance(name,int): return {"addr":name}
+          name2=name.split('.')
+#          print(name2,str2int(name2[0]),str2int(name2[1]))
+          if len(name2)==2:
+              return {"addr":str2int(name2[0]),"register_R":str2int(name2[1]),"register_W":str2int(name2[1])}
+          logging.error("Can not find device register "+str(name));
+        except:
+          logging.error("Can not find device register "+str(name));
+        return None;
+    def linkdevices(self):
+        #replace devreg reference with (pointer to) devreg dict
+        devreglist={}
+        drivers=self.conf['drivers']
+        for dev in self.conf['device_registers']:
+            N=dev.get('dim',1)
+            name=dev['name']    
+            for n in range(N):
+                addr=GetField(dev,'address',n,0)
+                devtype=GetField(dev,'driver',n)
+#                print(addr)
+                if devtype:
+                    devid=Find(drivers,'name',devtype)
+                    #devtype=Find(D.drivers,'name',devtype)['type']
+                else: devtype=None;
+                if N>1: name2=name+str(n+1)
+                else:   name2=name;
+                for reg in dev['registers']:
+                    regR=GetField(reg,'address',0,0)
+                    regW=GetField(reg,'address',1,0)
+                    store=reg.get('store',False)
+                    devregname=name2+'.'+reg['name'];
+                    devreglist[devregname]={"addr":addr,"register_R":regR,"register_W":regW,"store":store,"driver":devid};
+#                    print(devregname,devreglist[devregname]['addr'],devreglist[devregname]['register_R'],devreglist[devregname]['register_W']);
+        self.devreglist=devreglist;
+        for D in drivers:
+            devreg=D.get('devreg');
+            if not(devreg): continue;
+            for i,dr in enumerate(devreg):
+                #print(dr,self.getdevreg(dr))
+                devreg[i]=self.getdevreg(dr)
+
+        for D in self.conf['variables']:
+            devreg=D.get('devreg');
+            if not(devreg): continue;
+            if isinstance(devreg,list):
+                for i,dr in enumerate(devreg):
+                #print("linkdev",dr,self.getdevreg(dr))
+                    devreg[i]=self.getdevreg(dr)
+            else:
+                D['devreg']=[self.getdevreg(devreg)]
+            #print(D['name'],devreg)
+#         hf.write("inline const t_devreg %s {.address=%i,.register_R=%i,.register_W=%i,.store=%i,.driver=%i};\n" % (devregname,addr,regR,regW,storex,devtype) )
+#hf.write("#define NumberStoreReg %i"%store)
+#        print(devreglist)
+#  return devreglist,store
+
+    def loaddrivers(self):
+        import importlib
+        import sys, inspect
+        for c in self.conf['drivers']:
+#          print("loading",c['name'],c['type']);
+#          try:
+          i = importlib.import_module("i2cserv."+c['type'])
+ #         except:
+  #          logging.warn("No driver for "+c['type'])
+   #         c['obj']=None;
+    #        continue;
+          for name, obj in inspect.getmembers(i,inspect.isclass):
+              if name==c['type']:
+ #                 print("  Load child:",name)
+                  c['obj']=obj(c)
+          if not(c.get('obj')): 
+              logging.warn((("Driver "+c['type']+" not found!")))
+        
+    def linkdrivers(self):
+        drivers=self.conf['drivers']
+        for c in drivers:
+            name=c.get('parent');
+            if not(name): continue;
+            p=Find(drivers,'name',name);
+            if not(p):
+                    logging.error("Can not find driver "+str(name))
+                    continue;
+            c['parentcls']=p['obj'];
+#            print("link ",c['name'],name," to ",p['obj'])
+            #devregs=c.get('devreg')
+            #if not(devregs): continue;
+            #for dr in devregs:
+            #    if not(dr): continue;
+            #    name=dr.get('driver')
+            #    if not(name): #Give it the parents driver
+            #        dr["drivercls"]=p['obj']
+            #    drv=dr.get("drivercls")
+            #    if drv is None:  logging.warn("variable "+c['name']+" register driver not found")
+
+
+
+        for name,c in self.devreglist.items():
+            drv=c['driver'];
+            if not(drv): continue;
+#            print(drv)
+            c['drivercls']=drv.get('obj');
+#            print("link ",name,drv['name']," to ",c.driverobj)
+        for c in self.conf['variables']:
+            name=c.get('driver');
+            if not(name): continue;
+            p=Find(drivers,'name',name);
+            if not(p):
+                    logging.error("Can not find driver "+str(name))
+                    continue;
+            c['drivercls']=p['obj'];
+#            print("link ",c['name'],name," to ",p['obj'])
+
+            devregs=c.get('devreg')
+            if not(devregs): continue;
+            for dr in devregs:
+                if not(dr): continue;
+                name=dr.get('driver')
+                if not(name): #Give it the parents driver
+                    dr["drivercls"]=p['obj']
+                drv=dr.get("drivercls")
+                if drv is None:  logging.warn("variable "+c['name']+" register driver not found")
+     
+        for c in self.conf['methods']:
+            name=c.get('driver');
+            if not(name): continue;
+            p=Find(drivers,'name',name);
+            if not(p):
+                    logging.error("Can not find driver "+str(name))
+                    continue;
+            c['drivercls']=p['obj'];
+
+