625 lines
18 KiB
C
625 lines
18 KiB
C
|
/******************************************************************************
|
||
|
* 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":
|
||
|
*
|
||
|
* /\* USER CODE BEGIN 2 *\/
|
||
|
* si5351_init(&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>
|
||
|
|
||
|
/* Private includes ----------------------------------------------------------*/
|
||
|
|
||
|
/* Exported types ------------------------------------------------------------*/
|
||
|
/* Si5351 instance typedef */
|
||
|
typedef struct __SI5351_HandleTypeDef *si5351_inst_t;
|
||
|
|
||
|
/* Exported constants --------------------------------------------------------*/
|
||
|
/** @enum errno_t Error Number Constants
|
||
|
*/
|
||
|
typedef enum {
|
||
|
EPERM = 1, /*!< Operation not permitted */
|
||
|
ENOMEM = 12, /*!< Out of memory */
|
||
|
ENODEV = 19, /*!< No such device */
|
||
|
EINVAL = 22, /*!< Invalid argument */
|
||
|
EADDRINUSE = 98 /*!< Address already in use */
|
||
|
} si5351_errno_t;
|
||
|
|
||
|
/* Exported variables --------------------------------------------------------*/
|
||
|
|
||
|
/* Exported macros -----------------------------------------------------------*/
|
||
|
|
||
|
/* 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);
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
} /* extern "C" */
|
||
|
#endif
|
||
|
|
||
|
#endif /* STM32_SI5351_H */
|
||
|
|
||
|
/*
|
||
|
* 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
|
||
|
*
|
||
|
*/
|
||
|
#if 0
|
||
|
#ifndef ENABLESTATE
|
||
|
#define ENABLESTATE
|
||
|
typedef enum
|
||
|
{
|
||
|
OFF = 0,
|
||
|
ON = 1
|
||
|
} EnableState;
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* This section contains register addresses and bit masks for
|
||
|
* the device status registers.
|
||
|
*/
|
||
|
|
||
|
#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_ */
|
||
|
|