"""
  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: ub934_margin_analysis.py
# Purpose: Margin Analysis Script for DS90UB934
# Version 0.97
# Run from DES

print "\n"

import time
import logging

# Select log file name and log level(DEBUG, INFO)
logging.basicConfig(filename='ub934sfeq_testlog.log', filemode='a', format='%(levelname)s:%(message)s',level=logging.DEBUG)

# Select RX Port: RX_PORT0_934B or RX_PORT1_934B
CONST_RXPORT = 'RX_PORT0_934B'

# configure I2C device ID of the DES per IDX strap pin
# EVM: 0x60, SVB: 0x7A, Custom Board: 0x??
devAddr_DES = 0x60

f1=open('./ub934sfeq_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_934B':
	#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_934B':
	#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()
