diff --git a/clk/HWconf.py b/clk/HWconf.py
deleted file mode 100644
index b975665baded666250e115e29c9a372c03a72852..0000000000000000000000000000000000000000
--- a/clk/HWconf.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#from collections import namedtuple
-#from enum import Enum
-from pcctypes import *
-
-#Mid plane address
-RCU_MPaddr=MPaddr(1,[1],1,[7])
-
-CLK_IO3_OUT1=DevReg(0x20,0,2,1)
-CLK_IO3_OUT2=DevReg(0x20,1,3,2)
-CLK_IO3_CONF1=DevReg(0x20,6,6,3)
-CLK_IO3_CONF2=DevReg(0x20,7,7,4)
-
-RCU_storeReg=4; #Number of stored registers
-
-
-
-SPIBB_PLL=BBdev(4,[CLK_IO3_OUT1,CLK_IO3_OUT1,CLK_IO3_OUT1,CLK_IO3_OUT1],[4,7,5,6],0) #CLK,SDI,SDO,CS
-
-CLK_PLL_lock =DevReg(SPIBB_PLL,0X00,0X00,0) # PLL locked status
diff --git a/clk/Vars.py b/clk/Vars.py
deleted file mode 100644
index 7e4d4b02e5e8a06021fac03eacfc8abad5b0a01e..0000000000000000000000000000000000000000
--- a/clk/Vars.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from .HWconf import *
-
-CLKmod=I2Cmodules.CLK
-
-
-CLK_IGNORE_PPS= VarArray("CLK_Ignore_PPS",1,[Var2dev("",CLKmod,DevType.I2C,CLK_IO3_OUT2,1 ,2,1)],RW.ReadOnly,datatype.dInt,1,None,None)
-CLK_Enable_PWR= VarArray("CLK_Enable_PWR",1,[Var2dev("",CLKmod,DevType.I2C,CLK_IO3_OUT1,1 ,1,1)],RW.ReadOnly,datatype.dInt,1,None,None)
-CLK_Stat1     = VarArray("CLK_Stat"      ,1,[Var2dev("",CLKmod,DevType.I2C,CLK_IO3_OUT1,1 ,2,1)],RW.ReadOnly,datatype.dInt,1,None,None)
-CLK_lock1      = VarArray("CLK_Lock"      ,1,[Var2dev("",CLKmod,DevType.SPIbb,CLK_PLL_lock,8 ,0,1)],RW.ReadOnly,datatype.dInt,1,None,None)
-
-
-OPC_devvars=[CLK_Enable_PWR,CLK_lock1]
-
-RCU_init=Instrs("ReadRegisters",2,[
-   Instr(DevType.VarUpdate,CLK_IGNORE_PPS,1,[0]),
-   Instr(DevType.VarUpdate,CLK_Enable_PWR,1,[0])
-])
-
-CLK_on=Instrs("CLK_on",3,[
-   Instr(DevType.I2C,CLK_IO3_CONF1,1,[0x2C]),
-   Instr(DevType.I2C,CLK_IO3_OUT1 ,1,[0x42]),
-   Instr(DevType.VarUpdate,CLK_lock1,1,[0]),
-   Instr(DevType.VarUpdate,CLK_Enable_PWR,1,[0])
-])
-
-CLK_off=Instrs("CLK_off",3,[
-   Instr(DevType.I2C,CLK_IO3_CONF1,1,[0x2C]),
-   Instr(DevType.I2C,CLK_IO3_OUT1 ,1,[0x40]),
-   Instr(DevType.VarUpdate,CLK_Enable_PWR,1,[0])
-])
-
-def SPIinst(reg,value):
-  return Instr(DevType.SPIbb,DevReg(SPIBB_PLL,0,reg,0),1,[value])
-
-CLK_PLL_setup=Instrs("CLK_PLL_setup",15,[
-#   SPIinst(0x03,0x08),
-#   Instr(DevType.I2C,CLK_IO3_CONF1,1,[0x2C]),
-   SPIinst(0x05,0x97),
-   SPIinst(0x06,0x10),
-   SPIinst(0x07,0x04),
-   SPIinst(0x08,0x01),
-   SPIinst(0x07,0x00),
-   SPIinst(0x09,0x10),
-   SPIinst(0x0A,0x14),
-   SPIinst(0x09,0x00),
-   SPIinst(0x0D,0x01),#was 2
-   SPIinst(0x0F,0x01),
-   SPIinst(0x11,0x01),
-   SPIinst(0x13,0x01),
-   Instr(DevType.VarUpdate,CLK_lock1,1,[0])
-])
-
-
-OPC_methods=[CLK_on,CLK_off,CLK_PLL_setup]
diff --git a/config/CLK.yaml b/config/CLK.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..9edd498bfcd4b8bd13cf44b78ac2355d6ae79447
--- /dev/null
+++ b/config/CLK.yaml
@@ -0,0 +1,58 @@
+version: "1.0"
+description: "1234"
+
+drivers:
+ - name: I2C
+   type: i2c
+   parameters: [1] #I2C port number
+ - name: I2C_CLK
+   type: i2c_devs #I2C devices
+   parent: I2C
+   parameters:  [32] #number of RCUs
+ - name: SPIbb1 
+   type: spibitbang2 #SPI bitbang via GPIO expander: CLK, SDI,SDO,CS
+   parent: I2C_CLK
+   devreg: [IO3.GPIO1,IO3.GPIO1,IO3.GPIO1,IO3.GPIO1]
+   parameters: [4,7,5,6]
+
+#This is the I2C devices in the RCU
+device_registers:
+ - name: IO
+   dim: 3
+   description: IO-Expander
+   address: 0x20
+   device: TCA9539/TCA6416?
+   driver: I2C_CLK
+   registers:
+   - name: CONF1
+     description: Direction of port1
+     address: 6
+     store: True
+   - name: CONF2
+     description: Direction of port2
+     address: 7
+     store: True
+   - name: GPIO1
+     description: Input/Ouput port 1
+     address: [0,2]  #Read / Write address different
+     store: True
+   - name: GPIO2
+     description: Input/Ouput port 2
+     address: [1,3]
+     store: True
+
+ - name: PLL
+   driver: SPIbb1
+   registers:
+    - name: PLL_stat
+      description: PLL locked status
+      address: 0x0
+
+
+variables:
+   - name: CLK_IGNORE
+     description: Only masked RF chains are updated
+     driver: I2C_CLK
+     rw:  variable #server RW variable, not linked to IO
+     dtype: boolean
+
diff --git a/config/RCU.yaml b/config/RCU.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..50a6f8f664b7a1e08bf73e0db5ebc9e30ed12cea
--- /dev/null
+++ b/config/RCU.yaml
@@ -0,0 +1,388 @@
+version: "1.0"
+description: "1234"
+
+drivers:
+ - name: I2C1
+   type: RCU_switch
+   devreg: [SWITCH.MASK]
+   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
+ - name: I2Cbb1 
+   type: i2cbitbang1 #I2C bitbang via GPIO expander
+   devreg: [IO1.GPIO1,IO2.GPIO2,IO2.CONF2]
+   parameters: [6,3,3] #pins
+   parent: I2C_RCU
+ - name: I2Cbb2
+   type: i2cbitbang1
+   devreg: [IO1.GPIO2,IO2.GPIO1,IO1.CONF1]
+   parameters: [7,7,7]
+   parent: I2C_RCU
+ - name: I2Cbb3
+   type: i2cbitbang1
+   devreg: [IO1.GPIO2,IO2.GPIO1,IO1.CONF1]
+   parameters: [7,7,7]
+   parent: I2C_RCU
+ - name: SPIbb1 
+   type: spibitbang1 #SPI bitbang via GPIO expander: CLK, SDIO, SDIOdir,CS
+   devreg: [IO3.GPIO1,IO3.GPIO1,IO3.CONF1,IO3.GPIO2]
+   parameters: [1,0,0,0]
+   parent: I2C_RCU
+ - name: SPIbb2
+   type: spibitbang1
+   devreg: [IO3.GPIO1,IO3.GPIO1,IO3.CONF1,IO3.GPIO2]
+   parameters: [3,2,2,1]
+   parent: I2C_RCU
+ - name: SPIbb3
+   type: spibitbang1
+   devreg: [IO3.GPIO1,IO3.GPIO1,IO3.CONF1,IO3.GPIO2]
+   parameters: [5,4,4,2]
+   parent: I2C_RCU
+
+#This is the I2C devices in the RCU
+device_registers:
+ - name: IO
+   dim: 3
+   description: [IO-Expander for filter selection,IO-Expander for ON/OFF, Band, BUFx2,IO-Expander for ADC control]
+   address: [0x75,0x76,0x20]
+   device: [TCA9539,TCA9539,TCA6416]
+   driver: I2C1
+   registers:
+   - name: CONF1
+     description: Direction of port1
+     address: 6
+     store: True
+   - name: CONF2
+     description: Direction of port2
+     address: 7
+     store: True
+   - name: GPIO1
+     description: Input/Ouput port 1
+     address: [0,2]  #Read / Write address different
+     store: True
+   - name: GPIO2
+     description: Input/Ouput port 2
+     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
+   driver: I2C1
+   registers:
+   - name: ID
+     description: Random
+     address: 0xfc
+   - name: Version
+     description: Set in production
+     address: 0
+ 
+ - name: AN
+   description: Monitor ADC on RCU
+   address: 0x14
+   device: LTC2495
+   driver: I2C1
+   registers:
+   - name: V_1v8
+     address: 0xB080
+   - name: V_2v5
+     address: 0xB880
+   - name: V_3v3
+     address: 0xB180
+   - name: I_Ant0
+     address: 0xB980
+   - name: I_Ant1
+     address: 0xB280
+   - name: I_Ant2
+     address: 0xBA80
+   - name: V_Ant0
+     address: 0xB380
+   - name: V_Ant1
+     address: 0xBB80
+   - name: Temp
+     address: 0xA0C0
+
+#This 'special' devices that uses I2C
+
+ - name: HB_UC
+   description: RCU microcontroller 
+   address: 0x40
+   driver: I2C1
+   registers:
+   - name: ID
+     description: Device ID
+     address: 0
+
+ - name: HBAT
+   dim: 3
+   address: [0x41,0x42,0x43]
+   description: Virtual HBAT0 interface
+   driver: I2C1
+   registers:
+   - name: XY
+     address: 0x10
+     description: XY delay register
+   - name: Version
+     address: 127
+     description: HBAT server version
+
+ - name: ADC
+   dim: 3
+   description:  ADC SPI control
+   device: AD9683
+   driver: [SPIbb1,SPIbb2,SPIbb3]
+   registers:
+    - name: PLL_stat
+      description: PLL locked status
+      address: 0x0A
+    - name: JESD_control1
+      description: JESD link control
+      address: 0x5F
+    - name: CML_adjust
+      description: CML output adjust
+      address: 0x15
+    - name: Update
+      description: Global device uptate
+      address: 0xFF
+
+ - name: DTH
+   dim: 3
+   description: CW dither source
+   device: SI4012
+   driver: [I2Cbb1,I2Cbb1,I2Cbb1]
+   address: 0x70
+   registers:
+    - name: Freq
+      description: Frequency
+      address: [0x1140,0x1141]
+    - name: Property
+      description: Properties
+      address: [0x11,0x11]
+    - name: Start
+      description: Start CW
+      address: [0x62,0x62]
+    - name: Stop
+      description: Stop CW
+      address: [0x67,0x67]
+
+
+variables:
+   - name: Ant_mask
+     description: Only masked RF chains are updated
+     driver: I2C_RFCHAIN
+     rw:  variable #server RW variable, not linked to IO
+     dtype: boolean
+     dim: 96
+
+   - name: RCU_mask
+     description: Only masked RCUs are updated
+     driver: I2C_RCU
+     rw:  variable #server RW variable, not linked to IO
+     dtype: boolean
+     dim: 32
+
+   - name: RCU_state
+     description: State of RCUs 0=unknown, 1=ready, 2=busy, 3=error
+     driver: I2C_RCU
+     rw:  variable #server variable, not linked to IO
+     dtype: uint8
+     dim: 32
+
+   - name: RCU_attenuator
+     description: Attenuator before ADC
+     driver: I2C_RFCHAIN
+     devreg:  [IO1.GPIO1,IO1.GPIO2,IO2.GPIO1]
+     bitoffset: [0,0,0]
+     width: 5
+     rw:  rw
+     dtype: uint8
+     dim: 96
+     mask: Ant_mask
+
+   - name: RCU_band
+     description: Band select switch 1=10MHz,2=30MHz
+     driver: I2C_RFCHAIN
+     devreg:  [IO2.GPIO2,IO2.GPIO2,IO2.GPIO2]
+     bitoffset: [0,2,4]
+     width: 2
+     rw:  rw
+     dtype: uint8
+     dim: 96
+     mask: Ant_mask
+
+   - name: RCU_GPIO1
+     driver: I2C_RFCHAIN
+     devreg:  [IO1.GPIO1,IO2.GPIO1,IO3.GPIO1]
+     width: 8
+     rw:  ro
+     dtype: uint8
+     dim: 96
+     mask: Ant_mask
+
+   - name: RCU_GPIO2
+     driver: I2C_RFCHAIN
+     devreg:  [IO1.GPIO2,IO2.GPIO2,IO3.GPIO2]
+     width: 8
+     rw:  ro
+     dtype: uint8
+     dim: 96
+     mask: Ant_mask
+
+   - name: RCU_LED0
+     driver: I2C_RCU
+     description: LED on RCU
+     devreg:  IO2.GPIO2
+     bitoffset: 6
+     width: 1
+     rw:  rw
+     dtype: boolean
+     dim: 32
+     mask: RCU_mask
+
+   - name: RCU_LED1
+     driver: I2C_RCU
+     description: LED on RCU
+     devreg:  IO2.GPIO2
+     bitoffset: 7
+     width: 1
+     rw:  rw
+     dtype: boolean
+     dim: 32
+     mask: RCU_mask
+
+   - name: RCU_temperature
+     description: Temperature sensor on RCU
+     driver: I2C_RCU
+     devreg:  AN.Temp
+     width: 23
+     scale: 4.21e-3
+     rw:  ro
+     dtype: double
+     dim: 32
+
+   - name: RCU_Pwr_dig
+     description: Enable LDOs
+     driver: I2C_RCU
+     devreg:  IO2.GPIO1
+     width: 1
+     bitoffset: 6
+     rw:  ro
+     dtype: boolean
+     dim: 32
+     mask: RCU_mask
+
+   - name: HBA_element_beamformer_delays
+     description: Delays of each frontend
+     driver: I2C_HBAT
+     devreg:  [HBAT1.XY,HBAT2.XY,HBAT3.XY]
+     bitoffset: [2,2,2]
+     width: 5
+     rw:  rw
+     dtype: uint8
+     dim: 3072
+     mask: Ant_mask
+
+   - name: RCU_ID
+     description: Unique RCU ID
+     driver: I2C_RCU
+     devreg:  ROM.ID
+     width: 32
+     rw:  ro
+     dtype: uint32
+     dim: 32
+     mask: RCU_mask
+
+   - name: RCU_version
+     description: RCU version number
+     driver: I2C_RCU
+     devreg:  ROM.Version
+     width: 80  #10 characters
+     rw:  ro
+     dtype: string
+     dim: 32
+     mask: RCU_mask
+     
+   - name: RCU_ADC_lock
+     description: 0x81=locked
+     driver: I2C_RFCHAIN
+     devreg:  [ADC1.PLL_stat,ADC2.PLL_stat,ADC3.PLL_stat]
+     width: 8
+     rw:  ro
+     dtype: uint8
+     dim: 96
+     mask: Ant_mask
+
+   - name: RCU_dth1_freq
+     driver: I2C_RFCHAIN
+     devreg:  [DTH1.Freq,DTH2.Freq,DTH3.Freq]
+     width: 32
+     rw:  rw
+     dtype: uint32
+     dim: 96
+     mask: Ant_mask
+
+methods:
+  - name: RCU_update
+    mask: RCU_mask
+    instructions:
+     - RCU_ADC_lock: Update
+
+  - name: RCU_on
+    mask: RCU_mask
+    instructions:
+     - IO2.CONF1: 0    #Set device register, can also specify a register adress direction e.g. OIO2.0: 0
+     - IO2.GPIO1: 0x4A
+     - IO2.GPIO2: 0x55
+     - IO3.GPIO1: 0x15
+     - IO3.GPIO2: 0x47
+     - IO1.GPIO1: 0xCA
+     - IO1.GPIO2: 0xCA
+     - IO2.CONF2: 0
+     - IO3.CONF1: 0
+     - IO3.CONF2: 0
+     - IO1.CONF1: 0
+     - IO1.CONF1: 0
+     - RCU_attenuator: [10,10,10]  #Set OPC-UA variable
+     - RCU_Pwr_dig: Update  #Read value and update the OPC-UA variable
+     - WAIT: 500         #ms to wait
+     - ADC1_on: 0        #call another opc-ua method
+     - ADC2_on: 0
+     - WAIT: 500         #ms to wait
+     - RCU_ADC_lock: Update
+  - name: ADC1_on
+    rw: hidden
+    instructions:
+     - ADC1.JESD_control1 : 0x14
+#     - ADC1.SYNC_control: 1  #Setup ADCs
+#     - ADC1.CML_level: 0x7
+     - ADC1.Update: 1       #Needed to update ADC registers
+  - name: ADC2_on
+    rw: hidden
+    instructions:
+     - ADC2.JESD_control1 : 0x14
+#     - ADC2.SYNC_control: 1  #Setup ADCs
+#     - ADC2.CML_level: 0x7
+     - ADC2.Update: 1       #Needed to update ADC registers
+ 
+  - name: RCU_off
+    instructions:
+     - RCU_Pwr_dig: 0 #Switch power off
+     #todo, also make all GPIO pins (except power enables) inputs to remove all power from devices.
\ No newline at end of file
diff --git a/config/UNB2.yaml b/config/UNB2.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e187ac81108168d9c823cbb708fb5460c79e4693
--- /dev/null
+++ b/config/UNB2.yaml
@@ -0,0 +1,128 @@
+version: "0.0"
+description: "UNB2 LTS" 
+
+drivers:
+ - name: I2C1
+   type: UNB2_switch #Special driver mapping internal i2c line address to the 3 switches. 
+   #Address -> switch states       -> array of i2c-devices
+   #00:2F   -> [0:1][0:3][0:3,6:7] -> QSFP
+   #30:38   -> [0:1][0:3][4]       -> DDR4
+   #40:48   -> [0:1][0:3][5]       -> FPGA_PS
+   #80:81   -> [0:1][4]            -> PS
+   #A0:A1   -> [0:1][5]            -> Front panel
+   devreg: [APSCT_SWITCH.MASK,UB2_SWITCH1.MASK,UB2_SWITCH2.MASK] 
+   parameters: [1,0,0,0] #I2C port number, 3x switch reset pins 
+   
+ - name: d_QSFP 
+   type: i2c_array #An array of similar devices connected to an I2C switch
+   parent: I2C1
+   parameters: [0,48] #start,number of QSFP (2 UB x 2 nodes * 6 QSFP)
+ - name: d_DDR4
+   type: i2c_array 
+   parent: I2C1
+   parameters: [0x30,8] 
+ - name: d_FPGA_PS
+   type: i2c_array 
+   parent: I2C1
+   parameters: [0x40,48] 
+ - name: d_PS
+   type: i2c_array 
+   parent: I2C1
+   parameters: [0x80,2] 
+ - name: d_front_panel
+   type: i2c_array 
+   parent: I2C1
+   parameters: [0xA0,2] 
+# - name: GPIO
+#   type: GPIO
+#   parameters: [1] #pin numbers
+
+  
+#This is the I2C devices in the RCU
+device_registers:
+- name: APSCT_SWITCH #not in LTS
+  description: Uniboard select switch on APSCT
+  address: 0x70
+  device: TCA9548
+  driver: I2C1
+  registers:
+  - name: MASK
+- name: UB2_SWITCH1
+  description: UNB2 primary switch
+  address: 0x71
+  device: TCA9548
+  driver: I2C1
+  registers:
+  - name: MASK
+- name: UB2_SWITCH2
+  description: UNB2 secondary switch
+  address: 0x72
+  device: TCA9548
+  driver: I2C1
+  registers:
+  - name: MASK
+
+- name: FP_IO
+  description: IO-Expander for front panel
+  address: 0x41
+  device: PCA9536
+  driver: d_front_panel
+  registers:
+  - name: CONF #default 0xff = all input
+    description: Direction of GPIO
+    address: 3
+  - name: GPIO
+    description: Input/Ouput port 
+    address: [0,1]  #Read / Write address different
+    store: True
+
+- name: POL_FPGA_CORE
+  address: 0x01
+  driver: d_FPGA_PS
+  device: BMR4xx
+  registers:
+  - name: READ_VOUT
+    address: 0x8B
+  - name: READ_IOUT
+    address: 0x8C
+  - name: READ_TEMP
+    address: 0x8D
+
+variables:
+   - name: UNB2_mask
+     rw:  variable #translator variable
+     dtype: boolean
+     dim: 2
+
+   - name: UNB2_Front_Panel_LED
+     description: LED on front panel
+     mask: UNB2_mask
+     devreg: FP_IO.GPIO
+     driver: d_front_panel
+     rw:  rw
+     dtype: uint8
+     bitoffset: 4
+     width: 3
+     dim: 2
+
+   - name: UNB2_POL_FPGA_CORE_VOUT
+     driver: d_FPGA_PS
+     devreg:  POL_FPGA_CORE.READ_VOUT
+     width: 16
+     rw:  ro
+     dtype: double
+     scale: 1.2207e-4 #2^-13
+     dim: 8
+     mask: UNB2_node_mask
+
+methods:
+  - name: UNB2_on
+    mask: UNB2_mask
+    instructions:
+     - FP_IO.CONF: 0xff    #TODO: setup correctly
+     - UNB2_Front_Panel_LED: 1
+
+  - name: UNB2_off
+    mask: UNB2_mask
+    instructions:
+     - UNB2_Front_Panel_LED: 2
diff --git a/config/apsctl.schema.json b/config/apsctl.schema.json
new file mode 100644
index 0000000000000000000000000000000000000000..07c6b82a4866a48c4d4f4b3166af321404950a95
--- /dev/null
+++ b/config/apsctl.schema.json
@@ -0,0 +1,83 @@
+{
+    "$id": "http://git.astron.nl/lofar2.0/pypcc/apsctl.schema.json",
+    "$schema": "http://json-schema.org/draft-07/schema",
+    "title": "apsctl",
+    "description": "APSCTL yaml schema",
+    "type" : "object",
+    "properties": {
+        "version": {"type":"string"},
+        "description":{"type":"string"},
+        "drivers":         { "type":"array",  "items": { "$ref": "#/$defs/drivers"}},
+        "device_registers":{ "type":"array",  "items": { "$ref": "#/$defs/dev_regs"}},
+        "variables":{ "type":"array",  "items": { "$ref": "#/$defs/variables"}},
+        "methods":{ "type":"array",  "items": { "$ref": "#/$defs/methods"}}
+    },
+    "additionalProperties" : false,
+    "$defs":{
+        "drivers" : {
+            "type" : "object",
+            "properties": {
+                "name" : {"type":"string"},
+                "type" : {"enum":["i2c","RCU_switch","UNB2_switch","i2c_devs","i2c_array","i2c_array2","hba1","i2cbitbang1","spibitbang1","spibitbang2"]},
+                "parent" : {"type":"string"},
+                "parameters" : {"type":"array","items":{"type":"integer"}} ,
+                "devreg" : {"type":"array","items":{"type":"string"}}
+                },
+                "additionalProperties" : false
+            },
+        "dev_regs" : {
+            "type" : "object",
+            "properties": {
+                "name" : {"type":"string"},
+                "dim" : {"type":"integer"},
+                "description" : {},
+                "address" : {"anyOf":[{"type":"integer"},{"type":"array","items":{"type":"integer"}}]},
+                "device" : {},
+                "driver" : {},
+                "registers":{ "type":"array",  "items": { "$ref": "#/$defs/registers"}}
+            },
+            "additionalProperties" : false
+        },
+        "registers" : {
+            "type" : "object",
+            "properties": {
+                "name" : {"type":"string"},
+                "description" : {"type":"string"},
+                "address" : {},
+                "store" : {"type":"boolean"}
+            },
+            "additionalProperties" : false
+        },
+        "variables" : {
+            "type" : "object",
+            "properties": {
+                "name" : {"type":"string"},
+                "description" : {"type":"string"},
+                "dim" : {"type":"integer"},
+                "dtype" : {"enum":["uint64","uint32","uint16","uint8","double","boolean","string"]},
+                "driver" : {"type":"string"},
+                "rw" : {"enum":["variable","rw","ro","hidden"]},
+                "scale" : {"type":"number"},
+                "bitoffset" : {},
+                "width" : {"type":"integer"},
+                "devreg" : {},
+                "mask" : {"type":"string"}
+            },
+            "additionalProperties" : false
+        },
+        "methods" : {
+            "type" : "object",
+            "properties": {
+                "name" : {"type":"string"},
+                "mask" : {"type":"string"},
+                "instructions" : {"type":"array"},
+                "rw" : {"enum":["visible","hidden"]}
+            },
+            "additionalProperties" : false
+        }
+
+    }
+
+}
+
+
diff --git a/i2c/I2C.py.old b/i2c/I2C.py.old
deleted file mode 100644
index 1982b43c9c0e13bf33d61d4bf48e8c2b940b5d06..0000000000000000000000000000000000000000
--- a/i2c/I2C.py.old
+++ /dev/null
@@ -1,70 +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):
-#  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()
-       print("I2C4 error")
-#       data[0]=0xff
-       return False;
-
diff --git a/i2c/I2Cv2.py b/i2c/I2Cv2.py
deleted file mode 100644
index 1627b362488d3a250654c41856f4ecfe1baa41ad..0000000000000000000000000000000000000000
--- a/i2c/I2Cv2.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#import pylibi2c;
-#import 
-from periphery import I2C;
-
-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;
-
-
-i2c1=I2C("/dev/i2c-1")
-
-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)))
-       if read==1:
-          if not(reg is None):  i2c1.transfer(addr,[I2C.Message([reg])])
-          msgs=[I2C.Message(data,read=True)]
-          i2c1.transfer(addr,msgs)
-          data[:]=msgs[0].data
-       else:
-            if reg is None: 
-               msgs=[I2C.Message(data)]
-            else:
-               msgs=[I2C.Message([reg]+data)]
-            i2c1.transfer(addr,msgs)
-       return True;
-  except:
-       return False;
-
-i2c4=I2C("/dev/i2c-4")
-
-def I2C4server(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)))
-
-       if read==1:
-          if not(reg is None):  i2c4.transfer(addr,[I2C.Message([reg])])
-          msgs=[I2C.Message(data,read=True)]
-          i2c4.transfer(addr,msgs)
-          data[:]=msgs[0].data
-       else:
-            if reg is None: 
-               msgs=[I2C.Message(data)]
-            else:
-               msgs=[I2C.Message([reg]+data)]
-            i2c4.transfer(addr,msgs)
-       return True;
-  except:
-       return False;
diff --git a/i2c/setRCUversion.py b/i2c/setRCUversion.py
deleted file mode 100644
index 4771de66e197be6a9f94861bcf39c8c4b2baa3ce..0000000000000000000000000000000000000000
--- a/i2c/setRCUversion.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from I2C import *
-import time
-RCU=1
-Ver="RCU2H v0.2"
-R1=0
-ROM=0x50
-
-#Set switch
-print("Set switch")
-if not(I2C1server(0x70,[1<<RCU],reg=None,read=0)): exit() #select RCU
-#exit()
-#Get ID
-print("Get ID")
-ID=[0]*4
-if not(I2C1server(ROM,ID,reg=0xFC,read=1)): exit() #select RCU
-print(ID)
-exit()
-
-#Upload version
-Ver2=[(c.encode('utf-8')[0]) for c in Ver]
-print(len(Ver),Ver,Ver2)
-V2=[0]
-for i,v in enumerate(Ver2):
- time.sleep(0.1)
- I2C1server(ROM,[v],reg=R1+i,read=0) #select RCU
-# I2C1server(ROM,[v],reg=None,read=0) #select RCU
- time.sleep(0.1)
- I2C1server(ROM,V2,reg=R1+i,read=1) #select RCU
- print(i,v,V2)
-
-#Download version
-Ver2=[0]*10
-I2C1server(ROM,Ver2,reg=R1,read=1) #select RCU
-print(Ver2)
diff --git a/i2c/setswitch.py b/i2c/setswitch.py
deleted file mode 100644
index 45f43942a9b3dc1fc7cde1b4efa5a06b674bde92..0000000000000000000000000000000000000000
--- a/i2c/setswitch.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from I2C import *
-import time
-RCU=3
-Ver="RCU2H v0.2"
-R1=0
-ROM=0x50
-
-#Set switch
-print("Set switch")
-if not(I2C1server(0x70,[1<<RCU],reg=None,read=0)):
-   print("Error setting switch!")
-   exit() #select RCU
-exit()
-#Get ID
-print("Get ID")
-ID=[0]*4
-if not(I2C1server(ROM,ID,reg=0xFC,read=1)): exit() #select RCU
-print(ID)
-exit()
-
-#Upload version
-Ver2=[(c.encode('utf-8')[0]) for c in Ver]
-print(len(Ver),Ver,Ver2)
-V2=[0]
-for i,v in enumerate(Ver2):
- time.sleep(0.1)
- I2C1server(ROM,[v],reg=R1+i,read=0) #select RCU
-# I2C1server(ROM,[v],reg=None,read=0) #select RCU
- time.sleep(0.1)
- I2C1server(ROM,V2,reg=R1+i,read=1) #select RCU
- print(i,v,V2)
-
-#Download version
-Ver2=[0]*10
-I2C1server(ROM,Ver2,reg=R1,read=1) #select RCU
-print(Ver2)
diff --git a/i2c/test.py b/i2c/test.py
deleted file mode 100644
index 92ee093a8b833322558341cd664855f643f57dd1..0000000000000000000000000000000000000000
--- a/i2c/test.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from I2C import *
-import time
-RCU=1
-Ver="RCU2H v0.2"
-R1=0
-ROM=0x50
-
-ID=[0]*7
-I2C1server(0x20,ID,reg=2,read=1)
-print(ID)
-I2C1server(0x20,ID,reg=2,read=1)
-print(ID)
-exit()
-#0=0
-#1=0   #debug?
-#2=21  #spd1
-#3=7   #spd2
-#4=175 #TXspeed
-#5=0
-#6=0
-
-#Upload version
-Ver2=[(c.encode('utf-8')[0]) for c in Ver]
-print(len(Ver),Ver,Ver2)
-V2=[0]
-for i,v in enumerate(Ver2):
- time.sleep(0.1)
- I2C1server(ROM,[v],reg=R1+i,read=0) #select RCU
-# I2C1server(ROM,[v],reg=None,read=0) #select RCU
- time.sleep(0.1)
- I2C1server(ROM,V2,reg=R1+i,read=1) #select RCU
- print(i,v,V2)
-
-#Download version
-Ver2=[0]*10
-I2C1server(ROM,Ver2,reg=R1,read=1) #select RCU
-print(Ver2)
diff --git a/clk/CLK.py b/i2cserv/CLK.py
similarity index 99%
rename from clk/CLK.py
rename to i2cserv/CLK.py
index f71fe4de5f2eb5a48b97611a38ea03ca938c289c..a775b70b969ee2b37b7bd070c07139be2021b3a3 100644
--- a/clk/CLK.py
+++ b/i2cserv/CLK.py
@@ -1,8 +1,8 @@
-from . import Vars
+#from . import Vars
 import numpy as np
 import logging
 from .spibitbang2 import *
-import threading
+#import threading
 
 
 def ApplyMask(value,width=8,bitoffset=0,previous=0):
diff --git a/i2c/I2C.py b/i2cserv/I2C.py
similarity index 100%
rename from i2c/I2C.py
rename to i2cserv/I2C.py
diff --git a/i2c/I2C_dummy.py b/i2cserv/I2C_dummy.py
similarity index 94%
rename from i2c/I2C_dummy.py
rename to i2cserv/I2C_dummy.py
index ba39c1a5d6e1df962bc6f5e1eab79140cd5ec122..a085ae1eed655c14d45a6ca19687d78c16060659 100644
--- a/i2c/I2C_dummy.py
+++ b/i2cserv/I2C_dummy.py
@@ -17,7 +17,7 @@ def I2C1server(addr,data,reg=None,read=0):
            data[0]=0
        if reg: I2Ccounter+=1;
        I2Ccounter+=len(data)
-#       logging.debug(str(("I2C",addr,reg,data,read)))
+       logging.warn(str(("I2C",addr,reg,data,read)))
        return True
 
 def I2C4server(addr,data,reg=None,read=0):
diff --git a/i2c/I2Cswitch1.py b/i2cserv/I2Cswitch1.py
similarity index 100%
rename from i2c/I2Cswitch1.py
rename to i2cserv/I2Cswitch1.py
diff --git a/rcu/RCU.py b/i2cserv/RCU.py
similarity index 57%
rename from rcu/RCU.py
rename to i2cserv/RCU.py
index 98978660f16f68fa5f3d0a07de694fb1305b2e2d..b0678b8ccb7213ca7babe3c34f7eba40ea3941dd 100644
--- a/rcu/RCU.py
+++ b/i2cserv/RCU.py
@@ -1,10 +1,14 @@
-from . import Vars
+#from . import Vars
 import numpy as np
 import logging
 from .spibitbang1 import *
-import threading
+#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
@@ -26,7 +30,7 @@ def bytes2int(bts):
    return x;
 def int2bytes(i):
    b=[];
-   while i>255: 
+   while i>255:
         b=[i%256]+b;
         i>>=8;
    return [i]+b;
@@ -44,18 +48,80 @@ def bytes2strs(var,step,dtype):
     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):
+    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,Vars.RCU_storeReg],dtype='int')
+        self.previous   =np.zeros([number,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)
+        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]
 
@@ -75,6 +141,80 @@ class RCU1():
 #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
@@ -85,18 +225,20 @@ class RCU1():
         if Instr.type==Vars.DevType.Instr:
               #Execute instructions
               Iset=Instr.dev;
-              if len(Mask)==0:  Mask=Vars.RCU_mask.OPCW.get_value()
+              #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()
+##            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<<Vars.RCU_MPaddr.Switch[RCUi]
+                 if (Mask[RCUi]):
+                      mask|=1<<RCU_Switch[RCUi]
                       if RCU0<0: RCU0=RCUi;
             if RCU0<0: return; #Mask all zero
             self.SWcallback(mask)
@@ -124,8 +266,9 @@ class RCU1():
 #        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()
+        #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:
@@ -149,54 +292,54 @@ class RCU1():
 
         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:
-                logging.error("SPIbb Implemented")
-            else:
-                logging.error("Not Implemented")
 
-    def GetVarValueAll(self,V1,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<<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
+                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<<Vars.RCU_MPaddr.Switch[RCUi])
+                    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,var.devreg,var.width,var.bitoffset,value2)
-#                    print(value2)
-                    if (var.Scale!=0): value2[0]*=var.Scale;
+                    #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 V1.Vars[0].type==Vars.DevType.SPIbb:
+            elif devreg1.devtype[:3]=='spi':
               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):  
+            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<<Vars.RCU_MPaddr.Switch[RCUi])
+                    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
@@ -214,6 +357,8 @@ class RCU1():
             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)
@@ -221,7 +366,7 @@ class RCU1():
         def GetBit(RCUixx,dev,width,bitoffset,buffer=False):
             value=[0 for RCUi in range(self.N)]
             value2=[0]
-            if buffer: 
+            if buffer:
                 for RCUi in range(self.N):
                   self.GetI2Cbuffer(RCUi,dev,width,bitoffset,value2)
                   value[RCUi]=value2[0]
@@ -229,32 +374,20 @@ class RCU1():
             self.SWcallback(mask)
             self.SetI2CAddr(self,dev)
             for RCUi in range(self.N):
-                self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi])
+                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;
-        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")
+        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:
@@ -279,7 +412,7 @@ class RCU1():
         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: 
+        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
@@ -291,15 +424,15 @@ class RCU1():
         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): 
+        if (width!=l1*8) or (bitoffset>0):
           for i in range(len(value)):
-             value[i]=UnMask(value[i],width,bitoffset)      
+             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          
+#        return True
         l1=int(np.floor((width+bitoffset+7)/8))
 #        print(width,bitoffset,l1)
         makesinglevalue=((len(value)==1) and (l1>1));
@@ -318,9 +451,9 @@ class RCU1():
         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): 
+        if (width!=l1*8) or (bitoffset>0):
             for i in range(len(value)):
-              value[i]=UnMask(value[i],width,bitoffset)      
+              value[i]=UnMask(value[i],width,bitoffset)
         else: value[0]=value2[0]
         return True;
     def GetI2Cbit(self,RCUi,dev,pin):
@@ -350,9 +483,9 @@ class RCU1():
 #            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)      
+            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;
@@ -368,57 +501,35 @@ class RCU1():
         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)      
+        for i in range(len(value)):
+              value[i]=UnMask(value[i],width,bitoffset)
         return True;
 
 
-    def start(self,Q1):
-      def RCUthread(Q1):
+    def RCUthread(self,Qin):
          while True:
-           item = Q1.get()
+           item = Qin.get()
            if item is None: break;
-           self.statevar.set_value("busy");
-           self.SetVar(item)
-           if Q1.qsize()==0: self.statevar.set_value("ready");
+#           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")
 
-      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,AddVar):
-     self.statevar=AddVar("RCU_state_R","busy")
-     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)
+        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/clk/__init__.py b/i2cserv/__init__.py
similarity index 100%
rename from clk/__init__.py
rename to i2cserv/__init__.py
diff --git a/i2cserv/i2cthread.py b/i2cserv/i2cthread.py
new file mode 100644
index 0000000000000000000000000000000000000000..308c5a3815aae45c4c33b21bded791244fcd1ec2
--- /dev/null
+++ b/i2cserv/i2cthread.py
@@ -0,0 +1,50 @@
+#Start the correct I2C server connect to the pipes on a new process
+import logging
+from multiprocessing import Process
+
+from i2cserv import I2Cswitch1
+from i2cserv import I2C_dummy as I2C
+
+from i2cserv import RCU
+from i2cserv import CLK
+
+
+import yaml
+class AttrDict(object):
+    def __init__(self, dct):
+        self.dict = dct
+
+    def __repr__(self):
+        return repr(self.dict)
+
+    def __getattr__(self, attr):
+        try:
+            val = self.dict[attr]
+            if isinstance(val, dict):
+                val = AttrDict(val)
+            return val
+        except KeyError:
+            raise AttributeError
+
+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)
+
+def start(Qout,Qin,name):  
+        thread1 = Process(target=I2Cserver, args=(Qin,Qout,name))
+        thread1.start()
+        return thread1
+
+
diff --git a/rcu/spibitbang1.py b/i2cserv/spibitbang1.py
similarity index 83%
rename from rcu/spibitbang1.py
rename to i2cserv/spibitbang1.py
index ca8fd300bdb46cd1463318a9ea9b727d1c323580..7b5f4e6dbb93d80e427f529c82a9b974dc8379b7 100644
--- a/rcu/spibitbang1.py
+++ b/i2cserv/spibitbang1.py
@@ -78,30 +78,26 @@ def GetSPIbb(SetI2C,GetI2C,RCUi,dev,value):
         SetI2C(RCUi,SDIOdirdev,1,SDIOdirpin,[0]) #output
         return True;
 
-def GetSPIbb2(SetI2C,GetI2C,RCUi,devs,value):
-        ADC_reg_address=devs[0].Register_R
+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 dev in devs:
-             dev1=dev.Addr.devs[pintype.value]
-             pin1=dev.Addr.pins[pintype.value]
-             SetI2C(RCUi,dev1,1,pin1,[value],buffer=True) 
-           SetI2C(RCUi,dev1,1,pin1,[value]) 
+           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)
-           step=len(devs)
-           dev1=devs[0].Addr.devs[pintype.value]
-           pin1=devs[0].Addr.pins[pintype.value]
-           retvalue[0::step]=GetI2C(RCUi,dev1,1,pin1)
-           for i,dev in enumerate(devs[1:]):
-             dev1=dev.Addr.devs[pintype.value]
-             pin1=dev.Addr.pins[pintype.value]
-             retvalue[i+1::step]=GetI2C(RCUi,dev1,1,pin1,buffer=True)
+           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
            
-        CS=SPIBB_pins.CS
-        SDIO=SPIBB_pins.SDIO
-        CLK=SPIBB_pins.CLK
-        SDIOdir=SPIBB_pins.SDIOdir
+        CLK=0
+        SDIO=1
+        SDIOdir=2
+        CS=3
 
         logging.debug(str(("SPIbb get",ADC_reg_address)))
           
diff --git a/clk/spibitbang2.py b/i2cserv/spibitbang2.py
similarity index 100%
rename from clk/spibitbang2.py
rename to i2cserv/spibitbang2.py
diff --git a/i2c/__init__.py b/opcuaserv/__init__.py
similarity index 100%
rename from i2c/__init__.py
rename to opcuaserv/__init__.py
diff --git a/opcuaserv/i2client.py b/opcuaserv/i2client.py
new file mode 100644
index 0000000000000000000000000000000000000000..e644ecdcf988fc8a795963942ebbcf26d04022a2
--- /dev/null
+++ b/opcuaserv/i2client.py
@@ -0,0 +1,43 @@
+#This is the OPC-UA side of the pipes to I2Cserver
+
+from multiprocessing import Queue
+from queuetypes import *
+
+
+class i2client():
+    def __init__(self,name='RCU'):
+        self.Qin=Queue() 
+        self.Qout=Queue()
+        self.name=name;
+
+    def GetInfo(self):
+        return self.Qin,self.Qout,self.name
+
+    def stop(self):
+        self.Qout.put(None);
+        self.Qin.put(None);
+#        self.thread1.join();
+#        os.close(self.Output)
+#        self.Input.close()
+
+    def readvar(self,id1):
+        Data=OPCUAset(id1,InstType.varRead,[],[])
+        self.Qout.put(Data);
+
+    def setvar(self,id1,data=[],mask=[]):
+        Data=OPCUAset(id1,InstType.varSet,data,mask)
+        self.Qout.put(Data);
+
+    def callmethod(self,id1,mask=[]):
+        Data=OPCUAset(id1,InstType.method,[],[])
+        self.Qout.put(Data);
+
+    def data_waiting(self):
+        return (self.Qin.qsize()>0);
+
+    def readdata(self):
+        message=self.Qin.get()
+        if message is None: return None
+        return message.id,message.data,message.mask
+
+
diff --git a/opcuaserv.py b/opcuaserv/opcuaserv.py
similarity index 90%
rename from opcuaserv.py
rename to opcuaserv/opcuaserv.py
index f38b8acb5a4ced13f3e49bb6d45c1897de1de520..daa3cddd032508c6300deadce94409c870336b38 100644
--- a/opcuaserv.py
+++ b/opcuaserv/opcuaserv.py
@@ -8,7 +8,7 @@ from datetime import datetime;
 import logging
 #import Vars
 #import HWconf
-from pcctypes import *
+#from pcctypes import *
 
 Vars_R={}
 Vars_W={}
@@ -21,14 +21,15 @@ class SubHandler(object):
     def datachange_notification(self, node, val, data):
 #        print("Python: New data change event", node, val,data)
         if not(running): return
-        vname,myvar,VarD,Q1=Vars_W[node.nodeid.Identifier]
+        vname,myvar,v,reader=Vars_W[node.nodeid.Identifier]
 #        val=(val if isinstance(val, list) else [val] )
         logging.info(str(("Datachange callback",vname,val)))
 #        myvar2.Value.Value=val
 #        myvar2.SourceTimestamp = datetime.utcnow()
+        reader.setvar(v,val)
 
-        Inst=Instr(DevType.Var,VarD,len(val),val)
-        Q1.put(Inst)
+#        Inst=Instr(DevType.Var,VarD,len(val),val)
+#        Q1.put(Inst)
  #       P1.SetVarValue(vname,val)
         #readback
 #        if True:
@@ -46,7 +47,7 @@ class SubHandler(object):
 def CallMethod(ObjectID,name,Inst1,Q1):
         logging.info(str(("Callmethod",ObjectID,name)))
 #        Inst1=Vars.Instr(Vars.DevType.Instr,instrs,0,[])
-        Q1.put(Inst1)
+        Q1.callMethod(Inst1)
 
 #        P1.CallMethod(name,None)
 
@@ -58,18 +59,17 @@ def AddVar(name,value):
 def AddVarR(vname,varvalue2,v):
     myvar = PCCobj.add_variable(idx, vname, varvalue2)
     logging.info(str(("Variable added: ",vname,len(varvalue2))))
-    Vars_R[myvar.nodeid.Identifier]=[v.name,myvar.get_data_value(),varvalue2,v]
+    Vars_R[myvar.nodeid.Identifier]=[vname,myvar.get_data_value(),varvalue2,v]
     return myvar
 
 def AddVarW(vname,varvalue2,v,Q1):
     logging.info(str(("Variable added: ",vname)))#,'=',varvalue2)
     myvar2 = PCCobj.add_variable(idx, vname, varvalue2)
     myvar2.set_writable()
-    Vars_W[myvar2.nodeid.Identifier]=[v.name,myvar2.get_data_value(),v,Q1]
+    Vars_W[myvar2.nodeid.Identifier]=[vname,myvar2.get_data_value(),v,Q1]
     handle = sub.subscribe_data_change(myvar2)
     return myvar2
 
-
 def Addmethod(vname,v,Q1):
     myvar = PCCobj.add_method(idx, vname, lambda ObjectId,name=vname,inst=v,Q1=Q1 : CallMethod(ObjectId,name,inst,Q1), [],[] )
     logging.info(str(("AddMethod:",vname)))
diff --git a/opcuaserv/pypcc2.py b/opcuaserv/pypcc2.py
new file mode 100644
index 0000000000000000000000000000000000000000..ca0b4a21769f024112b41dda95589cfbce81b1b4
--- /dev/null
+++ b/opcuaserv/pypcc2.py
@@ -0,0 +1,59 @@
+import opcuaserv
+import threading
+import signal
+import sys
+import time
+#import Vars
+import logging
+import argparse
+from opcuaserv import i2client
+from opcuaserv import yamlreader
+
+def run(args):
+#RCUthread1=RCU.start(Q1)
+#CLKthread1=CLK.start(Q2)
+
+ RunTimer=True;
+ def TimerThread(RCU_I2C,RCU_conf):
+    V1=opcuaserv.AddVar("RCU_monitor_rate_RW",30)
+    cnt=0;#Count second ticks
+    while RunTimer:
+       time.sleep(1)
+       T1=V1.get_data_value().Value.Value
+       if T1==0:
+           continue;
+       cnt+=1;
+       if cnt>=T1:
+ #        if Q1.qsize()>3: continue;
+         cnt=0;
+ #        logging.debug(str(("I2C bytes=",I2C.I2Ccounter," Qlength=",Q1.qsize())))
+ #        RCU.Queue_Monitor(Q1)
+
+    logging.info("End Timer thread")
+
+#Timerthread1 = threading.Thread(target=TimerThread, args=(RCU_I2C,RCU_conf))
+#Timerthread1.start()
+
+# on SIGINT: stop thread(s) by adding None to instruction queue(s)
+ def signal_handler(sig, frame):
+#    logging.info('Stop RCU thread')
+#    Q1.put(None)
+#    Q2.put(None)
+#    logging.info('Stop timer thread')
+    global RunTimer; 
+    RunTimer=False
+ signal.signal(signal.SIGINT, signal_handler)
+
+
+# try:
+#Do nothing.
+ while RunTimer:
+    time.sleep(1)
+#    time.sleep(0.001)
+#    RCU_conf.getvar();#Todo use thread and blocking
+
+# finally:
+#        RCU_I2C.stop();
+#        RCUthread1.join()
+#        CLKthread1.join()
+#        Timerthread1.join()
diff --git a/opcuaserv/yamlreader.py b/opcuaserv/yamlreader.py
new file mode 100644
index 0000000000000000000000000000000000000000..91563dc1142c74016a73edbefaaf156c2b181c59
--- /dev/null
+++ b/opcuaserv/yamlreader.py
@@ -0,0 +1,191 @@
+import yaml
+import struct
+import time
+def Find(L,name,value):
+  for x in L:
+    if x[name]==value:
+        return x;
+  return False;
+
+def bytes2int(bts):
+   x=0;
+   for b in bts:
+     x=x*256+b;
+   return x;
+
+def int2bytes(i):
+   b=[];
+   while i>255: 
+        b=[i%256]+b;
+        i>>=8;
+   return [i]+b;
+
+
+class yamlreader():
+    def __init__(self,i2cserver,yamlfile='RCU'):
+        self.conf=yaml.load(open("config/"+yamlfile+'.yaml'))
+        for i,v in enumerate(self.conf['variables']):
+            v['id']=i
+        for i,v in enumerate(self.conf['methods']):
+            v['id']=i
+        self.server=i2cserver;
+
+    
+    def AddVars(self,AddVarR,AddVarW):
+     for v in self.conf['variables']:
+        print(v)
+        dim1=v.get('dim',1);
+        name=v.get('name');
+        datatype=v.get('dtype','integer')
+#        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   datatype in ['uint8','uint16','uint32','uint64']:  varvalue2=dim1*[0]
+        elif datatype=='double':    varvalue2=dim1*[0.0] 
+        elif datatype=='boolean':  varvalue2=dim1*[False] 
+        elif datatype=='string':   varvalue2=dim1*[""]
+#        print(len(varvalue2),varvalue2)
+        if v.get('rw') in ['ro','rw']:
+            var1=AddVarR(name+"_R",varvalue2,v['id'])
+            v['OPCR']=var1
+            print("Var added:"+name+"_R")
+            self.server.readvar(v['id'])
+            time.sleep(0.1);
+#            Inst=Vars.Instr(Vars.DevType.VarUpdate,v,dim2,varvalue2)
+#            Q1.put(Inst)
+
+        if v.get('rw') in ['wo','rw','variable']:
+            var1=AddVarW(name+"_RW",varvalue2,v['id'],self)
+            v['OPCW']=var1
+            print("Var added:"+name+"_RW")
+     for v in self.conf['variables']:
+        mask=v.get('mask');
+        if not(mask): continue;
+        mask=Find(self.conf['variables'],'name',mask)
+        if not(mask): continue;
+        mask=mask.get('OPCW',None)
+        if (mask==None): continue;
+        v['maskOPC']=mask
+
+    def AddMethod(self,Addmethod):
+      for v in self.conf['methods']:
+          if v.get('rw','')=='hidden': continue;
+          print(v)
+#        Inst1=Vars.Instr(Vars.DevType.Instr,v,0,[])
+          Addmethod(v['name'],v['id'],self)
+          mask=v.get('mask');
+          if not(mask): continue;
+          mask=Find(self.conf['variables'],'name',mask)
+          if not(mask): continue;
+          mask=mask.get('OPCW',None)
+          if (mask==None): continue;
+          v['maskOPC']=mask
+
+    def callMethod(self,id1):
+        v=self.conf['methods'][id1];
+        print("Method called!",v['name'])
+        mask=v.get('maskOPC',None);
+        mask=mask.get_value() if (mask!=None) else [];
+        self.server.callmethod(id1,mask) 
+
+    def setvar(self,id1,data=[]):
+        v=self.conf['variables'][id1];
+        if v['rw']=='variable': return;
+        mask=v.get('maskOPC',None);
+        mask=mask.get_value() if (mask!=None) else [];
+        print("M2:",mask)
+        dtype=v.get('dtype','integer');
+        width=(v.get('width',8)-1)//8+1
+        if (dtype=="double"): 
+                scale=v.get('scale',1.)
+                data=[int(d/scale) for d in data]
+        if (dtype=="boolean"): 
+                data2=bytearray(data*1);
+        elif (dtype in ['uint8','uint16','uint32','uint64','double']): 
+            if width<=1: 
+                data2=bytearray(data)
+            elif width==2:
+                data2 = struct.pack('>%sH' % len(data), *data)
+            elif width==3:
+                data2=bytearray()
+                for a in data: data2.extend(struct.pack('>L',a)[1:])
+            elif width==4:
+                data2 = struct.pack('>%sL' % len(data), *data)
+            elif width==8:
+                data2 = struct.pack('>%sQ' % len(data), *data)
+            else:
+                print("setvar",v['name']," unsupported width!",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");
+                return;
+        data2=[d for d in data2]
+        print("setvar ",v['name'],data2,mask);
+        self.server.setvar(id1,data2,mask) 
+
+    def getvar(self):
+#        if not(self.server.data_waiting()): return;
+#        print("getvar ...")
+        while True:
+#         while (self.server.data_waiting()):
+#           try:
+            item=self.server.readdata()
+            if item is None: break;
+            id1,data,mask=item; 
+            print("**getvar",id1,data,mask);
+            if len(data)==0: continue;
+#           except:
+#              print('finished')
+#              return;
+            self.OPCset(id1,data,mask);
+ 
+    def OPCset(self,id1,data,mask):
+        v=self.conf['variables'][id1];
+        dtype=v.get('dtype','integer');
+        width=(v.get('width',8)-1)//8+1
+        print("OPCset",width,data)
+        if dtype=="boolean": 
+                data2=[d==1 for d in data];
+        elif (dtype in ['uint8','uint16','uint32','uint64','double']): 
+            data=bytearray(data)
+            if width<=1: 
+                data2=[d for d in data]
+            elif width==2:
+                data2 = struct.unpack('>%sH' % (len(data)//2), data)
+            elif width==3:
+                data2 = [struct.unpack('>L' ,bytearray([0])+data[x*3:x*3+3])[0] for x in range(len(data)//3)]
+            elif width==4:
+                data2 = struct.unpack('>%sL' % (len(data)//4), data)
+            elif width==8:
+                data2 = struct.unpack('>%sQ' % (len(data)//8), data)
+            else:
+                print("OPCset",v['name']," unsupported width!",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");
+                return;
+        if dtype=="double": 
+                scale=float(v.get('scale',1.))
+                data2=[(d*scale) for d in data2]
+        data3=v['OPCR'].get_value();
+#        print("OPCset",v['name'],data3,mask)
+        if mask: #Only update masked values
+            step=len(data2)//len(mask)
+            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)
+        v['OPCR'].set_value(data3);
+
diff --git a/pcctypes.py b/pcctypes.py
index 56c4bc7da636ed670e6d4bfcfc69adda86a663d8..a980fdd5602787d7d6944ca80197b6b74b379ca3 100644
--- a/pcctypes.py
+++ b/pcctypes.py
@@ -1,8 +1,10 @@
+
 #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"); 
 
diff --git a/pypcc2.py b/pypcc2.py
index 4c873a2909dcd12b887880178b0738adfef8aec3..c0935e27d27a7b459a56600a096fb17c74fc6cb1 100644
--- a/pypcc2.py
+++ b/pypcc2.py
@@ -1,20 +1,14 @@
-import opcuaserv
-try:
- import queue
-except ImportError:
- import Queue as queue;
-from rcu import RCU
-from clk import CLK
-from i2c import I2Cswitch1
-import threading
-import signal
-import sys
-import time
-#import Vars
 import logging
 import argparse
-
-NRCU=32
+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
 
 parser = argparse.ArgumentParser()
 parser.add_argument("-s", "--simulator", help="Do not connect to I2c, but simulate behaviour.", action="store_true")
@@ -29,83 +23,59 @@ if not isinstance(loglevel_nr, int):
 #logging.basicConfig(level=loglevel_nr, format="%(asctime)s [%(levelname)8s] %(message)s")
 
 logging.basicConfig(level=loglevel_nr,format='%(asctime)s [%(levelname)-8s,%(filename)-20s:%(lineno)-3d] %(message)s')
-if args.simulator:
-    from i2c import I2C_dummy as I2C
-else:
-    from i2c import I2C
-#   from i2c import I2Cv2 as I2C
-
-#Queue used to pass instructions from opc-ua server to RCU
-Q1=queue.Queue() #RCUs
-Q2=queue.Queue() #CLK
-
-#Setup OPCUA server (running in its own thread)
-opcuaserv.InitServer(port=args.port)
-logging.info("OPC-UA Server started")   
-
-SW1=I2Cswitch1.I2Cswitch1(I2C.I2C1server)
-SW0=I2Cswitch1.I2Cswitch0(None) #Dummy switch as their is no switch on LTS
 
-RCU=RCU.RCU1(NRCU,I2C.I2C1server,SW1.SetChannel)
-RCU.AddVars(Q1,opcuaserv.AddVarR,opcuaserv.AddVarW,opcuaserv.AddVar)
-RCU.AddMethod(Q1,opcuaserv.Addmethod)
-RCU.load() #Load current register values from HW
 
-CLK=CLK.RCU1(1,I2C.I2C4server,SW0.SetChannel)
-CLK.AddVars(Q2,opcuaserv.AddVarR,opcuaserv.AddVarW)
-CLK.AddMethod(Q2,opcuaserv.Addmethod)
-CLK.load() #Load current register values from HW
+RunTimer=True;
+def signal_handler(sig, frame):
+    logging.warn('Stop signal received!')
+    global RunTimer; 
+    RunTimer=False
+signal.signal(signal.SIGINT, signal_handler)
 
-#logging.debug(str(("I2C bytes=",I2C.I2Ccounter)))
 
-if False:
-  opcuaserv.server.stop()
-  exit()
+#Initialise OPCUA server
+logging.info("Initialised OPC-UA Server")   
+opcuaserv.InitServer(port=args.port)
 
-RCUthread1=RCU.start(Q1)
-CLKthread1=CLK.start(Q2)
 
-RunTimer=True;
-def TimerThread(Q1,RCU):
-    V1=opcuaserv.AddVar("RCU_monitor_rate_RW",30)
-    cnt=0;#Count second ticks
-    while RunTimer:
-       time.sleep(1)
-       T1=V1.get_data_value().Value.Value
-       if T1==0:
-           continue;
-       cnt+=1;
-       if cnt>=T1:
-         if Q1.qsize()>3: continue;
-         cnt=0;
-         logging.debug(str(("I2C bytes=",I2C.I2Ccounter," Qlength=",Q1.qsize())))
-         RCU.Queue_Monitor(Q1,NRCU)
+logging.info("Start threads")   
+I2Cports=['RCU']
+#I2Cports=[]
+threads=[]
+I2Cclients=[]
+for name in I2Cports:
+    logging.info("Start I2C server process...")   
+    RCU_I2C=i2client.i2client(name=name)
+    thread1=i2cthread.start(*RCU_I2C.GetInfo())
+    threads.append(thread1)
+    I2Cclients.append(RCU_I2C)
 
-    logging.info("End Timer thread")
+    RCU_conf=yamlreader.yamlreader(RCU_I2C,yamlfile=name)
+    RCU_conf.AddVars(opcuaserv.AddVarR,opcuaserv.AddVarW)
+    RCU_conf.AddMethod(opcuaserv.Addmethod)
 
-Timerthread1 = threading.Thread(target=TimerThread, args=(Q1,RCU))
-Timerthread1.start()
+    logging.info("Start listing thread...")   
+    thread2=threading.Thread(target=RCU_conf.getvar); #Thread on OPC-UA side of pipe
+    thread2.start()
+    threads.append(thread2)
 
-# on SIGINT: stop thread(s) by adding None to instruction queue(s)
-def signal_handler(sig, frame):
-    logging.info('Stop RCU thread')
-    Q1.put(None)
-    Q2.put(None)
-    logging.info('Stop timer thread')
-    global RunTimer; 
-    RunTimer=False
-signal.signal(signal.SIGINT, signal_handler)
+if False:
+   opcuaserv.server.stop()
+   exit()
 
 time.sleep(1)
+logging.info("Start OPC-UA server")
 opcuaserv.start()
-
+ 
 try:
-#Do nothing.
  while RunTimer:
     time.sleep(1)
 finally:
-        logging.info("Stop OPC-UA server")
-        opcuaserv.server.stop()
-        RCUthread1.join()
-        CLKthread1.join()
-        Timerthread1.join()
+   logging.info("Stop OPC-UA server")
+   opcuaserv.server.stop()
+
+logging.info("Stop threads")
+for i2c in I2Cclients:
+    i2c.stop()
+for thread1 in threads:
+    thread1.join()
diff --git a/queuetypes.py b/queuetypes.py
new file mode 100644
index 0000000000000000000000000000000000000000..f10f7b1a4b52e651b5c7af3be933c592a53cb096
--- /dev/null
+++ b/queuetypes.py
@@ -0,0 +1,9 @@
+from enum import Enum
+from recordclass import recordclass
+
+class InstType (Enum):
+    varSet  = 0
+    varRead = 1
+    method  = 2
+
+OPCUAset=recordclass("OPCUAset","id type data mask")
diff --git a/rcu/HWconf.py b/rcu/HWconf.py
deleted file mode 100644
index 44b75df15fe7bc8caef46d1986a452fe154e5703..0000000000000000000000000000000000000000
--- a/rcu/HWconf.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#from collections import namedtuple
-#from enum import Enum
-from pcctypes import *
-#Mid plane address
-#MPaddr=namedtuple("MPaddr","nI2C I2C nSwitch Switch"); 
-RCU_MPaddr=MPaddr(1,[1],32,[0,1,2,3,4,5,6,7,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5])
-#RCU_MPaddr=MPaddr(1,[1],2,[0,1])
-#RCU_MPaddr=MPaddr(1,[1],1,[0])
-#CLK_MPaddr=MPaddr(1,[1],1,[7])
-
-#DevReg=namedtuple("DevReg","Addr Register_R Register_W store"); 
-#I2C:Addr=I2C addr (int)
-#BBdev: Addr=BBdev (pointer)
-
-#Control board switch
-#dev: TCA9548
-SW1_ch=DevReg(0x70,0,0,0) 
-#I2C IO-Expanders
-#Device: TCA9539
-RCU_IO1_OUT1=DevReg(0x75,0,2,1)
-RCU_IO1_OUT2=DevReg(0x75,1,3,2)
-RCU_IO1_CONF1=DevReg(0x75,6,6,3)
-RCU_IO1_CONF2=DevReg(0x75,7,7,4)
-#Device: TCA9539
-RCU_IO2_OUT1=DevReg(0x76,0,2,5)
-RCU_IO2_OUT2=DevReg(0x76,1,3,6)
-RCU_IO2_CONF1=DevReg(0x76,6,6,7)
-RCU_IO2_CONF2=DevReg(0x76,7,7,8)
-#Device: TCA6416
-RCU_IO3_OUT1=DevReg(0x20,0,2,9)
-RCU_IO3_OUT2=DevReg(0x20,1,3,10)
-RCU_IO3_CONF1=DevReg(0x20,6,6,11)
-RCU_IO3_CONF2=DevReg(0x20,7,7,12)
-
-RCU_storeReg=13; #Number of stored registers
-
-#I2C monitor ADC
-RCU_AN_Ch0=DevReg(0x14,0xB080,-1,0)
-RCU_AN_Ch1=DevReg(0x14,0xB880,-1,0)
-RCU_AN_Ch2=DevReg(0x14,0xB180,-1,0)
-#etc
-RCU_AN_Temp=DevReg(0x14,0xA0C0,-1,0)
-
-#HBA1
-RCU_HBA1=DevReg(0x41,0x10,0x10,1)
-RCU_HBA2=DevReg(0x42,0x10,0x10,2)
-RCU_HBA3=DevReg(0x43,0x10,0x10,3)
-
-
-
-RCU_ROM_ID =DevReg(0x50,0xfc,0xfc,0) #32 bit ID=4 bytes
-RCU_ROM_Ver=DevReg(0x50,0,0,0) #String
-
-#Bitbang devices
-#BBdev=namedtuple("BBdev","nPins devs pins addr")
-I2CBB_dth3=BBdev(3,[RCU_IO1_OUT1,RCU_IO2_OUT2,RCU_IO2_CONF2],[6,3,3],0x70); #SCL,SDIO,SDIOdir
-I2CBB_dth2=BBdev(3,[RCU_IO1_OUT2,RCU_IO2_OUT1,RCU_IO1_CONF1],[7,7,7],0x70);
-I2CBB_dth1=BBdev(3,[RCU_IO1_OUT2,RCU_IO2_OUT1,RCU_IO1_CONF1],[7,7,7],0x70);
-SPIBB_ADC1=BBdev(4,[RCU_IO3_OUT1,RCU_IO3_OUT1,RCU_IO3_CONF1,RCU_IO3_OUT2],[1,0,0,0],0) #CLK,SDIO,SDIOdir,CS
-SPIBB_ADC2=BBdev(4,[RCU_IO3_OUT1,RCU_IO3_OUT1,RCU_IO3_CONF1,RCU_IO3_OUT2],[3,2,2,1],0) #CLK,SDIO,SDIOdir,CS
-SPIBB_ADC3=BBdev(4,[RCU_IO3_OUT1,RCU_IO3_OUT1,RCU_IO3_CONF1,RCU_IO3_OUT2],[5,4,4,2],0) #CLK,SDIO,SDIOdir,CS
-
-#SPI ADC 
-#Dev: AD9683 
-RCU_ADC1_PLL_stat =DevReg(SPIBB_ADC1,0X0A,0X0A,0) # PLL locked status
-RCU_ADC1_PLL_enc =DevReg(SPIBB_ADC1,0X21,0X21,0) # PLL low encode
-RCU_ADC1_JESD_ctr =DevReg(SPIBB_ADC1,0X5F,0X5F,0) #JESD link control, ILAS mode
-RCU_ADC1_CML_level=DevReg(SPIBB_ADC1,0X15,0X15,0) #CML output adjust
-RCU_ADC1_SYNC_ctr =DevReg(SPIBB_ADC1,0X3A,0X3A,0) #SYNC / SYSREF control
-RCU_ADC1_update   =DevReg(SPIBB_ADC1,0XFF,0xFF,0)    # Global device update
-
-RCU_ADC2_PLL_stat =DevReg(SPIBB_ADC2,0X0A,0X0A,0) # PLL locked status
-RCU_ADC2_PLL_enc =DevReg(SPIBB_ADC2,0X21,0X21,0) # PLL low encode
-RCU_ADC2_JESD_ctr =DevReg(SPIBB_ADC2,0X5F,0X5F,0) #JESD link control, ILAS mode
-RCU_ADC2_CML_level=DevReg(SPIBB_ADC2,0X15,0X15,0) #CML output adjust
-RCU_ADC2_SYNC_ctr =DevReg(SPIBB_ADC2,0X3A,0X3A,0) #SYNC / SYSREF control
-RCU_ADC2_update   =DevReg(SPIBB_ADC2,0XFF,0xFF,0)    # Global device update
-
-RCU_ADC3_PLL_stat =DevReg(SPIBB_ADC3,0X0A,0X0A,0) # PLL locked status
-RCU_ADC3_PLL_enc =DevReg(SPIBB_ADC3,0X21,0X21,0) # PLL low encode
-RCU_ADC3_JESD_ctr =DevReg(SPIBB_ADC3,0X5F,0X5F,0) #JESD link control, ILAS mode
-RCU_ADC3_CML_level=DevReg(SPIBB_ADC3,0X15,0X15,0) #CML output adjust
-RCU_ADC3_SYNC_ctr =DevReg(SPIBB_ADC3,0X3A,0X3A,0) #SYNC / SYSREF control
-RCU_ADC3_update   =DevReg(SPIBB_ADC3,0XFF,0xFF,0)    # Global device update
-
-#I2C_dither 
-#Dev: SI4010
-RCU_Dth1_Freq =DevReg(I2CBB_dth1,0x1140,0x1141,0) ##TBC
-RCU_Dth1_Prop =DevReg(I2CBB_dth1,0x11  ,0x11,0) 
-RCU_Dth1_Start=DevReg(I2CBB_dth1,0x62  ,0x62,0) 
-RCU_Dth1_Stop =DevReg(I2CBB_dth1,0x67  ,0x67,0) 
-RCU_Dth2_Freq =DevReg(I2CBB_dth2,0x1140,0x1141,0) ##TBC
-RCU_Dth2_Prop =DevReg(I2CBB_dth2,0x11  ,0x11,0) 
-RCU_Dth2_Start=DevReg(I2CBB_dth2,0x62  ,0x62,0) 
-RCU_Dth2_Stop =DevReg(I2CBB_dth2,0x67  ,0x67,0) 
-RCU_Dth3_Freq =DevReg(I2CBB_dth3,0x1140,0x1141,0) ##TBC
-RCU_Dth3_Prop =DevReg(I2CBB_dth3,0x11  ,0x11,0) 
-RCU_Dth3_Start=DevReg(I2CBB_dth3,0x62  ,0x62,0) 
-RCU_Dth3_Stop =DevReg(I2CBB_dth3,0x67  ,0x67,0) 
-
-#class DevType(Enum):
-#    Var = 0
-#    I2C  = 1
-#    SPIbb= 2
-#    I2Cbb= 3
-#    Instr =4
-#    VarUpdate = 5
-#    Internal = 6
diff --git a/rcu/Vars.py b/rcu/Vars.py
deleted file mode 100644
index 7a14380585d0fab79f5dbe035b7eb8bd5d88e29d..0000000000000000000000000000000000000000
--- a/rcu/Vars.py
+++ /dev/null
@@ -1,198 +0,0 @@
-#from collections import namedtuple
-from recordclass import recordclass
-#from enum import Enum
-from .HWconf import *
-
-#OPCUA variables
-RCUmod=I2Cmodules.RCU
-
-#Var2dev=namedtuple("Var2dev","name MPaddr type devreg width bitoffset Scale")
-#VarArray=recordclass("VarArray","name nVars Vars RW type OPCR OPCW") #OPCR and OPCW linked at runtime
-RCU_att1= Var2dev("RCU_att1" ,RCUmod,DevType.I2C,RCU_IO1_OUT1,5 ,0,1)
-RCU_att2= Var2dev("RCU_att2" ,RCUmod,DevType.I2C,RCU_IO1_OUT2,5 ,0,1)
-RCU_att3= Var2dev("RCU_att3" ,RCUmod,DevType.I2C,RCU_IO2_OUT1,5 ,0,1)
-RCU_band1=Var2dev("RCU_band1",RCUmod,DevType.I2C,RCU_IO2_OUT2,2 ,0,1)
-RCU_band2=Var2dev("RCU_band2",RCUmod,DevType.I2C,RCU_IO2_OUT2,2 ,2,1)
-RCU_band3=Var2dev("RCU_band3",RCUmod,DevType.I2C,RCU_IO2_OUT2,2 ,4,1)
-RCU_led0= Var2dev("RCU_led0" ,RCUmod,DevType.I2C,RCU_IO2_OUT2,2 ,6,1)
-RCU_pwrd1=Var2dev("RCU_pwrd1",RCUmod,DevType.I2C,RCU_IO2_OUT1,1 ,6,1)
-RCU_temp1=Var2dev("RCU_temp1",RCUmod,DevType.I2C,RCU_AN_Temp ,23,0,4.21e-3)
-
-dummy=Var2dev("Dummy",RCUmod,DevType.Internal,None,8,0,1)
-
-
-Ant_mask=VarArray("Ant_mask"       ,3,[dummy,dummy,dummy]            ,RW.WriteOnly,datatype.dbool,3,None,None)
-RCU_att =VarArray("RCU_attenuator" ,3,[RCU_att1 ,RCU_att2 ,RCU_att3] ,RW.ReadWrite,datatype.dInt,3,None,None)
-RCU_band=VarArray("RCU_band"       ,3,[RCU_band1,RCU_band2,RCU_band3],RW.ReadWrite,datatype.dInt,3,None,None)
-
-RCU_mask=VarArray("RCU_mask"       ,1,[dummy]    ,RW.WriteOnly,datatype.dbool  ,1,None,None)
-RCU_temp=VarArray("RCU_temperature",1,[RCU_temp1],RW.ReadOnly ,datatype.dfloat,1,None,None)
-RCU_pwrd=VarArray("RCU_Pwr_dig"    ,1,[RCU_pwrd1],RW.ReadOnly ,datatype.dInt  ,1,None,None)
-RCU_LED =VarArray("RCU_LED0"       ,1,[RCU_led0] ,RW.ReadWrite,datatype.dInt  ,1,None,None)
-
-RCU_Dth3_freq=Var2dev("RCU_dth1_freq",RCUmod,DevType.I2Cbb,RCU_Dth3_Freq,32,0,1e-6)
-RCU_Dth2_freq=Var2dev("RCU_dth1_freq",RCUmod,DevType.I2Cbb,RCU_Dth2_Freq,32,0,1e-6)
-RCU_Dth1_freq=Var2dev("RCU_dth1_freq",RCUmod,DevType.I2Cbb,RCU_Dth1_Freq,32,0,1e-6)
-RCU_dth_freq=VarArray("RCU_dither_freq",3,[RCU_Dth1_freq,RCU_Dth2_freq,RCU_Dth3_freq],RW.ReadWrite,datatype.dfloat,3,None,None)
-
-HBA1_Delay=Var2dev("",RCUmod,DevType.HBA1,RCU_HBA1,5,2,1)
-HBA2_Delay=Var2dev("",RCUmod,DevType.HBA1,RCU_HBA2,5,2,1)
-HBA3_Delay=Var2dev("",RCUmod,DevType.HBA1,RCU_HBA3,5,2,1)
-HBA1_led  =Var2dev("",RCUmod,DevType.HBA1,RCU_HBA1,1,0,1)
-HBA2_led  =Var2dev("",RCUmod,DevType.HBA1,RCU_HBA2,1,0,1)
-HBA3_led  =Var2dev("",RCUmod,DevType.HBA1,RCU_HBA3,1,0,1)
-HBA1_pwr  =Var2dev("",RCUmod,DevType.HBA1,RCU_HBA1,1,7,1)
-HBA2_pwr  =Var2dev("",RCUmod,DevType.HBA1,RCU_HBA2,1,7,1)
-HBA3_pwr  =Var2dev("",RCUmod,DevType.HBA1,RCU_HBA3,1,7,1)
-HBA1_pwr2  =Var2dev("",RCUmod,DevType.HBA1,RCU_HBA1,1,1,1)
-HBA2_pwr2  =Var2dev("",RCUmod,DevType.HBA1,RCU_HBA2,1,1,1)
-HBA3_pwr2  =Var2dev("",RCUmod,DevType.HBA1,RCU_HBA3,1,1,1)
-HBA_Delay=VarArray("HBA_element_beamformer_delays",3,[HBA1_Delay,HBA2_Delay,HBA3_Delay],RW.ReadWrite,datatype.dInt,96,None,None)
-HBA_led  =VarArray("HBA_element_led"  ,3,[HBA1_led  ,HBA2_led  ,HBA3_led  ],RW.ReadWrite,datatype.dInt,96,None,None)
-HBA_pwr  =VarArray("HBA_element_pwr"  ,3,[HBA1_pwr  ,HBA2_pwr  ,HBA3_pwr  ],RW.ReadWrite,datatype.dInt,96,None,None)
-HBA_pwr2 =VarArray("HBA_element_pwr2"  ,3,[HBA1_pwr2  ,HBA2_pwr2  ,HBA3_pwr2  ],RW.ReadWrite,datatype.dInt,96,None,None)
-
-#RCU_ID0=Var2dev("",RCUmod,DevType.I2C,RCU_ROM,8,0,1)
-#RCU_ID=VarArray("RCU_ID",1,[RCU_ID0],RW.ReadOnly,datatype.dInt,4,None,None)
-
-RCU_ID0=Var2dev("",RCUmod,DevType.I2C,RCU_ROM_ID,32,0,1)
-RCU_ID=VarArray("RCU_ID",1,[RCU_ID0],RW.ReadOnly,datatype.dInt,1,None,None)
-RCU_Ver0=Var2dev("",RCUmod,DevType.I2C,RCU_ROM_Ver,7,0,1)
-RCU_VER=VarArray("RCU_version",1,[RCU_Ver0],RW.ReadOnly,datatype.dstring,10,None,None)
-
-
-RCU_uCV_ID    =VarArray("uC_ID  "  ,1,[Var2dev("",RCUmod,DevType.I2C,DevReg(0x40,0,0,0),8 ,0,1)],RW.ReadOnly,datatype.dInt,1,None,None)
-RCU_uCV_spd0  =VarArray("uC_spd0"  ,1,[Var2dev("",RCUmod,DevType.I2C,DevReg(0x40,1,1,0),8 ,0,1)],RW.ReadOnly,datatype.dInt,1,None,None)
-RCU_uCV_debug =VarArray("uC_debug" ,1,[Var2dev("",RCUmod,DevType.I2C,DevReg(0x40,2,2,0),8 ,0,1)],RW.ReadOnly,datatype.dInt,1,None,None)
-RCU_uCV_RXspd1=VarArray("uC_RXspd1",1,[Var2dev("",RCUmod,DevType.I2C,DevReg(0x40,3,3,0),8 ,0,1)],RW.ReadOnly,datatype.dInt,1,None,None)
-RCU_uCV_RXspd2=VarArray("uC_RXspd2",1,[Var2dev("",RCUmod,DevType.I2C,DevReg(0x40,4,4,0),8 ,0,1)],RW.ReadOnly,datatype.dInt,1,None,None)
-RCU_uCV_TXspd1=VarArray("uC_TXspd1",1,[Var2dev("",RCUmod,DevType.I2C,DevReg(0x40,6,6,0),8 ,0,1)],RW.ReadOnly,datatype.dInt,1,None,None)
-
-
-RCU_ADC1_lock=Var2dev("RCU_ADC1_lock",RCUmod,DevType.SPIbb,RCU_ADC1_PLL_stat,8,0,1)
-RCU_ADC2_lock=Var2dev("RCU_ADC2_lock",RCUmod,DevType.SPIbb,RCU_ADC2_PLL_stat,8,0,1)
-RCU_ADC3_lock=Var2dev("RCU_ADC3_lock",RCUmod,DevType.SPIbb,RCU_ADC3_PLL_stat,8,0,1)
-RCU_ADC_lock=VarArray("RCU_ADC_lock",3,[RCU_ADC1_lock,RCU_ADC2_lock,RCU_ADC3_lock],RW.ReadOnly,datatype.dInt,3,None,None)
-
-RCU_ADC1_SYNC=Var2dev("RCU_ADC1_SYNC",RCUmod,DevType.SPIbb,RCU_ADC1_SYNC_ctr,8,0,1)
-RCU_ADC2_SYNC=Var2dev("RCU_ADC2_SYNC",RCUmod,DevType.SPIbb,RCU_ADC2_SYNC_ctr,8,0,1)
-RCU_ADC3_SYNC=Var2dev("RCU_ADC3_SYNC",RCUmod,DevType.SPIbb,RCU_ADC3_SYNC_ctr,8,0,1)
-RCU_ADC_SYNC=VarArray("RCU_ADC_SYNC",3,[RCU_ADC1_SYNC,RCU_ADC2_SYNC,RCU_ADC3_SYNC],RW.ReadOnly,datatype.dInt,3,None,None)
-
-RCU_ADC1_JESD=Var2dev("RCU_ADC1_SYNC",RCUmod,DevType.SPIbb,RCU_ADC1_JESD_ctr,8,0,1)
-RCU_ADC2_JESD=Var2dev("RCU_ADC2_SYNC",RCUmod,DevType.SPIbb,RCU_ADC2_JESD_ctr,8,0,1)
-RCU_ADC3_JESD=Var2dev("RCU_ADC3_SYNC",RCUmod,DevType.SPIbb,RCU_ADC3_JESD_ctr,8,0,1)
-RCU_ADC_JESD=VarArray("RCU_ADC_JESD",3,[RCU_ADC1_JESD,RCU_ADC2_JESD,RCU_ADC3_JESD],RW.ReadOnly,datatype.dInt,3,None,None)
-
-RCU_ADC1_CML=Var2dev("RCU_ADC1_SYNC",RCUmod,DevType.SPIbb,RCU_ADC1_CML_level,8,0,1)
-RCU_ADC2_CML=Var2dev("RCU_ADC2_SYNC",RCUmod,DevType.SPIbb,RCU_ADC2_CML_level,8,0,1)
-RCU_ADC3_CML=Var2dev("RCU_ADC3_SYNC",RCUmod,DevType.SPIbb,RCU_ADC3_CML_level,8,0,1)
-RCU_ADC_CML=VarArray("RCU_ADC_CML",3,[RCU_ADC1_CML,RCU_ADC2_CML,RCU_ADC3_CML],RW.ReadOnly,datatype.dInt,3,None,None)
-
-
-RCU_IO1_1= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO1_OUT1,8,0,1)
-RCU_IO1_2= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO1_OUT2,8,0,1)
-#RCU_IO1_3= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO1_CONF1,8,0,1)
-#RCU_IO1_4= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO1_CONF2,8,0,1)
-#RCU_IO1=VarArray("RCU_IO1",3,[RCU_IO1_1,RCU_IO1_2,RCU_IO1_3],RW.ReadOnly,datatype.dInt,None,None)
-RCU_IO2_1= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO2_OUT1,8,0,1)
-RCU_IO2_2= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO2_OUT2,8,0,1)
-#RCU_IO2_3= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO2_CONF1,8,0,1)
-#RCU_IO2_4= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO2_CONF2,8,0,1)
-#RCU_IO2=VarArray("RCU_IO2",3,[RCU_IO2_1,RCU_IO2_2,RCU_IO2_3],RW.ReadOnly,datatype.dInt,None,None)
-RCU_IO3_1= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO3_OUT1,8,0,1)
-RCU_IO3_2= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO3_OUT2,8,0,1)
-#RCU_IO3_3= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO3_CONF1,8,0,1)
-#RCU_IO3_4= Var2dev("" ,RCUmod,DevType.I2C,RCU_IO3_CONF2,8,0,1)
-#RCU_IO3=VarArray("RCU_IO3",3,[RCU_IO3_1,RCU_IO3_2,RCU_IO3_3],RW.ReadOnly,datatype.dInt,None,None)
-
-RCU_OUT1=VarArray("RCU_OUT1",3,[RCU_IO1_1,RCU_IO2_1,RCU_IO3_1],RW.ReadOnly,datatype.dInt,3,None,None)
-RCU_OUT2=VarArray("RCU_OUT2",3,[RCU_IO1_2,RCU_IO2_2,RCU_IO3_2],RW.ReadOnly,datatype.dInt,3,None,None)
-#RCU_CNF1=VarArray("RCU_CONF1",3,[RCU_IO1_3,RCU_IO2_3,RCU_IO3_3],RW.ReadOnly,datatype.dInt,None,None)
-#RCU_CNF2=VarArray("RCU_CONF2",3,[RCU_IO1_4,RCU_IO2_4,RCU_IO3_4],RW.ReadOnly,datatype.dInt,None,None)
-
-#OPC_devvars=[RCU_mask,Ant_mask,RCU_att,RCU_band,RCU_temp,RCU_pwrd,RCU_LED,RCU_ID,RCU_VER,HBA_Delay,HBA_led]
-#OPC_devvars=[RCU_mask,Ant_mask,RCU_att,RCU_band,RCU_temp,RCU_pwrd,RCU_LED,RCU_ID,RCU_VER,HBA_Delay,HBA_led,RCU_uCV_ID]
-OPC_devvars=[RCU_mask,Ant_mask,RCU_att,RCU_band,RCU_temp,RCU_pwrd,RCU_LED,RCU_ADC_lock,RCU_ADC_SYNC,RCU_ADC_JESD,RCU_ADC_CML,RCU_OUT1,RCU_OUT2,RCU_ID,RCU_VER,HBA_Delay,HBA_led,HBA_pwr,HBA_pwr2,RCU_uCV_ID]
-#OPC_devvars=[RCU_mask,Ant_mask,RCU_att,RCU_band,RCU_temp,RCU_pwrd,RCU_LED,RCU_uCV_ID,RCU_uCV_spd0,RCU_uCV_RXspd1,RCU_uCV_RXspd2,RCU_uCV_TXspd1,RCU_uCV_debug ]#,HBA1_Pwr]#,RCU_CNF1,RCU_CNF2]
-#Instr=namedtuple("DevInstr","type dev nvalue value")
-#Instrs=namedtuple("Instr","name ninstr instr")
-
-#OPCUA methods
-
-RCU_init=Instrs("ReadRegisters",2,[
-   Instr(DevType.VarUpdate,RCU_OUT1,3,[0,0,0]),
-   Instr(DevType.VarUpdate,RCU_OUT2,3,[0,0,0])
-])
-
-ADC_on=Instrs("ADC_on",17,[
-   Instr(DevType.SPIbb,RCU_ADC1_JESD_ctr,1,[0x14]),
-   Instr(DevType.SPIbb,RCU_ADC1_CML_level,1,[0x7]),
-   Instr(DevType.SPIbb,RCU_ADC1_SYNC_ctr,1,[1]),
-   Instr(DevType.SPIbb,RCU_ADC1_PLL_enc,1,[0x8]),
-   Instr(DevType.SPIbb,RCU_ADC1_update,1,[1]),
-   Instr(DevType.Wait,0,0,[100]),
-   Instr(DevType.SPIbb,RCU_ADC2_JESD_ctr,1,[0x14]),
-   Instr(DevType.SPIbb,RCU_ADC2_CML_level,1,[0x7]),
-   Instr(DevType.SPIbb,RCU_ADC2_SYNC_ctr,1,[1]),
-   Instr(DevType.SPIbb,RCU_ADC2_PLL_enc,1,[0x8]),
-   Instr(DevType.SPIbb,RCU_ADC2_update,1,[1]),
-   Instr(DevType.Wait,0,0,[100]),
-   Instr(DevType.SPIbb,RCU_ADC3_JESD_ctr,1,[0x14]),
-   Instr(DevType.SPIbb,RCU_ADC3_CML_level,1,[0x7]),
-   Instr(DevType.SPIbb,RCU_ADC3_SYNC_ctr,1,[1]),
-   Instr(DevType.SPIbb,RCU_ADC3_PLL_enc,1,[0x8]),
-   Instr(DevType.SPIbb,RCU_ADC3_update,1,[1]),
-   Instr(DevType.Wait,0,0,[500]),
-   Instr(DevType.VarUpdate,RCU_ADC_SYNC,3,[0,0,0]),
-   Instr(DevType.VarUpdate,RCU_ADC_JESD,3,[0,0,0]),
-   Instr(DevType.VarUpdate,RCU_ADC_CML,3,[0,0,0]),
-   Instr(DevType.VarUpdate,RCU_ADC_lock,3,[0,0,0])
-])
-
-RCU_on=Instrs("RCU_on",20,[
-   Instr(DevType.I2C,RCU_IO2_CONF1,1,[0]),
-   Instr(DevType.I2C,RCU_IO2_CONF2,1,[0]),
-   Instr(DevType.I2C,RCU_IO2_OUT1,1,[0x4A]),
-   Instr(DevType.I2C,RCU_IO2_OUT2,1,[0x55]),
-   Instr(DevType.Wait,0,0,[300]),
-   Instr(DevType.I2C,RCU_IO3_CONF1,1,[0]),
-   Instr(DevType.I2C,RCU_IO3_CONF2,1,[0]),
-   Instr(DevType.I2C,RCU_IO1_CONF1,1,[0]),
-   Instr(DevType.I2C,RCU_IO1_CONF2,1,[0]),
-   Instr(DevType.I2C,RCU_IO3_OUT1,1,[0x15]),
-   Instr(DevType.I2C,RCU_IO3_OUT2,1,[0x47]),
-   Instr(DevType.I2C,RCU_IO1_OUT1,1,[0xCA]),
-   Instr(DevType.I2C,RCU_IO1_OUT2,1,[0xCA]),
-   Instr(DevType.Wait,0,0,[200]),
-   Instr(DevType.VarUpdate,RCU_att,3,[0,0,0]),
-   Instr(DevType.VarUpdate,RCU_pwrd,1,[0]),
-   Instr(DevType.VarUpdate,RCU_OUT1,3,[0,0,0]),
-   Instr(DevType.VarUpdate,RCU_OUT2,3,[0,0,0]),
-#   Instr(DevType.Wait,0,0,[300]),
-   Instr(DevType.Instr,ADC_on,0,[])
-])
-
-RCU_off=Instrs("RCU_off",1,[
-#   Instr(DevType.Var,RCU_mask,4,[1,1,1,1]),
-   Instr(DevType.Var,RCU_pwrd,32,[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),
-#   Instr(DevType.Var,RCU_mask,4,[0,0,0,0])
-])
-
-RCU_update=Instrs("RCU_update",11,[
-   Instr(DevType.VarUpdate,RCU_pwrd,1,[0]),
-   Instr(DevType.VarUpdate,RCU_OUT1,3,[0,0,0]),
-   Instr(DevType.VarUpdate,RCU_OUT2,3,[0,0,0]),
-   Instr(DevType.VarUpdate,RCU_ID,1,[0]),
-#   Instr(DevType.VarUpdate,RCU_VER,1,[0]*10),
-   Instr(DevType.VarUpdate,RCU_att,3,[0,0,0]),
-   Instr(DevType.VarUpdate,RCU_band,3,[0,0,0]),
-   Instr(DevType.VarUpdate,RCU_LED,1,[0]),
-   Instr(DevType.VarUpdate,RCU_ADC_SYNC,3,[0,0,0]),
-   Instr(DevType.VarUpdate,RCU_ADC_JESD,3,[0,0,0]),
-   Instr(DevType.VarUpdate,RCU_ADC_CML,3,[0,0,0]),
-   Instr(DevType.VarUpdate,RCU_ADC_lock,3,[0,0,0])
-])
-
-
-OPC_methods=[RCU_on,RCU_off,ADC_on,RCU_update]
diff --git a/rcu/__init__.py b/rcu/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000