Adafruit Si5351 Library
Adafruit_SI5351.h
1 /*
2  * @file Adafruit_SI5351.h
3  */
4 
5 #ifndef _SI5351_H_
6 #define _SI5351_H_
7 
8 #if ARDUINO >= 100
9 #include <Arduino.h>
10 #else
11 #include <WProgram.h>
12 #endif
13 // #include <Adafruit_Sensor.h>
14 #include <Adafruit_I2CDevice.h>
15 
16 #include "asserts.h"
17 #include "errors.h"
18 
19 #define SI5351_ADDRESS (0x60) // Assumes ADDR pin = low
20 #define SI5351_READBIT (0x01)
21 
22 /* Test setup from SI5351 ClockBuilder
23  * -----------------------------------
24  * XTAL: 25 MHz
25  * Channel 0: 120.00 MHz
26  * Channel 1: 12.00 MHz
27  * Channel 2: 13.56 MHz
28  * PROGMEM keeps the optional table out of SRAM on AVR.
29  */
30 static const uint8_t m_si5351_regs_15to92_149to170[100][2] PROGMEM = {
31  {15, 0x00}, /* Input source = crystal for PLLA and PLLB */
32  {16, 0x4F}, /* CLK0 Control: 8mA drive, Multisynth 0 as CLK0 source, Clock
33  not inverted, Source = PLLA, Multisynth 0 in integer mode,
34  clock powered up */
35  {17, 0x4F}, /* CLK1 Control: 8mA drive, Multisynth 1 as CLK1 source, Clock
36  not inverted, Source = PLLA, Multisynth 1 in integer mode,
37  clock powered up */
38  {18, 0x6F}, /* CLK2 Control: 8mA drive, Multisynth 2 as CLK2 source, Clock
39  not inverted, Source = PLLB, Multisynth 2 in integer mode,
40  clock powered up */
41  {19, 0x80}, /* CLK3 Control: Not used ... clock powered down */
42  {20, 0x80}, /* CLK4 Control: Not used ... clock powered down */
43  {21, 0x80}, /* CLK5 Control: Not used ... clock powered down */
44  {22, 0x80}, /* CLK6 Control: Not used ... clock powered down */
45  {23, 0x80}, /* CLK7 Control: Not used ... clock powered down */
46  {24, 0x00}, /* Clock disable state 0..3 (low when disabled) */
47  {25, 0x00}, /* Clock disable state 4..7 (low when disabled) */
48  /* PLL_A Setup */
49  {26, 0x00},
50  {27, 0x05},
51  {28, 0x00},
52  {29, 0x0C},
53  {30, 0x66},
54  {31, 0x00},
55  {32, 0x00},
56  {33, 0x02},
57  /* PLL_B Setup */
58  {34, 0x02},
59  {35, 0x71},
60  {36, 0x00},
61  {37, 0x0C},
62  {38, 0x1A},
63  {39, 0x00},
64  {40, 0x00},
65  {41, 0x86},
66  /* Multisynth Setup */
67  {42, 0x00},
68  {43, 0x01},
69  {44, 0x00},
70  {45, 0x01},
71  {46, 0x00},
72  {47, 0x00},
73  {48, 0x00},
74  {49, 0x00},
75  {50, 0x00},
76  {51, 0x01},
77  {52, 0x00},
78  {53, 0x1C},
79  {54, 0x00},
80  {55, 0x00},
81  {56, 0x00},
82  {57, 0x00},
83  {58, 0x00},
84  {59, 0x01},
85  {60, 0x00},
86  {61, 0x18},
87  {62, 0x00},
88  {63, 0x00},
89  {64, 0x00},
90  {65, 0x00},
91  {66, 0x00},
92  {67, 0x00},
93  {68, 0x00},
94  {69, 0x00},
95  {70, 0x00},
96  {71, 0x00},
97  {72, 0x00},
98  {73, 0x00},
99  {74, 0x00},
100  {75, 0x00},
101  {76, 0x00},
102  {77, 0x00},
103  {78, 0x00},
104  {79, 0x00},
105  {80, 0x00},
106  {81, 0x00},
107  {82, 0x00},
108  {83, 0x00},
109  {84, 0x00},
110  {85, 0x00},
111  {86, 0x00},
112  {87, 0x00},
113  {88, 0x00},
114  {89, 0x00},
115  {90, 0x00},
116  {91, 0x00},
117  {92, 0x00},
118  /* Misc Config Register */
119  {149, 0x00},
120  {150, 0x00},
121  {151, 0x00},
122  {152, 0x00},
123  {153, 0x00},
124  {154, 0x00},
125  {155, 0x00},
126  {156, 0x00},
127  {157, 0x00},
128  {158, 0x00},
129  {159, 0x00},
130  {160, 0x00},
131  {161, 0x00},
132  {162, 0x00},
133  {163, 0x00},
134  {164, 0x00},
135  {165, 0x00},
136  {166, 0x00},
137  {167, 0x00},
138  {168, 0x00},
139  {169, 0x00},
140  {170, 0x00}};
141 
142 /* See http://www.silabs.com/Support%20Documents/TechnicalDocs/AN619.pdf for
143  * registers 26..41 */
144 enum {
145  SI5351_REGISTER_0_DEVICE_STATUS = 0,
146  SI5351_REGISTER_1_INTERRUPT_STATUS_STICKY = 1,
147  SI5351_REGISTER_2_INTERRUPT_STATUS_MASK = 2,
148  SI5351_REGISTER_3_OUTPUT_ENABLE_CONTROL = 3,
149  SI5351_REGISTER_9_OEB_PIN_ENABLE_CONTROL = 9,
150  SI5351_REGISTER_15_PLL_INPUT_SOURCE = 15,
151  SI5351_REGISTER_16_CLK0_CONTROL = 16,
152  SI5351_REGISTER_17_CLK1_CONTROL = 17,
153  SI5351_REGISTER_18_CLK2_CONTROL = 18,
154  SI5351_REGISTER_19_CLK3_CONTROL = 19,
155  SI5351_REGISTER_20_CLK4_CONTROL = 20,
156  SI5351_REGISTER_21_CLK5_CONTROL = 21,
157  SI5351_REGISTER_22_CLK6_CONTROL = 22,
158  SI5351_REGISTER_23_CLK7_CONTROL = 23,
159  SI5351_REGISTER_24_CLK3_0_DISABLE_STATE = 24,
160  SI5351_REGISTER_25_CLK7_4_DISABLE_STATE = 25,
161  SI5351_REGISTER_42_MULTISYNTH0_PARAMETERS_1 = 42,
162  SI5351_REGISTER_43_MULTISYNTH0_PARAMETERS_2 = 43,
163  SI5351_REGISTER_44_MULTISYNTH0_PARAMETERS_3 = 44,
164  SI5351_REGISTER_45_MULTISYNTH0_PARAMETERS_4 = 45,
165  SI5351_REGISTER_46_MULTISYNTH0_PARAMETERS_5 = 46,
166  SI5351_REGISTER_47_MULTISYNTH0_PARAMETERS_6 = 47,
167  SI5351_REGISTER_48_MULTISYNTH0_PARAMETERS_7 = 48,
168  SI5351_REGISTER_49_MULTISYNTH0_PARAMETERS_8 = 49,
169  SI5351_REGISTER_50_MULTISYNTH1_PARAMETERS_1 = 50,
170  SI5351_REGISTER_51_MULTISYNTH1_PARAMETERS_2 = 51,
171  SI5351_REGISTER_52_MULTISYNTH1_PARAMETERS_3 = 52,
172  SI5351_REGISTER_53_MULTISYNTH1_PARAMETERS_4 = 53,
173  SI5351_REGISTER_54_MULTISYNTH1_PARAMETERS_5 = 54,
174  SI5351_REGISTER_55_MULTISYNTH1_PARAMETERS_6 = 55,
175  SI5351_REGISTER_56_MULTISYNTH1_PARAMETERS_7 = 56,
176  SI5351_REGISTER_57_MULTISYNTH1_PARAMETERS_8 = 57,
177  SI5351_REGISTER_58_MULTISYNTH2_PARAMETERS_1 = 58,
178  SI5351_REGISTER_59_MULTISYNTH2_PARAMETERS_2 = 59,
179  SI5351_REGISTER_60_MULTISYNTH2_PARAMETERS_3 = 60,
180  SI5351_REGISTER_61_MULTISYNTH2_PARAMETERS_4 = 61,
181  SI5351_REGISTER_62_MULTISYNTH2_PARAMETERS_5 = 62,
182  SI5351_REGISTER_63_MULTISYNTH2_PARAMETERS_6 = 63,
183  SI5351_REGISTER_64_MULTISYNTH2_PARAMETERS_7 = 64,
184  SI5351_REGISTER_65_MULTISYNTH2_PARAMETERS_8 = 65,
185  SI5351_REGISTER_66_MULTISYNTH3_PARAMETERS_1 = 66,
186  SI5351_REGISTER_67_MULTISYNTH3_PARAMETERS_2 = 67,
187  SI5351_REGISTER_68_MULTISYNTH3_PARAMETERS_3 = 68,
188  SI5351_REGISTER_69_MULTISYNTH3_PARAMETERS_4 = 69,
189  SI5351_REGISTER_70_MULTISYNTH3_PARAMETERS_5 = 70,
190  SI5351_REGISTER_71_MULTISYNTH3_PARAMETERS_6 = 71,
191  SI5351_REGISTER_72_MULTISYNTH3_PARAMETERS_7 = 72,
192  SI5351_REGISTER_73_MULTISYNTH3_PARAMETERS_8 = 73,
193  SI5351_REGISTER_74_MULTISYNTH4_PARAMETERS_1 = 74,
194  SI5351_REGISTER_75_MULTISYNTH4_PARAMETERS_2 = 75,
195  SI5351_REGISTER_76_MULTISYNTH4_PARAMETERS_3 = 76,
196  SI5351_REGISTER_77_MULTISYNTH4_PARAMETERS_4 = 77,
197  SI5351_REGISTER_78_MULTISYNTH4_PARAMETERS_5 = 78,
198  SI5351_REGISTER_79_MULTISYNTH4_PARAMETERS_6 = 79,
199  SI5351_REGISTER_80_MULTISYNTH4_PARAMETERS_7 = 80,
200  SI5351_REGISTER_81_MULTISYNTH4_PARAMETERS_8 = 81,
201  SI5351_REGISTER_82_MULTISYNTH5_PARAMETERS_1 = 82,
202  SI5351_REGISTER_83_MULTISYNTH5_PARAMETERS_2 = 83,
203  SI5351_REGISTER_84_MULTISYNTH5_PARAMETERS_3 = 84,
204  SI5351_REGISTER_85_MULTISYNTH5_PARAMETERS_4 = 85,
205  SI5351_REGISTER_86_MULTISYNTH5_PARAMETERS_5 = 86,
206  SI5351_REGISTER_87_MULTISYNTH5_PARAMETERS_6 = 87,
207  SI5351_REGISTER_88_MULTISYNTH5_PARAMETERS_7 = 88,
208  SI5351_REGISTER_89_MULTISYNTH5_PARAMETERS_8 = 89,
209  SI5351_REGISTER_90_MULTISYNTH6_PARAMETERS = 90,
210  SI5351_REGISTER_91_MULTISYNTH7_PARAMETERS = 91,
211  SI5351_REGISTER_092_CLOCK_6_7_OUTPUT_DIVIDER = 92,
212  SI5351_REGISTER_149_SPREAD_SPECTRUM_PARAMETERS = 149,
213  SI5351_REGISTER_165_CLK0_INITIAL_PHASE_OFFSET = 165,
214  SI5351_REGISTER_166_CLK1_INITIAL_PHASE_OFFSET = 166,
215  SI5351_REGISTER_167_CLK2_INITIAL_PHASE_OFFSET = 167,
216  SI5351_REGISTER_168_CLK3_INITIAL_PHASE_OFFSET = 168,
217  SI5351_REGISTER_169_CLK4_INITIAL_PHASE_OFFSET = 169,
218  SI5351_REGISTER_170_CLK5_INITIAL_PHASE_OFFSET = 170,
219  SI5351_REGISTER_177_PLL_RESET = 177,
220  SI5351_REGISTER_183_CRYSTAL_INTERNAL_LOAD_CAPACITANCE = 183
221 };
222 
223 #define SI5351_STATUS_SYS_INIT (1 << 7)
224 #define SI5351_STATUS_LOL_B (1 << 6)
225 #define SI5351_STATUS_LOL_A (1 << 5)
226 #define SI5351_STATUS_LOS_CLKIN (1 << 4)
227 
228 typedef enum {
229  SI5351_PLL_A = 0,
230  SI5351_PLL_B,
231 } si5351PLL_t;
232 
233 typedef enum {
234  SI5351_PLL_SOURCE_XTAL = 0,
235  SI5351_PLL_SOURCE_CLKIN = 1,
236 } si5351PLLSource_t;
237 
238 typedef enum {
239  SI5351_CLKIN_DIV_1 = 0,
240  SI5351_CLKIN_DIV_2 = 1,
241  SI5351_CLKIN_DIV_4 = 2,
242  SI5351_CLKIN_DIV_8 = 3,
243 } si5351ClkinDiv_t;
244 
245 typedef enum {
246  SI5351_CRYSTAL_LOAD_6PF = (1 << 6),
247  SI5351_CRYSTAL_LOAD_8PF = (2 << 6),
248  SI5351_CRYSTAL_LOAD_10PF = (3 << 6)
249 } si5351CrystalLoad_t;
250 
251 typedef enum {
252  SI5351_CRYSTAL_FREQ_25MHZ = (25000000),
253  SI5351_CRYSTAL_FREQ_27MHZ = (27000000)
254 } si5351CrystalFreq_t;
255 
256 typedef enum {
257  SI5351_MULTISYNTH_DIV_4 = 4,
258  SI5351_MULTISYNTH_DIV_6 = 6,
259  SI5351_MULTISYNTH_DIV_8 = 8
260 } si5351MultisynthDiv_t;
261 
262 typedef enum {
263  SI5351_R_DIV_1 = 0,
264  SI5351_R_DIV_2 = 1,
265  SI5351_R_DIV_4 = 2,
266  SI5351_R_DIV_8 = 3,
267  SI5351_R_DIV_16 = 4,
268  SI5351_R_DIV_32 = 5,
269  SI5351_R_DIV_64 = 6,
270  SI5351_R_DIV_128 = 7,
271 } si5351RDiv_t;
272 
276 typedef struct {
277  bool initialised;
278  si5351CrystalFreq_t crystalFreq;
279  si5351CrystalLoad_t crystalLoad;
280  uint32_t crystalPPM;
282  uint32_t plla_freq;
284  uint32_t pllb_freq;
286 
291  public:
292  Adafruit_SI5351(void);
293 
294  err_t begin(TwoWire* theWire = &Wire);
295  err_t setClockBuilderData(void);
296  err_t setupPLL(si5351PLL_t pll, uint8_t mult, uint32_t num,
297  uint32_t denom);
298  err_t setupPLLInt(si5351PLL_t pll, uint8_t mult);
300  si5351PLL_t pll, si5351PLLSource_t source,
301  si5351ClkinDiv_t clkinDiv = SI5351_CLKIN_DIV_1);
302  err_t setupMultisynth(uint8_t output, si5351PLL_t pllSource, uint32_t div,
303  uint32_t num, uint32_t denom);
304  err_t setupMultisynthInt(uint8_t output, si5351PLL_t pllSource,
305  uint8_t div);
306 
307  err_t setPhaseOffset(uint8_t output, uint8_t offset);
308  err_t resetPLL(si5351PLL_t pll);
309 
310  err_t enableSpreadSpectrum(bool enabled);
311  err_t enableOutputs(bool enabled);
313  uint8_t* device_status);
314  err_t readStickyStatus(uint8_t* sticky);
315  err_t clearStickyStatus(void);
317  uint8_t mask);
319  uint8_t mask);
320 
324  err_t setupRdiv(uint8_t output, si5351RDiv_t div);
325 
326  err_t setFrequency(uint8_t output, si5351PLL_t pll,
327  uint32_t freq);
328 
329  private:
331  struct ClockControl {
332  uint8_t driveStrength : 2;
333  uint8_t clockSource : 2;
334  uint8_t inverted : 1;
335  uint8_t pllSource : 1;
336  uint8_t integerMode : 1;
337  uint8_t powerDown : 1;
338  };
339 
341  struct PLLReset {
342  uint8_t reservedLow : 5;
343  uint8_t resetA : 1;
344  uint8_t reservedHigh : 1;
345  uint8_t resetB : 1;
346  };
347 
348  si5351Config_t m_si5351Config;
349 
350  Adafruit_I2CDevice* i2c_dev = NULL;
351  err_t write8(uint8_t reg, uint8_t value);
352  err_t read8(uint8_t reg, uint8_t* value);
353  err_t writeN(uint8_t* data, uint8_t n);
354 
355  uint8_t lastRdivValue[6];
356 };
357 
358 #endif
bool plla_configured
Phase-locked loop A configured.
Definition: Adafruit_SI5351.h:281
SI5351 constructor.
Definition: Adafruit_SI5351.h:276
err_t enableSpreadSpectrum(bool enabled)
Enables or disables spread spectrum.
Definition: Adafruit_SI5351.cpp:896
err_t
Definition: errors.h:13
err_t setupPLL(si5351PLL_t pll, uint8_t mult, uint32_t num, uint32_t denom)
Sets the multiplier for the specified PLL.
Definition: Adafruit_SI5351.cpp:285
err_t resetPLL(si5351PLL_t pll)
Resets one PLL after configuring its outputs and phase offsets.
Definition: Adafruit_SI5351.cpp:775
err_t setupPLLSource(si5351PLL_t pll, si5351PLLSource_t source, si5351ClkinDiv_t clkinDiv=SI5351_CLKIN_DIV_1)
Selects the reference source (XTAL or CLKIN) for the specified PLL, and optionally sets the CLKIN pre...
Definition: Adafruit_SI5351.cpp:233
bool pllb_configured
Phase-locked loop B configured.
Definition: Adafruit_SI5351.h:283
err_t setOEBPinMask(uint8_t mask)
Write register 9 OEB pin-enable mask byte.
Definition: Adafruit_SI5351.cpp:884
err_t setupMultisynth(uint8_t output, si5351PLL_t pllSource, uint32_t div, uint32_t num, uint32_t denom)
Configures the Multisynth divider, which determines the output clock frequency based on the specified...
Definition: Adafruit_SI5351.cpp:614
SI5351 class.
Definition: Adafruit_SI5351.h:290
err_t setFrequency(uint8_t output, si5351PLL_t pll, uint32_t freq)
Automatically computes and applies the PLL multiplier, Multisynth divider and R divider needed to gen...
Definition: Adafruit_SI5351.cpp:510
err_t readStickyStatus(uint8_t *sticky)
Read register 1 sticky byte.
Definition: Adafruit_SI5351.cpp:840
bool initialised
Initialization status of SI5351.
Definition: Adafruit_SI5351.h:277
Adafruit_SI5351(void)
SI5351 object.
Definition: Adafruit_SI5351.cpp:68
uint32_t pllb_freq
Phase-locked loop B frequency.
Definition: Adafruit_SI5351.h:284
err_t enableOutputs(bool enabled)
Enables or disables all clock outputs.
Definition: Adafruit_SI5351.cpp:807
err_t setInterruptMask(uint8_t mask)
Write register 2 interrupt mask byte.
Definition: Adafruit_SI5351.cpp:867
err_t readDeviceStatus(uint8_t *device_status)
Read register 0 status byte.
Definition: Adafruit_SI5351.cpp:826
err_t clearStickyStatus(void)
Clear register 1 sticky flags.
Definition: Adafruit_SI5351.cpp:853
err_t setClockBuilderData(void)
Configures the Si5351 with config settings generated in ClockBuilder. You can use this function to ma...
Definition: Adafruit_SI5351.cpp:151
err_t begin(TwoWire *theWire=&Wire)
Initializes I2C and configures the breakout (call this function before doing anything else) ...
Definition: Adafruit_SI5351.cpp:91
uint32_t plla_freq
Phase-locked loop A frequency.
Definition: Adafruit_SI5351.h:282
err_t setupMultisynthInt(uint8_t output, si5351PLL_t pllSource, uint8_t div)
Configures a Multisynth divider in integer mode.
Definition: Adafruit_SI5351.cpp:383
uint32_t crystalPPM
Frequency synthesis.
Definition: Adafruit_SI5351.h:280
err_t setupRdiv(uint8_t output, si5351RDiv_t div)
Configures the R divider for a given output channel.
Definition: Adafruit_SI5351.cpp:446
si5351CrystalLoad_t crystalLoad
Crystal load capacitors.
Definition: Adafruit_SI5351.h:279
err_t setupPLLInt(si5351PLL_t pll, uint8_t mult)
Sets the multiplier for the specified PLL using integer values.
Definition: Adafruit_SI5351.cpp:188
si5351CrystalFreq_t crystalFreq
Crystal frequency.
Definition: Adafruit_SI5351.h:278
err_t setPhaseOffset(uint8_t output, uint8_t offset)
Sets the initial phase offset for CLK0 through CLK5.
Definition: Adafruit_SI5351.cpp:735