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)