Skip to content

Commit 67c37f8

Browse files
committed
Add new lmclk
1 parent 35733c2 commit 67c37f8

File tree

8 files changed

+759
-33
lines changed

8 files changed

+759
-33
lines changed

rfsoc_qpsk/clocks.py

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import os
2+
import xrfclk
3+
4+
def _get_lmclk_devices():
5+
"""Populate LMK and LMX devices.
6+
"""
7+
8+
# Search for devices if none exist
9+
if xrfclk.lmk_devices == [] and xrfclk.lmx_devices == []:
10+
xrfclk.xrfclk._find_devices()
11+
12+
def _get_custom_lmclks(loc):
13+
"""Search for LMK and LMX clock files with a given address.
14+
"""
15+
16+
# Check type and value
17+
if not isinstance(loc, str):
18+
raise TypeError('Address location must be a string.')
19+
if not os.path.isdir(loc):
20+
raise ValueError('Address location does not exist.')
21+
22+
# Variables
23+
lmk_loc = ''
24+
lmx_loc = ''
25+
lmclk_loc = ''
26+
27+
# Walk through directory and find .txt files
28+
for root, dirs, files in os.walk(loc):
29+
for d in dirs:
30+
for lmk in xrfclk.lmk_devices:
31+
if d == lmk['compatible']:
32+
lmclk_loc = os.path.join(root, d)
33+
break
34+
35+
# Check variable is empty
36+
if lmclk_loc == '':
37+
raise RuntimeError('Could not find lmclk files.')
38+
39+
# Use root directory to extract LMK and LMX locs
40+
for file in os.listdir(lmclk_loc):
41+
if file.endswith('.txt'):
42+
if 'LMK' in file:
43+
lmk_loc = os.path.join(lmclk_loc, file)
44+
elif 'LMX' in file:
45+
lmx_loc = os.path.join(lmclk_loc, file)
46+
47+
# Check variables are empty
48+
if lmk_loc == '' or lmx_loc == '':
49+
raise RuntimeError('Could not find lmclk files.')
50+
51+
return lmk_loc, lmx_loc
52+
53+
def _get_custom_lmclk_props(lmk_loc, lmx_loc):
54+
"""Obtain the properties for LMK and LMX clocks using
55+
a set of address locations for clock files.
56+
"""
57+
58+
# Check type, value, and file format
59+
if not isinstance(lmk_loc, str) or not isinstance(lmx_loc, str):
60+
raise TypeError('TICS files must be a string.')
61+
if not os.path.isfile(lmk_loc) or not os.path.isfile(lmx_loc):
62+
raise ValueError('TICS file paths do not exist.')
63+
if not lmk_loc[-4:] == '.txt' or not lmx_loc[-4:] == '.txt':
64+
raise ValueError('TICS files must be .txt files.')
65+
66+
# Strip file name from arguments
67+
lmk_name = lmk_loc.split('/')[-1]
68+
lmx_name = lmx_loc.split('/')[-1]
69+
70+
# Split file name into LMK and LMX chip and freq (strip .txt)
71+
lmk_split = lmk_name.strip('.txt').split('_')
72+
lmx_split = lmx_name.strip('.txt').split('_')
73+
74+
# Obtain LMK and LMX chip and freq components and
75+
# check for errors in format
76+
if len(lmk_split) == 2 and len(lmx_split) == 2:
77+
lmk_chip, lmk_freq = lmk_split
78+
lmx_chip, lmx_freq = lmx_split
79+
else:
80+
raise ValueError('TICS file names have incorrect format.')
81+
82+
# Open files and parse registers
83+
with open(lmk_loc, 'r') as file:
84+
reg = [line.rstrip("\n") for line in file]
85+
lmk_reg = [int(r.split('\t')[-1], 16) for r in reg]
86+
with open(lmx_loc, 'r') as file:
87+
reg = [line.rstrip("\n") for line in file]
88+
lmx_reg = [int(r.split('\t')[-1], 16) for r in reg]
89+
90+
# Populate TICS file dictionary
91+
clk_props = {
92+
'lmk' : {
93+
'file' : lmk_name,
94+
'loc' : lmk_loc,
95+
'chip' : lmk_chip,
96+
'freq' : lmk_freq,
97+
'reg' : lmk_reg
98+
},
99+
'lmx' : {
100+
'file' : lmx_name,
101+
'loc' : lmx_loc,
102+
'chip' : lmx_chip,
103+
'freq' : lmx_freq,
104+
'reg' : lmx_reg
105+
}
106+
}
107+
108+
return clk_props
109+
110+
def _program_custom_lmclks(clk_props):
111+
"""Program the LMK and LMX clocks using clock properties.
112+
"""
113+
114+
# Program each device
115+
for lmk in xrfclk.lmk_devices:
116+
xrfclk.xrfclk._write_LMK_regs(clk_props['lmk']['reg'], lmk)
117+
for lmx in xrfclk.lmx_devices:
118+
xrfclk.xrfclk._write_LMX_regs(clk_props['lmx']['reg'], lmx)
119+
120+
def set_custom_lmclks():
121+
"""Populate LMK and LMX clocks. Search for clock files.
122+
Obtain the properties of the clock files. Program the
123+
LMK and LMX clocks with the properties of the files.
124+
"""
125+
126+
# Ensure LMK and LMX devices are known
127+
_get_lmclk_devices()
128+
129+
# Get custom ref clock locs
130+
cwd = os.getcwd()
131+
lmk_loc, lmx_loc = _get_custom_lmclks(cwd)
132+
133+
# Get custom ref clock props
134+
clk_props = _get_custom_lmclk_props(lmk_loc, lmx_loc)
135+
136+
# Program custom ref clocks
137+
_program_custom_lmclks(clk_props)
138+

rfsoc_qpsk/qpsk_overlay.py

+3-33
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import ipywidgets as ipw
77
from time import sleep
88

9-
from rfsoc_qpsk import dma_timer, sdr_plots, qpsk_rx, qpsk_tx
9+
from rfsoc_qpsk import dma_timer, sdr_plots, qpsk_rx, qpsk_tx, clocks
1010

1111

1212
class TimerRegistry():
@@ -55,8 +55,6 @@ def __init__(self, bitfile_name=None, init_rf_clks=True, dark_theme=False, prese
5555
bigger font
5656
5757
"""
58-
GEN3 = ['RFSoC4x2', 'ZCU208', 'ZCU216']
59-
GEN1 = ['RFSoC2x2', 'ZCU111']
6058

6159
# Generate default bitfile name
6260
if bitfile_name is None:
@@ -96,14 +94,8 @@ def __init__(self, bitfile_name=None, init_rf_clks=True, dark_theme=False, prese
9694
# Create Overlay
9795
super().__init__(bitfile_name, **kwargs)
9896

99-
# Determine board and set PLL appropriately
97+
# Determine board
10098
board = os.environ['BOARD']
101-
if board in GEN3:
102-
lmk_clk = 245.76
103-
elif board in GEN1:
104-
lmk_clk = 122.88
105-
else:
106-
raise RuntimeError('Platform not supported.') # shouldn't get here
10799

108100
# Extact in-use dataconverter objects with friendly names
109101
self.rf = self.usp_rf_data_converter_0
@@ -132,7 +124,7 @@ def __init__(self, bitfile_name=None, init_rf_clks=True, dark_theme=False, prese
132124

133125
# Start up LMX clock
134126
if init_rf_clks:
135-
xrfclk.set_ref_clks(lmk_clk, 409.6)
127+
clocks.set_custom_lmclks()
136128

137129
# Set sane DAC defaults
138130
self.dac_tile.DynamicPLLConfig(1, 409.6, 1024)
@@ -175,28 +167,6 @@ def __init__(self, bitfile_name=None, init_rf_clks=True, dark_theme=False, prese
175167

176168
self.timers = TimerRegistry()
177169

178-
def init_i2c(self):
179-
"""Initialize the I2C control drivers on RFSoC2x2.
180-
This should happen after a bitstream is loaded since I2C reset
181-
is connected to PL pins. The I2C-related drivers are made loadable
182-
modules so they can be removed or inserted.
183-
"""
184-
module_list = ['i2c_dev', 'i2c_mux_pca954x', 'i2c_mux']
185-
for module in module_list:
186-
cmd = "if lsmod | grep {0}; then rmmod {0}; fi".format(module)
187-
ret = os.system(cmd)
188-
if ret:
189-
raise RuntimeError(
190-
'Removing kernel module {} failed.'.format(module))
191-
192-
module_list.reverse()
193-
for module in module_list:
194-
cmd = "modprobe {}".format(module)
195-
ret = os.system(cmd)
196-
if ret:
197-
raise RuntimeError(
198-
'Inserting kernel module {} failed.'.format(module))
199-
200170
def plot_group(self, group_name, domains, get_time_data, fs, get_freq_data=None, get_const_data=None):
201171
"""Create a group of plots for a given set of data generators.
202172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
R0 (INIT) 0x00160040
2+
R0 0x00143200
3+
R1 0x00143201
4+
R2 0x00140322
5+
R3 0xC0140023
6+
R4 0x40140024
7+
R5 0x80141E05
8+
R6 0x01100006
9+
R7 0x01100007
10+
R8 0x06010008
11+
R9 0x55555549
12+
R10 0x9102410A
13+
R11 0x0401100B
14+
R12 0x1B0C006C
15+
R13 0x2302886D
16+
R14 0x0200000E
17+
R15 0x8000800F
18+
R16 0xC1550410
19+
R24 0x00000058
20+
R25 0x02C9C419
21+
R26 0x8FA8001A
22+
R27 0x10001E1B
23+
R28 0x0021201C
24+
R29 0x0180033D
25+
R30 0x0200033E
26+
R31 0x003F001F
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
R112 0x700000
2+
R111 0x6F0000
3+
R110 0x6E0000
4+
R109 0x6D0000
5+
R108 0x6C0000
6+
R107 0x6B0000
7+
R106 0x6A0000
8+
R105 0x690021
9+
R104 0x680000
10+
R103 0x670000
11+
R102 0x663F80
12+
R101 0x650011
13+
R100 0x640000
14+
R99 0x630000
15+
R98 0x620200
16+
R97 0x610888
17+
R96 0x600000
18+
R95 0x5F0000
19+
R94 0x5E0000
20+
R93 0x5D0000
21+
R92 0x5C0000
22+
R91 0x5B0000
23+
R90 0x5A0000
24+
R89 0x590000
25+
R88 0x580000
26+
R87 0x570000
27+
R86 0x560000
28+
R85 0x55D300
29+
R84 0x540001
30+
R83 0x530000
31+
R82 0x521E00
32+
R81 0x510000
33+
R80 0x506666
34+
R79 0x4F0026
35+
R78 0x4E0003
36+
R77 0x4D0000
37+
R76 0x4C000C
38+
R75 0x4B0980
39+
R74 0x4A0000
40+
R73 0x49003F
41+
R72 0x480001
42+
R71 0x470081
43+
R70 0x46C350
44+
R69 0x450000
45+
R68 0x4403E8
46+
R67 0x430000
47+
R66 0x4201F4
48+
R65 0x410000
49+
R64 0x401388
50+
R63 0x3F0000
51+
R62 0x3E0322
52+
R61 0x3D00A8
53+
R60 0x3C0000
54+
R59 0x3B0001
55+
R58 0x3A8001
56+
R57 0x390020
57+
R56 0x380000
58+
R55 0x370000
59+
R54 0x360000
60+
R53 0x350000
61+
R52 0x340820
62+
R51 0x330080
63+
R50 0x320000
64+
R49 0x314180
65+
R48 0x300300
66+
R47 0x2F0300
67+
R46 0x2E07FC
68+
R45 0x2DC0CC
69+
R44 0x2C0C23
70+
R43 0x2B0000
71+
R42 0x2A0000
72+
R41 0x290000
73+
R40 0x280000
74+
R39 0x270001
75+
R38 0x260000
76+
R37 0x250304
77+
R36 0x240050
78+
R35 0x230004
79+
R34 0x220000
80+
R33 0x211E21
81+
R32 0x200393
82+
R31 0x1F43EC
83+
R30 0x1E318C
84+
R29 0x1D318C
85+
R28 0x1C0488
86+
R27 0x1B0002
87+
R26 0x1A0DB0
88+
R25 0x190624
89+
R24 0x18071A
90+
R23 0x17007C
91+
R22 0x160001
92+
R21 0x150401
93+
R20 0x14E048
94+
R19 0x1327B7
95+
R18 0x120064
96+
R17 0x11012C
97+
R16 0x100080
98+
R15 0x0F064F
99+
R14 0x0E1E70
100+
R13 0x0D4000
101+
R12 0x0C5001
102+
R11 0x0B0018
103+
R10 0x0A10D8
104+
R9 0x090604
105+
R8 0x082000
106+
R7 0x0740B2
107+
R6 0x06C802
108+
R5 0x0500C8
109+
R4 0x040A43
110+
R3 0x030642
111+
R2 0x020500
112+
R1 0x010808
113+
R0 0x00249C

0 commit comments

Comments
 (0)