From 4926233d69089e30566e202f549a7934df235ccc Mon Sep 17 00:00:00 2001 From: Jason Milldrum Date: Sun, 28 Feb 2016 15:14:09 -0800 Subject: [PATCH] Add set_pll_input(), support for different PLL ref freqs in init() --- README.md | 34 +++++++-- keywords.txt | 50 +++++++++++-- library.properties | 4 +- src/si5351.cpp | 179 +++++++++++++++++++++++++++++++-------------- src/si5351.h | 29 ++++---- 5 files changed, 212 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index ceea705..eb54509 100644 --- a/README.md +++ b/README.md @@ -20,16 +20,12 @@ Wire the SDA and SCL pins of the Si5351 to the corresponding pins on the Arduino Connect a 25 MHz or 27 MHz crystal with a load capacitance of 6, 8, or 10 pF to the Si5351 XA and XB pins. Locate the crystal as close to the Si5351 as possible and keep the traces as short as possible. Please use a SMT crystal. A crystal with leads will have too much stray capacitance. -Library Installation --------------------- -The best way to install the library is via the Arduino Library Manager, which is available if you are using Arduino IDE version 1.6.2 or greater. To install it this way, simply go to the menu Sketch > Include Library > Manage Libraries..., and then in the search box at the upper-right, type "Etherkit Si5351". Click on the entry in the list below, then click on the provided "Install" button. By installing the library this way, you will always have notifications of future library updates, and can easily switch between library versions. - -If you need to or would like to install the library in the old way, then you can download a copy of the library in a ZIP file. Download a ZIP file of the library from the GitHub repository by using the "Download ZIP" button at the right of the main repository page. Extract the ZIP file, then rename the unzipped folder as "Si5351". Finally, open the Arduino IDE, select menu Sketch > Import Library... > Add Library..., and select the renamed folder that you just downloaded. Restart the IDE and you should have access to the new library. +Example +------- +Include the Si5351Arduino library into your instance of the Arduino IDE. Download a ZIP file of the library from the GitHub repository by using the "Download ZIP" button at the right of the main repository page. Extract the ZIP file, then rename the unzipped folder as "Si5351". Finally, open the Arduino IDE, select menu Sketch > Import Library... > Add Library..., and select the renamed folder that you just downloaded. Restart the IDE and you should have access to the new library. (Yes, the Arduino IDE can import a ZIP file, but it doesn't like filenames with characters such as dashes, as GitHub does when it appends the branch name with a dash. Perhaps there's an elegant way around this, we'll see.) -Example -------- There is a simple example that is placed in your examples menu under Si5351Arduino. Open this to see how to initialize the Si5351 and set a couple of the outputs to different frequencies. The commentary below will analyze the sample sketch. Before you do anything with the Si5351, you will need to include the "si5351.h" and "Wire.h" header files and instantiate the Si5351 class. @@ -437,6 +433,20 @@ void Si5351::set_clock_disable(enum si5351_clock clk, enum si5351_clock_disable */ void Si5351::set_clock_fanout(enum si5351_clock_fanout fanout, uint8_t enable) ``` +###set_pll_input() +``` +/* + * set_pll_input(enum si5351_pll pll, enum si5351_pll_input input) + * + * pll - Which PLL to use as the source + * (use the si5351_pll enum) + * input - Which reference oscillator to use as PLL input + * (use the si5351_pll_input enum) + * + * Set the desired reference oscillator source for the given PLL. + */ +void Si5351::set_pll_input(enum si5351_pll pll, enum si5351_pll_input input) +``` ###si5351_write_bulk() ``` uint8_t Si5351::si5351_write_bulk(uint8_t addr, uint8_t bytes, uint8_t *data) @@ -519,6 +529,16 @@ Oddities -------- Right now, this code is focused solely on the 3-output 10-MSOP variant (Si5351A3). Since some of the code was derived from the Si5351 driver in the Linux kernel, it may be useable on with the other variants, but certainly many features won't work yet. With any luck, we will get the library to work with the other variants as well, or even better, maybe someone will take the initiative, write the code, and send me a pull request. +Changelog +--------- +* v1.1.0 + + Added set_pll_input() method to allow toggling the PLL reference source for the Si5351C variant and added support to init() for different PLL reference frequencies from 10 to 100 MHz. + +* v1.0.0 + + Initial release + TODO ---- - [x] Create an interface to the ref osc frequency diff --git a/keywords.txt b/keywords.txt index 00ea2fe..93df66f 100644 --- a/keywords.txt +++ b/keywords.txt @@ -1,12 +1,37 @@ Si5351 KEYWORD1 -set_freq KEYWORD2 -set_pll KEYWORD2 -clock_enable KEYWORD2 -drive_strength KEYWORD2 +init KEYWORD2 +set_freqKEYWORD2 +set_pll KEYWORD2 +set_ms KEYWORD2 +output_enable KEYWORD2 +drive_strength KEYWORD2 update_status KEYWORD2 -set_correction KEYWORD2 -get_correction KEYWORD2 +set_correction KEYWORD2 +set_phase KEYWORD2 +get_correction KEYWORD2 +pll_reset KEYWORD2 +set_ms_source KEYWORD2 +set_int KEYWORD2 +set_clock_pwr KEYWORD2 +set_clock_invert KEYWORD2 +set_clock_source KEYWORD2 +set_clock_disable KEYWORD2 +set_clock_fanout KEYWORD2 +set_pll_input KEYWORD2 +si5351_write_bulk KEYWORD2 +si5351_write KEYWORD2 +si5351_read KEYWORD2 +dev_status KEYWORD2 +dev_int_status KEYWORD2 +plla_freq KEYWORD2 +pllb_freq KEYWORD2 +clk0_freq KEYWORD2 +clk1_freq KEYWORD2 +clk2_freq KEYWORD2 +clk0_int_mode KEYWORD2 +clk1_int_mode KEYWORD2 +clk2_int_mode KEYWORD2 SI5351_PLL_FIXED LITERAL1 SI5351_CRYSTAL_LOAD_6PF LITERAL1 @@ -26,3 +51,16 @@ SI5351_DRIVE_2MA LITERAL1 SI5351_DRIVE_4MA LITERAL1 SI5351_DRIVE_6MA LITERAL1 SI5351_DRIVE_8MA LITERAL1 +SI5351_CLK_SRC_XTAL LITERAL1 +SI5351_CLK_SRC_CLKIN LITERAL1 +SI5351_CLK_SRC_MS0 LITERAL1 +SI5351_CLK_SRC_MS LITERAL1 +SI5351_CLK_DISABLE_LOW LITERAL1 +SI5351_CLK_DISABLE_HIGH LITERAL1 +SI5351_CLK_DISABLE_HI_Z LITERAL1 +SI5351_CLK_DISABLE_NEVER LITERAL1 +SI5351_FANOUT_CLKIN LITERAL1 +SI5351_FANOUT_XO LITERAL1 +SI5351_FANOUT_MS LITERAL1 +SI5351_PLL_INPUT_XO LITERAL1 +SI5351_PLL_INPUT_CLKIN LITERAL1 diff --git a/library.properties b/library.properties index f0c6ae3..cc3e9d9 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=Etherkit Si5351 -version=1.0.0 +version=1.1.0 author=Jason Milldrum maintainer=Jason Milldrum sentence=A full-featured library for the Si5351 series of clock generator ICs from Silicon Labs -paragraph=It will allow you to control all features of the Si5351, without depending on the proprietary ClockBuilder software from Silicon Labs. +paragraph=This library will allow you to control all features of the Si5351, without depending on the proprietary ClockBuilder software from Silicon Labs. category=Device Control url=https://github.com/etherkit/Si5351Arduino architectures=* diff --git a/src/si5351.cpp b/src/si5351.cpp index 7de97be..4e76a24 100644 --- a/src/si5351.cpp +++ b/src/si5351.cpp @@ -67,24 +67,47 @@ void Si5351::init(uint8_t xtal_load_c, uint32_t ref_osc_freq) // Set crystal load capacitance si5351_write(SI5351_CRYSTAL_LOAD, xtal_load_c); - + // Change the ref osc freq if different from default + // Divide down if greater than 30 MHz if (ref_osc_freq != 0) { - xtal_freq = ref_osc_freq; + uint8_t reg_val; + reg_val = si5351_read(SI5351_PLL_INPUT_SOURCE); + + // Clear the bits first + reg_val &= ~(SI5351_CLKIN_DIV_MASK); + + if(ref_osc_freq <= 30000000UL) + { + xtal_freq = ref_osc_freq; + reg_val |= SI5351_CLKIN_DIV_1; + } + else if(ref_osc_freq > 30000000UL && ref_osc_freq <= 60000000UL) + { + xtal_freq = ref_osc_freq / 2; + reg_val |= SI5351_CLKIN_DIV_2; + } + else if(ref_osc_freq > 60000000UL && ref_osc_freq <= 100000000UL) + { + xtal_freq = ref_osc_freq / 4; + reg_val |= SI5351_CLKIN_DIV_4; + } + + si5351_write(SI5351_PLL_INPUT_SOURCE, reg_val); } - + // Initialize the CLK outputs according to flowchart in datasheet // First, turn them off si5351_write(16, 0x80); si5351_write(17, 0x80); si5351_write(18, 0x80); - + // Turn the clocks back on... si5351_write(16, 0x0c); si5351_write(17, 0x0c); si5351_write(18, 0x0c); - + // Then reset the PLLs pll_reset(SI5351_PLLA); pll_reset(SI5351_PLLB); @@ -110,7 +133,7 @@ uint8_t Si5351::set_freq(uint64_t freq, uint64_t pll_freq, enum si5351_clock clk uint8_t r_div = SI5351_OUTPUT_CLK_DIV_1; uint8_t int_mode = 0; uint8_t div_by_4 = 0; - + // PLL bounds checking if(pll_freq != 0) { @@ -120,21 +143,21 @@ uint8_t Si5351::set_freq(uint64_t freq, uint64_t pll_freq, enum si5351_clock clk } } - // Lower bounds check + // Lower bounds check if(freq < SI5351_CLKOUT_MIN_FREQ * SI5351_FREQ_MULT) { freq = SI5351_CLKOUT_MIN_FREQ * SI5351_FREQ_MULT; } - + // Upper bounds check if(freq > SI5351_MULTISYNTH_MAX_FREQ * SI5351_FREQ_MULT) { freq = SI5351_MULTISYNTH_MAX_FREQ * SI5351_FREQ_MULT; } - + // Select the proper R div value r_div = select_r_div(&freq); - + // Calculate the synth parameters // If pll_freq is 0 and freq < 150 MHz, let the algorithm pick a PLL frequency if((pll_freq) && (freq < SI5351_MULTISYNTH_DIVBY4_FREQ * SI5351_FREQ_MULT)) @@ -143,7 +166,7 @@ uint8_t Si5351::set_freq(uint64_t freq, uint64_t pll_freq, enum si5351_clock clk write_pll = 0; div_by_4 = 0; int_mode = 0; - + switch(clk) { case SI5351_CLK0: @@ -169,7 +192,7 @@ uint8_t Si5351::set_freq(uint64_t freq, uint64_t pll_freq, enum si5351_clock clk div_by_4 = 1; int_mode = 1; } - + // Determine which PLL to use // CLK0 gets PLLA, CLK1 gets PLLB // CLK2 gets PLLB if necessary @@ -181,7 +204,7 @@ uint8_t Si5351::set_freq(uint64_t freq, uint64_t pll_freq, enum si5351_clock clk target_pll = SI5351_PLLA; write_pll = 1; set_ms_source(SI5351_CLK0, SI5351_PLLA); - + plla_freq = pll_freq; clk0_freq = freq; break; @@ -190,7 +213,7 @@ uint8_t Si5351::set_freq(uint64_t freq, uint64_t pll_freq, enum si5351_clock clk if(lock_pllb == SI5351_CLK2) { // We can't have a 2nd output < 1.024 MHz or >= 112.5 MHz on the same PLL unless exact same freq, so exit - if((freq >= SI5351_MULTISYNTH_SHARE_MAX * SI5351_FREQ_MULT + if((freq >= SI5351_MULTISYNTH_SHARE_MAX * SI5351_FREQ_MULT || freq < SI5351_CLKOUT_MIN_FREQ * SI5351_FREQ_MULT * 128) && freq != clk2_freq) { clk1_freq = 0; @@ -212,11 +235,11 @@ uint8_t Si5351::set_freq(uint64_t freq, uint64_t pll_freq, enum si5351_clock clk write_pll = 1; set_ms_source(SI5351_CLK1, SI5351_PLLB); } - + if(freq >= SI5351_MULTISYNTH_SHARE_MAX * SI5351_FREQ_MULT || freq < SI5351_CLKOUT_MIN_FREQ * SI5351_FREQ_MULT * 128) { lock_pllb = SI5351_CLK1; - + // Recalc and rewrite the multisynth parameters on CLK2 if(clk2_freq != 0) { @@ -230,7 +253,7 @@ uint8_t Si5351::set_freq(uint64_t freq, uint64_t pll_freq, enum si5351_clock clk { lock_pllb = SI5351_CLKNONE; } - + target_pll = SI5351_PLLB; clk1_freq = freq; break; @@ -239,7 +262,7 @@ uint8_t Si5351::set_freq(uint64_t freq, uint64_t pll_freq, enum si5351_clock clk if(lock_pllb == SI5351_CLK1) { // We can't have a 2nd output < 1.024 MHz or >= 112.5 MHz on the same PLL unless exact same freq, so exit - if((freq >= SI5351_MULTISYNTH_SHARE_MAX * SI5351_FREQ_MULT + if((freq >= SI5351_MULTISYNTH_SHARE_MAX * SI5351_FREQ_MULT || freq < SI5351_CLKOUT_MIN_FREQ * SI5351_FREQ_MULT * 128) && freq != clk2_freq) { clk2_freq = 0; @@ -262,11 +285,11 @@ uint8_t Si5351::set_freq(uint64_t freq, uint64_t pll_freq, enum si5351_clock clk write_pll = 1; set_ms_source(SI5351_CLK2, SI5351_PLLB); } - + if(freq >= SI5351_MULTISYNTH_SHARE_MAX * SI5351_FREQ_MULT || freq < SI5351_CLKOUT_MIN_FREQ * SI5351_FREQ_MULT * 128) { lock_pllb = SI5351_CLK2; - + if(clk1_freq != 0) { // Recalc and rewrite the multisynth parameters on CLK1 @@ -280,7 +303,7 @@ uint8_t Si5351::set_freq(uint64_t freq, uint64_t pll_freq, enum si5351_clock clk { lock_pllb = SI5351_CLKNONE; } - + target_pll = SI5351_PLLB; clk2_freq = freq; break; @@ -291,7 +314,7 @@ uint8_t Si5351::set_freq(uint64_t freq, uint64_t pll_freq, enum si5351_clock clk // Set multisynth registers (MS must be set before PLL) set_ms(clk, ms_reg, int_mode, r_div, div_by_4); - + // Set PLL if necessary if(write_pll == 1) { @@ -316,7 +339,7 @@ void Si5351::set_pll(uint64_t pll_freq, enum si5351_pll target_pll) pll_calc(pll_freq, &pll_reg, ref_correction); - // Derive the register values to write + // Derive the register values to write // Prepare an array for parameters to be written to uint8_t *params = new uint8_t[20]; @@ -446,7 +469,7 @@ void Si5351::set_ms(enum si5351_clock clk, struct Si5351RegSet ms_reg, uint8_t i si5351_write_bulk(SI5351_CLK7_PARAMETERS, i, params); break; } - + set_int(clk, int_mode); ms_div(clk, r_div, div_by_4); @@ -579,7 +602,7 @@ void Si5351::set_phase(enum si5351_clock clk, uint8_t phase) { // Mask off the upper bit since it is reserved phase = phase & 0b01111111; - + si5351_write(SI5351_CLK0_PHASE_OFFSET + (uint8_t)clk, phase); } @@ -638,7 +661,7 @@ void Si5351::set_ms_source(enum si5351_clock clk, enum si5351_pll pll) { reg_val |= SI5351_CLK_PLL_SELECT; } - + si5351_write(SI5351_CLK0_CTRL + (uint8_t)clk, reg_val); } @@ -655,7 +678,7 @@ void Si5351::set_int(enum si5351_clock clk, uint8_t enable) { uint8_t reg_val; reg_val = si5351_read(SI5351_CLK0_CTRL + (uint8_t)clk); - + if(enable == 1) { reg_val |= (SI5351_CLK_INTEGER_MODE); @@ -664,9 +687,9 @@ void Si5351::set_int(enum si5351_clock clk, uint8_t enable) { reg_val &= ~(SI5351_CLK_INTEGER_MODE); } - + si5351_write(SI5351_CLK0_CTRL + (uint8_t)clk, reg_val); - + // Integer mode indication switch(clk) { @@ -698,7 +721,7 @@ void Si5351::set_clock_pwr(enum si5351_clock clk, uint8_t pwr) { uint8_t reg_val, reg; reg_val = si5351_read(SI5351_CLK0_CTRL + (uint8_t)clk); - + if(pwr == 1) { reg_val &= 0b01111111; @@ -707,7 +730,7 @@ void Si5351::set_clock_pwr(enum si5351_clock clk, uint8_t pwr) { reg_val |= 0b10000000; } - + si5351_write(SI5351_CLK0_CTRL + (uint8_t)clk, reg_val); } @@ -724,7 +747,7 @@ void Si5351::set_clock_invert(enum si5351_clock clk, uint8_t inv) { uint8_t reg_val; reg_val = si5351_read(SI5351_CLK0_CTRL + (uint8_t)clk); - + if(inv == 1) { reg_val |= (SI5351_CLK_INVERT); @@ -733,7 +756,7 @@ void Si5351::set_clock_invert(enum si5351_clock clk, uint8_t inv) { reg_val &= ~(SI5351_CLK_INVERT); } - + si5351_write(SI5351_CLK0_CTRL + (uint8_t)clk, reg_val); } @@ -754,10 +777,10 @@ void Si5351::set_clock_source(enum si5351_clock clk, enum si5351_clock_source sr { uint8_t reg_val; reg_val = si5351_read(SI5351_CLK0_CTRL + (uint8_t)clk); - + // Clear the bits first reg_val &= ~(SI5351_CLK_INPUT_MASK); - + switch(src) { case SI5351_CLK_SRC_XTAL: @@ -771,7 +794,7 @@ void Si5351::set_clock_source(enum si5351_clock clk, enum si5351_clock_source sr { return; } - + reg_val |= (SI5351_CLK_INPUT_MULTISYNTH_0_4); break; case SI5351_CLK_SRC_MS: @@ -780,7 +803,7 @@ void Si5351::set_clock_source(enum si5351_clock clk, enum si5351_clock_source sr default: return; } - + si5351_write(SI5351_CLK0_CTRL + (uint8_t)clk, reg_val); } @@ -799,7 +822,7 @@ void Si5351::set_clock_source(enum si5351_clock clk, enum si5351_clock_source sr void Si5351::set_clock_disable(enum si5351_clock clk, enum si5351_clock_disable dis_state) { uint8_t reg_val, reg; - + if (clk >= SI5351_CLK0 && clk <= SI5351_CLK3) { reg = SI5351_CLK3_0_DISABLE_STATE; @@ -808,9 +831,9 @@ void Si5351::set_clock_disable(enum si5351_clock clk, enum si5351_clock_disable { reg = SI5351_CLK7_4_DISABLE_STATE; } - + reg_val = si5351_read(reg); - + if (clk >= SI5351_CLK0 && clk <= SI5351_CLK3) { reg_val &= ~(0b11 << (clk * 2)); @@ -821,7 +844,7 @@ void Si5351::set_clock_disable(enum si5351_clock clk, enum si5351_clock_disable reg_val &= ~(0b11 << ((clk - 4) * 2)); reg_val |= dis_state << ((clk - 4) * 2); } - + si5351_write(reg, reg_val); } @@ -842,7 +865,7 @@ void Si5351::set_clock_fanout(enum si5351_clock_fanout fanout, uint8_t enable) { uint8_t reg_val; reg_val = si5351_read(SI5351_FANOUT_ENABLE); - + switch(fanout) { case SI5351_FANOUT_CLKIN: @@ -876,10 +899,54 @@ void Si5351::set_clock_fanout(enum si5351_clock_fanout fanout, uint8_t enable) } break; } - + si5351_write(SI5351_FANOUT_ENABLE, reg_val); } +/* + * set_pll_input(enum si5351_pll pll, enum si5351_pll_input input) + * + * pll - Which PLL to use as the source + * (use the si5351_pll enum) + * input - Which reference oscillator to use as PLL input + * (use the si5351_pll_input enum) + * + * Set the desired reference oscillator source for the given PLL. + */ +void Si5351::set_pll_input(enum si5351_pll pll, enum si5351_pll_input input) +{ + uint8_t reg_val; + reg_val = si5351_read(SI5351_PLL_INPUT_SOURCE); + + switch(pll) + { + case SI5351_PLLA: + if(input == SI5351_PLL_INPUT_CLKIN) + { + reg_val |= SI5351_PLLA_SOURCE; + } + else + { + reg_val &= ~(SI5351_PLLA_SOURCE); + } + break; + case SI5351_PLLB: + if(input == SI5351_PLL_INPUT_CLKIN) + { + reg_val |= SI5351_PLLB_SOURCE; + } + else + { + reg_val &= ~(SI5351_PLLB_SOURCE); + } + break; + default: + return; + } + + si5351_write(SI5351_PLL_INPUT_SOURCE, reg_val); +} + uint8_t Si5351::si5351_write_bulk(uint8_t addr, uint8_t bytes, uint8_t *data) { Wire.beginTransmission(SI5351_BUS_BASE_ADDR); @@ -913,7 +980,7 @@ uint8_t Si5351::si5351_read(uint8_t addr) { reg_val = Wire.read(); } - + return reg_val; } @@ -961,7 +1028,7 @@ uint64_t Si5351::pll_calc(uint64_t freq, struct Si5351RegSet *reg, int32_t corre lltmp *= denom; do_div(lltmp, ref_freq); rfrac = lltmp; - + b = (((uint64_t)(freq % ref_freq)) * RFRAC_DENOM) / ref_freq; c = b ? RFRAC_DENOM : 1; @@ -1030,10 +1097,10 @@ uint64_t Si5351::multisynth_calc(uint64_t freq, uint64_t pll_freq, struct Si5351 { // Preset PLL, so return the actual freq for these params instead of PLL freq ret_val = 1; - + // Determine integer part of feedback equation a = pll_freq / freq; - + if (a < SI5351_MULTISYNTH_A_MIN) { freq = pll_freq / SI5351_MULTISYNTH_A_MIN; @@ -1042,7 +1109,7 @@ uint64_t Si5351::multisynth_calc(uint64_t freq, uint64_t pll_freq, struct Si5351 { freq = pll_freq / SI5351_MULTISYNTH_A_MAX; } - + b = (pll_freq % freq * RFRAC_DENOM) / freq; c = b ? RFRAC_DENOM : 1; } @@ -1105,7 +1172,7 @@ void Si5351::update_int_status(struct Si5351IntStatus *int_status) void Si5351::ms_div(enum si5351_clock clk, uint8_t r_div, uint8_t div_by_4) { uint8_t reg_val, reg_addr; - + switch(clk) { case SI5351_CLK0: @@ -1131,12 +1198,12 @@ void Si5351::ms_div(enum si5351_clock clk, uint8_t r_div, uint8_t div_by_4) case SI5351_CLK7: return; } - + reg_val = si5351_read(reg_addr); - + // Clear the relevant bits reg_val &= ~(0x7c); - + if(div_by_4 == 0) { reg_val &= ~(SI5351_OUTPUT_CLK_DIVBY4); @@ -1145,16 +1212,16 @@ void Si5351::ms_div(enum si5351_clock clk, uint8_t r_div, uint8_t div_by_4) { reg_val |= (SI5351_OUTPUT_CLK_DIVBY4); } - + reg_val |= (r_div << SI5351_OUTPUT_CLK_DIV_SHIFT); - + si5351_write(reg_addr, reg_val); } uint8_t Si5351::select_r_div(uint64_t *freq) { uint8_t r_div = SI5351_OUTPUT_CLK_DIV_1; - + // Choose the correct R divider if((*freq >= SI5351_CLKOUT_MIN_FREQ * SI5351_FREQ_MULT) && (*freq < SI5351_CLKOUT_MIN_FREQ * SI5351_FREQ_MULT * 2)) { @@ -1191,6 +1258,6 @@ uint8_t Si5351::select_r_div(uint64_t *freq) r_div = SI5351_OUTPUT_CLK_DIV_2; *freq *= 2ULL; } - + return r_div; } diff --git a/src/si5351.h b/src/si5351.h index 23a328e..1128b2d 100644 --- a/src/si5351.h +++ b/src/si5351.h @@ -218,25 +218,27 @@ * @SI5351_VARIANT_B: Si5351B (8 output clocks, XTAL/VXCO input) * @SI5351_VARIANT_C: Si5351C (8 output clocks, XTAL/CLKIN input) */ -enum si5351_variant { - SI5351_VARIANT_A = 1, - SI5351_VARIANT_A3 = 2, - SI5351_VARIANT_B = 3, - SI5351_VARIANT_C = 4, -}; + enum si5351_variant {SI5351_VARIANT_A, SI5351_VARIANT_A3, SI5351_VARIANT_B, + SI5351_VARIANT_C}; + + enum si5351_clock {SI5351_CLK0, SI5351_CLK1, SI5351_CLK2, SI5351_CLK3, + SI5351_CLK4, SI5351_CLK5, SI5351_CLK6, SI5351_CLK7, SI5351_CLKNONE}; -enum si5351_clock {SI5351_CLK0, SI5351_CLK1, SI5351_CLK2, SI5351_CLK3, - SI5351_CLK4, SI5351_CLK5, SI5351_CLK6, SI5351_CLK7, SI5351_CLKNONE}; + enum si5351_pll {SI5351_PLLA, SI5351_PLLB}; -enum si5351_pll {SI5351_PLLA, SI5351_PLLB}; + enum si5351_drive {SI5351_DRIVE_2MA, SI5351_DRIVE_4MA, SI5351_DRIVE_6MA, + SI5351_DRIVE_8MA}; -enum si5351_drive {SI5351_DRIVE_2MA, SI5351_DRIVE_4MA, SI5351_DRIVE_6MA, SI5351_DRIVE_8MA}; + enum si5351_clock_source {SI5351_CLK_SRC_XTAL, SI5351_CLK_SRC_CLKIN, + SI5351_CLK_SRC_MS0, SI5351_CLK_SRC_MS}; -enum si5351_clock_source {SI5351_CLK_SRC_XTAL, SI5351_CLK_SRC_CLKIN, SI5351_CLK_SRC_MS0, SI5351_CLK_SRC_MS}; + enum si5351_clock_disable {SI5351_CLK_DISABLE_LOW, SI5351_CLK_DISABLE_HIGH, + SI5351_CLK_DISABLE_HI_Z, SI5351_CLK_DISABLE_NEVER}; -enum si5351_clock_disable {SI5351_CLK_DISABLE_LOW, SI5351_CLK_DISABLE_HIGH, SI5351_CLK_DISABLE_HI_Z, SI5351_CLK_DISABLE_NEVER}; + enum si5351_clock_fanout {SI5351_FANOUT_CLKIN, SI5351_FANOUT_XO, + SI5351_FANOUT_MS}; -enum si5351_clock_fanout {SI5351_FANOUT_CLKIN, SI5351_FANOUT_XO, SI5351_FANOUT_MS}; + enum si5351_pll_input{SI5351_PLL_INPUT_XO, SI5351_PLL_INPUT_CLKIN}; /* Struct definitions */ @@ -286,6 +288,7 @@ class Si5351 void set_clock_source(enum si5351_clock, enum si5351_clock_source); void set_clock_disable(enum si5351_clock, enum si5351_clock_disable); void set_clock_fanout(enum si5351_clock_fanout, uint8_t); + void set_pll_input(enum si5351_pll, enum si5351_pll_input); uint8_t si5351_write_bulk(uint8_t, uint8_t, uint8_t *); uint8_t si5351_write(uint8_t, uint8_t); uint8_t si5351_read(uint8_t);