diff --git a/.cproject b/.cproject
index 8e9c816..c8e4f01 100644
--- a/.cproject
+++ b/.cproject
@@ -82,8 +82,8 @@
-
+
@@ -165,8 +165,8 @@
-
+
diff --git a/Core/Inc/si5351.h b/Core/Inc/si5351.h
index 4e3660a..94035a3 100644
--- a/Core/Inc/si5351.h
+++ b/Core/Inc/si5351.h
@@ -70,8 +70,6 @@ extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
-#include
-#include /* register map of the Si5351 */
/* #include could also be included */
/* Private includes ----------------------------------------------------------*/
@@ -105,7 +103,7 @@ typedef enum {
/* Exported macros -----------------------------------------------------------*/
#define __SI5351__ 1
-#define __SI5351_MINOR__ 1
+#define __SI5351_MINOR__ 2
#define __SI5351_PATCHLEVEL__ 0
#define SI5351_VERSION (__SI5351__ * 10000 \
@@ -127,7 +125,6 @@ int si5351_deinitialize(void);
si5351_inst_t si5351_init(void * i2c_handle, uint8_t i2c_address, uint32_t xtal_frequency);
int si5351_deinit(si5351_inst_t si5351_handle);
int si5351_i2c_ready(si5351_inst_t inst);
-int si5351_program(si5351_inst_t inst);
int si5351_enable_output(si5351_inst_t inst, uint8_t clk);
int si5351_disable_output(si5351_inst_t inst, uint8_t clk);
int si5351_set_clk0(si5351_inst_t inst, uint32_t frequency);
@@ -136,7 +133,10 @@ int si5351_set_clk(si5351_inst_t inst, uint8_t clk, uint32_t frequency, si5351_p
char * si5351_read_debug_msg(si5351_inst_t inst);
char * si5351_read_register_debug(si5351_inst_t inst, char *buf, size_t bufsize, uint8_t regaddr);
+/* some functions for getting information */
int si5351_get_instance(si5351_inst_t *inst);
+int si5351_get_i2c_address(si5351_inst_t inst);
+void* si5351_get_i2c_handle(si5351_inst_t inst);
/* under development */
int si5351_set_clk_phase(si5351_inst_t inst, uint8_t clk, uint32_t frequency, double phase, si5351_pll_t pll);
diff --git a/Core/Src/commands.c b/Core/Src/commands.c
index 11b1b81..7671243 100644
--- a/Core/Src/commands.c
+++ b/Core/Src/commands.c
@@ -16,7 +16,7 @@
#include //strchr
#include //bsearch
#include "helper.h" //ltrim
-#include "stm32_si5351.h"
+#include "si5351.h"
#include "commands.h"
diff --git a/Core/Src/main.c b/Core/Src/main.c
index 2c94fbb..8668ea2 100644
--- a/Core/Src/main.c
+++ b/Core/Src/main.c
@@ -24,7 +24,7 @@
/* USER CODE BEGIN Includes */
#include
#include "at1_defines.h"
-#include "stm32_si5351.h"
+#include "si5351.h"
#include "commands.h"
#include
#include "ringbuf.h"
diff --git a/Core/Src/si5351.c b/Core/Src/si5351.c
index 2311418..9fb5d9d 100644
--- a/Core/Src/si5351.c
+++ b/Core/Src/si5351.c
@@ -1,9 +1,9 @@
/**
- ******************************************************************************
- * @file stm32_si5351.c
- * @brief STM32 library/driver for the Si5351 clock chip
- from Skyworks Solutions, Inc. (former SiLabs)
- ******************************************************************************
+ *******************************************************************************
+ * @file si5351.c
+ * @brief STM32 library/driver for the Si5351 clock chip
+ * from Skyworks Solutions, Inc. (former SiLabs)
+ *******************************************************************************
* @author: Thomas Kuschel KW4NZ
* created 2022-05-11
*
@@ -16,11 +16,13 @@
/* Defines for compilation ---------------------------------------------------*/
/* if you want to automatically enable the clk output after setting synthesis */
+/* you can set the AUTOMATICALLY_ENALBE_OUTPUT to 1 (not recommended) */
#define AUTOMATICALLY_ENABLE_OUTPUT 0
/* enable some optimizing, usually set to 1 */
#define OPTIMIZED 1
-/* Includes ------------------------------------------------------------------*/
+/* Includes -----------------------------------------------------------------*/
+#include
#include
#include
#ifdef DEBUG
@@ -31,7 +33,8 @@
#include
/* including the HAL here */
#include "stm32l4xx_hal.h"
-/* Include the header file */
+/* register map of the Si5351 */
+#include "si5351_reg.h"
#include "si5351.h"
/* Private typedef -----------------------------------------------------------*/
@@ -40,29 +43,29 @@
*/
typedef struct __SI5351_HandleTypeDef {
void *i2c_handle; /*!< the I2C handle, must not be unique */
- struct __SI5351_HandleTypeDef *next; /*!< next pointer to the following structure when there are several instances */
+ struct __SI5351_HandleTypeDef *next; /*!< used for several instances */
uint32_t xtal_frequency; /*!< XTAL or CLKIN frequency */
#if SI5351_DEBUG
- char debug_msg[1000]; /*!< debugging messages for extensive tests of the Si5351 chip, not required */
+ char debug_msg[1000]; /*!< for debugging msgs, extensive tests, N/A */
#endif
uint8_t clk_is_pllb; /*!< assignment of PLLA or PLLB per CLK #, if bit set to 1 ...PLLB */
uint8_t clk_is_disabled; /*!< assignment of Output Enable Control, app. Register 3 */
uint8_t clk_has_phase_shift;/*!< assignment of an output with a phase shift offset */
- uint8_t i2c_address; /*!< I2C address of the datasheet */
- uint8_t interrupt_status_mask; /*!< Reg 2: Interrupt Status Mask */
- uint8_t initialized :1; /*!< mark the driver initialized */
- uint8_t programmed :1; /*!< mark the chip is programmed */
+ uint8_t i2c_address; /*!< I2C address of the datasheet */
+ uint8_t interrupt_status_mask; /*!< Reg 2: Interrupt Status Mask */
+ uint8_t initialized :1; /*!< mark the driver initialized */
+ uint8_t programmed :1; /*!< mark the chip is programmed */
} si5351_HandleTypeDef;
/* @brief SI5351 synthesis settings */
typedef struct {
- uint32_t pll_multiplier; /*!< in datasheet this value corresponds to feedback multisynth (N) a */
- uint32_t pll_numerator; /*!< in datasheet this value corresponds to feedback multisynth (N) b */
- uint32_t pll_denominator; /*!< in datasheet this value corresponds to feedback multisynth (N) c */
- uint32_t out_multiplier; /*!< in datasheet this value corresponds to multisynth (M) a */
- uint32_t out_numerator; /*!< in datasheet this value corresponds to multisynth (M) b */
- uint32_t out_denominator; /*!< in datasheet this value corresponds to multisynth (M) c */
- uint8_t out_r_divider; /*!< R divider, log2 value bit set to 1; 2,4,8,...,128; for frequencies < 500 kHz, otherwise set to 1 i.e. bit 0 */
+ uint32_t pll_multiplier; /*!< corresponds to feedback multisynth (N) a */
+ uint32_t pll_numerator; /*!< corresponds to feedback multisynth (N) b */
+ uint32_t pll_denominator; /*!< corresponds to feedback multisynth (N) c */
+ uint32_t out_multiplier; /*!< corresponds to multisynth (M) a */
+ uint32_t out_numerator; /*!< corresponds to multisynth (M) b */
+ uint32_t out_denominator; /*!< corresponds to multisynth (M) c */
+ uint8_t out_r_divider; /*!< R divider, log2 value bit set to 1; 2,4,8,...,128; for frequencies < 500 kHz, otherwise set to 1 i.e. bit 0 */
} synthesis_t;
typedef struct {
@@ -108,32 +111,33 @@ typedef struct {
#endif
/* Private variables ---------------------------------------------------------*/
-si5351_HandleTypeDef *first_handle = NULL; /* pointer to the first instance */
-int si5351_errno = 0; /* error_number for functions with return == NULL */
+si5351_HandleTypeDef *first_handle = NULL; /* pointer to the first instance */
+int si5351_errno = 0; /* error_number for functions with return == NULL */
/* Private function prototypes -----------------------------------------------*/
#ifdef DEBUG
int __fprintb(FILE *stream, void *value, size_t size);
#endif
-int calculation(uint32_t frequency, uint32_t xtal, synthesis_t *synth);
-int si5351_set_pll(si5351_inst_t inst, synthesis_t *synth);
-int si5351_set_output(si5351_inst_t inst, synthesis_t *synth);
-int si5351_set_synthesis(si5351_inst_t inst, synthesis_t *synth, uint8_t clk);
+static int si5351_set_synthesis(si5351_inst_t inst, synthesis_t *synth, uint8_t clk);
+static int si5351_program(si5351_inst_t inst);
+static int si5351_error_status_i2c(HAL_StatusTypeDef status);
+static int si5351_read(si5351_inst_t inst, uint8_t regaddr, uint8_t *data, uint16_t size);
+static int si5351_write(si5351_inst_t inst, uint8_t regaddr, uint8_t *data, uint16_t size);
+static int band_select(uint32_t frequency, band_t *band);
+static int calculation(uint32_t frequency, uint32_t xtal, synthesis_t *synth);
/* Private functions ---------------------------------------------------------*/
-/** Wrapper functions for receiving/transceiving bytes from I2C bus (HAL function set)
+/** Wrapper functions for receiving/transceiving bytes from I2C bus
+ * (HAL function set)
*/
/** @brief Give better error numbers based on the Linux error_no.h
- * @param i2c_handle the handle of the I2C bus from HAL function, e.g. hi2c1
- * @param xtal_frequency either the XTAL frequency (25/27 MHz) or CLock-In
- * from 10 MHz to 100 MHz entered in Hz
- * @param i2c_address I2C bus address of the device from datasheet typically 0x60 (or 0x61)
- * @param datasize reserve an extra area of data space in bytes, access with function si5351_read_data() and si5351_write_data()
- * @return si5351_handle Pointer to the si5351 handle, NULL if error, see si5351_errno
+ * @param status based on HAL library in HAL_StatusTypeDef
+ * @return error number see si5351_errno
*/
static int si5351_error_status_i2c(HAL_StatusTypeDef status) {
+
switch (status) {
case HAL_TIMEOUT:
return -ETIMEDOUT;
@@ -150,32 +154,35 @@ static int si5351_error_status_i2c(HAL_StatusTypeDef status) {
}
}
-/** @brief Read (blocking mode) one ore more data bytes from the I2C bus starting at the regaddr register address
- * @param instance instance (handle) of the SI5351 driver
+/** @brief Read (blocking mode) one ore more data bytes from the I2C bus
+ * starting at the regaddr register address
+ * @param inst instance (handle) of the SI5351 driver
* @param regaddr starting register address of the SI5351
* @param data pointer to the first byte of data
- * @param datasize datasize of the reading data, sizeof (data), when reading only one register (byte), set to 1
+ * @param datasize datasize of the reading data, sizeof (data),
+ * when reading only one register (byte), set to 1
* @return errno 0 on success, see si5351_errno_t
- * @retval -EINVAL when given a NULL handle
- * @retval -ETIMEDOUT when HAL_TIMEOUT
- * @retval -EIO when HAL_ERROR
- * @retval -EBUSY when HAL_BUSY
+ * @retval -EINVAL when given a NULL handle
+ * @retval -ETIMEDOUT when HAL_TIMEOUT
+ * @retval -EIO when HAL_ERROR
+ * @retval -EBUSY when HAL_BUSY
* if applicable use interrupt controlled HAL functions
*/
-int si5351_read(si5351_inst_t instance, uint8_t regaddr, uint8_t *data,
- uint16_t size) {
+static int si5351_read(si5351_inst_t inst, uint8_t regaddr, uint8_t *data, uint16_t size) {
HAL_StatusTypeDef status;
- status = HAL_I2C_Mem_Read(instance->i2c_handle, instance->i2c_address,
+ status = HAL_I2C_Mem_Read(inst->i2c_handle, inst->i2c_address,
(uint16_t) regaddr, I2C_MEMADD_SIZE_8BIT, data, size, 0xffff);
return si5351_error_status_i2c(status);
}
-/** @brief Write (blocking mode) one ore more data bytes to the I2C bus starting at the regaddr register address
- * @param instance instance (handle) of the SI5351 driver
+/** @brief Write (blocking mode) one ore more data bytes to the I2C bus
+ * starting at the regaddr register address
+ * @param inst instance (handle) of the SI5351 driver
* @param regaddr starting register address of the SI5351
* @param data pointer to the first byte of data
- * @param datasize datasize of the writing data, sizeof (data), when writing to one register (byte), set to 1
+ * @param datasize datasize of the writing data, sizeof (data),
+ * when writing to one register (byte), set to 1
* @return errno 0 on success, see si5351_errno_t
* @retval -EINVAL when given a NULL handle
* @retval -ETIMEDOUT when HAL_TIMEOUT
@@ -183,11 +190,10 @@ int si5351_read(si5351_inst_t instance, uint8_t regaddr, uint8_t *data,
* @retval -EBUSY when HAL_BUSY
* if applicable use interrupt controlled HAL functions
*/
-int si5351_write(si5351_inst_t instance, uint8_t regaddr, uint8_t *data,
- uint16_t size) {
+static int si5351_write(si5351_inst_t inst, uint8_t regaddr, uint8_t *data, uint16_t size) {
HAL_StatusTypeDef status;
- status = HAL_I2C_Mem_Write(instance->i2c_handle, instance->i2c_address,
+ status = HAL_I2C_Mem_Write(inst->i2c_handle, inst->i2c_address,
(uint16_t) regaddr, I2C_MEMADD_SIZE_8BIT, data, size, 0xffff);
return si5351_error_status_i2c(status);
}
@@ -336,7 +342,7 @@ int si5351_deinitialize(void) {
* @retval -EIO when HAL_ERROR
* @retval -EBUSY when HAL_BUSY
*/
-int si5351_program(si5351_inst_t inst) {
+static int si5351_program(si5351_inst_t inst) {
uint8_t data;
int status = 0;
@@ -388,8 +394,12 @@ int si5351_program(si5351_inst_t inst) {
status = si5351_read(inst, SI5351_FANOUT_ENABLE, &data, 1);
if (status)
break;
- cx += snprintf(inst->debug_msg + cx, sizeof(inst->debug_msg) - (size_t)cx, "(%d) FANOUT_ENABLE 0x%x\n", cx, data);
- cx += snprintf(inst->debug_msg + cx, sizeof(inst->debug_msg) - (size_t)cx, "(%d) FANOUT_ENABLE %d\n", cx, data);
+ cx += snprintf(inst->debug_msg + cx,
+ sizeof(inst->debug_msg) - (size_t)cx,
+ "(%d) FANOUT_ENABLE 0x%x\n", cx, data);
+ cx += snprintf(inst->debug_msg + cx,
+ sizeof(inst->debug_msg) - (size_t)cx,
+ "(%d) FANOUT_ENABLE %d\n", cx, data);
#endif
data = SI5351_CLKIN_FANOUT_EN | SI5351_XO_FANOUT_EN
| SI5351_MS_FANOUT_EN; // set them to 1b
@@ -400,8 +410,12 @@ int si5351_program(si5351_inst_t inst) {
status = si5351_read(inst, SI5351_FANOUT_ENABLE, &data, 1);
if (status)
break;
- cx += snprintf(inst->debug_msg + cx, sizeof(inst->debug_msg) - (size_t)cx, "(%d) FANOUT_ENABLE 0x%x\n", cx, data);
- cx += snprintf(inst->debug_msg + cx, sizeof(inst->debug_msg) - (size_t)cx, "(%d) FANOUT_ENABLE %d\n", cx, data);
+ cx += snprintf(inst->debug_msg + cx,
+ sizeof(inst->debug_msg) - (size_t)cx,
+ "(%d) FANOUT_ENABLE 0x%x\n", cx, data);
+ cx += snprintf(inst->debug_msg + cx,
+ sizeof(inst->debug_msg) - (size_t)cx,
+ "(%d) FANOUT_ENABLE %d\n", cx, data);
#endif
/* Crystal Internal Load Capacitance */
@@ -410,7 +424,9 @@ int si5351_program(si5351_inst_t inst) {
status = si5351_write(inst, SI5351_CRYSTAL_INTERNAL_LOAD_CAPACITANCE, &data, 1);
if (status)
break;
- cx += snprintf(inst->debug_msg + cx, sizeof(inst->debug_msg) - (size_t)cx, "(%d) XTAL int. Load Cap: 0x%x (%dd)\n", cx, data, data);
+ cx += snprintf(inst->debug_msg + cx,
+ sizeof(inst->debug_msg) - (size_t)cx,
+ "(%d) XTAL int. Load Cap: 0x%x (%dd)\n", cx, data, data);
#endif
inst->programmed = 1; /* the device is programmed */
} while (0);
@@ -419,24 +435,31 @@ int si5351_program(si5351_inst_t inst) {
}
/** @brief Select the right band to calculate even divisors for the output
- * @param frequency
- * @param band pointer of band_t return parameters as a structure min, max, divisor for each band
+ * @param frequency
+ * @param band pointer of band_t return parameters as a structure min,
+ * max, divisor for each band
* @return 1 on success, when a frequency band is found
- * @retval 0 when frequency not found
+ * @retval 0 when frequency not found
*/
-int band_select(uint32_t frequency, band_t *band) {
+static int band_select(uint32_t frequency, band_t *band) {
static const band_t sband[] = { /* band in meters, frequ_lo, frequ_hi, multiplier, divider_bit */
- { "80", 3000000, 4500000, 200, 0 }, { "40", 5625000, 7500000, 120, 0 }, {
- "30", 7500000, 11250000, 80, 0 },
- { "20", 11250000, 15000000, 60, 0 }, { "15", 15000000, 22500000, 40,
- 0 }, { "10", 22500000, 32142000, 28, 0 }, { "8", 32142000,
- 45000000, 20, 0 }, { "6", 45000000, 64285000, 14, 0 }, {
- "4", 64285000, 76000000, 10, 0 }, { "3", 76000000, 11250000,
- 8, 0 }, { "2", 11250000, 15000000, 6, 0 }, { "180", 1500000,
- 2250000, 400, 0 }, { "120", 2250000, 3000000, 300, 0 }, {
- "60", 4500000, 5625000, 160, 0 }, };
-
+ { "80", 3000000, 4500000, 200, 0 },
+ { "40", 5625000, 7500000, 120, 0 },
+ { "30", 7500000, 11250000, 80, 0 },
+ { "20", 11250000, 15000000, 60, 0 },
+ { "15", 15000000, 22500000, 40, 0 },
+ { "10", 22500000, 32142000, 28, 0 },
+ { "8", 32142000, 45000000, 20, 0 },
+ { "6", 45000000, 64285000, 14, 0 },
+ { "4", 64285000, 76000000, 10, 0 },
+ { "3", 76000000, 11250000, 8, 0 },
+ { "2", 11250000, 15000000, 6, 0 },
+ {"180", 1500000, 2250000, 400, 0 },
+ {"120", 2250000, 3000000, 300, 0 },
+ { "60", 4500000, 5625000, 160, 0 },
+ };
+ /* possibly this could be improved with a bsearch algorithm: */
for (uint32_t i = 0; i < (sizeof(sband) / sizeof(sband[0])); i++) {
if (frequency > sband[i].qrg_min && frequency <= sband[i].qrg_max) {
memcpy(band, &sband[i], sizeof(*band));
@@ -452,7 +475,7 @@ int band_select(uint32_t frequency, band_t *band) {
* @param synth pointer to a structure snythesis_t will be set with the calculated values
* @return 0 on success
*/
-int calculation(uint32_t frequency, uint32_t xtal, synthesis_t *synth) {
+static int calculation(uint32_t frequency, uint32_t xtal, synthesis_t *synth) {
uint32_t t;
band_t band;
@@ -689,7 +712,7 @@ int si5351_set_clk_phase(si5351_inst_t inst, uint8_t clk, uint32_t frequency,
* @retval -EIO when HAL_ERROR
* @retval -EBUSY when HAL_BUSY
*/
-int si5351_reset_pll(si5351_inst_t inst, uint8_t clk) {
+static int si5351_reset_pll(si5351_inst_t inst, uint8_t clk) {
/* internal function, no need to check inst nor clk */
@@ -707,8 +730,8 @@ int si5351_reset_pll(si5351_inst_t inst, uint8_t clk) {
/** @brief Sets the CLK_x output phase of the si5351 (direct access to register)
* @param si5351_instance Given si5351 device handle
- * @param phase in uint8_t type value
* @param clk The CLK ouput to drive and disable 0...CLK0, 1...CLK1, 2...CLK2, ...
+ * @param phase in uint8_t type value
* @return 0 on success
* @retval -EINVAL when given a NULL handle
* @retval -ETIMEDOUT when HAL_TIMEOUT
@@ -743,7 +766,7 @@ int si5351_set_phase(si5351_inst_t inst, uint8_t clk, uint8_t phase) {
* @retval -EIO when HAL_ERROR
* @retval -EBUSY when HAL_BUSY
*/
-int si5351_set_synthesis(si5351_inst_t inst, synthesis_t *synth, uint8_t clk) {
+static int si5351_set_synthesis(si5351_inst_t inst, synthesis_t *synth, uint8_t clk) {
uint32_t MSNx_P1, MSNx_P2, MSNx_P3;
uint32_t MSx_P1, MSx_P2, MSx_P3;
diff --git a/stm32l4a6zg-f0x.at1.ioc b/stm32l4a6zg-f0x.at1.ioc
index 077114d..149ca69 100644
--- a/stm32l4a6zg-f0x.at1.ioc
+++ b/stm32l4a6zg-f0x.at1.ioc
@@ -511,4 +511,4 @@ VP_RTC_VS_RTC_Calendar.Signal=RTC_VS_RTC_Calendar
VP_SYS_VS_tim6.Mode=TIM6
VP_SYS_VS_tim6.Signal=SYS_VS_tim6
board=NUCLEO-L4A6ZG
-isbadioc=true
+isbadioc=false