From fb0880146df3bbfa604eefa325c6defa1475431a Mon Sep 17 00:00:00 2001
From: kruger <kruger@astron.nl>
Date: Wed, 28 Apr 2021 11:00:25 +0200
Subject: [PATCH] CLK update

---
 config/CLK.yaml         | 110 ++++++++++++++++----
 i2cserv/i2c_array.py    | 146 ++-------------------------
 i2cserv/i2c_dev.py      | 217 ++++++++++++++++++++++++++++++++++++++++
 i2cserv/spibitbang2.py  | 109 +++++++++++---------
 opcuaserv/opcuaserv.py  |   2 +-
 opcuaserv/yamlreader.py |   3 +
 testCLK.py              |  29 ++----
 yamlconfig.py           |  24 +++--
 8 files changed, 408 insertions(+), 232 deletions(-)
 create mode 100644 i2cserv/i2c_dev.py

diff --git a/config/CLK.yaml b/config/CLK.yaml
index 00eaa28..6da59dc 100644
--- a/config/CLK.yaml
+++ b/config/CLK.yaml
@@ -6,40 +6,29 @@ drivers:
    type: i2c
    parameters: [1] #I2C port number
  - name: I2C_CLK
-   type: i2c_array #I2C devices
+   type: i2c_dev #I2C devices
    parent: I2C
-   parameters:  [0,0] #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]
+   devreg: [IO1.GPIO1,IO1.GPIO1,IO1.GPIO1,IO1.GPIO1]
    parameters: [4,7,5,6]
 
 #This is the I2C devices in the RCU
 device_registers:
- - name: IO
-   dim: 3
+ - name: IO1
    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
@@ -47,14 +36,95 @@ device_registers:
     - name: PLL_stat
       description: PLL locked status
       address: 0x0
+    - {name: r3, address: 0x03}
+    - {name: r5, address: 0x05}
+    - {name: r6, address: 0x06}
 
 
 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
+  - name: CLK_I2C_STATUS
+    driver: I2C_CLK
+    rw:  variable #server RW variable, not linked to IO
+    dtype: boolean
+    debug: True
+
+  - name: CLK_Enable_PWR
+    description: Power enabled
+    rw:  ro
+    dtype: boolean
+    driver: I2C_CLK
+    devreg:  IO1.GPIO1
+    bitoffset: 1
+    width: 1
+
+  - name: CLK_PLL_locked
+    description: First status pin give lock status
+    rw:  ro
+    dtype: boolean
+    monitor: true
+    driver: I2C_CLK
+    devreg:  IO1.GPIO1
+    bitoffset: 2
+    width: 1
+
+  - name: CLK_PLL_error
+    description: Second status pin give error
+    rw:  ro
+    dtype: boolean
+    driver: I2C_CLK
+    devreg:  IO1.GPIO1
+    bitoffset: 3
+    width: 1
+
+  - name: CLK_PLL_locked_SPI
+    description: 0x81=locked
+    driver: I2C_CLK
+    devreg:  PLL.PLL_stat
+    width: 8
+    rw:  ro
+    dtype: uint8
+    debug: True
+
+  - name: [CLK_PLL_r3,CLK_PLL_r5,CLK_PLL_r6]
+    driver: I2C_CLK
+    devreg:  [PLL.r3,PLL.r5,PLL.r6]
+    width: 8
+    rw:  ro
+    dtype: uint8
+    debug: True
+
 
 methods:
-  - name: CLK_on
\ No newline at end of file
+  - name: CLK_on  
+    driver: I2C_CLK
+    instructions:   
+     - IO1.CONF1: 0x2C #0010 1100 PPS/PWR output, SCLK,CS,SDI
+     - IO1.GPIO1: 0x42 #0100 0010 high:PWR enable, CS
+     - CLK_Enable_PWR: Update
+
+#    - WAIT: 100         #ms to wait before checking lock
+#     - CLK_PLL_setup: 0
+#   - WAIT: 100         #ms to wait before checking lock
+#    - CLK_PLL_locked: Update
+
+  - name: CLK_PLL_setup  
+    driver: I2C_CLK
+    instructions:   
+#   - PLL.0x03: 0x08 #Set power, this is default
+    - PLL.0x05: 0x17 #was 97, set lock time
+    - PLL.0x06: 0x10
+
+    - PLL.0x07: 0x04 #Stop R divider
+    - PLL.0x08: 0x01 #Set R divider
+    - PLL.0x07: 0x00 #Start R divider
+
+    - PLL.0x09: 0x10 #Stop N divider
+    - PLL.0x0A: 0x14 #Set N divider=20, 200MHz/20=10MHz = input clock
+    - PLL.0x09: 0x00 #Start N divider
+
+    - PLL.0x0D: 0x01 #Divider output 1=1 
+    - PLL.0x0F: 0x01 #Divider output 2=1
+    - PLL.0x11: 0x01 #Divider output 3=1
+    - PLL.0x13: 0x01 #Divider output 4=1
+
+ 
diff --git a/i2cserv/i2c_array.py b/i2cserv/i2c_array.py
index b14c95e..db157cb 100644
--- a/i2cserv/i2c_array.py
+++ b/i2cserv/i2c_array.py
@@ -3,87 +3,17 @@ import logging
 from .spibitbang1 import spibitbang1
 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
+from .i2c_dev import *
 
 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)
+              Step2=V1.get('dim',1)*((V1.get('width',8)+7)//8)//Step #int(V1.size/V1.nVars)
               logging.debug(str(("GetStep",Step,Step2)));
               return Step,Step2
 
 
-class i2c_array(hwdev):
+class i2c_array(i2c_dev):
     def __init__(self,config):
         hwdev.__init__(self,config);
 #        self.Qout=Qout;
@@ -98,58 +28,11 @@ class i2c_array(hwdev):
 #        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,mask2=self.SetGetVarValueMask(var1,data,mask);
-#       if len(mask)==len(mask2): mask[:]=mask2[:];
-#       elif len(mask)==0: (mask.append(x) for x in mask2);
-       Data=OPCUAset(varid,InstType.varSet,data,mask2)
-       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,mask2=self.GetVarValueMask(var1,mask);
-#      if len(mask)==len(mask2): mask[:]=mask2[:];
-#      elif len(mask)==0: (mask.append(x) for x in mask2);
-      Data=OPCUAset(varid,InstType.varSet,data,mask2)
-      return [Data]
+      return i2c_dev.OPCUAReadVariable(self,varid,var1,mask)
 
-#    def OPCUAcallMethod(self,var1,data,mask):
-#       print("Call Method",var1)
-    
-    def i2csetget(self,*args,**kwargs):
-       return self.conf['parentcls'].i2csetget(*args,**kwargs)
     
-    def SetSwitch(self,RCUi):
-        self.conf['parentcls'].SetSW1(self.RCU_Switch1[RCUi]);
-
     def SetSwitchMask(self,mask):
         m=0;
         for RCUi in range(self.N):
@@ -244,19 +127,15 @@ class i2c_array(hwdev):
 
     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)))
+            logging.debug(str(("RCU1 Set ",self.RCUi,devreg['addr'],value)))
             #self.parentcls.SetChannel(1<<RCU_Switch[RCUi]);
             if devreg['store']:
-                storearray=self.getstorearray(devreg,len(value));
+                storearray=self.getstorearray(devreg);
                 previous=storearray[self.RCUi];
-                if (len(value)>1) and (isinstance(previous,list)) and (len(previous)==len(value)):
-                  for x in range(len(value)):
-                    value[x]=ApplyMask(value[x],width,bitoffset,previous[x]);
-                  storearray[self.RCUi]=value[:]
-                else:
-                  value[0]=ApplyMask(value[0],width,bitoffset,previous);
-                  storearray[self.RCUi]=value[0]
-                logging.debug(str(("Stored value:",value,"previous",previous)))
+                for x in range(len(value)):
+                  value[x]=ApplyMask(value[x],width,bitoffset,previous);
+                storearray[self.RCUi]=value[0]
+                logging.debug("Stored value:"+str(value[0]))
             #  devreg['drivercls'].i2csetget
             return devreg['drivercls'].i2csetget(devreg['addr'],value,reg=devreg['register_W'])
 
@@ -281,10 +160,7 @@ class i2c_array(hwdev):
         value[:]=value2[:];
         if devreg['store']:
              storearray=self.getstorearray(devreg,len(value));
-             if len(value)==1:
-                storearray[self.RCUi]=value[0]
-             else:
-                storearray[self.RCUi]=value[:]
+             storearray[self.RCUi]=value[:]
              logging.debug(str(("Store buffer",self.RCUi,value[0])))
  #            print("Stored values:",self.getstorearray(devreg))
         if (width!=l1*8) or (bitoffset>0):
diff --git a/i2cserv/i2c_dev.py b/i2cserv/i2c_dev.py
new file mode 100644
index 0000000..36f1ada
--- /dev/null
+++ b/i2cserv/i2c_dev.py
@@ -0,0 +1,217 @@
+import numpy as np
+import logging
+from .spibitbang1 import spibitbang1
+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.get('dim',1)*((V1.get('width',8)+7)//8)//Step #int(V1.size/V1.nVars)
+              logging.debug(str(("GetStep",Step,Step2)));
+              return Step,Step2
+
+
+class i2c_dev(hwdev):
+    def __init__(self,config):
+        hwdev.__init__(self,config);
+
+    def OPCUASetVariable(self,varid,var1,data,mask):
+       if var1['rw']=='variable': return;
+       logging.info(str(("Set Var",var1['name'],data,mask)))
+       data,mask2=self.SetGetVarValueMask(var1,data,mask);
+#       if len(mask)==len(mask2): mask[:]=mask2[:];
+#       elif len(mask)==0: (mask.append(x) for x in mask2);
+       Data=OPCUAset(varid,InstType.varSet,data,mask2)
+       return [Data]
+
+    def OPCUAReadVariable(self,varid,var1,mask):
+      logging.info(str(("Read Var",var1['name'],mask)))
+      #data=self.GetVarValueAll(var1)
+      #else:             
+      data,mask2=self.GetVarValueMask(var1,mask);
+#      if len(mask)==len(mask2): mask[:]=mask2[:];
+#      elif len(mask)==0: (mask.append(x) for x in mask2);
+      Data=OPCUAset(varid,InstType.varSet,data,mask2)
+      return [Data]
+
+#    def OPCUAcallMethod(self,var1,data,mask):
+#       print("Call Method",var1)
+    
+    def i2csetget(self,*args,**kwargs):
+       self.conf['parentcls'].i2csetget(*args,**kwargs)
+    
+    def SetSwitch(self,RCUi):
+        self.conf['parentcls'].SetSW1(self.RCU_Switch1[RCUi]);
+
+    def SetGetVarValueMask(self,var1,data,mask):
+        Step=(len(var1['devreg']) if isinstance(var1['devreg'],list) else 1)
+        value1=[0]*Step
+        if not(len(data)==Step):
+            print("Check data length!");
+            return;
+        if (len(mask)==1):
+          mask=[mask[0] for x in range(Step)]
+        if (len(mask)==0):
+          mask=[True for x in range(Step)]
+        if not(len(mask)==Step):
+            print("Check mask length!");
+            return;
+        for Vari in range(Step):
+                if not(mask[Vari]): continue
+                i0=(Vari)*Step
+                i1=(Vari+1)*Step
+                devreg=var1['devreg'][Vari];
+                width=var1.get('width',8)
+                bitoffset=GetField(var1,'bitoffset',Vari,0)
+                mask[Vari]=self.SetVarValue(devreg,width,bitoffset,data[i0:i1])
+                if not(mask[Vari]): continue
+                value2=value1[i0:i1]
+                mask[Vari]=self.GetVarValue(devreg,width,bitoffset,value2)
+                value1[i0:i1]=value2
+        return value1,mask
+
+
+    def GetVarValueMask(self,var1,mask):
+        Step=(len(var1['devreg']) if isinstance(var1['devreg'],list) else 1)
+        value1=[0]*Step;
+        if (len(mask)==1):
+          mask=[mask[0] for x in range(Step)]
+        if (len(mask)==0):
+          mask=[True for x in range(Step)]
+        if not(len(mask)==Step):
+            print("Check mask length!");
+            return;
+        for Vari in range(Step):
+                if not(mask[Vari]): continue
+                i0=( Vari)*Step
+                i1=(Vari+1)*Step
+                devreg=var1['devreg'][Vari];
+                width=var1.get('width',8)
+                bitoffset=GetField(var1,'bitoffset',Vari,0)
+                value2=value1[i0:i1]
+                mask[Vari]=self.GetVarValue(devreg,width,bitoffset,value2)
+                value1[i0:i1]=value2
+        return value1,mask
+
+
+    def getstoreval(self,devreg):
+          storeval=devreg.get('storeval')
+          if not(storeval):
+                devreg['storeval']=0;
+                storeval=devreg.get('storeval');
+          return storeval;
+
+    def Setdevreg(self,devreg,value,mask=[]):
+#        if devreg.get('store'): logging.debug("Stored")
+#        print(devreg['store'])
+        if devreg.get('store'):
+           devreg['storeval']=value[0];
+        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(("I2C Set ",devreg['addr'],value)))
+            #self.parentcls.SetChannel(1<<RCU_Switch[RCUi]);
+            if devreg['store']:
+                previous=self.getstoreval(devreg);
+                for x in range(len(value)):
+                  value[x]=ApplyMask(value[x],width,bitoffset,previous);
+                devreg['storeval']=value[0];
+                logging.debug("Stored value:"+str(value[0]))
+            #  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 ",devreg['addr'],value)))
+        callback=devreg['drivercls'].i2csetget;
+        value2=value
+        reg=devreg['register_R']
+        if not(callback(devreg['addr'],value2,reg=reg,read=1)): return False;
+        if value2[0] is None:  return False
+        value[:]=value2[:];
+        if devreg['store']:
+             devreg['storeval']=value[0];
+        l1=int(np.floor((width+bitoffset+7)/8))
+        if (width!=l1*8) or (bitoffset>0):
+            if (width<8):
+              for i in range(len(value)):
+                value[i]=UnMask(value[i],width,bitoffset)
+            else:
+                value[0]=UnMask(value[0],width-(l1-1)*8,bitoffset)
+        else: value[0]=value2[0]
+        return True;
+
diff --git a/i2cserv/spibitbang2.py b/i2cserv/spibitbang2.py
index d312d5b..0dedef8 100644
--- a/i2cserv/spibitbang2.py
+++ b/i2cserv/spibitbang2.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,64 +9,74 @@ class SPIBB_pins(Enum):
     SDO = 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.SDO.value]
-        SDOpin=dev.Addr.pins[SPIBB_pins.SDO.value]
-        SDIdev=dev.Addr.devs[SPIBB_pins.SDI.value]
-        SDIpin=dev.Addr.pins[SPIBB_pins.SDI.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)))
-
-#          dev_rw    = 0x00 # 0 for write, 1 for read
-#          data2 =  ( reg_address << 9 ) + ( dev_rw << 8 ) + value[0]
-        data2 = (  ADC_address << 9 ) + value[0]
-          
+
+class spibitbang2(hwdev):
+  def __init__(self,config):
+    hwdev.__init__(self,config)
+
+  def i2csetget(self,addr,data,reg=None,read=0):
+    if read==0: return self.SetSPIbb(reg,data)
+    elif read==1: return self.GetSPIbb(reg,data)
+    else: logging.warn("Not implemented!")
+    return False;
+
+  def SetSPIbb(self,address,value):
+         
+        CSdev=self.conf['devreg'][SPIBB_pins.CS.value]
+        CSpin=self.conf['parameters'][SPIBB_pins.CS.value]
+        SDIdev=self.conf['devreg'][SPIBB_pins.SDI.value]
+        SDIpin=self.conf['parameters'][SPIBB_pins.SDI.value]
+        CLKdev=self.conf['devreg'][SPIBB_pins.CLK.value]
+        CLKpin=self.conf['parameters'][SPIBB_pins.CLK.value]
+
+        logging.info(str(("SPIbb2 set",address,value)))
+
+        data2 = (  address << 9 ) + value[0]
+        SetI2C=self.conf['parentcls'].SetVarValue
+
         bit_array = "{0:{fill}16b}".format(data2, fill='0')
       #    print(bit_array)
-        SetI2C(RCUi,CSdev,1,CSpin,[1]) #disable
-        SetI2C(RCUi,CSdev,1,CSpin,[0]) #enable
+        SetI2C(CSdev,1,CSpin,[1]) #disable
+        SetI2C(CSdev,1,CSpin,[0]) #enable
         for bit in bit_array:
-              SetI2C(RCUi,CLKdev,1,CLKpin,[0]) 
-              SetI2C(RCUi,SDIdev,1,SDIpin,[int(bit)]) 
-              SetI2C(RCUi,CLKdev,1,CLKpin,[1]) 
-        SetI2C(RCUi,CLKdev,1,CLKpin,[0])#Why? 
-        SetI2C(RCUi,CLKdev,1,CLKpin,[1]) 
-        SetI2C(RCUi,CSdev,1,CSpin,[1]) #disable
+              SetI2C(CLKdev,1,CLKpin,[0]) 
+              SetI2C(SDIdev,1,SDIpin,[int(bit)]) 
+              SetI2C(CLKdev,1,CLKpin,[1]) 
+        SetI2C(CLKdev,1,CLKpin,[0])#Why? 
+        SetI2C(CLKdev,1,CLKpin,[1]) 
+        SetI2C(CSdev,1,CSpin,[1]) #disable
      #   SetI2C(RCUi,SDIdev,1,SDIpin,[1]) #high when finished
         return True;
+  
+  def GetSPIbb(self,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.SDO.value]
+        SDOpin=self.conf['parameters'][SPIBB_pins.SDO.value]
+        SDIdev=self.conf['devreg'][SPIBB_pins.SDI.value]
+        SDIpin=self.conf['parameters'][SPIBB_pins.SDI.value]
+        CLKdev=self.conf['devreg'][SPIBB_pins.CLK.value]
+        CLKpin=self.conf['parameters'][SPIBB_pins.CLK.value]
+
+
+        logging.info(str(("SPIbb2 get",reg_address)))
+        SetI2C=self.conf['parentcls'].SetVarValue
+        GetI2C=self.conf['parentcls'].GetVarValue
 
-def GetSPIbb(SetI2C,GetI2C,RCUi,dev,value):
-        ADC_reg_address=dev.Register_R
-        CSdev=dev.Addr.devs[SPIBB_pins.CS.value]
-        CSpin=dev.Addr.pins[SPIBB_pins.CS.value]
-        SDOdev=dev.Addr.devs[SPIBB_pins.SDO.value]
-        SDOpin=dev.Addr.pins[SPIBB_pins.SDO.value]
-        SDIdev=dev.Addr.devs[SPIBB_pins.SDI.value]
-        SDIpin=dev.Addr.pins[SPIBB_pins.SDI.value]
-        CLKdev=dev.Addr.devs[SPIBB_pins.CLK.value]
-        CLKpin=dev.Addr.pins[SPIBB_pins.CLK.value]
-
-        logging.info(str(("SPIbb get",ADC_reg_address)))
         ADC_bytes = 0x00
         #          ADC_rw    = 0x01 # 0 for write, 1 for read
-        data =  (ADC_reg_address << 1) + 1 #was 7??
+        data =  (reg_address << 1) + 1 #was 7??
           
-        SetI2C(RCUi,CSdev,1,CSpin,[1]) #disable
-        SetI2C(RCUi,CSdev,1,CSpin,[0]) #enable
+        SetI2C(CSdev,1,CSpin,[1]) #disable
+        SetI2C(CSdev,1,CSpin,[0]) #enable
 
 
         bit_array = "{0:{fill}8b}".format(data, fill='0')
         for bit in bit_array:
-              SetI2C(RCUi,SDIdev,1,SDIpin,[int(bit)]) 
-              SetI2C(RCUi,CLKdev,1,CLKpin,[0]) 
-              SetI2C(RCUi,CLKdev,1,CLKpin,[1]) 
+              SetI2C(SDIdev,1,SDIpin,[int(bit)]) 
+              SetI2C(CLKdev,1,CLKpin,[0]) 
+              SetI2C(CLKdev,1,CLKpin,[1]) 
 
-     #   SetI2C(RCUi,SDIdev,1,SDIpin,[1]) #high when finished
 
           #    print("read byte")
         a=[0]
@@ -73,12 +84,12 @@ def GetSPIbb(SetI2C,GetI2C,RCUi,dev,value):
         ret_value=[0]
         for i in range(N): value[i]=0
         for cnt in range(8*(ADC_bytes+1)):
-              SetI2C(RCUi,CLKdev,1,CLKpin,[0]) 
-              SetI2C(RCUi,CLKdev,1,CLKpin,[1])  #read after rising
-              GetI2C(RCUi,SDOdev,1,SDOpin,ret_value) 
+              SetI2C(CLKdev,1,CLKpin,[0]) 
+              SetI2C(CLKdev,1,CLKpin,[1])  #read after rising
+              GetI2C(SDOdev,1,SDOpin,ret_value) 
               for i in range(N): value[i]=(value[i]<<1)+ ret_value[i]
-        SetI2C(RCUi,CLKdev,1,CLKpin,[0]) 
-        SetI2C(RCUi,CSdev,1,CSpin,[1]) #disable
+        SetI2C(CLKdev,1,CLKpin,[0]) 
+        SetI2C(CSdev,1,CSpin,[1]) #disable
         return True;
 
 
diff --git a/opcuaserv/opcuaserv.py b/opcuaserv/opcuaserv.py
index 9ce7c06..63763e8 100644
--- a/opcuaserv/opcuaserv.py
+++ b/opcuaserv/opcuaserv.py
@@ -59,7 +59,7 @@ def AddVar(name,value):
 def AddVarR(vname,varvalue2,v,debug):
     obj=(DEBUGobj if debug else PCCobj) 
     myvar = obj.add_variable(idx, vname, varvalue2)
-    logging.info(str(("Variable added: ",vname,len(varvalue2))))
+    logging.info(str(("Variable added: ",vname,(len(varvalue2) if isinstance(varvalue2,list) else ''))))
     Vars_R[myvar.nodeid.Identifier]=[vname,myvar.get_data_value(),varvalue2,v]
     return myvar
 
diff --git a/opcuaserv/yamlreader.py b/opcuaserv/yamlreader.py
index 7b8e259..cd4b6a8 100644
--- a/opcuaserv/yamlreader.py
+++ b/opcuaserv/yamlreader.py
@@ -41,6 +41,7 @@ class yamlreader(yamlconfig):
         elif datatype=='double':    varvalue2=dim1*[0.0] 
         elif datatype=='boolean':  varvalue2=dim1*[False] 
         elif datatype=='string':   varvalue2=dim1*[""]
+        if len(varvalue2)==1: varvalue2=varvalue2[0];
 #        print(len(varvalue2),varvalue2)
         if v.get('rw') in ['ro','rw']:
             var1=AddVarR(name+"_R",varvalue2,v['id'],v.get('debug'))
@@ -93,6 +94,7 @@ class yamlreader(yamlconfig):
 #        print("M2:",mask)
         dtype=v.get('dtype','integer');
         width=(v.get('width',8)-1)//8+1
+        if not(isinstance(data,list)): data=[data];
         if (dtype=="double"): 
                 scale=v.get('scale',1.)
                 data=[int(d/scale) for d in data]
@@ -181,6 +183,7 @@ class yamlreader(yamlconfig):
                 if mask[i//step]: data3[i]=data2[i]
         else:
             data3=data2;
+        if len(data3)==1: data3=data3[0];
         logging.info(str(("OPCset",v['name'],data3)))
         v['OPCR'].set_value(data3);
 
diff --git a/testCLK.py b/testCLK.py
index 3927325..3bb0954 100644
--- a/testCLK.py
+++ b/testCLK.py
@@ -11,7 +11,7 @@ import sys
 import signal
 from yamlconfig import Find;
 
-logging.basicConfig(level="INFO",format='%(asctime)s [%(levelname)-8s,%(filename)-20s:%(lineno)-3d] %(message)s')
+logging.basicConfig(level="DEBUG",format='%(asctime)s [%(levelname)-8s,%(filename)-20s:%(lineno)-3d] %(message)s')
 
 RunTimer=True;
 #def signal_handler(sig, frame):
@@ -32,29 +32,16 @@ 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.getvarid('CLK_PLL_locked_SPI')
+var1=RCU_conf.getvarid('CLK_PLL_r3')
+RCU_I2C.readvar(var1,[])
 
-var1=RCU_conf.getmethodid('RCU_on');
-N=32;
-mask=[i<2 for i in range(N)];
-RCU_I2C.callmethod(var1,mask)
 
 
+#var1=RCU_conf.getmethodid('CLK_on');
+var1=RCU_conf.getmethodid('CLK_PLL_setup');
+#RCU_I2C.callmethod(var1,[])
+
 time.sleep(2);
 
 while RCU_I2C.data_waiting():
diff --git a/yamlconfig.py b/yamlconfig.py
index 7dd994a..521fc82 100644
--- a/yamlconfig.py
+++ b/yamlconfig.py
@@ -67,19 +67,31 @@ class yamlconfig():
                 N-=1;
 
     def getdevreg(self,name):
-        try:
+#        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]))
-          logging.debug("New devreg!")
+          logging.debug("New devreg! %s",str((name2)))
           if len(name2)==2:
-              return {"addr":str2int(name2[0]),"register_R":str2int(name2[1]),"register_W":str2int(name2[1])}
+              dev1=Find(self.conf['device_registers'],'name',name2[0])
+              if dev1: 
+                    store=dev1.get('store',False)
+                    devcls=dev1.get('driver');
+                    if not(devcls): logging.error("Can not find driver for register "+name2[0]);
+                    else:
+                       devcls=Find(self.conf['drivers'],'name',devcls)
+                       if not(devcls): logging.error("Can not find device for register "+name2[0]);
+                       else:
+                         devcls=devcls.get('obj')
+#                    print(dev1)
+                    return {"addr":dev1.get('address',0),"register_R":str2int(name2[1]),"register_W":str2int(name2[1]),"store":store,"drivercls":devcls};
+              else: 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;
+#        except:
+#          logging.error("Can not find device register "+str(name));
+#        return None;
     def linkdevices(self):
         #replace devreg reference with (pointer to) devreg dict
         devreglist={}
-- 
GitLab