From d705769f66a715122afc02a20dcf44fff23beacb Mon Sep 17 00:00:00 2001
From: Paulus <kruger@astron.nl>
Date: Fri, 29 Oct 2021 10:35:58 +0100
Subject: [PATCH] parallel i2c readout

---
 config/RECVTR.yaml   |  7 +++++++
 i2cserv/i2c_array.py | 48 ++++++++++++++++++++++++++++++++++----------
 i2cserv/i2c_dev.py   | 26 +++++++++++++++++-------
 3 files changed, 63 insertions(+), 18 deletions(-)

diff --git a/config/RECVTR.yaml b/config/RECVTR.yaml
index 69e87db..7dce229 100644
--- a/config/RECVTR.yaml
+++ b/config/RECVTR.yaml
@@ -319,6 +319,7 @@ variables:
      dtype: double
      dim: 32
      monitor: true
+     read_parallel: true
      mask: RECVTR_I2C_error
 
    - name: RCU_PWR_3V3
@@ -330,6 +331,7 @@ variables:
      rw:  ro
      dtype: double
      dim: 32
+     read_parallel: true
      monitor: true
      mask: RECVTR_I2C_error
 
@@ -342,6 +344,7 @@ variables:
      rw:  ro
      dtype: double
      dim: 32
+     read_parallel: true
      monitor: true
      mask: RECVTR_I2C_error
 
@@ -354,6 +357,7 @@ variables:
      rw:  ro
      dtype: double
      dim: 32
+     read_parallel: true
      monitor: true
      mask: RECVTR_I2C_error
 
@@ -367,6 +371,7 @@ variables:
      dtype: double
      dim: 96
      dim2: [3,32]
+     read_parallel: true
      monitor: true
      mask: RECVTR_I2C_error
 
@@ -380,6 +385,7 @@ variables:
      dtype: double
      dim: 96
      dim2: [3,32]
+     read_parallel: true
      monitor: true
      mask: RECVTR_I2C_error
 
@@ -393,6 +399,7 @@ variables:
      dtype: double
      dim: 96
      dim2: [3,32]
+     read_parallel: true
      monitor: true
      mask: RECVTR_I2C_error
 
diff --git a/i2cserv/i2c_array.py b/i2cserv/i2c_array.py
index 51381ee..2f08363 100644
--- a/i2cserv/i2c_array.py
+++ b/i2cserv/i2c_array.py
@@ -97,8 +97,23 @@ class i2c_array(i2c_dev):
 #        if (len(value1)==V1.nVars) and (self.N>1):  value1=(value1*self.N);
         i2c=self.conf['parentcls'];
 #        logging.debug(str(("Step=",Step,"Mask=",mask)))
-        for RCUi in range(self.N):
-            for Vari in range(Step):
+        mode=(1 if var1.get('read_parallel') else 0)
+        for Vari in range(Step):
+          if mode==1:
+#            logging.debug("parallel write register for read")
+#            print(mask2);
+               devreg=var1['devreg'][Vari];
+               width=var1.get('width',8)
+               bitoffset=GetField(var1,'bitoffset',Vari,0)
+               mask2=[mask[RCUi*Step+Vari] & (self.I2Cmask[RCUi]<=self.I2Ccut) for RCUi in range(self.N)]
+               self.SetSwitchMask(mask2);
+               res=self.GetVarValue(devreg,width,bitoffset,[],mode=3) #wait if needed
+               res=self.GetVarValue(devreg,width,bitoffset,[],mode=2) #only set register
+               res=self.GetVarValue(devreg,width,bitoffset,[],mode=3) #wait if needed
+#            for Vari in range(Step):
+#        else:
+          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
@@ -112,7 +127,7 @@ class i2c_array(i2c_dev):
                 self.SetSwitch(RCUi);
                 value2=value1[i0:i1]
                 self.RCUi=RCUi;
-                res=self.GetVarValue(devreg,width,bitoffset,value2)
+                res=self.GetVarValue(devreg,width,bitoffset,value2,mode=mode)
                 if not(res):
                   if self.disableI2ConError: self.I2Cmask[RCUi]+=1;
                   if self.I2Cmask[RCUi]>self.I2Ccut: mask[RCUi*Step+Vari]=False;
@@ -185,25 +200,36 @@ class i2c_array(i2c_dev):
             #  devreg['drivercls'].i2csetget
             return devreg['drivercls'].i2csetget(devreg['addr'],value,reg=devreg['register_W'])
 
-    def GetVarValue(self,devreg,width,bitoffset,value):
+    def GetVarValue(self,devreg,width,bitoffset,value,mode=0):
         logging.debug(str(("RCU1 Get ",self.RCUi,devreg['addr'],value)))
 #                self.GetI2C(RCUi,devreg,width,bitoffset,value)
 #        if dev.store>0:
 #            value[0]=self.previous[RCUi,dev.store-1]
 #        return True
         callback=devreg['drivercls'].i2csetget;
+        reg=devreg['register_R']
+
+        if mode==2:
+           return callback(devreg['addr'],int2bytes(reg),read=2)
+        elif mode==3:
+           if devreg.get('wait',0)>0: callback(0,[devreg['wait']],read=3)
+           elif reg>255: callback(0,[250],read=3)
+           return True;
+
         l1=int(np.floor((width+bitoffset+7)/8))
 #        print(width,bitoffset,l1)
         value2=value
-        reg=devreg['register_R']
         value2[0]=None; #default
-        if reg>255: #This is for the monitor ADC (+ DTH)
-          callback(0,[250],read=3)
-          if not(callback(devreg['addr'],int2bytes(reg),read=2)): return False;
-          callback(0,[250],read=3)
-          if not(callback(devreg['addr'],value2,read=1)): return False;
+        if mode==1:
+           if not(callback(devreg['addr'],value2,read=1)): return False;
         else:
-          if not(callback(devreg['addr'],value2,reg=reg,read=1)): return False;
+          if reg>255: #This is for the monitor ADC (+ DTH)
+            callback(0,[250],read=3)
+            if not(callback(devreg['addr'],int2bytes(reg),read=2)): return False;
+            callback(0,[250],read=3)
+            if not(callback(devreg['addr'],value2,read=1)): return False;
+          else:
+            if not(callback(devreg['addr'],value2,reg=reg,read=1)): return False;
         if value2[0] is None:  return False
         value[:]=value2[:];
         if devreg.get('store'):
diff --git a/i2cserv/i2c_dev.py b/i2cserv/i2c_dev.py
index c1a8abc..6e6885f 100644
--- a/i2cserv/i2c_dev.py
+++ b/i2cserv/i2c_dev.py
@@ -267,18 +267,30 @@ class i2c_dev(hwdev):
             #  devreg['drivercls'].i2csetget
             return devreg['drivercls'].i2csetget(devreg['addr'],value,reg=devreg['register_W'])
 
-    def GetVarValue(self,devreg,width,bitoffset,value):
+    def GetVarValue(self,devreg,width,bitoffset,value,mode=0):
+#mode=0: Set register, wait, read
+#mode=1: only read
+#mode=2: only set register
+#mode=3: only wait
         logging.debug(str(("i2c_dev Get ",devreg['addr'],value)))
         callback=devreg['drivercls'].i2csetget;
-        value2=value
         reg=devreg['register_R']
-        if devreg.get('wait',0)>0:
-           callback(0,[devreg['wait']],read=3)
-           if not(callback(devreg['addr'],int2bytes(reg),read=2)): return False;
-           callback(0,[devreg['wait']],read=3)
+        if mode==2:
+           return callback(devreg['addr'],int2bytes(reg),read=2)
+        elif mode==3:
+           if devreg.get('wait',0)>0: callback(0,[devreg['wait']],read=3)
+           return True;
+        value2=value
+        if mode==1:
            if not(callback(devreg['addr'],value2,read=1)): return False;
         else:
-          if not(callback(devreg['addr'],value2,reg=reg,read=1)): return False;
+           if devreg.get('wait',0)>0:
+              callback(0,[devreg['wait']],read=3)
+              if not(callback(devreg['addr'],int2bytes(reg),read=2)): return False;
+              callback(0,[devreg['wait']],read=3)
+              if not(callback(devreg['addr'],value2,read=1)): return False;
+           else:
+              if not(callback(devreg['addr'],value2,reg=reg,read=1)): return False;
         if value2[0] is None:  return False
         value[:]=value2[:];
         if devreg.get('store'):
-- 
GitLab