diff --git a/README.md b/README.md index 3c8d288..c442372 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() ``` @@ -706,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 b65c778..77ab26c 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..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 @@ -67,29 +56,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;