f0x.at1/stm32l4a6zg-f0x.at1/Core/external_sources/polasek/si5351.h

526 lines
14 KiB
C

/*
* 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
*
*/
#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;
#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_ */