rename si5351 driver, remove external files
This commit is contained in:
@ -1,525 +1,149 @@
|
||||
/*
|
||||
* si5351.h
|
||||
*
|
||||
* Created on: Feb 16, 2018
|
||||
* Author: Petr Polasek
|
||||
*
|
||||
* To make this library useable on any other device than
|
||||
* STM32Fxxx Cortex Mx, please edit these parts of the library:
|
||||
*
|
||||
* DEFINES:
|
||||
* SI5351_I2C_PERIPHERAL - the I2C peripheral name according
|
||||
* to your devices HAL library
|
||||
* I2C_TIMEOUT - time for the communication to time out
|
||||
*
|
||||
* TYPEDEFS:
|
||||
* Si5351_ConfigTypeDef - the I2Cx parameter should be changed
|
||||
* so that its type corresponds to your HAL library
|
||||
*
|
||||
* FUNCTIONS:
|
||||
* Si5351_WriteRegister
|
||||
* Si5351_ReadRegister
|
||||
* You need to write your own I2C handlers here
|
||||
*
|
||||
*/
|
||||
/******************************************************************************
|
||||
* File Name : si5351.h
|
||||
* Description : STM32 library/driver for the Si5351 clock chip
|
||||
* from Skyworks Solutions, Inc. (former SiLabs)
|
||||
******************************************************************************
|
||||
* @author: Thomas Kuschel KW4NZ, created 2022-05-11
|
||||
*
|
||||
* originally written by Petr Polasek, created Feb 16, 2018
|
||||
******************************************************************************
|
||||
* DO NOT EDIT THIS FILE FOR CONFIGURATION, USE THE FOLLOWING PROCEDURE:
|
||||
*
|
||||
* Inside your main.c program or within your STM32 code:
|
||||
* Include this header to the the main.c: #include "si5351.h"
|
||||
* You've to initialize the I2C functionality first (e.g. with STM32CubeIDE)
|
||||
* Afterwards, when there is a handle like "I2C_HandleTypeDef hi2c1;",
|
||||
* you simply initialize this si5351 library in your main.c ,
|
||||
* just after the MX_I2C1_Init();
|
||||
* so between the USER CODE like using the given i2c handle "hi2c1" with default values:
|
||||
*
|
||||
* /\* USER CODE BEGIN 2 *\/
|
||||
*
|
||||
* si5351_inst_t si5351_inst;
|
||||
* si5351_initialize(&hi2c1);
|
||||
*
|
||||
* /\* USER CODE END 2 *\/
|
||||
*
|
||||
* The 7-bit device (slave) address of the Si5351 consist of a 6-bit fixed
|
||||
* address plus a user selectable LSB bit as shown in Figure 6 of the datasheet.
|
||||
* The LSB bit is selectable as 0 or 1 using the optional A0 pin which is useful
|
||||
* for applications that require more than one Si5351 on a single I2C bus.
|
||||
* Only the Si5351A 20-QFN and Si5351A 16-QFN have the A0 LSB pin option.
|
||||
* If a part does not have the A0 pin, the default address is 0x60 with
|
||||
* the A0 bit set to 0.
|
||||
*
|
||||
* So additionally you may drive more then one Si5351 at the same or
|
||||
* another I2C bus when calling the init function with the given
|
||||
* I2C bus address (default: 0x60)
|
||||
* ( - internally this I2C address is shifted to the left
|
||||
* for the proper usage of the I2C HAL driver i.e. it becomes 0xC0 )
|
||||
*
|
||||
* Example:
|
||||
* /\* Define handlers for the sum of three SI5351 clock generators: *\/
|
||||
* si5351_HandleTypeDef hsi5351[3];
|
||||
*
|
||||
* /\* 1st SI5351 chip and with an A0 = 0: *\/
|
||||
* hsi5351[0] = si5351_init(&hi2c1, 0x60, 25000000);
|
||||
* /\* 2nd SI5351 chip on the same I2C bus "hi2c1" but address line A0 = 1 *\/
|
||||
* hsi5351[1] = si5351_init(&hi2c1, 0x61, 27000000);
|
||||
* /\* 3rd SI5351 chip on another IC2 bus with handle "hi2c2" *\/
|
||||
* hsi5351[2] = si5351_init(&hi2c2, 0x60, 25000000);
|
||||
*
|
||||
* PROs:
|
||||
* The library is preemptive and can be used within an operating system.
|
||||
* All structures and used variables are dynamically allocated.
|
||||
* CONs:
|
||||
* Not fully tested.
|
||||
* Tested with FreeRTOS and with 2 I2C bus systems.
|
||||
*
|
||||
* CHANGES:
|
||||
* - Removed several defines, enums, etc. from the header file, b/c we do not
|
||||
* want to export them to other programs
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef SI5351_H_
|
||||
#define SI5351_H_
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __SI5351_H__
|
||||
#define __SI5351_H__
|
||||
|
||||
#include "stm32l4xx_hal.h"
|
||||
|
||||
#define SI5351_I2C_ADDRESS 0xC0 //default I2C address of Si5351
|
||||
#define SI5351_I2C_PERIPHERAL I2C1 //default I2C interface
|
||||
|
||||
#define SI5351_XTAL_FREQ 25000000 // sets default value, 25000000 for 25 MHz, 27000000 for 27 MHz
|
||||
#define SI5351_CLKIN_FREQ 0 // set in Hz
|
||||
|
||||
#ifdef I2C_TIMEOUT
|
||||
#undef I2C_TIMEOUT
|
||||
#endif
|
||||
#define I2C_TIMEOUT 100000 //I2C timeout for wait loops
|
||||
|
||||
#define SI5351_TIMEOUT (I2C_TIMEOUT * 10)
|
||||
|
||||
#ifndef ENABLESTATE
|
||||
#define ENABLESTATE
|
||||
typedef enum
|
||||
{
|
||||
OFF = 0,
|
||||
ON = 1
|
||||
} EnableState;
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This section contains register addresses and bit masks for
|
||||
* the device status registers.
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include <si5351_reg.h> /* register map of the Si5351 */
|
||||
/* #include <errno.h> could also be included */
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/*!< Si5351 instance typedef -- handle as pointer */
|
||||
typedef struct __SI5351_HandleTypeDef *si5351_inst_t;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** @enum errno_t Error Number Constants, @TODO you can also include <errno.h>
|
||||
*/
|
||||
|
||||
#define REG_DEV_STATUS 0
|
||||
#define DEV_SYS_INIT_MASK 0x80
|
||||
#define DEV_LOL_B_MASK 0x40
|
||||
#define DEV_LOL_A_MASK 0x20
|
||||
#define DEV_LOS_CLKIN_MASK 0x10
|
||||
#define DEV_LOS_XTAL_MASK 0x08
|
||||
#define DEV_REVID_MASK 0x03
|
||||
|
||||
#define REG_DEV_STICKY 1
|
||||
#define DEV_STKY_SYS_INIT_MASK 0x80
|
||||
#define DEV_STKY_LOL_B_MASK 0x40
|
||||
#define DEV_STKY_LOL_A_MASK 0x20
|
||||
#define DEV_STKY_LOS_CLKIN_MASK 0x10
|
||||
#define DEV_STKY_LOS_XTAL_MASK 0x08
|
||||
|
||||
#define REG_INT_MASK 2
|
||||
#define INT_MASK_SYS_INIT_MASK 0x80
|
||||
#define INT_MASK_LOL_B_MASK 0x40
|
||||
#define INT_MASK_LOL_A_MASK 0x20
|
||||
#define INT_MASK_LOS_CLKIN_MASK 0x10
|
||||
#define INT_MASK_LOS_XTAL_MASK 0x08
|
||||
|
||||
/*
|
||||
* This section contains data structures for configuring the
|
||||
* oscillator, VCXO and CLKIN section.
|
||||
*/
|
||||
|
||||
#define REG_XTAL_CL 183
|
||||
#define XTAL_CL_MASK 0xC0
|
||||
#define PLL_CL_MASK 0x36
|
||||
|
||||
//this sets the crystal load capacitance
|
||||
typedef enum
|
||||
{
|
||||
XTAL_Load_4_pF = 0x00,
|
||||
XTAL_Load_6_pF = 0x40,
|
||||
XTAL_Load_8_pF = 0x80,
|
||||
XTAL_Load_10_pF = 0xC0
|
||||
} Si5351_XTALLoadTypeDef;
|
||||
|
||||
//The following is an unexplained parameter. However someone from SiLabs called it "VCO load cap".
|
||||
//Lower settings seem to be more stable on higher frequencies, higher settings are more stable on lower frequencies allowing to tune the PLL to <200 MHz.
|
||||
typedef enum
|
||||
{
|
||||
PLL_Capacitive_Load_0 = 0,
|
||||
PLL_Capacitive_Load_1 = 1,
|
||||
PLL_Capacitive_Load_2 = 2
|
||||
} Si5351_PLLCapacitiveLoadTypeDef;
|
||||
|
||||
#define REG_CLKIN_DIV 15
|
||||
#define CLKIN_MASK 0xC0
|
||||
|
||||
//this sets the CLKIN pre-divider, after division, CLKIN should
|
||||
//fall between 10-40 MHz
|
||||
typedef enum
|
||||
{
|
||||
CLKINDiv_Div1 = 0x00,
|
||||
CLKINDiv_Div2 = 0x40,
|
||||
CLKINDiv_Div4 = 0x80,
|
||||
CLKINDiv_Div8 = 0xC0
|
||||
} Si5351_CLKINDivTypeDef;
|
||||
|
||||
#define REG_FANOUT_EN 187
|
||||
#define FANOUT_CLKIN_EN_MASK 0x80
|
||||
#define FANOUT_XO_EN_MASK 0x40
|
||||
#define FANOUT_MS_EN_MASK 0x10
|
||||
|
||||
#define REG_VCXO_PARAM_0_7 162
|
||||
#define REG_VCXO_PARAM_8_15 163
|
||||
#define REG_VCXO_PARAM_16_21 164
|
||||
#define VCXO_PARAM_16_21_MASK 0x3F
|
||||
#define VCXO_PARAM_MASK 0x003FFFFF
|
||||
|
||||
#define APR_MINIMUM 30 //minimum pull range
|
||||
#define APR_MAXIMUM 240 //maximum pull range
|
||||
|
||||
#define CLKIN_MINIMUM 10000 //minimum CLKIN frequency after division in kHz
|
||||
#define CLKIN_MAXIMUM 40000 //maximum CLKIN frequency after division in kHz
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Si5351_XTALLoadTypeDef OSC_XTAL_Load; //capacitive load of XTAL, 10pF by default
|
||||
Si5351_CLKINDivTypeDef CLKIN_Div; //CLKIN predivision, input f to PLL must be 10-40 MHz
|
||||
uint8_t VCXO_Pull_Range_ppm; //can range from +-30 ppm to 240ppm
|
||||
} Si5351_OSCConfigTypeDef;
|
||||
|
||||
/*
|
||||
* This section contains data structures for configuring the
|
||||
* PLL (PLLA and PLLB)
|
||||
*/
|
||||
|
||||
#define REG_PLL_CLOCK_SOURCE 15
|
||||
#define PLLA_CLOCK_SOURCE_MASK 0x04
|
||||
#define PLLB_CLOCK_SOURCE_MASK 0x08
|
||||
|
||||
//this selects the clock source for the PLL
|
||||
typedef enum
|
||||
{
|
||||
PLL_Clock_Source_XTAL = 0x00,
|
||||
PLL_Clock_Source_CLKIN = 0x0C //0x04 for PLLA, 0x08 for PLLB, use mask!
|
||||
} Si5351_PLLClockSourceTypeDef;
|
||||
|
||||
#define REG_FB_INT 22
|
||||
#define FB_INT_MASK 0x40
|
||||
|
||||
#define REG_PLL_RESET 177
|
||||
#define PLLA_RESET_MASK 0x20
|
||||
#define PLLB_RESET_MASK 0x80
|
||||
|
||||
#define REG_MSN_P1_0_7 30
|
||||
#define REG_MSN_P1_8_15 29
|
||||
#define REG_MSN_P1_16_17 28
|
||||
#define MSN_P1_16_17_MASK 0x03
|
||||
|
||||
#define REG_MSN_P2_0_7 33
|
||||
#define REG_MSN_P2_8_15 32
|
||||
#define REG_MSN_P2_16_19 31
|
||||
#define MSN_P2_16_19_MASK 0x0F
|
||||
|
||||
#define REG_MSN_P3_0_7 27
|
||||
#define REG_MSN_P3_8_15 26
|
||||
#define REG_MSN_P3_16_19 31
|
||||
#define MSN_P3_16_19_MASK 0xF0
|
||||
|
||||
#define MSNA_MSNB_OFFSET 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t PLL_Multiplier_Integer;
|
||||
uint32_t PLL_Multiplier_Numerator;
|
||||
uint32_t PLL_Multiplier_Denominator;
|
||||
Si5351_PLLClockSourceTypeDef PLL_Clock_Source;
|
||||
Si5351_PLLCapacitiveLoadTypeDef PLL_Capacitive_Load;
|
||||
} Si5351_PLLConfigTypeDef;
|
||||
|
||||
/*
|
||||
* This section contains data structures for configuring the
|
||||
* Spread Spectrum feature.
|
||||
*/
|
||||
|
||||
#define REG_SSC_MODE 151
|
||||
#define SSC_MODE_MASK 0x80
|
||||
|
||||
//this selects the Spread Spectrum mode
|
||||
typedef enum
|
||||
{
|
||||
SS_Mode_DownSpread = 0x00,
|
||||
SS_Mode_CenterSpread = 0x80
|
||||
} Si5351_SSModeTypeDef;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SS_NCLK_0 = 0x00,
|
||||
SS_NCLK_1 = 0x10,
|
||||
SS_NCLK_2 = 0x20,
|
||||
SS_NCLK_3 = 0x30,
|
||||
SS_NCLK_4 = 0x40,
|
||||
SS_NCLK_5 = 0x50,
|
||||
SS_NCLK_6 = 0x60,
|
||||
SS_NCLK_7 = 0x70,
|
||||
SS_NCLK_8 = 0x80,
|
||||
SS_NCLK_9 = 0x90,
|
||||
SS_NCLK_10 = 0xA0,
|
||||
SS_NCLK_11 = 0xB0,
|
||||
SS_NCLK_12 = 0xC0,
|
||||
SS_NCLK_13 = 0xD0,
|
||||
SS_NCLK_14 = 0xE0,
|
||||
SS_NCLK_15 = 0xF0
|
||||
} Si5351_SSNCLKTypeDef;
|
||||
|
||||
#define REG_SSDN_P1_0_7 153
|
||||
#define REG_SSDN_P1_8_11 154
|
||||
#define SSDN_P1_8_11_MASK 0x0F
|
||||
|
||||
#define REG_SSDN_P2_0_7 150
|
||||
#define REG_SSDN_P2_8_14 149
|
||||
#define SSDN_P2_8_14_MASK 0x7F
|
||||
|
||||
#define REG_SSDN_P3_0_7 152
|
||||
#define REG_SSDN_P3_8_14 151
|
||||
#define SSDN_P3_8_14_MASK 0x7F
|
||||
|
||||
#define REG_SSUDP_0_7 155
|
||||
#define REG_SSUDP_8_11 154
|
||||
#define SSUDP_8_11_MASK 0xF0
|
||||
|
||||
#define REG_SSUP_P1_0_7 160
|
||||
#define REG_SSUP_P1_8_11 161
|
||||
#define SSUP_P1_8_11_MASK 0x0F
|
||||
|
||||
#define REG_SSUP_P2_0_7 157
|
||||
#define REG_SSUP_P2_8_14 156
|
||||
#define SSUP_P2_8_14_MASK 0x7F
|
||||
|
||||
#define REG_SSUP_P3_0_7 159
|
||||
#define REG_SSUP_P3_8_14 158
|
||||
#define SSUP_P3_8_14_MASK 0x7F
|
||||
|
||||
#define REG_SSC_EN 149
|
||||
#define SSC_EN_MASK 0x80
|
||||
|
||||
#define REG_SS_NCLK 161
|
||||
#define SS_NCLK_MASK 0xF0
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t SS_Amplitude_ppm; //amplitude of the SS feature in ppm of center frequency
|
||||
EnableState SS_Enable;
|
||||
Si5351_SSModeTypeDef SS_Mode;
|
||||
Si5351_SSNCLKTypeDef SS_NCLK;
|
||||
} Si5351_SSConfigTypeDef;
|
||||
|
||||
/*
|
||||
* This section contains data structures for configuring the
|
||||
* Output Multisynth.
|
||||
*/
|
||||
|
||||
//this selects the Multisynth clock source
|
||||
typedef enum
|
||||
{
|
||||
MS_Clock_Source_PLLA = 0x00,
|
||||
MS_Clock_Source_PLLB = 0x20
|
||||
} Si5351_MSClockSourceTypeDef;
|
||||
|
||||
#define REG_MS_P1_0_7 46
|
||||
#define REG_MS_P1_8_15 45
|
||||
#define REG_MS_P1_16_17 44
|
||||
#define MS_P1_16_17_MASK 0x03
|
||||
|
||||
#define REG_MS_P2_0_7 49
|
||||
#define REG_MS_P2_8_15 48
|
||||
#define REG_MS_P2_16_19 47
|
||||
#define MS_P2_16_19_MASK 0x0F
|
||||
|
||||
#define REG_MS_P3_0_7 43
|
||||
#define REG_MS_P3_8_15 42
|
||||
#define REG_MS_P3_16_19 47
|
||||
#define MS_P3_16_19_MASK 0xF0
|
||||
|
||||
#define REG_MS67_P1 90
|
||||
|
||||
#define REG_MS_INT 16
|
||||
#define MS_INT_MASK 0x40
|
||||
|
||||
#define REG_MS_DIVBY4 44
|
||||
#define MS_DIVBY4_MASK 0x0C
|
||||
|
||||
#define REG_MS_SRC 16
|
||||
#define MS_SRC_MASK 0x20
|
||||
|
||||
#define MS_SETUP_STEP 1
|
||||
#define MS_DIVIDER_STEP 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Si5351_MSClockSourceTypeDef MS_Clock_Source; //select source on MS input
|
||||
uint32_t MS_Divider_Integer; //the integer part of divider, called "a"
|
||||
uint32_t MS_Divider_Numerator; //the numerator, called "b"
|
||||
uint32_t MS_Divider_Denominator; //the denominator, called "c"
|
||||
} Si5351_MSConfigTypeDef; //sets MS divider ( a+(b/c) ) and clock (PLLA/PLLB)
|
||||
|
||||
/*
|
||||
* This section contains data structures for configuring the
|
||||
* CLK, R divider and output stage (joined together because they make
|
||||
* a tight block without any multiplexer).
|
||||
*/
|
||||
|
||||
#define REG_CLK_SRC 16
|
||||
#define CLK_SRC_MASK 0x0C
|
||||
|
||||
//this sets the CLK source clock
|
||||
typedef enum
|
||||
{
|
||||
CLK_Clock_Source_XTAL = 0x00,
|
||||
CLK_Clock_Source_CLKIN = 0x04,
|
||||
CLK_Clock_Source_MS0_MS4 = 0x08, //this uses MS0 for CLK0..3 and MS4 for CLK4..7
|
||||
CLK_Clock_Source_MS_Own = 0x0C //this uses MSx for CLKx
|
||||
} Si5351_CLKClockSourceTypeDef; //configures multiplexer on CLK input
|
||||
|
||||
#define REG_CLK_R_DIV 44
|
||||
#define CLK_R_DIV_MASK 0x70
|
||||
|
||||
#define REG_CLK_R67_DIV 92
|
||||
#define CLK_R67_DIV_MASK 0x07
|
||||
|
||||
//this sets the R divider ratio
|
||||
typedef enum
|
||||
{
|
||||
CLK_R_Div1 = 0x00,
|
||||
CLK_R_Div2 = 0x10,
|
||||
CLK_R_Div4 = 0x20,
|
||||
CLK_R_Div8 = 0x30,
|
||||
CLK_R_Div16 = 0x40,
|
||||
CLK_R_Div32 = 0x50,
|
||||
CLK_R_Div64 = 0x60,
|
||||
CLK_R_Div128 = 0x70
|
||||
} Si5351_CLKRDivTypeDef;
|
||||
|
||||
#define REG_CLK_DIS_STATE 24
|
||||
#define CLK_DIS_STATE_MASK 0x03
|
||||
|
||||
//this sets output buffer behaviour when disabled
|
||||
typedef enum
|
||||
{
|
||||
CLK_Disable_State_LOW = 0x00,
|
||||
CLK_Disable_State_HIGH = 0x01,
|
||||
CLK_Disable_State_HIGH_Z = 0x02, //three-stated when off
|
||||
CLK_Disable_State_ALWAYS_ON = 0x03 //cannot be disabled
|
||||
} Si5351_CLKDisableStateTypeDef;
|
||||
|
||||
#define REG_CLK_IDRV 16
|
||||
#define CLK_IDRV_MASK 0x03
|
||||
|
||||
//this sets current drive of the output buffer
|
||||
typedef enum
|
||||
{
|
||||
CLK_I_Drv_2mA = 0x00,
|
||||
CLK_I_Drv_4mA = 0x01,
|
||||
CLK_I_Drv_6mA = 0x02,
|
||||
CLK_I_Drv_8mA = 0x03
|
||||
} Si5351_CLKIDrvTypeDef;
|
||||
|
||||
#define REG_CLK_PHOFF 165
|
||||
#define CLK_PHOFF_MASK 0x7F
|
||||
|
||||
#define REG_CLK_EN 3
|
||||
|
||||
#define REG_CLK_INV 16
|
||||
#define CLK_INV_MASK 0x10
|
||||
|
||||
#define REG_CLK_PDN 16
|
||||
#define CLK_PDN_MASK 0x80
|
||||
|
||||
#define REG_CLK_OEB 9
|
||||
|
||||
#define CLK_PHOFF_STEP 1
|
||||
#define CLK_SETUP_STEP 1
|
||||
#define CLK_R_DIV_STEP 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Si5351_CLKClockSourceTypeDef CLK_Clock_Source; //clock source
|
||||
|
||||
/* this sets the time offset of the CLK channel, basic unit
|
||||
* is one quarter of the VCO period (90deg offset),
|
||||
* set it to 4*fVCO*toffset, the value is 7-bit, the max time offset
|
||||
* varies between 35 and 53 ns (1 cycle for 28 and 19 MHz, respectively)
|
||||
* according to the current frequency of the VCO
|
||||
*/
|
||||
uint8_t CLK_QuarterPeriod_Offset;
|
||||
|
||||
Si5351_CLKRDivTypeDef CLK_R_Div; //R divider value (only powers of 2)
|
||||
EnableState CLK_Invert; //invert output clock
|
||||
EnableState CLK_Enable; //enable flag
|
||||
EnableState CLK_PowerDown; //powerdown flag
|
||||
Si5351_CLKDisableStateTypeDef CLK_Disable_State; //sets output behaviour when disabled
|
||||
Si5351_CLKIDrvTypeDef CLK_I_Drv; //output driver current drive strength
|
||||
EnableState CLK_Use_OEB_Pin; //allows using OEB pin to enable clock
|
||||
} Si5351_CLKConfigTypeDef;
|
||||
|
||||
/*
|
||||
* This section contains main data structure for Si5351 configuration
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*
|
||||
* These are frequencies of the input clocks, set it in Hz.
|
||||
*/
|
||||
uint32_t f_XTAL;
|
||||
uint32_t f_CLKIN;
|
||||
|
||||
//Interrupt masking - enabling it disables the int source from pulling INTR low
|
||||
EnableState Interrupt_Mask_SysInit;
|
||||
EnableState Interrupt_Mask_PLLB;
|
||||
EnableState Interrupt_Mask_PLLA;
|
||||
EnableState Interrupt_Mask_CLKIN;
|
||||
EnableState Interrupt_Mask_XTAL;
|
||||
|
||||
//Fanout enable - enables internal clock routing
|
||||
EnableState Fanout_MS_EN;
|
||||
EnableState Fanout_XO_EN;
|
||||
EnableState Fanout_CLKIN_EN;
|
||||
|
||||
I2C_TypeDef *I2Cx; //the I2C interface that will be used
|
||||
uint8_t HW_I2C_Address; //I2C address of the Si5351 for the packages with A0 pin
|
||||
//(also, some duds with strange address reported)
|
||||
Si5351_OSCConfigTypeDef OSC; //Oscillator, CLKIN and VCXO settings
|
||||
Si5351_PLLConfigTypeDef PLL[2]; //PLL settings for PLLA and PLLB
|
||||
Si5351_MSConfigTypeDef MS[8]; //MultiSynth[0..7] settings
|
||||
Si5351_CLKConfigTypeDef CLK[8]; //CLK[0..7], R divider and output stage settings
|
||||
Si5351_SSConfigTypeDef SS; //spread spectrum settings
|
||||
} Si5351_ConfigTypeDef;
|
||||
|
||||
/*
|
||||
* Typedefs for selecting PLL, MS and CLK to be used
|
||||
*/
|
||||
|
||||
//this selects PLL channel
|
||||
typedef enum
|
||||
{
|
||||
PLL_A = 0,
|
||||
PLL_B = 1
|
||||
} Si5351_PLLChannelTypeDef;
|
||||
|
||||
//this selects Multisynth channel
|
||||
typedef enum
|
||||
{
|
||||
MS0 = 0,
|
||||
MS1 = 1,
|
||||
MS2 = 2,
|
||||
MS3 = 3,
|
||||
MS4 = 4,
|
||||
MS5 = 5,
|
||||
MS6 = 6,
|
||||
MS7 = 7
|
||||
} Si5351_MSChannelTypeDef;
|
||||
|
||||
//this selects CLK channel
|
||||
typedef enum
|
||||
{
|
||||
CLK0 = 0,
|
||||
CLK1 = 1,
|
||||
CLK2 = 2,
|
||||
CLK3 = 3,
|
||||
CLK4 = 4,
|
||||
CLK5 = 5,
|
||||
CLK6 = 6,
|
||||
CLK7 = 7
|
||||
} Si5351_CLKChannelTypeDef;
|
||||
|
||||
//this selects device status flag
|
||||
typedef enum
|
||||
{
|
||||
StatusBit_SysInit = DEV_SYS_INIT_MASK,
|
||||
StatusBit_PLLA = DEV_STKY_LOL_A_MASK,
|
||||
StatusBit_PLLB = DEV_LOL_B_MASK,
|
||||
StatusBit_CLKIN = DEV_LOS_CLKIN_MASK,
|
||||
StatusBit_XTAL = DEV_LOS_XTAL_MASK,
|
||||
} Si5351_StatusBitTypeDef;
|
||||
|
||||
//these write to and read from a Si5351 register, for porting
|
||||
//purposes, these functions should be the only ones which should need edits
|
||||
int Si5351_WriteRegister(Si5351_ConfigTypeDef *Si5351_ConfigStruct, uint8_t reg_address, uint8_t reg_data);
|
||||
uint8_t Si5351_ReadRegister(Si5351_ConfigTypeDef *Si5351_ConfigStruct, uint8_t reg_address);
|
||||
|
||||
void Si5351_StructInit(Si5351_ConfigTypeDef *Si5351_ConfigStruct);
|
||||
|
||||
void Si5351_OSCConfig(Si5351_ConfigTypeDef *Si5351_ConfigStruct);
|
||||
|
||||
EnableState Si5351_CheckStatusBit(Si5351_ConfigTypeDef *Si5351_ConfigStruct, Si5351_StatusBitTypeDef StatusBit);
|
||||
EnableState Si5351_CheckStickyBit(Si5351_ConfigTypeDef *Si5351_ConfigStruct, Si5351_StatusBitTypeDef StatusBit);
|
||||
void Si5351_InterruptConfig(Si5351_ConfigTypeDef *Si5351_ConfigStruct);
|
||||
void Si5351_ClearStickyBit(Si5351_ConfigTypeDef *Si5351_ConfigStruct, Si5351_StatusBitTypeDef StatusBit);
|
||||
|
||||
void Si5351_PLLConfig(Si5351_ConfigTypeDef *Si5351_ConfigStruct, Si5351_PLLChannelTypeDef PLL_Channel);
|
||||
void Si5351_PLLReset(Si5351_ConfigTypeDef *Si5351_ConfigStruct, Si5351_PLLChannelTypeDef PLL_Channel);
|
||||
void Si5351_PLLSimultaneousReset(Si5351_ConfigTypeDef *Si5351_ConfigStruct);
|
||||
|
||||
void Si5351_SSConfig(Si5351_ConfigTypeDef *Si5351_ConfigStruct);
|
||||
|
||||
void Si5351_MSConfig(Si5351_ConfigTypeDef *Si5351_ConfigStruct, Si5351_MSChannelTypeDef MS_Channel);
|
||||
|
||||
void Si5351_CLKPowerCmd(Si5351_ConfigTypeDef *Si5351_ConfigStruct, Si5351_CLKChannelTypeDef CLK_Channel);
|
||||
void Si5351_CLKConfig(Si5351_ConfigTypeDef *Si5351_ConfigStruct, Si5351_CLKChannelTypeDef CLK_Channel);
|
||||
|
||||
int Si5351_Init(Si5351_ConfigTypeDef *Si5351_ConfigStruct);
|
||||
#endif /* SI5351_H_ */
|
||||
#if !defined _SYS_ERRNO_H_ && !defined __ERRNO_H__ && !defined __AT1_ERROR_NUMBERS__
|
||||
typedef enum {
|
||||
EPERM = 1, /*!< Operation not permitted */
|
||||
EIO = 5, /*!< I/O error */
|
||||
ENOMEM = 12, /*!< Out of memory */
|
||||
EFAULT = 14, /*!< Bad address */
|
||||
EBUSY = 16, /*!< Device or resource busy */
|
||||
ENODEV = 19, /*!< No such device */
|
||||
EINVAL = 22, /*!< Invalid argument */
|
||||
EADDRINUSE = 98,/*!< Address already in use */
|
||||
ETIMEDOUT = 116 /*!< Connection timed out */
|
||||
} si5351_errno_t;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
SI5351_PLLA = 0,
|
||||
SI5351_PLLB
|
||||
}si5351_pll_t;
|
||||
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
#define __SI5351__ 1
|
||||
#define __SI5351_MINOR__ 1
|
||||
#define __SI5351_PATCHLEVEL__ 0
|
||||
|
||||
#define SI5351_VERSION (__SI5351__ * 10000 \
|
||||
+ __SI5351_MINOR__ * 100 \
|
||||
+ __SI5351_PATCHLEVEL__)
|
||||
|
||||
#ifndef SI5351_DEFAULTS
|
||||
#define SI5351_DEFAULTS 1
|
||||
#define SI5351_I2C_ADDR_DEFAULT 0x60
|
||||
#define SI5351_XTAL_DEFAULT 25000000u /* default xtal frequency in [Hz] */
|
||||
#define SI5351_NUMBER_OF_OUTPUTS 8
|
||||
#endif
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
#if SI5351_DEFAULTS
|
||||
si5351_inst_t si5351_initialize(void * i2c_handle);
|
||||
int si5351_deinitialize(void);
|
||||
#endif
|
||||
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);
|
||||
int si5351_set_clk(si5351_inst_t inst, uint8_t clk, uint32_t frequency, si5351_pll_t pll);
|
||||
|
||||
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);
|
||||
|
||||
int si5351_get_instance(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);
|
||||
int si5351_set_phase(si5351_inst_t inst, uint8_t clk, uint8_t phase);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __SI5351_H__ */
|
||||
|
@ -1,164 +0,0 @@
|
||||
/******************************************************************************
|
||||
* File Name : stm32_si5351.h
|
||||
* Description : STM32 library/driver for the Si5351 clock chip
|
||||
* from Skyworks Solutions, Inc. (former SiLabs)
|
||||
******************************************************************************
|
||||
* @author: Thomas Kuschel KW4NZ, created 2022-05-11
|
||||
*
|
||||
* originally written by Petr Polasek, created Feb 16, 2018
|
||||
******************************************************************************
|
||||
* DO NOT EDIT THIS FILE FOR CONFIGURATION, USE THE FOLLOWING PROCEDURE:
|
||||
*
|
||||
* Inside your main.c program or within your STM32 code:
|
||||
* Include this header to the the main.c: #include "stm32_si5351.h"
|
||||
* You've to initialize the I2C functionality first (e.g. with STM32CubeIDE)
|
||||
* Afterwards, when there is a handle like "I2C_HandleTypeDef hi2c1;",
|
||||
* you simply initialize this stm32_si5351 library in your main.c ,
|
||||
* just after the MX_I2C1_Init();
|
||||
* so between the USER CODE like using the given i2c handle "hi2c1" with default values:
|
||||
*
|
||||
* /\* USER CODE BEGIN 2 *\/
|
||||
*
|
||||
* si5351_inst_t si5351_inst;
|
||||
* si5351_initialize(&hi2c1);
|
||||
* /\* USER CODE END 2 *\/
|
||||
*
|
||||
* The 7-bit device (slave) address of the Si5351 consist of a 6-bit fixed
|
||||
* address plus a user selectable LSB bit as shown in Figure 6 of the datasheet.
|
||||
* The LSB bit is selectable as 0 or 1 using the optional A0 pin which is useful
|
||||
* for applications that require more than one Si5351 on a single I2C bus.
|
||||
* Only the Si5351A 20-QFN and Si5351A 16-QFN have the A0 LSB pin option.
|
||||
* If a part does not have the A0 pin, the default address is 0x60 with
|
||||
* the A0 bit set to 0.
|
||||
*
|
||||
* So additionally you may drive more then one Si5351 at the same or
|
||||
* another I2C bus when calling the init function with the given
|
||||
* I2C bus address (default: 0x60)
|
||||
* ( - internally this I2C address is shifted to the left
|
||||
* for the proper usage of the I2C HAL driver i.e. it becomes 0xC0 )
|
||||
*
|
||||
* Example:
|
||||
* \\ Define handlers for the sum of three SI5351 clock generators:
|
||||
* si5351_HandleTypeDef h_si5351[3];
|
||||
*
|
||||
* // 1st SI5351 chip and with an A0 = 0:
|
||||
* h_si5351[0] = si5351_init(&hi2c1, 25000000, 0x60);
|
||||
* // 2nd SI5351 chip on the same I2C bus "hi2c1" but address line A0 = 1
|
||||
* h_si5351[1] = si5351_init(&hi2c1, 27000000, 0x61);
|
||||
* // 3rd SI5351 chip on another IC2 bus with handle "hi2c2" *\/
|
||||
* h_si5351[2] = si5351_init(&hi2c2, 25000000, 0x60);
|
||||
*
|
||||
* PROs:
|
||||
* The library is preemptive and can be used within an operating system.
|
||||
* All structures and used variables are dynamically allocated.
|
||||
* CONs:
|
||||
* Not fully tested, but used with FreeRTOS and with 2 I2C bus systems.
|
||||
*
|
||||
* CHANGES:
|
||||
* - Removed several defines, enums, etc. from the header file, b/c we do not
|
||||
* want to export them to other programs
|
||||
*
|
||||
*
|
||||
* The old simple example to get 50 kHz output with an 25 MHz crystal:
|
||||
* Si5351_ConfigTypeDef Si5351_ConfigStruct;
|
||||
* Si5351_StructInit(&Si5351_ConfigStruct); //initialize the structure with default "safe" values
|
||||
* Si5351_ConfigStruct.OSC.OSC_XTAL_Load = XTAL_Load_8_pF; //use 8 pF load for crystal
|
||||
* Si5351_ConfigStruct.PLL[0].PLL_Clock_Source = PLL_Clock_Source_XTAL; //select xrystal as clock input for the PLL
|
||||
* Si5351_ConfigStruct.PLL[0].PLL_Multiplier_Integer = 32; //multiply the clock frequency by 32, this gets us 800 MHz clock
|
||||
* Si5351_ConfigStruct.MS[0].MS_Clock_Source = MS_Clock_Source_PLLA; //select PLLA as clock source for MultiSynth 0
|
||||
* Si5351_ConfigStruct.MS[0].MS_Divider_Integer = 250; //divide the 800 MHz by 250 this gets us 3.2 MHz
|
||||
* Si5351_ConfigStruct.CLK[0].CLK_R_Div = CLK_R_Div64; //divide the MultiSynth output by 64, this gets us 50 kHz
|
||||
* Si5351_ConfigStruct.CLK[0].CLK_Enable = ON; //turn on the output
|
||||
* Si5351_Init(&Si5351_ConfigStruct); //apply the changes
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _STM32_SI5351_H_
|
||||
#define _STM32_SI5351_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include <stm32_si5351_reg.h> /* register map of the Si5351 */
|
||||
/* #include <errno.h> could also be included */
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/*!< Si5351 instance typedef -- handle as pointer */
|
||||
typedef struct __SI5351_HandleTypeDef *si5351_inst_t;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** @enum errno_t Error Number Constants, @TODO you can also include <errno.h>
|
||||
*/
|
||||
#if !defined _SYS_ERRNO_H_ && !defined __ERRNO_H__ && !defined __AT1_ERROR_NUMBERS__
|
||||
typedef enum {
|
||||
EPERM = 1, /*!< Operation not permitted */
|
||||
EIO = 5, /*!< I/O error */
|
||||
ENOMEM = 12, /*!< Out of memory */
|
||||
EFAULT = 14, /*!< Bad address */
|
||||
EBUSY = 16, /*!< Device or resource busy */
|
||||
ENODEV = 19, /*!< No such device */
|
||||
EINVAL = 22, /*!< Invalid argument */
|
||||
EADDRINUSE = 98,/*!< Address already in use */
|
||||
ETIMEDOUT = 116 /*!< Connection timed out */
|
||||
} si5351_errno_t;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
SI5351_PLLA = 0,
|
||||
SI5351_PLLB
|
||||
}si5351_pll_t;
|
||||
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
#define __SI5351__ 1
|
||||
#define __SI5351_MINOR__ 0
|
||||
#define __SI5351_PATCHLEVEL__ 1
|
||||
|
||||
#define SI5351_VERSION (__SI5351__ * 10000 \
|
||||
+ __SI5351_MINOR__ * 100 \
|
||||
+ __SI5351_PATCHLEVEL__)
|
||||
|
||||
#ifndef SI5351_DEFAULTS
|
||||
#define SI5351_DEFAULTS 1
|
||||
#define SI5351_NUMBER_OF_OUTPUTS 8
|
||||
#define SI5351_I2C_ADDRESS_DEFAULT 0x60
|
||||
#define SI5351_XTAL_DEFAULT 25000000u // default xtal in [Hz]
|
||||
#endif
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
si5351_inst_t si5351_init(void * i2c_handle, uint32_t xtal_frequency, uint8_t i2c_address, size_t datasize);
|
||||
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);
|
||||
int si5351_set_clk(si5351_inst_t inst, uint32_t frequency, uint8_t clk, si5351_pll_t pll);
|
||||
int si5351_set_clk_phase(si5351_inst_t inst, uint32_t frequency, double phase, uint8_t clk, si5351_pll_t pll);
|
||||
int si5351_set_phase(si5351_inst_t inst, uint8_t phase, uint8_t clk);
|
||||
|
||||
#if SI5351_DEFAULTS
|
||||
si5351_inst_t si5351_initialize(void * i2c_handle);
|
||||
int si5351_deinitialize(void);
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
/* if initialized with data get a write and read functionality for data with: */
|
||||
int si5351_write_data(si5351_inst_t inst, void * data);
|
||||
int si5351_read_data(si5351_inst_t inst, void * data);
|
||||
|
||||
int si5351_get_instance(si5351_inst_t *inst);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif // _STM32_SI5351_H_
|
Reference in New Issue
Block a user