diff --git a/src/ArduinoInterface.h b/src/ArduinoInterface.h new file mode 100644 index 0000000..b13a305 --- /dev/null +++ b/src/ArduinoInterface.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2020 Bruce MacKinnon KC1FSZ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _ArduinoInterface_h +#define _ArduinoInterface_h + +#include "Arduino.h" +#include "Wire.h" +#include "I2CInterface.h" + +/** + * The standard Ardiuno way of talking to I2C + * via the Wire.h library. + */ +class ArduinoInterface : public I2CInterface { +public: + + ArduinoInterface() { + Wire.begin(); + } + + uint8_t check_address(uint8_t i2c_bus_addr) { + Wire.beginTransmission(i2c_bus_addr); + return Wire.endTransmission(); + } + + uint8_t read(uint8_t i2c_bus_addr, uint8_t addr) { + + uint8_t reg_val = 0; + + Wire.beginTransmission(i2c_bus_addr); + Wire.write(addr); + Wire.endTransmission(); + + Wire.requestFrom(i2c_bus_addr, (uint8_t)1, (uint8_t)false); + + while(Wire.available()) + { + reg_val = Wire.read(); + } + + return reg_val; + } + + uint8_t write(uint8_t i2c_bus_addr, uint8_t addr, uint8_t data) { + Wire.beginTransmission(i2c_bus_addr); + Wire.write(addr); + Wire.write(data); + return Wire.endTransmission(); + } + + uint8_t write_bulk(uint8_t i2c_bus_addr, uint8_t addr, uint8_t bytes, uint8_t *data) { + Wire.beginTransmission(i2c_bus_addr); + Wire.write(addr); + for(int i = 0; i < bytes; i++) + { + Wire.write(data[i]); + } + return Wire.endTransmission(); + } +}; + +#endif diff --git a/src/I2CInterface.h b/src/I2CInterface.h new file mode 100644 index 0000000..65aa2fa --- /dev/null +++ b/src/I2CInterface.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 Bruce MacKinnon KC1FSZ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _I2CInterface_h +#define _I2CInterface_h + +#include + +/** + * A generic interface for interacting with an I2C bus + */ +class I2CInterface { +public: + + /** + * Determmines whether a device is connected at the specified address. + * @return 0 if things are good, -1 if there is a problem. + */ + virtual uint8_t check_address(uint8_t i2c_bus_addr) = 0; + + /** + * Standard read operation. + * @return The received byte + */ + virtual uint8_t read(uint8_t i2c_bus_addr, uint8_t addr) = 0; + + /** + * Standard write operation. + * @return Then number of bytes written + */ + virtual uint8_t write(uint8_t i2c_bus_addr, uint8_t addr, uint8_t data) = 0; + + /** + * Multi-byte write operation + * @return The number of bytes written + */ + virtual uint8_t write_bulk(uint8_t i2c_bus_addr, uint8_t addr, uint8_t bytes, uint8_t *data) = 0; +}; + +#endif diff --git a/src/STM32_HAL_Interface.h b/src/STM32_HAL_Interface.h new file mode 100644 index 0000000..f2d5f73 --- /dev/null +++ b/src/STM32_HAL_Interface.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2020 Bruce MacKinnon KC1FSZ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _STM32_HAL_Interface_h +#define _STM32_HAL_Interface_h + +#include +// NOTE: Add the appropriate HAL include here: +#include "stm32f4xx_hal.h" + +#include "I2CInterface.h" + +// An STM32/HAL based implementation of the I2CInterface. +// +// NOT IMPLEMENTED YET!! +// +class STM32_HAL_Interface : public I2CInterface { +public: + + STM32_HAL_Interface(I2C_HandleTypeDef* hi2c) + : _hi2c(hi2c), + _errorCount(0), + _timeoutMs(10) { + } + + uint8_t check_address(uint8_t i2c_bus_addr) { + HAL_StatusTypeDef status = HAL_I2C_IsDeviceReady(_hi2c, (uint16_t)(i2c_bus_addr << 1), 1, _timeoutMs); + if (status == HAL_OK) { + return 0; + } else { + return -1; + } + } + + uint8_t read(uint8_t i2c_bus_addr, uint8_t addr) { + uint8_t reg_val = 0; + // NOTE: PER HAL DOCUMENTATION, ADDRESS NEEDS TO BE SHIFTED LEFT + HAL_StatusTypeDef status = HAL_I2C_Mem_Read(_hi2c, (uint16_t)(i2c_bus_addr << 1), (uint16_t)(addr), 1, + ®_val, 1, _timeoutMs); + if (status != HAL_OK) { + _errorCount++; + } + return reg_val; + } + + uint8_t write(uint8_t i2c_bus_addr, uint8_t addr, uint8_t data) { + // NOTE: PER HAL DOCUMENTATION, ADDRESS NEEDS TO BE SHIFTED LEFT + HAL_StatusTypeDef status = HAL_I2C_Mem_Write(_hi2c, (uint16_t)(i2c_bus_addr << 1), addr, 1, + &data, 1, _timeoutMs); + if (status != HAL_OK) { + _errorCount++; + } + return 1; + } + + uint8_t write_bulk(uint8_t i2c_bus_addr, uint8_t addr, uint8_t bytes, uint8_t *data) { + // NOTE: PER HAL DOCUMENTATION, ADDRESS NEEDS TO BE SHIFTED LEFT + HAL_StatusTypeDef status = HAL_I2C_Mem_Write(_hi2c, (uint16_t)(i2c_bus_addr << 1), addr, 1, + data, bytes, _timeoutMs); + if (status != HAL_OK) { + _errorCount++; + } + return bytes; + } + +private: + + I2C_HandleTypeDef* _hi2c; + int _errorCount; + uint32_t _timeoutMs; +}; + +#endif diff --git a/src/TestInterface.h b/src/TestInterface.h new file mode 100644 index 0000000..5d05179 --- /dev/null +++ b/src/TestInterface.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 Bruce MacKinnon KC1FSZ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _Test_Interface_h +#define _Test_Interface_h + +#include +#include +#include "I2CInterface.h" + +// A dummy interface for testing. +// +class TestInterface : public I2CInterface { +public: + TestInterface() { + printf("TestInterface initialized\n"); + } + uint8_t check_address(uint8_t i2c_bus_addr) { + printf("check_address\n"); + return 0; + } + uint8_t read(uint8_t i2c_bus_addr, uint8_t addr) { + printf("read(%x,%x)\n", i2c_bus_addr, addr); + return 0; + } + uint8_t write(uint8_t i2c_bus_addr, uint8_t addr, uint8_t data) { + printf("write(%x, %x, %x)\n", i2c_bus_addr, addr, data); + return 0; + } + uint8_t write_bulk(uint8_t i2c_bus_addr, uint8_t addr, uint8_t bytes, uint8_t *data) { + printf("write_bulk(%x, %x, ", i2c_bus_addr, addr); + for (int i = 0; i < bytes; i++) { + printf("%x ", data[i]); + } + printf(")\n"); + return 0; + } +}; + +#endif diff --git a/src/si5351.cpp b/src/si5351.cpp index e140d65..dd62d17 100644 --- a/src/si5351.cpp +++ b/src/si5351.cpp @@ -24,10 +24,21 @@ #include -#include "Arduino.h" -#include "Wire.h" -#include "si5351.h" +// Remove this to turn off the Arduino hardware environment. Arduino +// is the default. +#define SI5351_ARDUINO + +#if defined(SI5351_ARDUINO) + #include "Arduino.h" + #include "Wire.h" + #include "ArduinoInterface.h" + static ArduinoInterface I2C_Interface_Instance; +#else + #include "TestInterface.h" + static TestInterface I2C_Interface_Instance; +#endif +#include "si5351.h" /********************/ /* Public functions */ @@ -36,6 +47,24 @@ Si5351::Si5351(uint8_t i2c_addr): i2c_bus_addr(i2c_addr) { + // Connect to the default I2C interface + i2c_interface = &I2C_Interface_Instance; + + setup(); +} + +Si5351::Si5351(uint8_t i2c_addr, I2CInterface* i2c): + i2c_bus_addr(i2c_addr), + i2c_interface(i2c) +{ + setup(); +} + +/* + * Common setup code + */ +void Si5351::setup() { + xtal_freq[0] = SI5351_XTAL_FREQ; // Start by using XO ref osc as default for each PLL @@ -62,13 +91,8 @@ Si5351::Si5351(uint8_t i2c_addr): */ bool Si5351::init(uint8_t xtal_load_c, uint32_t xo_freq, int32_t corr) { - // Start I2C comms - Wire.begin(); - // 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(); + uint8_t reg_val = i2c_interface->check_address(i2c_bus_addr); if(reg_val == 0) { @@ -565,7 +589,7 @@ void Si5351::set_pll(uint64_t pll_freq, enum si5351_pll target_pll) pllb_freq = pll_freq; } - delete params; + delete [] params; } /* @@ -672,7 +696,7 @@ void Si5351::set_ms(enum si5351_clock clk, struct Si5351RegSet ms_reg, uint8_t i break; } - delete params; + delete [] params; } /* @@ -1240,7 +1264,7 @@ void Si5351::set_vcxo(uint64_t pll_freq, uint8_t ppm) // Write the parameters si5351_write_bulk(SI5351_PLLB_PARAMETERS, i, params); - delete params; + delete [] params; // Write the VCXO parameters vcxo_param = ((vcxo_param * ppm * SI5351_VCXO_MARGIN) / 100ULL) / 1000000ULL; @@ -1309,40 +1333,17 @@ void Si5351::set_ref_freq(uint32_t ref_freq, enum si5351_pll_input ref_osc) uint8_t Si5351::si5351_write_bulk(uint8_t addr, uint8_t bytes, uint8_t *data) { - Wire.beginTransmission(i2c_bus_addr); - Wire.write(addr); - for(int i = 0; i < bytes; i++) - { - Wire.write(data[i]); - } - return Wire.endTransmission(); - + return i2c_interface->write_bulk(i2c_bus_addr, addr, bytes, data); } uint8_t Si5351::si5351_write(uint8_t addr, uint8_t data) { - Wire.beginTransmission(i2c_bus_addr); - Wire.write(addr); - Wire.write(data); - return Wire.endTransmission(); + return i2c_interface->write(i2c_bus_addr, addr, data); } uint8_t Si5351::si5351_read(uint8_t addr) { - uint8_t reg_val = 0; - - Wire.beginTransmission(i2c_bus_addr); - Wire.write(addr); - Wire.endTransmission(); - - Wire.requestFrom(i2c_bus_addr, (uint8_t)1, (uint8_t)false); - - while(Wire.available()) - { - reg_val = Wire.read(); - } - - return reg_val; + return i2c_interface->read(i2c_bus_addr, addr); } /*********************/ diff --git a/src/si5351.h b/src/si5351.h index 59c16e9..c407f92 100644 --- a/src/si5351.h +++ b/src/si5351.h @@ -29,9 +29,8 @@ #ifndef SI5351_H_ #define SI5351_H_ -#include "Arduino.h" -#include "Wire.h" #include +#include "I2CInterface.h" /* Define definitions */ @@ -279,7 +278,19 @@ struct Si5351IntStatus class Si5351 { public: + + /** + * Use this constructor when using the (default) Arduino + * I2C interface. + */ Si5351(uint8_t i2c_addr = SI5351_BUS_BASE_ADDR); + + /** + * Use this constructor when explicitly passing the I2CInterface + * object. + */ + Si5351(uint8_t i2c_addr, I2CInterface* i2c); + bool init(uint8_t, uint32_t, int32_t); void reset(void); uint8_t set_freq(uint64_t, enum si5351_clock); @@ -318,6 +329,7 @@ class Si5351 enum si5351_pll_input pllb_ref_osc; uint32_t xtal_freq[2]; private: + void setup(); uint64_t pll_calc(enum si5351_pll, uint64_t, struct Si5351RegSet *, int32_t, uint8_t); uint64_t multisynth_calc(uint64_t, uint64_t, struct Si5351RegSet *); uint64_t multisynth67_calc(uint64_t, uint64_t, struct Si5351RegSet *); @@ -330,6 +342,8 @@ class Si5351 uint8_t clkin_div; uint8_t i2c_bus_addr; bool clk_first_set[8]; + // This is a connection to the I2C bus + I2CInterface* i2c_interface; }; #endif /* SI5351_H_ */ pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy