Skip to content

Commit a6ec014

Browse files
committed
adf435x: shuffle register description table
Move table columns, put the bit field position to the front before the name to get a less fragile visual appearance. All fields have a position and a name (of variable length), some of them have a "parser" (actually a formatter for their content). Address Python style while we are here: Prefer tuples over lists for immutable data. Add trailing commas to reduce future diff sizes. Add a TODO comment about optional content checkers. The current decoder implementation lets invalid register data pass unnoticed. [ see a word diff for the commit's essence ]
1 parent 4d86276 commit a6ec014

File tree

1 file changed

+89
-63
lines changed

1 file changed

+89
-63
lines changed

decoders/adf435x/pd.py

Lines changed: 89 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -27,80 +27,92 @@ def output_power(v):
2727
return '{:+d}dBm'.format([-4, -1, 2, 5][v])
2828

2929
# Notes on the implementation:
30+
# - A register's description is an iterable of tuples which contain:
31+
# The starting bit position, the bit count, the name of a field, and
32+
# an optional parser which interprets the field's content. Parser are
33+
# expected to yield a single text string when they exist. Other types
34+
# of output are passed to Python's .format() routine as is.
35+
# - TODO Add support for the creation of formatted values, as well as
36+
# optional warnings from register field parsers? The current approach
37+
# lets invalid register content go unnoticed.
3038
# - Bit fields' width in registers determines the range of indices in
3139
# table/tuple lookups. Keep the implementation as robust as possible
3240
# during future maintenance. Avoid Python runtime errors when adjusting
3341
# the decoder.
3442
regs = {
35-
# reg: name offset width parser
36-
0: [
37-
('FRAC', 3, 12, None),
38-
('INT', 15, 16, lambda v: 'Not Allowed' if v < 32 else v)
39-
],
40-
1: [
41-
('MOD', 3, 12, None),
42-
('Phase', 15, 12, None),
43-
('Prescalar', 27, 1, lambda v: ['4/5', '8/9'][v]),
44-
('Phase Adjust', 28, 1, lambda v: ['Off', 'On'][v]),
45-
],
46-
2: [
47-
('Counter Reset', 3, 1, disabled_enabled),
48-
('Charge Pump Three-State', 4, 1, disabled_enabled),
49-
('Power-Down', 5, 1, disabled_enabled),
50-
('PD Polarity', 6, 1, lambda v: ['Negative', 'Positive'][v]),
51-
('LDP', 7, 1, lambda v: ['10ns', '6ns'][v]),
52-
('LDF', 8, 1, lambda v: ['FRAC-N', 'INT-N'][v]),
53-
('Charge Pump Current Setting', 9, 4, lambda v: '{curr:0.2f}mA @ 5.1kΩ'.format(
54-
curr = (
43+
# Register description fields:
44+
# offset, width, name, parser.
45+
0: (
46+
( 3, 12, 'FRAC'),
47+
# Lower limit is 23 not 32?
48+
(15, 16, 'INT', lambda v: 'Not Allowed' if v < 32 else v),
49+
),
50+
1: (
51+
( 3, 12, 'MOD'),
52+
(15, 12, 'Phase'),
53+
(27, 1, 'Prescalar', lambda v: ('4/5', '8/9',)[v]),
54+
(28, 1, 'Phase Adjust', lambda v: ('Off', 'On',)[v]),
55+
),
56+
2: (
57+
( 3, 1, 'Counter Reset', disabled_enabled),
58+
( 4, 1, 'Charge Pump Three-State', disabled_enabled),
59+
( 5, 1, 'Power-Down', disabled_enabled),
60+
( 6, 1, 'PD Polarity', lambda v: ('Negative', 'Positive',)[v]),
61+
( 7, 1, 'LDP', lambda v: ('10ns', '6ns',)[v]),
62+
( 8, 1, 'LDF', lambda v: ('FRAC-N', 'INT-N',)[v]),
63+
( 9, 4, 'Charge Pump Current Setting',
64+
lambda v: '{curr:0.2f}mA @ 5.1kΩ'.format(curr = (
5565
0.31, 0.63, 0.94, 1.25, 1.56, 1.88, 2.19, 2.50,
5666
2.81, 3.13, 3.44, 3.75, 4.06, 4.38, 4.69, 5.00,
5767
)[v])),
58-
('Double Buffer', 13, 1, disabled_enabled),
59-
('R Counter', 14, 10, None),
60-
('RDIV2', 24, 1, disabled_enabled),
61-
('Reference Doubler', 25, 1, disabled_enabled),
62-
('MUXOUT', 26, 3, lambda v: '{text}'.format(
63-
text = (
68+
(13, 1, 'Double Buffer', disabled_enabled),
69+
(14, 10, 'R Counter'),
70+
(24, 1, 'RDIV2', disabled_enabled),
71+
(25, 1, 'Reference Doubler', disabled_enabled),
72+
(26, 3, 'MUXOUT',
73+
lambda v: '{text}'.format(text = (
6474
'Three-State Output', 'DVdd', 'DGND',
6575
'R Counter Output', 'N Divider Output',
6676
'Analog Lock Detect', 'Digital Lock Detect',
67-
'Reserved'
77+
'Reserved',
6878
)[v])),
69-
('Low Noise and Low Spur Modes', 29, 2, lambda v: '{text}'.format(
70-
text = (
71-
'Low Noise Mode', 'Reserved', 'Reserved', 'Low Spur Mode'
79+
(29, 2, 'Low Noise and Low Spur Modes',
80+
lambda v: '{text}'.format(text = (
81+
'Low Noise Mode', 'Reserved', 'Reserved', 'Low Spur Mode',
7282
)[v])),
73-
],
74-
3: [
75-
('Clock Divider', 3, 12, None),
76-
('Clock Divider Mode', 15, 2, lambda v: '{text}'.format(
77-
text = (
78-
'Clock Divider Off', 'Fast Lock Enable', 'Resync Enable', 'Reserved'
83+
),
84+
3: (
85+
( 3, 12, 'Clock Divider'),
86+
(15, 2, 'Clock Divider Mode',
87+
lambda v: '{text}'.format(text = (
88+
'Clock Divider Off', 'Fast Lock Enable',
89+
'Resync Enable', 'Reserved',
7990
)[v])),
80-
('CSR Enable', 18, 1, disabled_enabled),
81-
('Charge Cancellation', 21, 1, disabled_enabled),
82-
('ABP', 22, 1, lambda v: ['6ns (FRAC-N)', '3ns (INT-N)'][v]),
83-
('Band Select Clock Mode', 23, 1, lambda v: ['Low', 'High'][v])
84-
],
85-
4: [
86-
('Output Power', 3, 2, output_power),
87-
('Output Enable', 5, 1, disabled_enabled),
88-
('AUX Output Power', 6, 2, output_power),
89-
('AUX Output Select', 8, 1, lambda v: ['Divided Output', 'Fundamental'][v]),
90-
('AUX Output Enable', 9, 1, disabled_enabled),
91-
('MTLD', 10, 1, disabled_enabled),
92-
('VCO Power-Down', 11, 1, lambda v:
93-
'VCO Powered {updown}'.format(updown = 'Down' if v else 'Up')),
94-
('Band Select Clock Divider', 12, 8, None),
95-
('RF Divider Select', 20, 3, lambda v: '÷{:d}'.format(2 ** v)),
96-
('Feedback Select', 23, 1, lambda v: ['Divided', 'Fundamental'][v]),
97-
],
98-
5: [
99-
('LD Pin Mode', 22, 2, lambda v: '{text}'.format(
100-
text = (
91+
(18, 1, 'CSR Enable', disabled_enabled),
92+
(21, 1, 'Charge Cancellation', disabled_enabled),
93+
(22, 1, 'ABP', lambda v: ('6ns (FRAC-N)', '3ns (INT-N)',)[v]),
94+
(23, 1, 'Band Select Clock Mode', lambda v: ('Low', 'High',)[v]),
95+
),
96+
4: (
97+
( 3, 2, 'Output Power', output_power),
98+
( 5, 1, 'Output Enable', disabled_enabled),
99+
( 6, 2, 'AUX Output Power', output_power),
100+
( 8, 1, 'AUX Output Select',
101+
lambda v: ('Divided Output', 'Fundamental',)[v]),
102+
( 9, 1, 'AUX Output Enable', disabled_enabled),
103+
(10, 1, 'MTLD', disabled_enabled),
104+
(11, 1, 'VCO Power-Down',
105+
lambda v: 'VCO Powered {ud}'.format(ud = 'Down' if v else 'Up')),
106+
(12, 8, 'Band Select Clock Divider'),
107+
(20, 3, 'RF Divider Select', lambda v: '÷{:d}'.format(2 ** v)),
108+
(23, 1, 'Feedback Select', lambda v: ('Divided', 'Fundamental',)[v]),
109+
),
110+
5: (
111+
(22, 2, 'LD Pin Mode',
112+
lambda v: '{text}'.format(text = (
101113
'Low', 'Digital Lock Detect', 'Low', 'High',
102114
)[v])),
103-
]
115+
),
104116
}
105117

106118
ANN_REG = 0
@@ -145,12 +157,18 @@ def decode_bits(self, offset, width):
145157
value = bitpack_lsb(bits, 0)
146158
return ( value, ( ss, es, ))
147159

148-
def decode_field(self, name, offset, width, parser):
160+
def decode_field(self, name, offset, width, parser = None):
149161
'''Interpret a bit field. Emits an annotation.'''
162+
# Get the register field's content and position.
150163
val, ( ss, es, ) = self.decode_bits(offset, width)
151-
val = parser(val) if parser else '{}'.format(val)
152-
text = ['{name}: {val}'.format(name = name, val = val)]
153-
self.putg(ss, es, ANN_REG, text)
164+
# Have the field's content formatted, emit an annotation.
165+
formatted = parser(val) if parser else '{}'.format(val)
166+
if formatted is not None:
167+
text = ['{name}: {val}'.format(name = name, val = formatted)]
168+
else:
169+
text = ['{name}'.format(name = name)]
170+
if text:
171+
self.putg(ss, es, ANN_REG, text)
154172

155173
def decode_word(self, ss, es, bits):
156174
'''Interpret a 32bit word after accumulation completes.'''
@@ -181,7 +199,15 @@ def decode_word(self, ss, es, bits):
181199
if not field_descs:
182200
return
183201
for field_desc in field_descs:
184-
self.decode_field(*field_desc)
202+
parser = None
203+
if len(field_desc) == 3:
204+
start, count, name, = field_desc
205+
elif len(field_desc) == 4:
206+
start, count, name, parser = field_desc
207+
else:
208+
# Unsupported regs{} syntax, programmer's error.
209+
return
210+
self.decode_field(name, start, count, parser)
185211

186212
def decode(self, ss, es, data):
187213
ptype, _, _ = data

0 commit comments

Comments
 (0)