From b3e354e59143c91034159b272430083438859dfd Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Tue, 7 Mar 2017 12:34:13 +0200 Subject: [PATCH 01/26] comment fixed --- test1.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test1.py b/test1.py index e5fb247..c769886 100644 --- a/test1.py +++ b/test1.py @@ -11,7 +11,7 @@ # #defines: # # T32_APP_CMM_PATH of every define that is specific to this test. # # # -# #call the init.py module: # +# #import modules: # # execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") # #################################################################################################### From 2e7f7910622ea8bb609b71719d3cf5e9721ef24c Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Sun, 19 Mar 2017 15:58:11 +0200 Subject: [PATCH 02/26] fixed VotschVT4002 negative temps bug fixed the bug of setting a negative temperature on VotschVT4002 oven --- lab_equipment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lab_equipment.py b/lab_equipment.py index e397bb1..d8f268f 100644 --- a/lab_equipment.py +++ b/lab_equipment.py @@ -418,10 +418,10 @@ def change_port(self, com): #Sets the temperature and STARTS the chamber. temp can be from type int, float of str def set_temp(self, temp): - neg = '0' typ = type(temp) if (typ == str): temp = float(temp) + neg = '0' if int(temp) >= 0 else '-' if (abs(temp) < 10): temp = neg + '00' + str(round(temp,1)) elif (temp <= 100 and temp >= -50): From 0d70522622c04b90deef06e7f47d9c8299bf9468 Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Sun, 19 Mar 2017 15:58:52 +0200 Subject: [PATCH 03/26] syntax --- test1.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test1.py b/test1.py index c769886..a56da0a 100644 --- a/test1.py +++ b/test1.py @@ -9,7 +9,7 @@ # TEST_NAME - the test's name. # # # # #defines: # -# T32_APP_CMM_PATH of every define that is specific to this test. # +# T32_APP_CMM_PATH or every define that is specific to this test. # # # # #import modules: # # execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") # From 648eb05394346a659fb0af61765b14171981430c Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Sun, 19 Mar 2017 15:59:05 +0200 Subject: [PATCH 04/26] syntax --- init.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init.py b/init.py index 2f0b1aa..8d56170 100644 --- a/init.py +++ b/init.py @@ -28,7 +28,7 @@ import visa # for controlling GPIB devices. (this module takes long time to load, so load it only if necessary) import openpyxl # Excel library. (this module takes long time to load, so load it only if necessary) import decimal -import platform #for the Laurebach initialization +import platform # for the Laurebach initialization import PyTektronixScope From 7cbfe796941dede7aafa8fa195f7fb695b911ab5 Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Mon, 20 Mar 2017 10:24:28 +0200 Subject: [PATCH 05/26] Excel writing example A tamplate of a test that writes results to Excel --- Tests/functionality_test/excel_test.py | 68 ++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 Tests/functionality_test/excel_test.py diff --git a/Tests/functionality_test/excel_test.py b/Tests/functionality_test/excel_test.py new file mode 100644 index 0000000..fae7adc --- /dev/null +++ b/Tests/functionality_test/excel_test.py @@ -0,0 +1,68 @@ + +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\functionality_test" +TEST_NAME = "excel_test" + +#call the init.py module: +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") + +#defines: +headlines = ["Block", "Temp", "Voltage", "Result"] +temps = ["-40C", "25C", "80C"] +voltages = ["0.9", "1.1", "1.2"] +blocks = ["PTCM", "RAM", "DTCM"] + +block_col = 1 +temp_col = 2 +volt_col = 3 +result_col = 4 + +####################################################################################### + +wb1, full_path = create_excel_file(DIR_NAME, LOG_NAME_EXCEL) +ws1 = wb1.create_sheet("BIST results") + +# thermotron = Termotron3800(TERMOTRON_TCP_IP) +# pwr_sply = QL355TPPwrSply(POWER_SUPLLY_ADDRESS) +# dmm = Agillent34401A(DMM_ADDRESS) + + +#write headlines to excel +for i in range(len(headlines)): + ws1.cell(row=1, column=i+1).value = headlines[i] +wb1.save(full_path) + +current_row = 2 + +#start test and write results to excel +for temp in temps: + # thermotron.set_temp(temp) + + for volt in voltages: + # pwr_sply.set_volt(volt) + + for block in blocks: + + '''run test on the block''' + + #result: + if len(block) % 2 == 0: + result = "Pass" + else: + result = "Fail" + + #write results: + ws1.cell(row=current_row, column=block_col).value = block + ws1.cell(row=current_row, column=temp_col).value = temp + ws1.cell(row=current_row, column=volt_col).value = volt + ws1.cell(row=current_row, column=result_col).value = result + + #upgarde row number + current_row += 1 + + #save excel file + wb1.save(full_path) + + + From 05a3af906bae5c6e320728827eb111eadb59b409 Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Mon, 5 Jun 2017 11:12:04 +0300 Subject: [PATCH 06/26] deleted unrelevant lines --- apx500_module.py | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 apx500_module.py diff --git a/apx500_module.py b/apx500_module.py deleted file mode 100644 index 1d68921..0000000 --- a/apx500_module.py +++ /dev/null @@ -1,40 +0,0 @@ -import sys -sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\Lib') # Set the path to import pure Python Libs -sys.path.append(r"C:\Program Files (x86)\Audio Precision\APx500 4.3\API") # Set the path to import the Apx API -sys.path.append(r"C:\Program Files (x86)\Audio Precision\APx500 4.3\API\Python") # Set the path to import the Apx python sampleProject - -import clr # Import the Common Language Runtime -clr.AddReference("System.Drawing") # Needed for Dialog Boxes -clr.AddReference("System.Windows.Forms") # Needed for Dialog Boxes -clr.AddReference("C:\Program Files (x86)\Audio Precision\APx500 4.3\API\AudioPrecision.API2.dll") -clr.AddReference("C:\Program Files (x86)\Audio Precision\APx500 4.3\API\AudioPrecision.API.dll") - -from AudioPrecision.API import * # Import the APx API - - - -################################################################ -## some examples: - -### running an APx project: -# filename = 'Electrical_Test_Setup_APX_100mV_0dB.approjx' -# directory = "T:\Barkristal\DBMD6\DBMD6_electrical_functionality_tests\Tools" -# fullpath = os.path.join(directory, filename1) -# APx = APx500_Application(APxOperatingMode.BenchMode, True) -# APx.Visible= True -# APx.OpenProject(fullpath) - - -### configure to BenchMode: -# APx.BenchMode.Setup.OutputConnector.Type = OutputConnectorType.AnalogUnbalanced -# APx.BenchMode.Generator.Levels.SetValue(OutputChannelIndex.Ch1, 0.02) -# APx.BenchMode.Generator.Frequency.Value = 1234 -# APx.BenchMode.Generator.On = True -# fft = APx.BenchMode.Measurements.Fft -# fft.Show() -# fft.Start() -# time.sleep(1) -# xValues = fft.FFTSpectrum.GetXValues(InputChannelIndex.Ch1, VerticalAxis.Left) -# yValues = fft.FFTSpectrum.GetYValues(InputChannelIndex.Ch1) -# for i in xValues: -# print i \ No newline at end of file From 77b31234e7d662adc6d32ecb100f72c65d5c0257 Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Mon, 5 Jun 2017 11:17:24 +0300 Subject: [PATCH 07/26] added two new classs - UartDeviceTC : communicating with the TCII and TCIII (A7) - UartDeviceD7FPGA : communicating with the FPGA of the D7 --- devices.py | 983 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 677 insertions(+), 306 deletions(-) diff --git a/devices.py b/devices.py index 5547e9c..d81ffdb 100644 --- a/devices.py +++ b/devices.py @@ -16,315 +16,686 @@ class UartDevice(): - def __init__(self, name, com, baudrate=115200, bytesize=8, parity='N', stopbits=1,timeout=1): - self.name=name - self.ser=serial.Serial() - self.ser.close() - self.ser.port = com - self.ser.baudrate = baudrate - self.ser.bytesize = bytesize - self.ser.parity = parity - self.ser.stopbits = stopbits - self.ser.timeout = timeout - self.ser.open() - - #Close the serial connection with the device - def close(self): - self.ser.close() - - #Changing the serial connection's parameters: - def change_port(self, com): - self.ser.port = com - write_to_log("{} port changed to {}".format(self.name, com)) - def change_baudrate(self, baudrate): - self.ser.baudrate = baudrate - write_to_log("{} baudrate changed to {}".format(self.name, baudrate)) - def change_bytesize(self, bytesize): - self.ser.bytesize= bytesize - write_to_log("{} bytesize changed to {}".format(self.name, bytesize)) - def change_parity(self, parity): - self.ser.parity= parity - write_to_log("{} parity changed to {}".format(self.name, parity)) - def change_stopbits(self, stopbits): - self.ser.stopbits= stopbits - write_to_log("{} stopbits changed to {}".format(self.name, stopbits)) - def change_timeout(self, timeout): - self.ser.timeout= timeout - write_to_log("{} timeout changed to {}".format(self.name, timeout)) - - - - #Sync with the device, up to n attempts. - def sync (self, n): - data_in = '' - i=0 - if (self.name == 'DBMD2'): - sync_seq = 'AcAcAcAcAcAcAcAcAcAc' - elif (self.name in ['DBMD4','DBMD6','DBMD7']): - sync_seq = chr(0x0)*20 - else: - write_to_log('No sync method for this type of chip. Please make sure that you enterd the right name') - write_to_log("Sync failed") - return - while (i < n): - self.ser.write(sync_seq) - time.sleep(0.3) - data_in = self.ser.read(2) - if data_in == "OK": - time.sleep(0.1) - write_to_log("Synced!") - break - - else: - write_to_log("Sync failed") - write_to_log("Startover Sync function, loop number: "+str(i)) - write_to_log("Please restart %s" % self.name) - i=i+1 - - def read_apb_reg(self, address): - # fill with zero for 8 bit word - address = address.zfill(8) - # convert hexa value to ascii and divide to little indian - addr6 = binascii.unhexlify(address[6]+address[7]) - addr4 = binascii.unhexlify(address[4]+address[5]) - addr2 = binascii.unhexlify(address[2]+address[3]) - addr0 = binascii.unhexlify(address[0]+address[1]) - - self.ser.write(chr(0x5A)+chr(0x07)+addr6+addr4+addr2+addr0) - time.sleep(0.1) - reg = self.ser.read(20) - reg = reg.zfill(8) - # convert ascii to hex value - apb_reg = binascii.hexlify(reg[5])+binascii.hexlify(reg[4])+binascii.hexlify(reg[3])+binascii.hexlify(reg[2]) - return apb_reg - - def write_apb_reg(self, address, value): - # fill with zero for 8 bit word - value = value.zfill(8) - address = address.zfill(8) - # convert hexa value to ascii and divide to little indian - val6 = binascii.unhexlify(value[6]+value[7]) - val4 = binascii.unhexlify(value[4]+value[5]) - val2 = binascii.unhexlify(value[2]+value[3]) - val0 = binascii.unhexlify(value[0]+value[1]) - - # convert hexa value to ascii and divide to little indian - addr6 = binascii.unhexlify(address[6]+address[7]) - addr4 = binascii.unhexlify(address[4]+address[5]) - addr2 = binascii.unhexlify(address[2]+address[3]) - addr0 = binascii.unhexlify(address[0]+address[1]) - - # write apb register- command to D4 - self.ser.write(chr(0x5A)+chr(0x04) - +addr6+addr4 - +addr2+addr0 - +val6+val4 - +val2+val0) - - def clear_bits(self, address, bits_to_clr): - bits_to_clr = int(bits_to_clr, 16) # convert to number - current_value = self.read_apb_reg(address) - current_value = int(current_value, 16) # convert to number - new_value = current_value & (~bits_to_clr) # zero the bits wanted - new_value = hex(new_value)[2:] # convert to hex (string) and cut the 0x-prefix - self.write_apb_reg(address, new_value) - - def set_bits(self, address, bits_to_set): - bits_to_set = int(bits_to_set,16) # convert to number - current_value = self.read_apb_reg(address) - current_value = int(current_value,16) # convert to number - new_value = current_value | bits_to_set # set the bits wanted - new_value = hex(new_value)[2:] # convert to hex (string) and cut the 0x-prefix - self.write_apb_reg(address, new_value) - - def load_boot_file(self, file_name): - self.load_file(file_name, 0) - self.exeBootFile() - - def load_file(self, file_name, unsent_bytes): - infile = open(file_name, "rb") - bytes_to_send = infile.read() - #wakeup() - if (unsent_bytes == 0): - self.ser.write(str(bytes_to_send)) - else: - self.ser.write((str(bytes_to_send))[:-unsent_bytes]) - time.sleep(1) - self.ser.flushInput() - - def exeBootFile(self): - self.ser.write(chr(0x5A)) - self.ser.write(chr(0x0B)) - time.sleep(0.5) - self.ser.write("19r") - time.sleep(0.5) - version = self.ser.read(5) - write_to_log("Chip type check return: " + str(version)[:4]) - time.sleep(0.1) - if (version[:3] == 'dbd'): - write_to_log("Boot Succeeded") - else: - write_to_log("Boot Failed") - - # Write to a FW register. The function doesn't read the register after the writing. - def write_register(self, register_num, value): - self.ser.flushInput() - time.sleep(0.01) - #wakeup - value = (str(value)).zfill(4) - register_num = (str(register_num)).zfill(3) - self.ser.write(register_num + "w" + value) - - #Read a FW register - def read_register(self, register_num): - self.ser.flushInput() - time.sleep(0.01) - #wakeup() - register_num = (str(register_num)).zfill(3) - self.ser.write(register_num + "r") - time.sleep(0.01) - value = self.ser.read(5)[:4] - write_to_log("reg: 0x" + register_num + " ; value: 0x" + str(value)) - return str(value) - - # Write to an APB register - def write_IO_port (self, address, value): - self.ser.flushInput() - address = (str(address)).zfill(8) - address_msb = address [:4] - address_lsb = address [4:8] - value = (str(value)).zfill(8) - value_msb = reg_value [:4] - value_lsb = reg_value [4:8] - #wakeup() - self.ser.write("006w" + address_msb) - time.sleep (0.001) - self.ser.write("005w" + address_lsb) - time.sleep (0.001) - self.ser.write("007w" + value_lsb) - time.sleep (0.001) - self.ser.write("008w" + value_msb) - - # Read an APB register - def read_IO_port (self, address): - self.ser.flushInput() - time.sleep (0.001) - address = (str(address)).zfill(8) - address_msb = address [:4] - address_lsb = address [4:8] - #wakeup() - self.ser.write("006w" + address_msb) - time.sleep (0.001) - self.ser.write("005w" + address_lsb) - time.sleep (0.001) - self.ser.write("007r") - value_lsb = self.ser.read(5)[:4] - self.ser.write("008r") - value_msb = self.ser.read(5)[:4] - return str(value_msb)+str(value_lsb) - - -T32_OK = 0 -T32_DEV = 1 + def __init__(self, name, com, baudrate=115200, bytesize=8, parity='N', stopbits=1,timeout=1): + self.name=name + self.ser=serial.Serial() + self.ser.close() + self.ser.port = com + self.ser.baudrate = baudrate + self.ser.bytesize = bytesize + self.ser.parity = parity + self.ser.stopbits = stopbits + self.ser.timeout = timeout + self.ser.open() + + #Close the serial connection with the device + def close(self): + self.ser.close() + + #Changing the serial connection's parameters: + def change_port(self, com): + self.ser.port = com + write_to_log("{} port changed to {}".format(self.name, com)) + def change_baudrate(self, baudrate): + self.ser.baudrate = baudrate + write_to_log("{} baudrate changed to {}".format(self.name, baudrate)) + def change_bytesize(self, bytesize): + self.ser.bytesize= bytesize + write_to_log("{} bytesize changed to {}".format(self.name, bytesize)) + def change_parity(self, parity): + self.ser.parity= parity + write_to_log("{} parity changed to {}".format(self.name, parity)) + def change_stopbits(self, stopbits): + self.ser.stopbits= stopbits + write_to_log("{} stopbits changed to {}".format(self.name, stopbits)) + def change_timeout(self, timeout): + self.ser.timeout= timeout + write_to_log("{} timeout changed to {}".format(self.name, timeout)) + + + #Write data to the serial port + def write_data(self, data): + self.ser.write(data) + + #Read data from serial port + def read_data(self): + data = "" + c = self.ser.read(1) + while c != "\r" and c != "\n": + print c + data += c + c = self.ser.read(1) + return data + + + + #Sync with the device, up to n attempts. + def sync (self, n): + data_in = '' + i=0 + if (self.name in ['DBMD2','TC', 'A7']): + sync_seq = ('AcAcA'+chr(255))*30 + elif (self.name in ['DBMD4','DBMD6','DBMD7']): + sync_seq = chr(0x0)*20 + else: + write_to_log('No sync method for this type of chip. Please make sure that you enterd the right name') + write_to_log("Sync failed") + return + while (i < n): + self.ser.write(sync_seq) + time.sleep(0.3) + data_in = self.ser.read(2) + if data_in == "OK": + time.sleep(0.1) + write_to_log("Synced!") + break + + else: + write_to_log("Sync failed") + write_to_log("Startover Sync function, loop number: "+str(i)) + write_to_log("Please restart %s" % self.name) + i=i+1 + + + def load_boot_file(self, file_name): + if self.name in ['TC']: + self.load_file(file_name, 4) + self.exeBootFile() + else: + self.load_file(file_name, 0) + self.exeBootFile() + + def load_file(self, file_name, unsent_bytes): + infile = open(file_name, "rb") + bytes_to_send = infile.read() + # wakeup() + if (unsent_bytes == 0): + self.ser.write(str(bytes_to_send)) + else: + self.ser.write((str(bytes_to_send))[:-unsent_bytes]) + time.sleep(1) + self.ser.flushInput() + + def exeBootFile(self): + self.ser.write(chr(0x5A)) + self.ser.write(chr(0x0B)) + time.sleep(0.5) + if (self.name == 'TC'): + self.change_baudrate(1843200) + self.change_parity('N') + time.sleep(0.1) + version = self.read_version() + write_to_log("Version check returned: %s" % version) + time.sleep(0.1) + if (version == '15'): + write_to_log("Boot Succeeded") + else: + write_to_log("Boot Failed") + + elif (self.name == 'A7'): + self.change_baudrate(3000000) + self.change_parity('N') + self.change_stopbits(1) + # version = self.read_version() + # write_to_log("Version check returned: %s" % version) + # time.sleep(0.1) + # if (version == '0'): + # write_to_log("Boot Succeeded") + # else: + # write_to_log("Boot Failed") + else: + self.ser.write("19r") + time.sleep(0.5) + version = self.ser.read(5) + print version + write_to_log("Chip type check return: " + str(version)[:4]) + time.sleep(0.1) + if (version[:3] == 'dbd'): + write_to_log("Boot Succeeded") + else: + write_to_log("Boot Failed") + + + + ########## BEFORE BOOT FILE HAS BEEN LODED: ############ + + #Read from apb registers after boot file loaded: + def read_apb_reg(self, address): + # fill with zero for 8 bit word + address = address.zfill(8) + # convert hexa value to ascii and divide to little indian + addr6 = binascii.unhexlify(address[6]+address[7]) + addr4 = binascii.unhexlify(address[4]+address[5]) + addr2 = binascii.unhexlify(address[2]+address[3]) + addr0 = binascii.unhexlify(address[0]+address[1]) + + self.ser.write(chr(0x5A)+chr(0x07)+addr6+addr4+addr2+addr0) + time.sleep(0.1) + reg = self.ser.read(20) + reg = reg.zfill(8) + # convert ascii to hex value + # apb_reg = binascii.hexlify(reg[5])+binascii.hexlify(reg[4])+binascii.hexlify(reg[3])+binascii.hexlify(reg[2]) + apb_reg = binascii.hexlify(reg[7]) + binascii.hexlify(reg[6]) + binascii.hexlify(reg[5]) + binascii.hexlify( + reg[4]) #change by Bar, 18.4.17 + return apb_reg + + #Write to apb registers after boot file loaded: + def write_apb_reg(self, address, value): + # fill with zero for 8 bit word + value = value.zfill(8) + address = address.zfill(8) + # convert hexa value to ascii and divide to little indian + val6 = binascii.unhexlify(value[6]+value[7]) + val4 = binascii.unhexlify(value[4]+value[5]) + val2 = binascii.unhexlify(value[2]+value[3]) + val0 = binascii.unhexlify(value[0]+value[1]) + + # convert hexa value to ascii and divide to little indian + addr6 = binascii.unhexlify(address[6]+address[7]) + addr4 = binascii.unhexlify(address[4]+address[5]) + addr2 = binascii.unhexlify(address[2]+address[3]) + addr0 = binascii.unhexlify(address[0]+address[1]) + # write apb register- command to D4 + self.ser.write(chr(0x5A)+chr(0x04) + +addr6+addr4 + +addr2+addr0 + +val6+val4 + +val2+val0) + #Clear bits from apb register's value. This function can be used after loading boot file. + def apb_clear_bits(self, address, bits_to_clr): + bits_to_clr = int(bits_to_clr, 16) # convert to number + current_value = self.read_apb_reg(address) + current_value = int(current_value, 16) # convert to number + new_value = current_value & (~bits_to_clr) # zero the bits wanted + new_value = hex(new_value)[2:] # convert to hex (string) and cut the 0x-prefix + self.write_apb_reg(address, new_value) + + #Set bits is apb register's value. This function can be used after loading boot file. + def apb_set_bits(self, address, bits_to_set): + bits_to_set = int(bits_to_set,16) # convert to number + current_value = self.read_apb_reg(address) + current_value = int(current_value,16) # convert to number + new_value = current_value | bits_to_set # set the bits wanted + new_value = hex(new_value)[2:] # convert to hex (string) and cut the 0x-prefix + self.write_apb_reg(address, new_value) + + + ######## AFTER LOADING BOOT FILE: ############# + + #Write to a FW register. The function doesn't read the register after the writing. + def write_register(self, register_num, value): + self.ser.flushInput() + time.sleep(0.01) + #wakeup + value = (str(value)).zfill(4) + register_num = (str(register_num)).zfill(3) + self.ser.write(register_num + "w" + value) + + #Read a FW register + def read_register(self, register_num): + self.ser.flushInput() + time.sleep(0.01) + #wakeup() + register_num = (str(register_num)).zfill(3) + self.ser.write(register_num + "r") + time.sleep(0.01) + value = self.ser.read(5)[:4] + write_to_log("reg: 0x" + register_num + " ; value: 0x" + str(value)) + return str(value) + + # Write to an APB register + def write_IO_port (self, address, value): + self.ser.flushInput() + address = (str(address)).zfill(8) + address_msb = address [:4] + address_lsb = address [4:8] + value = (str(value)).zfill(8) + value_msb = value [:4] + value_lsb = value [4:8] + #wakeup() + self.ser.write("006w" + address_msb) + time.sleep (0.001) + self.ser.write("005w" + address_lsb) + time.sleep (0.001) + self.ser.write("007w" + value_lsb) + time.sleep (0.001) + self.ser.write("008w" + value_msb) + + # Read an APB register + def read_IO_port (self, address): + self.ser.flushInput() + time.sleep (0.001) + address = (str(address)).zfill(8) + address_msb = address [:4] + address_lsb = address [4:8] + #wakeup() + self.ser.write("006w" + address_msb) + time.sleep (0.001) + self.ser.write("005w" + address_lsb) + time.sleep (0.001) + self.ser.write("007r") + self.ser.reset_input_buffer() + time.sleep(0.5) + value_lsb = self.ser.read(5)[:4] + self.ser.write("008r") + value_msb = self.ser.read(5)[:4] + return str(value_msb)+str(value_lsb) + + def IO_port_set_bits(self, address, bits_to_set): + current_val = self.read_IO_port(address) + new_val = hex(int(current_val, 16) | int(bits_to_set, 16)).lstrip('0x') + self.write_IO_port(address, new_val) + + def IO_port_clear_bits(self, address, bits_to_clear): + current_val = self.read_IO_port(address) + new_val = hex(int(current_val, 16) & ~int(bits_to_clear, 16)).lstrip('0x') + self.write_IO_port(address, new_val) + + + +########################################################################################################## + +T32_OK = 0 +T32_DEV = 1 # NOTE: every script that using the LAUTERBACH should close the connection # with the device at the end by calling the function ".close()" class Lauterbach(): - def __init__(self, name): - self.name = name - # Start TRACE32 instance - exception_1_raised=1 - exception_2_raised=1 - num_of_attempts=2 #attempts to connect to LAUTERBACH - count=0 - T32_is_open=0 - while (exception_2_raised and count < num_of_attempts): - exception_2_raised=0 - count += 1 - while (exception_1_raised): - exception_1_raised=0 - try: - for i in psutil.pids(): - if (psutil.Process(i).name()== "t32marm.exe"): - T32_is_open=1 - except: - write_to_log("error raised while initializing LAUTERBACH") - exception_1_raised=1 - if (not T32_is_open): - t32_exe = os.path.join('C:\\','T32','t32marm.exe') - config_file = os.path.join('C:\\' ,'T32', 'config.t32') - start_up = os.path.join('C:\\','T32','demo', 'arm', 'compiler', 'arm', 'cortexm.cmm') - command = [t32_exe, '-c', config_file, '-s', start_up] - process = subprocess.Popen(command) - # Wait until the TRACE32 instance is started - time.sleep(5) - - # Load TRACE32 Remote API - if platform.architecture()[0] == '32bit': # check the system's architecture - self.t32api = ctypes.cdll.LoadLibrary(r'C:\T32\t32api.dll') #32bit - elif platform.architecture()[0] == '64bit': - self.t32api = ctypes.cdll.LoadLibrary(r'C:\T32\t32api64.dll') #64bit - else: - write_to_log(r"Error- can't determine the system's architecture") - # Configure communication channel: - self.t32api.T32_Config(b"NODE=",b"localhost") - self.t32api.T32_Config(b"PORT=",b"20000") - self.t32api.T32_Config(b"PACKLEN=",b"1024") - # Establish communication channel: - rc1 = self.t32api.T32_Init() - rc2 = self.t32api.T32_Attach(T32_DEV) - rc3 = self.t32api.T32_Ping() - if (rc2 != T32_OK or rc3 != T32_OK): - exception_2_raised=1 - self.close() - if count == num_of_attempts: - write_to_log("Error- failed to connect to Lautebach after {} attempts".format(count+1)) - # Start PRACTICE script - run dvf101_app.cmm - self.t32api.T32_Cmd(b"CD.DO {}".format(T32_APP_CMM_PATH)) - time.sleep(2) - - - def close(self): - self.t32api.T32_Exit() - - def write_register(self, address, value, length="LONG"): - command= "DATA.SET 0x{} %LE %{} 0x{}".format(address, length, value) - if (self.t32api.T32_Cmd(command) != T32_OK): - write_to_log("error while writing to 0x{}".format(address)) - - def read_register(self, address, length="LONG"): - self.t32api.T32_Cmd("PRINT") - command = "print data.{}(A:0x{})".format(length ,address) - if (self.t32api.T32_Cmd(command) != T32_OK): - write_to_log("Error while reading from 0x{}".format(address)) - return "" - else: - status = ctypes.c_uint16(-1) - message = ctypes.create_string_buffer(256) - mrc = self.t32api.T32_GetMessage(ctypes.byref(message), ctypes.byref(status)) - return message.value.decode("utf-8") - - #set only the specified bits_to_set with value_to_set - def set_bits(self, address, bits_to_set, value_to_set, length="LONG"): - command = "PER.Set.Field A:{} %{} 0x{} {}".format(address, length ,str(bits_to_set), str(value_to_set)) - if (self.t32api.T32_Cmd(command) != T32_OK): - write_to_log("error while writing to 0x{}".format(address)) - - - #set to 0 only the specified bits - def clear_bits(self, address, bits_to_clear, length="LONG"): - command = "PER.Set.Field A:{} %{} 0x{} {}".format(address, length ,str(bits_to_set), '0') - if (self.t32api.T32_Cmd(command) != T32_OK): - write_to_log("error while writing to 0x{}".format(address)) - - - #Execute a cmm file. the function should get the full path of the .cmm file - def execute_cmm_file(self, cmm_file): - command = "CD.DO {}".format(cmm_file) - if (self.t32api.T32_Cmd(command) != T32_OK): - write_to_log("Error while executing {}".format(cmm_file)) - else: - write_to_log("{} executed successfully".format(cmm_file)) + def __init__(self, name): + self.name = name + # Start TRACE32 instance + exception_1_raised=1 + exception_2_raised=1 + num_of_attempts=2 #attempts to connect to LAUTERBACH + count=0 + T32_is_open=0 + while (exception_2_raised and count < num_of_attempts): + exception_2_raised=0 + count += 1 + while (exception_1_raised): + exception_1_raised=0 + try: + for i in psutil.pids(): + if (psutil.Process(i).name()== "t32marm.exe"): + T32_is_open=1 + except: + write_to_log("error raised while initializing LAUTERBACH") + exception_1_raised=1 + if (not T32_is_open): + t32_exe = os.path.join('C:\\','T32','t32marm.exe') + config_file = os.path.join('C:\\' ,'T32', 'config.t32') + start_up = os.path.join('C:\\','T32','demo', 'arm', 'compiler', 'arm', 'cortexm.cmm') + command = [t32_exe, '-c', config_file, '-s', start_up] + process = subprocess.Popen(command) + # Wait until the TRACE32 instance is started + time.sleep(5) + + # Load TRACE32 Remote API + if platform.architecture()[0] == '32bit': # check the system's architecture + self.t32api = ctypes.cdll.LoadLibrary(r'C:\T32\t32api.dll') #32bit + elif platform.architecture()[0] == '64bit': + self.t32api = ctypes.cdll.LoadLibrary(r'C:\T32\t32api64.dll') #64bit + else: + write_to_log(r"Error- can't determine the system's architecture") + # Configure communication channel: + self.t32api.T32_Config(b"NODE=",b"localhost") + self.t32api.T32_Config(b"PORT=",b"20000") + self.t32api.T32_Config(b"PACKLEN=",b"1024") + # Establish communication channel: + rc1 = self.t32api.T32_Init() + rc2 = self.t32api.T32_Attach(T32_DEV) + rc3 = self.t32api.T32_Ping() + if (rc2 != T32_OK or rc3 != T32_OK): + exception_2_raised=1 + self.close() + if count == num_of_attempts: + write_to_log("Error- failed to connect to Lautebach after {} attempts".format(count+1)) + # Start PRACTICE script - run dvf101_app.cmm + self.t32api.T32_Cmd(b"CD.DO {}".format(T32_APP_CMM_PATH)) + time.sleep(2) + + + def close(self): + self.t32api.T32_Exit() + + def write_register(self, address, value, length="LONG"): + command= "DATA.SET 0x{} %LE %{} 0x{}".format(address, length, value) + if (self.t32api.T32_Cmd(command) != T32_OK): + write_to_log("error while writing to 0x{}".format(address)) + + def read_register(self, address, length="LONG"): + self.t32api.T32_Cmd("PRINT") + command = "print data.{}(A:0x{})".format(length ,address) + if (self.t32api.T32_Cmd(command) != T32_OK): + write_to_log("Error while reading from 0x{}".format(address)) + return "" + else: + status = ctypes.c_uint16(-1) + message = ctypes.create_string_buffer(256) + mrc = self.t32api.T32_GetMessage(ctypes.byref(message), ctypes.byref(status)) + return message.value.decode("utf-8") + + #set only the specified bits_to_set with value_to_set + def set_bits(self, address, bits_to_set, value_to_set, length="LONG"): + command = "PER.Set.Field A:{} %{} 0x{} {}".format(address, length ,str(bits_to_set), str(value_to_set)) + if (self.t32api.T32_Cmd(command) != T32_OK): + write_to_log("error while writing to 0x{}".format(address)) + + + #set to 0 only the specified bits + def clear_bits(self, address, bits_to_clear, length="LONG"): + command = "PER.Set.Field A:{} %{} 0x{} {}".format(address, length ,str(bits_to_set), '0') + if (self.t32api.T32_Cmd(command) != T32_OK): + write_to_log("error while writing to 0x{}".format(address)) + + + #Execute a cmm file. the function should get the full path of the .cmm file + def execute_cmm_file(self, cmm_file): + command = "CD.DO {}".format(cmm_file) + if (self.t32api.T32_Cmd(command) != T32_OK): + write_to_log("Error while executing {}".format(cmm_file)) + else: + write_to_log("{} executed successfully".format(cmm_file)) - \ No newline at end of file + +############################################################################################################### + +#This class is used for communicating with the analog Test Chip of DBM series. +#The communication is set through DBMD2 chip, that is connected to the Test Chip through SPI, and is using the FW_boot_file +#of nir michael, and the ART commands. +class UartDeviceTC(UartDevice): + def __init__(self, name, com, baudrate=115200, bytesize=8, parity='N', stopbits=1,timeout=1, boot_file=r"t:\art\classc\script\classd_boot_166.bin"): + UartDevice.__init__(self, name, com, baudrate, bytesize, parity, stopbits, timeout) + self.name=name + self.sync(10) + self.load_boot_file(boot_file) + time.sleep(1) + + + + #Write to register of the Test Chip: + def write_register(self, address, value): + if type(address) == str: + address = address.lower().lstrip('0x') + if type(address) in [int, long]: + address = hex(address).rstrip('L').lower().lstrip('0x') + + + if type(value) == str: + value = value.lower().lstrip('0x') + if type(value) in [int, long]: + value = hex(value).rstrip('L').lower().lstrip('0x') + + time.sleep(0.05) + self.write_data("\r\ntc_write 0x{} 0x{}\r\n".format(address, value)) + self.ser.reset_input_buffer() + self.ser.reset_output_buffer() + print self.read_register(address) + + #Read a register of the Test Chip: + def read_register(self, address): + if type(address) == str: + address = address.lower().lstrip('0x') + if type(address) in [int, long]: + address = hex(address).rstrip('L').lower().lstrip('0x') + + unknown = 0 + while not unknown: + self.ser.reset_input_buffer() + command = "tc_read 0x{}\r\n".format(address) + self.write_data(command) + time.sleep(0.05) + input = '' + c = self.ser.read(1) + while c != '\n': + c = self.ser.read(1) + c = self.ser.read(1) + while c != '\n': + input += c + c = self.ser.read(1) + input = input.replace(chr(0), '').replace(' ','').rstrip('\r') + if input != 'Unknowncommand': + unknown = 1 + return input + + #Set bits in a register of the Test Chip: + def tc_setbits(self, address, bits_to_set): + if type(address) == str: + address = address.lower().replace('0x', '') + elif type(address) in [int, long]: + address = hex(address).rstrip('L').lower().replace('0x', '') + + if type(bits_to_set) == str: + bits_to_set = bits_to_set.lower().replace('0x', '') + elif type(bits_to_set) in [int, long]: + bits_to_set = hex(bits_to_set).rstrip('L').lower().replace('0x', '') + + self.write_data("\r\ntc_setbits 0x{} 0x{}\r\n".format(address, bits_to_set)) + self.ser.reset_input_buffer() + self.ser.reset_output_buffer() + + #Clear bits in a register of the Test Chip: + def tc_clrbits(self, address, bits_to_clr): + if type(address) == str: + address = address.lower().replace('0x', '') + elif type(address) in [int, long]: + address = hex(address).rstrip('L').lower().replace('0x', '') + + if type(bits_to_clr) == str: + bits_to_clr = bits_to_clr.lower().replace('0x', '') + elif type(bits_to_clr) in [int, long]: + bits_to_clr = hex(bits_to_clr).rstrip('L').lower().replace('0x', '') + + self.write_data("\r\ntc_clrbits 0x{} 0x{}\r\n".format(address, bits_to_clr)) + self.ser.reset_input_buffer() + self.ser.reset_output_buffer() + + + def tc_modify_register(self, address, bits_to_modify, mask): + if type(address) == str: + address = address.lower().replace('0x', '') + elif type(address) in [int, long]: + address = hex(address).rstrip('L').lower().replace('0x', '') + + if type(bits_to_modify) == str: + bits_to_modify = bits_to_modify.lower().replace('0x', '') + elif type(bits_to_modify) in [int, long]: + bits_to_modify = hex(bits_to_modify).rstrip('L').lower().replace('0x', '') + + if type(mask) == str: + mask = mask.lower().replace('0x', '') + elif type(mask) in [int, long]: + mask = hex(mask).rstrip('L').lower().replace('0x', '') + + bits_to_set = hex(int(bits_to_modify, 16) & int(mask, 16))[2:].rstrip('L') + self.tc_setbits(address, bits_to_set) + bits_to_clr = hex((int(bits_to_modify,16) ^ 0xffffffff) & int(mask, 16))[2:].rstrip('L') + self.tc_clrbits(address, bits_to_clr) + print self.read_register(address) + + def read_version(self): + flag = 0 + while not flag: + self.ser.reset_input_buffer() + self.write_data("\r\nversion\r\n") + time.sleep(0.001) + input = '' + c = self.ser.read(1) + while c != '\n': + c = self.ser.read(1) + c = self.ser.read(1) + while c != '\n': + input += c + c = self.ser.read(1) + input = input.replace(chr(0), '').replace(' ','').rstrip('\r') + if input != 'Unknowncommand': + flag = 1 + return input + + + + + +class UartDeviceD7FPGA(UartDevice): + def __init__(self, name, com, baudrate=115200, bytesize=8, parity='N', stopbits=1,timeout=1): + UartDevice.__init__(self, name, com, baudrate, bytesize, parity, stopbits, timeout) + self.name=name + + + #Write to register of the Test Chip: + def write_register(self, address, value): + if type(address) == str: + address = address.lower().lstrip('0x') + if type(address) in [int, long]: + address = hex(address).rstrip('L').lower().lstrip('0x') + + + if type(value) == str: + value = value.lower().lstrip('0x') + if type(value) in [int, long]: + value = hex(value).rstrip('L').lower().lstrip('0x') + + time.sleep(0.05) + self.write_data("\r\naw 0x{} 0x{}\r\n".format(address, value)) + self.ser.reset_input_buffer() + self.ser.reset_output_buffer() + # print self.read_register(address) + + #Read a register of the Test Chip: + # def read_register_old(self, address): + # if type(address) == str: + # address = address.lower().lstrip('0x') + # if type(address) in [int, long]: + # address = hex(address).rstrip('L').lower().lstrip('0x') + # + # unknown = 0 + # while not unknown: + # time.sleep(0.1) + # self.ser.reset_input_buffer() + # command = "ad 0x{}\r\n".format(address) + # self.write_data(command) + # # time.sleep(0.05) + # input = '' + # c = self.ser.read(1) + # while c != '\n': + # c = self.ser.read(1) + # c = self.ser.read(3) + # while c != ' ': + # c = self.ser.read(1) + # + # c = self.ser.read(1) + # while c != '\n': + # input += c + # c = self.ser.read(1) + # + # if input != 'Unknowncommand': + # unknown = 1 + # + # input = input.replace(chr(0), '').split(' ') + # for p in input: + # if p != '': + # input = p + # break + # # input = input.replace(chr(0), '').replace(' ','').rstrip('\r') + # return input + + # Read a register of the Test Chip: + def read_register(self, address): + if type(address) == str: + address = address.lower().lstrip('0x') + if type(address) in [int, long]: + address = hex(address).rstrip('L').lower().lstrip('0x') + + unknown = 0 + while not unknown: + self.ser.reset_input_buffer() + command = "ar 0x{}\r\n".format(address) + self.write_data(command) + # time.sleep(0.05) + input = '' + c = self.ser.read(1) + while c != '\n': + c = self.ser.read(1) + c = self.ser.read(1) + while c != '\n': + input += c + c = self.ser.read(1) + input = input.replace(chr(0), '').replace(' ', '').rstrip('\r').replace('0x', '') + if input != 'Unknowncommand': + unknown = 1 + return input + + #Set bits in a register of the Test Chip: + def setbits(self, address, bits_to_set): + if type(address) == str: + address = address.lower().replace('0x', '') + elif type(address) in [int, long]: + address = hex(address).rstrip('L').lower().replace('0x', '') + + if type(bits_to_set) == str: + bits_to_set = bits_to_set.lower().replace('0x', '') + elif type(bits_to_set) in [int, long]: + bits_to_set = hex(bits_to_set).rstrip('L').lower().replace('0x', '') + + self.write_data("\r\napb_setbits 0x{} 0x{}\r\n".format(address, bits_to_set)) + self.ser.reset_input_buffer() + self.ser.reset_output_buffer() + + #Clear bits in a register of the Test Chip: + def clrbits(self, address, bits_to_clr): + if type(address) == str: + address = address.lower().replace('0x', '') + elif type(address) in [int, long]: + address = hex(address).rstrip('L').lower().replace('0x', '') + + if type(bits_to_clr) == str: + bits_to_clr = bits_to_clr.lower().replace('0x', '') + elif type(bits_to_clr) in [int, long]: + bits_to_clr = hex(bits_to_clr).rstrip('L').lower().replace('0x', '') + + self.write_data("\r\napb_clrbits 0x{} 0x{}\r\n".format(address, bits_to_clr)) + self.ser.reset_input_buffer() + self.ser.reset_output_buffer() + + + def modify_register(self, address, bits_to_modify, mask): + if type(address) == str: + address = address.lower().replace('0x', '') + elif type(address) in [int, long]: + address = hex(address).rstrip('L').lower().replace('0x', '') + + if type(bits_to_modify) == str: + bits_to_modify = bits_to_modify.lower().replace('0x', '') + elif type(bits_to_modify) in [int, long]: + bits_to_modify = hex(bits_to_modify).rstrip('L').lower().replace('0x', '') + + if type(mask) == str: + mask = mask.lower().replace('0x', '') + elif type(mask) in [int, long]: + mask = hex(mask).rstrip('L').lower().replace('0x', '') + + bits_to_set = hex(int(bits_to_modify, 16) & int(mask, 16))[2:].rstrip('L') + self.apb_setbits(address, bits_to_set) + bits_to_clr = hex((int(bits_to_modify,16) ^ 0xffffffff) & int(mask, 16))[2:].rstrip('L') + self.apb_clrbits(address, bits_to_clr) + print self.read_register(address) + + def read_version(self): + flag = 0 + while not flag: + self.ser.reset_input_buffer() + self.write_data("version\r\n") + time.sleep(0.001) + input = '' + c = self.ser.read(1) + while c != '\n': + c = self.ser.read(1) + c = self.ser.read(1) + while c != '\n': + input += c + c = self.ser.read(1) + input = input.replace(chr(0), '').replace(' ','').rstrip('\r') + if input != 'Unknowncommand': + flag = 1 + return input \ No newline at end of file From 87b2ae2ac9a3ec20c589d008fb8dffb5e462bcba Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Mon, 5 Jun 2017 11:19:04 +0300 Subject: [PATCH 08/26] added import to saleae module saleae is a logic sniffer --- init.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/init.py b/init.py index 8d56170..94a67db 100644 --- a/init.py +++ b/init.py @@ -30,7 +30,7 @@ import decimal import platform # for the Laurebach initialization import PyTektronixScope - +import saleae @@ -45,6 +45,7 @@ execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\devices.py") execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\utilities.py") execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\lab_equipment.py") + # execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\apx525_module.py") POWER_SUPLLY_ADDRESS = "GPIB0::29::INSTR" DMM_ADDRESS = "GPIB0::22::INSTR" @@ -52,7 +53,7 @@ WAVE_GENERATOR_ADDRESS = "GPIB0::1::INSTR" ELECTRONIC_LOAD_ADDRESS = "GPIB0::3::INSTR" SCOPE_ADDRESS = "GPIB0::9::INSTR" - + OVEN_ADDRESS = 'COM17' elif USER_NAME == "Sas": execfile(r"C:\GitHub\Python\devices.py") From 1dc12b6ed97e738fc0676ea0bb1d31e30a1a491e Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Mon, 5 Jun 2017 11:19:52 +0300 Subject: [PATCH 09/26] fixed bugs --- lab_equipment.py | 1038 +++++++++++++++++++++++----------------------- 1 file changed, 521 insertions(+), 517 deletions(-) diff --git a/lab_equipment.py b/lab_equipment.py index d8f268f..27b5f7d 100644 --- a/lab_equipment.py +++ b/lab_equipment.py @@ -9,543 +9,547 @@ #Errors: class Error_connecting_device(): - def __init__(self): - write_to_log("Error: failed connecting to device" %(self.type)) + def __init__(self): + write_to_log("Error: failed connecting to device" %(self.type)) #Lab equipment classes: class Agillent34401A(): - def __init__(self,address): - resource_manager = visa.ResourceManager() - self.dev=resource_manager.open_resource(address) - self.name=self.dev.query('*IDN?')[:-1] - self.dev.timeout = 5000 - - def close(self): - self.dev.close() - #write_to_log ('The connection with: %s is now closed' %(self.name)) - - def send_command(self, command): - #Send a visa command to the device. - #This function and the next one can be used in order to send a command that doesn't covered by this module. - self.dev.write(command) - - def read_response(self, command): - #read from the device. can be used after sending a query command to the device. - return self.dev.read()[-1] - - def meas(self,meas): - if meas == 'DCV': - self.dev.write('MEAS:VOLT:DC?') - result = self.dev.read()[:-1] - write_to_log ("DC Measurement: %s" %(result)) - elif meas == 'ACV': - self.dev.write('MEAS:VOLT:AC?') - result = self.dev.read()[:-1] - write_to_log ("AC Measurement: %s" %(result)) - elif meas == 'frequency': - self.dev.write('MEAS:FREQ?') - result = self.dev.read()[:-1] - write_to_log ("Frequency Measurement: %s" %(result)) - elif meas == 'resistance': - self.dev.write('MEAS:REAS?') - result = self.dev.read()[:-1] - write_to_log ("Resistance Measurement: %s" %(result)) - elif meas == 'DCI': - self.dev.write('MEAS:CURR:DC?') - result = self.dev.read()[:-1] - write_to_log ("DC Current Measurement: %s" %(result)) - elif meas == 'ACI': - self.dev.write('MEAS:CURR:AC?') - result = self.dev.read()[:-1] - write_to_log ("AC Current Measurement: %s" %(result)) - return result + def __init__(self,address): + resource_manager = visa.ResourceManager() + self.dev=resource_manager.open_resource(address) + self.name=self.dev.query('*IDN?')[:-1] + self.dev.timeout = 5000 + + def close(self): + self.dev.close() + #write_to_log ('The connection with: %s is now closed' %(self.name)) + + def send_command(self, command): + #Send a visa command to the device. + #This function and the next one can be used in order to send a command that doesn't covered by this module. + self.dev.write(command) + + def read_response(self, command): + #read from the device. can be used after sending a query command to the device. + return self.dev.read()[-1] + + def meas(self,meas): + if meas == 'DCV': + self.dev.write('MEAS:VOLT:DC?') + result = self.dev.read()[:-1] + write_to_log ("DC Measurement: %s" %(result)) + elif meas == 'ACV': + self.dev.write('MEAS:VOLT:AC?') + result = self.dev.read()[:-1] + write_to_log ("AC Measurement: %s" %(result)) + elif meas == 'frequency': + self.dev.write('MEAS:FREQ?') + result = self.dev.read()[:-1] + write_to_log ("Frequency Measurement: %s" %(result)) + elif meas == 'resistance': + self.dev.write('MEAS:REAS?') + result = self.dev.read()[:-1] + write_to_log ("Resistance Measurement: %s" %(result)) + elif meas == 'DCI': + self.dev.write('MEAS:CURR:DC?') + result = self.dev.read()[:-1] + write_to_log ("DC Current Measurement: %s" %(result)) + elif meas == 'ACI': + self.dev.write('MEAS:CURR:AC?') + result = self.dev.read()[:-1] + write_to_log ("AC Current Measurement: %s" %(result)) + return result class QL355TPPwrSply(): - def __init__(self,address): - resource_manager = visa.ResourceManager() - self.dev=resource_manager.open_resource(address) - self.dev.clear() - self.name=self.dev.query('*IDN?')[:-1] - self.dev.timeout = 5000 - - - def close(self): - self.dev.close() - write_to_log ('The connection with: %s is now closed' %(self.name)) - - def set_timeout(self, time): - time = int(time) - self.dev.timeout = time - - def send_command(self, command): - #Send a visa command to the device. - #This function and the next one can be used in order to send a command that doesn't covered by this module. - self.dev.write(command) - - def read_response(self, command): - #read from the device. can be used after sending a query command to the device. - return self.dev.read()[-1] - - def set_volt(self, channel, volt): - #set the voltage output of the specified channel - channel = str(channel) - self.dev.write("V%s %s" %(channel , volt)) - time.sleep(0.5) - res = self.dev.query("V%s?" %(channel))[:-1] - return res - - def set_current_lim(self, channel, current): - #set the current limit of the specified channel - channel = str(channel) - self.dev.write("I%s %s" %(channel ,current)) - time.sleep(0.1) - res = self.dev.query("I%s?" %(channel))[:-1] - return res - - def channel_on(self, channel): - #set ON the specified channel - channel = str(channel) - self.dev.write('OP%s 1' %(channel)) - write_to_log('Channel %s is on' %(channel)) - - def channel_off(self, channel): - #set OFF the specified channel - channel = str(channel) - self.dev.write('OP%s 0' %(channel)) - write_to_log('Channel %s is off' %(channel)) - - def increment_voltage(self, channel, step_size): - #increment the channel's output voltage in a step_size voltage - channel = str(channel) - self.dev.write('DELTAV%s %s' %(channel ,step_size)) - self.dev.write('INCV%s' %(channel)) - #write_to_log("Channel %s was incremented by %sV" %(channel ,step_size)) - res = self.dev.write('V%s?' %(channel)) - #write_to_log("Channel %s volatge is now %sV" %(channel ,self.dev.read()[3:])) - return res - - def all_off(self): - #set ALL channels OFF - self.dev.write('OPALL 0') - #write_to_log("All channels set OFF") - - def all_on(self): - #set ALL channels ON - self.dev.write('OPALL 1') - #write_to_log("All channels set ON") - - def read_current(self, channel): - #reads the current flows right now through the channel - self.dev.write('I%sO?' %(str(channel))) - cur = self.dev.read()[:-1] - #write_to_log("The current at channel %s is: %s" %(channel, cur)) - return cur - - def sense(self, channel, mode): - #mode=0: local, mode=1: remote - self.dev.write('SENSE%s %s' %(channel, mode)) - mod="local" if mode == '0' else "remote" - #write_to_log("Activated %s sense on channel %s" %(mod, str(channel))) - - + def __init__(self,address): + resource_manager = visa.ResourceManager() + self.dev=resource_manager.open_resource(address) + self.dev.clear() + self.name=self.dev.query('*IDN?')[:-1] + self.dev.timeout = 5000 + + + def close(self): + self.dev.close() + write_to_log ('The connection with: %s is now closed' %(self.name)) + + def set_timeout(self, time): + time = int(time) + self.dev.timeout = time + + def send_command(self, command): + #Send a visa command to the device. + #This function and the next one can be used in order to send a command that doesn't covered by this module. + self.dev.write(command) + + def read_response(self, command): + #read from the device. can be used after sending a query command to the device. + return self.dev.read()[-1] + + def set_volt(self, channel, volt): + #set the voltage output of the specified channel + channel = str(channel) + self.dev.write("V%s %s" %(channel , volt)) + time.sleep(0.5) + res = self.dev.query("V%s?" %(channel))[:-1] + return res + + def set_current_lim(self, channel, current): + #set the current limit of the specified channel + channel = str(channel) + self.dev.write("I%s %s" %(channel ,current)) + time.sleep(0.1) + res = self.dev.query("I%s?" %(channel))[:-1] + return res + + def channel_on(self, channel): + #set ON the specified channel + channel = str(channel) + self.dev.write('OP%s 1' %(channel)) + write_to_log('Channel %s is on' %(channel)) + + def channel_off(self, channel): + #set OFF the specified channel + channel = str(channel) + self.dev.write('OP%s 0' %(channel)) + write_to_log('Channel %s is off' %(channel)) + + def increment_voltage(self, channel, step_size): + #increment the channel's output voltage in a step_size voltage + channel = str(channel) + self.dev.write('DELTAV%s %s' %(channel ,step_size)) + self.dev.write('INCV%s' %(channel)) + #write_to_log("Channel %s was incremented by %sV" %(channel ,step_size)) + res = self.dev.write('V%s?' %(channel)) + #write_to_log("Channel %s volatge is now %sV" %(channel ,self.dev.read()[3:])) + return res + + def all_off(self): + #set ALL channels OFF + self.dev.write('OPALL 0') + #write_to_log("All channels set OFF") + + def all_on(self): + #set ALL channels ON + self.dev.write('OPALL 1') + #write_to_log("All channels set ON") + + def read_current(self, channel): + #reads the current flows right now through the channel + self.dev.write('I%sO?' %(str(channel))) + cur = self.dev.read()[:-1] + #write_to_log("The current at channel %s is: %s" %(channel, cur)) + return cur + + def sense(self, channel, mode): + #mode=0: local, mode=1: remote + self.dev.write('SENSE%s %s' %(channel, mode)) + mod="local" if mode == '0' else "remote" + #write_to_log("Activated %s sense on channel %s" %(mod, str(channel))) + + class HP53131aFreqCounter(): - def __init__(self,address): - resource_manager = visa.ResourceManager() - self.dev=resource_manager.open_resource(address) - self.name=self.dev.query('*IDN?')[:-1] - self.dev.timeout = 5000 - - def close(self): - self.dev.close() - write_to_log ('The connection with: %s is now closed' %(self.name)) - - def send_command(self, command): - #Send a visa command to the device. - #This function and the next one can be used in order to send a command that doesn't covered by this module. - self.dev.write(command) - - def read_response(self, command): - #read from the device. can be used after sending a query command to the device. - return self.dev.read()[-1] - - #Take one of the following measurement options. - #Notice that the 'channel' argument is an option, only for 'frequency' mesurement, when the default is "1" - def meas(self, meas, channel="1"): - channel = str(channel) - if ((meas != "frequency" and meas != "volt_max_peak" and meas != "volt_min_peak") and (channel != "1")): - write_to_log("Error: %s measurement can be taken only from channel 1" %(meas)) - return "" - else: - if (meas == "frequency"): - self.dev.write('MEAS%s:FREQ?' %(channel)) - result = self.dev.read()[:-1] - write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) - elif (meas == "rise_time"): - self.dev.write('MEAS:RTIME?') - result = self.dev.read()[:-1] - write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) - elif (meas == "fall_time"): - self.dev.write('MEAS:FTIME?') - result = self.dev.read()[:-1] - write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) - elif (meas == "period"): - self.dev.write('MEAS:PER?') - result = self.dev.read()[:-1] - write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) - elif (meas == "pos_width"): - self.dev.write('MEAS:PWID?') - result = self.dev.read()[:-1] - write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) - elif (meas == "neg_width"): - self.dev.write('MEAS:NWID?') - result = self.dev.read()[:-1] - write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) - elif (meas == "duty_cycle"): - self.dev.write('MEAS:DCYC?') - result = self.dev.read()[:-1] - write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) - elif (meas == "volt_max_peak"): - self.dev.write('MEAS%s:MAX?' %(channel)) - result = self.dev.read()[:-1] - write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) - elif (meas == "volt_min_peak"): - self.dev.write('MEAS%s:MIN?' %(channel)) - result = self.dev.read()[:-1] - write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) - elif (meas == "ratio"): - self.dev.write('MEAS:FREQ:RAT?') - result = self.dev.read()[:-1] - write_to_log ("Ratio %s to %s: %s" %("1", "2", result)) - elif (meas == "phase"): - self.dev.write('MEAS:PHAS?') - result = self.dev.read()[:-1] - write_to_log ("Phase %s to %s: %s" %("1", "2", result)) - return result - - + def __init__(self,address): + resource_manager = visa.ResourceManager() + self.dev=resource_manager.open_resource(address) + self.name=self.dev.query('*IDN?')[:-1] + self.dev.timeout = 5000 + + def close(self): + self.dev.close() + write_to_log ('The connection with: %s is now closed' %(self.name)) + + def send_command(self, command): + #Send a visa command to the device. + #This function and the next one can be used in order to send a command that doesn't covered by this module. + self.dev.write(command) + + def read_response(self, command): + #read from the device. can be used after sending a query command to the device. + return self.dev.read()[-1] + + #Take one of the following measurement options. + #Notice that the 'channel' argument is an option, only for 'frequency' mesurement, when the default is "1" + def meas(self, meas, channel="1"): + channel = str(channel) + if ((meas != "frequency" and meas != "volt_max_peak" and meas != "volt_min_peak") and (channel != "1")): + write_to_log("Error: %s measurement can be taken only from channel 1" %(meas)) + return "" + else: + if (meas == "frequency"): + self.dev.write('MEAS%s:FREQ?' %(channel)) + result = self.dev.read()[:-1] + write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) + elif (meas == "rise_time"): + self.dev.write('MEAS:RTIME?') + result = self.dev.read()[:-1] + write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) + elif (meas == "fall_time"): + self.dev.write('MEAS:FTIME?') + result = self.dev.read()[:-1] + write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) + elif (meas == "period"): + self.dev.write('MEAS:PER?') + result = self.dev.read()[:-1] + write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) + elif (meas == "pos_width"): + self.dev.write('MEAS:PWID?') + result = self.dev.read()[:-1] + write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) + elif (meas == "neg_width"): + self.dev.write('MEAS:NWID?') + result = self.dev.read()[:-1] + write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) + elif (meas == "duty_cycle"): + self.dev.write('MEAS:DCYC?') + result = self.dev.read()[:-1] + write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) + elif (meas == "volt_max_peak"): + self.dev.write('MEAS%s:MAX?' %(channel)) + result = self.dev.read()[:-1] + write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) + elif (meas == "volt_min_peak"): + self.dev.write('MEAS%s:MIN?' %(channel)) + result = self.dev.read()[:-1] + write_to_log ("%s measurement on channel %s: %s" %(meas, channel, result)) + elif (meas == "ratio"): + self.dev.write('MEAS:FREQ:RAT?') + result = self.dev.read()[:-1] + write_to_log ("Ratio %s to %s: %s" %("1", "2", result)) + elif (meas == "phase"): + self.dev.write('MEAS:PHAS?') + result = self.dev.read()[:-1] + write_to_log ("Phase %s to %s: %s" %("1", "2", result)) + return result + + class HP33120aWaveGen(): - '''Compatible also for Agilent33250A device''' - def __init__(self, address): - resource_manager = visa.ResourceManager() - self.dev=resource_manager.open_resource(address) - self.name=self.dev.query('*IDN?')[:-1] - self.dev.timeout = 5000 - - def close(self): - self.dev.close() - write_to_log ('The connection with: %s is now closed' %(self.name)) - - def send_command(self, command): - #Send a visa command to the device. - #This function and the next one can be used in order to send a command that doesn't covered by this module. - self.dev.write(command) - - def read_response(self, command): - #read from the device. can be used after sending a query command to the device. - return self.dev.read()[-1] - - #Generate a waveform in single command. - #Example: self.generate("SIN", 3000, 1.5, -1) generates a sine wave, 3KHz, 1.5Vpp, -1V offset. - def generate(self, wave, frequency, amplitude, offset): - self.dev.write("APPL:%s %s, %s, %s" %(wave, frequency, amplitude, offset)) - - #Set specifiied shape : SINusoid|SQUare|TRIangle|RAMP|NOISe|DC|USER - def set_shape(self, shape): - self.dev.write("FUNC:SHAP %s" %(shape)) - - #Set frequency - def set_frequency(self, frequency): - self.dev.write("FREQ: %s" %(frequency)) - - def set_amplitude(self, amplitude): - self.dev.write("VOLT: %s" %(amplitude)) - - #Set the units of the amplitude: VPP|VRMS|DBM|DEFault - #Do not affect the offset units, which stays V. - def set_amplitude_units(self, units): - self.dev.write("VOLT:UNIT %s" %(amplitude)) - - def set_offset(self, offset): - self.dev.write("VOLT:OFFS %s" %(offset)) - - def get_shape(self): - result = self.dev.query("FUNC:SHAP?")[:-1] - write_to_log("Signal's shape is: %s" %(result)) - return result - - def get_frequency(self): - result = self.dev.query("FREQ?")[:-1] - write_to_log("Frequency is: %s" %(result)) - return result - - def get_amplitude(self): - result = self.dev.query("VOLT?")[:-1] - write_to_log("Amplitude is: %s" %(result)) - return result - - def get_amplitude_unit(self): - result = self.dev.query("VOLT:UNIT?")[:-1] - write_to_log("Amplitude units are: %s" %(result)) - return result - - - def get_offset(self): - result = self.dev.query("VOLT:OFFS?")[:-1] - write_to_log("Offset is: %s" %(result)) - return result - - #Turn on the output channel. Doesn't necessary when using the generate() command, - #because output channel is being turn on automatically. - def output_on(self): - self.dev.write("OUTPUT ON") - - def output_off(self): - self.dev.write("OUTPUT OFF") + '''Compatible also for Agilent33250A device''' + def __init__(self, address): + resource_manager = visa.ResourceManager() + self.dev=resource_manager.open_resource(address) + self.name=self.dev.query('*IDN?')[:-1] + self.dev.timeout = 5000 + + def close(self): + self.dev.close() + write_to_log ('The connection with: %s is now closed' %(self.name)) + + def send_command(self, command): + #Send a visa command to the device. + #This function and the next one can be used in order to send a command that doesn't covered by this module. + self.dev.write(command) + + def read_response(self, command): + #read from the device. can be used after sending a query command to the device. + return self.dev.read()[-1] + + #Generate a waveform in single command. + #Example: self.generate("SIN", 3000, 1.5, -1) generates a sine wave, 3KHz, 1.5Vpp, -1V offset. + def generate(self, wave, frequency, amplitude, offset): + self.dev.write("APPL:%s %s, %s, %s" %(wave, frequency, amplitude, offset)) + + #Set specifiied shape : SINusoid|SQUare|TRIangle|RAMP|NOISe|DC|USER + def set_shape(self, shape): + self.dev.write("FUNC:SHAP %s" %(shape)) + + #Set frequency + def set_frequency(self, frequency): + self.dev.write("FREQ: %s" %(frequency)) + + def set_amplitude(self, amplitude): + self.dev.write("VOLT: %s" %(amplitude)) + + #Set the units of the amplitude: VPP|VRMS|DBM|DEFault + #Do not affect the offset units, which stays V. + def set_amplitude_units(self, units): + self.dev.write("VOLT:UNIT %s" %(amplitude)) + + def set_offset(self, offset): + self.dev.write("VOLT:OFFS %s" %(offset)) + + def get_shape(self): + result = self.dev.query("FUNC:SHAP?")[:-1] + write_to_log("Signal's shape is: %s" %(result)) + return result + + def get_frequency(self): + result = self.dev.query("FREQ?")[:-1] + write_to_log("Frequency is: %s" %(result)) + return result + + def get_amplitude(self): + result = self.dev.query("VOLT?")[:-1] + write_to_log("Amplitude is: %s" %(result)) + return result + + def get_amplitude_unit(self): + result = self.dev.query("VOLT:UNIT?")[:-1] + write_to_log("Amplitude units are: %s" %(result)) + return result + + + def get_offset(self): + result = self.dev.query("VOLT:OFFS?")[:-1] + write_to_log("Offset is: %s" %(result)) + return result + + #Turn on the output channel. Doesn't necessary when using the generate() command, + #because output channel is being turn on automatically. + def output_on(self): + self.dev.write("OUTPUT ON") + + def output_off(self): + self.dev.write("OUTPUT OFF") class KikusuiPLZ70UA(): - def __init__(self, address): - resource_manager = visa.ResourceManager() - self.dev=resource_manager.open_resource(address) - self.name=self.dev.query('*IDN?')[:-1] - self.dev.timeout = 5000 - - #Close the connection with the device - def close(self): - self.dev.close() - write_to_log ('The connection with: %s is now closed' %(self.name)) - - def send_command(self, command): - #Send a visa command to the device. - #This function and the next one can be used in order to send a command that doesn't covered by this module. - self.dev.write(command) - - def read_response(self, command): - #read from the device. can be used after sending a query command to the device. - return self.dev.read()[-1] - - #Reset the device to factory default settings. - def reset(self): - self.dev.write("*RST") - write_to_log ('%s configured to factory default settings' %(self.name[:-1])) - - def load_on(self): - self.dev.write("INP ON") - if (self.dev.query("INP?") != '0'): - write_to_log("Load in on") - - def load_off(self): - self.dev.write("INP OFF") - if (self.dev.query("INP?") != '1'): - write_to_log("Load in off") - - #mode=CC/CR/CV/CCCV/CRCV, when CC='constant current' CR='constant resistance' CV='constant voltage' - def set_constant_mode(self, channel, mode): - self.dev.write("INST CH%s" %channel) - self.dev.write("FUNC %s" %mode) - - - #Set the conductance (in units of [S]). This funciton sets both of the channels together - def set_conductance(self, conductance): - self.dev.write("COND %s" %conductance) - - #Set the resistance (in unit of [ohm]) by first changing to conductance units. This funciton sets both of the channels together - def set_resistance(self, resistance): - if (float(resistance) != 0): - conductance = str(1/float(resistance)) - self.dev.write("COND %s" %conductance) - - #Set current. This funciton sets both of the channels together - def set_current(self, current): - self.dev.write("CURR %s" %current) - - #Set voltage. This funciton sets both of the channels together - def set_voltage(self, channel, voltage): - self.dev.write("INST CH%s" %channel) - self.dev.write("VOLT %s" %voltage) - - #Read the conductance on the specified channel - def read_conductance(self, channel): - self.dev.write("INST CH%s" %channel) - res = self.dev.query("MEAS:COND?")[:-1] - write_to_log("The conductance on channel %s is: %sS" %(channel, res)) - return res - - #Read the conductance on the specified channel - def read_current(self, channel): - self.dev.write("INST CH%s" %channel) - res = self.dev.query("MEAS:CURR?")[:-1] - write_to_log("The current on channel %s is: %sA" %(channel, res)) - return res - - #Read the conductance on the specified channel - def read_voltage(self, channel): - self.dev.write("INST CH%s" %channel) - res = self.dev.query("MEAS:VOLT?")[:-1] - write_to_log("The voltage on channel %s is: %sV" %(channel, res)) - return res - + def __init__(self, address): + resource_manager = visa.ResourceManager() + self.dev=resource_manager.open_resource(address) + self.name=self.dev.query('*IDN?')[:-1] + self.dev.timeout = 5000 + + #Close the connection with the device + def close(self): + self.dev.close() + write_to_log ('The connection with: %s is now closed' %(self.name)) + + def send_command(self, command): + #Send a visa command to the device. + #This function and the next one can be used in order to send a command that doesn't covered by this module. + self.dev.write(command) + + def read_response(self, command): + #read from the device. can be used after sending a query command to the device. + return self.dev.read()[-1] + + #Reset the device to factory default settings. + def reset(self): + self.dev.write("*RST") + write_to_log ('%s configured to factory default settings' %(self.name[:-1])) + + def load_on(self): + self.dev.write("INP ON") + if (self.dev.query("INP?") != '0'): + write_to_log("Load is on") + + def load_off(self): + self.dev.write("INP OFF") + if (self.dev.query("INP?") != '1'): + write_to_log("Load is off") + + #mode=CC/CR/CV/CCCV/CRCV, when CC='constant current' CR='constant resistance' CV='constant voltage' + def set_constant_mode(self, channel, mode): + self.dev.write("INST CH%s" %channel) + self.dev.write("FUNC %s" %mode) + + + #Set the conductance (in units of [S]). This funciton sets both of the channels together + def set_conductance(self, conductance): + self.dev.write("COND %s" %conductance) + + #Set the resistance (in unit of [ohm]) by first changing to conductance units. This funciton sets both of the channels together + def set_resistance(self, resistance): + if (float(resistance) != 0): + conductance = str(1/float(resistance)) + self.dev.write("COND %s" %conductance) + + #Set current. This funciton sets both of the channels together + def set_current(self, current): + self.dev.write("CURR %s" %current) + + #Set voltage. This funciton sets both of the channels together + def set_voltage(self, channel, voltage): + self.dev.write("INST CH%s" %channel) + self.dev.write("VOLT %s" %voltage) + + #Read the conductance on the specified channel + def read_conductance(self, channel): + self.dev.write("INST CH%s" %channel) + res = self.dev.query("MEAS:COND?")[:-1] + write_to_log("The conductance on channel %s is: %sS" %(channel, res)) + return res + + #Read the conductance on the specified channel + def read_current(self, channel): + self.dev.write("INST CH%s" %channel) + res = self.dev.query("MEAS:CURR?")[:-1] + write_to_log("The current on channel %s is: %sA" %(channel, res)) + return res + + #Read the conductance on the specified channel + def read_voltage(self, channel): + self.dev.write("INST CH%s" %channel) + res = self.dev.query("MEAS:VOLT?")[:-1] + write_to_log("The voltage on channel %s is: %sV" %(channel, res)) + return res + # The connection with this oven is a serial connection - rs232 - which is done using a usb-to-RS232 connector. # This connector appears as a virtual port with a specified 'COM'- this is the COM we need to enter when initializing the connection. class VotschVT4002(): - def __init__(self, com): - self.name="VotschVT4002" - self.ser=serial.Serial() - self.ser.close() - self.ser.port = com - self.ser.baudrate = 9600 - self.ser.bytesize = 8 - self.ser.parity = 'N' - self.ser.stopbits = 1 - self.ser.timeout = 1 - self.ser.open() - - - #Close the serial connection with the device - def close(self): - self.ser.close() - - #Changing the serial connection's parameters: - def change_port(self, com): - self.ser.port = com - write_to_log("{} port changed to {}".format(self.name, com)) - - #Sets the temperature and STARTS the chamber. temp can be from type int, float of str - def set_temp(self, temp): - typ = type(temp) - if (typ == str): - temp = float(temp) - neg = '0' if int(temp) >= 0 else '-' - if (abs(temp) < 10): - temp = neg + '00' + str(round(temp,1)) - elif (temp <= 100 and temp >= -50): - temp = neg + '0' +str(round(temp,1)) - else: - write_to_log("Error: temperature should be between -50C to 100C") - self.ser.write("$00E %s 0000.0 0000.0 0000.0 0000.0 010100000000111013" %temp) - self.ser.write("$00I\r\n") - - #Return the temperature - def read_temp(self): - self.ser.write("$00I\r\n") - res = self.ser.readline() - res = res.split(" ")[1] - if (res[0] == '1'): #negative - res = '-' + res[2:] - else: - res = res[2:] - #write_to_log("Temperature is: %sC" %res) - return res - - #Stops the function of the chamber - def stop_champer(self): - self.ser.write("$00E 0000.0 0000.0 0000.0 0000.0 0000.0 000100000000111013") - - #Sets a temperature, and waits until it gets to the desirable temp. - def wait_for_temp(self,temp): - self.set_temp(temp) - time.sleep(0.5) - current_temp = float(self.read_temp()) - write_to_log("wait for the temperature to reach %sC" %temp) - temp = float(temp) - while (abs(current_temp) <= abs(temp*0.98) or abs(current_temp) >= abs(temp*1.02)): - time.sleep(1) - current_temp = float(self.read_temp()) - write_to_log("Temperature has reached the desirable value") - - def read_error(self): - self.ser.write("$00F\r\n") - time.sleep(1) - return self.ser.readline() + def __init__(self, com): + self.name="VotschVT4002" + self.ser=serial.Serial() + self.ser.close() + self.ser.port = com + self.ser.baudrate = 9600 + self.ser.bytesize = 8 + self.ser.parity = 'N' + self.ser.stopbits = 1 + self.ser.timeout = 1 + self.ser.open() + + + #Close the serial connection with the device + def close(self): + self.ser.close() + + #Changing the serial connection's parameters: + def change_port(self, com): + self.ser.port = com + write_to_log("{} port changed to {}".format(self.name, com)) + + #Sets the temperature and STARTS the chamber. temp can be from type int, float of str + def set_temp(self, temp): + typ = type(temp) + if (typ == str): + temp = float(temp) + neg = '0' if int(temp) >= 0 else '-' + if (abs(temp) < 10): + temp = neg + '00' + str(round(abs(temp), 1)) + elif (temp <= 100 and temp >= -50): + temp = neg + '0' +str(round(abs(temp), 1)) + else: + write_to_log("Error: temperature should be between -50C to 100C") + return + self.ser.write("$00E %s 0000.0 0000.0 0000.0 0000.0 010100000000111013" %temp) + self.ser.write("$00I\r\n") + + #Return the temperature + def read_temp(self): + self.ser.write("$00I\r\n") + res = self.ser.readline() + res = res.split(" ")[1] + if (res[0] == '1'): #negative + res = '-' + res[2:] + else: + res = res[2:] + #write_to_log("Temperature is: %sC" %res) + return res + + #Stops the function of the chamber + def stop_champer(self): + self.ser.write("$00E 0000.0 0000.0 0000.0 0000.0 0000.0 000100000000111013") + + #Sets a temperature, and waits until it gets to the desirable temp. + def wait_for_temp(self,temp): + self.set_temp(temp) + time.sleep(0.5) + current_temp = float(self.read_temp()) + write_to_log("wait for the temperature to reach %sC" %temp) + temp = float(temp) + while (current_temp <= temp-1 or current_temp >= temp+1): + time.sleep(1) + current_temp = float(self.read_temp()) + write_to_log("Temperature has reached the desirable value") + + def read_error(self): + self.ser.write("$00F\r\n") + time.sleep(1) + return self.ser.readline() class Termotron3800(): - def __init__(self,address): - self.tcp_ip = address[0] - self.port = address[1] - self.buffer_size = 1024 - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.connect((self.tcp_ip, self.port)) - self.sock.send("IDEN?\r\n") #ask for device identity - self.name = self.read_line() - self.sock.send("VRSN?\r\n") #ask for software version - self.version = self.read_line() - - - #close connection with device - def close(self): - self.sock.close() - - #read line from socket - def read_line(self): - line = "" - while True: - c = self.sock.recv(64) - if c == "": - break - elif "\r" in c: - line += c.split("\r")[0] - break - else: - line += c - return line - - #before reading the device's answer: - def clear_buffer(self): - c = self.sock.recv(1) - while (c != ""): - c = self.sock.recv(16) - time.sleep(0.1) - - #stop chamber from working - def stop_chamber(self): - err = "0" - k = 0 - while (err != "5" and k<3): #5 means that Termotron received the stop command - self.sock.send("STOP\r\n") #send the STOP command - self.sock.send("SCOD?\r\n") #check if the command had been received - err = self.read_line() - k += 1 - - if (k == 10): #5 means that Termotron received the stop command - write_to_log("Error while sending STOP command to %s" %self.name) - - def run_chamber(self): - self.sock.send("RUNM\r\n") - - - def set_temp(self, temp): - if type(temp != str): - temp = str(temp) - self.sock.send("SETP1,%s\r\n" %temp) - time.sleep(0.1) - self.run_chamber() - - #read the current temperature of the chamber. - def read_temp(self): - self.sock.send("PVAR1?\r\n") #read the deviation from the configured value - time.sleep(0.1) - current_temp = self.read_line() - count = 0 - while current_temp == '0' and count<3: - self.sock.send("PVAR1?\r\n") - current_temp = self.read_line() - count += 1 - return float(current_temp) - - - def wait_for_temp(self, temp): - self.set_temp(temp) - time.sleep(0.1) - current_temp = self.read_temp() - while (abs(current_temp) <= abs(temp*0.98) or abs(current_temp) >= abs(temp*1.02)): - time.sleep(1) - current_temp = self.read_temp() - write_to_log("Temperature has reached the desirable value") + def __init__(self,address): + self.tcp_ip = address[0] + self.port = address[1] + self.buffer_size = 1024 + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.connect((self.tcp_ip, self.port)) + self.sock.send("IDEN?\r\n") #ask for device identity + self.name = self.read_line() + self.sock.send("VRSN?\r\n") #ask for software version + self.version = self.read_line() + + + #close connection with device + def close(self): + self.sock.close() + + #read line from socket + def read_line(self): + line = "" + while True: + c = self.sock.recv(64) + if c == "": + break + elif "\r" in c: + line += c.split("\r")[0] + break + else: + line += c + return line + + #before reading the device's answer: + def clear_buffer(self): + c = self.sock.recv(1) + while (c != ""): + c = self.sock.recv(16) + time.sleep(0.1) + + #stop chamber from working + def stop_chamber(self): + err = "0" + k = 0 + while (err != "5" and k<3): #5 means that Termotron received the stop command + self.sock.send("STOP\r\n") #send the STOP command + self.sock.send("SCOD?\r\n") #check if the command had been received + err = self.read_line() + k += 1 + + if (k == 10): #5 means that Termotron received the stop command + write_to_log("Error while sending STOP command to %s" %self.name) + + def run_chamber(self): + self.sock.send("RUNM\r\n") + + + def set_temp(self, temp): + if type(temp != str): + temp = str(temp) + self.sock.send("SETP1,%s\r\n" %temp) + time.sleep(0.1) + self.run_chamber() + + #read the current temperature of the chamber. + def read_temp(self): + self.sock.send("PVAR1?\r\n") #read the deviation from the configured value + time.sleep(0.1) + current_temp = self.read_line() + count = 0 + while current_temp == '0' and count<3: + self.sock.send("PVAR1?\r\n") + current_temp = self.read_line() + count += 1 + return float(current_temp) + + + def wait_for_temp(self, temp): + self.set_temp(temp) + time.sleep(0.1) + current_temp = self.read_temp() + while (abs(current_temp) <= abs(temp*0.98) or abs(current_temp) >= abs(temp*1.02)): + time.sleep(1) + current_temp = self.read_temp() + write_to_log("Temperature has reached the desirable value") + + + From 28f4fe8cd5b9507726bc07494ba3d16c76371157 Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Mon, 5 Jun 2017 11:20:43 +0300 Subject: [PATCH 10/26] added saleae handling lines --- test1.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/test1.py b/test1.py index a56da0a..5e99953 100644 --- a/test1.py +++ b/test1.py @@ -11,7 +11,7 @@ # #defines: # # T32_APP_CMM_PATH or every define that is specific to this test. # # # -# #import modules: # +# #import modules: # # execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") # #################################################################################################### @@ -38,6 +38,13 @@ # D6.load_boot_file(r'T:\Barkristal\VT_D6_ver_293_Sen333.bin') # print D6.read_IO_port('3000000') +D4 = UartDevice('DBMD4', 'COM9', baudrate=912600, bytesize=8, parity='N', stopbits=1,timeout=1) +D4.change_baudrate(115200) +print D4.ser.baudrate +D4.sync(10) +# D6.load_boot_file(r'T:\Barkristal\VT_D6_ver_293_Sen333.bin') +print D4.read_apb_reg('3000000') +print D4.read_apb_reg('3000008') ######################## @@ -136,6 +143,11 @@ ######################## ## Wave generator -wave_gen = HP33120aWaveGen("GPIB0::12::INSTR") -wave_gen.generate("SIN", '1000', "1", "0") +# wave_gen = HP33120aWaveGen("GPIB0::12::INSTR") +# wave_gen.generate("SIN", '1000', "1", "0") + +######################## +## saleae +# logic = saleae.Saleae() +# logic.capture_to_file(r'c:\saleae_capture') \ No newline at end of file From c0b64976f494d449df937001f64e7d0b7f3b2f65 Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Mon, 5 Jun 2017 11:22:49 +0300 Subject: [PATCH 11/26] test to check the communication with the TCIII (A7) --- Tests/DBMA7/dbma7_bringup.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 Tests/DBMA7/dbma7_bringup.py diff --git a/Tests/DBMA7/dbma7_bringup.py b/Tests/DBMA7/dbma7_bringup.py new file mode 100644 index 0000000..34d8d90 --- /dev/null +++ b/Tests/DBMA7/dbma7_bringup.py @@ -0,0 +1,23 @@ +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMA7." +TEST_NAME = "dbmA7_bringup" + +## Defines +#boot file path for the initialization of UartDeviceTC(): +TC55B01_BOOT_FILE = r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\classd_boot_166.bin" +dbma7_boot_file = r"t:\art\TCIII\script\ram_boot.bin" + +#call the init.py module: +import math +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_regs.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_defs.py") +################################################################################################## + +A7 = UartDeviceTC(name="A7", com="COM22", baudrate=921600, parity='E', stopbits=2, boot_file=dbma7_boot_file) +# A7.change_baudrate(3000000) + +# A7.write_register('3000000', 'ffffaaaa') +chk = A7.read_register('3000000') +print chk From bb3f397476754433966d78e1b2c7e75acb63308e Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Mon, 5 Jun 2017 11:23:35 +0300 Subject: [PATCH 12/26] some tests for the A7 --- Tests/DBMA7/dbma7_tests.py | 89 +++++++++++++++++ Tests/DBMA7/dbma7_tx_gain_n_frequency.py | 91 +++++++++++++++++ Tests/DBMA7/dbma7_tx_noise_floor_test.py | 118 +++++++++++++++++++++++ Tests/DBMA7/dbma7_tx_snr_test.py | 94 ++++++++++++++++++ Tests/DBMA7/dbma7_tx_thdn_test.py | 101 +++++++++++++++++++ 5 files changed, 493 insertions(+) create mode 100644 Tests/DBMA7/dbma7_tests.py create mode 100644 Tests/DBMA7/dbma7_tx_gain_n_frequency.py create mode 100644 Tests/DBMA7/dbma7_tx_noise_floor_test.py create mode 100644 Tests/DBMA7/dbma7_tx_snr_test.py create mode 100644 Tests/DBMA7/dbma7_tx_thdn_test.py diff --git a/Tests/DBMA7/dbma7_tests.py b/Tests/DBMA7/dbma7_tests.py new file mode 100644 index 0000000..d4ba8e6 --- /dev/null +++ b/Tests/DBMA7/dbma7_tests.py @@ -0,0 +1,89 @@ +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMA7." +TEST_NAME = "dbmA7._use_cases" + +## Defines +#boot file path for the initialization of UartDeviceTC(): +TC55B01_BOOT_FILE = r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\classd_boot_166.bin" +dbma7_boot_file = r"t:\art\TCIII\ram_boot.bin" + +#call the init.py module: +import math +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_regs.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_defs.py") +################################################################################################## + +# defines: +CMU_BASE = 0x0000 +AFE_BASE = 0x0100 + + +SCU_CLK_PMOD = CMU_BASE + 0x20 +AFE_BGREF_CFG = AFE_BASE + 0x24 +AFE_OUTAMP_CFG0 = AFE_BASE + 0x0c + +def tx_noise_floor_config(A7): + ''' + 1. Open the band-gap, charge-pump block and LDO, + and enable CLK_CP. + 2. Enable the output amplifier. + 3. Enable the digital path with no specific order + 4. Enable the DAC.''' + + # # pll_configurations: + A7.write_register('4', '1002f00') + A7.write_register('0', '1017') + + # # enable bad-gap: + A7.tc_setbits(AFE_BGREF_CFG, 0x1) + + # # enable CLK_CP: + A7.tc_setbits(SCU_CLK_PMOD, 0x40000) + + # #enable LDO + #TBD + + # # enable OUTAMP0_EN: + A7.tc_setbits(AFE_OUTAMP_CFG0, 0x1) + + # # enable GDAC0_CLK, GDAC1_CLK, GDAC_CLK_MOD: + A7.tc_setbits(SCU_CLK_PMOD, 0xe0000000) + + # # enable I2S: + A7.tc_setbits(SCU_CLK_PMOD, 0x1000) + + +process = 'TYP' #'FF' / 'SS' +oven = VotschVT4002(OVEN_ADDRESS) + +procese_col = 1 +temp_col = 2 +gear_col = 3 +qual_col = 4 +result_col = 5 + +temp_list = ['-40', '25', '90'] +gear_list = [1, 2, 3, 4] +qual_list = ['LP', 'HQ', 'BTL'] +output_load_list = ['32k', '16k'] + +#inital Excel file: +wb1, full_path = create_excel_file(DIR_NAME, LOG_NAME_EXCEL) +ws1 = wb1.create_sheet("Noise_floor_test_{}".format(prosess)) + +ws1.cell(row=1, column=procese_col).value = process +ws1.cell(row=1, column=temp_col).value = temp +ws1.cell(row=1, column=gear_col).value = 'gear_number' +ws1.cell(row=1, column=qual_col).value = 'quality' +ws1.cell(row=1, column=result_col).value = 'result' + + +for temp in temp_list: + oven.wait_for_temp(temp) + + for + tx_noise_floor_config(A7, gear_num, quality) + + diff --git a/Tests/DBMA7/dbma7_tx_gain_n_frequency.py b/Tests/DBMA7/dbma7_tx_gain_n_frequency.py new file mode 100644 index 0000000..67d4843 --- /dev/null +++ b/Tests/DBMA7/dbma7_tx_gain_n_frequency.py @@ -0,0 +1,91 @@ +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMA7." +TEST_NAME = "dbmA7_tx_gain_n_frequency_test + +## Defines +#boot file path for the initialization of UartDeviceTC(): +TC55B01_BOOT_FILE = r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\classd_boot_166.bin" + +#call the init.py module: +import math +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_regs.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_defs.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\apx525_functions.py") +################################################################################################## + +# defines: + + +def tx_gain_config(A7): + '''configure TX path for the test''' + + + + +process = 'TYP' #'FF' / 'SS' +oven = VotschVT4002(OVEN_ADDRESS) +A7 = UartDeviceTC(name="TC", com="COM6", baudrate=115200, parity='E', stopbits=1, boot_file=TC55B01_BOOT_FILE) + + +temp_list = ['-40', '25', '90'] +noise_gating_list = ['off'] +output_load_list = ['32000', '16000'] +vcca_list = ['1.7, 1.8', '2'] +input_amplitude_list= ['-20', '-1', '0'] #in dBFS + +#inital Excel file: +wb1, full_path = create_excel_file(DIR_NAME, LOG_NAME_EXCEL) +ws1 = wb1.create_sheet("gain_n_frequency_test_{}".format(prosess)) + + + +#define the values for this test: +colomns_dict = {} +colomns_list = ['process', + 'temp[C]', + 'VCCA[V]', + 'input amplitude[V]', + 'result', + 'units'] + +#define a colomn number for every value: +for col, value in enumerate(colomns_list): + colomns_dict[value] = col + # insert healines into Excel: + ws1.cell(row=1, column=col).value = value + +wb1.save(full_path) + + +#initial the row number +current_row = 1 + + +for temp in temp_list: + oven.wait_for_temp(temp) + + for load in output_load_list: + electronic_load = KikusuiPLZ70UA(ELECTRONIC_LOAD_ADDRESS) + electronic_load.set_resistance(load) + + for vcca in vcca_list: + for input_amplitude in input_amplitude_list: + current_row += 1 + + #config TX PATH + tx_gain_config(A7) + + #measure gain with APX525; + # THD_resutls, thd_units = SequenceMode_THD_from_project(THD_project) + # THDN_resutls, thdn_units = SequenceMode_THDN_Ratio_from_project(THDN_project) + + #insert values into Excel + ws1.cell(row=current_row, column=colomns_dict['process']).value = process + ws1.cell(row=current_row, column=colomns_dict['temp[C]']).value = temp + ws1.cell(row=current_row, column=colomns_dict['VCCA[V]']).value = vcca + ws1.cell(row=current_row, column=colomns_dict['result']).value = gain_resutls + ws1.cell(row=current_row, column=colomns_dict['units']).value = gain_units + + wb1.save(full_path) \ No newline at end of file diff --git a/Tests/DBMA7/dbma7_tx_noise_floor_test.py b/Tests/DBMA7/dbma7_tx_noise_floor_test.py new file mode 100644 index 0000000..44636fb --- /dev/null +++ b/Tests/DBMA7/dbma7_tx_noise_floor_test.py @@ -0,0 +1,118 @@ +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMA7." +TEST_NAME = "dbmA7_tx_noise_floor" + +## Defines +#boot file path for the initialization of UartDeviceTC(): +TC55B01_BOOT_FILE = r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\classd_boot_166.bin" + +#call the init.py module: +import math +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_regs.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_defs.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\apx525_functions.py") + +################################################################################################## + +# defines: + +def tx_noise_floor_config(A7): + ''' + 1. Open the band-gap, charge-pump block and LDO, + and enable CLK_CP. + 2. Enable the output amplifier. + 3. Enable the digital path with no specific order + 4. Enable the DAC.''' + + # # pll_configurations: + A7.write_register('4', '1002f00') + A7.write_register('0', '1017') + # # enable bad-gap: + A7.tc_setbits(AFE_BGREF_CFG, 0x1) + # # enable CLK_CP: + A7.tc_setbits(SCU_CLK_PMOD, 0x40000) + # #enable LDO + #TBD + # # enable OUTAMP0_EN: + A7.tc_setbits(AFE_OUTAMP_CFG0, 0x1) + # # enable GDAC0_CLK, GDAC1_CLK, GDAC_CLK_MOD: + A7.tc_setbits(SCU_CLK_PMOD, 0xe0000000) + # # enable I2S: + A7.tc_setbits(SCU_CLK_PMOD, 0x1000) + + +process = 'TYP' #'FF' / 'SS' +# oven = VotschVT4002(OVEN_ADDRESS) +# A7 = UartDeviceTC(name="TC", com="COM6", baudrate=115200, parity='E', stopbits=1, boot_file=TC55B01_BOOT_FILE) + +#inital Excel file: +wb1, full_path = create_excel_file(DIR_NAME, LOG_NAME_EXCEL) +ws1 = wb1.create_sheet("Noise_floor_test_{}".format(process)) + +#define the values for this test: +colomns_dict = {} +colomns_list = ['process', + 'temp[C]', + 'VCCA[V]', + 'gear_number', + 'quality', + 'Noise level result', + 'result_units'] +#define a colomn number for every value: +for col, value in enumerate(colomns_list): + colomns_dict[value] = col + # insert healines into Excel: + ws1.cell(row=1, column=col).value = value +wb1.save(full_path) + + +temp_list = ['-40', '25', '90'] +gear_list = [1, 2, 3, 4] +qual_list = ['LP', 'HQ', 'BTL'] +output_load_list = ['32000', '16000'] #ohm +vcca_list = ['1.8'] + + + +#initial the row number +current_row = 1 + + +for temp in temp_list: + # oven.wait_for_temp(temp) + + for load in output_load_list: + electronic_load = KikusuiPLZ70UA(ELECTRONIC_LOAD_ADDRESS) + electronic_load.set_resistance(load) + + for vcca in vcca_list: + + for gear in gear_list: + for qual in qual_list: + + if gear == 4 and qual == 'HQ': + break + elif qual == 'BTL' and gear != 4: + break + + else: + current_row += 1 + + #config TX PATH + # tx_noise_floor_config(A7, gear, qual) + + #measure noise level with APX525; + # Noise_RMS_resutls, units = SequenceMode_NoiseLevel_from_project(Noise_Level_project) + + #insert values into Excel + ws1.cell(row=current_row, column=colomns_dict['process']).value = process + ws1.cell(row=current_row, column=colomns_dict['temp[C]']).value = temp + ws1.cell(row=current_row, column=colomns_dict['VCCA[V]']).value = vcca + ws1.cell(row=current_row, column=colomns_dict['gear_number']).value = gear + ws1.cell(row=current_row, column=colomns_dict['quality']).value = qual + # ws1.cell(row=current_row, column=colomns_dict['Noise level result']).value = Noise_RMS_resutls + # ws1.cell(row=current_row, column=colomns_dict['result_units']).value = units + + wb1.save(full_path) \ No newline at end of file diff --git a/Tests/DBMA7/dbma7_tx_snr_test.py b/Tests/DBMA7/dbma7_tx_snr_test.py new file mode 100644 index 0000000..c1479b6 --- /dev/null +++ b/Tests/DBMA7/dbma7_tx_snr_test.py @@ -0,0 +1,94 @@ +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMA7." +TEST_NAME = "dbmA7_tx_snr_test" + +## Defines +#boot file path for the initialization of UartDeviceTC(): +TC55B01_BOOT_FILE = r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\classd_boot_166.bin" + +#call the init.py module: +import math +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_regs.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_defs.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\apx525_functions.py") +################################################################################################## + +# defines: + +def tx_snr_config(A7): + '''configure TX path for the test''' + + + + +process = 'TYP' #'FF' / 'SS' +oven = VotschVT4002(OVEN_ADDRESS) +A7 = UartDeviceTC(name="TC", com="COM6", baudrate=115200, parity='E', stopbits=1, boot_file=TC55B01_BOOT_FILE) + + +temp_list = ['-40', '25', '90'] +gear_list = ['auto'] +qual_list = ['auto'] +noise_gating_list = ['on', 'off'] +output_load_list = ['32000', '16000'] +vcca_list = ['1.8'] + +#inital Excel file: +wb1, full_path = create_excel_file(DIR_NAME, LOG_NAME_EXCEL) +ws1 = wb1.create_sheet("SNR_test_{}".format(prosess)) + +#define the values for this test: +colomns_dict = {} +colomns_list = ['process', + 'temp[C]', + 'VCCA[V]', + 'gear_number', + 'quality', + 'noise gating', + 'SNR result', + 'result_units'] + +#define a colomn number for every value: +for col, value in enumerate(colomns_list): + colomns_dict[value] = col + # insert healines into Excel: + ws1.cell(row=1, column=col).value = value +wb1.save(full_path) + + +#initial the row number +current_row = 1 + + +for temp in temp_list: + oven.wait_for_temp(temp) + + for load in output_load_list: + electronic_load = KikusuiPLZ70UA(ELECTRONIC_LOAD_ADDRESS) + electronic_load.set_resistance(load) + + for vcca in vcca_list: + for gear in gear_list: + for qual in qual_list: + for noise_gating in noise_gating_list: + current_row += 1 + + #config TX PATH + tx_snr_config(A7, noise_gating) + + #measure noise level with APX525; + # SNR_resutls, units = SequenceMode_SNR_from_project(SNR_project) + + #insert values into Excel + ws1.cell(row=current_row, column=colomns_dict['process']).value = process + ws1.cell(row=current_row, column=colomns_dict['temp[C]']).value = temp + ws1.cell(row=current_row, column=colomns_dict['VCCA[V]']).value = vcca + ws1.cell(row=current_row, column=colomns_dict['gear_number']).value = gear + ws1.cell(row=current_row, column=colomns_dict['quality']).value = qual + ws1.cell(row=current_row, column=colomns_dict['noise_gating']).value = noise_gating + ws1.cell(row=current_row, column=colomns_dict['SNR_resutls']).value = SNR_resutls + ws1.cell(row=current_row, column=colomns_dict['result_units']).value = units + + wb1.save(full_path) \ No newline at end of file diff --git a/Tests/DBMA7/dbma7_tx_thdn_test.py b/Tests/DBMA7/dbma7_tx_thdn_test.py new file mode 100644 index 0000000..d2857ee --- /dev/null +++ b/Tests/DBMA7/dbma7_tx_thdn_test.py @@ -0,0 +1,101 @@ +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMA7." +TEST_NAME = "dbmA7_tx_thdn_test + +## Defines +#boot file path for the initialization of UartDeviceTC(): +TC55B01_BOOT_FILE = r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\classd_boot_166.bin" + +#call the init.py module: +import math +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_regs.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_defs.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\apx525_functions.py") +################################################################################################## + +# defines: + + +def tx_thdn_config(A7): + '''configure TX path for the test''' + + + + +process = 'TYP' #'FF' / 'SS' +oven = VotschVT4002(OVEN_ADDRESS) +A7 = UartDeviceTC(name="TC", com="COM6", baudrate=115200, parity='E', stopbits=1, boot_file=TC55B01_BOOT_FILE) + + +temp_list = ['-40', '25', '90'] +gear_list = ['auto'] +qual_list = ['auto'] +noise_gating_list = ['off'] +output_load_list = ['32000', '16000'] +vcca_list = ['1.7, 1.8', '2'] + +#inital Excel file: +wb1, full_path = create_excel_file(DIR_NAME, LOG_NAME_EXCEL) +ws1 = wb1.create_sheet("thd+n_test_{}".format(prosess)) + + +#define the values for this test: +colomns_dict = {} +colomns_list = ['process', + 'temp[C]', + 'VCCA[V]', + 'gear_number', + 'quality', + 'noise gating', + 'THD result', + 'THD result_units', + 'THD+N result', + 'THD+N result_units'] + +#define a colomn number for every value: +for col, value in enumerate(colomns_list): + colomns_dict[value] = col + # insert healines into Excel: + ws1.cell(row=1, column=col).value = value +wb1.save(full_path) + +#initial the row number +current_row = 1 + + +for temp in temp_list: + oven.wait_for_temp(temp) + + for load in output_load_list: + electronic_load = KikusuiPLZ70UA(ELECTRONIC_LOAD_ADDRESS) + electronic_load.set_resistance(load) + + for vcca in vcca_list: + for gear in gear_list: + for qual in qual_list: + for noise_gating in noise_gating_list: + current_row += 1 + + #config TX PATH + tx_thdn_config(A7) + + #measure noise level with APX525; + # THD_resutls, thd_units = SequenceMode_THD_from_project(THD_project) + # THDN_resutls, thdn_units = SequenceMode_THDN_Ratio_from_project(THDN_project) + + #insert values into Excel + ws1.cell(row=current_row, column=colomns_dict['process']).value = process + ws1.cell(row=current_row, column=colomns_dict['temp[C]']).value = temp + ws1.cell(row=current_row, column=colomns_dict['VCCA[V]']).value = vcca + ws1.cell(row=current_row, column=colomns_dict['gear_number']).value = gear + ws1.cell(row=current_row, column=colomns_dict['quality']).value = qual + ws1.cell(row=current_row, column=colomns_dict['noise_gating']).value = noise_gating + ws1.cell(row=current_row, column=colomns_dict['THD result']).value = THD_resutls + ws1.cell(row=current_row, column=colomns_dict['THD result_units']).value = thd_units + ws1.cell(row=current_row, column=colomns_dict['THD+N result']).value = THDN_resutls + ws1.cell(row=current_row, column=colomns_dict['THD+N result_units']).value = thdn_units + + + wb1.save(full_path) \ No newline at end of file From 8e29cc0479de2ce79e1758b12d377d36c554f67d Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Mon, 5 Jun 2017 11:24:15 +0300 Subject: [PATCH 13/26] dbmd4 leakage test --- Tests/DBMD4/dbma4_leakage_test.py | 87 +++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 Tests/DBMD4/dbma4_leakage_test.py diff --git a/Tests/DBMD4/dbma4_leakage_test.py b/Tests/DBMD4/dbma4_leakage_test.py new file mode 100644 index 0000000..3e38661 --- /dev/null +++ b/Tests/DBMD4/dbma4_leakage_test.py @@ -0,0 +1,87 @@ +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMD4" +TEST_NAME = "dbmd4_leakage_test" + +## Defines +#boot file path for the initialization of UartDeviceTC(): +TC55B01_BOOT_FILE = r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\classd_boot_166.bin" + +#call the init.py module: +import math +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_regs.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_defs.py") +################################################################################################## + +# defines: +num_of_repeat = 4 + +process_col = 1 +temp_col = 2 +core_voltage_col = 3 + + +process = 'TYP' #'TYP' / 'FF' / 'SS' + +oven = VotschVT4002(OVEN_ADDRESS) +power_supply = QL355TPPwrSply(POWER_SUPLLY_ADDRESS) +dmm = Agillent34401A(DMM_ADDRESS) + +power_supply.channel_off(2) +power_supply.set_volt(2, 0) +power_supply.sense(2, 0) + + +temp_list = ['80'] +core_voltage_list = ['1.2'] + +#inital Excel file: +wb1, full_path = create_excel_file(DIR_NAME, LOG_NAME_EXCEL) +ws1 = wb1.create_sheet("DBMD4_leakage_test {}".format(process)) + +#define the values for this test: +colomns_dict = {} +colomns_list = ['process', + 'temp[C]', + 'core_voltage[V]', + 'leakage current w/o core power', + 'leakage current with core power'] + +#define a colomn number for every value: +for col, value in enumerate(colomns_list, 1): + colomns_dict[value] = col + # insert healines into Excel: + ws1.cell(row=1, column=col).value = value +wb1.save(full_path) + +current_row = 1 #initialize the row counter + +for temp in temp_list: + # oven.wait_for_temp(temp) + oven.set_temp(temp) + for voltage in core_voltage_list: + + for i in range(num_of_repeat): + power_supply.set_volt(2, 0) + power_supply.channel_on(2) + time.sleep(0.1) + result1 = dmm.meas('DCV') + + time.sleep(0.1) + power_supply.set_volt(2, voltage) + time.sleep(0.1) + result2 = dmm.meas('DCV') + + current_row += 1 + + # insert values into Excel + ws1.cell(row=current_row, column=colomns_dict['process']).value = process + ws1.cell(row=current_row, column=colomns_dict['temp[C]']).value = temp + ws1.cell(row=current_row, column=colomns_dict['core_voltage[V]']).value = voltage + ws1.cell(row=current_row, column=colomns_dict['leakage current w/o core power']).value = result1 + ws1.cell(row=current_row, column=colomns_dict['leakage current with core power']).value = result2 + + wb1.save(full_path) + + From e9d1b7c0595cc09b7f7d29ea3832b963699400a8 Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Mon, 5 Jun 2017 11:24:48 +0300 Subject: [PATCH 14/26] some test for D7-FPGA --- Tests/DBMD7-FPGA/check.py | 31 +++++++ Tests/DBMD7-FPGA/timers_auto_restart.py | 103 +++++++++++++++++++++++ Tests/DBMD7-FPGA/timers_event_count.py | 93 +++++++++++++++++++++ Tests/DBMD7-FPGA/timers_free_running.py | 106 ++++++++++++++++++++++++ Tests/DBMD7-FPGA/timers_single_count.py | 92 ++++++++++++++++++++ Tests/DBMD7-FPGA/timers_watchdog.py | 88 ++++++++++++++++++++ 6 files changed, 513 insertions(+) create mode 100644 Tests/DBMD7-FPGA/check.py create mode 100644 Tests/DBMD7-FPGA/timers_auto_restart.py create mode 100644 Tests/DBMD7-FPGA/timers_event_count.py create mode 100644 Tests/DBMD7-FPGA/timers_free_running.py create mode 100644 Tests/DBMD7-FPGA/timers_single_count.py create mode 100644 Tests/DBMD7-FPGA/timers_watchdog.py diff --git a/Tests/DBMD7-FPGA/check.py b/Tests/DBMD7-FPGA/check.py new file mode 100644 index 0000000..09e3df6 --- /dev/null +++ b/Tests/DBMD7-FPGA/check.py @@ -0,0 +1,31 @@ + +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMD7-FPGA\check" +TEST_NAME = "check" + +#defines: +T32_APP_CMM_PATH = r"T:\\barkristal\DVF101\SPI\scripts\dvf101_app.cmm" + +#call the init.py module: +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +####################################################################################### + + + +## Uart_Device: + +# D6 = UartDevice('DBMD6', 'COM13', baudrate=912600, bytesize=8, parity='N', stopbits=1,timeout=1) +# D6.change_baudrate(115200) +# print D6.ser.baudrate +# D6.sync(10) +# D6.load_boot_file(r'T:\Barkristal\VT_D6_ver_293_Sen333.bin') +# print D6.read_IO_port('3000000') + +D7 = UartDeviceD7FPGA('DBMD4', 'COM9', baudrate=912600, bytesize=8, parity='N', stopbits=1,timeout=1) +# D4.sync(10) +# D6.load_boot_file(r'T:\Barkristal\VT_D6_ver_293_Sen333.bin') +print D7.read_register('3000000') +print D7.read_register('3000008') +print D7.read_register('3000040') +print D7.read_register('3000024') \ No newline at end of file diff --git a/Tests/DBMD7-FPGA/timers_auto_restart.py b/Tests/DBMD7-FPGA/timers_auto_restart.py new file mode 100644 index 0000000..ecb1009 --- /dev/null +++ b/Tests/DBMD7-FPGA/timers_auto_restart.py @@ -0,0 +1,103 @@ + +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMD7-FPGA\timers" +TEST_NAME = "timers_auto_restart" + + +#call the init.py module: +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +####################################################################################### + + + +###### defines: ###### + +TIMER0_BASE = '50' +TIMER1_BASE = '58' +TIMER2_BASE = '90' +TIMER3_BASE = '98' + +timer = 1 #set the TIMER to be tested +ITERATIONS = 3 + +if timer == 0: + BASE = TIMER0_BASE + MASK = 0x10 +else: + if timer == 1: + BASE = TIMER1_BASE + MASK = 0x8 + else: + if timer == 2: + BASE = TIMER2_BASE + MASK = 0x400 + else: + BASE = TIMER3_BASE + MASK = 0x800 + +D7 = UartDeviceD7FPGA('DBMD4', 'COM5', baudrate=912600, bytesize=8, parity='N', stopbits=1,timeout=1) + + + + + +#enable TIMERS_LP_EN and TIMERS23_EN: +D7.setbits('3000024', '110') + + + + +## auto restart count mode : +write_to_log("####auto-restart mode test on TIMER%d:####"%timer) + +#TIMER_OUT_R cleared by setting CT, auto_restart mode: +D7.write_register(BASE +'00000', '4') +D7.setbits(BASE +'00004', '8') + +#set timer value: +D7.write_register(BASE +'0000c', "8000000") +time.sleep(1) +write_to_log( D7.read_register(BASE +'00010') ) +#start counting down +D7.setbits(BASE +'00004', '1') +time.sleep(1) + +#clear TC: +D7.setbits(BASE + '00004', '4') +#clear TIMER0 interrupt at EICR +D7.write_register('200000c', 'ffff') +time.sleep(0.01) +interrupt0 = int(D7.read_register('2000004'),16) + +timer_cc = D7.read_register(BASE +'00010') +timer_cc_prev = timer_cc +itr = 0 +while (itr < ITERATIONS): + time.sleep(1) + write_to_log(timer_cc) + timer_cc = D7.read_register(BASE +'00010') + if (int(timer_cc, 16) > int(timer_cc_prev, 16)): + itr += 1 + interrupt1 = int(D7.read_register('2000004'), 16) + write_to_log("interrupt0: %x" % (interrupt0)) + write_to_log("interrupt1: %x" % (interrupt1)) + + if (interrupt0 & MASK == 0 and interrupt1 & MASK == MASK): + + write_to_log("timer0 on single count mode PASSED") + else: + write_to_log("timer0 on single count mode FAILED") + + #clear TIMER0 interrupt at EICR + D7.setbits(BASE + '00004', '4') + D7.write_register('200000c', 'ffff') + + else: + interrupt0 = int(D7.read_register('2000004'), 16) + + timer_cc_prev = timer_cc + + + + diff --git a/Tests/DBMD7-FPGA/timers_event_count.py b/Tests/DBMD7-FPGA/timers_event_count.py new file mode 100644 index 0000000..7200af1 --- /dev/null +++ b/Tests/DBMD7-FPGA/timers_event_count.py @@ -0,0 +1,93 @@ + +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMD7-FPGA\timers" +TEST_NAME = "timers_single_count" + + +#call the init.py module: +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +####################################################################################### + + + +###### defines: ###### + +TIMER0_BASE = '50' +TIMER1_BASE = '58' +TIMER2_BASE = '90' +TIMER3_BASE = '98' + +timer = 1 #set the TIMER to be tested +if timer == 0: + BASE = TIMER0_BASE + MASK = 0x10 +else: + if timer == 1: + BASE = TIMER1_BASE + MASK = 0x8 + else: + if timer == 2: + BASE = TIMER2_BASE + MASK = 0x400 + else: + BASE = TIMER3_BASE + MASK = 0x800 + +D7 = UartDeviceD7FPGA('DBMD4', 'COM5', baudrate=912600, bytesize=8, parity='N', stopbits=1,timeout=1) + + + + + +#enable TIMERS_LP_EN and TIMERS23_EN: +D7.setbits('3000024', '110') + + + + + +## event count mode : +write_to_log("####event count mode test on TIMER%d:####"%timer) + +#TIMER_OUT_R cleared by setting CT: +D7.write_register(BASE +'00000', '0c') +time.sleep(0.01) +D7.setbits(BASE + '00004', '4') + +#clear TIMER0 interrupt at EICR +D7.write_register('200000c', 'ffff') +time.sleep(0.1) +#read interrupt status: +interrupt0 = int(D7.read_register('2000004'),16) + + +#COUNTER regiser is reflected at TIMER_CC: +D7.setbits(BASE + '00004', '8') +#set timer value: +D7.write_register(BASE + '0000c', "f") +time.sleep(1) +write_to_log( D7.read_register(BASE + '00010') ) +#start counting down +D7.setbits(BASE + '00004', '1') +time.sleep(1) +timer_cc = D7.read_register(BASE + '00010') +while( timer_cc != '0'): + # write 1 to EW: (click the event counter) + D7.write_register(BASE + '00008', '1') + write_to_log(timer_cc) + timer_cc = D7.read_register(BASE + '00010') +time.sleep(0.01) + +interrupt1 = int(D7.read_register('2000004'), 16) +write_to_log("interrupt0: %x"%(interrupt0)) +write_to_log("interrupt1: %x"%(interrupt1)) + +if (interrupt0&MASK == 0 and interrupt1&MASK == MASK): + + write_to_log("timer0 on event count mode PASSED") +else: + write_to_log("timer0 on event count mode FAILED") + + + diff --git a/Tests/DBMD7-FPGA/timers_free_running.py b/Tests/DBMD7-FPGA/timers_free_running.py new file mode 100644 index 0000000..ec033f2 --- /dev/null +++ b/Tests/DBMD7-FPGA/timers_free_running.py @@ -0,0 +1,106 @@ + +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMD7-FPGA\timers" +TEST_NAME = "timers_free_running" + + +#call the init.py module: +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +####################################################################################### + + + +###### defines: ###### + +TIMER0_BASE = '50' +TIMER1_BASE = '58' +TIMER2_BASE = '90' +TIMER3_BASE = '98' + +timer = 0 #set the TIMER to be tested +ITERATIONS = 2 + +if timer == 0: + BASE = TIMER0_BASE + MASK = 0x10 +else: + if timer == 1: + BASE = TIMER1_BASE + MASK = 0x8 + else: + if timer == 2: + BASE = TIMER2_BASE + MASK = 0x400 + else: + BASE = TIMER3_BASE + MASK = 0x800 + +D7 = UartDeviceD7FPGA('DBMD4', 'COM5', baudrate=912600, bytesize=8, parity='N', stopbits=1,timeout=1) + + + + + +#enable TIMERS_LP_EN and TIMERS23_EN: +D7.setbits('3000024', '110') + +### free running mode : +write_to_log("####free running test on TIMER%d:####"%timer) + + +#pause the counter: +D7.setbits(BASE + '00004', '2') + +#clear TC: +D7.setbits(BASE + '00004', '4') +#clear TIMER0 interrupt at EICR +D7.write_register('200000c', 'ffff') +time.sleep(0.01) +interrupt0 = int(D7.read_register('2000004'),16) + +#TIMER_OUT_R cleared by setting CT, free-running mode, TS(time scale)= /16 : +D7.write_register(BASE +'00000', 'b') + +#un-pause the counter: +D7.clrbits(BASE + '00004', '2') + + +#pause the counter: +D7.setbits(BASE + '00004', '2') +if (int(D7.read_register(BASE +'00010'), 16) == int(D7.read_register(BASE +'00010'), 16)): + write_to_log("Pause Count PASSED") +#un-pause the counter: +D7.clrbits(BASE + '00004', '2') + + +timer_cc = D7.read_register(BASE +'00010') +timer_cc_prev = timer_cc +itr = 0 +while (itr < ITERATIONS): + time.sleep(1) + write_to_log(timer_cc) + timer_cc = D7.read_register(BASE +'00010') + if (int(timer_cc, 16) > int(timer_cc_prev, 16)): + itr += 1 + interrupt1 = int(D7.read_register('2000004'), 16) + write_to_log("interrupt0: %x" % (interrupt0)) + write_to_log("interrupt1: %x" % (interrupt1)) + + if (interrupt0 & MASK == 0 and interrupt1 & MASK == MASK): + + write_to_log("timer0 on single count mode PASSED") + else: + write_to_log("timer0 on single count mode FAILED") + + #clear TIMER0 interrupt at EICR + D7.setbits(BASE + '00004', '4') + D7.write_register('200000c', 'ffff') + + else: + interrupt0 = int(D7.read_register('2000004'), 16) + + timer_cc_prev = timer_cc + + + diff --git a/Tests/DBMD7-FPGA/timers_single_count.py b/Tests/DBMD7-FPGA/timers_single_count.py new file mode 100644 index 0000000..dcd8597 --- /dev/null +++ b/Tests/DBMD7-FPGA/timers_single_count.py @@ -0,0 +1,92 @@ + +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMD7-FPGA\timers" +TEST_NAME = "timers_single_count" + + +#call the init.py module: +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +####################################################################################### + + + +###### defines: ###### + +TIMER0_BASE = '50' +TIMER1_BASE = '58' +TIMER2_BASE = '90' +TIMER3_BASE = '98' + +timer = 1 #set the TIMER to be tested +if timer == 0: + BASE = TIMER0_BASE + MASK = 0x10 +else: + if timer == 1: + BASE = TIMER1_BASE + MASK = 0x8 + else: + if timer == 2: + BASE = TIMER2_BASE + MASK = 0x400 + else: + BASE = TIMER3_BASE + MASK = 0x800 + +D7 = UartDeviceD7FPGA('DBMD4', 'COM5', baudrate=912600, bytesize=8, parity='N', stopbits=1,timeout=1) + + + + + +#enable TIMERS_LP_EN and TIMERS23_EN: +D7.setbits('3000024', '110') + + + + + +## single count mode : +write_to_log("####single count mode test on TIMER%d:####"%timer) + +#TIMER_OUT_R cleared by setting CT: +D7.write_register(BASE +'00000', '0') +time.sleep(0.01) +D7.setbits(BASE + '00004', '4') + +#clear TIMER0 interrupt at EICR +D7.write_register('200000c', 'ffff') +time.sleep(0.1) +#read interrupt status: +interrupt0 = int(D7.read_register('2000004'),16) + + +#COUNTER regiser is reflected at TIMER_CC: +D7.setbits(BASE + '00004', '8') +#set timer value: +D7.write_register(BASE + '0000c', "8000000") +time.sleep(1) +write_to_log( D7.read_register(BASE + '00010') ) +#start counting down +D7.setbits(BASE + '00004', '1') +time.sleep(1) +timer_cc = D7.read_register(BASE + '00010') +while( timer_cc != '0'): + time.sleep(1) + write_to_log(timer_cc) + timer_cc = D7.read_register(BASE + '00010') +time.sleep(0.01) + +interrupt1 = int(D7.read_register('2000004'), 16) +write_to_log("interrupt0: %x"%(interrupt0)) +write_to_log("interrupt1: %x"%(interrupt1)) + +if (interrupt0&MASK == 0 and interrupt1&MASK == MASK): + + write_to_log("timer0 on single count mode PASSED") +else: + write_to_log("timer0 on single count mode FAILED") + + + diff --git a/Tests/DBMD7-FPGA/timers_watchdog.py b/Tests/DBMD7-FPGA/timers_watchdog.py new file mode 100644 index 0000000..092c8e2 --- /dev/null +++ b/Tests/DBMD7-FPGA/timers_watchdog.py @@ -0,0 +1,88 @@ + +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMD7-FPGA\timers" +TEST_NAME = "timers_watchdog" + + +#call the init.py module: +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +####################################################################################### + + + +###### defines: ###### + +TIMER0_BASE = '50' + + +timer = 0 #set the TIMER to be tested +ITERATIONS = 3 + +BASE = TIMER0_BASE +MASK = 0x10 + + +D7 = UartDeviceD7FPGA('DBMD4', 'COM9', baudrate=912600, bytesize=8, parity='N', stopbits=1,timeout=1) + + + + + +#enable TIMERS_LP_EN and TIMERS23_EN: +D7.setbits('3000024', '110') + + + + +## watchdog mode : +write_to_log("####watchdog test on TIMER%d:####"%timer) + + +#set timer value: +D7.write_register(BASE +'0000c', "8000000") +time.sleep(1) +write_to_log( D7.read_register(BASE +'00010') ) + + +#TIMER_OUT_R cleared by setting CT,watchdog mode: +D7.setbits(BASE +'00004', '8') +D7.write_register(BASE +'00000', '14') #sub-mode 2 (NMI) + + +#clear TC: +# D7.setbits(BASE + '00004', '4') +#clear TIMER0 interrupt at EICR +D7.write_register('200000c', 'ffff') +time.sleep(0.01) +interrupt0 = int(D7.read_register('2000004'),16) + + +#start counting down +D7.setbits(BASE +'00008', '1') +time.sleep(0.1) + + +timer_cc = D7.read_register(BASE +'00010') +timer_cc_prev = timer_cc +while( timer_cc != '0'): + time.sleep(1) + write_to_log(timer_cc) + timer_cc = D7.read_register(BASE + '00010') +time.sleep(0.01) + +interrupt1 = int(D7.read_register('2000004'), 16) +write_to_log("interrupt0: %x"%(interrupt0)) +write_to_log("interrupt1: %x"%(interrupt1)) + +if (interrupt0&MASK == 0 and interrupt1&MASK == MASK): + + write_to_log("timer0 on single count mode PASSED") +else: + write_to_log("timer0 on single count mode FAILED") + + + + + + From 1d279e42a9a769a8cd582e90bc00cf97ce4fa821 Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Mon, 5 Jun 2017 11:28:29 +0300 Subject: [PATCH 15/26] excel test- updated --- Tests/functionality_test/excel_test.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Tests/functionality_test/excel_test.py b/Tests/functionality_test/excel_test.py index fae7adc..6c787f9 100644 --- a/Tests/functionality_test/excel_test.py +++ b/Tests/functionality_test/excel_test.py @@ -7,7 +7,7 @@ #call the init.py module: execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") -#defines: +# defines: headlines = ["Block", "Temp", "Voltage", "Result"] temps = ["-40C", "25C", "80C"] voltages = ["0.9", "1.1", "1.2"] @@ -23,9 +23,10 @@ wb1, full_path = create_excel_file(DIR_NAME, LOG_NAME_EXCEL) ws1 = wb1.create_sheet("BIST results") -# thermotron = Termotron3800(TERMOTRON_TCP_IP) -# pwr_sply = QL355TPPwrSply(POWER_SUPLLY_ADDRESS) -# dmm = Agillent34401A(DMM_ADDRESS) +thermotron = Termotron3800(TERMOTRON_TCP_IP) +pwr_sply = QL355TPPwrSply(POWER_SUPLLY_ADDRESS) +dmm = Agillent34401A(DMM_ADDRESS) + #write headlines to excel @@ -38,6 +39,7 @@ #start test and write results to excel for temp in temps: # thermotron.set_temp(temp) + time.sleep(3) for volt in voltages: # pwr_sply.set_volt(volt) From 478d4adb3fa7d28ae5e87b1ce0ea49c9100851be Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Mon, 5 Jun 2017 11:29:02 +0300 Subject: [PATCH 16/26] some test for TCII --- Tests/TC55B01/TC55b_defs.py | 610 +++++++++ Tests/TC55B01/TC55b_regs.py | 1188 +++++++++++++++++ Tests/TC55B01/TC_test.py | 120 ++ Tests/TC55B01/classd_boot_166.bin | Bin 0 -> 64978 bytes .../classd_boot_166_no_last_4_bytes.bin | Bin 0 -> 64976 bytes 5 files changed, 1918 insertions(+) create mode 100644 Tests/TC55B01/TC55b_defs.py create mode 100644 Tests/TC55B01/TC55b_regs.py create mode 100644 Tests/TC55B01/TC_test.py create mode 100644 Tests/TC55B01/classd_boot_166.bin create mode 100644 Tests/TC55B01/classd_boot_166_no_last_4_bytes.bin diff --git a/Tests/TC55B01/TC55b_defs.py b/Tests/TC55B01/TC55b_defs.py new file mode 100644 index 0000000..7c45b48 --- /dev/null +++ b/Tests/TC55B01/TC55b_defs.py @@ -0,0 +1,610 @@ +# =============================================== +# ===== TC55B01 (a.k.a TC2) register defs ===== +# ===== Based on tc55b_defs.dbt ===== +# ===== File Creator: Avihay Shemesh ===== +# ===== Date: 14/03/2017 ===== +# ===== Last modified: 14/03/2017 ===== +# =============================================== + + +NO_MASK = 0x00000000 +FULL_MASK = 0xFFFFFFFF +MASK_LOW = 0x0000FFFF +MASK_HIGH = 0xFFFF0000 + +# ===== REGS DEFAULTS +AFE_INAMP_CFG_DEFAULT = 0x14341434 +AFE_ADC_VREF_DLY_DEFAULT = 0x00ffffff +AFE_ADC_CFG_DEFAULT = 0x0cc90008 +AFE_OUTAMP_CFG_DEFAULT = 0x02203000 +AFE_DAC_CFG_DEFAULT = 0x00000300 +AFE_CHARGE_PUMP_0_CFG_DEFAULT = 0x00408fcc +AFE_CHARGE_PUMP_1_CFG_DEFAULT = 0x00408fcc +AFE_CHARGE_PUMP_0_CTL_DEFAULT = 0x00102010 +AFE_CHARGE_PUMP_1_CTL_DEFAULT = 0x00102010 +AFE_DNS_TO_CP_CTL_DEFAULT = 0x00000000 +AFE_BGREF_CFG_DEFAULT = 0x0000f0f0 +AFE_ANALOG_TEST_MUX_CFG_DEFAULT = 0x0000a0f7 +AFE_SPARE_CFG1_DEFAULT = 0x00000000 +AFE_SPARE_CFG2_DEFAULT = 0x00000000 + +# ===== FIELDS + +AFE_INAMP_CFG_INAMP0_GAIN = 0x0000001F +AFE_INAMP_CFG_INAMP0_ICTRL = 0x00000020 +AFE_INAMP_CFG_INAMP0_INC_CURR = 0x00000040 +AFE_INAMP_CFG_INAMP0_EN = 0x00000080 +AFE_INAMP_CFG_INAMP1_GAIN = 0x00001F00 +AFE_INAMP_CFG_INAMP1_EN = 0x00008000 +AFE_INAMP_CFG_INAMP2_GAIN = 0x001F0000 +AFE_INAMP_CFG_INAMP2_ICTRL = 0x00200000 +AFE_INAMP_CFG_INAMP2_INC_CURR = 0x00400000 +AFE_INAMP_CFG_INAMP2_EN = 0x00800000 +AFE_INAMP_CFG_INAMP3_GAIN = 0x1F000000 +AFE_INAMP_CFG_INAMP3_EN = 0x80000000 + + +AFE_ADC_CFG_ADC0_EN = 0x00000001 +AFE_ADC_CFG_ADC1_EN = 0x00000002 +AFE_ADC_CFG_EN_DR2Z = 0x00000004 +AFE_ADC_CFG_VREFAMP_ICTRL = 0x00000008 +AFE_ADC_CFG_DITHER_PWR = 0x00000700 +AFE_ADC_CFG_DITHER_EN = 0x00000800 +AFE_ADC_CFG_DIS_OPAMPS = 0x00001000 +AFE_ADC_CFG_FLASH_TEST_EN = 0x00002000 +AFE_ADC_CFG_VREF_FAST_CHARGE = 0x00004000 +AFE_ADC_CFG_PLUS_6DB = 0x00008000 +AFE_ADC_CFG_VERF_AMP_FLWR_LVL = 0x00070000 +AFE_ADC_CFG_VREF_FLASH_LVL = 0x00F80000 +AFE_ADC_CFG_VREF_AMP_LVL = 0x07000000 +AFE_ADC_CFG_ICTRL = 0x08000000 +AFE_ADC_CFG_VTEST_OUT_SEL = 0x70000000 +AFE_ADC_CFG_ADC_COM_VREF_EN = 0x80000000 + +AFE_OUTAMP_CFG_OUTAMP0_EN = 0x00000001 +AFE_OUTAMP_CFG_OUTAMP0_EN_BIAS = 0x00000002 +AFE_OUTAMP_CFG_OUTAMP1_EN = 0x00000004 +AFE_OUTAMP_CFG_OUTAMP1_EN_BIAS = 0x00000008 +AFE_OUTAMP_CFG_OUTAMP2_EN = 0x00000010 +AFE_OUTAMP_CFG_OUTAMP2_EN_BIAS = 0x00000020 +AFE_OUTAMP_CFG_OUTAMP3_EN = 0x00000040 +AFE_OUTAMP_CFG_OUTAMP3_EN_BIAS = 0x00000080 +AFE_OUTAMP_CFG_OUTAMP4_EN = 0x00000100 +AFE_OUTAMP_CFG_OUTAMP4_EN_BIAS = 0x00000200 +AFE_OUTAMP_CFG_OUTAMP5_EN = 0x00000400 +AFE_OUTAMP_CFG_OUTAMP5_EN_BIAS = 0x00000800 +AFE_OUTAMP_CFG_ICTRL = 0x00003000 +AFE_OUTAMP_CFG_RES_CONFIG = 0x0000C000 +AFE_OUTAMP_CFG_OUTAMP01_VCCAQ_EN = 0x00010000 +AFE_OUTAMP_CFG_OUTAMP23_VCCAQ_EN = 0x00020000 +AFE_OUTAMP_CFG_OUTAMP45_VCCAQ_EN = 0x00040000 +AFE_OUTAMP_CFG_VCCAQ_BIAS_TRIM = 0x00300000 +AFE_OUTAMP_CFG_VCCAQ_OUTPUT_TRIM = 0x07000000 + +AFE_DAC_CFG_DAC0_EN = 0x1 +AFE_DAC_CFG_DAC1_EN = 0x2 +AFE_DAC_CFG_DAC2_EN = 0x4 +AFE_DAC_CFG_DAC3_EN = 0x8 +AFE_DAC_CFG_DAC4_EN = 0x10 +AFE_DAC_CFG_DAC5_EN = 0x20 +# ===== reserved +AFE_DAC_CFG_DAC_ICTRL_loc = 8 +AFE_DAC_CFG_DAC_ICTRL = 0x700 +# ===== skip +AFE_DAC_CFG_DAC0_FORCE_EN = 0x10000 +AFE_DAC_CFG_DAC1_FORCE_EN = 0x20000 +AFE_DAC_CFG_DAC2_FORCE_EN = 0x40000 +AFE_DAC_CFG_DAC3_FORCE_EN = 0x80000 +AFE_DAC_CFG_DAC4_FORCE_EN = 0x100000 +AFE_DAC_CFG_DAC5_FORCE_EN = 0x200000 + + +AFE_CHARGE_PUMP_x_CFG_CP_EN_REG = 0x1 + +AFE_DNS_TO_CP_CTL_CP0_HI_SIG0_EN = 0x1 +AFE_DNS_TO_CP_CTL_CP0_HI_SIG1_EN = 0x2 +AFE_DNS_TO_CP_CTL_CP0_HI_SIG2_EN = 0x4 +AFE_DNS_TO_CP_CTL_CP0_HI_SIG3_EN = 0x8 +AFE_DNS_TO_CP_CTL_CP1_HI_SIG0_EN = 0x10 +AFE_DNS_TO_CP_CTL_CP1_HI_SIG1_EN = 0x20 +AFE_DNS_TO_CP_CTL_CP1_HI_SIG2_EN = 0x40 +AFE_DNS_TO_CP_CTL_CP1_HI_SIG3_EN = 0x80 + +AFE_BGREF_CFG_BGREF_EN = 0x1 + +# ============================================ +# =================== DDF ==================== +# ============================================ + +# ===== REGS DEFAULTS +DDF_CFG1_DEFAULT = 0x00401F08 +DDF_CFG2_DEFAULT = 0x0A100100 +DDF_CFG3_DEFAULT = 0x00640301 +DDF_DC_OFFST_DEFAULT = 0x00000000 +DDF_EVENT_CFG_DEFAULT = 0x00000000 +DDF_STAT_DEFAULT = 0x00000000 +DDF_TEST_IN_DATA_DEFAULT = 0x00000000 +DDF_OFIFO_DATA_DEFAULT = 0x00000000 +DDF_BQ_B_DEFAULT = 0x00000000 +DDF_BQ_AN_DEFAULT = 0x00000000 + +# ===== FIELDS +DDF_CFG1_FIFO_WM = 0x0000001F +DDF_CFG1_OUT_16_24 = 0x00000020 +DDF_CFG1_ROUND_MODE = 0x00000040 +DDF_CFG1_CDF = 0x0001FF00 +DDF_CFG1_CIC_ORDER = 0x00700000 +DDF_CFG1_CICD_BP = 0x01000000 +DDF_CFG1_CICI_BP = 0x02000000 +DDF_CFG1_INPUT_TEST = 0x04000000 +DDF_CFG1_DDF_ENABLE = 0x08000000 + +DDF_CFG2_POST_IIR_G2 = 0x000001FF +DDF_CFG2_POST_IIR_SHIFT = 0x00000E00 +DDF_CFG2_PRE_IIR_G1 = 0x001FF000 +DDF_CFG2_PRE_IIR_SHIFT = 0x1F000000 + +DDF_CFG3_IDF2 = 0x0000001F +DDF_CFG3_IDF1 = 0x00001F00 +DDF_CFG3_SIIR2 = 0x000F0000 +DDF_CFG3_SIIR1 = 0x00F00000 + +DDF_DC_OFFST_DC_OFFST = 0x00FFFFFF + +DDF_EVENT_CFG_POST_IIR_SAT_IE = 0x00000001 +DDF_EVENT_CFG_PRE_IIR_OVF_IE = 0x00000002 +DDF_EVENT_CFG_IIR_OVF_IE = 0x00000004 +DDF_EVENT_CFG_DATA_OVRN_IE = 0x00000008 +DDF_EVENT_CFG_FIFO_ERR_IE = 0x00000010 +DDF_EVENT_CFG_IE_ALL = 0x1F + +DDF_STAT_OFIFO_STAT = 0x0000001F +DDF_STAT_POST_IIR_ST = 0x00000100 +DDF_STAT_PRE_IIR_ST = 0x00000200 +DDF_STAT_IIR_OVF_ST = 0x00000400 +DDF_STAT_DATA_OVRN_ST = 0x00000800 +DDF_STAT_FIFO_OVRN_ST = 0x00001000 +DDF_STAT_FIFO_UDRN_ST = 0x00002000 +DDF_STAT_WM_ST = 0x00004000 +DDF_STAT_BQ_OVF_INDEX = 0x000F0000 + +DDF_TEST_IN_DATA_TEST_I_DATA = 0x0000001F +DDF_OFIFO_DATA_OFIFO_DATA = 0xFFFFFFFF +DDF_BQ_B_BQi_Bj = 0x0003FFFF +DDF_BQ_AN_BQi_AjN = 0x0003FFFF + +# ============================================ +# ================= SCU ====================== +# ============================================ + +# ===== REGS DEFAULTS +TC55_SCU_PLL_CFG1_DEFAULT = 0x00001018 +TC55_SCU_PLL_CFG2_DEFAULT = 0x11002F00 +TC55_SCU_PLL_LCK_DEFAULT = 0x0007B1FF +TC55_SCU_CLK_DIV1_DEFAULT = 0x00000000 +TC55_SCU_CLK_DIV2_DEFAULT = 0x23470E00 +TC55_SCU_CLK_DIV3_DEFAULT = 0x00001000 +TC55_SCU_CLK_DIV4_DEFAULT = 0x007B3800 +TC55_SCU_CLK_DIV5_DEFAULT = 0x00bf00bf +TC55_SCU_CLK_PMOD_DEFAULT = 0x00000000 +TC55_SCU_BLK_RST_DEFAULT = 0x00000000 +TC55_SCU_I2S_CFG_DEFAULT = 0x00001717 +TC55_SCU_CP_CFG_DEFAULT = 0x0000006C +TC55_SCU_IODS_DEFAULT = 0x00000000 +TC55_SCU_IOKE_DEFAULT = 0xFFFFFFFD +TC55_SCU_IOPE_DEFAULT = 0xF0000002 +TC55_SCU_IOPV_DEFAULT = 0x00000002 +TC55_SCU_IOIE_DEFAULT = 0xFFFFFFFF +TC55_SCU_TEST_CTL1_DEFAULT = 0x3210F000 +TC55_SCU_TEST_CTL2_DEFAULT = 0x00000000 + +# ===== FEILDS +# ===== TC55_SCU_PLL_CFG1 +TC55_BYPASS = 0x00008000 +TC55_TEST = 0x00004000 +TC55_FASTEN = 0x00002000 +TC55_ENSAT = 0x00001000 +TC55_BWADJ = 0x00000FFF + +# ===== TC55_SCU_PLL_CFG2 +TC55_POWER_DOWN = 0x10000000 +TC55_CLKOD = 0x07000000 +TC55_CLKF = 0x001FFF00 +TC55_CLKR = 0x0000003F + +# ===== TC55_SCU_PLL_LCK +TC55_PLL_LCK = 0x01000000 +TC55_PLL_RST_COUNT = 0x003FF000 +TC55_PLL_LOCK_COUNT = 0x00000FFF + +# ===== TC55_SCU_CLK_DIV1 +TC55_SYS_CLK_DIV = 0x0000FF00 +TC55_PLL_POSTDIV = 0x000000FC +TC55_PLL_PREDIV = 0x00000003 + +# ===== TC55_SCU_CLK_DIV2 +TC55_ADC_DAC_CLK_DIV_loc = 24 +TC55_ADC_DAC_CLK_DIV = 0xFF000000 +TC55_ADC_CLK_DIV_loc = 16 +TC55_ADC_CLK_DIV = 0x00FF0000 +TC55_DEM_CLK_DIV_loc = 8 +TC55_DEM_CLK_DIV = 0x0000FF00 +TC55_DDF_CLK_DIV_loc = 0 +TC55_DDF_CLK_DIV = 0x000000FF + +# ===== TC55_SCU_CLK_DIV3 +TC55_DAC2DNS_STRB_DLY_loc = 24 +TC55_DAC2DNS_STRB_DLY = 0xFF000000 +TC55_ADC2DDF_STRB_DLY = 0x00FF0000 +TC55_ADC2ADCDAC_DLY = 0x0000FF00 +TC55_ADC2DEM_DLY = 0x000000FF + +# ===== TC55_SCU_CLK_DIV4 +TC55_CP_CLK_DIV = 0x0FFF0000 +TC55_DAC_CLK_DIV_loc = 8 +TC55_DAC_CLK_DIV = 0x0000FF00 +TC55_DNS_CLK_DIV_loc = 0 +TC55_DNS_CLK_DIV = 0x000000FF + +# ===== TC55_SCU_CLK_DIV5 +TC55_I2S0_CLK_DIV_loc = 0 +TC55_I2S1_CLK_DIV_loc = 16 +TC55_I2S0_CLK_DIV = 0x0000FFFF +TC55_I2S1_CLK_DIV = 0xFFFF0000 + +# ===== TC55_SCU_CLK_PMOD +TC55_CP_CLK_EN = 0x00040000 +TC55_DAC_CLK_EN = 0x00020000 +TC55_ADC_CLK_EN = 0x00010000 +# ===== bits 15-14 reserved +TC55_I2S1_CLK_EN = 0x00002000 +TC55_I2S0_CLK_EN = 0x00001000 +TC55_CLSSG_DNS3_CLK_EN = 0x00000800 +TC55_CLSSG_DNS2_CLK_EN = 0x00000400 +TC55_CLSSG_DNS1_CLK_EN = 0x00000200 +TC55_CLSSG_DNS0_CLK_EN = 0x00000100 +TC55_DNS3_CLK_EN = 0x00000080 +TC55_DNS2_CLK_EN = 0x00000040 +TC55_DNS1_CLK_EN = 0x00000020 +TC55_DNS0_CLK_EN = 0x00000010 +TC55_DEM1_CLK_EN = 0x00000008 +TC55_DEM0_CLK_EN = 0x00000004 +TC55_DDF1_CLK_EN = 0x00000002 +TC55_DDF0_CLK_EN = 0x00000001 + +# ===== TC55_SCU_BLK_RST +TC55_I2S1_RST = 0x00080000 +TC55_I2S0_RST = 0x00040000 +TC55_CLSSG_DNS3_RST = 0x00020000 +TC55_CLSSG_DNS2_RST = 0x00010000 +TC55_CLSSG_DNS1_RST = 0x00008000 +TC55_CLSSG_DNS0_RST = 0x00004000 +TC55_DNS3_CORE_RST = 0x00002000 +TC55_DNS2_CORE_RST = 0x00001000 +TC55_DNS1_CORE_RST = 0x00000800 +TC55_DNS0_CORE_RST = 0x00000400 +TC55_DNS3_RST = 0x00000200 +TC55_DNS2_RST = 0x00000100 +TC55_DNS1_RST = 0x00000080 +TC55_DNS0_RST = 0x00000040 +TC55_DEM1_RST = 0x00000020 +TC55_DEM0_RST = 0x00000010 +TC55_DDF1_CORE_RST = 0x00000008 +TC55_DDF0_CORE_RST = 0x00000004 +TC55_DDF1_RST = 0x00000002 +TC55_DDF0_RST = 0x00000001 + +# ===== TC55_SCU_I2S_CFG +TC55_I2S1_LRC_TYPE = 0x00008000 +TC55_I2S1_SCLK_TYPE = 0x00004000 +TC55_I2S1_WIDTH_CTRL = 0x00001F00 +TC55_I2S0_LRC_TYPE = 0x00000080 +TC55_I2S0_SCLK_TYPE = 0x00000040 +TC55_I2S0_WIDTH_CTRL = 0x0000001F + +TC55_I2S1_WIDTH_32 = 0x00001F00 +TC55_I2S1_WIDTH_24 = 0x00001700 +TC55_I2S1_WIDTH_16 = 0x00000F00 +TC55_I2S0_WIDTH_32 = 0x0000001F +TC55_I2S0_WIDTH_24 = 0x00000017 +TC55_I2S0_WIDTH_16 = 0x0000000F + +# ===== TC55_SCU_IODS +TC55_IODS_TST_MUX_CLK_3 = 0x80000000 +TC55_IODS_TST_MUX_CLK_2 = 0x40000000 +TC55_IODS_TST_MUX_CLK_1 = 0x20000000 +TC55_IODS_TST_MUX_CLK_0 = 0x10000000 +TC55_IODS_TST_MUX_DATA_15 = 0x08000000 +TC55_IODS_TST_MUX_DATA_14 = 0x04000000 +TC55_IODS_TST_MUX_DATA_13 = 0x02000000 +TC55_IODS_TST_MUX_DATA_12 = 0x01000000 +TC55_IODS_TST_MUX_DATA_11 = 0x00800000 +TC55_IODS_TST_MUX_DATA_10 = 0x00400000 +TC55_IODS_TST_MUX_DATA_9 = 0x00200000 +TC55_IODS_TST_MUX_DATA_8 = 0x00100000 +TC55_IODS_TST_MUX_DATA_7 = 0x00080000 + +#define CLSSG_DNS_CLK_MASK 0x0f00 +TC55_IODS_TST_MUX_DATA_6 = 0x00040000 +TC55_IODS_TST_MUX_DATA_5 = 0x00020000 +TC55_IODS_TST_MUX_DATA_4 = 0x00010000 +TC55_IODS_TST_MUX_DATA_3 = 0x00008000 +TC55_IODS_TST_MUX_DATA_2 = 0x00004000 +TC55_IODS_TST_MUX_DATA_1 = 0x00002000 +TC55_IODS_TST_MUX_DATA_0 = 0x00001000 +TC55_IODS_I2S1_TXD = 0x00000800 +TC55_IODS_I2S1_RXD = 0x00000400 +TC55_IODS_I2S1_FSYNC = 0x00000200 +TC55_IODS_I2S1_SCLK = 0x00000100 +TC55_IODS_I2S0_TXD = 0x00000080 +TC55_IODS_I2S0_RXD = 0x00000040 +TC55_IODS_I2S0_FSYNC = 0x00000020 +TC55_IODS_I2S0_SCLK = 0x00000010 +TC55_IODS_SPI_SDO = 0x00000008 +TC55_IODS_SPI_SDI = 0x00000004 +TC55_IODS_SPI_SCS = 0x00000002 +TC55_IODS_SPI_SCK = 0x00000001 + +# ===== TC55_SCU_IOKE +TC55_IOKE_TST_MUX_CLK_3 = 0x80000000 +TC55_IOKE_TST_MUX_CLK_2 = 0x40000000 +TC55_IOKE_TST_MUX_CLK_1 = 0x20000000 +TC55_IOKE_TST_MUX_CLK_0 = 0x10000000 +TC55_IOKE_TST_MUX_DATA_15 = 0x08000000 +TC55_IOKE_TST_MUX_DATA_14 = 0x04000000 +TC55_IOKE_TST_MUX_DATA_13 = 0x02000000 +TC55_IOKE_TST_MUX_DATA_12 = 0x01000000 +TC55_IOKE_TST_MUX_DATA_11 = 0x00800000 +TC55_IOKE_TST_MUX_DATA_10 = 0x00400000 +TC55_IOKE_TST_MUX_DATA_9 = 0x00200000 +TC55_IOKE_TST_MUX_DATA_8 = 0x00100000 +TC55_IOKE_TST_MUX_DATA_7 = 0x00080000 +TC55_IOKE_TST_MUX_DATA_6 = 0x00040000 +TC55_IOKE_TST_MUX_DATA_5 = 0x00020000 +TC55_IOKE_TST_MUX_DATA_4 = 0x00010000 +TC55_IOKE_TST_MUX_DATA_3 = 0x00008000 +TC55_IOKE_TST_MUX_DATA_2 = 0x00004000 +TC55_IOKE_TST_MUX_DATA_1 = 0x00002000 +TC55_IOKE_TST_MUX_DATA_0 = 0x00001000 +TC55_IOKE_I2S1_TXD = 0x00000800 +TC55_IOKE_I2S1_RXD = 0x00000400 +TC55_IOKE_I2S1_FSYNC = 0x00000200 +TC55_IOKE_I2S1_SCLK = 0x00000100 +TC55_IOKE_I2S0_TXD = 0x00000080 +TC55_IOKE_I2S0_RXD = 0x00000040 +TC55_IOKE_I2S0_FSYNC = 0x00000020 +TC55_IOKE_I2S0_SCLK = 0x00000010 +TC55_IOKE_SPI_SDO = 0x00000008 +TC55_IOKE_SPI_SDI = 0x00000004 +TC55_IOKE_SPI_SCS = 0x00000002 +TC55_IOKE_SPI_SCK = 0x00000001 + +# ===== TC55_SCU_IOPE +TC55_IOPE_TST_MUX_CLK_3 = 0x80000000 +TC55_IOPE_TST_MUX_CLK_2 = 0x40000000 +TC55_IOPE_TST_MUX_CLK_1 = 0x20000000 +TC55_IOPE_TST_MUX_CLK_0 = 0x10000000 +TC55_IOPE_TST_MUX_DATA_15 = 0x08000000 +TC55_IOPE_TST_MUX_DATA_14 = 0x04000000 +TC55_IOPE_TST_MUX_DATA_13 = 0x02000000 +TC55_IOPE_TST_MUX_DATA_12 = 0x01000000 +TC55_IOPE_TST_MUX_DATA_11 = 0x00800000 +TC55_IOPE_TST_MUX_DATA_10 = 0x00400000 +TC55_IOPE_TST_MUX_DATA_9 = 0x00200000 +TC55_IOPE_TST_MUX_DATA_8 = 0x00100000 +TC55_IOPE_TST_MUX_DATA_7 = 0x00080000 +TC55_IOPE_TST_MUX_DATA_6 = 0x00040000 +TC55_IOPE_TST_MUX_DATA_5 = 0x00020000 +TC55_IOPE_TST_MUX_DATA_4 = 0x00010000 +TC55_IOPE_TST_MUX_DATA_3 = 0x00008000 +TC55_IOPE_TST_MUX_DATA_2 = 0x00004000 +TC55_IOPE_TST_MUX_DATA_1 = 0x00002000 +TC55_IOPE_TST_MUX_DATA_0 = 0x00001000 +TC55_IOPE_I2S1_TXD = 0x00000800 +TC55_IOPE_I2S1_RXD = 0x00000400 +TC55_IOPE_I2S1_FSYNC = 0x00000200 +TC55_IOPE_I2S1_SCLK = 0x00000100 +TC55_IOPE_I2S0_TXD = 0x00000080 +TC55_IOPE_I2S0_RXD = 0x00000040 +TC55_IOPE_I2S0_FSYNC = 0x00000020 +TC55_IOPE_I2S0_SCLK = 0x00000010 +TC55_IOPE_SPI_SDO = 0x00000008 +TC55_IOPE_SPI_SDI = 0x00000004 +TC55_IOPE_SPI_SCS = 0x00000002 +TC55_IOPE_SPI_SCK = 0x00000001 + +# ===== TC55_SCU_IOPV +TC55_IOPV_TST_MUX_CLK_3 = 0x80000000 +TC55_IOPV_TST_MUX_CLK_2 = 0x40000000 +TC55_IOPV_TST_MUX_CLK_1 = 0x20000000 +TC55_IOPV_TST_MUX_CLK_0 = 0x10000000 +TC55_IOPV_TST_MUX_DATA_15 = 0x08000000 +TC55_IOPV_TST_MUX_DATA_14 = 0x04000000 +TC55_IOPV_TST_MUX_DATA_13 = 0x02000000 +TC55_IOPV_TST_MUX_DATA_12 = 0x01000000 +TC55_IOPV_TST_MUX_DATA_11 = 0x00800000 +TC55_IOPV_TST_MUX_DATA_10 = 0x00400000 +TC55_IOPV_TST_MUX_DATA_9 = 0x00200000 +TC55_IOPV_TST_MUX_DATA_8 = 0x00100000 +TC55_IOPV_TST_MUX_DATA_7 = 0x00080000 +TC55_IOPV_TST_MUX_DATA_6 = 0x00040000 +TC55_IOPV_TST_MUX_DATA_5 = 0x00020000 +TC55_IOPV_TST_MUX_DATA_4 = 0x00010000 +TC55_IOPV_TST_MUX_DATA_3 = 0x00008000 +TC55_IOPV_TST_MUX_DATA_2 = 0x00004000 +TC55_IOPV_TST_MUX_DATA_1 = 0x00002000 +TC55_IOPV_TST_MUX_DATA_0 = 0x00001000 +TC55_IOPV_I2S1_TXD = 0x00000800 +TC55_IOPV_I2S1_RXD = 0x00000400 +TC55_IOPV_I2S1_FSYNC = 0x00000200 +TC55_IOPV_I2S1_SCLK = 0x00000100 +TC55_IOPV_I2S0_TXD = 0x00000080 +TC55_IOPV_I2S0_RXD = 0x00000040 +TC55_IOPV_I2S0_FSYNC = 0x00000020 +TC55_IOPV_I2S0_SCLK = 0x00000010 +TC55_IOPV_SPI_SDO = 0x00000008 +TC55_IOPV_SPI_SDI = 0x00000004 +TC55_IOPV_SPI_SCS = 0x00000002 +TC55_IOPV_SPI_SCK = 0x00000001 + +# ===== TC55_SCU_IOIE +TC55_IOIE_TST_MUX_CLK_3 = 0x80000000 +TC55_IOIE_TST_MUX_CLK_2 = 0x40000000 +TC55_IOIE_TST_MUX_CLK_1 = 0x20000000 +TC55_IOIE_TST_MUX_CLK_0 = 0x10000000 +TC55_IOIE_TST_MUX_DATA_15 = 0x08000000 +TC55_IOIE_TST_MUX_DATA_14 = 0x04000000 +TC55_IOIE_TST_MUX_DATA_13 = 0x02000000 +TC55_IOIE_TST_MUX_DATA_12 = 0x01000000 +TC55_IOIE_TST_MUX_DATA_11 = 0x00800000 +TC55_IOIE_TST_MUX_DATA_10 = 0x00400000 +TC55_IOIE_TST_MUX_DATA_9 = 0x00200000 +TC55_TIOIE_ST_MUX_DATA_8 = 0x00100000 +TC55_IOIE_TST_MUX_DATA_7 = 0x00080000 +TC55_IOIE_TST_MUX_DATA_6 = 0x00040000 +TC55_IOIE_TST_MUX_DATA_5 = 0x00020000 +TC55_IOIE_TST_MUX_DATA_4 = 0x00010000 +TC55_IOIE_TST_MUX_DATA_3 = 0x00008000 +TC55_IOIE_TST_MUX_DATA_2 = 0x00004000 +TC55_IOIE_TST_MUX_DATA_1 = 0x00002000 +TC55_IOIE_TST_MUX_DATA_0 = 0x00001000 +TC55_IOIE_I2S1_TXD = 0x00000800 +TC55_IOIE_I2S1_RXD = 0x00000400 +TC55_IOIE_I2S1_FSYNC = 0x00000200 +TC55_IOIE_I2S1_SCLK = 0x00000100 +TC55_IOIE_I2S0_TXD = 0x00000080 +TC55_IOIE_I2S0_RXD = 0x00000040 +TC55_IOIE_I2S0_FSYNC = 0x00000020 +TC55_IOIE_I2S0_SCLK = 0x00000010 +# ===== bit 3 reserved +TC55_IOIE_SPI_SDI = 0x00000004 +TC55_IOIE_SPI_SCS = 0x00000002 +TC55_IOIE_SPI_SCK = 0x00000001 + +# ===== TC55_SCU_TEST_CTL1 +TC55_DAC3_IN_SEL = 0xF0000000 +TC55_DAC2_IN_SEL = 0x0F000000 +TC55_DAC1_IN_SEL = 0x00F00000 +TC55_DAC0_IN_SEL = 0x000F0000 +TC55_DIFF_CLK_DIV = 0x0000F000 +TC55_DIFF_CLK_EN = 0x00000800 +TC55_SE_CLK0_MUX = 0x00000780 +TC55_SE_CLK1_MUX = 0x00000078 +TC55_DIG_TST_MUX = 0x00000007 + +# ===== TC55_SCU_TEST_CTL2 +# ============================================ +# ===== DNS +# ============================================ +# ===== REGS DEFAULTS +DNS_CFG1_DEFAULT = 0x00000000 +DNS_CFG2_DEFAULT = 0x00007551 +DNS_CFG3_DEFAULT = 0x00000000 +DNS_CFG4_DEFAULT = 0x00000000 +DNS_CFG5_DEFAULT = 0x00100000 +DNS_CFG6_DEFAULT = 0x00000000 +DNS_STAT_DEFAULT = 0x00000000 +DNS_DAT_DEFAULT = 0x00000000 +DNS_BQ_B_DEFAULT = 0x00000000 +DNS_BQ_AN_DEFAULT = 0x00000000 +# ===== FIELDS +DNS_CFG1_ENABLE = 0x00000001 +DNS_CFG1_MUTE = 0x00000002 + +DNS_CFG2_ZIS1 = 0x0000000F +DNS_CFG2_IIR1_B = 0x000000F0 +DNS_CFG2_IIR2_B = 0x00000F00 +DNS_CFG2_ZIS_ZOH2 = 0x0000F000 +DNS_CFG2_ZIS2_ZOH2_MD = 0x00010000 + +DNS_CFG3_GAIN = 0x000001FF +DNS_CFG3_SHIFT = 0x0000F000 + +DNS_CFG4_OFFSET = 0x00FFFFFF + +DNS_CFG5_DITHER_GAIN = 0x0000FFFF +DNS_CFG5_ZOH = 0x001F0000 +DNS_CFG5_DITH_EN = 0x01000000 +DNS_CFG5_SD_MODE = 0x30000000 + +DNS_CFG6_FIFO_WMT = 0x0000001F +DNS_CFG6_WM_IE = 0x00000020 +DNS_CFG6_FIFO_ERR_IE = 0x00000040 +DNS_CFG6_LM_IE = 0x00000080 +DNS_CFG6_BI_TRN_SAT_INT_EN = 0x00000100 + +DNS_STAT_FIFO_STAT = 0x0000001F +DNS_STAT_WM_INT_STAT = 0x00000020 +DNS_STAT_FIFO_OVRN = 0x00000040 +DNS_STAT_FIFO_UDRN = 0x00000080 +DNS_STAT_SCL_L = 0x00000100 +DNS_STAT_SD_L1 = 0x00000200 +DNS_STAT_SD_L2 = 0x00000400 +DNS_STAT_SD_L3 = 0x00000800 +DNS_STAT_SD_L4 = 0x00001000 +DNS_STAT_TRN_SAT = 0x00008000 +DNS_STAT_Bi_TRN_SAT = 0x000F0000 + +DNS_DAT_DATA = 0x00FFFFFF + +DNS_BQ_B_BQi_Bj = 0x0003FFFF +DNS_BQ_AN_BQi_AjN = 0x0003FFFF + +# ============================================ +# ===== DEM +# ============================================ + +# ===== REGS DEFAULTS + +DEM_CTL_DEFAULT = 0x00000004 +DEM_TST_DEFAULT = 0x00000000 +DEM_TEST_INPUT_DEFAULT = 0x00000000 +DEM_TEST_OUTPUT_DEFAULT = 0x00000000 + +# ===== FIELDS + +#DEM_CTL +DEM_EN = 0x00000001 +DEM_BYPASS = 0x00000002 +DITHER_EN = 0x00000004 + +#DEM_TST +I2_SAT_COUNT = 0x0000003F +I2_SAT_RAW = 0x00000040 +I2_SAT_IND_EN = 0x00000080 +MOD4_LOW_BYP = 0x00000100 +DITHER_LOW_BP = 0x00000400 +DITHER_SINGLE_STRB = 0x00000800 +INV_THERM_CNT = 0x0001F000 +DEM_TST_BSY = 0x40000000 +DEM_TST = 0x80000000 + +#DEM_TEST_INPUT +TEST_INPUT = 0x0000FFFF + +#DEM_TEST_OUTPUT +TEST_OUTPUT = 0x0000FFFF + +# ============================================ +# ===== CLASSG_DNS +# ============================================ + +# ===== REGS DEFAULTS + +CLASSG_DNS_CLSG_DET_DEFAULT = 0x0003E884 +CLASSG_DNS_IIR_CFG_DEFAULT = 0x00000248 +CLASSG_DNS_IIR_STAT_DEFAULT = 0x00000000 +CLASSG_DNS_THRS_DET_DEFAULT = 0x0002223E +CLASSG_DNS_BQ_B_DEFAULT = 0x00000000 +CLASSG_DNS_BQ_AN_DEFAULT = 0x00000000 + +# ===== FIELDS +CLASSGX_DET_ENABLE = 0x00000001 + +CLASSG_DNS_CLSG_DET_DLY_LNGT = 0x1E +CLASSG_DNS_IIR_STAT_TRN_SAT = 0x00000001 +CLASSG_DNS_IIR_STAT_Bi_TRN_SAT = 0x0000001E + + + + diff --git a/Tests/TC55B01/TC55b_regs.py b/Tests/TC55B01/TC55b_regs.py new file mode 100644 index 0000000..51b138f --- /dev/null +++ b/Tests/TC55B01/TC55b_regs.py @@ -0,0 +1,1188 @@ +# ==================================================== +# ===== TC55B01 (a.k.a TC2) register list ===== +# ===== Based on tc55b_regs.dbt ===== +# ===== File Creator: Avihay Shemesh ===== +# ===== Date: 14/03/2017 ===== +# ===== Last modified: 14/03/2017 ===== +# ==================================================== + +# ===== Define Base Adressess ===== +SCU_BASE = 0x0000 +AFE_BASE = 0x0100 +DNS0_BASE = 0x0200 +DNS1_BASE = 0x0400 +DNS2_BASE = 0x0600 +DNS3_BASE = 0x0800 +DDF0_BASE = 0x0A00 +DDF1_BASE = 0x0C00 +DEM0_BASE = 0x0E00 +DEM1_BASE = 0x0E40 +VT_BASE = 0x0E80 +TEMP_SENSE_BASE = 0x0EC0 +CLASSG_DNS0_BASE = 0x0F00 +CLASSG_DNS1_BASE = 0x0F80 +CLASSG_DNS2_BASE = 0x1000 +CLASSG_DNS3_BASE = 0x1080 +DCLS0_BASE = 0x1100 +DCLS1_BASE = 0x1200 +SP_IDDF_BASE = 0x1400 +SP_VDDF_BASE = 0x1600 +GDAC0_DNS_BASE = 0x1800 +GDAC0_CTRL_BASE = 0x1980 +GDAC1_DNS_BASE = 0x1A00 +GDAC1_CTRL_BASE = 0x1B80 + +# ===== SCU ===== +#TC55_SCU_PLL_CFG1 = 0x0000 +#TC55_SCU_PLL_CFG2 = 0x0004 +#TC55_SCU_PLL_LCK = 0x0008 +#TC55_SCU_CLK_DIV1 = 0x000c +#TC55_SCU_CLK_DIV2 = 0x0010 +#TC55_SCU_CLK_DIV3 = 0x0014 +#TC55_SCU_CLK_DIV4 = 0x0018 +#TC55_SCU_CLK_DIV5 = 0x001C +#TC55_SCU_CLK_PMOD = 0x0020 +#TC55_SCU_BLK_RST = 0x0024 +#TC55_SCU_I2S_CFG = 0x0028 +#TC55_SCU_IODS = 0x0034 +#TC55_SCU_IOKE = 0x0038 +#TC55_SCU_IOPE = 0x003c +#TC55_SCU_IOIE = 0x0044 +#TC55_SCU_TEST_CTL1 = 0x0050 +#TC55_SCU_TEST_CTL2 = 0x0054 +#TC55_SCU_CLK_DIV6 = 0x0058 +#TC55_SCU_CLK_DIV7 = 0x005C +#TC55_SCU_CLK_DIV8 = 0x0060 +#TC55_SCU_CLK_DIV9 = 0x0064 +#TC55_SCU_BLK_RST1 = 0x0068 +SCU_PLL_CFG1 = 0x0000 +SCU_PLL_CFG2 = 0x0004 +SCU_PLL_LCK = 0x0008 +SCU_CLK_DIV1 = 0x000c +SCU_CLK_DIV2 = 0x0010 +SCU_CLK_DIV3 = 0x0014 +SCU_CLK_DIV4 = 0x0018 +SCU_CLK_DIV5 = 0x001C +SCU_CLK_PMOD = 0x0020 +SCU_BLK_RST = 0x0024 +SCU_I2S_CFG = 0x0028 +SCU_IODS = 0x0034 +SCU_IOKE = 0x0038 +SCU_IOPE = 0x003c +SCU_IOIE = 0x0044 +SCU_TEST_CTL1 = 0x0050 +SCU_TEST_CTL2 = 0x0054 +SCU_CLK_DIV6 = 0x0058 +SCU_CLK_DIV7 = 0x005C +SCU_CLK_DIV8 = 0x0060 +SCU_CLK_DIV9 = 0x0064 +SCU_BLK_RST1 = 0x0068 +# =============== +# ===== AFE +# =============== +AFE_INAMP_CFG = 0x0100 +AFE_ADC_VREF_DLY = 0x0104 +AFE_ADC_CFG = 0x0108 +AFE_OUTAMP_CFG = 0x010C +AFE_DAC_CFG = 0x0110 +AFE_CHARGE_PUMP_0_CFG = 0x0114 +AFE_CHARGE_PUMP_1_CFG = 0x0118 +AFE_CHARGE_PUMP_0_CTL = 0x011C +AFE_CHARGE_PUMP_1_CTL = 0x0120 +AFE_DNS_TO_CP_CTL = 0x0124 +AFE_BGREF_CFG = 0x0128 +AFE_ANALOG_TEST_MUX_CFG = 0x012C +AFE_SPARE_CFG1 = 0x0130 +AFE_SPARE_CFG2 = 0x0134 +AFE_CLASSD_0_CFG1 = 0x013c +AFE_CLASSD_0_CFG2 = 0x0140 +AFE_CLASSD_0_PRTCT_CFG1 = 0x0144 +AFE_CLASSD_0_PRTCT_CFG2 = 0x0148 +AFE_CLASSD_1_CFG1 = 0x014c +AFE_CLASSD_1_CFG2 = 0x0150 +AFE_CLASSD_1_PRTCT_CFG1 = 0x0154 +AFE_CLASSD_1_PRTCT_CFG2 = 0x0158 +AFE_STATUS = 0x015c +# =============== +# ===== DNS0 +# =============== +DNS0_CFG1 = 0x0200 +DNS0_CFG2 = 0x0204 +DNS0_CFG3 = 0x0208 +DNS0_CFG4 = 0x020C +DNS0_CFG5 = 0x0210 +DNS0_CFG6 = 0x0214 +DNS0_STAT = 0x0218 +DNS0_DAT = 0x021C +DNS0_BQ1_B0 = 0x0240 +DNS0_BQ1_B1 = 0x0244 +DNS0_BQ1_B2 = 0x0248 +DNS0_BQ1_A1N = 0x024C +DNS0_BQ1_A2N = 0x0250 +DNS0_BQ2_B0 = 0x0254 +DNS0_BQ2_B1 = 0x0258 +DNS0_BQ2_B2 = 0x025C +DNS0_BQ2_A1N = 0x0260 +DNS0_BQ2_A2N = 0x0264 +DNS0_BQ3_B0 = 0x0268 +DNS0_BQ3_B1 = 0x026C +DNS0_BQ3_B2 = 0x0270 +DNS0_BQ3_A1N = 0x0274 +DNS0_BQ3_A2N = 0x0278 +DNS0_BQ4_B0 = 0x027C +DNS0_BQ4_B1 = 0x0280 +DNS0_BQ4_B2 = 0x0284 +DNS0_BQ4_A1N = 0x0288 +DNS0_BQ4_A2N = 0x028C +DNS0_BQ5_B0 = 0x0290 +DNS0_BQ5_B1 = 0x0294 +DNS0_BQ5_B2 = 0x0298 +DNS0_BQ5_A1N = 0x029C +DNS0_BQ5_A2N = 0x02A0 +DNS0_BQ6_B0 = 0x02A4 +DNS0_BQ6_B1 = 0x02A8 +DNS0_BQ6_B2 = 0x02AC +DNS0_BQ6_A1N = 0x02B0 +DNS0_BQ6_A2N = 0x02B4 +DNS0_BQ7_B0 = 0x02B8 +DNS0_BQ7_B1 = 0x02BC +DNS0_BQ7_B2 = 0x02C0 +DNS0_BQ7_A1N = 0x02C4 +DNS0_BQ7_A2N = 0x02C8 +DNS0_BQ8_B0 = 0x02CC +DNS0_BQ8_B1 = 0x02D0 +DNS0_BQ8_B2 = 0x02D4 +DNS0_BQ8_A1N = 0x02D8 +DNS0_BQ8_A2N = 0x02DC +DNS0_BQ9_B0 = 0x02E0 +DNS0_BQ9_B1 = 0x02E4 +DNS0_BQ9_B2 = 0x02E8 +DNS0_BQ9_A1N = 0x02EC +DNS0_BQ9_A2N = 0x02F0 +DNS0_BQ10_B0 = 0x02F4 +DNS0_BQ10_B1 = 0x02F8 +DNS0_BQ10_B2 = 0x02FC +DNS0_BQ10_A1N = 0x0300 +DNS0_BQ10_A2N = 0x0304 +# =============== +# ===== DNS1 +# =============== +DNS1_CFG1 = 0x0400 +DNS1_CFG2 = 0x0404 +DNS1_CFG3 = 0x0408 +DNS1_CFG4 = 0x040C +DNS1_CFG5 = 0x0410 +DNS1_CFG6 = 0x0414 +DNS1_STAT = 0x0418 +DNS1_DAT = 0x041C +DNS1_BQ1_B0 = 0x0440 +DNS1_BQ1_B1 = 0x0444 +DNS1_BQ1_B2 = 0x0448 +DNS1_BQ1_A1N = 0x044C +DNS1_BQ1_A2N = 0x0450 +DNS1_BQ2_B0 = 0x0454 +DNS1_BQ2_B1 = 0x0458 +DNS1_BQ2_B2 = 0x045C +DNS1_BQ2_A1N = 0x0460 +DNS1_BQ2_A2N = 0x0464 +DNS1_BQ3_B0 = 0x0468 +DNS1_BQ3_B1 = 0x046C +DNS1_BQ3_B2 = 0x0470 +DNS1_BQ3_A1N = 0x0474 +DNS1_BQ3_A2N = 0x0478 +DNS1_BQ4_B0 = 0x047C +DNS1_BQ4_B1 = 0x0480 +DNS1_BQ4_B2 = 0x0484 +DNS1_BQ4_A1N = 0x0488 +DNS1_BQ4_A2N = 0x048C +DNS1_BQ5_B0 = 0x0490 +DNS1_BQ5_B1 = 0x0494 +DNS1_BQ5_B2 = 0x0498 +DNS1_BQ5_A1N = 0x049C +DNS1_BQ5_A2N = 0x04A0 +DNS1_BQ6_B0 = 0x04A4 +DNS1_BQ6_B1 = 0x04A8 +DNS1_BQ6_B2 = 0x04AC +DNS1_BQ6_A1N = 0x04B0 +DNS1_BQ6_A2N = 0x04B4 +DNS1_BQ7_B0 = 0x04B8 +DNS1_BQ7_B1 = 0x04BC +DNS1_BQ7_B2 = 0x04C0 +DNS1_BQ7_A1N = 0x04C4 +DNS1_BQ7_A2N = 0x04C8 +DNS1_BQ8_B0 = 0x04CC +DNS1_BQ8_B1 = 0x04D0 +DNS1_BQ8_B2 = 0x04D4 +DNS1_BQ8_A1N = 0x04D8 +DNS1_BQ8_A2N = 0x04DC +DNS1_BQ9_B0 = 0x04E0 +DNS1_BQ9_B1 = 0x04E4 +DNS1_BQ9_B2 = 0x04E8 +DNS1_BQ9_A1N = 0x04EC +DNS1_BQ9_A2N = 0x04F0 +DNS1_BQ10_B0 = 0x04F4 +DNS1_BQ10_B1 = 0x04F8 +DNS1_BQ10_B2 = 0x04FC +DNS1_BQ10_A1N = 0x0500 +DNS1_BQ10_A2N = 0x0504 +# =============== +# ===== DNS2 +# =============== +DNS2_CFG1 = 0x0600 +DNS2_CFG2 = 0x0604 +DNS2_CFG3 = 0x0608 +DNS2_CFG4 = 0x060C +DNS2_CFG5 = 0x0610 +DNS2_CFG6 = 0x0614 +DNS2_STAT = 0x0618 +DNS2_DAT = 0x061C +DNS2_BQ1_B0 = 0x0640 +DNS2_BQ1_B1 = 0x0644 +DNS2_BQ1_B2 = 0x0648 +DNS2_BQ1_A1N = 0x064C +DNS2_BQ1_A2N = 0x0650 +DNS2_BQ2_B0 = 0x0654 +DNS2_BQ2_B1 = 0x0658 +DNS2_BQ2_B2 = 0x065C +DNS2_BQ2_A1N = 0x0660 +DNS2_BQ2_A2N = 0x0664 +DNS2_BQ3_B0 = 0x0668 +DNS2_BQ3_B1 = 0x066C +DNS2_BQ3_B2 = 0x0670 +DNS2_BQ3_A1N = 0x0674 +DNS2_BQ3_A2N = 0x0678 +DNS2_BQ4_B0 = 0x067C +DNS2_BQ4_B1 = 0x0680 +DNS2_BQ4_B2 = 0x0684 +DNS2_BQ4_A1N = 0x0688 +DNS2_BQ4_A2N = 0x068C +DNS2_BQ5_B0 = 0x0690 +DNS2_BQ5_B1 = 0x0694 +DNS2_BQ5_B2 = 0x0698 +DNS2_BQ5_A1N = 0x069C +DNS2_BQ5_A2N = 0x06A0 +DNS2_BQ6_B0 = 0x06A4 +DNS2_BQ6_B1 = 0x06A8 +DNS2_BQ6_B2 = 0x06AC +DNS2_BQ6_A1N = 0x06B0 +DNS2_BQ6_A2N = 0x06B4 +DNS2_BQ7_B0 = 0x06B8 +DNS2_BQ7_B1 = 0x06BC +DNS2_BQ7_B2 = 0x06C0 +DNS2_BQ7_A1N = 0x06C4 +DNS2_BQ7_A2N = 0x06C8 +DNS2_BQ8_B0 = 0x06CC +DNS2_BQ8_B1 = 0x06D0 +DNS2_BQ8_B2 = 0x06D4 +DNS2_BQ8_A1N = 0x06D8 +DNS2_BQ8_A2N = 0x06DC +DNS2_BQ9_B0 = 0x06E0 +DNS2_BQ9_B1 = 0x06E4 +DNS2_BQ9_B2 = 0x06E8 +DNS2_BQ9_A1N = 0x06EC +DNS2_BQ9_A2N = 0x06F0 +DNS2_BQ10_B0 = 0x06F4 +DNS2_BQ10_B1 = 0x06F8 +DNS2_BQ10_B2 = 0x06FC +DNS2_BQ10_A1N = 0x0700 +DNS2_BQ10_A2N = 0x0704 +# =============== +# ===== DNS3 +# =============== +DNS3_CFG1 = 0x0800 +DNS3_CFG2 = 0x0804 +DNS3_CFG3 = 0x0808 +DNS3_CFG4 = 0x080C +DNS3_CFG5 = 0x0810 +DNS3_CFG6 = 0x0814 +DNS3_STAT = 0x0818 +DNS3_DAT = 0x081C +DNS3_BQ1_B0 = 0x0840 +DNS3_BQ1_B1 = 0x0844 +DNS3_BQ1_B2 = 0x0848 +DNS3_BQ1_A1N = 0x084C +DNS3_BQ1_A2N = 0x0850 +DNS3_BQ2_B0 = 0x0854 +DNS3_BQ2_B1 = 0x0858 +DNS3_BQ2_B2 = 0x085C +DNS3_BQ2_A1N = 0x0860 +DNS3_BQ2_A2N = 0x0864 +DNS3_BQ3_B0 = 0x0868 +DNS3_BQ3_B1 = 0x086C +DNS3_BQ3_B2 = 0x0870 +DNS3_BQ3_A1N = 0x0874 +DNS3_BQ3_A2N = 0x0878 +DNS3_BQ4_B0 = 0x087C +DNS3_BQ4_B1 = 0x0880 +DNS3_BQ4_B2 = 0x0884 +DNS3_BQ4_A1N = 0x0888 +DNS3_BQ4_A2N = 0x088C +DNS3_BQ5_B0 = 0x0890 +DNS3_BQ5_B1 = 0x0894 +DNS3_BQ5_B2 = 0x0898 +DNS3_BQ5_A1N = 0x089C +DNS3_BQ5_A2N = 0x08A0 +DNS3_BQ6_B0 = 0x08A4 +DNS3_BQ6_B1 = 0x08A8 +DNS3_BQ6_B2 = 0x08AC +DNS3_BQ6_A1N = 0x08B0 +DNS3_BQ6_A2N = 0x08B4 +DNS3_BQ7_B0 = 0x08B8 +DNS3_BQ7_B1 = 0x08BC +DNS3_BQ7_B2 = 0x08C0 +DNS3_BQ7_A1N = 0x08C4 +DNS3_BQ7_A2N = 0x08C8 +DNS3_BQ8_B0 = 0x08CC +DNS3_BQ8_B1 = 0x08D0 +DNS3_BQ8_B2 = 0x08D4 +DNS3_BQ8_A1N = 0x08D8 +DNS3_BQ8_A2N = 0x08DC +DNS3_BQ9_B0 = 0x08E0 +DNS3_BQ9_B1 = 0x08E4 +DNS3_BQ9_B2 = 0x08E8 +DNS3_BQ9_A1N = 0x08EC +DNS3_BQ9_A2N = 0x08F0 +DNS3_BQ10_B0 = 0x08F4 +DNS3_BQ10_B1 = 0x08F8 +DNS3_BQ10_B2 = 0x08FC +DNS3_BQ10_A1N = 0x0900 +DNS3_BQ10_A2N = 0x0904 +# =============== +# ===== DDFx +# =============== +DDF_CFG1 = 0x0000 +DDF_CFG2 = 0x0004 +DDF_CFG3 = 0x0008 +DDF_DC_OFFST = 0x000C +DDF_EVENT_CFG = 0x0010 +DDF_STAT = 0x0014 +DDF_TEST_IN_DATA = 0x0018 +DDF_OFIFO_DATA = 0x001C +DDF_BQ1_B0 = 0x0020 +DDF_BQ1_B1 = 0x0024 +DDF_BQ1_B2 = 0x0028 +DDF_BQ1_A1N = 0x002C +DDF_BQ1_A2N = 0x0030 +DDF_BQ2_B0 = 0x0034 +DDF_BQ2_B1 = 0x0038 +DDF_BQ2_B2 = 0x003C +DDF_BQ2_A1N = 0x0040 +DDF_BQ2_A2N = 0x0044 +DDF_BQ3_B0 = 0x0048 +DDF_BQ3_B1 = 0x004C +DDF_BQ3_B2 = 0x0050 +DDF_BQ3_A1N = 0x0054 +DDF_BQ3_A2N = 0x0058 +DDF_BQ4_B0 = 0x005C +DDF_BQ4_B1 = 0x0060 +DDF_BQ4_B2 = 0x0064 +DDF_BQ4_A1N = 0x0068 +DDF_BQ4_A2N = 0x006C +DDF_BQ5_B0 = 0x0070 +DDF_BQ5_B1 = 0x0074 +DDF_BQ5_B2 = 0x0078 +DDF_BQ5_A1N = 0x007C +DDF_BQ5_A2N = 0x0080 +DDF_BQ6_B0 = 0x0084 +DDF_BQ6_B1 = 0x0088 +DDF_BQ6_B2 = 0x008C +DDF_BQ6_A1N = 0x0090 +DDF_BQ6_A2N = 0x0094 +DDF_BQ7_B0 = 0x0098 +DDF_BQ7_B1 = 0x009C +DDF_BQ7_B2 = 0x00A0 +DDF_BQ7_A1N = 0x00A4 +DDF_BQ7_A2N = 0x00A8 +DDF_BQ8_B0 = 0x00AC +DDF_BQ8_B1 = 0x00B0 +DDF_BQ8_B2 = 0x00B4 +DDF_BQ8_A1N = 0x00B8 +DDF_BQ8_A2N = 0x00BC +DDF_BQ9_B0 = 0x00C0 +DDF_BQ9_B1 = 0x00C4 +DDF_BQ9_B2 = 0x00C8 +DDF_BQ9_A1N = 0x00CC +DDF_BQ9_A2N = 0x00D0 +DDF_BQ10_B0 = 0x00D4 +DDF_BQ10_B1 = 0x00D8 +DDF_BQ10_B2 = 0x00DC +DDF_BQ10_A1N = 0x00E0 +DDF_BQ10_A2N = 0x00E4 +# =============== +# ===== DDF0 +# =============== +DDF0_CFG1 = 0x0a00 +DDF0_CFG2 = 0x0a04 +DDF0_CFG3 = 0x0a08 +DDF0_DC_OFFST = 0x0a0C +DDF0_EVENT_CFG = 0x0a10 +DDF0_STAT = 0x0a14 +DDF0_TEST_IN_DATA = 0x0a18 +DDF0_OFIFO_DATA = 0x0a1C +DDF0_BQ1_B0 = 0x0a20 +DDF0_BQ1_B1 = 0x0a24 +DDF0_BQ1_B2 = 0x0a28 +DDF0_BQ1_A1N = 0x0a2C +DDF0_BQ1_A2N = 0x0a30 +DDF0_BQ2_B0 = 0x0a34 +DDF0_BQ2_B1 = 0x0a38 +DDF0_BQ2_B2 = 0x0a3C +DDF0_BQ2_A1N = 0x0a40 +DDF0_BQ2_A2N = 0x0a44 +DDF0_BQ3_B0 = 0x0a48 +DDF0_BQ3_B1 = 0x0a4C +DDF0_BQ3_B2 = 0x0a50 +DDF0_BQ3_A1N = 0x0a54 +DDF0_BQ3_A2N = 0x0a58 +DDF0_BQ4_B0 = 0x0a5C +DDF0_BQ4_B1 = 0x0a60 +DDF0_BQ4_B2 = 0x0a64 +DDF0_BQ4_A1N = 0x0a68 +DDF0_BQ4_A2N = 0x0a6C +DDF0_BQ5_B0 = 0x0a70 +DDF0_BQ5_B1 = 0x0a74 +DDF0_BQ5_B2 = 0x0a78 +DDF0_BQ5_A1N = 0x0a7C +DDF0_BQ5_A2N = 0x0a80 +DDF0_BQ6_B0 = 0x0a84 +DDF0_BQ6_B1 = 0x0a88 +DDF0_BQ6_B2 = 0x0a8C +DDF0_BQ6_A1N = 0x0a90 +DDF0_BQ6_A2N = 0x0a94 +DDF0_BQ7_B0 = 0x0a98 +DDF0_BQ7_B1 = 0x0a9C +DDF0_BQ7_B2 = 0x0aA0 +DDF0_BQ7_A1N = 0x0aA4 +DDF0_BQ7_A2N = 0x0aA8 +DDF0_BQ8_B0 = 0x0aAC +DDF0_BQ8_B1 = 0x0aB0 +DDF0_BQ8_B2 = 0x0aB4 +DDF0_BQ8_A1N = 0x0aB8 +DDF0_BQ8_A2N = 0x0aBC +DDF0_BQ9_B0 = 0x0aC0 +DDF0_BQ9_B1 = 0x0aC4 +DDF0_BQ9_B2 = 0x0aC8 +DDF0_BQ9_A1N = 0x0aCC +DDF0_BQ9_A2N = 0x0aD0 +DDF0_BQ10_B0 = 0x0aD4 +DDF0_BQ10_B1 = 0x0aD8 +DDF0_BQ10_B2 = 0x0aDC +DDF0_BQ10_A1N = 0x0aE0 +DDF0_BQ10_A2N = 0x0aE4 +# =============== +# ===== DDF1 +# =============== +DDF1_CFG1 = 0x0c00 +DDF1_CFG2 = 0x0c04 +DDF1_CFG3 = 0x0c08 +DDF1_DC_OFFST = 0x0c0C +DDF1_EVENT_CFG = 0x0c10 +DDF1_STAT = 0x0c14 +DDF1_TEST_IN_DATA = 0x0c18 +DDF1_OFIFO_DATA = 0x0c1C +DDF1_BQ1_B0 = 0x0c20 +DDF1_BQ1_B1 = 0x0c24 +DDF1_BQ1_B2 = 0x0c28 +DDF1_BQ1_A1N = 0x0c2C +DDF1_BQ1_A2N = 0x0c30 +DDF1_BQ2_B0 = 0x0c34 +DDF1_BQ2_B1 = 0x0c38 +DDF1_BQ2_B2 = 0x0c3C +DDF1_BQ2_A1N = 0x0c40 +DDF1_BQ2_A2N = 0x0c44 +DDF1_BQ3_B0 = 0x0c48 +DDF1_BQ3_B1 = 0x0c4C +DDF1_BQ3_B2 = 0x0c50 +DDF1_BQ3_A1N = 0x0c54 +DDF1_BQ3_A2N = 0x0c58 +DDF1_BQ4_B0 = 0x0c5C +DDF1_BQ4_B1 = 0x0c60 +DDF1_BQ4_B2 = 0x0c64 +DDF1_BQ4_A1N = 0x0c68 +DDF1_BQ4_A2N = 0x0c6C +DDF1_BQ5_B0 = 0x0c70 +DDF1_BQ5_B1 = 0x0c74 +DDF1_BQ5_B2 = 0x0c78 +DDF1_BQ5_A1N = 0x0c7C +DDF1_BQ5_A2N = 0x0c80 +DDF1_BQ6_B0 = 0x0c84 +DDF1_BQ6_B1 = 0x0c88 +DDF1_BQ6_B2 = 0x0c8C +DDF1_BQ6_A1N = 0x0c90 +DDF1_BQ6_A2N = 0x0c94 +DDF1_BQ7_B0 = 0x0c98 +DDF1_BQ7_B1 = 0x0c9C +DDF1_BQ7_B2 = 0x0cA0 +DDF1_BQ7_A1N = 0x0cA4 +DDF1_BQ7_A2N = 0x0cA8 +DDF1_BQ8_B0 = 0x0cAC +DDF1_BQ8_B1 = 0x0cB0 +DDF1_BQ8_B2 = 0x0cB4 +DDF1_BQ8_A1N = 0x0cB8 +DDF1_BQ8_A2N = 0x0cBC +DDF1_BQ9_B0 = 0x0cC0 +DDF1_BQ9_B1 = 0x0cC4 +DDF1_BQ9_B2 = 0x0cC8 +DDF1_BQ9_A1N = 0x0cCC +DDF1_BQ9_A2N = 0x0cD0 +DDF1_BQ10_B0 = 0x0cD4 +DDF1_BQ10_B1 = 0x0cD8 +DDF1_BQ10_B2 = 0x0cDC +DDF1_BQ10_A1N = 0x0cE0 +DDF1_BQ10_A2N = 0x0cE4 +# =============== +# ===== DEM0 +# =============== +DEM0_CTL = 0x0e00 +DEM0_TST = 0x0e04 +DEM0_TEST_INPUT = 0x0e08 +DEM0_TEST_OUTPUT = 0x0e0C +# =============== +# ===== DEM1 +# =============== +DEM1_CTL = 0x0e40 +DEM1_TST = 0x0e44 +DEM1_TEST_INPUT = 0x0e48 +DEM1_TEST_OUTPUT = 0x0e4C +# =============== +# ===== VT_ADC_CTRL VOICE_TRIG SAR ADC +# =============== +VT_CTL_CFG1 = 0x0E80 +VT_CTL_CFG2 = 0x0E84 +VT_CTL_CFG3 = 0x0E88 +VT_CTL_CFG4 = 0x0E8C +VT_CTL_CFG5 = 0x0E90 +VT_CTL_CFG6 = 0x0E94 +VT_CTL_CFG7 = 0x0E98 +VT_CTL_STAT = 0x0E9C +# =============== +# ===== TEMP_SENSE +# =============== +TEMP_SENSE_CFG1 = 0x0EC0 +TEMP_SENSE_STAT = 0x0EC4 +# =============== +# ===== CLASSG_DNS0 +# =============== +CLASSG_DNS0_CLSG_DET = 0x0f00 +CLASSG_DNS0_IIR_CFG = 0x0f04 +CLASSG_DNS0_IIR_STAT = 0x0f08 +CLASSG_DNS0_THRS_DET = 0x0f0C +CLASSG_DNS0_BQ1_B0 = 0x0f10 +CLASSG_DNS0_BQ1_B1 = 0x0f14 +CLASSG_DNS0_BQ1_B2 = 0x0f18 +CLASSG_DNS0_BQ1_A1N = 0x0f1C +CLASSG_DNS0_BQ1_A2N = 0x0f20 +CLASSG_DNS0_BQ2_B0 = 0x0f24 +CLASSG_DNS0_BQ2_B1 = 0x0f28 +CLASSG_DNS0_BQ2_B2 = 0x0f2C +CLASSG_DNS0_BQ2_A1N = 0x0f30 +CLASSG_DNS0_BQ2_A2N = 0x0f34 +CLASSG_DNS0_BQ3_B0 = 0x0f38 +CLASSG_DNS0_BQ3_B1 = 0x0f3C +CLASSG_DNS0_BQ3_B2 = 0x0f40 +CLASSG_DNS0_BQ3_A1N = 0x0f44 +CLASSG_DNS0_BQ3_A2N = 0x0f48 +CLASSG_DNS0_BQ4_B0 = 0x0f4C +CLASSG_DNS0_BQ4_B1 = 0x0f50 +CLASSG_DNS0_BQ4_B2 = 0x0f54 +CLASSG_DNS0_BQ4_A1N = 0x0f58 +CLASSG_DNS0_BQ4_A2N = 0x0f5C +# =============== +# ===== CLASSG_DNS1 +# =============== +CLASSG_DNS1_CLSG_DET = 0x0f80 +CLASSG_DNS1_IIR_CFG = 0x0f84 +CLASSG_DNS1_IIR_STAT = 0x0f88 +CLASSG_DNS1_THRS_DET = 0x0f8C +CLASSG_DNS1_BQ1_B0 = 0x0f90 +CLASSG_DNS1_BQ1_B1 = 0x0f94 +CLASSG_DNS1_BQ1_B2 = 0x0f98 +CLASSG_DNS1_BQ1_A1N = 0x0f9C +CLASSG_DNS1_BQ1_A2N = 0x0fa0 +CLASSG_DNS1_BQ2_B0 = 0x0fa4 +CLASSG_DNS1_BQ2_B1 = 0x0fa8 +CLASSG_DNS1_BQ2_B2 = 0x0faC +CLASSG_DNS1_BQ2_A1N = 0x0fb0 +CLASSG_DNS1_BQ2_A2N = 0x0fb4 +CLASSG_DNS1_BQ3_B0 = 0x0fb8 +CLASSG_DNS1_BQ3_B1 = 0x0fbC +CLASSG_DNS1_BQ3_B2 = 0x0fc0 +CLASSG_DNS1_BQ3_A1N = 0x0fc4 +CLASSG_DNS1_BQ3_A2N = 0x0fc8 +CLASSG_DNS1_BQ4_B0 = 0x0fcC +CLASSG_DNS1_BQ4_B1 = 0x0fd0 +CLASSG_DNS1_BQ4_B2 = 0x0fd4 +CLASSG_DNS1_BQ4_A1N = 0x0fd8 +CLASSG_DNS1_BQ4_A2N = 0x0fdC +# =============== +# ===== CLASSG_DNS2 +# =============== +CLASSG_DNS2_CLSG_DET = 0x1000 +CLASSG_DNS2_IIR_CFG = 0x1004 +CLASSG_DNS2_IIR_STAT = 0x1008 +CLASSG_DNS2_THRS_DET = 0x100C +CLASSG_DNS2_BQ1_B0 = 0x1010 +CLASSG_DNS2_BQ1_B1 = 0x1014 +CLASSG_DNS2_BQ1_B2 = 0x1018 +CLASSG_DNS2_BQ1_A1N = 0x101C +CLASSG_DNS2_BQ1_A2N = 0x1020 +CLASSG_DNS2_BQ2_B0 = 0x1024 +CLASSG_DNS2_BQ2_B1 = 0x1028 +CLASSG_DNS2_BQ2_B2 = 0x102C +CLASSG_DNS2_BQ2_A1N = 0x1030 +CLASSG_DNS2_BQ2_A2N = 0x1034 +CLASSG_DNS2_BQ3_B0 = 0x1038 +CLASSG_DNS2_BQ3_B1 = 0x103C +CLASSG_DNS2_BQ3_B2 = 0x1040 +CLASSG_DNS2_BQ3_A1N = 0x1044 +CLASSG_DNS2_BQ3_A2N = 0x1048 +CLASSG_DNS2_BQ4_B0 = 0x104C +CLASSG_DNS2_BQ4_B1 = 0x1050 +CLASSG_DNS2_BQ4_B2 = 0x1054 +CLASSG_DNS2_BQ4_A1N = 0x1058 +CLASSG_DNS2_BQ4_A2N = 0x105C +# =============== +# ===== CLASSG_DNS3 +# =============== +CLASSG_DNS3_CLSG_DET = 0x1080 +CLASSG_DNS3_IIR_CFG = 0x1084 +CLASSG_DNS3_IIR_STAT = 0x1088 +CLASSG_DNS3_THRS_DET = 0x108C +CLASSG_DNS3_BQ1_B0 = 0x1090 +CLASSG_DNS3_BQ1_B1 = 0x1094 +CLASSG_DNS3_BQ1_B2 = 0x1098 +CLASSG_DNS3_BQ1_A1N = 0x109C +CLASSG_DNS3_BQ1_A2N = 0x10a0 +CLASSG_DNS3_BQ2_B0 = 0x10a4 +CLASSG_DNS3_BQ2_B1 = 0x10a8 +CLASSG_DNS3_BQ2_B2 = 0x10aC +CLASSG_DNS3_BQ2_A1N = 0x10b0 +CLASSG_DNS3_BQ2_A2N = 0x10b4 +CLASSG_DNS3_BQ3_B0 = 0x10b8 +CLASSG_DNS3_BQ3_B1 = 0x10bC +CLASSG_DNS3_BQ3_B2 = 0x10c0 +CLASSG_DNS3_BQ3_A1N = 0x10c4 +CLASSG_DNS3_BQ3_A2N = 0x10c8 +CLASSG_DNS3_BQ4_B0 = 0x10cC +CLASSG_DNS3_BQ4_B1 = 0x10d0 +CLASSG_DNS3_BQ4_B2 = 0x10d4 +CLASSG_DNS3_BQ4_A1N = 0x10d8 +CLASSG_DNS3_BQ4_A2N = 0x10dC +# =============== +# ===== classD modulator - dcls_pwm_tc55b01 - DCLS0 +# =============== +CLSD0_SD_CTRL = 0x1100 +CLSD0_GAIN_CTRL1 = 0x1104 +CLSD0_GAIN_CTRL2 = 0x1108 +CLSD0_DC = 0x110C +CLSD0_IIR_CTRL = 0x1110 +CLSD0_RAMP_CFG = 0x1114 +CLSD0_MOD_INT = 0x1118 +CLSD0_BQ1_B0 = 0x111C +CLSD0_BQ1_B1 = 0x1120 +CLSD0_BQ1_B2 = 0x1124 +CLSD0_BQ1_A0N = 0x1128 +CLSD0_BQ1_A1N = 0x112C +CLSD0_BQ2_B0 = 0x1130 +CLSD0_BQ2_B1 = 0x1134 +CLSD0_BQ2_B2 = 0x1138 +CLSD0_BQ2_A0N = 0x113C +CLSD0_BQ2_A1N = 0x1140 +CLSD0_BQ3_B0 = 0x1144 +CLSD0_BQ3_B1 = 0x1148 +CLSD0_BQ3_B2 = 0x114C +CLSD0_BQ3_A0N = 0x1150 +CLSD0_BQ3_A1N = 0x1154 +CLSD0_BQ4_B0 = 0x1158 +CLSD0_BQ4_B1 = 0x115C +CLSD0_BQ4_B2 = 0x1160 +CLSD0_BQ4_A0N = 0x1164 +CLSD0_BQ4_A1N = 0x1168 +CLSD0_BQ5_B0 = 0x116C +CLSD0_BQ5_B1 = 0x1170 +CLSD0_BQ5_B2 = 0x1174 +CLSD0_BQ5_A0N = 0x1178 +CLSD0_BQ5_A1N = 0x117C +CLSD0_BQ6_B0 = 0x1180 +CLSD0_BQ6_B1 = 0x1184 +CLSD0_BQ6_B2 = 0x1188 +CLSD0_BQ6_A0N = 0x118C +CLSD0_BQ6_A1N = 0x1190 +CLSD0_BQ7_B0 = 0x1194 +CLSD0_BQ7_B1 = 0x1198 +CLSD0_BQ7_B2 = 0x119C +CLSD0_BQ7_A0N = 0x11A0 +CLSD0_BQ7_A1N = 0x11A4 +CLSD0_BQ8_B0 = 0x11A8 +CLSD0_BQ8_B1 = 0x11AC +CLSD0_BQ8_B2 = 0x11B0 +CLSD0_BQ8_A0N = 0x11B4 +CLSD0_BQ8_A1N = 0x11B8 +CLSD0_BQ9_B0 = 0x11BC +CLSD0_BQ9_B1 = 0x11C0 +CLSD0_BQ9_B2 = 0x11C4 +CLSD0_BQ9_A0N = 0x11C8 +CLSD0_BQ9_A1N = 0x11CC +CLSD0_BQ10_B0 = 0x11D0 +CLSD0_BQ10_B1 = 0x11D4 +CLSD0_BQ10_B2 = 0x11D8 +CLSD0_BQ10_A0N = 0x11DC +CLSD0_BQ10_A1N = 0x11E0 +# =============== +# ===== classD modulator - dcls_pwm_tc55b01 - DCLS1 +# =============== +CLSD1_SD_CTRL = 0x1200 +CLSD1_GAIN_CTRL1 = 0x1204 +CLSD1_GAIN_CTRL2 = 0x1208 +CLSD1_DC = 0x120C +CLSD1_IIR_CTRL = 0x1210 +CLSD1_RAMP_CFG = 0x1214 +CLSD1_MOD_INT = 0x1218 +CLSD1_BQ1_B0 = 0x121C +CLSD1_BQ1_B1 = 0x1220 +CLSD1_BQ1_B2 = 0x1224 +CLSD1_BQ1_A0N = 0x1228 +CLSD1_BQ1_A1N = 0x122C +CLSD1_BQ2_B0 = 0x1230 +CLSD1_BQ2_B1 = 0x1234 +CLSD1_BQ2_B2 = 0x1238 +CLSD1_BQ2_A0N = 0x123C +CLSD1_BQ2_A1N = 0x1240 +CLSD1_BQ3_B0 = 0x1244 +CLSD1_BQ3_B1 = 0x1248 +CLSD1_BQ3_B2 = 0x124C +CLSD1_BQ3_A0N = 0x1250 +CLSD1_BQ3_A1N = 0x1254 +CLSD1_BQ4_B0 = 0x1258 +CLSD1_BQ4_B1 = 0x125C +CLSD1_BQ4_B2 = 0x1260 +CLSD1_BQ4_A0N = 0x1264 +CLSD1_BQ4_A1N = 0x1268 +CLSD1_BQ5_B0 = 0x126C +CLSD1_BQ5_B1 = 0x1270 +CLSD1_BQ5_B2 = 0x1274 +CLSD1_BQ5_A0N = 0x1278 +CLSD1_BQ5_A1N = 0x127C +CLSD1_BQ6_B0 = 0x1280 +CLSD1_BQ6_B1 = 0x1284 +CLSD1_BQ6_B2 = 0x1288 +CLSD1_BQ6_A0N = 0x128C +CLSD1_BQ6_A1N = 0x1290 +CLSD1_BQ7_B0 = 0x1294 +CLSD1_BQ7_B1 = 0x1298 +CLSD1_BQ7_B2 = 0x129C +CLSD1_BQ7_A0N = 0x12A0 +CLSD1_BQ7_A1N = 0x12A4 +CLSD1_BQ8_B0 = 0x12A8 +CLSD1_BQ8_B1 = 0x12AC +CLSD1_BQ8_B2 = 0x12B0 +CLSD1_BQ8_A0N = 0x12B4 +CLSD1_BQ8_A1N = 0x12B8 +CLSD1_BQ9_B0 = 0x12BC +CLSD1_BQ9_B1 = 0x12C0 +CLSD1_BQ9_B2 = 0x12C4 +CLSD1_BQ9_A0N = 0x12C8 +CLSD1_BQ9_A1N = 0x12CC +CLSD1_BQ10_B0 = 0x12D0 +CLSD1_BQ10_B1 = 0x12D4 +CLSD1_BQ10_B2 = 0x12D8 +CLSD1_BQ10_A0N = 0x12DC +CLSD1_BQ10_A1N = 0x12E0 +# =============== +# ===== SP_IDDF +# =============== +SP_IDDF_CFG1 = 0x1400 +SP_IDDF_CFG2 = 0x1404 +SP_IDDF_STAT = 0x1408 +SP_IDDF_FIR_DC_OFST = 0x140c +SP_IDDF_FIFO_DATA = 0x1410 +# Bi-Quad Coef +SP_IDDF_BQ1_B0 = 0x1414 +SP_IDDF_BQ1_B1 = 0x1418 +SP_IDDF_BQ1_B2 = 0x141c +SP_IDDF_BQ1_A1N = 0x1420 +SP_IDDF_BQ1_A2N = 0x1424 +SP_IDDF_BQ2_B0 = 0x1428 +SP_IDDF_BQ2_B1 = 0x142c +SP_IDDF_BQ2_B2 = 0x1430 +SP_IDDF_BQ2_A1N = 0x1434 +SP_IDDF_BQ2_A2N = 0x1438 +SP_IDDF_BQ3_B0 = 0x143c +SP_IDDF_BQ3_B1 = 0x1440 +SP_IDDF_BQ3_B2 = 0x1444 +SP_IDDF_BQ3_A1N = 0x1448 +SP_IDDF_BQ3_A2N = 0x144c +SP_IDDF_BQ4_B0 = 0x1450 +SP_IDDF_BQ4_B1 = 0x1454 +SP_IDDF_BQ4_B2 = 0x1458 +SP_IDDF_BQ4_A1N = 0x145c +SP_IDDF_BQ4_A2N = 0x1460 +# FIR coeff +SP_IDDF_FIR_COEF_0 = 0x1480 +SP_IDDF_FIR_COEF_1 = 0x1484 +SP_IDDF_FIR_COEF_2 = 0x1488 +SP_IDDF_FIR_COEF_3 = 0x148c +SP_IDDF_FIR_COEF_4 = 0x1490 +SP_IDDF_FIR_COEF_5 = 0x1494 +SP_IDDF_FIR_COEF_6 = 0x1498 +SP_IDDF_FIR_COEF_7 = 0x149c +SP_IDDF_FIR_COEF_8 = 0x14a0 +SP_IDDF_FIR_COEF_9 = 0x14a4 +SP_IDDF_FIR_COEF_10 = 0x14a8 +SP_IDDF_FIR_COEF_11 = 0x14ac +SP_IDDF_FIR_COEF_12 = 0x14b0 +SP_IDDF_FIR_COEF_13 = 0x14b4 +SP_IDDF_FIR_COEF_14 = 0x14b8 +SP_IDDF_FIR_COEF_15 = 0x14bc +SP_IDDF_FIR_COEF_16 = 0x14c0 +SP_IDDF_FIR_COEF_17 = 0x14c4 +SP_IDDF_FIR_COEF_18 = 0x14c8 +SP_IDDF_FIR_COEF_19 = 0x14cc +SP_IDDF_FIR_COEF_20 = 0x14d0 +SP_IDDF_FIR_COEF_21 = 0x14d4 +SP_IDDF_FIR_COEF_22 = 0x14d8 +SP_IDDF_FIR_COEF_23 = 0x14dc +SP_IDDF_FIR_COEF_24 = 0x14e0 +SP_IDDF_FIR_COEF_25 = 0x14e4 +SP_IDDF_FIR_COEF_26 = 0x14e8 +SP_IDDF_FIR_COEF_27 = 0x14ec +SP_IDDF_FIR_COEF_28 = 0x14f0 +SP_IDDF_FIR_COEF_29 = 0x14f4 +SP_IDDF_FIR_COEF_30 = 0x14f8 +SP_IDDF_FIR_COEF_31 = 0x14fc +SP_IDDF_FIR_COEF_32 = 0x1500 +SP_IDDF_FIR_COEF_33 = 0x1504 +SP_IDDF_FIR_COEF_34 = 0x1508 +SP_IDDF_FIR_COEF_35 = 0x150c +SP_IDDF_FIR_COEF_36 = 0x1510 +SP_IDDF_FIR_COEF_37 = 0x1514 +SP_IDDF_FIR_COEF_38 = 0x1518 +SP_IDDF_FIR_COEF_39 = 0x151c +SP_IDDF_FIR_COEF_40 = 0x1520 +SP_IDDF_FIR_COEF_41 = 0x1524 +SP_IDDF_FIR_COEF_42 = 0x1528 +SP_IDDF_FIR_COEF_43 = 0x152c +SP_IDDF_FIR_COEF_44 = 0x1530 +SP_IDDF_FIR_COEF_45 = 0x1534 +SP_IDDF_FIR_COEF_46 = 0x1538 +SP_IDDF_FIR_COEF_47 = 0x153c +SP_IDDF_FIR_COEF_48 = 0x1540 +SP_IDDF_FIR_COEF_49 = 0x1544 +SP_IDDF_FIR_COEF_50 = 0x1548 +SP_IDDF_FIR_COEF_51 = 0x154c +SP_IDDF_FIR_COEF_52 = 0x1550 +SP_IDDF_FIR_COEF_53 = 0x1554 +SP_IDDF_FIR_COEF_54 = 0x1558 +SP_IDDF_FIR_COEF_55 = 0x155c +SP_IDDF_FIR_COEF_56 = 0x1560 +SP_IDDF_FIR_COEF_57 = 0x1564 +SP_IDDF_FIR_COEF_58 = 0x1568 +SP_IDDF_FIR_COEF_59 = 0x156c +SP_IDDF_FIR_COEF_60 = 0x1570 +SP_IDDF_FIR_COEF_61 = 0x1574 +SP_IDDF_FIR_COEF_62 = 0x1578 +SP_IDDF_FIR_COEF_63 = 0x157c +SP_IDDF_FIR_COEF_64 = 0x1580 +SP_IDDF_FIR_1ST_COEF = SP_IDDF_FIR_COEF_0 +SP_IDDF_FIR_LST_COEF = SP_IDDF_FIR_COEF_64 + +# =============== +# ===== SP_VDDF +# =============== +SP_VDDF_CFG1 = 0x1600 +SP_VDDF_CFG2 = 0x1604 +SP_VDDF_STAT = 0x1608 +SP_VDDF_FIR_DC_OFST = 0x160c +SP_VDDF_FIFO_DATA = 0x1610 +# Bi-Quad Coef +SP_VDDF_BQ1_B0 = 0x1614 +SP_VDDF_BQ1_B1 = 0x1618 +SP_VDDF_BQ1_B2 = 0x161c +SP_VDDF_BQ1_A1N = 0x1620 +SP_VDDF_BQ1_A2N = 0x1624 +SP_VDDF_BQ2_B0 = 0x1628 +SP_VDDF_BQ2_B1 = 0x162c +SP_VDDF_BQ2_B2 = 0x1630 +SP_VDDF_BQ2_A1N = 0x1634 +SP_VDDF_BQ2_A2N = 0x1638 +SP_VDDF_BQ3_B0 = 0x163c +SP_VDDF_BQ3_B1 = 0x1640 +SP_VDDF_BQ3_B2 = 0x1644 +SP_VDDF_BQ3_A1N = 0x1648 +SP_VDDF_BQ3_A2N = 0x164c +SP_VDDF_BQ4_B0 = 0x1650 +SP_VDDF_BQ4_B1 = 0x1654 +SP_VDDF_BQ4_B2 = 0x1658 +SP_VDDF_BQ4_A1N = 0x165c +SP_VDDF_BQ4_A2N = 0x1660 +#FIR coeff +SP_VDDF_FIR_COEF_0 = 0x1680 +SP_VDDF_FIR_COEF_1 = 0x1684 +SP_VDDF_FIR_COEF_2 = 0x1688 +SP_VDDF_FIR_COEF_3 = 0x168c +SP_VDDF_FIR_COEF_4 = 0x1690 +SP_VDDF_FIR_COEF_5 = 0x1694 +SP_VDDF_FIR_COEF_6 = 0x1698 +SP_VDDF_FIR_COEF_7 = 0x169c +SP_VDDF_FIR_COEF_8 = 0x16a0 +SP_VDDF_FIR_COEF_9 = 0x16a4 +SP_VDDF_FIR_COEF_10 = 0x16a8 +SP_VDDF_FIR_COEF_11 = 0x16ac +SP_VDDF_FIR_COEF_12 = 0x16b0 +SP_VDDF_FIR_COEF_13 = 0x16b4 +SP_VDDF_FIR_COEF_14 = 0x16b8 +SP_VDDF_FIR_COEF_15 = 0x16bc +SP_VDDF_FIR_COEF_16 = 0x16c0 +SP_VDDF_FIR_COEF_17 = 0x16c4 +SP_VDDF_FIR_COEF_18 = 0x16c8 +SP_VDDF_FIR_COEF_19 = 0x16cc +SP_VDDF_FIR_COEF_20 = 0x16d0 +SP_VDDF_FIR_COEF_21 = 0x16d4 +SP_VDDF_FIR_COEF_22 = 0x16d8 +SP_VDDF_FIR_COEF_23 = 0x16dc +SP_VDDF_FIR_COEF_24 = 0x16e0 +SP_VDDF_FIR_COEF_25 = 0x16e4 +SP_VDDF_FIR_COEF_26 = 0x16e8 +SP_VDDF_FIR_COEF_27 = 0x16ec +SP_VDDF_FIR_COEF_28 = 0x16f0 +SP_VDDF_FIR_COEF_29 = 0x16f4 +SP_VDDF_FIR_COEF_30 = 0x16f8 +SP_VDDF_FIR_COEF_31 = 0x16fc +SP_VDDF_FIR_COEF_32 = 0x1700 +SP_VDDF_FIR_COEF_33 = 0x1704 +SP_VDDF_FIR_COEF_34 = 0x1708 +SP_VDDF_FIR_COEF_35 = 0x170c +SP_VDDF_FIR_COEF_36 = 0x1710 +SP_VDDF_FIR_COEF_37 = 0x1714 +SP_VDDF_FIR_COEF_38 = 0x1718 +SP_VDDF_FIR_COEF_39 = 0x171c +SP_VDDF_FIR_COEF_40 = 0x1720 +SP_VDDF_FIR_COEF_41 = 0x1724 +SP_VDDF_FIR_COEF_42 = 0x1728 +SP_VDDF_FIR_COEF_43 = 0x172c +SP_VDDF_FIR_COEF_44 = 0x1730 +SP_VDDF_FIR_COEF_45 = 0x1734 +SP_VDDF_FIR_COEF_46 = 0x1738 +SP_VDDF_FIR_COEF_47 = 0x173c +SP_VDDF_FIR_COEF_48 = 0x1740 +SP_VDDF_FIR_COEF_49 = 0x1744 +SP_VDDF_FIR_COEF_50 = 0x1748 +SP_VDDF_FIR_COEF_51 = 0x174c +SP_VDDF_FIR_COEF_52 = 0x1750 +SP_VDDF_FIR_COEF_53 = 0x1754 +SP_VDDF_FIR_COEF_54 = 0x1758 +SP_VDDF_FIR_COEF_55 = 0x175c +SP_VDDF_FIR_COEF_56 = 0x1760 +SP_VDDF_FIR_COEF_57 = 0x1764 +SP_VDDF_FIR_COEF_58 = 0x1768 +SP_VDDF_FIR_COEF_59 = 0x176c +SP_VDDF_FIR_COEF_60 = 0x1770 +SP_VDDF_FIR_COEF_61 = 0x1774 +SP_VDDF_FIR_COEF_62 = 0x1778 +SP_VDDF_FIR_COEF_63 = 0x177c +SP_VDDF_FIR_COEF_64 = 0x1780 +SP_VDDF_FIR_1ST_COEF = SP_VDDF_FIR_COEF_0 +SP_VDDF_FIR_LST_COEF = SP_VDDF_FIR_COEF_64 + +# =============== +# ===== GDAC0_DNS +# =============== +GDAC0_DNS_CFG1 = 0x1800 +GDAC0_DNS_CFG2 = 0x1804 +GDAC0_DNS_CFG5 = 0x1810 +GDAC0_DNS_CFG6 = 0x1814 +GDAC0_DNS_STAT = 0x1818 +GDAC0_DNS_DAT = 0x181C +GDAC0_DNS_BQ1_B0 = 0x1840 +GDAC0_DNS_BQ1_B1 = 0x1844 +GDAC0_DNS_BQ1_B2 = 0x1848 +GDAC0_DNS_BQ1_A1N = 0x184C +GDAC0_DNS_BQ1_A2N = 0x1850 +GDAC0_DNS_BQ2_B0 = 0x1854 +GDAC0_DNS_BQ2_B1 = 0x1858 +GDAC0_DNS_BQ2_B2 = 0x185C +GDAC0_DNS_BQ2_A1N = 0x1860 +GDAC0_DNS_BQ2_A2N = 0x1864 +GDAC0_DNS_BQ3_B0 = 0x1868 +GDAC0_DNS_BQ3_B1 = 0x186C +GDAC0_DNS_BQ3_B2 = 0x1870 +GDAC0_DNS_BQ3_A1N = 0x1874 +GDAC0_DNS_BQ3_A2N = 0x1878 +GDAC0_DNS_BQ4_B0 = 0x187C +GDAC0_DNS_BQ4_B1 = 0x1880 +GDAC0_DNS_BQ4_B2 = 0x1884 +GDAC0_DNS_BQ4_A1N = 0x1888 +GDAC0_DNS_BQ4_A2N = 0x188C +GDAC0_DNS_BQ5_B0 = 0x1890 +GDAC0_DNS_BQ5_B1 = 0x1894 +GDAC0_DNS_BQ5_B2 = 0x1898 +GDAC0_DNS_BQ5_A1N = 0x189C +GDAC0_DNS_BQ5_A2N = 0x18A0 +GDAC0_DNS_BQ6_B0 = 0x18A4 +GDAC0_DNS_BQ6_B1 = 0x18A8 +GDAC0_DNS_BQ6_B2 = 0x18AC +GDAC0_DNS_BQ6_A1N = 0x18B0 +GDAC0_DNS_BQ6_A2N = 0x18B4 +GDAC0_DNS_BQ7_B0 = 0x18B8 +GDAC0_DNS_BQ7_B1 = 0x18BC +GDAC0_DNS_BQ7_B2 = 0x18C0 +GDAC0_DNS_BQ7_A1N = 0x18C4 +GDAC0_DNS_BQ7_A2N = 0x18C8 +GDAC0_DNS_BQ8_B0 = 0x18CC +GDAC0_DNS_BQ8_B1 = 0x18D0 +GDAC0_DNS_BQ8_B2 = 0x18D4 +GDAC0_DNS_BQ8_A1N = 0x18D8 +GDAC0_DNS_BQ8_A2N = 0x18DC +GDAC0_DNS_BQ9_B0 = 0x18E0 +GDAC0_DNS_BQ9_B1 = 0x18E4 +GDAC0_DNS_BQ9_B2 = 0x18E8 +GDAC0_DNS_BQ9_A1N = 0x18EC +GDAC0_DNS_BQ9_A2N = 0x18F0 +GDAC0_DNS_BQ10_B0 = 0x18F4 +GDAC0_DNS_BQ10_B1 = 0x18F8 +GDAC0_DNS_BQ10_B2 = 0x18FC +GDAC0_DNS_BQ10_A1N = 0x1900 +GDAC0_DNS_BQ10_A2N = 0x1904 +GDAC0_DNS_GAIN1 = 0x1908 +GDAC0_DNS_OFFSET1 = 0x190C +GDAC0_DNS_GAIN2 = 0x1910 +GDAC0_DNS_OFFSET2 = 0x1914 +GDAC0_DNS_GAIN3 = 0x1918 +GDAC0_DNS_OFFSET3 = 0x191C +GDAC0_DNS_GAIN_CTRL1 = 0x1920 +GDAC0_DNS_GAIN_CTRL2 = 0x1924 +GDAC0_DNS_GAIN_CTRL_OFFST = 0x1928 +# =============== +# ===== GDAC0_CTRL +# =============== +GDAC0_CTRL_GS_CFG1 = 0x1980 +GDAC0_CTRL_GS_CFG2 = 0x1984 +GDAC0_CTRL_IIR_STAT = 0x1988 +GDAC0_CTRL_THRS_DET_CFG1 = 0x198C +GDAC0_CTRL_BQ1_B0 = 0x1990 +GDAC0_CTRL_BQ1_B1 = 0x1994 +GDAC0_CTRL_BQ1_B2 = 0x1998 +GDAC0_CTRL_BQ1_A1N = 0x199C +GDAC0_CTRL_BQ1_A2N = 0x19A0 +GDAC0_CTRL_BQ2_B0 = 0x19A4 +GDAC0_CTRL_BQ2_B1 = 0x19A8 +GDAC0_CTRL_BQ2_B2 = 0x19AC +GDAC0_CTRL_BQ2_A1N = 0x19B0 +GDAC0_CTRL_BQ2_A2N = 0x19B4 +GDAC0_CTRL_BQ3_B0 = 0x19B8 +GDAC0_CTRL_BQ3_B1 = 0x19BC +GDAC0_CTRL_BQ3_B2 = 0x19C0 +GDAC0_CTRL_BQ3_A1N = 0x19C4 +GDAC0_CTRL_BQ3_A2N = 0x19C8 +GDAC0_CTRL_BQ4_B0 = 0x19CC +GDAC0_CTRL_BQ4_B1 = 0x19D0 +GDAC0_CTRL_BQ4_B2 = 0x19D4 +GDAC0_CTRL_BQ4_A1N = 0x19D8 +GDAC0_CTRL_BQ4_A2N = 0x19DC +GDAC0_CTRL_BQ5_B0 = 0x19E0 +GDAC0_CTRL_BQ5_B1 = 0x19E4 +GDAC0_CTRL_BQ5_B2 = 0x19E8 +GDAC0_CTRL_BQ5_A1N = 0x19Ec +GDAC0_CTRL_BQ5_A2N = 0x19F0 +GDAC0_CTRL_THRS_DET_CFG2 = 0x19F4 +# =============== +# ===== GDAC1_DNS +# =============== +GDAC1_DNS_CFG1 = 0x1A00 +GDAC1_DNS_CFG2 = 0x1A04 +GDAC1_DNS_CFG5 = 0x1A10 +GDAC1_DNS_CFG6 = 0x1A14 +GDAC1_DNS_STAT = 0x1A18 +GDAC1_DNS_DAT = 0x1A1C +GDAC1_DNS_BQ1_B0 = 0x1A40 +GDAC1_DNS_BQ1_B1 = 0x1A44 +GDAC1_DNS_BQ1_B2 = 0x1A48 +GDAC1_DNS_BQ1_A1N = 0x1A4C +GDAC1_DNS_BQ1_A2N = 0x1A50 +GDAC1_DNS_BQ2_B0 = 0x1A54 +GDAC1_DNS_BQ2_B1 = 0x1A58 +GDAC1_DNS_BQ2_B2 = 0x1A5C +GDAC1_DNS_BQ2_A1N = 0x1A60 +GDAC1_DNS_BQ2_A2N = 0x1A64 +GDAC1_DNS_BQ3_B0 = 0x1A68 +GDAC1_DNS_BQ3_B1 = 0x1A6C +GDAC1_DNS_BQ3_B2 = 0x1A70 +GDAC1_DNS_BQ3_A1N = 0x1A74 +GDAC1_DNS_BQ3_A2N = 0x1A78 +GDAC1_DNS_BQ4_B0 = 0x1A7C +GDAC1_DNS_BQ4_B1 = 0x1A80 +GDAC1_DNS_BQ4_B2 = 0x1A84 +GDAC1_DNS_BQ4_A1N = 0x1A88 +GDAC1_DNS_BQ4_A2N = 0x1A8C +GDAC1_DNS_BQ5_B0 = 0x1A90 +GDAC1_DNS_BQ5_B1 = 0x1A94 +GDAC1_DNS_BQ5_B2 = 0x1A98 +GDAC1_DNS_BQ5_A1N = 0x1A9C +GDAC1_DNS_BQ5_A2N = 0x1AA0 +GDAC1_DNS_BQ6_B0 = 0x1AA4 +GDAC1_DNS_BQ6_B1 = 0x1AA8 +GDAC1_DNS_BQ6_B2 = 0x1AAC +GDAC1_DNS_BQ6_A1N = 0x1AB0 +GDAC1_DNS_BQ6_A2N = 0x1AB4 +GDAC1_DNS_BQ7_B0 = 0x1AB8 +GDAC1_DNS_BQ7_B1 = 0x1ABC +GDAC1_DNS_BQ7_B2 = 0x1AC0 +GDAC1_DNS_BQ7_A1N = 0x1AC4 +GDAC1_DNS_BQ7_A2N = 0x1AC8 +GDAC1_DNS_BQ8_B0 = 0x1ACC +GDAC1_DNS_BQ8_B1 = 0x1AD0 +GDAC1_DNS_BQ8_B2 = 0x1AD4 +GDAC1_DNS_BQ8_A1N = 0x1AD8 +GDAC1_DNS_BQ8_A2N = 0x1ADC +GDAC1_DNS_BQ9_B0 = 0x1AE0 +GDAC1_DNS_BQ9_B1 = 0x1AE4 +GDAC1_DNS_BQ9_B2 = 0x1AE8 +GDAC1_DNS_BQ9_A1N = 0x1AEC +GDAC1_DNS_BQ9_A2N = 0x1AF0 +GDAC1_DNS_BQ10_B0 = 0x1AF4 +GDAC1_DNS_BQ10_B1 = 0x1AF8 +GDAC1_DNS_BQ10_B2 = 0x1AFC +GDAC1_DNS_BQ10_A1N = 0x1B00 +GDAC1_DNS_BQ10_A2N = 0x1B04 +GDAC1_DNS_GAIN1 = 0x1B08 +GDAC1_DNS_OFFSET1 = 0x1B0C +GDAC1_DNS_GAIN2 = 0x1B10 +GDAC1_DNS_OFFSET2 = 0x1B14 +GDAC1_DNS_GAIN3 = 0x1B18 +GDAC1_DNS_OFFSET3 = 0x1B1C +GDAC1_DNS_GAIN_CTRL1 = 0x1B20 +GDAC1_DNS_GAIN_CTRL2 = 0x1B24 +GDAC1_DNS_GAIN_CTRL_OFFST = 0x1B28 +# =============== +# ===== GDAC1_CTRL +# =============== +GDAC1_CTRL_GS_CFG1 = 0x1B80 +GDAC1_CTRL_GS_CFG2 = 0x1B84 +GDAC1_CTRL_IIR_STAT = 0x1B88 +GDAC1_CTRL_THRS_DET_CFG1 = 0x1B8C +GDAC1_CTRL_BQ1_B0 = 0x1B90 +GDAC1_CTRL_BQ1_B1 = 0x1B94 +GDAC1_CTRL_BQ1_B2 = 0x1B98 +GDAC1_CTRL_BQ1_A1N = 0x1B9C +GDAC1_CTRL_BQ1_A2N = 0x1BA0 +GDAC1_CTRL_BQ2_B0 = 0x1BA4 +GDAC1_CTRL_BQ2_B1 = 0x1BA8 +GDAC1_CTRL_BQ2_B2 = 0x1BAC +GDAC1_CTRL_BQ2_A1N = 0x1BB0 +GDAC1_CTRL_BQ2_A2N = 0x1BB4 +GDAC1_CTRL_BQ3_B0 = 0x1BB8 +GDAC1_CTRL_BQ3_B1 = 0x1BBC +GDAC1_CTRL_BQ3_B2 = 0x1BC0 +GDAC1_CTRL_BQ3_A1N = 0x1BC4 +GDAC1_CTRL_BQ3_A2N = 0x1BC8 +GDAC1_CTRL_BQ4_B0 = 0x1BCC +GDAC1_CTRL_BQ4_B1 = 0x1BD0 +GDAC1_CTRL_BQ4_B2 = 0x1BD4 +GDAC1_CTRL_BQ4_A1N = 0x1BD8 +GDAC1_CTRL_BQ4_A2N = 0x1BDC +GDAC1_CTRL_BQ5_B0 = 0x1BD0 +GDAC1_CTRL_BQ5_B1 = 0x1BE4 +GDAC1_CTRL_BQ5_B2 = 0x1BE8 +GDAC1_CTRL_BQ5_A1N = 0x1BEc +GDAC1_CTRL_BQ5_A2N = 0x1BE0 +GDAC1_CTRL_THRS_DET_CFG2 = 0x1BF4 diff --git a/Tests/TC55B01/TC_test.py b/Tests/TC55B01/TC_test.py new file mode 100644 index 0000000..ac78eb3 --- /dev/null +++ b/Tests/TC55B01/TC_test.py @@ -0,0 +1,120 @@ +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC_functionality_test" +TEST_NAME = "TC_test" + +## Defines +#boot file path for the initialization of UartDeviceTC(): +TC55B01_BOOT_FILE = r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\classd_boot_166.bin" + +#call the init.py module: +import math +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_regs.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\TC55b_defs.py") +################################################################################################## + + + + + +def Temp_Sense(tc): + # Driver.WriteRegister(atc3, 0x128, 0x13131) + # tc.write_register('128', '13131') + tc.write_register('128', '0f0f1') + # Driver.WriteRegister(atc3, 0x13C, 0x40488841) + tc.write_register('13c', '40488841') + # Driver.WriteRegister(atc3, 0x144, 0x5A10800) + tc.write_register('144', '5a10800') + + # Driver.WriteRegister(atc3, 0x4, 0x1002F00) + tc.write_register('0004', '1002f00') + # Driver.WriteRegister(atc3, 0x0, 0x1018) + tc.write_register('0000', '1018') + # ModifyRegister(SCU_CLK_DIV1, 0x100, 0x100) + tc.tc_setbits('000c', '100') + # ModifyRegister(SCU_CLK_DIV6, 0x12500000, 0xFFF00000) + tc.tc_setbits('0058', '12500000') + tc.tc_clrbits('0058', 'eda00000') + # ModifyRegister(SCU_CLK_PMOD, 0x08000000, 0x08000000) + tc.tc_setbits('20', '08000000') + # Driver.WriteRegister(atc3, TEMP_SENSE_CFG1, 0x00000000) + tc.write_register('0ec0', '0') + # Driver.WriteRegister(atc3, TEMP_SENSE_CFG1, 0x37) + tc.write_register('0ec0', '37') + + time.sleep(4) + + # Driver.WriteRegister(atc3, 0x0EC4, 0xFFF) + tc.write_register('0ec4', 'fff') + # Driver.WriteRegister(atc3, 0x0EC4, 0x0) + tc.write_register('0ec4', '0') + # Driver.WriteRegister(atc3, 0x0EC4, 0x80000000) + tc.write_register('0ec4', '80000000') + time.sleep(4) + RegVal1 = tc.read_register('ec4') + print "regVal1: %s" %RegVal1 + + # Driver.WriteRegister(atc3, 0x144, 0x5A90800) + tc.write_register('144', '5a90800') + time.sleep(4) + # Driver.WriteRegister(atc3, 0x0EC4, 0xFFF) + tc.write_register('0ec4', 'fff') + # Driver.WriteRegister(atc3, 0x0EC4, 0x0) + tc.write_register('0ec4', '0') + # Driver.WriteRegister(atc3, 0x0EC4, 0x80000000) + tc.write_register('0ec4', '80000000') + time.sleep(4) + RegVal2 = tc.read_register('ec4') + + print "regVal2: %s" % RegVal2 + + vbe1 = 1.8 * int(RegVal1, 16) / 32764 + vbe2 = 1.8 * int(RegVal2, 16) / 32764 + print "\n vbe1 " + str(vbe1) + print "\n vbe2 " + str(vbe2) + q = 1.6E-19 + k = 1.38E-23 + N = 4000 + offset = 0.0038 + temp = (vbe2 - vbe1 - offset) * q / (k * math.log(N)) - 273 + print "\n Measured Temperature:" + str(temp) + + + +def vt_adc(tc): + ## config PLL: + tc.write_register('4', '1002f00') + tc.write_register('0', '1017') + tc.tc_modify_register(SCU_CLK_DIV1, '100', '100') + + ## config i2s0 to master, 16bit word: + tc.write_register(SCU_I2S_CFG, '17cf') + + tc.tc_modify_register(SCU_IOIE, '00', '80') + tc.write_register('015c', 'ff00010c') + tc.write_register(AFE_INAMP_CFG,0x00103434) + tc.write_register(VT_CTL_CFG2,0x80000000) + tc.write_register(VT_CTL_CFG3,0xc0000000) + tc.write_register(VT_CTL_CFG4,0xc0000000) + tc.write_register(VT_CTL_CFG5,0x0024007c) + tc.write_register(VT_CTL_CFG1,0x800000bf) + tc.write_register(SCU_CLK_DIV5,0x00470047) + tc.tc_modify_register(SCU_CLK_DIV7,0x0b00300,0xfff00000) + tc.tc_modify_register(SCU_TEST_CTL1,0x02010000,0x02010000) + tc.write_register(AFE_BGREF_CFG,0x000f0f1) + + #enable GDAC_MOD_CLK: + tc.tc_modify_register(SCU_CLK_PMOD,0x10000000,0x10000000) + + tc.write_register(AFE_INAMP_CFG,0x010b434) + tc.write_register(AFE_ADC_CFG,0x8cc9080e) + + #enable I2S0_CLK, VT_CLK, ADC_CLK: + tc.tc_modify_register(SCU_CLK_PMOD,0x10011000,0x10011000) + + tc.write_register(0x12c,0x8) + +tc = Uar\tDeviceTC(name="TC", com="COM4", baudrate=115200, parity='E', stopbits=1, boot_file=TC55B01_BOOT_FILE) +# Temp_Sense(tc) +vt_adc(tc) diff --git a/Tests/TC55B01/classd_boot_166.bin b/Tests/TC55B01/classd_boot_166.bin new file mode 100644 index 0000000000000000000000000000000000000000..c7858a4fe801afc63e990dd9094d9af87eef4347 GIT binary patch literal 64978 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 literal 0 HcmV?d00001 diff --git a/Tests/TC55B01/classd_boot_166_no_last_4_bytes.bin b/Tests/TC55B01/classd_boot_166_no_last_4_bytes.bin new file mode 100644 index 0000000000000000000000000000000000000000..7b8b6eeb9531b7210d49fb68c004fe2ea8801e5d GIT binary patch literal 64976 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 literal 0 HcmV?d00001 From 3447b63a6cf68fa0976957da00d5c04bdc445ebe Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Mon, 19 Jun 2017 10:18:06 +0300 Subject: [PATCH 17/26] class RaspberryPi added opens an ssh connection between pc and raspberrypi, enables us to control the RPI from the pc --- devices.py | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/devices.py b/devices.py index d81ffdb..1eb2d33 100644 --- a/devices.py +++ b/devices.py @@ -698,4 +698,52 @@ def read_version(self): input = input.replace(chr(0), '').replace(' ','').rstrip('\r') if input != 'Unknowncommand': flag = 1 - return input \ No newline at end of file + return input + + +class RaspberryPi(): + def __init__(self, ip_address, user_name, user_password ): + self.ip_address = ip_address + self.user_name = user_name + self.user_password = user_password + # open an ssh connection: + self.ssh = paramiko.SSHClient() + self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + self.ssh.connect(self.ip_address, username=self.user_name, password=self.user_password, allow_agent=False) + # open a channel: + self.channel = self.ssh.invoke_shell() + self.channel.settimeout(3) + # check connection: + time.sleep(0.5) + self.read() + check = self.send("echo check") + if check != "check\r\n": + write_to_log("Error: failed to open an ssh conncetion with the RaspberryPi") + self.close + + + def send(self, command): + '''send command to the RaspberryPi's terminal, and returns the answer''' + self.channel.sendall(command + '\n') + time.sleep(0.1) + while (not self.channel.recv_ready()): + pass + self.channel.recv(len(command+'\n')+1) #ignore the echo of the command itself + return self.read() + + def read(self): + '''reads the answer from the RaspberryPi's terminal''' + if (not self.channel.recv_ready()): + return + answer = self.channel.recv(8192) + while (self.channel.recv_ready()): + answer += self.channel.recv(8192) + answer = answer.rsplit("{}@raspberry".format(self.user_name))[0] + return answer + + def close(self): + '''close connection with the RaspberryPi''' + self.channel.close() + self.ssh.close() + + From 4a6f5463d85b758d9b2d36bfdee64cd6fd96f561 Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Mon, 19 Jun 2017 17:52:29 +0300 Subject: [PATCH 18/26] class RaspberryPi- updated added functions for write_register and read_register from the D2 and A7 --- devices.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/devices.py b/devices.py index 1eb2d33..fbc22ed 100644 --- a/devices.py +++ b/devices.py @@ -720,7 +720,13 @@ def __init__(self, ip_address, user_name, user_password ): if check != "check\r\n": write_to_log("Error: failed to open an ssh conncetion with the RaspberryPi") self.close - + # go to DBMA7_valab directory + self.send("cd ../DBMA7_valab") + # reset d2 and a7, init d2: + self.send("sudo python host_valab.py atc3 reset") + self.send("sudo python host_valab.py d2 reset") + self.send("sudo python host_valab.py init_d2") + time.sleep(1) def send(self, command): '''send command to the RaspberryPi's terminal, and returns the answer''' @@ -734,13 +740,31 @@ def send(self, command): def read(self): '''reads the answer from the RaspberryPi's terminal''' if (not self.channel.recv_ready()): - return + time.sleep(1) + if (not self.channel.recv_ready()): + return answer = self.channel.recv(8192) while (self.channel.recv_ready()): answer += self.channel.recv(8192) answer = answer.rsplit("{}@raspberry".format(self.user_name))[0] return answer + def read_register_D2(self, address): + answer = RPI.send("sudo python host_valab.py d2 r {}".format(address)) + answer = answer.split("value: ")[1].lstrip("0x").rstrip('\r\n') + return answer + + def write_register_D2(self, address, value): + RPI.send("sudo python host_valab.py d2 w {} {}".format(address, value)) + + def read_register_A7(self, address): + answer = RPI.send("sudo python host_valab.py atc3 r {}".format(address)) + answer = answer.split("value: ")[1].lstrip("0x").rstrip('\r\n') + return answer + + def write_register_A7(self, address, value): + RPI.send("sudo python host_valab.py atc3 w {} {}".format(address, value)) + def close(self): '''close connection with the RaspberryPi''' self.channel.close() From 7d9682ec759419f2cf52e5e49bd195b4ca86d04f Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Tue, 20 Jun 2017 14:42:52 +0300 Subject: [PATCH 19/26] RaspberryPi - send() updated --- devices.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/devices.py b/devices.py index fbc22ed..b4d0cb0 100644 --- a/devices.py +++ b/devices.py @@ -729,6 +729,8 @@ def __init__(self, ip_address, user_name, user_password ): time.sleep(1) def send(self, command): + while (self.channel.recv_ready()): + self.channel.recv(8192) '''send command to the RaspberryPi's terminal, and returns the answer''' self.channel.sendall(command + '\n') time.sleep(0.1) From bbe044a47c73f8a08f3d3126da62eb2073b95c2b Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Tue, 20 Jun 2017 16:26:36 +0300 Subject: [PATCH 20/26] dbma7- example of RaspberyPi class --- Tests/DBMA7/dbma7_ssh.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 Tests/DBMA7/dbma7_ssh.py diff --git a/Tests/DBMA7/dbma7_ssh.py b/Tests/DBMA7/dbma7_ssh.py new file mode 100644 index 0000000..489e5ac --- /dev/null +++ b/Tests/DBMA7/dbma7_ssh.py @@ -0,0 +1,29 @@ +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMA7." +TEST_NAME = "dbmA7_ssh" + +## Defines +#boot file path for the initialization of UartDeviceTC(): +TC55B01_BOOT_FILE = r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\TC55B01\classd_boot_166.bin" +dbma7_boot_file = r"t:\art\TCIII\script\ram_boot.bin" + +#call the init.py module: +import paramiko +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") + + +################################################################################################## +rpi_address = "172.19.66.17" +rpi_username = "pi" +rpi_password = "Validation23" + + +RPI = RaspberryPi(rpi_address, rpi_username, rpi_password) +# print RPI.send("sudo python host_valab.py atc3 r 0x0") + +print RPI.read_register_A7('0x0') +RPI.write_register_A7('0x0', '0x0004') +print RPI.read_register_A7('0x0') + +RPI.close() \ No newline at end of file From 8d508a4e55e33b305b69f732da92bdabd281a535 Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Thu, 22 Jun 2017 15:33:06 +0300 Subject: [PATCH 21/26] RaspberryPi: updated read() function --- devices.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/devices.py b/devices.py index b4d0cb0..2f6ade0 100644 --- a/devices.py +++ b/devices.py @@ -729,9 +729,11 @@ def __init__(self, ip_address, user_name, user_password ): time.sleep(1) def send(self, command): - while (self.channel.recv_ready()): - self.channel.recv(8192) '''send command to the RaspberryPi's terminal, and returns the answer''' + # while (self.channel.recv_ready()): + # self.channel.recv(8192) + while (not self.channel.send_ready()): + pass self.channel.sendall(command + '\n') time.sleep(0.1) while (not self.channel.recv_ready()): @@ -739,7 +741,7 @@ def send(self, command): self.channel.recv(len(command+'\n')+1) #ignore the echo of the command itself return self.read() - def read(self): + def read_old(self): '''reads the answer from the RaspberryPi's terminal''' if (not self.channel.recv_ready()): time.sleep(1) @@ -748,9 +750,22 @@ def read(self): answer = self.channel.recv(8192) while (self.channel.recv_ready()): answer += self.channel.recv(8192) + # answer = answer.rsplit("{}@raspberry".format(self.user_name))[0] + return answer + + def read(self): + '''reads the answer from the RaspberryPi's terminal''' + if (not self.channel.recv_ready()): + time.sleep(1) + if (not self.channel.recv_ready()): + return + answer = self.channel.recv(8192) + while (not "{}@raspberry".format(self.user_name) in answer): + answer += self.channel.recv(8192) answer = answer.rsplit("{}@raspberry".format(self.user_name))[0] return answer + def read_register_D2(self, address): answer = RPI.send("sudo python host_valab.py d2 r {}".format(address)) answer = answer.split("value: ")[1].lstrip("0x").rstrip('\r\n') From 7991f15f19a981783b6298c3d25cc4819acecd06 Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Sun, 25 Jun 2017 10:53:43 +0300 Subject: [PATCH 22/26] updated --- Chip_Validation_Python_Manual.docx | Bin 173625 -> 173940 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Chip_Validation_Python_Manual.docx b/Chip_Validation_Python_Manual.docx index 9d2e36d593a42fbb67fedd05c9305d1a394b588c..2314ee464d2f7e73e6e14fc844055b5ad7d0850c 100644 GIT binary patch delta 22397 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 Hr<4B!uBX

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 C%0{jL From fcf7d252249450fb431c65964c843bf9f17f46e4 Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Sun, 25 Jun 2017 10:54:18 +0300 Subject: [PATCH 23/26] updated --- devices.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/devices.py b/devices.py index 2f6ade0..3a93c39 100644 --- a/devices.py +++ b/devices.py @@ -722,11 +722,7 @@ def __init__(self, ip_address, user_name, user_password ): self.close # go to DBMA7_valab directory self.send("cd ../DBMA7_valab") - # reset d2 and a7, init d2: - self.send("sudo python host_valab.py atc3 reset") - self.send("sudo python host_valab.py d2 reset") - self.send("sudo python host_valab.py init_d2") - time.sleep(1) + def send(self, command): '''send command to the RaspberryPi's terminal, and returns the answer''' @@ -765,6 +761,15 @@ def read(self): answer = answer.rsplit("{}@raspberry".format(self.user_name))[0] return answer + def reset_A7(self): + self.send("sudo python host_valab.py atc3 reset") + + def reset_D2(self): + self.send("sudo python host_valab.py d2 reset") + + def init_D2(self): + self.send("sudo python host_valab.py init_d2") + time.sleep(1) def read_register_D2(self, address): answer = RPI.send("sudo python host_valab.py d2 r {}".format(address)) @@ -782,6 +787,7 @@ def read_register_A7(self, address): def write_register_A7(self, address, value): RPI.send("sudo python host_valab.py atc3 w {} {}".format(address, value)) + def close(self): '''close connection with the RaspberryPi''' self.channel.close() From e068adf8eef4695569fef1b5cd66c318af5f86cd Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Sun, 25 Jun 2017 11:21:35 +0300 Subject: [PATCH 24/26] DBMA7 test template --- Tests/DBMA7/DBMA7_test_template.py | 41 ++++++++++++++++++++++++++++++ Tests/DBMA7/dbma7_ssh.py | 6 ++++- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 Tests/DBMA7/DBMA7_test_template.py diff --git a/Tests/DBMA7/DBMA7_test_template.py b/Tests/DBMA7/DBMA7_test_template.py new file mode 100644 index 0000000..8e85be9 --- /dev/null +++ b/Tests/DBMA7/DBMA7_test_template.py @@ -0,0 +1,41 @@ +## Test ID: +USER_NAME = 'Bar' +FOLDER_PATH = r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\DBMA7." +TEST_NAME = "test_template" + +## Defines +rpi_address = "172.19.66.17" +rpi_username = "pi" +rpi_password = "pi" +apx_project_path = r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\apx500_functionality_test\SNR_test2.approjx" +apx_results_path = r"C:\Users\bar.kristal\Documents\GitHub\Python\apx500_functionality_test\full_sequence" + +#call the init.py module: +import paramiko +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\init.py") +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\apx525_functions.py") + +################################################################################################## +## test start: + +#initial RPI connection +RPI = RaspberryPi(rpi_address, rpi_username, rpi_password) +#reset both D2 and A7 +RPI.reset_A7() +RPI.reset_D2() +RPI.init_D2() + +#call FW functions (configuration and set-ups that written in the RPI's python code): +print RPI.send("sudo python host_valab.py det_internal") + +#read and write to registers +print RPI.read_register_A7('0x0') +RPI.write_register_A7('0x0', '0x0004') +print RPI.read_register_A7('0x0') + +#run measurements with AudioPrecision, result saved at apx_results_path +SequenceMode_full_sequence_from_project(apx_project_path, apx_results_path) + +#close connection with RPI: +RPI.close() + diff --git a/Tests/DBMA7/dbma7_ssh.py b/Tests/DBMA7/dbma7_ssh.py index 489e5ac..6964d3a 100644 --- a/Tests/DBMA7/dbma7_ssh.py +++ b/Tests/DBMA7/dbma7_ssh.py @@ -20,10 +20,14 @@ RPI = RaspberryPi(rpi_address, rpi_username, rpi_password) -# print RPI.send("sudo python host_valab.py atc3 r 0x0") + print RPI.read_register_A7('0x0') RPI.write_register_A7('0x0', '0x0004') print RPI.read_register_A7('0x0') +print RPI.send("sudo python host_valab.py det_internal") +print RPI.send("sudo python host_valab.py atc3 reset") +print RPI.send("sudo python host_valab.py det_internal") + RPI.close() \ No newline at end of file From a510d678d00e38266a9df44047db186a1c31f412 Mon Sep 17 00:00:00 2001 From: Bar Kristal Date: Sun, 25 Jun 2017 11:25:51 +0300 Subject: [PATCH 25/26] Audio Precision module for automation --- apx525_functions.py | 326 ++++++++++++++++++++++++++++++++++++++++++++ apx525_module.py | 40 ++++++ 2 files changed, 366 insertions(+) create mode 100644 apx525_functions.py create mode 100644 apx525_module.py diff --git a/apx525_functions.py b/apx525_functions.py new file mode 100644 index 0000000..d0d068d --- /dev/null +++ b/apx525_functions.py @@ -0,0 +1,326 @@ +execfile(r"C:\Users\bar.kristal\Documents\GitHub\Python\apx525_module.py") + +import matplotlib.pyplot as plt +import threading + + + +################################################################ +### some examples: +## initialize APx500 +# APx = APx500_Application(APxOperatingMode.BenchMode, True) +# APx.Visible = True + + +### running an APx project: +# filename = 'Electrical_Test_Setup_APX_100mV_0dB.approjx' +# directory = "T:\Barkristal\DBMD6\DBMD6_electrical_functionality_tests\Tools" +# fullpath = os.path.join(directory, filename) +# APx.OpenProject(fullpath) + + +### BenchMode, FFT: +'''Connect the Digital Serial output to the Digital Serial input. + The test generates a sine wave from the digital serial, and show it's FFT''' +# APx.BenchMode.Setup.OutputConnector.Type = OutputConnectorType.DigitalSerial +# APx.BenchMode.Setup.InputConnector.Type = InputConnectorType.DigitalSerial +# APx.SignalPathSetup.SerialDigitalTransmitter.EnableOutputs = True +# #APx.BenchMode.Generator.Levels.SetValue(OutputChannelIndex.Ch1, 0.02) +# APx.BenchMode.Generator.Frequency.Value = 2000 +# APx.BenchMode.Generator.On = True +# fft = APx.BenchMode.Measurements.Fft +# fft.Show() +# fft.Start() +# time.sleep(2) +# xValues = fft.FFTSpectrum.GetXValues(InputChannelIndex.Ch1, VerticalAxis.Left) +# yValues = fft.FFTSpectrum.GetYValues(InputChannelIndex.Ch1, VerticalAxis.Left) +# yval = [] +# xval = [] +# for i in yValues: +# yval.append(i) +# for j in xValues: +# xval.append(j) +# plt.semilogx(xval, yval) +# plt.show() + +### BenchMode, THD: +'''Connect the Digital Serial output to the Digital Serial input. + The test generates a sine wave from the digital serial, and measure it's THD''' +# APx.BenchMode.Setup.OutputConnector.Type = OutputConnectorType.DigitalSerial +# APx.BenchMode.Setup.InputConnector.Type = InputConnectorType.DigitalSerial +# APx.SignalPathSetup.SerialDigitalTransmitter.EnableOutputs = True +# APx.BenchMode.Generator.Frequency.Value = 2000 +# APx.BenchMode.Generator.On = True +# AcousticResponse = APx.BenchMode.Measurements.AcousticResponse +# AcousticResponse.Start() #start measurements +# THD = AcousticResponse.ThdLevel +# time.sleep(2) +# xValues = THD.GetXValues(InputChannelIndex.Ch1, VerticalAxis.Left) +# yValues = THD.GetYValues(InputChannelIndex.Ch1, VerticalAxis.Left) +# yval = [] +# xval = [] +# for i in yValues: +# yval.append(i) +# for j in xValues: +# xval.append(j) +# plt.semilogx(xval,yval) +# plt.show() + + + +### BenchMode, THD, load project: +'''Connect the Digital Serial output to the Digital Serial input. + The test generates a sine wave from the digital serial, and measure it's THD''' +# APx.OpenProject(r"C:\Users\bar.kristal\Documents\GitHub\Python\Tests\apx500_functionality_test\THD_test.approjx") +# AcousticResponse = APx.BenchMode.Measurements.AcousticResponse +# AcousticResponse.Start() #start measurements +# THD = AcousticResponse.ThdLevel +# time.sleep(2) +# xValues = THD.GetXValues(InputChannelIndex.Ch1, VerticalAxis.Left) +# yValues = THD.GetYValues(InputChannelIndex.Ch1, VerticalAxis.Left) +# yval = [] +# xval = [] +# for i in yValues: +# yval.append(i) +# for j in xValues: +# xval.append(j) +# plt.semilogx(xval,yval) +# plt.show() + + + +### SequenceMode, SNR, load project: +def SequenceMode_SNR_from_project(project_path): + '''This function loads a specified project, and returns the SNR results. + Results are in the following form: list results, str units. The length of the results list + is dependent on the number of channels that turned on in the project. + The project need to be in Sequence mode''' + APx = APx500_Application() + APx.Visible = True + APx.OpenProject(project_path) + SNR = APx.Sequence.GetMeasurement("Signal Path1", "Signal to Noise Ratio") + SNR.Checked = True + SNR.Run() + show_fft(APx) # save a figure of the FFT + if SNR.HasSequenceResults: + readingValues = SNR.SequenceResults[MeasurementResultType.SignalToNoiseRatioMeter].GetMeterValues() + units = SNR.SequenceResults[MeasurementResultType.SignalToNoiseRatioMeter].MeterUnit + + results = [] + for i in range(len(readingValues)): + results.append(readingValues[i]) + return results, units + + + +def SequenceMode_THDN_Ratio_from_project(project_path): + '''This function loads a specified project, and returns the THD+N results. + Results are in the following form: list results, str units. The length of the results list + is dependent on the number of channels that turned on in the project. + The project need to be in Sequence mode''' + APx = APx500_Application() + APx.Visible = True + APx.OpenProject(project_path) + THD_N = APx.Sequence.GetMeasurement("Signal Path1", "THD+N") + THD_N.Checked = True + THD_N.Run() #run the measurement + show_fft(APx) # save a figure of the FFT + if THD_N.HasSequenceResults: + readingValues = THD_N.SequenceResults[MeasurementResultType.ThdNRatioMeter].GetMeterValues() + units = THD_N.SequenceResults[MeasurementResultType.ThdNRatioMeter].MeterUnit + results = [] + for i in range(len(readingValues)): + results.append(readingValues[i]) + + return results, units + + + +def SequenceMode_THD_from_project(project_path): + '''This function loads a specified project, and returns the THD results. + Results are in the following form: list results, str units. The length of the results list + is dependent on the number of channels that turned on in the project. + The project need to be in Sequence mode''' + APx = APx500_Application() + APx.Visible = True + APx.OpenProject(project_path) + THD = APx.Sequence.GetMeasurement("Signal Path1", "THD+N") + THD.Checked = True + THD.Run() #run the measurement + show_fft(APx) # save a figure of the FFT + if THD.HasSequenceResults: + readingValues = THD.SequenceResults[MeasurementResultType.ThdRatioMeter].GetMeterValues() + units = THD.SequenceResults[MeasurementResultType.ThdRatioMeter].MeterUnit + results = [] + for i in range(len(readingValues)): + results.append(readingValues[i]) + + return results, units + + +def SequenceMode_SINAD_from_project(project_path): + '''This function loads a specified project, and returns the SINAD results. + Results are in the following form: list results, str units. The length of the results list + is dependent on the number of channels that turned on in the project. + The project need to be in Sequence mode''' + APx = APx500_Application() + APx.Visible = True + APx.OpenProject(project_path) + SINAD = APx.Sequence.GetMeasurement("Signal Path1", "SINAD") + SINAD.Checked = True + SINAD.Run() #run the measurement + time.sleep(4) + show_fft(APx) #save a figure of the FFT + if SINAD.HasSequenceResults: + readingValues = SINAD.SequenceResults[MeasurementResultType.SinadRatioMeter].GetMeterValues() + units = SINAD.SequenceResults[MeasurementResultType.SinadRatioMeter].MeterUnit + results = [] + for i in range(len(readingValues)): + results.append(readingValues[i]) + + return results, units + + +def SequenceMode_NoiseLevel_from_project(project_path): + '''This function loads a specified project, and returns the Noise level results. + Results are in the following form: list results, str units. The length of the results list + is dependent on the number of channels that turned on in the project. + The project need to be in Sequence mode''' + APx = APx500_Application() + APx.Visible = True + APx.OpenProject(project_path) + Noise = APx.Sequence.GetMeasurement("Signal Path1", "Noise (RMS)") + Noise.Checked = True + Noise.Run() #run the measurement + show_fft(APx) # save a figure of the FFT + if Noise.HasSequenceResults: + readingValues = Noise.SequenceResults[MeasurementResultType.NoiseRmsLevelMeter].GetMeterValues() + units = Noise.SequenceResults[MeasurementResultType.NoiseRmsLevelMeter].MeterUnit + results = [] + for i in range(len(readingValues)): + results.append(readingValues[i]) + + return results, units + +def SequenceMode_CMRR_from_project(project_path): + '''This function loads a specified project, and returns the CMRR results. + Results are in the following form: list results, str units. The length of the results list + is dependent on the number of channels that turned on in the project. + The project need to be in Sequence mode''' + APx = APx500_Application() + APx.Visible = True + APx.OpenProject(project_path) + CMRR = APx.Sequence.GetMeasurement("Signal Path1", "CMRR") + CMRR.Checked = True + CMRR.Run() #run the measurement + show_fft(APx) # save a figure of the FFT + if CMRR.HasSequenceResults: + readingValues = CMRR.SequenceResults[MeasurementResultType.CmrrMeter].GetMeterValues() + units = CMRR.SequenceResults[MeasurementResultType.CmrrMeter].MeterUnit + results = [] + for i in range(len(readingValues)): + results.append(readingValues[i]) + + return results, units + + + +def SequenceMode_frequency_response_from_project(project_path): + '''This function loads a specified project, and returns the frequency response results. + Results are in the following form: list results, str units. The length of the results list + is dependent on the number of channels that turned on in the project. + The project need to be in Sequence mode''' + APx = APx500_Application() + APx.Visible = True + APx.OpenProject(project_path) + APx.FrequencyResponse.Start() + level = APx.FrequencyResponse.Level + data = level.GetValues(0, APx.FrequencyResponse.Level.AcquisitionCount - 1) + xval = [] + yval = [] + for i in range(len(data)): + # print "point %s: (%s %s,%s %s)"%(i, data[i].X, level.XAxis.Unit, data[i].Y, level.YAxis.Unit) + xval.append(data[i].X) + yval.append(data[i].Y) + + graph_path = DIR_NAME + r"\\" + TEST_NAME + r"_" + "frequency_response" + TEST_DATE + r"_" + TEST_TIME + r".png" + plt.plot(xval, yval) + # plt.show() + plt.savefig(graph_path) + return graph_path + + +def SequenceMode_full_sequence_from_project(project_path, results_path): + '''This function loads a project that runs a sequence of measurments, + sets the path and name for the results_file to be saved, + and runs the sequence.''' + + APx = APx500_Application() + APx.Visible = True + APx.OpenProject(project_path) + SequenceMode_change_log_path(APx, results_path) + APx.Sequence.Run() + + + + +def SequenceMode_change_log_path(APx, log_path): + ''' + :param APx: instance ot the APx_Application() class + log_path: path for the results csv file to be saved + for example: log_path = "c:\DBMA7\SNR", than the results_file will be saved at: "c:\DBMA7\SNR\date&time.csv" + :return: none + ''' + path = log_path+"$(Date)$(Time).csv" + try: + APx.Sequence.DataOutput.MeterReadingsFileName = path + except: + raise "path is not valid" + + +def show_scope(APx): + scope_path = DIR_NAME + r"\\" + TEST_NAME + r"_" + "scope_figure" + TEST_DATE + r"_" + TEST_TIME + r".png" + + scope = APx.ScopeSignalMonitor.Scope + yValues = scope.GetYValues(InputChannelIndex.Ch1, VerticalAxis.Left) + xValues = scope.GetXValues(InputChannelIndex.Ch1, VerticalAxis.Left) + + yval = [] + xval = [] + for i in yValues: + yval.append(i) + for j in xValues: + xval.append(j) + plt.plot(xval, yval) + #plt.show() + plt.savefig(scope_path) + + +def show_fft(APx): + fft_path = DIR_NAME + r"\\" + TEST_NAME + r"_" + "fft_figure" + TEST_DATE + r"_" + TEST_TIME + r".png" + + fft = APx.FftSpectrumSignalMonitor + fft.FFTLength = FFTLength.FFT_48000 + xValues = fft.FFTSpectrum.GetXValues(InputChannelIndex.Ch1, VerticalAxis.Left) + yValues = fft.FFTSpectrum.GetYValues(InputChannelIndex.Ch1, VerticalAxis.Left) + yval = [] + xval = [] + for i in yValues: + yval.append(i) + for j in xValues: + xval.append(j) + plt.semilogx(xval, yval) + #plt.show() + plt.savefig(fft_path) + + +def show_scope_new_thread(APx): + thread = threading.Thread(target=show_scope, args=(APx,)) + thread.start() + + +def show_fft_new_thread(APx): + thread = threading.Thread(target=show_fft, args=(APx,)) + thread.start() + + diff --git a/apx525_module.py b/apx525_module.py new file mode 100644 index 0000000..b5b7a7b --- /dev/null +++ b/apx525_module.py @@ -0,0 +1,40 @@ +import sys +sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\Lib') # Set the path to import pure Python Libs +sys.path.append(r"C:\Program Files (x86)\Audio Precision\APx500 4.4\API") # Set the path to import the Apx API +sys.path.append(r"C:\Program Files (x86)\Audio Precision\APx500 4.4\API\Python") # Set the path to import the Apx python sampleProject + +import clr # Import the Common Language Runtime +clr.AddReference("System.Drawing") # Needed for Dialog Boxes +clr.AddReference("System.Windows.Forms") # Needed for Dialog Boxes +clr.AddReference("C:\Program Files (x86)\Audio Precision\APx500 4.4\API\AudioPrecision.API2.dll") #the path changed from APx500 4.3 to APx500 4.4 +clr.AddReference("C:\Program Files (x86)\Audio Precision\APx500 4.4\API\AudioPrecision.API.dll") + +from AudioPrecision.API import * # Import the APx API + + + +################################################################ +## some examples: + +### running an APx project: +# filename = 'Electrical_Test_Setup_APX_100mV_0dB.approjx' +# directory = "T:\Barkristal\DBMD6\DBMD6_electrical_functionality_tests\Tools" +# fullpath = os.path.join(directory, filename1) +# APx = APx500_Application(APxOperatingMode.BenchMode, True) +# APx.Visible= True +# APx.OpenProject(fullpath) + + +### configure to BenchMode: +# APx.BenchMode.Setup.OutputConnector.Type = OutputConnectorType.AnalogUnbalanced +# APx.BenchMode.Generator.Levels.SetValue(OutputChannelIndex.Ch1, 0.02) +# APx.BenchMode.Generator.Frequency.Value = 1234 +# APx.BenchMode.Generator.On = True +# fft = APx.BenchMode.Measurements.Fft +# fft.Show() +# fft.Start() +# time.sleep(1) +# xValues = fft.FFTSpectrum.GetXValues(InputChannelIndex.Ch1, VerticalAxis.Left) +# yValues = fft.FFTSpectrum.GetYValues(InputChannelIndex.Ch1) +# for i in xValues: +# print i \ No newline at end of file From 8f749cb62df70741acba9b096433bd2139e8f436 Mon Sep 17 00:00:00 2001 From: ronny2651 Date: Sun, 25 Jun 2017 15:47:40 +0300 Subject: [PATCH 26/26] added Ronny's addresses --- .gitignore | 3 ++- init.py | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 8b60424..3e659c5 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ Tests/DCX81/spi_read_fifo.cmm Tests/DCX81/spi2_slave.cmm *.xlsx Tests/apx500_functionality_test/THD_test.approjx -Tests/apx500_functionality_test/SNR_test.approjx \ No newline at end of file +Tests/apx500_functionality_test/SNR_test.approjx +Tests/DBMA7/script1.py \ No newline at end of file diff --git a/init.py b/init.py index 94a67db..2dade73 100644 --- a/init.py +++ b/init.py @@ -29,8 +29,8 @@ import openpyxl # Excel library. (this module takes long time to load, so load it only if necessary) import decimal import platform # for the Laurebach initialization -import PyTektronixScope -import saleae +# import PyTektronixScope +# import saleae @@ -83,7 +83,18 @@ SCOPE_ADDRESS = "GPIB0::9::INSTR" TERMOTRON_TCP_IP = ("172.19.5.239", 8080) # (ip, port) , (Bisset) - +elif USER_NAME == "Ronny": + execfile(r"C:\Users\ronnyi\Documents\GitHub\Python\devices.py") + execfile(r"C:\Users\ronnyi\Documents\GitHub\Python\utilities.py") + execfile(r"C:\Users\ronnyi\Documents\GitHub\Python\lab_equipment.py") + + # POWER_SUPLLY_ADDRESS = "GPIB1::29::INSTR" + # DMM_ADDRESS = "GPIB0::22::INSTR" + # FREQUENCY_COUNTER_ADDRESS = "GPIB0::27::INSTR" + # WAVE_GENERATOR_ADDRESS = "GPIB0::1::INSTR" + # ELECTRONIC_LOAD_ADDRESS = "GPIB0::3::INSTR" + # SCOPE_ADDRESS = "GPIB0::9::INSTR" + TERMOTRON_TCP_IP = ("172.19.5.240", 8080) # (ip, port) , (Ronny)