From aaab3915d4f12955c23af587347fe5f2b5c3c3ce Mon Sep 17 00:00:00 2001 From: Gijs Schoonderbeek <schoonderbeek@astron.nl> Date: Fri, 6 Jan 2023 09:57:22 +0100 Subject: [PATCH] Make ready for testing APSCT --- apsct_lib.py | 357 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 357 insertions(+) create mode 100644 apsct_lib.py diff --git a/apsct_lib.py b/apsct_lib.py new file mode 100644 index 0000000..99309c6 --- /dev/null +++ b/apsct_lib.py @@ -0,0 +1,357 @@ +''' +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 APSCT_CLK + +''' +import sys +import time +sys.path.insert(0,'.') +import os +if os.name =="posix": + from I2C_serial_pi2 import * +else: + from I2C_serial import * + +DEBUG = False +I2CBUSNR=5 +sleep_time = 0.15 +SET_PLL = True +READ_LOCK = True +READ_ALL = False +CHECK_EEPROM = False +PWR_RST = False #True #False +READ_SENSOR = False #True +READ_REGS = False #True + +CLK_FREQ = '200MHz' +dev_i2c_eeprom = I2C(0x50) +dev_i2c_eeprom.bus_nr = I2CBUSNR + +CS = 6 +SCLK = 4 +SDO = 5 +SDI = 7 + +PLL_200M = 0x20 +PLL_160M = 0x21 + +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 to address : 0x{1:{fill}2x} value 0x{0:{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 read_all_regs_pll(pll_frequency='200MHz') : + I2C_device = I2C(0x20, BUSNR=I2CBUSNR) #clock selection + I2C_device.write_bytes(0x07, 0x00) + if pll_frequency == '160MHz': + print("Read PLL 160 MHz") + pll_address = PLL_160M +# I2C_device.write_bytes(0x03, 0x0F) + else: + print("Read PLL 200 MHz") + pll_address=PLL_200M +# I2C_device.write_bytes(0x03, 0xF8) +# for reg_cnt in range(0x15): + bytes_to_read = 24 + ret_value = Read_byte_PLL(0, nof_bytes = bytes_to_read, ADDRESS=pll_address) + for cnt in range(bytes_to_read): + start = cnt*8 + stri = "Reg nr 0x{:0>2x} value: 0x{:0>2x}".format(cnt, int(ret_value[start:start+8], 2)) + print(stri) + +def read_IO_expanderis(): + i2c_addr = [0x20, 0x21] + for addr in i2c_addr: + I2C_device = I2C(addr, BUSNR=I2CBUSNR) #clock selection + for reg_cnt in range(8): + ack, ret_value = I2C_device.read_bytes(reg_cnt, 2) + stri = "Expander : 0x{:0>2x}, Reg 0x{:0>2x}, value 0x{}{}".format(addr, reg_cnt, ret_value[0], ret_value[1]) #[start+2:start]) + print(stri) + +def setup_pll(pll_frequency='200MHz') : + I2C_device = I2C(0x20, BUSNR=I2CBUSNR) #clock selection + I2C_device.write_bytes(0x07, 0x00) + if pll_frequency == '160MHz': + print("Set PLL to 160 MHz mode") + pll_address = PLL_160M + I2C_device.write_bytes(0x03, 0x08) + else: + print("Set PLL to 200 MHz mode") + pll_address=PLL_200M + I2C_device.write_bytes(0x03, 0x28) + Write_byte_PLL(0x03, 0x0C, pll_address) + sleep(0.5) + Write_byte_PLL(0x03, 0x08, pll_address) + Write_byte_PLL(0x03, 0x08, pll_address) + Write_byte_PLL(0x04, 0xCF, pll_address) # CF disable not used outputs, 00 enable all + Write_byte_PLL(0x05, 0x97, pll_address) + Write_byte_PLL(0x06, 0x10, pll_address) # cp inv = 0xF4 other 0xE4 + Write_byte_PLL(0x07, 0x04, pll_address) # Divider R = 1 dec + Write_byte_PLL(0x08, 0x01, pll_address) + Write_byte_PLL(0x07, 0x00, pll_address) + Write_byte_PLL(0x09, 0x10, pll_address) # reset + if pll_frequency == '160MHz' : + Write_byte_PLL(0x0A, 0x10, pll_address) + else: + Write_byte_PLL(0x0A, 0x14, pll_address) + Write_byte_PLL(0x09, 0x00, pll_address) + Write_byte_PLL(0x0C, 0x8F, pll_address) + Write_byte_PLL(0x0D, 0x88, pll_address) # Dig CLK = 200/1 = 200 MHz + Write_byte_PLL(0x0F, 0x08, pll_address) # RCU CLK = 200/1 = 200 MHz + Write_byte_PLL(0x11, 0x08, pll_address) # PPS ref CLK = 200/1 = 200 MHz + Write_byte_PLL(0x13, 0x88, pll_address) # T.P. CLK = 200/1 = 200 MHz + + +def power(state): + stri = "Power to {}".format(state) + print(stri) + 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 apsct_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.1) + 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(1.0) + I2C_device.write_bytes(0xA0, 0xC0) + sleep(1.0) + 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 read_lol(pll_frequency='200MHz'): + 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 + I2C_IO_device_B.write_bytes(0x07, 0xFF) # '0' is output + + ack, ret_value = I2C_IO_device_B.read_bytes(0x01, 1) + status_reg = int(ret_value,16) + if (pll_frequency=='200MHz') & ((status_reg & 0x10) > 0): + print("lost lock 200MHz") + if ((status_reg & 0x20) > 0) & (pll_frequency=='160MHz'): + print("lost lock 160MHz") + ack, ret_value = I2C_IO_device_A.read_bytes(0x01, 1) + old_reg = int(ret_value,16) + I2C_IO_device_A.write_bytes(0x03, (old_reg | 0x10)) # '0' is output + sleep(1) + I2C_IO_device_A.write_bytes(0x03, (old_reg & 0xEF)) # '0' is output + + + + + +#if READ_REGS: +# read_all_regs_pll(CLK_FREQ) + +read_temp() + +if CHECK_EEPROM : + wr_rd_eeprom() + +if PWR_RST : + power(False) + sleep(10) + power(True) + +if SET_PLL : + setup_pll(CLK_FREQ) + +if READ_LOCK: + if CLK_FREQ == '160MHz' : + pll_addr = PLL_160M + else: + pll_addr = PLL_200M + 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_REGS: + read_all_regs_pll(CLK_FREQ) + +if READ_ALL: + read_all_regs_pll(CLK_FREQ) + read_IO_expanderis() + +if READ_SENSOR: + apsct_sensors() +read_lol(CLK_FREQ) -- GitLab