@@ -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.
3442regs = {
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
106118ANN_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