Commit 5492d082 authored by Dave Newbold's avatar Dave Newbold

Adding SI5344 libraries and config

parent 9ee4d9f2
# -*- coding: utf-8 -*-
"""
"""
import time
import uhal
verbose = True
################################################################################
# /*
# I2C CORE
# */
################################################################################
class I2CCore:
"""I2C communication block."""
# Define bits in cmd_stat register
startcmd = 0x1 << 7
stopcmd = 0x1 << 6
readcmd = 0x1 << 5
writecmd = 0x1 << 4
ack = 0x1 << 3
intack = 0x1
recvdack = 0x1 << 7
busy = 0x1 << 6
arblost = 0x1 << 5
inprogress = 0x1 << 1
interrupt = 0x1
def __init__(self, target, wclk, i2cclk, name="i2c", delay=None):
self.target = target
self.name = name
self.delay = delay
self.prescale_low = self.target.getNode("%s.ps_lo" % name)
self.prescale_high = self.target.getNode("%s.ps_hi" % name)
self.ctrl = self.target.getNode("%s.ctrl" % name)
self.data = self.target.getNode("%s.data" % name)
self.cmd_stat = self.target.getNode("%s.cmd_stat" % name)
self.wishboneclock = wclk
self.i2cclock = i2cclk
self.config()
def state(self):
status = {}
status["ps_low"] = self.prescale_low.read()
status["ps_hi"] = self.prescale_high.read()
status["ctrl"] = self.ctrl.read()
status["data"] = self.data.read()
status["cmd_stat"] = self.cmd_stat.read()
self.target.dispatch()
status["prescale"] = status["ps_hi"] << 8
status["prescale"] |= status["ps_low"]
for reg in status:
val = status[reg]
bval = bin(int(val))
if verbose:
print "\treg %s = %d, 0x%x, %s" % (reg, val, val, bval)
def clearint(self):
self.ctrl.write(0x1)
self.target.dispatch()
def config(self):
#INITIALIZATION OF THE I2S MASTER CORE
#Disable core
self.ctrl.write(0x0 << 7)
self.target.dispatch()
#Write pre-scale register
#prescale = int(self.wishboneclock / (5.0 * self.i2cclock)) - 1
prescale = 0x0100 #FOR NOW HARDWIRED, TO BE MODIFIED
#prescale = 0x2710 #FOR NOW HARDWIRED, TO BE MODIFIED
self.prescale_low.write(prescale & 0xff)
self.prescale_high.write((prescale & 0xff00) >> 8)
#Enable core
self.ctrl.write(0x1 << 7)
self.target.dispatch()
def checkack(self):
inprogress = True
ack = False
while inprogress:
cmd_stat = self.cmd_stat.read()
self.target.dispatch()
inprogress = (cmd_stat & I2CCore.inprogress) > 0
ack = (cmd_stat & I2CCore.recvdack) == 0
return ack
def delayorcheckack(self):
ack = True
if self.delay is None:
ack = self.checkack()
else:
time.sleep(self.delay)
ack = self.checkack()#Remove this?
return ack
################################################################################
# /*
# I2C WRITE
# */
################################################################################
def write(self, addr, data, stop=True):
"""Write data to the device with the given address."""
# Start transfer with 7 bit address and write bit (0)
nwritten = -1
addr &= 0x7f
addr = addr << 1
startcmd = 0x1 << 7
stopcmd = 0x1 << 6
writecmd = 0x1 << 4
#Set transmit register (write operation, LSB=0)
self.data.write(addr)
#Set Command Register to 0x90 (write, start)
self.cmd_stat.write(I2CCore.startcmd | I2CCore.writecmd)
self.target.dispatch()
ack = self.delayorcheckack()
if not ack:
self.cmd_stat.write(I2CCore.stopcmd)
self.target.dispatch()
return nwritten
nwritten += 1
for val in data:
val &= 0xff
#Write slave memory address
self.data.write(val)
#Set Command Register to 0x10 (write)
self.cmd_stat.write(I2CCore.writecmd)
self.target.dispatch()
ack = self.delayorcheckack()
if not ack:
self.cmd_stat.write(I2CCore.stopcmd)
self.target.dispatch()
return nwritten
nwritten += 1
if stop:
self.cmd_stat.write(I2CCore.stopcmd)
self.target.dispatch()
return nwritten
################################################################################
# /*
# I2C READ
# */
################################################################################
def read(self, addr, n):
"""Read n bytes of data from the device with the given address."""
# Start transfer with 7 bit address and read bit (1)
data = []
addr &= 0x7f
addr = addr << 1
addr |= 0x1 # read bit
self.data.write(addr)
self.cmd_stat.write(I2CCore.startcmd | I2CCore.writecmd)
self.target.dispatch()
ack = self.delayorcheckack()
if not ack:
self.cmd_stat.write(I2CCore.stopcmd)
self.target.dispatch()
return data
for i in range(n):
if i < (n-1):
self.cmd_stat.write(I2CCore.readcmd) # <---
else:
self.cmd_stat.write(I2CCore.readcmd | I2CCore.ack | I2CCore.stopcmd) # <--- This tells the slave that it is the last word
self.target.dispatch()
ack = self.delayorcheckack()
val = self.data.read()
self.target.dispatch()
data.append(val & 0xff)
#self.cmd_stat.write(I2CCore.stopcmd)
#self.target.dispatch()
return data
################################################################################
# /*
# I2C WRITE-READ
# */
################################################################################
# def writeread(self, addr, data, n):
# """Write data to device, then read n bytes back from it."""
# nwritten = self.write(addr, data, stop=False)
# readdata = []
# if nwritten == len(data):
# readdata = self.read(addr, n)
# return nwritten, readdata
"""
SPI core XML:
<node description="SPI master controller" fwinfo="endpoint;width=3">
<node id="d0" address="0x0" description="Data reg 0"/>
<node id="d1" address="0x1" description="Data reg 1"/>
<node id="d2" address="0x2" description="Data reg 2"/>
<node id="d3" address="0x3" description="Data reg 3"/>
<node id="ctrl" address="0x4" description="Control reg"/>
<node id="divider" address="0x5" description="Clock divider reg"/>
<node id="ss" address="0x6" description="Slave select reg"/>
</node>
"""
class SPICore:
go_busy = 0x1 << 8
rising = 1
falling = 0
def __init__(self, target, wclk, spiclk, basename="io.spi"):
self.target = target
# Only a single data register is required since all transfers are
# 16 bit long
self.data = target.getNode("%s.d0" % basename)
self.control = target.getNode("%s.ctrl" % basename)
self.control_val = 0b0
self.divider = target.getNode("%s.divider" % basename)
self.slaveselect = target.getNode("%s.ss" % basename)
self.divider_val = int(wclk / spiclk / 2.0 - 1.0)
self.divider_val = 0x7f
self.configured = False
def config(self):
"Configure SPI interace for communicating with ADCs."
self.divider_val = int(self.divider_val) % 0xffff
if verbose:
print "Configuring SPI core, divider = 0x%x" % self.divider_val
self.divider.write(self.divider_val)
self.target.dispatch()
self.control_val = 0x0
self.control_val |= 0x0 << 13 # Automatic slave select
self.control_val |= 0x0 << 12 # No interrupt
self.control_val |= 0x0 << 11 # MSB first
# ADC samples data on rising edge of SCK
self.control_val |= 0x1 << 10 # change ouput on falling edge of SCK
# ADC changes output shortly after falling edge of SCK
self.control_val |= 0x0 << 9 # read input on rising edge
self.control_val |= 0x10 # 16 bit transfers
if verbose:
print "SPI control val = 0x%x = %s" % (self.control_val, bin(self.control_val))
self.configured = True
def transmit(self, chip, value):
if not self.configured:
self.config()
assert chip >= 0 and chip < 8
value &= 0xffff
self.data.write(value)
checkdata = self.data.read()
self.target.dispatch()
assert checkdata == value
self.control.write(self.control_val)
self.slaveselect.write(0xff ^ (0x1 << chip))
self.target.dispatch()
self.control.write(self.control_val | SPICore.go_busy)
self.target.dispatch()
busy = True
while busy:
status = self.control.read()
self.target.dispatch()
busy = status & SPICore.go_busy > 0
self.slaveselect.write(0xff)
data = self.data.read()
ss = self.slaveselect.read()
status = self.control.read()
self.target.dispatch()
#print "Received data: 0x%x, status = 0x%x, ss = 0x%x" % (data, status, ss)
return data
import time
import uhal
from I2CuHal import I2CCore
import StringIO
import csv
class si5344:
#Class to configure the Si5344 clock generator
def __init__(self, i2c, slaveaddr=0x68):
self.i2c = i2c
self.slaveaddr = slaveaddr
#self.configList=
#def writeReg(self, address, data):
def readRegister(self, myaddr, nwords):
### Read a specific register on the Si5344 chip. There is not check on the validity of the address but
### the code sets the correct page before reading.
#First make sure we are on the correct page
currentPg= self.getPage()
requirePg= (myaddr & 0xFF00) >> 8
# print "REG", hex(myaddr), "CURR PG" , hex(currentPg[0]), "REQ PG", hex(requirePg)
if currentPg[0] != requirePg:
self.setPage(requirePg)
#Now read from register.
addr=[]
addr.append(myaddr)
mystop=False
self.i2c.write( self.slaveaddr, addr, mystop)
# time.sleep(0.1)
res= self.i2c.read( self.slaveaddr, nwords)
return res
def writeRegister(self, myaddr, data, verbose=False):
### Write a specific register on the Si5344 chip. There is not check on the validity of the address but
### the code sets the correct page before reading.
### myaddr is an int
### data is a list of ints
#First make sure we are on the correct page
myaddr= myaddr & 0xFFFF
currentPg= self.getPage()
requirePg= (myaddr & 0xFF00) >> 8
# print "REG", hex(myaddr), "CURR PG" , currentPg, "REQ PG", hex(requirePg)
if currentPg[0] != requirePg:
self.setPage(requirePg)
#Now write to register.
data.insert(0, myaddr)
if verbose:
print " Writing: "
result="\t "
for iaddr in data:
result+="%#02x "%(iaddr)
print result
self.i2c.write( self.slaveaddr, data)
#time.sleep(0.01)
def setPage(self, page, verbose=False):
#Configure the chip to perform operations on the specified address page.
mystop=True
myaddr= [0x01, page]
self.i2c.write( self.slaveaddr, myaddr, mystop)
#time.sleep(0.01)
if verbose:
print "Si5344 Set Reg Page:", page
def getPage(self, verbose=False):
#Read the current address page
mystop=False
myaddr= [0x01]
self.i2c.write( self.slaveaddr, myaddr, mystop)
rPage= self.i2c.read( self.slaveaddr, 1)
#time.sleep(0.1)
if verbose:
print " Page read:", rPage
return rPage
def getDeviceVersion(self):
#Read registers containing chip information
mystop=False
nwords=2
myaddr= [0x02 ]#0xfa
self.setPage(0)
self.i2c.write( self.slaveaddr, myaddr, mystop)
#time.sleep(0.1)
res= self.i2c.read( self.slaveaddr, nwords)
print " CLOCK EPROM: "
result="\t "
for iaddr in res:
result+="%#02x "%(iaddr)
print result
return res
def parse_clk(self, filename):
#Parse the configuration file produced by Clockbuilder Pro (Silicon Labs)
deletedcomments=""""""
print "\tParsing file", filename
with open(filename, 'rb') as configfile:
for i, line in enumerate(configfile):
if not line.startswith('#') :
if not line.startswith('Address'):
deletedcomments+=line
csvfile = StringIO.StringIO(deletedcomments)
cvr= csv.reader(csvfile, delimiter=',', quotechar='|')
#print "\tN elements parser:", sum(1 for row in cvr)
#return [addr_list,data_list]
# for item in cvr:
# print "rere"
# regAddr= int(item[0], 16)
# regData[0]= int(item[1], 16)
# print "\t ", hex(regAddr), hex(regData[0])
#self.configList= cvr
regSettingList= list(cvr)
print "\t ", len(regSettingList), "elements"
return regSettingList
def writeConfiguration(self, regSettingList):
print "\tWrite configuration:"
#regSettingList= list(regSettingCsv)
counter=0
for item in regSettingList:
regAddr= int(item[0], 16)
regData=[0]
regData[0]= int(item[1], 16)
# print "\t ", counter, "Reg:", hex(regAddr), "Data:", regData
counter += 1
self.writeRegister(regAddr, regData)
../../../components/solid/software/I2CuHal.py
\ No newline at end of file
# Si538x/4x Registers Script
#
# Part: Si5344
# Project File: O:\Si5344-RevD-SolMas01-Project.slabtimeproj
# Design ID: SolMas01
# Includes Pre/Post Download Control Register Writes: Yes
# Die Revision: B1
# Creator: ClockBuilder Pro v2.15 [2017-05-15]
# Created On: 2017-07-12 13:15:46 GMT+01:00
Address,Data
#
# Start configuration preamble
0x0B24,0xC0
0x0B25,0x00
0x0540,0x01
# End configuration preamble
#
# Delay 300 msec
# Delay is worst case time for device to complete any calibration
# that is running due to device state change previous to this script
# being processed.
#
# Start configuration registers
0x000B,0x68
0x0016,0x02
0x0017,0xDC
0x0018,0xFF
0x0019,0xFF
0x001A,0xFF
0x002B,0x02
0x002C,0x00
0x002D,0x00
0x002E,0x00
0x002F,0x00
0x0030,0x00
0x0031,0x00
0x0032,0x00
0x0033,0x00
0x0034,0x00
0x0035,0x00
0x0036,0x00
0x0037,0x00
0x0038,0x00
0x0039,0x00
0x003A,0x00
0x003B,0x00
0x003C,0x00
0x003D,0x00
0x003F,0x00
0x0040,0x04
0x0041,0x00
0x0042,0x00
0x0043,0x00
0x0044,0x00
0x0045,0x0C
0x0046,0x00
0x0047,0x00
0x0048,0x00
0x0049,0x00
0x004A,0x00
0x004B,0x00
0x004C,0x00
0x004D,0x00
0x004E,0x00
0x004F,0x00
0x0051,0x00
0x0052,0x00
0x0053,0x00
0x0054,0x00
0x0055,0x00
0x0056,0x00
0x0057,0x00
0x0058,0x00
0x0059,0x00
0x005A,0x00
0x005B,0x00
0x005C,0x00
0x005D,0x00
0x005E,0x00
0x005F,0x00
0x0060,0x00
0x0061,0x00
0x0062,0x00
0x0063,0x00
0x0064,0x00
0x0065,0x00
0x0066,0x00
0x0067,0x00
0x0068,0x00
0x0069,0x00
0x0092,0x00
0x0093,0x00
0x0095,0x00
0x0096,0x00
0x0098,0x00
0x009A,0x00
0x009B,0x00
0x009D,0x00
0x009E,0x00
0x00A0,0x00
0x00A2,0x00
0x00A9,0x00
0x00AA,0x00
0x00AB,0x00
0x00AC,0x00
0x00E5,0x01
0x00EA,0x00
0x00EB,0x00
0x00EC,0x00
0x00ED,0x00
0x0102,0x01
0x0112,0x06
0x0113,0x09
0x0114,0x3B
0x0115,0x28
0x0117,0x06
0x0118,0x09
0x0119,0x3B
0x011A,0x28
0x0126,0x06
0x0127,0x09
0x0128,0x3B
0x0129,0x28
0x012B,0x01
0x012C,0x09
0x012D,0x3B
0x012E,0x28
0x013F,0x00
0x0140,0x00
0x0141,0x40
0x0142,0xFF
0x0206,0x00
0x0208,0x00
0x0209,0x00
0x020A,0x00
0x020B,0x00
0x020C,0x00
0x020D,0x00
0x020E,0x00
0x020F,0x00
0x0210,0x00
0x0211,0x00
0x0212,0x00
0x0213,0x00
0x0214,0x00
0x0215,0x00
0x0216,0x00
0x0217,0x00
0x0218,0x00
0x0219,0x00
0x021A,0x00
0x021B,0x00
0x021C,0x00
0x021D,0x00
0x021E,0x00
0x021F,0x00
0x0220,0x00
0x0221,0x00
0x0222,0x00
0x0223,0x00
0x0224,0x00
0x0225,0x00
0x0226,0x00
0x0227,0x00
0x0228,0x00
0x0229,0x00
0x022A,0x00
0x022B,0x00
0x022C,0x00
0x022D,0x00
0x022E,0x00
0x022F,0x00
0x0231,0x0B
0x0232,0x0B
0x0233,0x0B
0x0234,0x0B
0x0235,0x00
0x0236,0x00
0x0237,0x00
0x0238,0x00
0x0239,0x84
0x023A,0x00
0x023B,0x00
0x023C,0x00
0x023D,0x00
0x023E,0x80
0x0250,0x00
0x0251,0x00
0x0252,0x00
0x0253,0x00
0x0254,0x00
0x0255,0x00
0x025C,0x00
0x025D,0x00
0x025E,0x00
0x025F,0x00
0x0260,0x00
0x0261,0x00
0x026B,0x53
0x026C,0x6F
0x026D,0x6C
0x026E,0x4D
0x026F,0x61
0x0270,0x73
0x0271,0x30
0x0272,0x31
0x0294,0x80
0x0296,0x00
0x0297,0x00
0x0299,0x00
0x029D,0x00
0x029E,0x00
0x029F,0x00
0x02A9,0x00
0x02AA,0x00
0x02AB,0x00
0x02B7,0xFF
0x0302,0x00
0x0303,0x00
0x0304,0x00
0x0305,0x80
0x0306,0x52
0x0307,0x00
0x0308,0x00
0x0309,0x00
0x030A,0x00
0x030B,0x80
0x030C,0x00
0x030D,0x00
0x030E,0x00
0x030F,0x00
0x0310,0x00
0x0311,0x00
0x0312,0x00
0x0313,0x00
0x0314,0x00
0x0315,0x00
0x0316,0x00
0x0317,0x00
0x0318,0x00
0x0319,0x00
0x031A,0x00
0x031B,0x00
0x031C,0x00
0x031D,0x00
0x031E,0x00
0x031F,0x00
0x0320,0x00
0x0321,0x00
0x0322,0x00
0x0323,0x00
0x0324,0x00
0x0325,0x00
0x0326,0x00
0x0327,0x00
0x0328,0x00
0x0329,0x00
0x032A,0x00
0x032B,0x00
0x032C,0x00
0x032D,0x00
0x0338,0x00
0x0339,0x1F
0x033B,0x00
0x033C,0x00
0x033D,0x00
0x033E,0x00
0x033F,0x00
0x0340,0x00
0x0341,0x00
0x0342,0x00
0x0343,0x00
0x0344,0x00
0x0345,0x00
0x0346,0x00
0x0347,0x00
0x0348,0x00
0x0349,0x00
0x034A,0x00
0x034B,0x00
0x034C,0x00
0x034D,0x00
0x034E,0x00
0x034F,0x00
0x0350,0x00
0x0351,0x00
0x0352,0x00
0x0359,0x00
0x035A,0x00
0x035B,0x00
0x035C,0x00
0x035D,0x00
0x035E,0x00
0x035F,0x00
0x0360,0x00
0x0487,0x00
0x0502,0x01
0x0508,0x00
0x0509,0x00
0x050A,0x00
0x050B,0x00
0x050C,0x00
0x050D,0x00
0x050E,0x00
0x050F,0x00
0x0510,0x00
0x0511,0x00
0x0512,0x00
0x0513,0x00
0x0515,0x00
0x0516,0x00
0x0517,0x00
0x0518,0x00
0x0519,0x00
0x051A,0x00
0x051B,0x00
0x051C,0x00
0x051D,0x00
0x051E,0x00
0x051F,0x00
0x0521,0x2B
0x052A,0x00