From aea74308409456efe03029e932442897b2b0ce27 Mon Sep 17 00:00:00 2001
From: kruger <kruger@astron.nl>
Date: Wed, 8 May 2024 08:53:34 +0100
Subject: [PATCH] APSPU array of 2

---
 pypcc/config/APSPUTR.yaml       |  21 +++-
 pypcc/config/APSPUTR_1.yaml     | 177 ++++++++++++++++++++++++++++++++
 pypcc/i2cserv/i2c_switch_smb.py |  65 ++++++++++++
 3 files changed, 261 insertions(+), 2 deletions(-)
 create mode 100644 pypcc/config/APSPUTR_1.yaml
 create mode 100644 pypcc/i2cserv/i2c_switch_smb.py

diff --git a/pypcc/config/APSPUTR.yaml b/pypcc/config/APSPUTR.yaml
index c8cbdfc..662ef64 100644
--- a/pypcc/config/APSPUTR.yaml
+++ b/pypcc/config/APSPUTR.yaml
@@ -3,13 +3,22 @@ description: "1234"
 
 drivers:
  - name: I2C
-   type: i2c_smbus
+   type: i2c_switch_smb
    parameters: [4] #I2C port number
+   devreg: [0x70]
+
  - name: I2C_PU
-   type: i2c_dev #I2C devices
+   type: i2c_array
    parent: I2C
+   parameters: [0,1] #lookup table
+   I2Ccut: 10
    status: APSPUTR_I2C_error
 
+# - name: I2C_PU
+#   type: i2c_dev #I2C devices
+#   parent: I2C
+#   status: APSPUTR_I2C_error
+
 #This is the I2C devices in the RCU
 device_registers:
  - name: ROM
@@ -75,6 +84,7 @@ variables:
     driver: I2C_PU
     rw:  ro #server RW variable, not linked to IO
     dtype: uint8
+    dim: 2
 
   - name: APSPUTR_monitor_rate
     description: Monitor rate in seconds
@@ -93,6 +103,7 @@ variables:
     width: 32
     rw:  ro
     dtype: uint32
+    dim: 2
 
   - name: APSPU_PCB_version
     description: Version number
@@ -101,6 +112,7 @@ variables:
     width: 0x100  #32 characters
     rw:  ro
     dtype: string
+    dim: 2
 
   - name: APSPU_PCB_number
     description: PCB number
@@ -109,6 +121,7 @@ variables:
     width: 0x100  #32 characters
     rw:  ro
     dtype: string
+    dim: 2
 
   - name: [APSPU_LBA_VOUT,APSPU_RCU2A_VOUT,APSPU_RCU2D_VOUT]
     description: Output voltage (V)
@@ -120,6 +133,7 @@ variables:
     endian: "<"
     scale: 4.8828e-4 #2^-11
     monitor: true
+    dim: 2
 
   - name: [APSPU_LBA_IOUT,APSPU_RCU2A_IOUT,APSPU_RCU2D_IOUT]
     description: Output current (A)
@@ -130,6 +144,7 @@ variables:
     dtype: double
     scale: smbus_2bytes_to_float
     monitor: true
+    dim: 2
 
   - name: [APSPU_LBA_TEMP,APSPU_RCU2A_TEMP,APSPU_RCU2D_TEMP]
     description: DC-DC converter temperature (Celsius)
@@ -140,6 +155,7 @@ variables:
     dtype: double
     scale: smbus_2bytes_to_float
     monitor: true
+    dim: 2
 
   - name: [APSPU_FAN1_RPM,APSPU_FAN2_RPM,APSPU_FAN3_RPM]
     description: FAN speed in RPM.
@@ -153,6 +169,7 @@ variables:
     scale: 4.7684e-7 #FAN_TACHS/TACH_COUNT_FREQ/TACH_PERIODS = 1/8192/16 /16 (bitoffset=0)
     convert_unit: period2RPM
     monitor: true
+    dim: 2
 
 methods:
   - name: APSPUTR_Init #Called after startup to load. Should have all stored registers  
diff --git a/pypcc/config/APSPUTR_1.yaml b/pypcc/config/APSPUTR_1.yaml
new file mode 100644
index 0000000..c8cbdfc
--- /dev/null
+++ b/pypcc/config/APSPUTR_1.yaml
@@ -0,0 +1,177 @@
+1version: "1.0"
+description: "1234"
+
+drivers:
+ - name: I2C
+   type: i2c_smbus
+   parameters: [4] #I2C port number
+ - name: I2C_PU
+   type: i2c_dev #I2C devices
+   parent: I2C
+   status: APSPUTR_I2C_error
+
+#This is the I2C devices in the RCU
+device_registers:
+ - name: ROM
+   address: 0x50
+   driver: I2C_PU
+   registers:
+   - name: ID
+     description: Random
+     address: 0xfc
+   - name: Version
+     description: Set in production
+     address: 0
+   - name: Serial
+     address: 0x20
+
+ - name: POL_LBA
+   address: 0x3C 
+   driver: i2c_smbus
+   registers: 
+   - { name: "TEMP", address: 0x8D, crc: True}
+   - { name: "VIN" , address: 0x88, crc: True}
+   - { name: "VOUT", address: 0x8B, crc: True}
+   - { name: "IOUT", address: 0x8C, crc: True}
+ - name: POL_RCU2A
+   address: 0x3D
+   driver: i2c_smbus
+   registers: 
+   - { name: "TEMP", address: 0x8D, crc: True}
+   - { name: "VIN" , address: 0x88, crc: True}
+   - { name: "VOUT", address: 0x8B, crc: True}
+   - { name: "IOUT", address: 0x8C, crc: True}
+ - name: POL_RCU2D
+   address: 0x3E
+   driver: i2c_smbus
+   registers: 
+   - { name: "TEMP", address: 0x8D, crc: True}
+   - { name: "VIN" , address: 0x88, crc: True}
+   - { name: "VOUT", address: 0x8B, crc: True}
+   - { name: "IOUT", address: 0x8C, crc: True}
+
+
+ - name: MAX
+   description: MAX6620 fan speed controller
+   address: 0x29
+   driver: I2C_PU
+   registers:
+   - { name: GLOBAL, address: 0x00}
+   - { name: TACH1,  address: 0x10}
+   - { name: TACH2,  address: 0x12}
+   - { name: TACH3, address: 0x14}
+   - { name: r2, address: 0x2}
+   - { name: r3, address: 0x3}
+   - { name: r4, address: 0x4}
+   - { name: r5, address: 0x5}
+   - { name: r6, address: 0x6}
+   - { name: r7, address: 0x7}
+   - { name: r8, address: 0x8}
+
+
+variables:
+  - name: APSPUTR_I2C_error
+    description: 0=Good, >0 I2C communication error
+    driver: I2C_PU
+    rw:  ro #server RW variable, not linked to IO
+    dtype: uint8
+
+  - name: APSPUTR_monitor_rate
+    description: Monitor rate in seconds
+    rw:  variable 
+    dtype: uint8
+
+  - name: APSPUTR_translator_busy
+    description: True when I2C line busy
+    rw:  ro #server variable, not linked to IO
+    dtype: boolean
+
+  - name: APSPU_PCB_ID
+    description: Unique PCB ID
+    driver: I2C_PU
+    devreg:  ROM.ID
+    width: 32
+    rw:  ro
+    dtype: uint32
+
+  - name: APSPU_PCB_version
+    description: Version number
+    driver: I2C_PU
+    devreg:  ROM.Version
+    width: 0x100  #32 characters
+    rw:  ro
+    dtype: string
+
+  - name: APSPU_PCB_number
+    description: PCB number
+    driver: I2C_PU
+    devreg:  ROM.Serial
+    width: 0x100  #32 characters
+    rw:  ro
+    dtype: string
+
+  - name: [APSPU_LBA_VOUT,APSPU_RCU2A_VOUT,APSPU_RCU2D_VOUT]
+    description: Output voltage (V)
+    driver: I2C_PU
+    devreg:  [POL_LBA.VOUT,POL_RCU2A.VOUT,POL_RCU2D.VOUT]
+    width: 16
+    rw:  ro
+    dtype: double
+    endian: "<"
+    scale: 4.8828e-4 #2^-11
+    monitor: true
+
+  - name: [APSPU_LBA_IOUT,APSPU_RCU2A_IOUT,APSPU_RCU2D_IOUT]
+    description: Output current (A)
+    driver: I2C_PU
+    devreg:  [POL_LBA.IOUT,POL_RCU2A.IOUT,POL_RCU2D.IOUT]
+    width: 16
+    rw:  ro
+    dtype: double
+    scale: smbus_2bytes_to_float
+    monitor: true
+
+  - name: [APSPU_LBA_TEMP,APSPU_RCU2A_TEMP,APSPU_RCU2D_TEMP]
+    description: DC-DC converter temperature (Celsius)
+    driver: I2C_PU
+    devreg:  [POL_LBA.TEMP,POL_RCU2A.TEMP,POL_RCU2D.TEMP]
+    width: 16
+    rw:  ro
+    dtype: double
+    scale: smbus_2bytes_to_float
+    monitor: true
+
+  - name: [APSPU_FAN1_RPM,APSPU_FAN2_RPM,APSPU_FAN3_RPM]
+    description: FAN speed in RPM.
+    driver: I2C_PU
+    devreg:  [MAX.TACH1,MAX.TACH2,MAX.TACH3]
+#    bitoffset: 5
+    width: 16
+    rw:  ro
+    dtype: double
+#    scale: 1.52588e-5 #FAN_TACHS/TACH_COUNT_FREQ/TACH_PERIODS = 1/8192/16 *2 (bitoffset=5) - not working correctly
+    scale: 4.7684e-7 #FAN_TACHS/TACH_COUNT_FREQ/TACH_PERIODS = 1/8192/16 /16 (bitoffset=0)
+    convert_unit: period2RPM
+    monitor: true
+
+methods:
+  - name: APSPUTR_Init #Called after startup to load. Should have all stored registers  
+    driver: I2C_PU
+    debug: True
+    instructions:   
+      - APSPU_PCB_ID : Update
+      - APSPU_PCB_version : Update
+      - APSPU_PCB_number : Update
+      - APSPU_FAN_monitor_on : 0
+
+  - name: APSPU_FAN_monitor_on
+    description: Setup the FAN monitor. Called automatically on power-on.
+    driver: I2C_PU
+    instructions:   
+      - MAX.GLOBAL : 0x02 #Run monitor
+      - MAX.r2 : 0x88
+      - MAX.r6 : 0x80 # int((math.log(TACH_PERIODS{16}) / math.log(2))) << 5, 
+      - MAX.r3 : 0x88
+      - MAX.r7 : 0x80
+      - MAX.r4 : 0x88
+      - MAX.r8 : 0x80
diff --git a/pypcc/i2cserv/i2c_switch_smb.py b/pypcc/i2cserv/i2c_switch_smb.py
new file mode 100644
index 0000000..e22f310
--- /dev/null
+++ b/pypcc/i2cserv/i2c_switch_smb.py
@@ -0,0 +1,65 @@
+import logging
+#from .i2c import i2c
+from .i2c_smbus import i2c_smbus as i2c
+
+#import HWconf
+#SWaddr=0x70
+class i2c_switch_smb(i2c):
+    def __init__(self,config):
+        i2c.__init__(self,config)
+#        self.SWaddr=config['devreg'][0]['addr']
+        self.SWcnt=len(config['devreg']);
+        self.SWaddrs=[config['devreg'][x]['addr'] for x in range(self.SWcnt)]; 
+        self.CurrentChannel=[-1 for x in range(self.SWcnt)];
+        self.NoSwitch=self.SWcnt==0;
+        S=''; 
+        for x in range(self.SWcnt): S+=str(self.SWaddrs[x])+",";
+        logging.info("i2c switch at address "+S)
+        if self.NoSwitch:
+           logging.warn("i2c switch disabled!")
+
+    def clearSwitch(self):
+        for x in range(self.SWcnt): self.CurrentChannel[x]=-1;
+
+    def SetSW1(self,channelbit):
+#        channel=(0 if (channelbit>5) else 1<<(channelbit)) #LTS
+        if self.NoSwitch: return True;
+        SWn=channelbit>>3;
+        channel=1<<(channelbit & 0x07)
+        result=True
+        for x in range(self.SWcnt):
+           if x==SWn:
+              if (channel)!=self.CurrentChannel[x]:
+                 self.CurrentChannel[x]=channel
+                 logging.debug("SetChannel addr %i = val %i" % (SWn,channel));
+                 if not(self.i2csetget(self.SWaddrs[x],[channel])): result=False
+           else:
+              if self.CurrentChannel[x]!=0:
+                 logging.debug("SetChannel addr %i = val %i" % (x,0));
+                 self.CurrentChannel[x]=0
+                 if not(self.i2csetget(self.SWaddrs[x],[0])): result=False
+        if not(result): logging.info("Switch set error!")
+        return result
+
+    def ClearNewChannel(self):
+        self.newChannel=[0 for x in self.SWaddrs]+[0];#last one is a dummy
+
+    def AddNewChannel(self,channelbit):
+        SWn=(channelbit>>3);
+        channel=1<<(channelbit & 0x07)
+        self.newChannel[SWn]|=channel;
+
+    def UpdateNewChannel(self):
+#        channel&=0x3F;#LTS
+        if self.NoSwitch: return True;
+        for x in range(self.SWcnt):
+              if self.newChannel[x]!=self.CurrentChannel[x]:
+                self.CurrentChannel[x]=self.newChannel[x];
+                logging.debug("SetChannel2 addr %i = val %i" % (x,self.newChannel[x]));
+                if not(self.i2csetget(self.SWaddrs[x],[self.newChannel[x]])): return False;
+#        logging.debug("SetChannel=%i" % channel)
+#        self.CurrentChannel=channel
+        return True
+
+#    def I2Ccallback(self,RCU,addr,data,reg=None,read=0):
+#        self.callback1(addr,data,reg,read)    
-- 
GitLab