diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fff3aa9..1dad804 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,7 @@ jobs: source actions-ci/install.sh - name: Pip install pylint, black, & Sphinx run: | - pip install --force-reinstall pylint==1.9.2 black==19.10b0 Sphinx sphinx-rtd-theme + pip install --force-reinstall pylint black==19.10b0 Sphinx sphinx-rtd-theme - name: Library version run: git describe --dirty --always --tags - name: PyLint diff --git a/adafruit_si5351.py b/adafruit_si5351.py index 3e79f12..c4d1137 100644 --- a/adafruit_si5351.py +++ b/adafruit_si5351.py @@ -40,112 +40,113 @@ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_SI5351.git" -#pylint: disable=bad-whitespace +# pylint: disable=bad-whitespace # Internal constants: -_SI5351_ADDRESS = const(0x60) # Assumes ADDR pin = low -_SI5351_READBIT = const(0x01) -_SI5351_CRYSTAL_FREQUENCY = 25000000.0 # Fixed 25mhz crystal on board. -_SI5351_REGISTER_0_DEVICE_STATUS = const(0) -_SI5351_REGISTER_1_INTERRUPT_STATUS_STICKY = const(1) -_SI5351_REGISTER_2_INTERRUPT_STATUS_MASK = const(2) -_SI5351_REGISTER_3_OUTPUT_ENABLE_CONTROL = const(3) -_SI5351_REGISTER_9_OEB_PIN_ENABLE_CONTROL = const(9) -_SI5351_REGISTER_15_PLL_INPUT_SOURCE = const(15) -_SI5351_REGISTER_16_CLK0_CONTROL = const(16) -_SI5351_REGISTER_17_CLK1_CONTROL = const(17) -_SI5351_REGISTER_18_CLK2_CONTROL = const(18) -_SI5351_REGISTER_19_CLK3_CONTROL = const(19) -_SI5351_REGISTER_20_CLK4_CONTROL = const(20) -_SI5351_REGISTER_21_CLK5_CONTROL = const(21) -_SI5351_REGISTER_22_CLK6_CONTROL = const(22) -_SI5351_REGISTER_23_CLK7_CONTROL = const(23) -_SI5351_REGISTER_24_CLK3_0_DISABLE_STATE = const(24) -_SI5351_REGISTER_25_CLK7_4_DISABLE_STATE = const(25) -_SI5351_REGISTER_42_MULTISYNTH0_PARAMETERS_1 = const(42) -_SI5351_REGISTER_43_MULTISYNTH0_PARAMETERS_2 = const(43) -_SI5351_REGISTER_44_MULTISYNTH0_PARAMETERS_3 = const(44) -_SI5351_REGISTER_45_MULTISYNTH0_PARAMETERS_4 = const(45) -_SI5351_REGISTER_46_MULTISYNTH0_PARAMETERS_5 = const(46) -_SI5351_REGISTER_47_MULTISYNTH0_PARAMETERS_6 = const(47) -_SI5351_REGISTER_48_MULTISYNTH0_PARAMETERS_7 = const(48) -_SI5351_REGISTER_49_MULTISYNTH0_PARAMETERS_8 = const(49) -_SI5351_REGISTER_50_MULTISYNTH1_PARAMETERS_1 = const(50) -_SI5351_REGISTER_51_MULTISYNTH1_PARAMETERS_2 = const(51) -_SI5351_REGISTER_52_MULTISYNTH1_PARAMETERS_3 = const(52) -_SI5351_REGISTER_53_MULTISYNTH1_PARAMETERS_4 = const(53) -_SI5351_REGISTER_54_MULTISYNTH1_PARAMETERS_5 = const(54) -_SI5351_REGISTER_55_MULTISYNTH1_PARAMETERS_6 = const(55) -_SI5351_REGISTER_56_MULTISYNTH1_PARAMETERS_7 = const(56) -_SI5351_REGISTER_57_MULTISYNTH1_PARAMETERS_8 = const(57) -_SI5351_REGISTER_58_MULTISYNTH2_PARAMETERS_1 = const(58) -_SI5351_REGISTER_59_MULTISYNTH2_PARAMETERS_2 = const(59) -_SI5351_REGISTER_60_MULTISYNTH2_PARAMETERS_3 = const(60) -_SI5351_REGISTER_61_MULTISYNTH2_PARAMETERS_4 = const(61) -_SI5351_REGISTER_62_MULTISYNTH2_PARAMETERS_5 = const(62) -_SI5351_REGISTER_63_MULTISYNTH2_PARAMETERS_6 = const(63) -_SI5351_REGISTER_64_MULTISYNTH2_PARAMETERS_7 = const(64) -_SI5351_REGISTER_65_MULTISYNTH2_PARAMETERS_8 = const(65) -_SI5351_REGISTER_66_MULTISYNTH3_PARAMETERS_1 = const(66) -_SI5351_REGISTER_67_MULTISYNTH3_PARAMETERS_2 = const(67) -_SI5351_REGISTER_68_MULTISYNTH3_PARAMETERS_3 = const(68) -_SI5351_REGISTER_69_MULTISYNTH3_PARAMETERS_4 = const(69) -_SI5351_REGISTER_70_MULTISYNTH3_PARAMETERS_5 = const(70) -_SI5351_REGISTER_71_MULTISYNTH3_PARAMETERS_6 = const(71) -_SI5351_REGISTER_72_MULTISYNTH3_PARAMETERS_7 = const(72) -_SI5351_REGISTER_73_MULTISYNTH3_PARAMETERS_8 = const(73) -_SI5351_REGISTER_74_MULTISYNTH4_PARAMETERS_1 = const(74) -_SI5351_REGISTER_75_MULTISYNTH4_PARAMETERS_2 = const(75) -_SI5351_REGISTER_76_MULTISYNTH4_PARAMETERS_3 = const(76) -_SI5351_REGISTER_77_MULTISYNTH4_PARAMETERS_4 = const(77) -_SI5351_REGISTER_78_MULTISYNTH4_PARAMETERS_5 = const(78) -_SI5351_REGISTER_79_MULTISYNTH4_PARAMETERS_6 = const(79) -_SI5351_REGISTER_80_MULTISYNTH4_PARAMETERS_7 = const(80) -_SI5351_REGISTER_81_MULTISYNTH4_PARAMETERS_8 = const(81) -_SI5351_REGISTER_82_MULTISYNTH5_PARAMETERS_1 = const(82) -_SI5351_REGISTER_83_MULTISYNTH5_PARAMETERS_2 = const(83) -_SI5351_REGISTER_84_MULTISYNTH5_PARAMETERS_3 = const(84) -_SI5351_REGISTER_85_MULTISYNTH5_PARAMETERS_4 = const(85) -_SI5351_REGISTER_86_MULTISYNTH5_PARAMETERS_5 = const(86) -_SI5351_REGISTER_87_MULTISYNTH5_PARAMETERS_6 = const(87) -_SI5351_REGISTER_88_MULTISYNTH5_PARAMETERS_7 = const(88) -_SI5351_REGISTER_89_MULTISYNTH5_PARAMETERS_8 = const(89) -_SI5351_REGISTER_90_MULTISYNTH6_PARAMETERS = const(90) -_SI5351_REGISTER_91_MULTISYNTH7_PARAMETERS = const(91) -_SI5351_REGISTER_092_CLOCK_6_7_OUTPUT_DIVIDER = const(92) -_SI5351_REGISTER_165_CLK0_INITIAL_PHASE_OFFSET = const(165) -_SI5351_REGISTER_166_CLK1_INITIAL_PHASE_OFFSET = const(166) -_SI5351_REGISTER_167_CLK2_INITIAL_PHASE_OFFSET = const(167) -_SI5351_REGISTER_168_CLK3_INITIAL_PHASE_OFFSET = const(168) -_SI5351_REGISTER_169_CLK4_INITIAL_PHASE_OFFSET = const(169) -_SI5351_REGISTER_170_CLK5_INITIAL_PHASE_OFFSET = const(170) -_SI5351_REGISTER_177_PLL_RESET = const(177) -_SI5351_REGISTER_183_CRYSTAL_INTERNAL_LOAD_CAPACITANCE = const(183) +_SI5351_ADDRESS = const(0x60) # Assumes ADDR pin = low +_SI5351_READBIT = const(0x01) +_SI5351_CRYSTAL_FREQUENCY = 25000000.0 # Fixed 25mhz crystal on board. +_SI5351_REGISTER_0_DEVICE_STATUS = const(0) +_SI5351_REGISTER_1_INTERRUPT_STATUS_STICKY = const(1) +_SI5351_REGISTER_2_INTERRUPT_STATUS_MASK = const(2) +_SI5351_REGISTER_3_OUTPUT_ENABLE_CONTROL = const(3) +_SI5351_REGISTER_9_OEB_PIN_ENABLE_CONTROL = const(9) +_SI5351_REGISTER_15_PLL_INPUT_SOURCE = const(15) +_SI5351_REGISTER_16_CLK0_CONTROL = const(16) +_SI5351_REGISTER_17_CLK1_CONTROL = const(17) +_SI5351_REGISTER_18_CLK2_CONTROL = const(18) +_SI5351_REGISTER_19_CLK3_CONTROL = const(19) +_SI5351_REGISTER_20_CLK4_CONTROL = const(20) +_SI5351_REGISTER_21_CLK5_CONTROL = const(21) +_SI5351_REGISTER_22_CLK6_CONTROL = const(22) +_SI5351_REGISTER_23_CLK7_CONTROL = const(23) +_SI5351_REGISTER_24_CLK3_0_DISABLE_STATE = const(24) +_SI5351_REGISTER_25_CLK7_4_DISABLE_STATE = const(25) +_SI5351_REGISTER_42_MULTISYNTH0_PARAMETERS_1 = const(42) +_SI5351_REGISTER_43_MULTISYNTH0_PARAMETERS_2 = const(43) +_SI5351_REGISTER_44_MULTISYNTH0_PARAMETERS_3 = const(44) +_SI5351_REGISTER_45_MULTISYNTH0_PARAMETERS_4 = const(45) +_SI5351_REGISTER_46_MULTISYNTH0_PARAMETERS_5 = const(46) +_SI5351_REGISTER_47_MULTISYNTH0_PARAMETERS_6 = const(47) +_SI5351_REGISTER_48_MULTISYNTH0_PARAMETERS_7 = const(48) +_SI5351_REGISTER_49_MULTISYNTH0_PARAMETERS_8 = const(49) +_SI5351_REGISTER_50_MULTISYNTH1_PARAMETERS_1 = const(50) +_SI5351_REGISTER_51_MULTISYNTH1_PARAMETERS_2 = const(51) +_SI5351_REGISTER_52_MULTISYNTH1_PARAMETERS_3 = const(52) +_SI5351_REGISTER_53_MULTISYNTH1_PARAMETERS_4 = const(53) +_SI5351_REGISTER_54_MULTISYNTH1_PARAMETERS_5 = const(54) +_SI5351_REGISTER_55_MULTISYNTH1_PARAMETERS_6 = const(55) +_SI5351_REGISTER_56_MULTISYNTH1_PARAMETERS_7 = const(56) +_SI5351_REGISTER_57_MULTISYNTH1_PARAMETERS_8 = const(57) +_SI5351_REGISTER_58_MULTISYNTH2_PARAMETERS_1 = const(58) +_SI5351_REGISTER_59_MULTISYNTH2_PARAMETERS_2 = const(59) +_SI5351_REGISTER_60_MULTISYNTH2_PARAMETERS_3 = const(60) +_SI5351_REGISTER_61_MULTISYNTH2_PARAMETERS_4 = const(61) +_SI5351_REGISTER_62_MULTISYNTH2_PARAMETERS_5 = const(62) +_SI5351_REGISTER_63_MULTISYNTH2_PARAMETERS_6 = const(63) +_SI5351_REGISTER_64_MULTISYNTH2_PARAMETERS_7 = const(64) +_SI5351_REGISTER_65_MULTISYNTH2_PARAMETERS_8 = const(65) +_SI5351_REGISTER_66_MULTISYNTH3_PARAMETERS_1 = const(66) +_SI5351_REGISTER_67_MULTISYNTH3_PARAMETERS_2 = const(67) +_SI5351_REGISTER_68_MULTISYNTH3_PARAMETERS_3 = const(68) +_SI5351_REGISTER_69_MULTISYNTH3_PARAMETERS_4 = const(69) +_SI5351_REGISTER_70_MULTISYNTH3_PARAMETERS_5 = const(70) +_SI5351_REGISTER_71_MULTISYNTH3_PARAMETERS_6 = const(71) +_SI5351_REGISTER_72_MULTISYNTH3_PARAMETERS_7 = const(72) +_SI5351_REGISTER_73_MULTISYNTH3_PARAMETERS_8 = const(73) +_SI5351_REGISTER_74_MULTISYNTH4_PARAMETERS_1 = const(74) +_SI5351_REGISTER_75_MULTISYNTH4_PARAMETERS_2 = const(75) +_SI5351_REGISTER_76_MULTISYNTH4_PARAMETERS_3 = const(76) +_SI5351_REGISTER_77_MULTISYNTH4_PARAMETERS_4 = const(77) +_SI5351_REGISTER_78_MULTISYNTH4_PARAMETERS_5 = const(78) +_SI5351_REGISTER_79_MULTISYNTH4_PARAMETERS_6 = const(79) +_SI5351_REGISTER_80_MULTISYNTH4_PARAMETERS_7 = const(80) +_SI5351_REGISTER_81_MULTISYNTH4_PARAMETERS_8 = const(81) +_SI5351_REGISTER_82_MULTISYNTH5_PARAMETERS_1 = const(82) +_SI5351_REGISTER_83_MULTISYNTH5_PARAMETERS_2 = const(83) +_SI5351_REGISTER_84_MULTISYNTH5_PARAMETERS_3 = const(84) +_SI5351_REGISTER_85_MULTISYNTH5_PARAMETERS_4 = const(85) +_SI5351_REGISTER_86_MULTISYNTH5_PARAMETERS_5 = const(86) +_SI5351_REGISTER_87_MULTISYNTH5_PARAMETERS_6 = const(87) +_SI5351_REGISTER_88_MULTISYNTH5_PARAMETERS_7 = const(88) +_SI5351_REGISTER_89_MULTISYNTH5_PARAMETERS_8 = const(89) +_SI5351_REGISTER_90_MULTISYNTH6_PARAMETERS = const(90) +_SI5351_REGISTER_91_MULTISYNTH7_PARAMETERS = const(91) +_SI5351_REGISTER_092_CLOCK_6_7_OUTPUT_DIVIDER = const(92) +_SI5351_REGISTER_165_CLK0_INITIAL_PHASE_OFFSET = const(165) +_SI5351_REGISTER_166_CLK1_INITIAL_PHASE_OFFSET = const(166) +_SI5351_REGISTER_167_CLK2_INITIAL_PHASE_OFFSET = const(167) +_SI5351_REGISTER_168_CLK3_INITIAL_PHASE_OFFSET = const(168) +_SI5351_REGISTER_169_CLK4_INITIAL_PHASE_OFFSET = const(169) +_SI5351_REGISTER_170_CLK5_INITIAL_PHASE_OFFSET = const(170) +_SI5351_REGISTER_177_PLL_RESET = const(177) +_SI5351_REGISTER_183_CRYSTAL_INTERNAL_LOAD_CAPACITANCE = const(183) # User-facing constants: -R_DIV_1 = 0 -R_DIV_2 = 1 -R_DIV_4 = 2 -R_DIV_8 = 3 -R_DIV_16 = 4 -R_DIV_32 = 5 -R_DIV_64 = 6 +R_DIV_1 = 0 +R_DIV_2 = 1 +R_DIV_4 = 2 +R_DIV_8 = 3 +R_DIV_16 = 4 +R_DIV_32 = 5 +R_DIV_64 = 6 R_DIV_128 = 7 -#pylint: enable=bad-whitespace +# pylint: enable=bad-whitespace # Disable invalid name because p1, p2, p3 variables are false positives. # These are legitimate register names and adding more characters obfuscates # the intention of the code. -#pylint: disable=invalid-name +# pylint: disable=invalid-name # Disable protected access warning because inner classes by design need and use # access to protected members. -#pylint: disable=protected-access +# pylint: disable=protected-access # Another silly pylint check to disable, it has no context of the complexity # of R divider values and explicit unrolling of them into multiple if cases # and return statements. Disable. -#pylint: disable=too-many-return-statements +# pylint: disable=too-many-return-statements + class SI5351: """SI5351 clock generator. Initialize this class by specifying: @@ -159,7 +160,6 @@ class SI5351: # of this, PLL A and PLL B. Each can be the source for a clock output # (with further division performed per clock output). class _PLL: - def __init__(self, si5351, base_address, clock_control_enabled): self._si5351 = si5351 self._base = base_address @@ -175,16 +175,17 @@ def _configure_registers(self, p1, p2, p3): # Update PLL registers. # The datasheet is a nightmare of typos and inconsistencies here! self._si5351._write_u8(self._base, (p3 & 0x0000FF00) >> 8) - self._si5351._write_u8(self._base+1, (p3 & 0x000000FF)) - self._si5351._write_u8(self._base+2, (p1 & 0x00030000) >> 16) - self._si5351._write_u8(self._base+3, (p1 & 0x0000FF00) >> 8) - self._si5351._write_u8(self._base+4, (p1 & 0x000000FF)) - self._si5351._write_u8(self._base+5, ((p3 & 0x000F0000) >> 12) | \ - ((p2 & 0x000F0000) >> 16)) - self._si5351._write_u8(self._base+6, (p2 & 0x0000FF00) >> 8) - self._si5351._write_u8(self._base+7, (p2 & 0x000000FF)) + self._si5351._write_u8(self._base + 1, (p3 & 0x000000FF)) + self._si5351._write_u8(self._base + 2, (p1 & 0x00030000) >> 16) + self._si5351._write_u8(self._base + 3, (p1 & 0x0000FF00) >> 8) + self._si5351._write_u8(self._base + 4, (p1 & 0x000000FF)) + self._si5351._write_u8( + self._base + 5, ((p3 & 0x000F0000) >> 12) | ((p2 & 0x000F0000) >> 16) + ) + self._si5351._write_u8(self._base + 6, (p2 & 0x0000FF00) >> 8) + self._si5351._write_u8(self._base + 7, (p2 & 0x000000FF)) # Reset both PLLs. - self._si5351._write_u8(_SI5351_REGISTER_177_PLL_RESET, (1<<7) | (1<<5)) + self._si5351._write_u8(_SI5351_REGISTER_177_PLL_RESET, (1 << 7) | (1 << 5)) def configure_integer(self, multiplier): """Configure the PLL with a simple integer mulitplier for the most @@ -217,10 +218,13 @@ def configure_fractional(self, multiplier, numerator, denominator): numerator = int(numerator) denominator = int(denominator) # Compute register values and configure them. - p1 = int(128 * multiplier + math.floor(128 * \ - ((numerator/denominator)) - 512)) - p2 = int(128 * numerator - denominator * math.floor(128 * \ - (numerator/denominator))) + p1 = int( + 128 * multiplier + math.floor(128 * ((numerator / denominator)) - 512) + ) + p2 = int( + 128 * numerator + - denominator * math.floor(128 * (numerator / denominator)) + ) p3 = denominator self._configure_registers(p1, p2, p3) # Calculate exact frequency and store it for reference. @@ -235,7 +239,6 @@ def configure_fractional(self, multiplier, numerator, denominator): # these and they can each be independently configured to use a specific # PLL source and have their own divider on that PLL. class _Clock: - def __init__(self, si5351, base_address, control_register, r_register): self._si5351 = si5351 self._base = base_address @@ -262,21 +265,21 @@ def frequency(self): if r_divider == R_DIV_1: return base_frequency elif r_divider == R_DIV_2: - return base_frequency/2 + return base_frequency / 2 elif r_divider == R_DIV_4: - return base_frequency/4 + return base_frequency / 4 elif r_divider == R_DIV_8: - return base_frequency/8 + return base_frequency / 8 elif r_divider == R_DIV_16: - return base_frequency/16 + return base_frequency / 16 elif r_divider == R_DIV_32: - return base_frequency/32 + return base_frequency / 32 elif r_divider == R_DIV_64: - return base_frequency/64 + return base_frequency / 64 elif r_divider == R_DIV_128: - return base_frequency/128 + return base_frequency / 128 else: - raise RuntimeError('Unexpected R divider!') + raise RuntimeError("Unexpected R divider!") @property def r_divider(self): @@ -306,14 +309,15 @@ def r_divider(self, divider): def _configure_registers(self, p1, p2, p3): # Update MSx registers. self._si5351._write_u8(self._base, (p3 & 0x0000FF00) >> 8) - self._si5351._write_u8(self._base+1, (p3 & 0x000000FF)) - self._si5351._write_u8(self._base+2, (p1 & 0x00030000) >> 16) - self._si5351._write_u8(self._base+3, (p1 & 0x0000FF00) >> 8) - self._si5351._write_u8(self._base+4, (p1 & 0x000000FF)) - self._si5351._write_u8(self._base+5, ((p3 & 0x000F0000) >> 12) | \ - ((p2 & 0x000F0000) >> 16)) - self._si5351._write_u8(self._base+6, (p2 & 0x0000FF00) >> 8) - self._si5351._write_u8(self._base+7, (p2 & 0x000000FF)) + self._si5351._write_u8(self._base + 1, (p3 & 0x000000FF)) + self._si5351._write_u8(self._base + 2, (p1 & 0x00030000) >> 16) + self._si5351._write_u8(self._base + 3, (p1 & 0x0000FF00) >> 8) + self._si5351._write_u8(self._base + 4, (p1 & 0x000000FF)) + self._si5351._write_u8( + self._base + 5, ((p3 & 0x000F0000) >> 12) | ((p2 & 0x000F0000) >> 16) + ) + self._si5351._write_u8(self._base + 6, (p2 & 0x0000FF00) >> 8) + self._si5351._write_u8(self._base + 7, (p2 & 0x000000FF)) def configure_integer(self, pll, divider): """Configure the clock output with the specified PLL source @@ -331,10 +335,10 @@ def configure_integer(self, pll, divider): p3 = 1 self._configure_registers(p1, p2, p3) # Configure the clock control register. - control = 0x0F # 8mA drive strength, MS0 as CLK0 source, - # Clock not inverted, powered up + control = 0x0F # 8mA drive strength, MS0 as CLK0 source, + # Clock not inverted, powered up control |= pll.clock_control_enabled - control |= (1 << 6) # Enable integer mode. + control |= 1 << 6 # Enable integer mode. self._si5351._write_u8(self._control, control) # Store the PLL and divisor value so frequency can be calculated. self._pll = pll @@ -355,13 +359,16 @@ def configure_fractional(self, pll, divider, numerator, denominator): # Make sure the PLL is configured (has a frequency set). assert pll.frequency is not None # Compute MSx register values. - p1 = int(128 * divider + math.floor(128 * (numerator/denominator)) - 512) - p2 = int(128 * numerator - denominator * math.floor(128 * (numerator/denominator))) + p1 = int(128 * divider + math.floor(128 * (numerator / denominator)) - 512) + p2 = int( + 128 * numerator + - denominator * math.floor(128 * (numerator / denominator)) + ) p3 = denominator self._configure_registers(p1, p2, p3) # Configure the clock control register. - control = 0x0F # 8mA drive strength, MS0 as CLK0 source, - # Clock not inverted, powered up + control = 0x0F # 8mA drive strength, MS0 as CLK0 source, + # Clock not inverted, powered up control |= pll.clock_control_enabled self._si5351._write_u8(self._control, control) # Store the PLL and divisor value so frequency can be calculated. @@ -390,18 +397,24 @@ def __init__(self, i2c, *, address=_SI5351_ADDRESS): self.pll_a = self._PLL(self, 26, 0) self.pll_b = self._PLL(self, 34, (1 << 5)) # Initialize the 3 clock outputs. - self.clock_0 = self._Clock(self, - _SI5351_REGISTER_42_MULTISYNTH0_PARAMETERS_1, - _SI5351_REGISTER_16_CLK0_CONTROL, - _SI5351_REGISTER_44_MULTISYNTH0_PARAMETERS_3) - self.clock_1 = self._Clock(self, - _SI5351_REGISTER_50_MULTISYNTH1_PARAMETERS_1, - _SI5351_REGISTER_17_CLK1_CONTROL, - _SI5351_REGISTER_52_MULTISYNTH1_PARAMETERS_3) - self.clock_2 = self._Clock(self, - _SI5351_REGISTER_58_MULTISYNTH2_PARAMETERS_1, - _SI5351_REGISTER_18_CLK2_CONTROL, - _SI5351_REGISTER_60_MULTISYNTH2_PARAMETERS_3) + self.clock_0 = self._Clock( + self, + _SI5351_REGISTER_42_MULTISYNTH0_PARAMETERS_1, + _SI5351_REGISTER_16_CLK0_CONTROL, + _SI5351_REGISTER_44_MULTISYNTH0_PARAMETERS_3, + ) + self.clock_1 = self._Clock( + self, + _SI5351_REGISTER_50_MULTISYNTH1_PARAMETERS_1, + _SI5351_REGISTER_17_CLK1_CONTROL, + _SI5351_REGISTER_52_MULTISYNTH1_PARAMETERS_3, + ) + self.clock_2 = self._Clock( + self, + _SI5351_REGISTER_58_MULTISYNTH2_PARAMETERS_1, + _SI5351_REGISTER_18_CLK2_CONTROL, + _SI5351_REGISTER_60_MULTISYNTH2_PARAMETERS_3, + ) def _read_u8(self, address): # Read an 8-bit unsigned value from the specified 8-bit address. diff --git a/docs/conf.py b/docs/conf.py index 507bc43..01a9d46 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,7 +2,8 @@ import os import sys -sys.path.insert(0, os.path.abspath('..')) + +sys.path.insert(0, os.path.abspath("..")) # -- General configuration ------------------------------------------------ @@ -10,9 +11,9 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.intersphinx', - 'sphinx.ext.todo', + "sphinx.ext.autodoc", + "sphinx.ext.intersphinx", + "sphinx.ext.todo", ] # Uncomment the below if you use native CircuitPython modules such as @@ -20,29 +21,36 @@ # autodoc module docs will fail to generate with a warning. # autodoc_mock_imports = ["digitalio", "busio", "ustruct", "micropython", "adafruit_bus_device"] -intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),'BusDevice': ('https://circuitpython.readthedocs.io/projects/busdevice/en/latest/', None),'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)} +intersphinx_mapping = { + "python": ("https://docs.python.org/3.4", None), + "BusDevice": ( + "https://circuitpython.readthedocs.io/projects/busdevice/en/latest/", + None, + ), + "CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None), +} # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] -source_suffix = '.rst' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'Adafruit SI5351 Library' -copyright = u'2017 Tony DiCola' -author = u'Tony DiCola' +project = u"Adafruit SI5351 Library" +copyright = u"2017 Tony DiCola" +author = u"Tony DiCola" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = u'1.0' +version = u"1.0" # The full version, including alpha/beta/rc tags. -release = u'1.0' +release = u"1.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -54,7 +62,7 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.env', 'CODE_OF_CONDUCT.md'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".env", "CODE_OF_CONDUCT.md"] # The reST default role (used for this markup: `text`) to use for all # documents. @@ -66,7 +74,7 @@ add_function_parentheses = True # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False @@ -80,53 +88,56 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -on_rtd = os.environ.get('READTHEDOCS', None) == 'True' +on_rtd = os.environ.get("READTHEDOCS", None) == "True" if not on_rtd: # only import and set the theme if we're building docs locally try: import sphinx_rtd_theme - html_theme = 'sphinx_rtd_theme' - html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.'] + + html_theme = "sphinx_rtd_theme" + html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."] except: - html_theme = 'default' - html_theme_path = ['.'] + html_theme = "default" + html_theme_path = ["."] else: - html_theme_path = ['.'] + html_theme_path = ["."] # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Output file base name for HTML help builder. -htmlhelp_basename = 'AdafruitSi5351Librarydoc' +htmlhelp_basename = "AdafruitSi5351Librarydoc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'AdafruitSI5351Library.tex', u'AdafruitSI5351 Library Documentation', - author, 'manual'), + ( + master_doc, + "AdafruitSI5351Library.tex", + u"AdafruitSI5351 Library Documentation", + author, + "manual", + ), ] # -- Options for manual page output --------------------------------------- @@ -134,8 +145,13 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'AdafruitSI5351library', u'Adafruit SI5351 Library Documentation', - [author], 1) + ( + master_doc, + "AdafruitSI5351library", + u"Adafruit SI5351 Library Documentation", + [author], + 1, + ) ] # -- Options for Texinfo output ------------------------------------------- @@ -144,7 +160,13 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'AdafruitSI5351Library', u'Adafruit SI5351 Library Documentation', - author, 'AdafruitSI5351Library', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "AdafruitSI5351Library", + u"Adafruit SI5351 Library Documentation", + author, + "AdafruitSI5351Library", + "One line description of project.", + "Miscellaneous", + ), ] diff --git a/examples/si5351_simpletest.py b/examples/si5351_simpletest.py index 76de447..74f4475 100644 --- a/examples/si5351_simpletest.py +++ b/examples/si5351_simpletest.py @@ -20,7 +20,7 @@ # Initialize SI5351. si5351 = adafruit_si5351.SI5351(i2c) # Alternatively you can specify the I2C address if it has been changed: -#si5351 = adafruit_si5351.SI5351(i2c, address=0x61) +# si5351 = adafruit_si5351.SI5351(i2c, address=0x61) # Now configue the PLLs and clock outputs. # The PLLs can be configured with a multiplier and division of the on-board @@ -29,7 +29,7 @@ # but allows less of a range of frequencies compared to a fractional # multiplier shown next. si5351.pll_a.configure_integer(36) # Multiply 25mhz by 36 -print('PLL A frequency: {0}mhz'.format(si5351.pll_a.frequency/1000000)) +print("PLL A frequency: {0}mhz".format(si5351.pll_a.frequency / 1000000)) # And next configure PLL B to 616.6667mhz by multiplying 25mhz by 24.667 using # the fractional multiplier configuration. Notice you specify the integer @@ -38,7 +38,7 @@ # configuration is susceptible to some jitter over time but can set a larger # range of frequencies. si5351.pll_b.configure_fractional(24, 2, 3) # Multiply 25mhz by 24.667 (24 2/3) -print('PLL B frequency: {0}mhz'.format(si5351.pll_b.frequency/1000000)) +print("PLL B frequency: {0}mhz".format(si5351.pll_b.frequency / 1000000)) # Now configure the clock outputs. Each is driven by a PLL frequency as input # and then further divides that down to a specific frequency. @@ -46,14 +46,14 @@ # of 112.5mhz (900mhz / 8). Again this uses the most precise integer division # but can't set as wide a range of values. si5351.clock_0.configure_integer(si5351.pll_a, 8) -print('Clock 0: {0}mhz'.format(si5351.clock_0.frequency/1000000)) +print("Clock 0: {0}mhz".format(si5351.clock_0.frequency / 1000000)) # Next configure clock 1 to be driven by PLL B divided by 45.5 to get # 13.5531mhz (616.6667mhz / 45.5). This uses fractional division and again # notice the numerator and denominator are explicitly specified. This is less # precise but allows a large range of frequencies. -si5351.clock_1.configure_fractional(si5351.pll_b, 45, 1, 2) # Divide by 45.5 (45 1/2) -print('Clock 1: {0}mhz'.format(si5351.clock_1.frequency/1000000)) +si5351.clock_1.configure_fractional(si5351.pll_b, 45, 1, 2) # Divide by 45.5 (45 1/2) +print("Clock 1: {0}mhz".format(si5351.clock_1.frequency / 1000000)) # Finally configure clock 2 to be driven by PLL B divided once by 900 to get # down to 685.15 khz and then further divided by a special R divider that @@ -69,7 +69,7 @@ # - R_DIV_64: divider of 64 # - R_DIV_128: divider of 128 si5351.clock_2.r_divider = adafruit_si5351.R_DIV_64 -print('Clock 2: {0}khz'.format(si5351.clock_2.frequency/1000)) +print("Clock 2: {0}khz".format(si5351.clock_2.frequency / 1000)) # After configuring PLLs and clocks, enable the outputs. si5351.outputs_enabled = True diff --git a/setup.py b/setup.py index dbec762..4c61483 100644 --- a/setup.py +++ b/setup.py @@ -7,6 +7,7 @@ # Always prefer setuptools over distutils from setuptools import setup, find_packages + # To use a consistent encoding from codecs import open from os import path @@ -14,47 +15,38 @@ here = path.abspath(path.dirname(__file__)) # Get the long description from the README file -with open(path.join(here, 'README.rst'), encoding='utf-8') as f: +with open(path.join(here, "README.rst"), encoding="utf-8") as f: long_description = f.read() setup( - name='adafruit-circuitpython-si5351', - + name="adafruit-circuitpython-si5351", use_scm_version=True, - setup_requires=['setuptools_scm'], - - description='CircuitPython library for SI5351 clock generator module.', + setup_requires=["setuptools_scm"], + description="CircuitPython library for SI5351 clock generator module.", long_description=long_description, - long_description_content_type='text/x-rst', - + long_description_content_type="text/x-rst", # The project's main homepage. - url='https://github.com/adafruit/Adafruit_CircuitPython_SI5351', - + url="https://github.com/adafruit/Adafruit_CircuitPython_SI5351", # Author details - author='Adafruit Industries', - author_email='circuitpython@adafruit.com', - - install_requires=['Adafruit-Blinka', 'adafruit-circuitpython-busdevice'], - + author="Adafruit Industries", + author_email="circuitpython@adafruit.com", + install_requires=["Adafruit-Blinka", "adafruit-circuitpython-busdevice"], # Choose your license - license='MIT', - + license="MIT", # See https://pypi.python.org/pypi?%3Aaction=list_classifiers classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Developers', - 'Topic :: Software Development :: Libraries', - 'Topic :: System :: Hardware', - 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Topic :: Software Development :: Libraries", + "Topic :: System :: Hardware", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", ], - # What does your project relate to? - keywords='adafruit si5351 clock generator module breakout hardware micropython circuitpython', - + keywords="adafruit si5351 clock generator module breakout hardware micropython circuitpython", # You can just specify the packages manually here if your project is # simple. Or you can use find_packages(). - py_modules=['adafruit_si5351'], + py_modules=["adafruit_si5351"], )