From 32e9e6644c1d8cc4aab4b610e41439bad4fad1a8 Mon Sep 17 00:00:00 2001
From: kruger <kruger@astron.nl>
Date: Mon, 26 Apr 2021 11:36:57 +0200
Subject: [PATCH] HBAT1 control added

---
 config/RCU.yaml             | 32 +++++++++++++++++++++++++++-----
 i2cserv/gpio.py             |  2 +-
 i2cserv/gpio_hba_trigger.py | 28 ++++++++++++++++++++++++++++
 i2cserv/hba1.py             | 36 +++++++++++++++++++++++++++++++++---
 i2cserv/i2c_array.py        | 28 ++++++++++++++++++----------
 i2cserv/i2cthread.py        |  2 +-
 pypcc2.py                   |  2 +-
 scripts/HBA_wait_PPS.py     | 10 ++++++++++
 testRCU.py                  | 18 ++++++++++++------
 9 files changed, 131 insertions(+), 27 deletions(-)
 create mode 100644 i2cserv/gpio_hba_trigger.py
 create mode 100644 scripts/HBA_wait_PPS.py

diff --git a/config/RCU.yaml b/config/RCU.yaml
index 258c543..ef0371f 100644
--- a/config/RCU.yaml
+++ b/config/RCU.yaml
@@ -10,7 +10,7 @@ drivers:
    type: i2c_array #An array of similar devices connected to an I2C switch
    parent: I2C1
    parameters: [0,31] #start,number of RCUs
- - name: I2C_HBAT 
+ - name: I2C_HBAT
    type: hba1 #Special driver to manage HBAT1s.
    parent: I2C_RCU
  - name: I2Cbb1 
@@ -43,6 +43,11 @@ drivers:
    devreg: [IO3.GPIO1,IO3.GPIO1,IO3.CONF1,IO3.GPIO2]
    parameters: [5,4,4,2]
    parent: I2C_RCU
+ - name: HBA_trigger
+   type: gpio_hba_trigger
+   devreg: [0x40.0x10] #I2C broadcast register
+   parameters: [15] #PPS GPIO pin
+   parent: I2C_RCU
 
 #This is the I2C devices in the RCU
 device_registers:
@@ -118,15 +123,24 @@ device_registers:
      description: Device ID
      address: 0
 
+ - name: HB_UC_update
+   description: RCU microcontroller 
+   address: 0x40
+   driver: HBA_trigger
+   registers:
+   - name: wait_pps
+     address: 10
+
  - name: HBAT
    dim: 3
    address: [0x41,0x42,0x43]
    description: Virtual HBAT0 interface
-   driver: I2C1
+   driver: I2C_HBAT
    registers:
    - name: XY
      address: 0x10
      description: XY delay register
+     store: True
    - name: Version
      address: 127
      description: HBAT server version
@@ -170,7 +184,6 @@ device_registers:
       description: Stop CW
       address: [0x67,0x67]
 
-
 variables:
    - name: Ant_mask
      description: Only masked RF chains are updated
@@ -279,7 +292,7 @@ variables:
 
    - name: HBA_element_beamformer_delays
      description: Delays of each frontend
-     driver: I2C_HBAT
+     driver: I2C_RCU
      devreg:  [HBAT1.XY,HBAT2.XY,HBAT3.XY]
      bitoffset: [2,2,2]
      width: 5
@@ -328,6 +341,8 @@ variables:
      dim: 96
      mask: Ant_mask
 
+
+
 methods:
   - name: RCU_on
     driver: I2C_RCU
@@ -392,4 +407,11 @@ methods:
   - 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
+     #todo, also make all GPIO pins (except power enables) inputs to remove all power from devices.
+
+  - name: RCU_HBAT_WAIT_PPS
+    driver: I2C_RCU
+    mask: RCU_mask
+    instructions:
+     - HB_UC_update.wait_pps : 1
+
diff --git a/i2cserv/gpio.py b/i2cserv/gpio.py
index e768ef2..20e38ab 100644
--- a/i2cserv/gpio.py
+++ b/i2cserv/gpio.py
@@ -1,4 +1,4 @@
-import numpy as np
+#import numpy as np
 from .hwdev import hwdev;
 import logging
 class gpio(hwdev):
diff --git a/i2cserv/gpio_hba_trigger.py b/i2cserv/gpio_hba_trigger.py
new file mode 100644
index 0000000..452f563
--- /dev/null
+++ b/i2cserv/gpio_hba_trigger.py
@@ -0,0 +1,28 @@
+from .hwdev import hwdev;
+import logging
+import signal
+try:
+  import RPi.GPIO as GPIO
+except:
+  GPIO=False;
+  
+class gpio_hba_trigger(hwdev):
+  def __init__(self,config):
+    hwdev.__init__(self,config);
+    self.pin=config['parameters'][0];
+    logging.info("HBAT wait for PPS on pin %i",self.pin)
+    if GPIO:
+      GPIO.setmode(GPIO.BCM)
+      GPIO.setup(self.pin,GPIO.IN)
+    else:
+      logging.warn("RPi GPIO module not found, PPS input disable!")
+
+  def i2csetget(self,addr,data,reg=None,read=0):
+    if (read==0) and GPIO:
+      channel=GPIO.wait_for_edge(self.pin,GPIO.RISING,timeout=1500)
+      if channel is None:
+        logging.info("PPS not received!");
+        return False;
+    self.conf['parentcls'].i2csetget(addr,data,reg,read)
+    
+    
diff --git a/i2cserv/hba1.py b/i2cserv/hba1.py
index 41637cc..73e6d3c 100644
--- a/i2cserv/hba1.py
+++ b/i2cserv/hba1.py
@@ -1,8 +1,38 @@
 import numpy as np
-from .hwdev import hwdev;
+from .hwdev import hwdev
 import logging
+from .i2c_array import ApplyMask
+from time import sleep
+
 class hba1(hwdev):
   def __init__(self,config):
     hwdev.__init__(self,config);
-    logging.info("HBA1 todo")
-    self.previousHBA=np.zeros([32,3,32],dtype='int')
+    logging.info("HBA1 not tested yet!")
+#    self.previousHBA=np.zeros([32,3,32],dtype='int')
+
+  def i2csetget(self,addr,data,reg=None,read=0):
+    if read==0: return self.sethba(addr,reg,data)
+    elif read==1: return self.gethba(addr,reg,data)
+    else: logging.warn("Not implemented!")
+    return False;
+
+  def sethba(self,addr,reg,data):
+      logging.debug("SetHba addr=0x%x reg=0x%x",addr,reg)
+      I2Ccallback=self.conf['parentcls'].i2csetget
+      I2Ccallback(0x40,[],reg=0,read=1)#wakeup, do nothing
+      sleep(0.01) 
+      I2Ccallback(addr,data[:16],reg=reg)
+      if len(data)>16:
+        sleep(0.01) 
+        I2Ccallback(addr,data[16:],reg=reg+16)
+      sleep(0.01) 
+      return True
+
+  def gethba(self,addr,reg,data):
+      I2Ccallback=self.conf['parentcls'].i2csetget
+      if not(I2Ccallback(addr,data,read=1)): return False;
+#      I2Ccallback(addr,data,read=1);
+      if data is None:  return False
+      data[:]=[255]*len(data)
+      logging.debug("getHba addr=0x%x reg=0x%x data=%s",addr,reg,str((data)))
+      return True;
\ No newline at end of file
diff --git a/i2cserv/i2c_array.py b/i2cserv/i2c_array.py
index 293c5a8..a3f7100 100644
--- a/i2cserv/i2c_array.py
+++ b/i2cserv/i2c_array.py
@@ -79,7 +79,7 @@ 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);
+              logging.debug(str(("GetStep",Step,Step2)));
               return Step,Step2
 
 
@@ -220,10 +220,10 @@ class i2c_array(hwdev):
         return value1,mask
 
 
-    def getstorearray(self,devreg):
+    def getstorearray(self,devreg,N=1):
           storearray=devreg.get('storearray')
           if not(storearray):
-                devreg['storearray']=[0]*self.N;
+                devreg['storearray']=([0] if N==1 else [[0]*N])*self.N;
                 storearray=devreg.get('storearray');
           return storearray;
 
@@ -244,14 +244,19 @@ 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);
+                storearray=self.getstorearray(devreg,len(value));
                 previous=storearray[self.RCUi];
-                value[0]=ApplyMask(value[0],width,bitoffset,previous);
-                storearray[self.RCUi]=value[0]
-                logging.debug("Stored value:"+str(value[0]))
+                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)))
             #  devreg['drivercls'].i2csetget
             return devreg['drivercls'].i2csetget(devreg['addr'],value,reg=devreg['register_W'])
 
@@ -275,8 +280,11 @@ class i2c_array(hwdev):
         if value2[0] is None:  return False
         value[:]=value2[:];
         if devreg['store']:
-             storearray=self.getstorearray(devreg);
-             storearray[self.RCUi]=value[0]
+             storearray=self.getstorearray(devreg,len(value));
+             if len(value)==1:
+                storearray[self.RCUi]=value[0]
+             else:
+                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/i2cthread.py b/i2cserv/i2cthread.py
index 3fa382f..e3540ef 100644
--- a/i2cserv/i2cthread.py
+++ b/i2cserv/i2cthread.py
@@ -52,7 +52,7 @@ def runmethod(conf,Qout,methodid,mask):
                 continue;
             v1=conf.getdevreg(key)
             if v1:
-                drv2=v1['drivercls']
+                drv2=v1.get('drivercls')
                 if drv:  drv.Setdevreg(v1,value,mask)
                 elif drv2: drv2.Setdevreg(v1,value,mask)
                 else: logging.warn("Driver not specified for instruction"+key)
diff --git a/pypcc2.py b/pypcc2.py
index df83420..e4bdd2a 100644
--- a/pypcc2.py
+++ b/pypcc2.py
@@ -25,7 +25,6 @@ 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')
-
 RunTimer=True;
 def signal_handler(sig, frame):
     logging.warn('Stop signal received!')
@@ -66,6 +65,7 @@ if not(args.test):
     time.sleep(1)
     logging.info("Start OPC-UA server")
     opcuaserv.start()
+logging.getLogger().setLevel("WARNING")
 
 if False:
    opcuaserv.server.stop()
diff --git a/scripts/HBA_wait_PPS.py b/scripts/HBA_wait_PPS.py
new file mode 100644
index 0000000..d1d8d74
--- /dev/null
+++ b/scripts/HBA_wait_PPS.py
@@ -0,0 +1,10 @@
+from test_common import *
+
+RCUs=[0,1,2,3];
+setRCUmask(RCUs)
+#for RCU in RCUs: 
+#setAntmask(RCUs,[True,True,True])
+
+callmethod("RCU_HBAT_WAIT_PPS")
+
+disconnect();
\ No newline at end of file
diff --git a/testRCU.py b/testRCU.py
index f68c675..8669f0d 100644
--- a/testRCU.py
+++ b/testRCU.py
@@ -38,17 +38,22 @@ var1=RCU_conf.getmethodid('RCU_update');
 #mask=[i<2 for i in range(N)];
 #RCU_I2C.callmethod(var1,[])
 
-if True:
+if False:
     var1=RCU_conf.getvarid('RCU_LED0');
     N=32;
     mask=[i<8 for i in range(N)];
     data=[0]*N;
-elif True:
+elif False:
     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]
+else:
+    var1=RCU_conf.getvarid('HBA_element_beamformer_delays');
+    N=32*3;
+    mask=[i<8 for i in range(N)];
+    data=[1]*(N*32);
 #print(var1)
 print("mask=",mask);
 print("data=",data);
@@ -57,19 +62,20 @@ print("data=",data);
 var1=RCU_conf.getvarid('RCU_temperature');
 N=32;
 mask=[i<2 for i in range(N)];
-RCU_I2C.readvar(var1,mask);
+#RCU_I2C.readvar(var1,mask);
 
 #data=[0]*N;
 #RCU_I2C.setvar(var1,data,mask);
 #def setvar(self,id1,data=[],mask=[]):
 
-var1=RCU_conf.getmethodid('RCU_on');
+#var1=RCU_conf.getmethodid('RCU_on');
+var1=RCU_conf.getmethodid('RCU_HBAT_WAIT_PPS');
 N=32;
 mask=[i<7 for i in range(N)];
-#RCU_I2C.callmethod(var1,mask)
+RCU_I2C.callmethod(var1,mask)
 
 
-time.sleep(5);
+time.sleep(2);
 
 while RCU_I2C.data_waiting():
     varid,data,mask=RCU_I2C.readdata()
-- 
GitLab