18
18
19
19
from adafruit_bus_device import i2c_device
20
20
21
+ try :
22
+ import typing # pylint: disable=unused-import
23
+ from busio import I2C
24
+ except ImportError :
25
+ pass
21
26
22
27
__version__ = "0.0.0+auto.0"
23
28
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_SI5351.git"
@@ -141,18 +146,20 @@ class SI5351:
141
146
# of this, PLL A and PLL B. Each can be the source for a clock output
142
147
# (with further division performed per clock output).
143
148
class _PLL :
144
- def __init__ (self , si5351 , base_address , clock_control_enabled ):
149
+ def __init__ (
150
+ self , si5351 : "SI5351" , base_address : int , clock_control_enabled : bool
151
+ ) -> None :
145
152
self ._si5351 = si5351
146
153
self ._base = base_address
147
154
self ._frequency = None
148
155
self .clock_control_enabled = clock_control_enabled
149
156
150
157
@property
151
- def frequency (self ):
158
+ def frequency (self ) -> int :
152
159
"""Get the frequency of the PLL in hertz."""
153
160
return self ._frequency
154
161
155
- def _configure_registers (self , p1 , p2 , p3 ) :
162
+ def _configure_registers (self , p1 : int , p2 : int , p3 : int ) -> None :
156
163
# Update PLL registers.
157
164
# The datasheet is a nightmare of typos and inconsistencies here!
158
165
self ._si5351 ._write_u8 (self ._base , (p3 & 0x0000FF00 ) >> 8 )
@@ -168,7 +175,7 @@ def _configure_registers(self, p1, p2, p3):
168
175
# Reset both PLLs.
169
176
self ._si5351 ._write_u8 (_SI5351_REGISTER_177_PLL_RESET , (1 << 7 ) | (1 << 5 ))
170
177
171
- def configure_integer (self , multiplier ) :
178
+ def configure_integer (self , multiplier : int ) -> None :
172
179
"""Configure the PLL with a simple integer multiplier for the most
173
180
accurate (but more limited) PLL frequency generation.
174
181
"""
@@ -188,8 +195,10 @@ def configure_integer(self, multiplier):
188
195
# https://github.com/adafruit/circuitpython/issues/572
189
196
self ._frequency = fvco
190
197
191
- def configure_fractional (self , multiplier , numerator , denominator ):
192
- """Configure the PLL with a fractional multipler specified by
198
+ def configure_fractional (
199
+ self , multiplier : int , numerator : int , denominator : int
200
+ ) -> None :
201
+ """Configure the PLL with a fractional multiplier specified by
193
202
multiplier and numerator/denominator. This is less accurate and
194
203
susceptible to jitter but allows a larger range of PLL frequencies.
195
204
"""
@@ -226,7 +235,13 @@ def configure_fractional(self, multiplier, numerator, denominator):
226
235
# these and they can each be independently configured to use a specific
227
236
# PLL source and have their own divider on that PLL.
228
237
class _Clock :
229
- def __init__ (self , si5351 , base_address , control_register , r_register ):
238
+ def __init__ (
239
+ self ,
240
+ si5351 : "SI5351" ,
241
+ base_address : int ,
242
+ control_register : int ,
243
+ r_register : int ,
244
+ ) -> None :
230
245
self ._si5351 = si5351
231
246
self ._base = base_address
232
247
self ._control = control_register
@@ -235,7 +250,7 @@ def __init__(self, si5351, base_address, control_register, r_register):
235
250
self ._divider = None
236
251
237
252
@property
238
- def frequency (self ):
253
+ def frequency (self ) -> float :
239
254
"""Get the frequency of this clock output in hertz. This is
240
255
computed based on the configured PLL, clock divider, and R divider.
241
256
"""
@@ -269,7 +284,7 @@ def frequency(self):
269
284
raise RuntimeError ("Unexpected R divider!" )
270
285
271
286
@property
272
- def r_divider (self ):
287
+ def r_divider (self ) -> int :
273
288
"""Get and set the R divider value, must be one of:
274
289
- R_DIV_1: divider of 1
275
290
- R_DIV_2: divider of 2
@@ -284,7 +299,7 @@ def r_divider(self):
284
299
return (reg_value >> 4 ) & 0x07
285
300
286
301
@r_divider .setter
287
- def r_divider (self , divider ) :
302
+ def r_divider (self , divider : int ) -> None :
288
303
if divider > 7 or divider < 0 :
289
304
raise Exception ("Divider must in range 0 to 7." )
290
305
reg_value = self ._si5351 ._read_u8 (self ._r )
@@ -294,7 +309,7 @@ def r_divider(self, divider):
294
309
reg_value |= divider
295
310
self ._si5351 ._write_u8 (self ._r , reg_value )
296
311
297
- def _configure_registers (self , p1 , p2 , p3 ) :
312
+ def _configure_registers (self , p1 : int , p2 : int , p3 : int ) -> None :
298
313
# Update MSx registers.
299
314
self ._si5351 ._write_u8 (self ._base , (p3 & 0x0000FF00 ) >> 8 )
300
315
self ._si5351 ._write_u8 (self ._base + 1 , (p3 & 0x000000FF ))
@@ -307,7 +322,9 @@ def _configure_registers(self, p1, p2, p3):
307
322
self ._si5351 ._write_u8 (self ._base + 6 , (p2 & 0x0000FF00 ) >> 8 )
308
323
self ._si5351 ._write_u8 (self ._base + 7 , (p2 & 0x000000FF ))
309
324
310
- def configure_integer (self , pll , divider , inverted = False ):
325
+ def configure_integer (
326
+ self , pll : "PLL" , divider : int , inverted : bool = False
327
+ ) -> None :
311
328
"""Configure the clock output with the specified PLL source
312
329
(should be a PLL instance on the SI5351 class) and specific integer
313
330
divider. This is the most accurate way to set the clock output
@@ -339,10 +356,15 @@ def configure_integer(self, pll, divider, inverted=False):
339
356
self ._divider = divider
340
357
341
358
def configure_fractional (
342
- self , pll , divider , numerator , denominator , inverted = False
343
- ):
359
+ self ,
360
+ pll : "PLL" ,
361
+ divider : int ,
362
+ numerator : int ,
363
+ denominator : int ,
364
+ inverted : bool = False ,
365
+ ) -> None :
344
366
"""Configure the clock output with the specified PLL source
345
- (should be a PLL instance on the SI5351 class) and specifiec
367
+ (should be a PLL instance on the SI5351 class) and specific
346
368
fractional divider with numerator/denominator. Again this is less
347
369
accurate but has a wider range of output frequencies.
348
370
"""
@@ -386,7 +408,7 @@ def configure_fractional(
386
408
# This is not thread-safe or re-entrant by design!
387
409
_BUFFER = bytearray (2 )
388
410
389
- def __init__ (self , i2c , * , address = _SI5351_ADDRESS ):
411
+ def __init__ (self , i2c : I2C , * , address : int = _SI5351_ADDRESS ) -> None :
390
412
self ._device = i2c_device .I2CDevice (i2c , address )
391
413
# Setup the SI5351.
392
414
# Disable all outputs setting CLKx_DIS high.
@@ -423,38 +445,38 @@ def __init__(self, i2c, *, address=_SI5351_ADDRESS):
423
445
_SI5351_REGISTER_60_MULTISYNTH2_PARAMETERS_3 ,
424
446
)
425
447
426
- def _read_u8 (self , address ) :
448
+ def _read_u8 (self , address : int ) -> int :
427
449
# Read an 8-bit unsigned value from the specified 8-bit address.
428
450
with self ._device as i2c :
429
451
self ._BUFFER [0 ] = address & 0xFF
430
452
i2c .write (self ._BUFFER , end = 1 )
431
453
i2c .readinto (self ._BUFFER , end = 1 )
432
454
return self ._BUFFER [0 ]
433
455
434
- def _write_u8 (self , address , val ) :
456
+ def _write_u8 (self , address : int , val : int ) -> None :
435
457
# Write an 8-bit unsigned value to the specified 8-bit address.
436
458
with self ._device as i2c :
437
459
self ._BUFFER [0 ] = address & 0xFF
438
460
self ._BUFFER [1 ] = val & 0xFF
439
461
i2c .write (self ._BUFFER , end = 2 )
440
462
441
463
@property
442
- def outputs_enabled (self ):
464
+ def outputs_enabled (self ) -> bool :
443
465
"""Get and set the enabled state of all clock outputs as a boolean.
444
466
If true then all clock outputs are enabled, and if false then they are
445
467
all disabled.
446
468
"""
447
469
return self ._read_u8 (_SI5351_REGISTER_3_OUTPUT_ENABLE_CONTROL ) == 0xFF
448
470
449
471
@outputs_enabled .setter
450
- def outputs_enabled (self , val ) :
472
+ def outputs_enabled (self , val : bool ) -> None :
451
473
if not val :
452
474
self ._write_u8 (_SI5351_REGISTER_3_OUTPUT_ENABLE_CONTROL , 0xFF )
453
475
else :
454
476
self ._write_u8 (_SI5351_REGISTER_3_OUTPUT_ENABLE_CONTROL , 0x00 )
455
477
self .reset_plls ()
456
478
457
- def reset_plls (self ):
479
+ def reset_plls (self ) -> None :
458
480
"""Reset both PLLs. This is required when the phase between clocks
459
481
needs to be non-random.
460
482
0 commit comments