From 5177f954ae7b570e7842a69793baf83a5ab80478 Mon Sep 17 00:00:00 2001 From: Bruce MacKinnon Date: Sat, 10 Oct 2020 13:46:19 -0400 Subject: [PATCH 1/5] Small refactoring to allow other I2C interfaces --- src/ArduinoInterface.h | 72 +++++++++++++++++++++++++++++++++++++++ src/I2CInterface.h | 49 ++++++++++++++++++++++++++ src/STM32_HAL_Interface.h | 46 +++++++++++++++++++++++++ src/si5351.cpp | 55 +++++++++++------------------- src/si5351.h | 4 +-- 5 files changed, 188 insertions(+), 38 deletions(-) create mode 100644 src/ArduinoInterface.h create mode 100644 src/I2CInterface.h create mode 100644 src/STM32_HAL_Interface.h diff --git a/src/ArduinoInterface.h b/src/ArduinoInterface.h new file mode 100644 index 0000000..fb974f8 --- /dev/null +++ b/src/ArduinoInterface.h @@ -0,0 +1,72 @@ +/* + * 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" + +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..8dc0055 --- /dev/null +++ b/src/I2CInterface.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + virtual uint8_t check_address(uint8_t i2c_bus_addr) = 0; + + /** + * Standard read operation. + */ + virtual uint8_t read(uint8_t i2c_bus_addr, uint8_t addr) = 0; + + /** + * Standard write operation. + */ + virtual uint8_t write(uint8_t i2c_bus_addr, uint8_t addr, uint8_t data) = 0; + + /** + * Multi-byte write operation + */ + 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..0e09451 --- /dev/null +++ b/src/STM32_HAL_Interface.h @@ -0,0 +1,46 @@ +/* + * 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 +#include "I2CInterface.h" + +// An STM32/HAL based implementation of the I2CInterface. +// +// NOT IMPLEMENTED YET!! +// +class STM32_HAL_Interface : public I2C_Interface { +public: + // TODO: WILL PASS THE HAL I2C STRUCTURE HERE + STM32_HAL_Interface() { + } + uint8_t check_address(uint8_t i2c_bus_addr) { + return 0; + } + uint8_t read(uint8_t i2c_bus_addr, uint8_t addr) { + return 0; + } + uint8_t write(uint8_t i2c_bus_addr, uint8_t addr, uint8_t data) { + return 0; + } + uint8_t write_bulk(uint8_t i2c_bus_addr, uint8_t addr, uint8_t bytes, uint8_t *data) { + return 0; + } +}; + +#endif diff --git a/src/si5351.cpp b/src/si5351.cpp index e140d65..97dd99b 100644 --- a/src/si5351.cpp +++ b/src/si5351.cpp @@ -24,10 +24,18 @@ #include +// Bring in the relevant interface to the I2C bus +#ifndef STM32 +#include "STM32_HAL_Interface.h" +static STM32_HAL_Interface I2C_Interface_Instance; +#else #include "Arduino.h" #include "Wire.h" -#include "si5351.h" +#include "ArduinoInterface.h" +static ArduinoInterface I2C_Interface_Instance; +#endif +#include "si5351.h" /********************/ /* Public functions */ @@ -36,6 +44,9 @@ Si5351::Si5351(uint8_t i2c_addr): i2c_bus_addr(i2c_addr) { + // Connect to the appropriate I2C interface + i2c_interface = &I2C_Interface_Instance; + xtal_freq[0] = SI5351_XTAL_FREQ; // Start by using XO ref osc as default for each PLL @@ -62,13 +73,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 +571,7 @@ void Si5351::set_pll(uint64_t pll_freq, enum si5351_pll target_pll) pllb_freq = pll_freq; } - delete params; + delete [] params; } /* @@ -672,7 +678,7 @@ void Si5351::set_ms(enum si5351_clock clk, struct Si5351RegSet ms_reg, uint8_t i break; } - delete params; + delete [] params; } /* @@ -1240,7 +1246,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 +1315,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..0092ebc 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 */ @@ -330,6 +329,7 @@ class Si5351 uint8_t clkin_div; uint8_t i2c_bus_addr; bool clk_first_set[8]; + I2CInterface* i2c_interface; }; #endif /* SI5351_H_ */ From e392bbc85e06dd9c12b23534757f9b040e4f24ee Mon Sep 17 00:00:00 2001 From: Bruce MacKinnon Date: Sat, 10 Oct 2020 13:55:14 -0400 Subject: [PATCH 2/5] Improved comments --- src/ArduinoInterface.h | 4 ++++ src/si5351.cpp | 4 +++- src/si5351.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ArduinoInterface.h b/src/ArduinoInterface.h index fb974f8..b13a305 100644 --- a/src/ArduinoInterface.h +++ b/src/ArduinoInterface.h @@ -21,6 +21,10 @@ #include "Wire.h" #include "I2CInterface.h" +/** + * The standard Ardiuno way of talking to I2C + * via the Wire.h library. + */ class ArduinoInterface : public I2CInterface { public: diff --git a/src/si5351.cpp b/src/si5351.cpp index 97dd99b..e8c8323 100644 --- a/src/si5351.cpp +++ b/src/si5351.cpp @@ -24,7 +24,9 @@ #include -// Bring in the relevant interface to the I2C bus +// Bring in the relevant interface to the I2C bus. This has been +// abstracted to allow the library to be used in differnet +// hardware environments. #ifndef STM32 #include "STM32_HAL_Interface.h" static STM32_HAL_Interface I2C_Interface_Instance; diff --git a/src/si5351.h b/src/si5351.h index 0092ebc..7579dd0 100644 --- a/src/si5351.h +++ b/src/si5351.h @@ -329,6 +329,7 @@ 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; }; From 8a2ad1219a0ec2bd2d0a7ca2949248389333ee0f Mon Sep 17 00:00:00 2001 From: Bruce MacKinnon Date: Sat, 10 Oct 2020 14:57:39 -0400 Subject: [PATCH 3/5] Corrected some typos, added TTestInterface for debug --- src/STM32_HAL_Interface.h | 2 +- src/TestInterface.h | 53 +++++++++++++++++++++++++++++++++++++++ src/si5351.cpp | 19 ++++++++------ 3 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 src/TestInterface.h diff --git a/src/STM32_HAL_Interface.h b/src/STM32_HAL_Interface.h index 0e09451..1df9597 100644 --- a/src/STM32_HAL_Interface.h +++ b/src/STM32_HAL_Interface.h @@ -24,7 +24,7 @@ // // NOT IMPLEMENTED YET!! // -class STM32_HAL_Interface : public I2C_Interface { +class STM32_HAL_Interface : public I2CInterface { public: // TODO: WILL PASS THE HAL I2C STRUCTURE HERE STM32_HAL_Interface() { 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 e8c8323..7b4ffaf 100644 --- a/src/si5351.cpp +++ b/src/si5351.cpp @@ -24,17 +24,22 @@ #include +#define SI5351_DEMO + // Bring in the relevant interface to the I2C bus. This has been // abstracted to allow the library to be used in differnet // hardware environments. -#ifndef STM32 -#include "STM32_HAL_Interface.h" -static STM32_HAL_Interface I2C_Interface_Instance; +#if defined(SI5351_STM32) + #include "STM32_HAL_Interface.h" + static STM32_HAL_Interface I2C_Interface_Instance; +#elif defined(SI5351_DEMO) + #include "TestInterface.h" + static TestInterface I2C_Interface_Instance; #else -#include "Arduino.h" -#include "Wire.h" -#include "ArduinoInterface.h" -static ArduinoInterface I2C_Interface_Instance; + #include "Arduino.h" + #include "Wire.h" + #include "ArduinoInterface.h" + static ArduinoInterface I2C_Interface_Instance; #endif #include "si5351.h" From 3bb7651bc86d75eb50fc666ca84172756644692b Mon Sep 17 00:00:00 2001 From: Bruce MacKinnon Date: Sat, 10 Oct 2020 16:03:29 -0400 Subject: [PATCH 4/5] Initial implementation of STM32 interface --- src/I2CInterface.h | 4 ++++ src/STM32_HAL_Interface.h | 49 ++++++++++++++++++++++++++++++++++----- src/si5351.cpp | 8 +++++-- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/I2CInterface.h b/src/I2CInterface.h index 8dc0055..65aa2fa 100644 --- a/src/I2CInterface.h +++ b/src/I2CInterface.h @@ -27,21 +27,25 @@ class I2CInterface { /** * 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; }; diff --git a/src/STM32_HAL_Interface.h b/src/STM32_HAL_Interface.h index 1df9597..a0d744a 100644 --- a/src/STM32_HAL_Interface.h +++ b/src/STM32_HAL_Interface.h @@ -26,21 +26,58 @@ // class STM32_HAL_Interface : public I2CInterface { public: - // TODO: WILL PASS THE HAL I2C STRUCTURE HERE - STM32_HAL_Interface() { + + STM32_HAL_Interface(I2C_HandleTypeDef* hi2c) + : _hi2c(hi2c), + _errorCount(0), + _timeoutMs(10) { } + uint8_t check_address(uint8_t i2c_bus_addr) { - return 0; + 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) { - return 0; + 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) { - return 0; + // 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) { - return 0; + // 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/si5351.cpp b/src/si5351.cpp index 7b4ffaf..9ba9851 100644 --- a/src/si5351.cpp +++ b/src/si5351.cpp @@ -24,7 +24,11 @@ #include -#define SI5351_DEMO +// Uncomment the relevant hardware environment. Arduino +// is the default +//#define SI5351_DEMO +#define SI5351_STM32 +//#define SI5351_ARDINO // Bring in the relevant interface to the I2C bus. This has been // abstracted to allow the library to be used in differnet @@ -35,7 +39,7 @@ #elif defined(SI5351_DEMO) #include "TestInterface.h" static TestInterface I2C_Interface_Instance; -#else +#elif defined(SI5351_ARDUINO) #include "Arduino.h" #include "Wire.h" #include "ArduinoInterface.h" From 7fcbe068d46552e022ad49e86216c92c46f1be1d Mon Sep 17 00:00:00 2001 From: Bruce MacKinnon Date: Sat, 10 Oct 2020 17:07:29 -0400 Subject: [PATCH 5/5] Test successfully on STM32 --- src/STM32_HAL_Interface.h | 3 +++ src/si5351.cpp | 43 +++++++++++++++++++++++---------------- src/si5351.h | 13 ++++++++++++ 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/STM32_HAL_Interface.h b/src/STM32_HAL_Interface.h index a0d744a..f2d5f73 100644 --- a/src/STM32_HAL_Interface.h +++ b/src/STM32_HAL_Interface.h @@ -18,6 +18,9 @@ #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. diff --git a/src/si5351.cpp b/src/si5351.cpp index 9ba9851..dd62d17 100644 --- a/src/si5351.cpp +++ b/src/si5351.cpp @@ -24,26 +24,18 @@ #include -// Uncomment the relevant hardware environment. Arduino -// is the default -//#define SI5351_DEMO -#define SI5351_STM32 -//#define SI5351_ARDINO - -// Bring in the relevant interface to the I2C bus. This has been -// abstracted to allow the library to be used in differnet -// hardware environments. -#if defined(SI5351_STM32) - #include "STM32_HAL_Interface.h" - static STM32_HAL_Interface I2C_Interface_Instance; -#elif defined(SI5351_DEMO) - #include "TestInterface.h" - static TestInterface I2C_Interface_Instance; -#elif defined(SI5351_ARDUINO) +// 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" @@ -55,9 +47,24 @@ Si5351::Si5351(uint8_t i2c_addr): i2c_bus_addr(i2c_addr) { - // Connect to the appropriate I2C interface + // 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 diff --git a/src/si5351.h b/src/si5351.h index 7579dd0..c407f92 100644 --- a/src/si5351.h +++ b/src/si5351.h @@ -278,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); @@ -317,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 *); 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