diff --git a/APSPU_I2C.py b/APSPU_I2C.py index 876263b9bc9a34566404cbf7438e9328d476dc3b..7d3584dea5e1b107bf10cb281de6694f7b0722f8 100644 --- a/APSPU_I2C.py +++ b/APSPU_I2C.py @@ -1,70 +1,116 @@ -#******************************************# -# I2C address, registers and ports for UNB2c -# Created: 2021-05-11 -#******************************************# +""" +Copyright 2022 Stichting Nederlandse Wetenschappelijk Onderzoek Instituten, +ASTRON Netherlands Institute for Radio Astronomy +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. -################################### + + Created: 2022-12-07 +This file contains the definitions of the APSPU registers etc. + + +""" +# +# I2C address, registers and ports for APSPU +# Created: 2022-12-07 +# + +# # General, Point of load converters -################################### +# -CTR_LBA = 0x3C +CTR_LBA = 0x3C CTR_RCU2_A = 0x3D CTR_RCU2_D = 0x0E -CTR_POLS = {"CTR_LBA" : 0x3C, - "CTR_RCU2_A" : 0x3D, - "CTR_RCU2_D" : 0x3E} +CTR_POLS = {"CTR_LBA": 0x3C, + "CTR_RCU2_A": 0x3D, + "CTR_RCU2_D": 0x3E} + +VOUT_POLS = {"CTR_LBA": 8.0, + "CTR_RCU2_A": 5.60009765625, + "CTR_RCU2_D": 3.2998046875} + +IOUT_POLS = {"CTR_LBA": 0.45, + "CTR_RCU2_A": 0.7, + "CTR_RCU2_D": 0.3} -LP_VOUT_MODE = 0x20 -LP_VOUT = 0x8B # -LP_temp = 0x8D # -LP_IOUT = 0x8C +LP_VIN = 0x88 +LP_VOUT_MODE = 0x20 +LP_VOUT = 0x8B +LP_temp = 0x8D +LP_IOUT = 0x8C +LP_VOUT_COMMAND = 0x21 +LP_VOUT_TRIM = 0x22 +LP_VOUT_MAX = 0x24 +LP_VOUT_SCALE_LOOP = 0x29 +LP_VOUT_SCALE_MON = 0x2A +LP_VOUT_OV_LIMIT = 0x40 +LP_VOUT_UV_LIMIT = 0x44 +LP_STORE_USER_ALL = 0x15 +LP_ON_OFF_CONFIG = 0x02 +LP_OPERATION = 0x01 -################################### +# # Central I2C Devices -################################### -EEPROM = 0x50 +# +EEPROM = 0x50 -################################### +# # FAN speed -################################### -MAX6620 = 0x29 +# +MAX6620 = 0x29 REG_GLOBAL = 0x00 -REG_TACH_MSP_REGS = [ 0x10, 0x12, 0x14] -REG_TACH_LSP_REGS = [ 0x11, 0x13, 0x15] +REG_TACH_MSP_REGS = [0x10, 0x12, 0x14] +REG_TACH_LSP_REGS = [0x11, 0x13, 0x15] TACH_PERIODS = 16 TACH_COUNT_FREQ = 8192 FAN_TACHS = 1 RUN_MONITOR = 0x02 - NOF_APS_FANS = 3 -###################### +# # Functions -###################### +# + -# Calculate floating point value according PMBus lineair def calc_lin_2bytes(data): - expo = ((data[1] & 0xf8)>>3) + # + # Calculate floating point value according PMBus lineair + # + # input data (Byte array) + # return value (float) + # + expo = ((data[1] & 0xf8) >> 3) if expo == 1: expo = -7 if expo > (2**4): expo = expo-2**5 mantisse = (data[1] & 0x7)*0x100 + data[0] if mantisse > (2**(8+2)): - mantisse = mantisse -2**(8+3) + mantisse = mantisse - 2**(8 + 3) output = mantisse * 2**expo return output -# Calculate floating point value according PMBus lineair -def calc_lin_3bytes(data,mode): - expo = (mode[0] & 0x1F) + +def calc_lin_3bytes(data, mode): + # + # Calculate floating point value according PMBus lineair + # + # input data (Byte array) + # return value (float) + # + expo = (mode[0] & 0x1F) if expo > 2**4: expo = expo - 2**5 mant = (data[1]*256 + data[0]) output = mant * 2**expo return output - - - diff --git a/CCD_I2C.py b/CCD_I2C.py deleted file mode 100644 index 806538001701e1a8a1581be5a79454079e93af49..0000000000000000000000000000000000000000 --- a/CCD_I2C.py +++ /dev/null @@ -1,355 +0,0 @@ -''' -Copyright 2021 Stichting Nederlandse Wetenschappelijk Onderzoek Instituten, -ASTRON Netherlands Institute for Radio Astronomy -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -Set CCD - -''' -import sys -import time -import math -sys.path.insert(0,'.') -import os -if os.name =="posix": - from I2C_serial_pi2 import * -else: - from I2C_serial import * - -DEBUG = False -I2CBUSNR=1 -sleep_time = 0.05 -SET_PLL = True -READ_LOCK = True -READ_ALL = False -CHECK_EEPROM = True -PWR_RST = False -READ_SENSOR = False -READ_SET_FAN = True -CLK_FREQ = '200MHz' -dev_i2c_eeprom = I2C(0x50) -dev_i2c_eeprom.bus_nr = I2CBUSNR - -CS = 6 -SCLK = 4 -SDO = 5 -SDI = 7 -PLL_addr = 0x20 - - -def Write_byte_PLL(reg_address, wr_data, ADDRESS=0x20): - # - # Write Byte to the ADC - # - I2C_device = I2C(ADDRESS, BUSNR=I2CBUSNR) - PLL_rw = 0x00 # 0 for write, 1 for read - stri = "Write : 0x{0:{fill}2x} to Address : 0x{1:{fill}2x}".format(wr_data, reg_address, fill='0') - print(stri) - I2C_device.write_bytes(0x06, 0x2C) - if DEBUG: - rd_bytes = I2C_device.read_bytes(0x06, 1) - stri = "IO expander wrote 0x{0:x}, read 0x{1}".format(0x2C, rd_bytes[1]) - print(stri) - data = (reg_address << 9) + (PLL_rw << 8) + wr_data - bit_array = "{0:{fill}16b}".format(data, fill='0') - I2C_device.write_bytes(0x02, 0x02 | (0x1 << CS)) - for bit in bit_array: - for clk in range(2): - Write_data = 0x02 | (0 << CS) | (clk << SCLK) | (int(bit) << SDI) - I2C_device.write_bytes(0x02, Write_data) - for clk in range(2): - Write_data = 0x02 | (0 << CS) | (clk << SCLK) - I2C_device.write_bytes(0x02, Write_data) - for clk in range(2): - Write_data = 0x02 | (1 << CS) | (clk << SCLK) - I2C_device.write_bytes(0x02, Write_data) - - Write_data = 0x02 | (1 << CS) | (0 << SCLK) | (0 << SDI) - I2C_device.write_bytes(0x02, Write_data) - if DEBUG: - read_bits = Read_byte_PLL(reg_address, nof_bytes=1, ADDRESS=ADDRESS) -# stri = "Bits written 0x{0:x} to register 0x{1:x} read from PLL are {2}".format(wr_data, reg_address, read_bits) -# print(stri) - - -def Read_byte_PLL(reg_address, nof_bytes=1, ADDRESS=0x20 ): - # - # Read Byte from the ADC - # - I2C_device = I2C(ADDRESS, BUSNR=I2CBUSNR) - PLL_rw = 0x01 # 0 for write, 1 for read - - I2C_device.write_bytes(0x06, 0x2C) - data = ( reg_address << 7 ) + PLL_rw - - - bit_array = "{0:{fill}8b}".format(data, fill='0') - for bit in bit_array: - for clk in range(2): - Write_data = 0x02 | (0 << CS) | (clk << SCLK) | ( int(bit) << SDI) - I2C_device.write_bytes(0x02, Write_data) -# sleep(sleep_time) - -# print("read byte") - read_bit = '' - for cnt in range(8*nof_bytes): - for clk in [0, 1]: # Read after rizing edge - Write_data = 0x02 | (clk << SCLK) | ( int(bit) << SDI ) - I2C_device.write_bytes(0x02, Write_data) - ret_ack, ret_value = I2C_device.read_bytes(0x00, 1) -# stri= "ret_value = {}".format(int(ret_value,16)) -# print(stri) - if ret_ack: - read_bit += str((int(ret_value, 16) >> SDO) & 0x01) - else: - print("ACK nok") - Write_data = 0x02 | (1 << CS) | (0 << SCLK) | (0 << SDI) - I2C_device.write_bytes(0x02, Write_data) - stri = "Read back at address 0x{0:{fill}2x} result : 0x{1:{fill}2x} ".format(reg_address, int(read_bit, 2), fill='0') - print(stri) - return read_bit; - - -def setup_pll() : - I2C_device = I2C(0x20, BUSNR=I2CBUSNR) #clock selection - I2C_device.write_bytes(0x07, 0x00) - Write_byte_PLL(0x03, 0x08, PLL_addr) - Write_byte_PLL(0x04, 0xFF, PLL_addr) # CF disable not used outputs, 00 enable all - Write_byte_PLL(0x05, 0xD7, PLL_addr) - Write_byte_PLL(0x06, 0xE0, PLL_addr) # cp inv = 0xF4 other 0xE4 - Write_byte_PLL(0x07, 0x04, PLL_addr) # Divider R = 1 dec - Write_byte_PLL(0x08, 0x01, PLL_addr) - Write_byte_PLL(0x07, 0x00, PLL_addr) - Write_byte_PLL(0x09, 0x10, PLL_addr) - Write_byte_PLL(0x0A, 0x01, PLL_addr) - Write_byte_PLL(0x09, 0x00, PLL_addr) - Write_byte_PLL(0x0B, 0x00, PLL_addr) - Write_byte_PLL(0x0D, 0x01, PLL_addr) - Write_byte_PLL(0x0E, 0x00, PLL_addr) - Write_byte_PLL(0x0F, 0x01, PLL_addr) - Write_byte_PLL(0x10, 0x00, PLL_addr) - Write_byte_PLL(0x11, 0x01, PLL_addr) - Write_byte_PLL(0x12, 0x00, PLL_addr) - Write_byte_PLL(0x13, 0x01, PLL_addr) - Write_byte_PLL(0x14, 0x01, PLL_addr) - - - -def power(state): - I2C_IO_device_A = I2C(0x20, BUSNR=I2CBUSNR) - I2C_IO_device_A.write_bytes(0x06, 0x2C) # '0' is output - I2C_IO_device_A.write_bytes(0x07, 0x00) # '0' is output - I2C_IO_device_B = I2C(0x21, BUSNR=I2CBUSNR) - I2C_IO_device_B.write_bytes(0x06, 0x2C) # '0' is output - if state: - bits_to_set_A1 = 0x02 | (1 << CS) | (0 << SCLK) | (0 << SDI) - bits_to_set_A2 = 0x04 - bits_to_set_B1 = 0x02 | (1 << CS) | (0 << SCLK) | (0 << SDI) - else: - bits_to_set_A1 = 0x00 | (1 << CS) | (0 << SCLK) | (0 << SDI) - bits_to_set_A2 = 0x00 - bits_to_set_B1 = 0x00 | (1 << CS) | (0 << SCLK) | (0 << SDI) - if DEBUG : - stri = "Bits to reg 0 0x{0:x}".format(bits_to_set_A1) - print(stri) - I2C_IO_device_A.write_bytes(0x02, bits_to_set_A1) - I2C_IO_device_A.write_bytes(0x03, bits_to_set_A2) - I2C_IO_device_B.write_bytes(0x02, bits_to_set_B1) - -def write_eeprom( data=0x01): - # - # Write the EEPROM with the serial number etc. - # - ret_ack, ret_value = dev_i2c_eeprom.read_bytes(0) - if ret_ack < 1: - print("EEPROM not found during write") - return False - else: - dev_i2c_eeprom.write_bytes(0x00, data) - sleep(0.1) - return True - -def read_eeprom(): - # - # Read the EEPROM with the serial number etc. - # - ret_ack, ret_value = dev_i2c_eeprom.read_last_reg(1) - if ret_ack < 1: - print("no EEPROM found during read") - return False - else: - ret_ack, ret_value = dev_i2c_eeprom.read_bytes(0x00, 1) - return ret_value - -def wr_rd_eeprom(value=0x34): - # - # Write and Read the EEPROM to check functionality - # - if write_eeprom(value): - ret_value = read_eeprom() - stri = "Wrote to EEPROM: 0x{0:X}, Read from EEPROM: 0x{1} ".format(value, ret_value) - print(stri) - return True - -def ccd_sensors(): - for sens_line in range(7): - read_voltage(sens_line) - read_temp() - -def read_voltage(input_channel=0): - addr = 0x74 - Vref = 3.0 - one_step = Vref/(2**(16)) - I2C_device = I2C(addr, BUSNR=I2CBUSNR) - channel_select_word = 0xB0 | ((input_channel%2) << 3) | ((input_channel >> 1) & 0x7) - if DEBUG: - stri = "Word to select sens input is 0x{0:x}".format(channel_select_word) - print(stri) - sleep(0.5) - I2C_device.write_bytes(channel_select_word, 0xB8) - sleep(0.5) - ret_ack, ret_value = I2C_device.read_last_reg(3) - if 1: #ret_ack: - if DEBUG: - stri = "Return value input 0 : 0x{0} ".format(ret_value) - print(stri) - if int(ret_value, 16) >= 0xC00000: - print("over range") - else: - steps = (int(ret_value, 16) & 0x1FFFFF) >> 6 - voltage = one_step * steps - voltage = ((4.7+2.2)/2.2)*2*voltage - string = "Voltage sens line {1} is {0:.4f} V".format(voltage, input_channel) - print(string) - else: - stri = " No ACK on device 0x{0:x} ".format(addr) - print(stri) - -def read_temp(): - Vref = 3.0 - addr = 0x74 - one_step = Vref/(2**(16)) - I2C_device = I2C(addr, BUSNR=I2CBUSNR) - temp_slope = 93.5E-6 * 2**(16+1) / Vref - sleep(0.5) - I2C_device.write_bytes(0xA0, 0xC0) - sleep(0.5) - ret_ack, ret_value = I2C_device.read_last_reg(3) - if ret_ack: - raw_value = (int(ret_value, 16) & 0x1FFFFF) >> 6 - temperature_K = (raw_value/temp_slope) - temperature = temperature_K-273 - stri = "Temperature : {0:.2f} gr. C".format(temperature) - print(stri) - else: - print("Error reading tempeature") - -def set_fan_off(): - # - # Switch CCD fan off - # - print("Switch fan off") - MAX6620 = 0x29 - fanmonitor_dev = I2C(MAX6620) - fanmonitor_dev.bus_nr = 3 - fanmonitor_dev.write_bytes(0x00, 0x10) - fanmonitor_dev.write_bytes(0x02, 0x08) - fanmonitor_dev.write_bytes(0x28, 0x00) - fanmonitor_dev.write_bytes(0x29, 0x00) - -def set_fan_speed(speed): - # - # Set control voltage of fan PNP - # - stri = "Set fan to {} %".format(speed) - print(stri) - MAX6620 = 0x29 - reg_a = ((0xFF*speed)/100) & 0xFF - fanmonitor_dev = I2C(MAX6620) - fanmonitor_dev.bus_nr = 3 - fanmonitor_dev.write_bytes(0x00, 0x00) - fanmonitor_dev.write_bytes(0x02, 0x08) - fanmonitor_dev.write_bytes(0x01, 0x0F) - fanmonitor_dev.write_bytes(0x06, 0x60) - fanmonitor_dev.write_bytes(0x28, reg_a) - fanmonitor_dev.write_bytes(0x29, 0x80) - - -def read_tacho(): - # - # Read the fan speed - # - MAX6620 = 0x29 - REG_TACH_MSP_REGS = [ 0x10, 0x12, 0x14] - REG_TACH_LSP_REGS = [ 0x11, 0x13, 0x15] - TACH_PERIODS = 16 - TACH_COUNT_FREQ = 8192 - FAN_TACHS = 1 - DEBUG=1 - fanmonitor_dev = I2C(MAX6620) - fanmonitor_dev.bus_nr = 3 - fan_nr=0 - ret_ack, ret_value = fanmonitor_dev.read_bytes(1) - if ret_ack < 1: - stri = " Device {0} at address 0x{1:X} not found".format("MAX6620", MAX6620) - print(stri) - status = False - ret_ack, tach_msb = fanmonitor_dev.read_bytes(REG_TACH_MSP_REGS[0], 1) - tach_msb = int(tach_msb, 16) & 0xFF - if tach_msb > 254: - if DEBUG : - tach_lsb = 255 - tach = 99999 - rpm = 0 - else: - ret_ack, tach_lsb = fanmonitor_dev.read_bytes(REG_TACH_LSP_REGS[0], 1) - tach_lsb = int(tach_lsb, 16) & 0xE0 - tach = tach_msb*16 + tach_lsb/8 - rpm = float((TACH_COUNT_FREQ*TACH_PERIODS*60))/(FAN_TACHS*tach) - if DEBUG: - stri = "MSP: {0}, LSB: {1}, TACH : {2}, RPM : {3:6.2f}".format(tach_msb, tach_lsb, tach, rpm) - print(stri) - -if CHECK_EEPROM : - wr_rd_eeprom() - -if PWR_RST : - power(False) - sleep(10) - power(True) - -if SET_PLL : - setup_pll() - -if READ_LOCK: - ret_value = Read_byte_PLL(0x00, nof_bytes = 1, ADDRESS=PLL_addr) - status_pll = int(ret_value,2) - if status_pll == 0x04: - print("PLL in lock") - elif (status_pll & 0x10) > 0: - print("Not Locked --> No 10 MHz ref") - else: - print("Not locked --> PLL Error") -if READ_SET_FAN : - read_tacho() - set_fan_off() - sleep(10) - read_tacho() - set_fan_speed(75) - sleep(10) - read_tacho() - set_fan_speed(100) - sleep(10) - read_tacho() - - -if READ_SENSOR: - ccd_sensors() diff --git a/I2C_serial_pi2.py b/I2C_serial_pi2.py index ce05e27972d977799ae42497650663c2f070c545..5ae5af3976e9d28807f0eaa4b0f894a72ff1b8ec 100644 --- a/I2C_serial_pi2.py +++ b/I2C_serial_pi2.py @@ -38,12 +38,14 @@ class I2C: try: (count, rd_value) = pi.i2c_read_i2c_block_data(bus, register, bytes_to_read) ret_value = '' + if len(rd_value) < bytes_to_read: + return False, 999 for cnt in range(bytes_to_read): ret_value += (hex(rd_value[cnt])[2:]) ret_ack = 1 if SLOW: sleep(0.2) - except IOError, err: + except IOError: ret_ack = 0 ret_value = 'ffff' if DEBUG: @@ -65,7 +67,7 @@ class I2C: ret_ack = 1 if SLOW: sleep(0.2) - except IOError, err: + except IOError: ret_ack = 0 rd_value = [0]*bytes_to_read if DEBUG: @@ -77,12 +79,14 @@ class I2C: def write_bytes(self, register, data): bus = pi.i2c_open(self.bus_nr, self.I2C_Address) + if type(data) is not list: + data = [data] try: - pi.i2c_write_i2c_block_data(bus, register, [data]) + pi.i2c_write_i2c_block_data(bus, register, data) ret_ack = 1 if SLOW: sleep(0.3) - except IOError, err: + except IOError: ret_ack = 0 ret_value = 0 if DEBUG: @@ -97,7 +101,7 @@ class I2C: ret_ack = 1 if SLOW: sleep(0.3) - except IOError, err: + except IOError: ret_ack = 0 ret_value = 0 if DEBUG: @@ -113,7 +117,7 @@ class I2C: ret_ack = 1 if SLOW: sleep(0.3) - except IOError, err: + except IOError: ret_ack = 0 ret_value = 0 if DEBUG: diff --git a/apspu_lib.py b/apspu_lib.py new file mode 100644 index 0000000000000000000000000000000000000000..4cb45a8d5f7e0a2d38a0112e5440a46fe04bb973 --- /dev/null +++ b/apspu_lib.py @@ -0,0 +1,603 @@ +""" +Copyright 2021 Stichting Nederlandse Wetenschappelijk Onderzoek Instituten, +ASTRON Netherlands Institute for Radio Astronomy +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + + Created: 2022-17-12 +This file contains the APSPU class with all monitoring function. It can be used stand-alone to test it. + +""" + +import sys +sys.path.insert(0, '.') +import os +import math +from APSPU_I2C import * + + +if os.name == "posix": + from I2C_serial_pi2 import * +else: + from I2C_serial import * + +I2CBUSNR = 1 # Bus used on the Pi +DEBUG = False # Set True to print debug information on the screen + + +class ApspuClass: + # + # Toplevel Class that contains all parts on a APSU + # + def __init__(self): + self.status = False + self.pols = [] + for pol in list(CTR_POLS.keys()): + self.pols.append(PolClass(pol)) + self.fans = FanmonitorClass() + self.eeprom = EepromClass() + + def read_all(self): + # + # Function to read all monitoring points of the APSPU + # + print("--------- \nRead APSPU Status\n---------") + for pol in self.pols: + pol.read_all() + self.fans.read_all() + return True + + def print_status(self): + # + # Function to dump monitoring information on the screen + # + for pol in self.pols: + pol.print_status() + self.fans.print_status() + return True + + def set_pols(self): + # + # Function to set output voltage level on the APSPU + # Values are read from the APSPU_I2C + # + print("--------- \nProgram Pols\n---------") + for pol in self.pols: + pol.set_vout_pol(VOUT_POLS[pol.name]) + vout = pol.read_vout_set() + if not (0.9*VOUT_POLS[pol.name] < vout < 1.1*VOUT_POLS[pol.name]): + print(f"POL {pol.name:10} Error setting Vout, " + f"set to {VOUT_POLS[pol.name]} read back {vout}") + exit() + pol.set_vout_ov_limit_pol(1.2*VOUT_POLS[pol.name]) + ov_out = pol.read_ov_limit() + if not (1.1*VOUT_POLS[pol.name] < ov_out < 1.3*VOUT_POLS[pol.name]): + print(f"POL {pol.name:10} Error setting output overvoltage" + f"set {1.2*VOUT_POLS[pol.name]} read back {ov_out}") + exit() + pol.set_on_off_config() + pol.write_to_nvm() + print("Done") + + def check_apspu(self): + # + # Function to check values of read_all() Used during production + # + # Return True is OK, False if not OK + # + print("--------- \nCheck APSPU \n---------") + check_ok = True + for pol in self.pols: + check_ok = check_ok & pol.check_pol() + check_ok = check_ok & self.fans.check_fans() + check_ok = check_ok & self.eeprom.wr_rd_eeprom(value="PROD_CHECK", address=0x30) + if check_ok: + print("APSPU OK") + else: + print(">>> APSPU NOT OK <<<") + return check_ok + + def apspu_on_off(self, on): + # + # Function to switch off the POLs on APSPU + # on = True to switch APSU on + # on = False to switch APSU off + # Return: always True + # + if on: + print(f">> Switch APSPU ON") + else: + print(">> Switch APSPU OFF") + for pol in self.pols: + pol.on_off(on) + return True + + +class EepromClass: + # + # Class to handle EEPROM communication + # + def __init__(self): + # + # All monitor. read and write functions for the EEPROM + # + self.dev_i2c_eeprom = I2C(EEPROM) + self.dev_i2c_eeprom.bus_nr = I2CBUSNR + + def write_eeprom(self, data="APSPU", address=0): + # + # Write the EEPROM with the serial number etc. + # + # Data = data to write in string formal + # Address = address to write the data to + # Return True if successfully + # + ret_ack, ret_value = self.dev_i2c_eeprom.read_bytes(0) + if ret_ack < 1: + print("EEPROM not found during write") + return False + else: + wr_data = bytearray(data.encode("utf-8", errors="ignore")) + for loc, data_byte in enumerate(wr_data): + self.dev_i2c_eeprom.write_bytes(address+loc, data_byte) + sleep(0.1) + return True + + def read_eeprom(self, address=0, nof_bytes=5): + # + # Read the EEPROM with the serial number etc. + # + # Address = address to read from + # nof_bytes = number of bytes to read + # return string with the data from the flash + # + ret_ack, ret_value = self.dev_i2c_eeprom.read_last_reg(1) + if ret_ack < 1: + print("no EEPROM found during read") + return False + else: + ret_ack, ret_value = self.dev_i2c_eeprom.read_bytes(address, nof_bytes) + str_return = bytes.fromhex(ret_value[:nof_bytes*2]).decode('UTF-8') + return str_return + + def wr_rd_eeprom(self, value="APSPU-1", address=0): + # + # Write and Read the EEPROM to check functionality + # + # value = string with data to write + # address = address to write the data to + # return True if read back is same as write value + # + if self.write_eeprom(value, address=0): + ret_value = self.read_eeprom(address=0, nof_bytes=len(value)) + stri = "Wrote to EEPROM register 0x{2:x} : {0}, Read from EEPROM: {1}".format(value, ret_value, address) + print(stri) + if ret_value == value: + return True + else: + return False + + +class PolClass: + # + # Class to read all monitoring points Point of Load DC/DC converter + # + def __init__(self, name): + # + # All monitoring points Point of Load DC/DC converter + # + self.name = name + self.vout = 0 + self.vin = 0 + self.iout = 0 + self.temp = 0 + self.pol_dev = I2C(CTR_POLS[self.name]) + self.pol_dev.bus_nr = I2CBUSNR + ret_ack, ret_value = self.pol_dev.read_bytes(1) + if ret_ack < 1: + stri = " Device {0} at address 0x{1:X} not found".format(self.name, CTR_POLS[self.name]) + print(stri) + self.status = False + else: + self.status = True + + def read_vout_set(self): + # + # Function to read the output voltage of the Point of Load DC/DC converter + # + # Return: output value is of else 999 + # + if self.status: + ret_ack, raw_value = self.pol_dev.read_bytes(LP_VOUT_COMMAND, 2) + if len(raw_value) < 4: + raw_value = '0' + raw_value + ret_value = int(raw_value[2:], 16) * 2**8 + ret_value += int(raw_value[:2], 16) + output_value = ret_value * 2**-11 + if DEBUG: + print(f"Output set to: = {output_value:5.2f} V using hex value {raw_value}") + return output_value + else: + return 999 + + def set_on_off_config(self): + # + # Function to set the output of the DC/DC converter + # + # Return always I2C ack + # + ret_ack = False + if self.status: + if DEBUG: + ret_ack, raw_value = self.pol_dev.read_bytes(LP_ON_OFF_CONFIG, 1) + print(f"Current setting ON/OFF register 0x{int(raw_value, 16):02x}") + on_off_bit = not 1 << 0 + polarity_pin = 1 << 1 + use_external = 0 << 2 + use_soft = 1 << 3 + default_off = 1 << 4 + wr_data = on_off_bit + polarity_pin + use_external + use_soft + default_off + ret_ack = self.pol_dev.write_bytes(LP_ON_OFF_CONFIG, wr_data) + return ret_ack + + def on_off(self, on=True): + # + # Function to switch on or off a POL + # + # if on = True switch on the POL + # if on = Flase swtich off the POL + # Return I2C ack + # + wr_data = (on << 7) + 0 + ret_ack = self.pol_dev.write_bytes(LP_OPERATION, wr_data) + return ret_ack + + def set_vout_pol(self, value): + # + # Function to read the output voltage of the Point of Load DC/DC converter + # + # value is the output voltage level in V + # return I2C ack + # + ret_ack = False + if self.status: + set_value = int(value * (2**11)) + hex_set_value = hex(set_value) + wr_value = (hex_set_value[4:6] + hex_set_value[2:4]) + if DEBUG: + print(f"Calculated wr_value is {wr_value}") + wr_data = [] + wr_data.append(int(hex_set_value[4:6], 16)) + wr_data.append(int(hex_set_value[2:4], 16)) + ret_ack = self.pol_dev.write_bytes(LP_VOUT_COMMAND, wr_data) + return ret_ack + + def set_vout_ov_limit_pol(self, value): + # + # Function to read the output voltage of the Point of Load DC/DC converter + # + # value is the overvoltage level of the output + # return I2C ack + # + ret_ack = False + if self.status: + set_value = int(value * (2**11)) + hex_set_value = hex(set_value) + wr_value = (hex_set_value[4:6] + hex_set_value[2:4]) + if DEBUG: + print(f"Calculated wr_value is {wr_value}") + wr_data = [] + wr_data.append(int(hex_set_value[4:6], 16)) + wr_data.append(int(hex_set_value[2:4], 16)) + ret_ack = self.pol_dev.write_bytes(LP_VOUT_OV_LIMIT, wr_data) + return ret_ack + + def write_to_nvm(self): + # + # Function to write the POL's registers to NVM memory + # + # return is always True + # + ret_ack = self.pol_dev.write_bytes(LP_STORE_USER_ALL, 0) + return True + + def read_vin(self): + # + # Function to read the output voltage of the Point of Load DC/DC converter + # + if self.status: + ret_ack, raw_value = self.pol_dev.read_bytes(LP_VIN, 2) + if not ret_ack: + self.iout=999 + return False + if len(raw_value) < 4: + raw_value = '0' + raw_value + ret_value = [] + ret_value.append(int(raw_value[:2], 16)) + ret_value.append(int(raw_value[2:], 16)) + output_value = calc_lin_2bytes(ret_value) + self.vin = output_value + return True + + def read_vout(self): + # + # Function to read the output voltage of the Point of Load DC/DC converter + # + if self.status: + ret_ack, vout_mod = self.pol_dev.read_bytes(LP_VOUT_MODE, 1) + if not ret_ack: + self.vout=999 + return False + ret_ack, raw_value = self.pol_dev.read_bytes(LP_VOUT, 2) + if not ret_ack: + self.vout=999 + return False + vout_mod = int(vout_mod, 16) + ret_value = [] + ret_value.append(int(raw_value[:2], 16)) + try: + ret_value.append(int(raw_value[2:], 16)) + except: + ret_value.append(0) + self.vout = calc_lin_3bytes(ret_value, [vout_mod]) + return True + else: + self.vout = 999 + return False + + def read_ov_limit(self): + # + # Function to read the output voltage of the Point of Load DC/DC converter + # and print on the screen + # + # Return OV limit + # + output_value = 0 + if self.status: + ret_ack, raw_value = self.pol_dev.read_bytes(LP_VOUT_OV_LIMIT, 2) + if len(raw_value) < 4: + raw_value = '0' + raw_value + ret_value = int(raw_value[2:], 16) * 2**8 + ret_value += int(raw_value[:2], 16) + output_value = ret_value * 2**-11 + if DEBUG: + print(f"Output OV limit is set to: = {output_value:5.2f} V using hex value {raw_value}") + return output_value + + def read_uv_limit(self): + # + # Function to read the output voltage of the Point of Load DC/DC converter + # + # Return UV limit if OK else False + # + if self.status: + ret_ack, raw_value = self.pol_dev.read_bytes(LP_VOUT_UV_LIMIT, 2) + if len(raw_value) < 4: + raw_value = '0' + raw_value + ret_value = [] + ret_value = int(raw_value[2:], 16) * 2**8 + ret_value += int(raw_value[:2], 16) + output_value = ret_value * 2**-11 + if DEBUG: + print(f"Output UV limit is set to: = {output_value:5.2f} V using hex value {raw_value}") + return output_value + else: + return False + + def read_iout(self): + # + # Function to read the output current of the Point of Load DC/DC converter + # + if self.status: + ret_ack, raw_value = self.pol_dev.read_bytes(0x39, 2) + ret_ack, raw_value = self.pol_dev.read_bytes(LP_IOUT, 2) + ret_value = [] + ret_value.append(int(raw_value[:2], 16)) + ret_value.append(int(raw_value[2:], 16)) + self.iout = calc_lin_2bytes(ret_value) + else: + self.iout = 999 + + def read_temp(self): + # + # Function to read the temperature of the Point of Load DC/DC converter + # + if self.status: + ret_ack, raw_value = self.pol_dev.read_bytes(LP_temp, 2) + ret_value = [] + ret_value.append(int(raw_value[:2], 16)) + ret_value.append(int(raw_value[2:], 16)) + self.temp = calc_lin_2bytes(ret_value) + else: + self.temp = 999 + + def read_all(self): + # + # Function to read all monitoring points of the Point of Load DC/DC converter + # + self.read_vout() + self.read_iout() + self.read_temp() + self.read_vin() + + def check_pol(self): + # + # Function to read all monitoring points of the Point of Load DC/DC converter + # + # Return True if OK, False if not OK + # + self.read_all() + self.on_off(on=True) + check_ok = False + expected_vout = VOUT_POLS[self.name] + if 0.9*expected_vout < self.vout < 1.1*expected_vout: + check_ok = True + else: + check_ok = False + print(f"POL {self.name:10} Vout not OK, expected {expected_vout} V, measured {self.vout} V") + return check_ok + vin_low = 45 + vin_high = 50 + if vin_low < self.vin < vin_high: + check_ok = True + else: + check_ok = False + print(f"POL {self.name:10} Vin not OK, expected {vin_low} V - {vin_high} V, measured {self.vout} V ") + return check_ok + temp_low = 20 + temp_high = 50 + if temp_low < self.temp < temp_high: + check_ok = True + else: + check_ok = False + print(f"POL {self.name:10} TEMP not OK, expected {temp_low} C - {temp_high} C, measured {self.temp} C ") + return check_ok + i_low = 0.75*IOUT_POLS[self.name] + i_high = 1.25*IOUT_POLS[self.name] + if i_low < self.iout < i_high: + check_ok = True + else: + check_ok = False + print(f"POL {self.name:10} Iout not OK," + f" expected {i_low:4.2f} A - {i_high:4.2f} A, measured {self.iout:4.2f} A ") + return check_ok + + def print_status(self): + # + # Function to dump all monitoring points of the Point of Load DC/DC converter on the screen + # + if self.status: + stri = f"POL: {self.name:10} :" + stri += "Vin :{0: >5.2f} V ".format(self.vin) + stri += "Vout :{0: >5.2f} V ".format(self.vout) + stri += "Iout :{0: >5.2f} A ".format(self.iout) + stri += "Temp :{0: >5.2f} \N{DEGREE SIGN}C".format(self.temp) + print(stri) + self.read_vout_set() + + +class FanmonitorClass: + # + # Class to read all monitoring points fan units in the APS + # + def __init__(self): + # + # All monitoring points for the fans + # + self.rpm = [] + self.fanmonitor_dev = I2C(MAX6620) + self.fanmonitor_dev.bus_nr = I2CBUSNR + ret_ack, ret_value = self.fanmonitor_dev.read_bytes(1) + if ret_ack < 1: + stri = " Device {0} at address 0x{1:X} not found".format("MAX6620", MAX6620) + print(stri) + self.status = False + else: + if DEBUG: + stri = "Device {0} at address 0x{1:X} is found ".format("MAX6620", MAX6620) + print(stri) + self.set_active() + self.status = True + + def set_active(self): + # + # Function to activate monitoring + # + ret_ack, reg_before = self.fanmonitor_dev.read_bytes(REG_GLOBAL, 1) + self.fanmonitor_dev.write_bytes(REG_GLOBAL, RUN_MONITOR) + ret_ack, reg_after = self.fanmonitor_dev.read_bytes(REG_GLOBAL, 1) + if DEBUG: + stri = "Reg at address 0x{0} before : {1} and after write action {2}"\ + .format(REG_GLOBAL, reg_before, reg_after) + print(stri) + fan_config_reg = int((math.log(TACH_PERIODS) / math.log(2))) << 5 + for fan_cnt in range(NOF_APS_FANS): + self.fanmonitor_dev.write_bytes(0x02 + fan_cnt, 0x88) + self.fanmonitor_dev.write_bytes(0x06 + fan_cnt, fan_config_reg) + + def read_fan(self, fan_nr): + # + # Function to a single fan + # fan_nr is the fan to read ranging from 0 till 2 + # return the speed of the fan + # + if fan_nr > NOF_APS_FANS: + return 0 + ret_ack, tach_msb = self.fanmonitor_dev.read_bytes(REG_TACH_MSP_REGS[fan_nr], 1) + tach_msb = int(tach_msb, 16) & 0xFF + tach_lsb = 255 + tach = 99999 + if tach_msb > 254: + rpm = 0 + else: + ret_ack, tach_lsb = self.fanmonitor_dev.read_bytes(REG_TACH_LSP_REGS[fan_nr], 1) + tach_lsb = int(tach_lsb, 16) & 0xE0 + tach = tach_msb*16 + tach_lsb/8 + rpm = float((TACH_COUNT_FREQ*TACH_PERIODS*60))/(FAN_TACHS*tach) + if DEBUG: + stri = "MSP: {0}, LSB: {1}, TACH : {2}".format(tach_msb, tach_lsb, tach) + print(stri) + return rpm + + def read_all(self): + # + # Function to read all fan's + # + self.rpm = [] + for fan_counter in range(NOF_APS_FANS): + self.rpm.append(self.read_fan(fan_counter)) + + def check_fans(self): + # + # Function to check fan speeds + # + self.read_all() + check_ok = True + for cnt, speed in enumerate(self.rpm): + if speed < 10: + print(f"Low speed on fan {cnt}") + check_ok = False + return check_ok + + def print_status(self): + # + # Function to dump all monitoring points of the Point of Load DC/DC converter on the screen + # + if self.status: + stri = "Fan speeds of " + for fan_cnt in range(len(self.rpm)): + stri += "FAN_" + str(fan_cnt+1) + stri += " :{0: <5.2f} RPM ".format(self.rpm[fan_cnt]) + print(stri) + + +def main(): + # + # Function to test the class, read all info and dump on the screen + # + apspu = ApspuClass() + apspu.apspu_on_off(False) + sleep(5) + apspu.set_pols() + apspu.apspu_on_off(True) + sleep(10) + apspu.read_all() + apspu.print_status() + apspu.check_apspu() + apspu.apspu_on_off(False) + sleep(10) + apspu.read_all() + apspu.print_status() + apspu.apspu_on_off(True) + + +if __name__ == "__main__": + main() diff --git a/production_apspu.py b/production_apspu.py new file mode 100644 index 0000000000000000000000000000000000000000..6e4431caa69593e92d394075884a9ca7324746f0 --- /dev/null +++ b/production_apspu.py @@ -0,0 +1,47 @@ +""" +Copyright 2022 Stichting Nederlandse Wetenschappelijk Onderzoek Instituten, +ASTRON Netherlands Institute for Radio Astronomy +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + + Created: 2022-12-07 +This file contains the APSPU production script. + +""" + +import sys +sys.path.insert(0, '.') + +from apspu_lib import * + + +if len(sys.argv) < 2: + print("Production_apspy.py <ASTRON NR> <Serial number>") + print("e.g. python production_apspy.py 2022-01 1234") + exit() + +apspu = ApspuClass() +apspu.apspu_on_off(False) +sleep(5) # Wait for outputs to be stable off +apspu.set_pols() +input("Change dipswitches and press key to continue..") +apspu.apspu_on_off(True) +sleep(5) # Wait for outputs to be stable on +apspu.read_all() +apspu.print_status() +if apspu.check_apspu(): + apspu_id = "APSPU-" + sys.argv[1] + serial = sys.argv[2] + rw_ok = apspu.eeprom.wr_rd_eeprom(apspu_id, address=0) + if rw_ok: + rw_ok = apspu.eeprom.wr_rd_eeprom(serial, address=0x20) + if not rw_ok: + print("EEPROM Error") diff --git a/rd_apspu.py b/rd_apspu.py deleted file mode 100644 index 1d9e7ce6f298cb410a548b25a6eda1221d64b8f8..0000000000000000000000000000000000000000 --- a/rd_apspu.py +++ /dev/null @@ -1,280 +0,0 @@ -""" -Copyright 2021 Stichting Nederlandse Wetenschappelijk Onderzoek Instituten, -ASTRON Netherlands Institute for Radio Astronomy -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - - Created: 2021-05-10 -This file contains the UniBoard2 class with all monitoring function. It can be used stand-alone to test it. - -""" - -import sys -sys.path.insert(0, '.') -import os -import math -# import time -from APSPU_I2C import * -if os.name == "posix": - from I2C_serial_pi import * -else: - from I2C_serial import * - - -I2CBUSNR = 3 -DEBUG = False - -class ApspuClass: - # - # Class that contains all parts on a UniBoard2 - # - def __init__(self): - self.status = False - self.pols = [] - for pol in list(CTR_POLS.keys()): - self.pols.append(PolClass(pol)) - self.dev_i2c_eeprom = I2C(EEPROM) - self.dev_i2c_eeprom.bus_nr = I2CBUSNR - self.fans = FanmonitorClass() - - def write_eeprom(self, data=0x01): - # - # Write the EEPROM with the serial number etc. - # - ret_ack, ret_value = self.dev_i2c_eeprom.read_bytes(0) - if ret_ack < 1: - print("EEPROM not found during write") - return False - else: - self.dev_i2c_eeprom.write_bytes(0x00, data) - sleep(0.1) - return True - - def read_eeprom(self): - # - # Read the EEPROM with the serial number etc. - # - ret_ack, ret_value = self.dev_i2c_eeprom.read_last_reg(1) - if ret_ack < 1: - print("no EEPROM found during read") - return False - else: - ret_ack, ret_value = self.dev_i2c_eeprom.read_bytes(0x00, 1) - return ret_value - - def wr_rd_eeprom(self, value=0x34): - # - # Write and Read the EEPROM to check functionality - # - if self.write_eeprom(value): - ret_value = self.read_eeprom() - stri = "Wrote to EEPROM: 0x{0:X}, Read from EEPROM: 0x{1} ".format(value, ret_value) - print(stri) - return True - - def read_all(self): - # - # Function to read all monitoring points of the UniBoard - # - print("Read POLs") - for pol in self.pols: - pol.read_all() - self.fans.read_all() - return True - - def print_status(self): - # - # Function to dump monitoring information on the screen - # - print("Power supplies") - for pol in self.pols: - pol.print_status() - self.wr_rd_eeprom() - self.fans.print_status() - return True - - -class PolClass: - # - # Class to read all monitoring points Point of Load DC/DC converter - # - def __init__(self, name): - # - # All monitoring points Point of Load DC/DC converter - # - self.name = name - self.vout = 0 - self.iout = 0 - self.temp = 0 - self.pol_dev = I2C(CTR_POLS[self.name]) - self.pol_dev.bus_nr = I2CBUSNR - ret_ack, ret_value = self.pol_dev.read_bytes(1) - if ret_ack < 1: - stri = " Device {0} at address 0x{1:X} not found".format(self.name, CTR_POLS[self.name]) - print(stri) - self.status = False - else: - self.status = True - - - def read_vout(self): - # - # Function to read the output voltage of the Point of Load DC/DC converter - # - if self.status: - ret_ack, vout_mod = self.pol_dev.read_bytes(LP_VOUT_MODE, 1) - ret_ack, raw_value = self.pol_dev.read_bytes(LP_VOUT, 2) - vout_mod = int(vout_mod, 16) - ret_value = [] - ret_value.append(int(raw_value[:2], 16)) - ret_value.append(int(raw_value[2:], 16)) - self.vout = calc_lin_3bytes(ret_value, [vout_mod]) - else: - self.vout = 999 - - def read_iout(self): - # - # Function to read the output current of the Point of Load DC/DC converter - # - if self.status: - ret_ack, raw_value = self.pol_dev.read_bytes(0x39,2) - ret_ack, raw_value = self.pol_dev.read_bytes(LP_IOUT, 2) - ret_value = [] - ret_value.append(int(raw_value[:2], 16)) - ret_value.append(int(raw_value[2:], 16)) - self.iout = calc_lin_2bytes(ret_value) - else: - self.iout = 999 - - def read_temp(self): - # - # Function to read the temperature of the Point of Load DC/DC converter - # - if self.status: - ret_ack, raw_value = self.pol_dev.read_bytes(LP_temp, 2) - ret_value = [] - ret_value.append(int(raw_value[:2], 16)) - ret_value.append(int(raw_value[2:], 16)) - self.temp = calc_lin_2bytes(ret_value) - else: - self.temp = 999 - - def read_all(self): - # - # Function to read all monitoring points of the Point of Load DC/DC converter - # - self.read_vout() - self.read_iout() - self.read_temp() - - def print_status(self): - # - # Function to dump all monitoring points of the Point of Load DC/DC converter on the screen - # - if self.status: - stri = "POL: " + self.name + " " - stri += "Output voltage :{0: <5.2f} V ".format(self.vout) - stri += "Output Current :{0: <5.2f} A ".format(self.iout) - stri += "temperature :{0: <5.2f} Deg C".format(self.temp) - print(stri) - - -class FanmonitorClass: - # - # Class to read all monitoring points Point of Load DC/DC converter - # - def __init__(self): - # - # All monitoring points Point of Load DC/DC converter - # - self.rpm = [] - self.fanmonitor_dev = I2C(MAX6620) - self.fanmonitor_dev.bus_nr = I2CBUSNR - ret_ack, ret_value = self.fanmonitor_dev.read_bytes(1) - if ret_ack < 1: - stri = " Device {0} at address 0x{1:X} not found".format("MAX6620", MAX6620) - print(stri) - self.status = False - else: - if DEBUG: - stri = "Device {0} at address 0x{1:X} is found ".format("MAX6620", MAX6620) - print(stri) - self.set_active() - self.status = True - - def set_active(self): - # - # Function to activate monitoring - # - ret_ack, reg_before = self.fanmonitor_dev.read_bytes(REG_GLOBAL, 1) - self.fanmonitor_dev.write_bytes(REG_GLOBAL, RUN_MONITOR) - ret_ack, reg_after = self.fanmonitor_dev.read_bytes(REG_GLOBAL, 1) - if DEBUG: - stri = "Reg at address 0x{0} before : {1} and after write action {2}".format(REG_GLOBAL, reg_before, reg_after) - print(stri) - fan_config_reg = int((math.log(TACH_PERIODS) / math.log(2))) << 5 - for fan_cnt in range(NOF_APS_FANS): - self.fanmonitor_dev.write_bytes(0x02 + fan_cnt, 0x88) - self.fanmonitor_dev.write_bytes(0x06 + fan_cnt, fan_config_reg) - - def read_fan(self, fan_nr): - # - # Function to a single fan - # - ret_ack, tach_msb = self.fanmonitor_dev.read_bytes(REG_TACH_MSP_REGS[fan_nr], 1) - tach_msb = int(tach_msb, 16) & 0xFF - if tach_msb > 254: - if DEBUG : - tach_lsb = 255 - tach = 99999 - rpm = 0 - else: - ret_ack, tach_lsb = self.fanmonitor_dev.read_bytes(REG_TACH_LSP_REGS[fan_nr], 1) - tach_lsb = int(tach_lsb, 16) & 0xE0 - tach = tach_msb*16 + tach_lsb/8 - rpm = float((TACH_COUNT_FREQ*TACH_PERIODS*60))/(FAN_TACHS*tach) - if DEBUG: - stri = "MSP: {0}, LSB: {1}, TACH : {2}".format(tach_msb, tach_lsb, tach) - print(stri) - return rpm - - def read_all(self): - # - # Function to read all fan's - # - for fan_counter in range(NOF_APS_FANS): - self.rpm.append(self.read_fan(fan_counter)) - - def print_status(self): - # - # Function to dump all monitoring points of the Point of Load DC/DC converter on the screen - # - if self.status: - stri = "Fan speeds of " - for fan_cnt in range(len(self.rpm)): - stri += "FAN_" + str(fan_cnt+1) - stri += " :{0: <5.2f} RPM ".format(self.rpm[fan_cnt]) - print(stri) - - -def main(): - # - # Function to test the class, read all info and dump on the screen - # - apspu = ApspuClass() - print("read / write EEPROM") - apspu.wr_rd_eeprom(value=0x34) - apspu.read_all() - apspu.print_status() - - -if __name__ == "__main__": - main() diff --git a/spi_switch_Unb2c.py b/spi_switch_Unb2c.py index 9ddd737031091e3ed68a3ade7f1daf3a1f2b5ea6..713e7ea4fe37769fb8b2058bcf3d343177802139 100644 --- a/spi_switch_Unb2c.py +++ b/spi_switch_Unb2c.py @@ -31,6 +31,7 @@ import sys import spidev DEBUG=False +CRC = False #True # CRC or packet counter # We only have SPI bus 0 available to us on the Pi bus = 0 @@ -136,7 +137,7 @@ def read_link_status(): stri = "| " for cnt_port in range(16): if ret[3] & (0x8000 >> cnt_port) : - stri += "U | " + stri += "P | " else: stri += " | " print(stri) @@ -166,6 +167,9 @@ def read_link_status(): stri += "Rx: Er " if ret[2] & 0x40: stri += "Rx FIFO Er " +# ret_err = read_switch(0x10+cnt,0x2E, pr_stri = False) +# stri += f"CRC errs: 0x{ret_err[1]:2x}" +# rest = write_switch_bytes(0x01,0x23, [0x40], pr_stri = False) else: stri += "link down " print(stri) @@ -208,7 +212,7 @@ def read_link_status(): read_switch(0x10+cnt,0x2e) if 1: # alternative status read out, works better for SerDes lines. - for prt_cnt in [9, 10, 11,12, 13,14, 15]: + for prt_cnt in [8, 9, 10, 11,12, 13,14, 15]: ret = read_switch(0x10+prt_cnt,0x28, pr_stri = False) stri = "Port status of " + str(prt_cnt) + " " if ret[1] & 0x02: @@ -235,6 +239,19 @@ def read_link_status(): stri += "Rx Fifo Err " if ret[2] & 0x80: stri += "Tx Fifo Err " + ret = read_switch(0x10+prt_cnt,0x2E, pr_stri = False) + if CRC: + rest = write_switch_bytes(0x10+prt_cnt,0x34, [0x20, 0x10], pr_stri = False) + rest = write_switch_bytes(0x10+prt_cnt,0x3e, [0x00, 0x00], pr_stri = False) + rest = write_switch_bytes(0x10+prt_cnt,0x20, [0xD0, 0x01], pr_stri = False) + stri += f"CRC err: {ret[0]} " + else: + rest = write_switch_bytes(0x10+prt_cnt,0x3e, [0x00, 0x00], pr_stri = False) + rest = write_switch_bytes(0x10+prt_cnt,0x20, [0xD0, 0x09], pr_stri = False) + stri += f"Rx packet count: {ret[0]} " + rest = write_switch_bytes(0x10+prt_cnt,0x22, [0x41, 0x41], pr_stri = False) + rest = write_switch_bytes(0x10+prt_cnt,0x3e, [0x00, 0x00], pr_stri = False) + rest = write_switch_bytes(0x10+prt_cnt,0x2E, [0x00, 0x00], pr_stri = False) else: stri += "Down " print(stri)