From 8bbd75a4e9fc1eab0ae7f6b28937d0b130b09537 Mon Sep 17 00:00:00 2001 From: Jason Milldrum Date: Mon, 1 Jan 2018 13:48:24 -0800 Subject: [PATCH 1/3] Add check for device on I2C bus to init() --- README.md | 11 +++- examples/si5351_example/si5351_example.ino | 8 ++- library.properties | 2 +- src/si5351.cpp | 68 +++++++++++++++------- src/si5351.h | 8 ++- 5 files changed, 67 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 3c8d288..bea86f4 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,9 @@ Before you do anything with the Si5351, you will need to include the "si5351.h" Now in the _Setup()_ function, let's initialize communications with the Si5351, specify the load capacitance of the reference crystal, that we want to use the default reference oscillator frequency of 25 MHz (the second argument of "0" indicates that we want to use the default), and that we will apply no frequency correction at this point (the third argument of "0"): - si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0); + i2c_found = si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0); + +The _init()_ method returns a _bool_ which indicates whether the Arduino can communicate with a device on the I2C bus at the specified address (it does not verify that the device is an actual Si5351, but this is useful for ensuring that I2C communication is working). Next, let's set the CLK0 output to 14 MHz: @@ -277,12 +279,15 @@ Public Methods * * xtal_load_c - Crystal load capacitance. Use the SI5351_CRYSTAL_LOAD_*PF * defines in the header file - * ref_osc_freq - Crystal/reference oscillator frequency in 1 Hz increments. + * xo_freq - Crystal/reference oscillator frequency in 1 Hz increments. * Defaults to 25000000 if a 0 is used here. * corr - Frequency correction constant in parts-per-billion * + * Returns a boolean that indicates whether a device was found on the desired + * I2C address. + * */ -void Si5351::init(uint8_t xtal_load_c, uint32_t ref_osc_freq, uint32_t ref_osc_freq) +bool Si5351::init(uint8_t xtal_load_c, uint32_t ref_osc_freq, uint32_t ref_osc_freq) ``` ### reset() ``` diff --git a/examples/si5351_example/si5351_example.ino b/examples/si5351_example/si5351_example.ino index b65c778..93c1aa7 100644 --- a/examples/si5351_example/si5351_example.ino +++ b/examples/si5351_example/si5351_example.ino @@ -24,9 +24,15 @@ Si5351 si5351; void setup() { + bool i2c_found; + // Start serial and initialize the Si5351 Serial.begin(57600); - si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0); + i2c_found = si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0); + if(i2c_found) + { + Serial.println("Device not found on I2C bus!") + } // Set CLK0 to output 14 MHz si5351.set_freq(1400000000ULL, SI5351_CLK0); diff --git a/library.properties b/library.properties index e87bcc3..dc83bbb 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Etherkit Si5351 -version=2.1.0 +version=2.1.1 author=Jason Milldrum maintainer=Jason Milldrum sentence=A full-featured library for the Si5351 series of clock generator ICs from Silicon Labs diff --git a/src/si5351.cpp b/src/si5351.cpp index 6ec7276..d8062b9 100644 --- a/src/si5351.cpp +++ b/src/si5351.cpp @@ -36,16 +36,16 @@ Si5351::Si5351(uint8_t i2c_addr): i2c_bus_addr(i2c_addr) { - dev_status.SYS_INIT = 0; - dev_status.LOL_B = 0; - dev_status.LOL_A = 0; - dev_status.LOS = 0; - dev_status.REVID = 0; - - dev_int_status.SYS_INIT_STKY = 0; - dev_int_status.LOL_B_STKY = 0; - dev_int_status.LOL_A_STKY = 0; - dev_int_status.LOS_STKY = 0; + // dev_status.SYS_INIT = 0; + // dev_status.LOL_B = 0; + // dev_status.LOL_A = 0; + // dev_status.LOS = 0; + // dev_status.REVID = 0; + // + // dev_int_status.SYS_INIT_STKY = 0; + // dev_int_status.LOL_B_STKY = 0; + // dev_int_status.LOL_A_STKY = 0; + // dev_int_status.LOS_STKY = 0; xtal_freq[0] = SI5351_XTAL_FREQ; @@ -67,29 +67,53 @@ Si5351::Si5351(uint8_t i2c_addr): * Defaults to 25000000 if a 0 is used here. * corr - Frequency correction constant in parts-per-billion * + * Returns a boolean that indicates whether a device was found on the desired + * I2C address. + * */ -void Si5351::init(uint8_t xtal_load_c, uint32_t xo_freq, int32_t corr) +bool Si5351::init(uint8_t xtal_load_c, uint32_t xo_freq, int32_t corr) { // Start I2C comms Wire.begin(); - // Set crystal load capacitance - si5351_write(SI5351_CRYSTAL_LOAD, (xtal_load_c & SI5351_CRYSTAL_LOAD_MASK) | 0b00010010); + // Check for a device on the bus, bail out if it is not there + Wire.beginTransmission(i2c_bus_addr); + uint8_t reg_val; + reg_val = Wire.endTransmission(); - // Set up the XO reference frequency - if (xo_freq != 0) + if(reg_val == 0) { - set_ref_freq(xo_freq, SI5351_PLL_INPUT_XO); + // Wait for SYS_INIT flag to be clear, indicating that device is ready + uint8_t status_reg = 0; + do + { + status_reg = si5351_read(SI5351_DEVICE_STATUS); + } while (status_reg >> 7 == 1); + + // Set crystal load capacitance + si5351_write(SI5351_CRYSTAL_LOAD, (xtal_load_c & SI5351_CRYSTAL_LOAD_MASK) | 0b00010010); + + // Set up the XO reference frequency + if (xo_freq != 0) + { + set_ref_freq(xo_freq, SI5351_PLL_INPUT_XO); + } + else + { + set_ref_freq(SI5351_XTAL_FREQ, SI5351_PLL_INPUT_XO); + } + + // Set the frequency calibration for the XO + set_correction(corr, SI5351_PLL_INPUT_XO); + + reset(); + + return true; } else { - set_ref_freq(SI5351_XTAL_FREQ, SI5351_PLL_INPUT_XO); + return false; } - - // Set the frequency calibration for the XO - set_correction(corr, SI5351_PLL_INPUT_XO); - - reset(); } /* diff --git a/src/si5351.h b/src/si5351.h index 07a51dc..c1c4548 100644 --- a/src/si5351.h +++ b/src/si5351.h @@ -280,7 +280,7 @@ class Si5351 { public: Si5351(uint8_t i2c_addr = SI5351_BUS_BASE_ADDR); - void init(uint8_t, uint32_t, int32_t); + bool init(uint8_t, uint32_t, int32_t); void reset(void); uint8_t set_freq(uint64_t, enum si5351_clock); uint8_t set_freq_manual(uint64_t, uint64_t, enum si5351_clock); @@ -306,8 +306,10 @@ class Si5351 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); - struct Si5351Status dev_status; - struct Si5351IntStatus dev_int_status; + struct Si5351Status dev_status = {.SYS_INIT = 0, .LOL_B = 0, .LOL_A = 0, + .LOS = 0, .REVID = 0}; + struct Si5351IntStatus dev_int_status = {.SYS_INIT_STKY = 0, .LOL_B_STKY = 0, + .LOL_A_STKY = 0, .LOS_STKY = 0}; enum si5351_pll pll_assignment[8]; uint64_t clk_freq[8]; uint64_t plla_freq; From 257444a569670a9d4e34a8d4bb67e11dfc59719d Mon Sep 17 00:00:00 2001 From: Jason Milldrum Date: Tue, 2 Jan 2018 12:40:30 -0800 Subject: [PATCH 2/3] Fix error in example sketch --- README.md | 4 ++++ examples/si5351_example/si5351_example.ino | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bea86f4..c442372 100644 --- a/README.md +++ b/README.md @@ -711,6 +711,10 @@ This library does not currently support the spread spectrum function of the Si53 Changelog --------- +* v2.1.1 + + * Add bool return value to _init()_ indicating whether a device is on the I2C bus + * v2.1.0 * Add support for reference frequencies and corrections for both the XO and CLKIN diff --git a/examples/si5351_example/si5351_example.ino b/examples/si5351_example/si5351_example.ino index 93c1aa7..77ab26c 100644 --- a/examples/si5351_example/si5351_example.ino +++ b/examples/si5351_example/si5351_example.ino @@ -29,7 +29,7 @@ void setup() // Start serial and initialize the Si5351 Serial.begin(57600); i2c_found = si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0); - if(i2c_found) + if(!i2c_found) { Serial.println("Device not found on I2C bus!") } From d08ebcd0248a7f080cf61254153926f6782dfb92 Mon Sep 17 00:00:00 2001 From: Jason Milldrum Date: Mon, 15 Jan 2018 13:07:56 -0800 Subject: [PATCH 3/3] code cleanup' --- src/si5351.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/si5351.cpp b/src/si5351.cpp index d8062b9..5f512b8 100644 --- a/src/si5351.cpp +++ b/src/si5351.cpp @@ -36,17 +36,6 @@ Si5351::Si5351(uint8_t i2c_addr): i2c_bus_addr(i2c_addr) { - // dev_status.SYS_INIT = 0; - // dev_status.LOL_B = 0; - // dev_status.LOL_A = 0; - // dev_status.LOS = 0; - // dev_status.REVID = 0; - // - // dev_int_status.SYS_INIT_STKY = 0; - // dev_int_status.LOL_B_STKY = 0; - // dev_int_status.LOL_A_STKY = 0; - // dev_int_status.LOS_STKY = 0; - xtal_freq[0] = SI5351_XTAL_FREQ; // Start by using XO ref osc as default for each PLL