CHG programming further investigation
This commit is contained in:
parent
acc0f0a5da
commit
f4a61ee06f
@ -105,12 +105,15 @@ typedef enum {
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
|
||||
#ifndef SI5351_NUMBER_OF_OUTPUTS
|
||||
#define SI5351_NUMBER_OF_OUTPUTS 8
|
||||
#endif
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
si5351_inst_t si5351_init(void * i2c_handle, uint32_t xtal_frequency, uint8_t i2c_address);
|
||||
int si5351_deinit(si5351_inst_t si5351_handle);
|
||||
int si5351_isready(si5351_inst_t inst);
|
||||
int si5351_program(si5351_inst_t inst);
|
||||
char * si5351_read_debug_msg(si5351_inst_t inst);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
@ -68,9 +68,17 @@
|
||||
#define SI5351_CLK0_SRC_1 (1u<<3) /* Output Clock 0 Input Source */
|
||||
#define SI5351_CLK0_SRC_0 (1u<<2) /* 00: Select the XTAL as the clock source for CLK0. By-pass both synthesis stages (PLL/VCXO & MultiSynth) */
|
||||
#define SI5351_CLK0_SRC (3u<<2) /* and connects CLK0 directly to the oscillator which generates an output freq determined by the XTAL freq. */
|
||||
#define SI5351_CLK_SRC_XTAL (0x00<<2) /*!< Select the XTAL as the clock source for CLKx */
|
||||
#define SI5351_CLK_SRC_CLKIN (0x01<<2) /*!< Select the CLKIN as the clock source for CLKx */
|
||||
#define SI5351_CLK_SRC_MS0 (0x02<<2) /*!< Select the MulitSynth 0 as the clock source for CLKx */
|
||||
#define SI5351_CLK_SRC_MS1 (0x03<<2) /*!< Select the MulitSynth 1 as the clock source for CLKx */
|
||||
#define SI5351_CLK0_IDRV_1 (1u<<1) /* 01: CLKIN as clock source for CLK0. By-pass both synthesis stages. 10: N/A. 11: Select MultiSynth 0 as source for CLK0 */
|
||||
#define SI5351_CLK0_IDRV_0 (1u<<0) /* CLK0 Output Rise and Fall time / Drive Strength Control */
|
||||
#define SI5551_CLK0_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK0_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK_2_MA (0x00) /*!< 2 mA output rise and fall time / drive strength control */
|
||||
#define SI5351_CLK_4_MA (0x01) /*!< 4 mA output rise and fall time / drive strength control */
|
||||
#define SI5351_CLK_6_MA (0x02) /*!< 6 mA output rise and fall time / drive strength control */
|
||||
#define SI5351_CLK_8_MA (0x03) /*!< 8 mA output rise and fall time / drive strength control */
|
||||
#define SI5351_CLK0_CONTROL_RESET_VALUE 0x00
|
||||
|
||||
#define SI5351_CLK1_CONTROL 17u /* R/W */
|
||||
@ -83,7 +91,7 @@
|
||||
#define SI5351_CLK1_SRC (3u<<2) /* and connects CLK1 directly to the oscillator which generates an output freq determined by the XTAL freq. */
|
||||
#define SI5351_CLK1_IDRV_1 (1u<<1) /* 01: CLKIN as clock source for CLK1. By-pass both synthesis stages. 10: N/A. 11: Select MultiSynth 1 as source for CLK1 */
|
||||
#define SI5351_CLK1_IDRV_0 (1u<<0) /* CLK1 Output Rise and Fall time / Drive Strength Control */
|
||||
#define SI5551_CLK1_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK1_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK1_CONTROL_RESET_VALUE 0x00
|
||||
|
||||
#define SI5351_CLK2_CONTROL 18u /* R/W */
|
||||
@ -96,7 +104,7 @@
|
||||
#define SI5351_CLK2_SRC (3u<<2) /* and connects CLK2 directly to the oscillator which generates an output freq determined by the XTAL freq. */
|
||||
#define SI5351_CLK2_IDRV_1 (1u<<1) /* 01: CLKIN as clock source for CLK2. By-pass both synthesis stages. 10: N/A. 11: Select MultiSynth 2 as source for CLK2 */
|
||||
#define SI5351_CLK2_IDRV_0 (1u<<0) /* CLK2 Output Rise and Fall time / Drive Strength Control */
|
||||
#define SI5551_CLK2_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK2_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK2_CONTROL_RESET_VALUE 0x00
|
||||
|
||||
#define SI5351_CLK3_CONTROL 19u /* R/W */
|
||||
@ -109,7 +117,7 @@
|
||||
#define SI5351_CLK3_SRC (3u<<2) /* and connects CLK3 directly to the oscillator which generates an output freq determined by the XTAL freq. */
|
||||
#define SI5351_CLK3_IDRV_1 (1u<<1) /* 01: CLKIN as clock source for CLK3. By-pass both synthesis stages. 10: N/A. 11: Select MultiSynth 3 as source for CLK3 */
|
||||
#define SI5351_CLK3_IDRV_0 (1u<<0) /* CLK3 Output Rise and Fall time / Drive Strength Control */
|
||||
#define SI5551_CLK3_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK3_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK3_CONTROL_RESET_VALUE 0x00
|
||||
|
||||
#define SI5351_CLK4_CONTROL 20u /* R/W */
|
||||
@ -122,7 +130,7 @@
|
||||
#define SI5351_CLK4_SRC (3u<<2) /* and connects CLK4 directly to the oscillator which generates an output freq determined by the XTAL freq. */
|
||||
#define SI5351_CLK4_IDRV_1 (1u<<1) /* 01: CLKIN as clock source for CLK4. By-pass both synthesis stages. 10: N/A. 11: Select MultiSynth 4 as source for CLK4 */
|
||||
#define SI5351_CLK4_IDRV_0 (1u<<0) /* CLK4 Output Rise and Fall time / Drive Strength Control */
|
||||
#define SI5551_CLK4_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK4_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK4_CONTROL_RESET_VALUE 0x00
|
||||
|
||||
#define SI5351_CLK5_CONTROL 21u /* R/W */
|
||||
@ -135,12 +143,13 @@
|
||||
#define SI5351_CLK5_SRC (3u<<2) /* and connects CLK5 directly to the oscillator which generates an output freq determined by the XTAL freq. */
|
||||
#define SI5351_CLK5_IDRV_1 (1u<<1) /* 01: CLKIN as clock source for CLK5. By-pass both synthesis stages. 10: N/A. 11: Select MultiSynth 5 as source for CLK5 */
|
||||
#define SI5351_CLK5_IDRV_0 (1u<<0) /* CLK5 Output Rise and Fall time / Drive Strength Control */
|
||||
#define SI5551_CLK5_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK5_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK5_CONTROL_RESET_VALUE 0x00
|
||||
|
||||
#define SI5351_CLK6_CONTROL 22u /* R/W */
|
||||
#define SI5351_CLK6_PDN (1u<<7) /* Clock 6 Power Down. */
|
||||
#define SI5351_MS6_INT (1u<<6) /* MultiSynth 6 Integer Mode. 1..MS6 operates in integer mode. */
|
||||
/* #define SI5351_MS6_INT (1u<<6) */
|
||||
#define SI5351_FBA_INT (1u<<6) /*!< FBA MultiSynth Integer Mode. 1..MSNA operates in integer mode */
|
||||
#define SI5351_MS6_SRC (1u<<5) /* MultiSynth Source Select for CLK6 */
|
||||
#define SI5351_CLK6_INV (1u<<4) /* Output Clock 6 Invert. */
|
||||
#define SI5351_CLK6_SRC_1 (1u<<3) /* Output Clock 6 Input Source */
|
||||
@ -148,12 +157,13 @@
|
||||
#define SI5351_CLK6_SRC (3u<<2) /* and connects CLK6 directly to the oscillator which generates an output freq determined by the XTAL freq. */
|
||||
#define SI5351_CLK6_IDRV_1 (1u<<1) /* 01: CLKIN as clock source for CLK6. By-pass both synthesis stages. 10: N/A. 11: Select MultiSynth 6 as source for CLK6 */
|
||||
#define SI5351_CLK6_IDRV_0 (1u<<0) /* CLK6 Output Rise and Fall time / Drive Strength Control */
|
||||
#define SI5551_CLK6_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK6_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK6_CONTROL_RESET_VALUE 0x00
|
||||
|
||||
#define SI5351_CLK7_CONTROL 23u /* R/W */
|
||||
#define SI5351_CLK7_PDN (1u<<7) /* Clock 7 Power Down. */
|
||||
#define SI5351_MS7_INT (1u<<6) /* MultiSynth 7 Integer Mode. 1..MS7 operates in integer mode. */
|
||||
/* #define SI5351_MS7_INT (1u<<6) */
|
||||
#define SI5351_FBB_INT (1u<<6) /*!< FBB Multisynth Integer Mode. 1..MSNB operates in integer mode */
|
||||
#define SI5351_MS7_SRC (1u<<5) /* MultiSynth Source Select for CLK7 */
|
||||
#define SI5351_CLK7_INV (1u<<4) /* Output Clock 7 Invert. */
|
||||
#define SI5351_CLK7_SRC_1 (1u<<3) /* Output Clock 7 Input Source */
|
||||
@ -161,7 +171,7 @@
|
||||
#define SI5351_CLK7_SRC (3u<<2) /* and connects CLK7 directly to the oscillator which generates an output freq determined by the XTAL freq. */
|
||||
#define SI5351_CLK7_IDRV_1 (1u<<1) /* 01: CLKIN as clock source for CLK7. By-pass both synthesis stages. 10: N/A. 11: Select MultiSynth 7 as source for CLK7 */
|
||||
#define SI5351_CLK7_IDRV_0 (1u<<0) /* CLK7 Output Rise and Fall time / Drive Strength Control */
|
||||
#define SI5551_CLK7_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK7_IDRV (3u<<0) /* 00: 2 mA, 01: 4 mA, 10: 6 mA, 11: 8 mA */
|
||||
#define SI5351_CLK7_CONTROL_RESET_VALUE 0x00
|
||||
|
||||
#define SI5351_CLK3_0_DISABLE_STATE 24u /* R/W */
|
||||
@ -1079,3 +1089,21 @@ even integers greater than or equal to 6. All other divide values are invalid. *
|
||||
#define R6_DIV (7u<<4)
|
||||
|
||||
|
||||
/* Crystal Internal Load Capacitance
|
||||
* Two bits determine the internal load capacitance value for the crystal. See the Crystal
|
||||
* Inputs section in the Si5351 data sheet
|
||||
* Default: SI5351_XTAL_CL_10_PF (10 pF load capacitors)
|
||||
*/
|
||||
#define SI5351_CRYSTAL_INTERNAL_LOAD_CAPACITANCE 183u /* R/W */
|
||||
#define SI5351_XTAL_CL_6_PF (1u<<6) /*!< Internal CL = 6 pF */
|
||||
#define SI5351_XTAL_CL_8_PF (2u<<6) /*!< Internal CL = 8 pF */
|
||||
#define SI5351_XTAL_CL_10_PF (3u<<6) /*!< Internal CL = 10 pF */
|
||||
#define SI5351_XTAL_CL_MASK (3u<<6) /*!< Mask of the load capacitance */
|
||||
#define SI5351_XTAL_RESERVED (0x13) /*!< RESERVED bit[5:0] should be written! */
|
||||
/* Fanout Enable, set these bits to 1 for each fanout
|
||||
* note: the reset value of this SI5351 register is 0x00 */
|
||||
|
||||
#define SI5351_FANOUT_ENABLE 187u /* R/W */
|
||||
#define SI5351_CLKIN_FANOUT_EN (1u<<7) /*!< Enable fanout of CLKIN to clock output multiplexers. Set it to 1 */
|
||||
#define SI5351_XO_FANOUT_EN (1u<<6) /*!< Enable fanout of XO to clock output multiplexers. Set it to 1 */
|
||||
#define SI5351_MS_FANOUT_EN (1u<<4) /*!< Enable fanout of Multisynth0 & Multisynth4 to all output multiplexers. Set it to 1 */
|
||||
|
@ -145,6 +145,7 @@ int main(void)
|
||||
|
||||
status = si5351_program(instance_si5351[1]);
|
||||
printf("Device #1 gets status %d\n", status);
|
||||
printf("Debug:\n%s", si5351_read_debug_msg(instance_si5351[1]));
|
||||
|
||||
for (int i=2; i>=0; i--) {
|
||||
si5351_deinit(instance_si5351[i]);
|
||||
@ -178,7 +179,7 @@ int main(void)
|
||||
terminalTaskHandle = osThreadNew(start_terminal_task, NULL, &terminalTask_attributes);
|
||||
|
||||
/* creation of idTask */
|
||||
idTaskHandle = osThreadNew(start_id_task, NULL, &idTask_attributes);
|
||||
// idTaskHandle = osThreadNew(start_id_task, NULL, &idTask_attributes);
|
||||
|
||||
/* USER CODE BEGIN RTOS_THREADS */
|
||||
/* add threads, ... */
|
||||
|
@ -10,14 +10,21 @@
|
||||
* adapted, idea and much information from Petr Polasek, created Feb 16, 2018
|
||||
******************************************************************************/
|
||||
|
||||
/* Defines for compilation ---------------------------------------------------*/
|
||||
#define DEBUG 1
|
||||
#define OPTIMIZED 1
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
// @TODO try to get rid off including the HAL here, using pointer to the specified functions
|
||||
#if DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "stm32l4xx_hal.h"
|
||||
|
||||
#include "stm32_si5351.h"
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
#define SI5351_VERSION 1
|
||||
|
||||
/* @brief Si5351 handle structure definition
|
||||
*/
|
||||
@ -26,12 +33,15 @@ typedef struct __SI5351_HandleTypeDef {
|
||||
uint32_t xtal_frequency; /*!< XTAL or CLKIN frequency */
|
||||
int si5351_num;
|
||||
struct __SI5351_HandleTypeDef *next;
|
||||
char debug_msg[1000];
|
||||
uint8_t i2c_address; /*!< I2C address of the datasheet */
|
||||
// uint8_t interrupt_status_mask; /*!< Reg 2: Interrupt Status Mask */
|
||||
uint8_t interrupt_status_mask; /*!< Reg 2: Interrupt Status Mask */
|
||||
uint8_t initialized:1; /*!< mark the driver initialized */
|
||||
} si5351_HandleTypeDef;
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
#define SI5351_VERSION 1
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
si5351_HandleTypeDef * first_handle = NULL; /* pointer to the first instancee */
|
||||
@ -111,6 +121,9 @@ si5351_HandleTypeDef *si5351_init(void * i2c_handle, uint32_t xtal_frequency, ui
|
||||
si5351_handle->i2c_handle = i2c_handle;
|
||||
si5351_handle->i2c_address = i2c_address;
|
||||
si5351_handle->xtal_frequency = xtal_frequency;
|
||||
/* disable all interrupts (Si5351C only) */
|
||||
si5351_handle->interrupt_status_mask = SI5351_SYS_INIT_MASK | SI5351_LOL_B_MASK |
|
||||
SI5351_LOL_A_MASK | SI5351_LOS_CLKIN_MASK | SI5351_LOS_XTAL_MASK;
|
||||
si5351_handle->initialized = 1;
|
||||
return si5351_handle;
|
||||
}
|
||||
@ -151,10 +164,11 @@ int si5351_deinit(si5351_HandleTypeDef * si5351_handle) {
|
||||
|
||||
/** @brief Check if there is any I2C device ready on the bus
|
||||
* @param si5351_instance Given si5351 device handle
|
||||
* @return 0 on success (HAL_StatusTypeDef)
|
||||
* @retval HAL_ERROR = 0x01
|
||||
* @retval HAL_BUSY = 0x02
|
||||
* @retval HAL_TIMEOUT = 0x03
|
||||
* @return 0 on success
|
||||
* @retval -EINVAL when given a NULL handle
|
||||
* @retval -ETIMEDOUT when HAL_TIMEOUT
|
||||
* @retval -EIO when HAL_ERROR
|
||||
* @retval -EBUSY when HAL_BUSY
|
||||
*/
|
||||
int si5351_isready(si5351_inst_t inst) {
|
||||
|
||||
@ -169,10 +183,20 @@ int si5351_isready(si5351_inst_t inst) {
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Program the si5351 with the already set values according to Figure 10 of the datasheet
|
||||
* @param si5351_instance Given si5351 device handle
|
||||
* @return 0 on success
|
||||
* @retval -EINVAL when given a NULL handle
|
||||
* @retval -ETIMEDOUT when HAL_TIMEOUT
|
||||
* @retval -EIO when HAL_ERROR
|
||||
* @retval -EBUSY when HAL_BUSY
|
||||
*/
|
||||
int si5351_program(si5351_inst_t inst) {
|
||||
|
||||
uint8_t data;
|
||||
int status = 0;
|
||||
int cx = 0;
|
||||
|
||||
if(!inst)
|
||||
return -EINVAL;
|
||||
@ -184,29 +208,82 @@ int si5351_program(si5351_inst_t inst) {
|
||||
|
||||
} while(data & SI5351_SYS_INIT);
|
||||
|
||||
do {
|
||||
/* Disable Outputs Set CLKx_DIS high, Reg. 3 = 0xFF */
|
||||
data = 0xff;
|
||||
data = SI5351_CLK7_OEB | SI5351_CLK6_OEB | SI5351_CLK5_OEB | SI5351_CLK4_OEB |
|
||||
SI5351_CLK3_OEB | SI5351_CLK2_OEB | SI5351_CLK1_OEB | SI5351_CLK0_OEB;
|
||||
status = si5351_write(inst, SI5351_OUTPUT_ENABLE_CONTROL, &data, 1);
|
||||
if (status)
|
||||
return status;
|
||||
break;
|
||||
|
||||
/* power down all output drivers reg 16 -- 23 */
|
||||
data = 0x80;
|
||||
data = SI5351_CLKx_PDN; // 0x80
|
||||
#if OPTIMIZED
|
||||
status = si5351_write(inst, SI5351_CLK0_CONTROL, &data, SI5351_NUMBER_OF_OUTPUTS);
|
||||
if (status)
|
||||
break;
|
||||
#else
|
||||
for(int i = SI5351_CLK0_CONTROL; i <= SI5351_CLK7_CONTROL; i++) {
|
||||
status = si5351_write(inst, i, &data, 1);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* set interrupt masks (see register 2 description) */
|
||||
status = si5351_write(inst, SI5351_INTERRUPT_STATUS_MASK, &inst->interrupt_status_mask, 1);
|
||||
if (status)
|
||||
break;
|
||||
|
||||
/* for debugging purpose, read out fanout enable register */
|
||||
#if DEBUG
|
||||
status = si5351_read(inst, SI5351_FANOUT_ENABLE, &data, 1);
|
||||
if (status)
|
||||
break;
|
||||
cx += snprintf(inst->debug_msg + cx, sizeof(inst->debug_msg) - cx, "(%d) FANOUT_ENABLE 0x%x\n", cx, data);
|
||||
cx += snprintf(inst->debug_msg + cx, sizeof(inst->debug_msg) - 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
|
||||
status = si5351_write(inst, SI5351_FANOUT_ENABLE, &data, 1);
|
||||
if (status)
|
||||
break;
|
||||
#if DEBUG
|
||||
status = si5351_read(inst, SI5351_FANOUT_ENABLE, &data, 1);
|
||||
if (status)
|
||||
break;
|
||||
cx += snprintf(inst->debug_msg + cx, sizeof(inst->debug_msg) - cx, "(%d) FANOUT_ENABLE 0x%x\n", cx, data);
|
||||
cx += snprintf(inst->debug_msg + cx, sizeof(inst->debug_msg) - cx, "(%d) FANOUT_ENABLE %d\n", cx, data);
|
||||
#endif
|
||||
|
||||
/* Crystal Internal Load Capacitance */
|
||||
|
||||
#if DEBUG
|
||||
status = si5351_read(inst, SI5351_CRYSTAL_INTERNAL_LOAD_CAPACITANCE, &data, 1);
|
||||
if (status)
|
||||
break;
|
||||
cx += snprintf(inst->debug_msg + cx, sizeof(inst->debug_msg) - cx, "(%d) XTAL int. Load Cap: 0x%x (%dd)\n", cx, data, data);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
} while(0);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
char * si5351_read_debug_msg(si5351_inst_t inst) {
|
||||
|
||||
if (!inst)
|
||||
return NULL;
|
||||
|
||||
return inst->debug_msg;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
|
||||
int Si5351_WriteRegister(Si5351_ConfigTypeDef *Si5351_ConfigStruct, uint8_t reg_address, uint8_t reg_data)
|
||||
{
|
||||
uint32_t error_wait;
|
||||
|
Loading…
Reference in New Issue
Block a user