Commit 07fd2633 authored by Grzegorz Daniluk's avatar Grzegorz Daniluk

Merge branch 'si5341_script' into 'master'

Add Si5341 configuration script with default config

See merge request !1
parents 19cdfcdb aeb5d6f4
# Si534x/7x/8x/9x Registers Script
#
# Part: Si5341
# Project File: C:\Users\adbyszuk\cernbox\Documents\Si5341-RevD-CCE-Project.slabtimeproj
# Design ID: CCE
# Includes Pre/Post Download Control Register Writes: Yes
# Die Revision: B1
# Creator: ClockBuilder Pro v4.4 [2022-03-30]
# Created On: 2022-08-17 11:55:33 GMT+02:00
#
# (adbyszuk) Some basic config info:
# Clock input: XTAL only
# Clock outputs:
# OUT2, OUT3, OUT4: 125 MHz, output enabled (connected to FPGA)
# OUT0, OUT1: 125 MHz, output disabled (connected to FMC slot)
#
Address,Data
#
# Start configuration preamble
0x0B24,0xC0
0x0B25,0x00
# Rev D stuck divider fix
0x0502,0x01
0x0505,0x03
0x0957,0x17
0x0B4E,0x1A
# 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
0x0006,0x00
0x0007,0x00
0x0008,0x00
0x000B,0x74
0x0017,0xD0
0x0018,0xFF
0x0021,0x0F
0x0022,0x00
0x002B,0x02
0x002C,0x20
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
0x0041,0x00
0x0042,0x00
0x0043,0x00
0x0044,0x00
0x009E,0x00
0x0102,0x01
0x0108,0x04
0x0109,0x09
0x010A,0x3E
0x010B,0x18
0x010D,0x04
0x010E,0x09
0x010F,0x3E
0x0110,0x18
0x0112,0x06
0x0113,0x09
0x0114,0x3E
0x0115,0x18
0x0117,0x06
0x0118,0x09
0x0119,0x3E
0x011A,0x18
0x011C,0x06
0x011D,0x09
0x011E,0x3E
0x011F,0x18
0x0121,0x01
0x0122,0x09
0x0123,0x3B
0x0124,0x28
0x0126,0x01
0x0127,0x09
0x0128,0x3B
0x0129,0x28
0x012B,0x01
0x012C,0x09
0x012D,0x3B
0x012E,0x28
0x0130,0x01
0x0131,0x09
0x0132,0x3B
0x0133,0x28
0x013A,0x01
0x013B,0x09
0x013C,0x3B
0x013D,0x28
0x013F,0x00
0x0140,0x00
0x0141,0x40
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
0x0235,0x00
0x0236,0x00
0x0237,0x00
0x0238,0xA0
0x0239,0x8C
0x023A,0x00
0x023B,0x00
0x023C,0x00
0x023D,0x00
0x023E,0x80
0x024A,0x00
0x024B,0x00
0x024C,0x00
0x024D,0x00
0x024E,0x00
0x024F,0x00
0x0250,0x00
0x0251,0x00
0x0252,0x00
0x0253,0x00
0x0254,0x00
0x0255,0x00
0x0256,0x00
0x0257,0x00
0x0258,0x00
0x0259,0x00
0x025A,0x00
0x025B,0x00
0x025C,0x00
0x025D,0x00
0x025E,0x00
0x025F,0x00
0x0260,0x00
0x0261,0x00
0x0262,0x00
0x0263,0x00
0x0264,0x00
0x0268,0x00
0x0269,0x00
0x026A,0x00
0x026B,0x43
0x026C,0x43
0x026D,0x45
0x026E,0x00
0x026F,0x00
0x0270,0x00
0x0271,0x00
0x0272,0x00
0x0302,0x00
0x0303,0x00
0x0304,0x00
0x0305,0x00
0x0306,0x1B
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
0x032E,0x00
0x032F,0x00
0x0330,0x00
0x0331,0x00
0x0332,0x00
0x0333,0x00
0x0334,0x00
0x0335,0x00
0x0336,0x00
0x0337,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
0x0353,0x00
0x0354,0x00
0x0355,0x00
0x0356,0x00
0x0357,0x00
0x0358,0x00
0x0359,0x00
0x035A,0x00
0x035B,0x00
0x035C,0x00
0x035D,0x00
0x035E,0x00
0x035F,0x00
0x0360,0x00
0x0361,0x00
0x0362,0x00
0x0802,0x00
0x0803,0x00
0x0804,0x00
0x0805,0x00
0x0806,0x00
0x0807,0x00
0x0808,0x00
0x0809,0x00
0x080A,0x00
0x080B,0x00
0x080C,0x00
0x080D,0x00
0x080E,0x00
0x080F,0x00
0x0810,0x00
0x0811,0x00
0x0812,0x00
0x0813,0x00
0x0814,0x00
0x0815,0x00
0x0816,0x00
0x0817,0x00
0x0818,0x00
0x0819,0x00
0x081A,0x00
0x081B,0x00
0x081C,0x00
0x081D,0x00
0x081E,0x00
0x081F,0x00
0x0820,0x00
0x0821,0x00
0x0822,0x00
0x0823,0x00
0x0824,0x00
0x0825,0x00
0x0826,0x00
0x0827,0x00
0x0828,0x00
0x0829,0x00
0x082A,0x00
0x082B,0x00
0x082C,0x00
0x082D,0x00
0x082E,0x00
0x082F,0x00
0x0830,0x00
0x0831,0x00
0x0832,0x00
0x0833,0x00
0x0834,0x00
0x0835,0x00
0x0836,0x00
0x0837,0x00
0x0838,0x00
0x0839,0x00
0x083A,0x00
0x083B,0x00
0x083C,0x00
0x083D,0x00
0x083E,0x00
0x083F,0x00
0x0840,0x00
0x0841,0x00
0x0842,0x00
0x0843,0x00
0x0844,0x00
0x0845,0x00
0x0846,0x00
0x0847,0x00
0x0848,0x00
0x0849,0x00
0x084A,0x00
0x084B,0x00
0x084C,0x00
0x084D,0x00
0x084E,0x00
0x084F,0x00
0x0850,0x00
0x0851,0x00
0x0852,0x00
0x0853,0x00
0x0854,0x00
0x0855,0x00
0x0856,0x00
0x0857,0x00
0x0858,0x00
0x0859,0x00
0x085A,0x00
0x085B,0x00
0x085C,0x00
0x085D,0x00
0x085E,0x00
0x085F,0x00
0x0860,0x00
0x0861,0x00
0x090E,0x02
0x091C,0x04
0x0943,0x01
0x0949,0x00
0x094A,0x00
0x094E,0x49
0x094F,0x02
0x095E,0x00
0x0A02,0x00
0x0A03,0x01
0x0A04,0x01
0x0A05,0x01
0x0A14,0x00
0x0A1A,0x00
0x0A20,0x00
0x0A26,0x00
0x0A2C,0x00
0x0B44,0x0F
0x0B4A,0x1E
0x0B57,0x0E
0x0B58,0x01
# End configuration registers
#
# Start configuration postamble
0x001C,0x01
0x0B24,0xC3
0x0B25,0x02
# End configuration postamble
"""
Configures Silabs 5341 clock generator.
On DIOT peripheral board there's embedded FTDI (FT4232) UART-to-I2C bridge.
"""
from pyftdi.ftdi import Ftdi
from pyftdi.i2c import I2cController
from typing import Union, Iterable
from pathlib import Path
import time
import csv
class si5341:
"""Silabs 5341 communication class."""
def __init__(self, i2c, addr=0x76):
"""Class constructor.
:param i2c: I2C controller object from pyftdi (after configure())
:param addr: I2C address
"""
self.port = i2c.get_port(addr)
self.gpio = i2c.get_gpio()
self.__page = None # device page is unknown without configuration
def configure(self) -> None:
"""Configure board and enable I2C access."""
# Buffer enable is connected to BDBUS6
bufen_mask = 0x1 << 6
self.gpio.set_direction(bufen_mask, bufen_mask)
self.gpio.write(bufen_mask)
# reset page register to known setting
self.__page = 0
self.port.write_to(0x1, [self.__page])
def write(self, addr: int, val: int) -> None:
"""Write to device register."""
page = addr >> 8
assert page in [0, 1, 2, 3, 5, 8, 9, 0xA, 0xB]
# pages #5 and #8 aren't mentioned in the reference manual, but are
# used by config generated with clockbuilder software
if page != self.__page:
self.port.write_to(0x1, [page])
self.__page = page
self.port.write_to(addr & 0xFF, [val])
def read(self, addr: int) -> int:
"""Read from device register."""
page = addr >> 8
assert page in [0, 1, 2, 3, 5, 8, 9, 0xA, 0xB]
# pages #5 and #8 aren't mentioned in the reference manual, but are
# used by config generated with clockbuilder software
if page != self.__page:
self.port.write_to(0x1, [page])
self.__page = page
val = self.port.exchange([addr & 0xFF], 1)
return int.from_bytes(val, "big")
def nvm_write(self) -> None:
"""Write current configuration to NV memory.
THIS IS VERY DANGEROUS OPERATION THAT CANNOT BE REVERTED!
Si5341 devices have two NVM banks that can be programmed only one time.
"""
# check if there are any free banks available to burn
bank = self.read(0xe2)
if bank == 3:
print('Two banks left')
elif bank == 15:
print('One bank left')
elif bank == 63:
raise Exception('No free NVM banks available to burn')
else:
raise Exception(f"Unknown status ({bank}), can't proceed")
answer = input('Do you want to proceed? [yes]/[no]')
if any(answer.lower() == f for f in ['yes', 'y']):
pass
else:
print('Aborting NVM burn')
return
print('Starting NVM burn procedure')
self.write(0xe2, 0xc7)
while self.read(0xfe) != 0x0F:
pass
print('Burning finished, checking NVM download')
self.write(0xe4, 0x1)
while self.read(0xfe) != 0x0F: # wait until download is finished
pass
new_bank = self.read(0xe2)
if (bank == 3 and new_bank == 15) or (bank == 15 and new_bank == 63):
print('NVM programmed properly')
def load_from_csv(self, path: Union[str, Path]) -> None:
"""Send device configuration from CSV file generated by ClockBuilder.
:param path: Path to csv file
"""
def decomment(csvfile):
for row in csvfile:
raw = row.split('#')[0].strip()
if raw:
yield raw
with open(path) as csvfile:
reader = csv.reader(decomment(csvfile))
# skip header text
next(reader)
ldata = list(reader)
for idx, row in enumerate(ldata):
addr = int(row[0], base=16)
val = int(row[1], base=16)
self.write(addr, val)
if addr == 0x0B4E:
# Comment in the CSV file suggests waiting after preamble
time.sleep(0.3)
print('Config sent, starting verification readback')
# skip preamble and postamble
for idx, row in enumerate(ldata[2:-3]):
addr = int(row[0], base=16)
val = int(row[1], base=16)
rval = self.read(addr)
if val != rval:
print(f'Data mismatch - addr={hex(addr)} sent={hex(val)} '
f'received={hex(rval)}')
time.sleep(1)
val = self.read(0xC)
print('Done')
print(f'Device status (should be 0xC0): {hex(val)}')
print('Connecting to USB-I2C bridge')
i2c = I2cController()
i2c.configure('ftdi://ftdi:4232h/2')
dev = si5341(i2c, 0x76)
print('Enabling USB access to I2C bus')
dev.configure()
fname = 'Si5341-RevD-CCE-Registers.txt'
print(f'Loading configuration data from {fname}')
data = dev.load_from_csv(fname)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment