This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DS90UB960-Q1: DS90UB960-Q1 I2C Register Script for MAP Analysis

Part Number: DS90UB960-Q1
Other Parts Discussed in Thread: USB2ANY, DS90UB953-Q1

Good morning,

Is it possible to perform a MAP analysis without using the USB2ANY device and writing to the I2C registers directly? Is there a list of I2C commands available for this or even a python script available?

We're quite interested in running a MAP analysis from our own software and would like to produce either:

1. A table similar to the MAP analysis results found in SNLA301; or

2. A text file with similar parameters to those exported by the USB2ANY when a MAP analysis has been completed.

Ideally we just want to sweep across EQ and SP levels 0-14 with a dwell time of 1000ms and see how the system performs in synchronous mode when connected to a DS90UB953-Q1.

Many thanks,

Connor

  • Hi Connor,

    Yes, this is possible to run MAP without the use of USB2ANY and Analog LaunchPAD. When downloading Analog LaunchPAD, predefined example scripts will be available in the file directory, which includes a 954 Margin Analysis script. An example file path for the file location C:\Program Files (x86)\Texas Instruments\Analog LaunchPAD v1.57.0010\PreDefScripts\DS90UB954\ub954_margin_analysis_script. Please note the example script will output these results in an excel file.

    I have also attached the script here for your convenience.

    """
      Copyright 2018 Texas Instruments Incorporated. All rights reserved.
    
      IMPORTANT: Your use of this Software is limited to those specific rights
      granted under the terms of a software license agreement between the user who
      downloaded the software, his/her employer (which must be your employer) and
      Texas Instruments Incorporated (the "License"). You may not use this Software
      unless you agree to abide by the terms of the License. The License limits your
      use, and you acknowledge, that the Software may not be modified, copied or
      distributed unless embedded on a Texas Instruments microcontroller which is
      integrated into your product. Other than for the foregoing purpose, you may
      not use, reproduce, copy, prepare derivative works of, modify, distribute,
      perform, display or sell this Software and/or its documentation for any
      purpose.
    
      YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
      PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
      INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
      NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL TEXAS
      INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
      NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL
      EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT
      LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL
      DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS,
      TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT
      LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
    
      Should you have any questions regarding your right to use this Software,
      contact Texas Instruments Incorporated at www.TI.com.
    
    """
    # Name: ub954_margin_analysis.py
    # Purpose: Margin Analysis Script for DS90UB954
    # Version 0.98
    # Run from DES
    
    print "\n"
    
    import time
    import logging
    
    # Select log file name and log level(DEBUG, INFO)
    logging.basicConfig(filename='ub954sfeq_testlog.log', filemode='a', format='%(levelname)s:%(message)s',level=logging.DEBUG)
    
    # Select RX Port: RX_PORT0_954B or RX_PORT1_954B
    CONST_RXPORT = 'RX_PORT0_954B'
    
    # configure I2C device ID of the DES per IDX strap pin
    # EVM: 0x60, SVB: 0x7A, Custom Board: 0x??
    devAddr_DES = 0x60
    
    f1=open('./ub954sfeq_test.csv', 'w+')
    f1.write(",,,,,,,,SP,,,,,,,,")
    f1.write("\r")
    f1.write("EQ,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14")
    
    # default (0x83) is for port0, for port1 would need to change thie to be 0x97.
    if CONST_RXPORT == 'RX_PORT0_954B':
    	#set RX_PORT_CTL register
    	board.WriteI2C(devAddr_DES,0x0C,0x83)
    	time.sleep(0.1)
    	#set FPD3_PORT_SEL register
    	board.WriteI2C(devAddr_DES,0x4c,0x01)
    	time.sleep(0.1)
    	# choose analog register page
    	board.WriteI2C(devAddr_DES, 0xB0, 0x04)
    	time.sleep(0.1)
    elif CONST_RXPORT == 'RX_PORT1_954B':
    	#set RX_PORT_CTL register
    	board.WriteI2C(devAddr_DES, 0x0C, 0x97)
    	time.sleep(0.1)
    	#set FPD3_PORT_SEL register
    	board.WriteI2C(devAddr_DES,0x4c,0x12)
    	time.sleep(0.1)
    	# choose analog register page
    	board.WriteI2C(devAddr_DES, 0xB0, 0x08)
    	time.sleep(0.1)
    else:
    	#set RX_PORT_CTL register
    	board.WriteI2C(devAddr_DES,0x0C,0x83)
    	time.sleep(0.1)
    	#set FPD3_PORT_SEL register
    	board.WriteI2C(devAddr_DES,0x4c,0x01)
    	time.sleep(0.1)
    	# choose analog register page
    	board.WriteI2C(devAddr_DES, 0xB0, 0x04)
    	time.sleep(0.1)
    
    # choose reg_8 @ offset 8
    board.WriteI2C(devAddr_DES, 0xB1, 0x08)
    time.sleep(0.1)
    # configure AEQ_CTL register: Disable SFILTER adaption with AEQ
    board.WriteI2C(devAddr_DES, 0x42, 0x70)
    time.sleep(0.1)
    # set AEQ Bypass register: bypass AEQ, STAGE1=0, STAGE2=0, Lock Mode = 1
    board.WriteI2C(devAddr_DES, 0xD4, 0x01)
    time.sleep(0.1)
    # set Parity Error Threshold Hi Register 
    board.WriteI2C(devAddr_DES, 0x05, 0x00)
    time.sleep(0.1)
    # set Parity Error Threshold Lo Register 
    board.WriteI2C(devAddr_DES, 0x06, 0x01)
    time.sleep(0.1)
    # Enable Encoder CRC error capability
    enc_crc = board.ReadI2C(devAddr_DES, 0x4A, 0x01)
    board.WriteI2C(devAddr_DES, 0x4A, (enc_crc | 0x10))
    # Enable Encoder CRC
    enc_crc = board.ReadI2C(devAddr_DES, 0xBA, 0x01)
    board.WriteI2C(devAddr_DES, 0xBA, (enc_crc & 0x7F))
    
    logging.info('**** Begin Initial Settings ****')
    logging.info('Test lock status with sfilter changes')
    logging.info('Check RX_PORT_CTL Register (0x0C): %s', hex(board.ReadI2C(devAddr_DES, 0x0C, 1)))
    logging.info('Select PORT 0 (0x4C): %s', hex(board.ReadI2C(devAddr_DES, 0x4c)))
    logging.info('Check RX_PORT_STS1 Register (0x4D): %s', hex(board.ReadI2C(devAddr_DES, 0x4D, 1)))
    logging.info('Check Device Status Register (0x04): %s', hex(board.ReadI2C(devAddr_DES, 0x04,1)))
    logging.info('Disable sfilter adaption in AEQ_CTL register (0x42): %s', hex(board. ReadI2C(devAddr_DES, 0x42)))
    logging.info('Check AEQ_CTL2 register (0xD2): %s', hex(board.ReadI2C(devAddr_DES, 0xD2,1)))
    logging.info('Check AEQ MIN/MAX register (0xD5): %s', hex(board.ReadI2C(devAddr_DES, 0xD5,1)))
    logging.info('Check AEQ BYPASS register (0xD4): %s', hex(board.ReadI2C(devAddr_DES, 0xD4,1)))
    logging.info('reg_8 initial value: %s', hex(board.ReadI2C(devAddr_DES, 0xB2)))
    logging.info('Updated AEQ BYPASS register (0xD4): %s', hex(board.ReadI2C(devAddr_DES, 0xD4,1)))
    logging.info('**** End Initial Settings ****')
    
    # delay before lock is checked, use minimum of 0.5 when doing digital reset
    dwell_time = 0.9
    
    for y in range(0,1):
    	eq_sel2 = 0
    	#eq_sel1 is needed from 0 to 7
    	for eq_sel1 in range(0, 8, 1):
    		board.WriteI2C(devAddr_DES, 0xD4, ((eq_sel1<<5)+(eq_sel2<<1)+0x01))
    		time.sleep(0.1)
    		logging.debug('AEQ BYPASS register (0xD4): %s', hex(board.ReadI2C(devAddr_DES, 0xD4,1)))
    		time.sleep(0.1)
    		logging.info('%s', hex(eq_sel1))
    		print 'eq_sel1= ', hex(eq_sel1)
    		print 'lock status:'
    		f1.write("\r")
    		out_string = str(eq_sel1) + ","
    		f1.write(out_string)
    		ddly_ctrl = 8 #(disable 6 extra delay)
    		for cdly_ctrl in range(15, 8, -1):
    			# write reg_8
    			board.WriteI2C(devAddr_DES, 0xB2, ((ddly_ctrl<<4) + cdly_ctrl))
    			time.sleep(0.1)
    			logging.debug('**reg_8 updated value**: %s', hex(board.ReadI2C(devAddr_DES, 0xB2)))
    			# reset digital block except registers
    			board.WriteI2C(devAddr_DES, 0x01, 0x01)
    			time.sleep(dwell_time)
    			port_status1 = board.ReadI2C(devAddr_DES, 0x4D,1)
    			logging.debug('Check RX_PORT_STS1 Register (0x4D): %s', hex(port_status1))
    			time.sleep(0.1)
    			logging.debug('port lock status: %s', hex(port_status1 & 0x01))
    			time.sleep(0.1)
    			port_status2 = board.ReadI2C(devAddr_DES, 0x4E,1)
    			logging.debug('Check RX_PORT_STS2 Register (0x4E): %s', hex(port_status2))
    			time.sleep(0.1)			
    			lock_status = 0
    			lock_sum = 0
    			for loop in range(0, 10, 1):
    				port_status1 = board.ReadI2C(devAddr_DES, 0x4D, 1)
    				time.sleep(0.1)
    				port_status2 = board.ReadI2C(devAddr_DES, 0x4E, 1)
    				time.sleep(0.1)				
    				if (((port_status1 & 0x3C) == 0) and ((port_status2 & 0x20) == 0)):
    					lock_sum += int(port_status1 & 0x01)
    				else:
    					board.ReadI2C(devAddr_DES, 0x56, 1) # clear parity error
    				time.sleep(0.1)
    			lock_avg = round(float(lock_sum) / 10, 2)
    			lock_str = "%0.1f" %lock_avg
    			logging.debug('port lock status: %s', lock_str)
    			time.sleep(0.1)
    			out_string = lock_str + ","
    			f1.write(out_string)
    			print lock_str
    		logging.debug('**cdly_ctrl value at end of loop**: %s', hex(cdly_ctrl))
    		cdly_ctrl = 8 #(disable 6 extra delay)
    		for ddly_ctrl in range(8, 16, 1):
    			# write reg_8
    			board.WriteI2C(devAddr_DES, 0xB2, ((ddly_ctrl<<4) + cdly_ctrl))
    			time.sleep(0.1)
    			logging.debug('**reg_8 updated value**: %s', hex(board.ReadI2C(devAddr_DES, 0xB2)))
    			# reset digital block except registers
    			board.WriteI2C(devAddr_DES, 0x01, 0x01)
    			time.sleep(dwell_time)
    			port_status1 = board.ReadI2C(devAddr_DES, 0x4D,1)
    			logging.debug('Check RX_PORT_STS1 Register (0x4D): %s', hex(port_status1))
    			time.sleep(0.1)
    			logging.debug('port lock status: %s', hex(port_status1 & 0x01))
    			time.sleep(0.1)
    			port_status2 = board.ReadI2C(devAddr_DES, 0x4E,1)
    			logging.debug('Check RX_PORT_STS2 Register (0x4E): %s', hex(port_status2))
    			time.sleep(0.1)			
    			lock_status = 0
    			lock_sum = 0
    			for loop in range(0, 10, 1):
    				port_status1 = board.ReadI2C(devAddr_DES, 0x4D, 1)
    				time.sleep(0.1)
    				port_status2 = board.ReadI2C(devAddr_DES, 0x4E, 1)
    				time.sleep(0.1)				
    				if (((port_status1 & 0x3C) == 0) and ((port_status2 & 0x20) == 0)):
    					lock_sum += int(port_status1 & 0x01)
    				else:
    					board.ReadI2C(devAddr_DES, 0x56, 1) # clear parity error
    				time.sleep(0.1)
    			lock_avg = round(float(lock_sum) / 10, 2)
    			lock_str = "%0.1f" %lock_avg
    			logging.debug('port lock status: %s', lock_str)
    			time.sleep(0.1)
    			out_string = lock_str + ","
    			f1.write(out_string)
    			print lock_str
    	
    	eq_sel1 = 7
    	#eq_sel2 is needed only from 1 to 7
    	for eq_sel2 in range(1, 8, 1):						
    		board.WriteI2C(devAddr_DES, 0xD4, ((eq_sel1<<5)+(eq_sel2<<1)+0x01))
    		time.sleep(0.1)
    		logging.debug('AEQ BYPASS register (0xD4): %s', hex(board.ReadI2C(devAddr_DES, 0xD4,1)))
    		time.sleep(0.1)
    		logging.info('%s', hex(eq_sel2))
    		print 'eq_sel2= ', hex(eq_sel2)
    		print 'lock status:'
    		f1.write("\r")
    		out_string = str(eq_sel1+eq_sel2) + ","
    		f1.write(out_string)	
    		ddly_ctrl = 8 #(disable 6 extra delay)
    		for cdly_ctrl in range(15, 8, -1):
    			# write reg_8
    			board.WriteI2C(devAddr_DES, 0xB2, ((ddly_ctrl<<4) + cdly_ctrl))
    			time.sleep(0.1)
    			logging.debug('**reg_8 updated value**: %s', hex(board.ReadI2C(devAddr_DES, 0xB2)))
    			# reset digital block except registers
    			board.WriteI2C(devAddr_DES, 0x01, 0x01)
    			time.sleep(dwell_time)
    			port_status1 = board.ReadI2C(devAddr_DES, 0x4D,1)
    			logging.debug('Check RX_PORT_STS1 Register (0x4D): %s', hex(port_status1))
    			time.sleep(0.1)
    			logging.debug('port lock status: %s', hex(port_status1 & 0x01))
    			time.sleep(0.1)
    			port_status2 = board.ReadI2C(devAddr_DES, 0x4E,1)
    			logging.debug('Check RX_PORT_STS2 Register (0x4E): %s', hex(port_status2))
    			time.sleep(0.1)			
    			lock_status = 0
    			lock_sum = 0
    			for loop in range(0, 10, 1):
    				port_status1 = board.ReadI2C(devAddr_DES, 0x4D, 1)
    				time.sleep(0.1)
    				port_status2 = board.ReadI2C(devAddr_DES, 0x4E, 1)
    				time.sleep(0.1)				
    				if (((port_status1 & 0x3C) == 0) and ((port_status2 & 0x20) == 0)):
    					lock_sum += int(port_status1 & 0x01)
    				else:
    					board.ReadI2C(devAddr_DES, 0x56, 1) # clear parity error
    				time.sleep(0.1)
    			lock_avg = round(float(lock_sum) / 10, 2)
    			lock_str = "%0.1f" %lock_avg
    			logging.debug('port lock status: %s', lock_str)
    			time.sleep(0.1)
    			out_string = lock_str + ","
    			f1.write(out_string)
    			print lock_str
    		logging.debug('**cdly_ctrl value at end of loop**: %s', hex(cdly_ctrl))
    		cdly_ctrl = 8 #(disable 6 extra delay)
    		for ddly_ctrl in range(8, 16, 1):
    			# write reg_8
    			board.WriteI2C(devAddr_DES, 0xB2, ((ddly_ctrl<<4) + cdly_ctrl))
    			time.sleep(0.1)
    			logging.debug('**reg_8 updated value**: %s', hex(board.ReadI2C(devAddr_DES, 0xB2)))
    			# reset digital block except registers
    			board.WriteI2C(devAddr_DES, 0x01, 0x01)
    			time.sleep(dwell_time)
    			port_status1 = board.ReadI2C(devAddr_DES, 0x4D,1)
    			logging.debug('Check RX_PORT_STS1 Register (0x4D): %s', hex(port_status1))
    			time.sleep(0.1)
    			logging.debug('port lock status: %s', hex(port_status1 & 0x01))
    			time.sleep(0.1)
    			port_status2 = board.ReadI2C(devAddr_DES, 0x4E,1)
    			logging.debug('Check RX_PORT_STS2 Register (0x4E): %s', hex(port_status2))
    			time.sleep(0.1)			
    			lock_status = 0
    			lock_sum = 0
    			for loop in range(0, 10, 1):
    				port_status1 = board.ReadI2C(devAddr_DES, 0x4D, 1)
    				time.sleep(0.1)
    				port_status2 = board.ReadI2C(devAddr_DES, 0x4E, 1)
    				time.sleep(0.1)				
    				if (((port_status1 & 0x3C) == 0) and ((port_status2 & 0x20) == 0)):
    					lock_sum += int(port_status1 & 0x01)
    				else:
    					board.ReadI2C(devAddr_DES, 0x56, 1) # clear parity error	
    				time.sleep(0.1)
    			lock_avg = round(float(lock_sum) / 10, 2)
    			lock_str = "%0.1f" %lock_avg
    			logging.debug('port lock status: %s', lock_str)
    			time.sleep(0.1)
    			out_string = lock_str + ","
    			f1.write(out_string)
    			print lock_str
    
    # write reg_8 default value
    board.WriteI2C(devAddr_DES, 0xB2, 0x0)
    time.sleep(0.1)
    
    #do a final digital reset including registers
    board.WriteI2C(devAddr_DES, 0x01, 0x02)
    time.sleep(0.1)
    
    #readback RX_PORT_STS1 to clear Lock status changed on RX Port 0
    board.ReadI2C(devAddr_DES, 0x4D, 1)
    time.sleep(0.1)
    
    logging.debug('reg_8 default value: %s', hex(board.ReadI2C(devAddr_DES, 0xB2)))
    time.sleep(0.1)
    
    logging.debug('DES lock & pass: %s', hex(board.ReadI2C(devAddr_DES, 0x04,1)))
    time.sleep(0.1)
    
    f1.close()
    

    Please let me know if there are any additional questions!

    Best,

    Zoe