CHG programming further investigation

This commit is contained in:
Tom Kuschel
2022-05-17 01:28:20 +02:00
parent acc0f0a5da
commit f4a61ee06f
4 changed files with 141 additions and 32 deletions

View File

@ -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, ... */

View File

@ -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);
/* Disable Outputs Set CLKx_DIS high, Reg. 3 = 0xFF */
data = 0xff;
status = si5351_write(inst, SI5351_OUTPUT_ENABLE_CONTROL, &data, 1);
if (status)
return status;
/* power down all output drivers reg 16 -- 23 */
data = 0x80;
for(int i = SI5351_CLK0_CONTROL; i <= SI5351_CLK7_CONTROL; i++) {
status = si5351_write(inst, i, &data, 1);
do {
/* Disable Outputs Set CLKx_DIS high, Reg. 3 = 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 = 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)
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;