# Python Library to control i2c devices such as the USB2ANY
#
# NOTE: The USB2ANY uses a 7-bit I2C address field ... we standardly use 8-bit I2C addresses
#
# E.g. on DS110DF1610, we commonly use an address of 0x30 which is an 8-bit representation.
# On the USB2ANY dongle, the addr is 7-bits, so the address is 0x18
#
# Ver Date Author Changes
#####################################################################################
# v1 5 Mar 2013 Bridger Initial version with basic I2C read/writes with USB2ANY
# v1.1 13 Mar 2013 Bridger Added read
#
#C:\TestFolder\dopl_temp_sensor\i2c.py
#
from ctypes import*
#from intelhex import IntelHex
import math
import time
import os
import string
DEFAULT_FIRST_TOKEN = "RAW"
class usb2any():
def get_7bit_addr(self,addr8):
return addr8>>1
def get_8bit_addr(self,addr7):
return addr7<<1
def __init__(self):
# Basic DLL interaction
#self.usb2anydll = windll.LoadLibrary("C:\\Test_Folder\\usb2any_lib\\USB2ANY.dll") # Change me to the actual location on your PC!!!!
#self.usb2anydll = windll.LoadLibrary("C:\\Program Files (x86)\\TI USB2ANY SDK\\Sample Code\\Release\\USB2ANY.dll")
self.usb2anydll = windll.LoadLibrary("C:\\Program Files (x86)\\Texas Instruments\\SigCon Architect EVM GUI\\Shared Library\\USB2ANY.dll")
self.numcontrollers = self.usb2anydll.u2aFindControllers()
if(self.numcontrollers <0):
quit("No USB2ANY controllers found")
else:
print "USB-2-Any devices found: ",self.numcontrollers
self.serialnum = self.get_serial_numbers()
#print "SerialNum: ",self.serialnum
self.u2ahandle = self.get_handle(self.serialnum)
print "Opening USB2ANY... Obtained handle for ",self.serialnum," as ",self.u2ahandle
#Init function.
def get_serial_numbers(self):
#int u2aGetSerialNumber(int index, char *SerialNumber
sernums = self.usb2anydll.u2aGetSerialNumber
sernums.argtype = [c_int, c_char_p]
serial = c_char_p(" ") ;
sernums(0,serial)
print "USB2ANY<0> Device SerialNumber: ", serial.value
return serial.value
#Init function.
def get_handle(self,serial_number):
u2aopen_py = self.usb2anydll.u2aOpen
u2aopen_py.argtype = [c_char_p]
u2ahandle = u2aopen_py(serial_number)
#print "Opening USB2ANY... Obtained handle for ",serial.value," as ",u2ahandle
return u2ahandle
#def configure_I2C(self,speed,numbits_addr,pullups):
# return self.usb2anydll.u2aI2C_Control(u2ahandle,speed,numbits_addr,pullups)
# #print "Setting up I2C at 400 kHz, no pullups, 7-bit address. Status(0 is good): ", usb2any.u2aI2C_Control(u2ahandle,1,0,0)
# Write an Atomic Macro
#int u2aI2C_RegisterRead (U2A_HANDLE handle, UInt16 I2C_Address, Byte RegisterAddress)
def i2c_readByte(self,i2c_slave_addr,reg_address):
i2cread = self.usb2anydll.u2aI2C_RegisterRead
i2cread.argtype = [c_int, c_uint,c_ubyte]
i2cread.restype = c_int
return i2cread(self.u2ahandle,self.get_7bit_addr(i2c_slave_addr),reg_address)
def i2c_readByte_hex(self,i2c_slave_addr,reg_address):
return hex(self.i2c_readByte(i2c_slave_addr,reg_address))
def i2c_writeMask(self,i2c_slave_addr, reg_address,value,mask):
ReadVal = self.i2c_readByte(i2c_slave_addr,reg_address)
notMask = 0xff^mask # Require bitwise or to invert because otherwise python clips values like 0x0f as long integers and inverts the sign bit
maskedReadVal = ReadVal¬Mask
maskedVal = value&mask
writeVal = maskedReadVal | maskedVal
# print "Val: ",hex(value),"Mask:",hex(mask),"NotMask:",hex(notMask),"ReadVal:",hex(ReadVal),"maskedReadVal:",hex(maskedReadVal),"Val to Write: ",hex(writeVal)
return self.i2c_writeByte(i2c_slave_addr,reg_address,writeVal)
#u2aI2C_RegisterWrite(U2A_HANDLE handle, UInt16 I2C_Address, Byte RegisterAddress, Byte Value)
def i2c_writeByte(self,i2c_slave_addr, reg_address,value):
i2cwrite = self.usb2anydll.u2aI2C_RegisterWrite
i2cwrite.argtype = [c_int, c_uint, c_ubyte, c_ubyte]
i2cwrite.restype = c_int
return i2cwrite(self.u2ahandle,self.get_7bit_addr(i2c_slave_addr),reg_address,value)
#u2aI2C_RegisterWrite(U2A_HANDLE handle, UInt16 I2C_Address, Byte RegisterAddressUpper, Byte RegisterAddressLower, Byte Value)
def i2c_EEPROM_writeByte(self, i2c_slave_addr, reg_address,value):
i2cRawWrite = self.usb2anydll.u2aI2C_RawWrite
i2cRawWrite.argtype = [c_int, c_uint, c_ubyte, POINTER(c_char)]
i2cRawWrite.restype = c_int
reg_address_upper = reg_address >> 8
reg_address_lower = reg_address & 0x00FF
data = (c_ubyte * 3) (0,0,0) # Create and initialize an array
data[0] = reg_address_upper
data[1] = reg_address_lower
data[2] = value
num_bytes = 3 # Two bytes of address and one of data
return i2cRawWrite(self.u2ahandle,self.get_7bit_addr(i2c_slave_addr),num_bytes,data)
# Write an Intel Hex file to an EEPROM
def i2c_EEPROM_writeHex(self, i2c_slave_addr, write_address, hex_file):
# Read the .hex file of uC code and construct a vector to load to the DS100DF811
# This hex file is generated from an ARM Cortex compiler and must be located in
# '.\uC_Image\'
uC_CodeHex = IntelHex()
# load uC firmware from compiler-generated hex file
#uC_CodeHex.fromfile('.\uC_Image\LED_Flash\uC.hex',format='hex')
full_filename = ".\uC_Image\%s" % hex_file
uC_CodeHex.fromfile(full_filename,format='hex')
# Create a ctypes data buffer for output of uC_Image to USB2ANY
outputDataBuff = (c_ubyte * uC_CodeHex.maxaddr()) (0) #create an array and init the first two locations(it's a don't care)
image_num_bytes = uC_CodeHex.maxaddr()
outputDataBuff = uC_CodeHex.tobinarray(start=uC_CodeHex.minaddr(), size=(uC_CodeHex.maxaddr())) #data gets automatically recasted to c_ubyte
# Construct the array of write data, including the start address
write_address_upper = write_address >> 8
write_address_lower = write_address & 0x00FF
write_data = (c_ubyte * (2 + image_num_bytes)) (0,1)
write_data[0] = write_address_upper
write_data[1] = write_address_lower
#write_data[2:image_num_bytes+2] = outputDataBuff
for i in range(0,image_num_bytes):
write_data[i+2]=outputDataBuff[i]
# Write the data to the EEPROM
i2cRawWrite = self.usb2anydll.u2aI2C_RawWrite
i2cRawWrite.argtype = [c_int, c_uint, c_ubyte, POINTER(c_char)]
i2cRawWrite.restype = c_int
EEPROM_7bit_addr = i2c_slave_addr >> 1
num_bytes_per_write = 8 # Found we have to break the write up into smaller segments
num_8_byte_cycles = int(math.ceil(image_num_bytes / num_bytes_per_write))
for i in range(0,num_8_byte_cycles):
# Found it was necessary to add a small delay to make the write successfull
time.sleep(0.1)
# Prepare the write data
write_data = (c_ubyte * (2 + num_bytes_per_write)) (0)
# Update the write address
cur_write_address = i*num_bytes_per_write + write_address
cur_write_address_upper = cur_write_address >> 8
cur_write_address_lower = cur_write_address & 0x00FF
# Store the write address as the first two bytes of the write data
write_data[0] = cur_write_address_upper
write_data[1] = cur_write_address_lower
# Grab the rest of the write data
for k in range(0,num_bytes_per_write):
write_data[k+2]=outputDataBuff[i*num_bytes_per_write + k]
# Write this segment to the EEPROM using a raw write
result = i2cRawWrite(self.u2ahandle,EEPROM_7bit_addr,2+num_bytes_per_write,write_data)
if (result==0):
print('.'),
else:
print 'Error'
# print final carriage return
print 'DONE'
print '****************************************************************************************'
print '****************************************************************************************'
print '****************************************************************************************'