From 6736be0b277e94c9d074b1bb023eae5698dfdf21 Mon Sep 17 00:00:00 2001
From: kruger <kruger@astron.nl>
Date: Wed, 9 Jun 2021 11:22:11 +0100
Subject: [PATCH] PPS working

---
 config/RCU_uC_test.yaml     | 332 ++++++++++++++++++++++++++++++++++++
 i2cserv/gpio_hba_trigger.py |  36 ++--
 i2cserv/hba1.py             |  23 ++-
 i2cserv/i2c_dev.py          |   2 +-
 scripts/SetHBAT_BFs.py      |  45 +++--
 scripts/SetHBAT_LEDs.py     |  37 ++++
 scripts/SetHBAT_PPS.py      |  22 +++
 scripts/pps_generator.py    |  13 ++
 scripts/pps_test.py         |  10 ++
 9 files changed, 492 insertions(+), 28 deletions(-)
 create mode 100644 config/RCU_uC_test.yaml
 create mode 100644 scripts/SetHBAT_LEDs.py
 create mode 100644 scripts/SetHBAT_PPS.py
 create mode 100644 scripts/pps_generator.py
 create mode 100644 scripts/pps_test.py

diff --git a/config/RCU_uC_test.yaml b/config/RCU_uC_test.yaml
new file mode 100644
index 0000000..2e7d4cf
--- /dev/null
+++ b/config/RCU_uC_test.yaml
@@ -0,0 +1,332 @@
+version: "1.0"
+description: "1234"
+
+drivers:
+ - name: I2C1 #TCA9548
+   type: i2c_switch
+   devreg: [0x70]
+   parameters: [1] #I2C port number
+ - name: I2C_RCU 
+   type: i2c_array #An array of similar devices connected to an I2C switch
+   parent: I2C1
+   parameters: [0,31] #start,number of RCUs
+   status: RCU_I2C_STATUS
+ - name: I2C_HBAT
+   type: hba1 #Special driver to manage HBAT1s.
+   devreg: [0x40.0xFF] #I2C broadcast register
+   parameters: [23] #PPS GPIO pin
+   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
+# - name: HBA_trigger
+#   type: gpio_hba_trigger
+#   devreg: [0x40.0xFF] #I2C broadcast register
+#   parameters: [23] #PPS GPIO pin
+#   parent: I2C_HBAT
+
+#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: 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: 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: I2C_HBAT
+   registers:
+   - name: XY
+     address: 0x10
+     description: XY delay register
+     store: True
+   - 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: SYNC_control
+      address: 0x3A
+    - name: CML_level
+      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_RCU
+     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_I2C_STATUS
+     description: 0=Good, 1=No communication, 2=error
+     driver: I2C_RCU
+     rw:  ro #server RW variable, not linked to IO
+     dtype: uint8
+     mask: RCU_mask
+     dim: 32
+
+#   - name: RCU_state
+#     description: State of RCUs 0=unknown, 1=ready, 2=busy, 3= wait PPS, 4=error
+#     driver: I2C_RCU
+#     rw:  ro #server variable, not linked to IO
+#     dtype: uint8
+#     dim: 1
+
+   - name: RCU_translator_busy
+     description: False when idle
+     rw:  ro #server variable, not linked to IO
+     dtype: boolean
+     dim: 1
+
+   - name: HBA_uC_Timeout_RXTX
+     description: Time waiting for replay from tile
+     driver: I2C_RCU
+     devreg:  HB_UC.8
+     width: 16
+     endian: "<"
+     rw:  rw
+     dtype: uint16
+     dim: 32
+     mask: RCU_mask
+     debug: True
+     wait: 10 #ms
+
+   - name: HBA_uC_wait_PPS
+     description: wait for PPS after receiving signals
+     driver: I2C_RCU
+     devreg:  HB_UC.12
+     width: 1
+     rw:  rw
+     dtype: boolean
+     dim: 32
+     mask: RCU_mask
+     debug: True
+
+   - 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
+     wait: PPS
+
+   - name: HBA_element_led
+     description: LED of each frontend
+     driver: I2C_HBAT
+     devreg:  [HBAT1.XY,HBAT2.XY,HBAT3.XY]
+     bitoffset: 0
+     width: 1
+     rw:  rw
+     dtype: boolean
+     dim: 3072
+     mask: Ant_mask
+     wait: 100 #ms
+#     debug: True
+
+   - name: HBA_element_pwr
+     description: power
+     driver: I2C_HBAT
+     devreg:  [HBAT1.XY,HBAT2.XY,HBAT3.XY]
+     bitoffset: 7
+     width: 1
+     rw:  rw
+     dtype: boolean
+     dim: 3072
+     mask: Ant_mask
+     wait: 100 #ms
+#     debug: True
+
+   - name: HBA_element_LNA_pwr
+     description: frontend power of each frontend
+     driver: I2C_HBAT
+     devreg:  [HBAT1.XY,HBAT2.XY,HBAT3.XY]
+     bitoffset: 1
+     width: 1
+     rw:  rw
+     dtype: boolean
+     dim: 3072
+     mask: Ant_mask
+     wait: 100 #ms
+#     debug: True
+
+
+methods:
+  - name: RCU_Init #Called after startup to load. Should have all stored registers  
+    driver: I2C_RCU
+    debug: True
+    instructions:
+     - RCU_UC_Load: 0
+
+  - name: RCU_UC_Load
+    driver: I2C_RCU
+    debug: True
+    instructions:   
+     - HBA_uC_Timeout_RXTX: Update
+     - HBA_uC_wait_PPS: Update
+
+  - name: RCU_off
+    driver: I2C_RCU
+    mask: RCU_mask
+    instructions:
+     - RCU_I2C_STATUS: 0
+#     - RCU_Pwr_dig: 0 #Switch power off
+#     - IO2.GPIO1: 0
+#     - IO2.GPIO2: 0
+#     - IO3.GPIO1: 0
+#     - IO3.GPIO2: 0
+#     - IO1.GPIO1: 0
+#     - IO1.GPIO2: 0
+#     - RCU_update: 0
+     #todo, also make all GPIO pins (except power enables) inputs to remove all power from devices.
+
diff --git a/i2cserv/gpio_hba_trigger.py b/i2cserv/gpio_hba_trigger.py
index 452f563..cf77c9c 100644
--- a/i2cserv/gpio_hba_trigger.py
+++ b/i2cserv/gpio_hba_trigger.py
@@ -1,4 +1,4 @@
-from .hwdev import hwdev;
+from .hba1 import hba1;
 import logging
 import signal
 try:
@@ -6,23 +6,37 @@ try:
 except:
   GPIO=False;
   
-class gpio_hba_trigger(hwdev):
+class gpio_hba_trigger(hba1):
   def __init__(self,config):
-    hwdev.__init__(self,config);
+    hba1.__init__(self,config);
     self.pin=config['parameters'][0];
-    logging.info("HBAT wait for PPS on pin %i",self.pin)
+    self.addr=config['devreg'][0]['addr']
+    self.reg=config['devreg'][0]['register_R']
+    logging.info("HBAT wait for PPS on pin %i, TX=%i:%i",self.pin,self.addr,self.reg)
     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)
+  def OPCUASetVariable(self,varid,var1,data,mask):
+       logging.info(str(("HBA set Var",var1['name'],data[:32*3],mask[:12])))
+       self.conf['parentcls'].SetGetVarValueMask(var1,data,mask,getalso=False)
+       #Wait for PPS if required else wait a bit
+       channel=GPIO.wait_for_edge(self.pin,GPIO.RISING,timeout=1500)
+       self.conf['parentcls'].i2csetget(self.addr,[],self.reg,0)
+       if channel is None:
+         logging.info("PPS not received!");
+#         return False;
+       if var1.get('wait'):
+         logging.debug("Wait %i ms",var1.get('wait')) 
+         sleep(var1['wait']/100.)
+       data,mask2=self.conf['parentcls'].GetVarValueMask(var1,mask)
+       Data=OPCUAset(varid,InstType.varSet,data.copy(),mask2.copy())
+       return [Data]
+
+#  def i2csetget(self,addr,data,reg=None,read=0):
+#    if (read==0) and GPIO:
+#    self.conf['parentcls'].i2csetget(addr,data,reg,read)
     
     
diff --git a/i2cserv/hba1.py b/i2cserv/hba1.py
index 1a0524b..bca60ab 100644
--- a/i2cserv/hba1.py
+++ b/i2cserv/hba1.py
@@ -4,18 +4,39 @@ import logging
 from .i2c_array import ApplyMask
 from time import sleep
 from queuetypes import *
+import signal
+try:
+  import RPi.GPIO as GPIO
+except:
+  GPIO=False;
 
 class hba1(hwdev):
   def __init__(self,config):
     hwdev.__init__(self,config);
     logging.info("HBA1 driver loaded")
 #    self.previousHBA=np.zeros([32,3,32],dtype='int')
+    self.pin=config['parameters'][0];
+    self.addr=config['devreg'][0]['addr']
+    self.reg=config['devreg'][0]['register_R']
+    if GPIO:
+      GPIO.setmode(GPIO.BCM)
+      GPIO.setup(self.pin,GPIO.IN)
+      logging.info("HBAT wait for PPS on pin %i, TX=%i:%i",self.pin,self.addr,self.reg)
+    else:
+      logging.warn("RPi GPIO module not found, PPS input disable!")
 
   def OPCUASetVariable(self,varid,var1,data,mask):
        logging.info(str(("HBA set Var",var1['name'],data[:32*3],mask[:12])))
        self.conf['parentcls'].SetGetVarValueMask(var1,data,mask,getalso=False)
        #Wait for PPS if required else wait a bit
-       if var1.get('wait'):
+       if var1.get('wait')=="PPS":
+         channel=GPIO.wait_for_edge(self.pin,GPIO.RISING,timeout=1500)
+         self.conf['parentcls'].i2csetget(self.addr,[],self.reg,0)
+         if channel is None:
+           logging.info("PPS not received!");
+         sleep(0.5)
+#         return False;
+       elif var1.get('wait'):
          logging.debug("Wait %i ms",var1.get('wait')) 
          sleep(var1['wait']/100.)
        data,mask2=self.conf['parentcls'].GetVarValueMask(var1,mask)
diff --git a/i2cserv/i2c_dev.py b/i2cserv/i2c_dev.py
index 2f73afa..2dc3673 100644
--- a/i2cserv/i2c_dev.py
+++ b/i2cserv/i2c_dev.py
@@ -89,7 +89,7 @@ class i2c_dev(hwdev):
         if self.I2Cmaskid is None: logging.warn(config['name']+" I2C mask not found!")
 
     def OPCUASetVariable(self,varid,var1,data,mask):
-       logging.info(str(("Set Var",var1['name'],data,mask)))
+       logging.info(str(("Set Var",var1['name'],data[:32],mask)))
        if (var1['rw']=='variable') or not(var1.get('devreg')):
           if varid==self.I2Cmaskid:
               if len(mask)==0: mask=[True]*len(data);
diff --git a/scripts/SetHBAT_BFs.py b/scripts/SetHBAT_BFs.py
index 7f64d0f..425cd6b 100644
--- a/scripts/SetHBAT_BFs.py
+++ b/scripts/SetHBAT_BFs.py
@@ -1,11 +1,11 @@
 RCU=0
-#HBAT=1 #HBAT on RCU 0..2
-#HBA=5; #HBA Element in HBAT
-#BFX=11 #delay in 0.5ns
-#BFY=BFX+1
 name="HBA_element_beamformer_delays"
 AntMask=[True,True,True]
-NewVal=[2]*64
+NewVal1=range(32)
+NewVal2=[1]*32
+NewValues=[NewVal1,NewVal2,NewVal1,NewVal2,NewVal1,NewVal2,NewVal1,NewVal2,NewVal1,NewVal2]
+#NewValues=[NewVal1,NewVal2]
+DEBUG=False
 
 from test_common import *
 import numpy as np
@@ -15,16 +15,31 @@ setAntmask([RCU],AntMask)
 i=(RCU*3)*32
 
 val=get_value(name+"_R")
-print("old:",val[i:i+64])
-
-val[i:i+64]=NewVal
-
-set_value(name+"_RW",val)
-print("set:",val[i:i+64])
-time.sleep(2)
-val=get_value(name+"_R")
-print("new:",val[i:i+64])
-
+if DEBUG:
+  print("Current values:");
+  for x in range(3): print(val[i+x*32:i+(x+1)*32])
+
+for cnt,NewVal in enumerate(NewValues):
+
+ for x in range(3): val[i+x*32:i+(x+1)*32]=NewVal
+
+ set_value(name+"_RW",val)
+ if DEBUG:
+   print("set:")
+   for x in range(3): print(val[i+x*32:i+(x+1)*32])
+ time.sleep(0.4)
+ wait_not_busy("RCU_translator_busy_R",timeout_sec=2)
+# time.sleep(0.1)
+ val=get_value(name+"_R")
+ if DEBUG:
+   print("readback:")
+   for x in range(3): print(val[i+x*32:i+(x+1)*32])
+
+ same=True;
+ for x in range(3): 
+   for y in range(32): 
+     if not(val[i+x*32+y]==NewVal[y]): same=False;
+ print(cnt+1,"Success" if same else "FAILED!")
 #time.sleep(5)
 #val[i:i+64]=[0]*64
 
diff --git a/scripts/SetHBAT_LEDs.py b/scripts/SetHBAT_LEDs.py
new file mode 100644
index 0000000..a625466
--- /dev/null
+++ b/scripts/SetHBAT_LEDs.py
@@ -0,0 +1,37 @@
+RCU=0
+#HBAT=1 #HBAT on RCU 0..2
+#HBA=5; #HBA Element in HBAT
+#BFX=11 #delay in 0.5ns
+#BFY=BFX+1
+name="HBA_element_led"
+AntMask=[True,True,True]
+NewVal=[True]*64
+
+from test_common import *
+import numpy as np
+
+setAntmask([RCU],AntMask)
+
+i=(RCU*3)*32
+
+val=get_value(name+"_R")
+print("old:",val[i:i+64])
+
+val[i:i+64]=NewVal
+
+set_value(name+"_RW",val)
+print("set:",val[i:i+64])
+time.sleep(2)
+val=get_value(name+"_R")
+print("new:",val[i:i+64])
+
+#time.sleep(5)
+#val[i:i+64]=[0]*64
+
+#set_value(name+"_RW",val)
+#print("set:",val[i:i+64])
+#time.sleep(1)
+#val=get_value(name+"_R")
+#print("new:",val[i:i+64])
+
+disconnect()
diff --git a/scripts/SetHBAT_PPS.py b/scripts/SetHBAT_PPS.py
new file mode 100644
index 0000000..2660fc2
--- /dev/null
+++ b/scripts/SetHBAT_PPS.py
@@ -0,0 +1,22 @@
+RCU=[0]
+name="HBA_uC_wait_PPS"
+NewVal=True
+
+from test_common import *
+import numpy as np
+
+setRCUmask(RCU)
+
+
+val=get_value(name+"_R")
+print("old:",val)
+for r in RCU:
+  val[r]=NewVal
+
+set_value(name+"_RW",val)
+print("set:",val)
+time.sleep(0.1)
+val=get_value(name+"_R")
+print("new:",val)
+
+disconnect()
diff --git a/scripts/pps_generator.py b/scripts/pps_generator.py
new file mode 100644
index 0000000..8c5567f
--- /dev/null
+++ b/scripts/pps_generator.py
@@ -0,0 +1,13 @@
+import RPi.GPIO as GPIO
+import time
+PIN=24
+  
+GPIO.setmode(GPIO.BCM)
+GPIO.setup(PIN,GPIO.OUT)
+
+while True:
+  GPIO.output(PIN,GPIO.LOW)
+  time.sleep(0.5)
+  GPIO.output(PIN,GPIO.HIGH)
+  time.sleep(0.5)
+#  print('*')
diff --git a/scripts/pps_test.py b/scripts/pps_test.py
new file mode 100644
index 0000000..c1d9668
--- /dev/null
+++ b/scripts/pps_test.py
@@ -0,0 +1,10 @@
+import RPi.GPIO as GPIO
+import time
+PIN=23
+  
+GPIO.setmode(GPIO.BCM)
+GPIO.setup(PIN,GPIO.IN)
+
+for x in range(3):
+  channel=GPIO.wait_for_edge(PIN,GPIO.RISING,timeout=1500)
+  print("Timeout!" if channel is None else "PPS")
-- 
GitLab