Si5351C: Un-singleton the high- and low-level drivers. Proper.
This commit is contained in:
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
#include "hackrf_core.h"
|
#include "hackrf_core.h"
|
||||||
#include "si5351c.h"
|
#include "si5351c.h"
|
||||||
#include "si5351c_drv.h"
|
|
||||||
#include "max2837.h"
|
#include "max2837.h"
|
||||||
#include "rffc5071.h"
|
#include "rffc5071.h"
|
||||||
#include "sgpio.h"
|
#include "sgpio.h"
|
||||||
@ -36,6 +35,10 @@
|
|||||||
|
|
||||||
#define WAIT_CPU_CLOCK_INIT_DELAY (10000)
|
#define WAIT_CPU_CLOCK_INIT_DELAY (10000)
|
||||||
|
|
||||||
|
si5351c_driver_t clock_gen = {
|
||||||
|
.i2c_address = 0x60,
|
||||||
|
};
|
||||||
|
|
||||||
void delay(uint32_t duration)
|
void delay(uint32_t duration)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
@ -119,9 +122,9 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
|
|||||||
|
|
||||||
/* Can we enable integer mode ? */
|
/* Can we enable integer mode ? */
|
||||||
if (a & 0x1 || b)
|
if (a & 0x1 || b)
|
||||||
si5351c_set_int_mode(0, 0);
|
si5351c_set_int_mode(&clock_gen, 0, 0);
|
||||||
else
|
else
|
||||||
si5351c_set_int_mode(0, 1);
|
si5351c_set_int_mode(&clock_gen, 0, 1);
|
||||||
|
|
||||||
/* Final MS values */
|
/* Final MS values */
|
||||||
MSx_P1 = 128*a + (128 * b/c) - 512;
|
MSx_P1 = 128*a + (128 * b/c) - 512;
|
||||||
@ -129,13 +132,13 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
|
|||||||
MSx_P3 = c;
|
MSx_P3 = c;
|
||||||
|
|
||||||
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
|
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
|
||||||
si5351c_configure_multisynth(0, MSx_P1, MSx_P2, MSx_P3, 1);
|
si5351c_configure_multisynth(&clock_gen, 0, MSx_P1, MSx_P2, MSx_P3, 1);
|
||||||
|
|
||||||
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
|
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
|
||||||
si5351c_configure_multisynth(1, 0, 0, 0, 0);//p1 doesn't matter
|
si5351c_configure_multisynth(&clock_gen, 1, 0, 0, 0, 0);//p1 doesn't matter
|
||||||
|
|
||||||
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
|
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
|
||||||
si5351c_configure_multisynth(2, 0, 0, 0, 0);//p1 doesn't matter
|
si5351c_configure_multisynth(&clock_gen, 2, 0, 0, 0, 0);//p1 doesn't matter
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -175,13 +178,13 @@ bool sample_rate_set(const uint32_t sample_rate_hz) {
|
|||||||
* values are irrelevant. */
|
* values are irrelevant. */
|
||||||
|
|
||||||
/* MS0/CLK1 is the source for the MAX5864 codec. */
|
/* MS0/CLK1 is the source for the MAX5864 codec. */
|
||||||
si5351c_configure_multisynth(1, 4608, 0, 1, r_div_sample);
|
si5351c_configure_multisynth(&clock_gen, 1, 4608, 0, 1, r_div_sample);
|
||||||
|
|
||||||
/* MS0/CLK2 is the source for the CPLD codec clock (same as CLK1). */
|
/* MS0/CLK2 is the source for the CPLD codec clock (same as CLK1). */
|
||||||
si5351c_configure_multisynth(2, 4608, 0, 1, r_div_sample);
|
si5351c_configure_multisynth(&clock_gen, 2, 4608, 0, 1, r_div_sample);
|
||||||
|
|
||||||
/* MS0/CLK3 is the source for the SGPIO clock. */
|
/* MS0/CLK3 is the source for the SGPIO clock. */
|
||||||
si5351c_configure_multisynth(3, 4608, 0, 1, r_div_sgpio);
|
si5351c_configure_multisynth(&clock_gen, 3, 4608, 0, 1, r_div_sgpio);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
@ -238,13 +241,13 @@ bool sample_rate_set(const uint32_t sample_rate_hz) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
|
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
|
||||||
si5351c_configure_multisynth(0, p1, p2, p3, 1);
|
si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1);
|
||||||
|
|
||||||
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
|
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
|
||||||
si5351c_configure_multisynth(1, p1, 0, 1, 0);//p1 doesn't matter
|
si5351c_configure_multisynth(&clock_gen, 1, p1, 0, 1, 0);//p1 doesn't matter
|
||||||
|
|
||||||
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
|
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
|
||||||
si5351c_configure_multisynth(2, p1, 0, 1, 0);//p1 doesn't matter
|
si5351c_configure_multisynth(&clock_gen, 2, p1, 0, 1, 0);//p1 doesn't matter
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
@ -267,13 +270,13 @@ void cpu_clock_init(void)
|
|||||||
|
|
||||||
i2c0_init(15);
|
i2c0_init(15);
|
||||||
|
|
||||||
si5351c_disable_all_outputs();
|
si5351c_disable_all_outputs(&clock_gen);
|
||||||
si5351c_disable_oeb_pin_control();
|
si5351c_disable_oeb_pin_control(&clock_gen);
|
||||||
si5351c_power_down_all_clocks();
|
si5351c_power_down_all_clocks(&clock_gen);
|
||||||
si5351c_set_crystal_configuration();
|
si5351c_set_crystal_configuration(&clock_gen);
|
||||||
si5351c_enable_xo_and_ms_fanout();
|
si5351c_enable_xo_and_ms_fanout(&clock_gen);
|
||||||
si5351c_configure_pll_sources();
|
si5351c_configure_pll_sources(&clock_gen);
|
||||||
si5351c_configure_pll_multisynth();
|
si5351c_configure_pll_multisynth(&clock_gen);
|
||||||
|
|
||||||
#ifdef JELLYBEAN
|
#ifdef JELLYBEAN
|
||||||
/*
|
/*
|
||||||
@ -289,13 +292,13 @@ void cpu_clock_init(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* MS0/CLK0 is the source for the MAX2837 clock input. */
|
/* MS0/CLK0 is the source for the MAX2837 clock input. */
|
||||||
si5351c_configure_multisynth(0, 2048, 0, 1, 0); /* 40MHz */
|
si5351c_configure_multisynth(&clock_gen, 0, 2048, 0, 1, 0); /* 40MHz */
|
||||||
|
|
||||||
/* MS4/CLK4 is the source for the LPC43xx microcontroller. */
|
/* MS4/CLK4 is the source for the LPC43xx microcontroller. */
|
||||||
si5351c_configure_multisynth(4, 8021, 0, 3, 0); /* 12MHz */
|
si5351c_configure_multisynth(&clock_gen, 4, 8021, 0, 3, 0); /* 12MHz */
|
||||||
|
|
||||||
/* MS5/CLK5 is the source for the RFFC5071 mixer. */
|
/* MS5/CLK5 is the source for the RFFC5071 mixer. */
|
||||||
si5351c_configure_multisynth(5, 1536, 0, 1, 0); /* 50MHz */
|
si5351c_configure_multisynth(&clock_gen, 5, 1536, 0, 1, 0); /* 50MHz */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined JAWBREAKER || defined HACKRF_ONE)
|
#if (defined JAWBREAKER || defined HACKRF_ONE)
|
||||||
@ -312,28 +315,28 @@ void cpu_clock_init(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* MS3/CLK3 is the source for the external clock output. */
|
/* MS3/CLK3 is the source for the external clock output. */
|
||||||
si5351c_configure_multisynth(3, 80*128-512, 0, 1, 0); /* 800/80 = 10MHz */
|
si5351c_configure_multisynth(&clock_gen, 3, 80*128-512, 0, 1, 0); /* 800/80 = 10MHz */
|
||||||
|
|
||||||
/* MS4/CLK4 is the source for the RFFC5071 mixer. */
|
/* MS4/CLK4 is the source for the RFFC5071 mixer. */
|
||||||
si5351c_configure_multisynth(4, 16*128-512, 0, 1, 0); /* 800/16 = 50MHz */
|
si5351c_configure_multisynth(&clock_gen, 4, 16*128-512, 0, 1, 0); /* 800/16 = 50MHz */
|
||||||
|
|
||||||
/* MS5/CLK5 is the source for the MAX2837 clock input. */
|
/* MS5/CLK5 is the source for the MAX2837 clock input. */
|
||||||
si5351c_configure_multisynth(5, 20*128-512, 0, 1, 0); /* 800/20 = 40MHz */
|
si5351c_configure_multisynth(&clock_gen, 5, 20*128-512, 0, 1, 0); /* 800/20 = 40MHz */
|
||||||
|
|
||||||
/* MS6/CLK6 is unused. */
|
/* MS6/CLK6 is unused. */
|
||||||
/* MS7/CLK7 is the source for the LPC43xx microcontroller. */
|
/* MS7/CLK7 is the source for the LPC43xx microcontroller. */
|
||||||
uint8_t ms7data[] = { 90, 255, 20, 0 };
|
uint8_t ms7data[] = { 90, 255, 20, 0 };
|
||||||
si5351c_write(ms7data, sizeof(ms7data));
|
si5351c_write(&clock_gen, ms7data, sizeof(ms7data));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Set to 10 MHz, the common rate between Jellybean and Jawbreaker. */
|
/* Set to 10 MHz, the common rate between Jellybean and Jawbreaker. */
|
||||||
sample_rate_set(10000000);
|
sample_rate_set(10000000);
|
||||||
|
|
||||||
si5351c_set_clock_source(PLL_SOURCE_XTAL);
|
si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL);
|
||||||
// soft reset
|
// soft reset
|
||||||
uint8_t resetdata[] = { 177, 0xac };
|
uint8_t resetdata[] = { 177, 0xac };
|
||||||
si5351c_write(resetdata, sizeof(resetdata));
|
si5351c_write(&clock_gen, resetdata, sizeof(resetdata));
|
||||||
si5351c_enable_clock_outputs();
|
si5351c_enable_clock_outputs(&clock_gen);
|
||||||
|
|
||||||
//FIXME disable I2C
|
//FIXME disable I2C
|
||||||
/* Kick I2C0 down to 400kHz when we switch over to APB1 clock = 204MHz */
|
/* Kick I2C0 down to 400kHz when we switch over to APB1 clock = 204MHz */
|
||||||
|
@ -32,6 +32,8 @@ extern "C"
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "si5351c_drv.h"
|
||||||
|
|
||||||
/* hardware identification number */
|
/* hardware identification number */
|
||||||
#define BOARD_ID_JELLYBEAN 0
|
#define BOARD_ID_JELLYBEAN 0
|
||||||
#define BOARD_ID_JAWBREAKER 1
|
#define BOARD_ID_JAWBREAKER 1
|
||||||
@ -350,6 +352,8 @@ typedef enum {
|
|||||||
|
|
||||||
void delay(uint32_t duration);
|
void delay(uint32_t duration);
|
||||||
|
|
||||||
|
extern si5351c_driver_t clock_gen;
|
||||||
|
|
||||||
void cpu_clock_init(void);
|
void cpu_clock_init(void);
|
||||||
void cpu_clock_pll1_low_speed(void);
|
void cpu_clock_pll1_low_speed(void);
|
||||||
void cpu_clock_pll1_max_speed(void);
|
void cpu_clock_pll1_max_speed(void);
|
||||||
|
@ -27,21 +27,21 @@
|
|||||||
enum pll_sources active_clock_source;
|
enum pll_sources active_clock_source;
|
||||||
|
|
||||||
/* Disable all CLKx outputs. */
|
/* Disable all CLKx outputs. */
|
||||||
void si5351c_disable_all_outputs()
|
void si5351c_disable_all_outputs(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 3, 0xFF };
|
uint8_t data[] = { 3, 0xFF };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Turn off OEB pin control for all CLKx */
|
/* Turn off OEB pin control for all CLKx */
|
||||||
void si5351c_disable_oeb_pin_control()
|
void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 9, 0xFF };
|
uint8_t data[] = { 9, 0xFF };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Power down all CLKx */
|
/* Power down all CLKx */
|
||||||
void si5351c_power_down_all_clocks()
|
void si5351c_power_down_all_clocks(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 16
|
uint8_t data[] = { 16
|
||||||
, SI5351C_CLK_POWERDOWN
|
, SI5351C_CLK_POWERDOWN
|
||||||
@ -53,7 +53,7 @@ void si5351c_power_down_all_clocks()
|
|||||||
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE
|
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE
|
||||||
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE
|
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE
|
||||||
};
|
};
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -61,20 +61,20 @@ void si5351c_power_down_all_clocks()
|
|||||||
* Reads as 0xE4 on power-up
|
* Reads as 0xE4 on power-up
|
||||||
* Set to 8pF based on crystal specs and HackRF One testing
|
* Set to 8pF based on crystal specs and HackRF One testing
|
||||||
*/
|
*/
|
||||||
void si5351c_set_crystal_configuration()
|
void si5351c_set_crystal_configuration(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 183, 0x80 };
|
uint8_t data[] = { 183, 0x80 };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register 187: Fanout Enable
|
* Register 187: Fanout Enable
|
||||||
* Turn on XO and MultiSynth fanout only.
|
* Turn on XO and MultiSynth fanout only.
|
||||||
*/
|
*/
|
||||||
void si5351c_enable_xo_and_ms_fanout()
|
void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 187, 0xD0 };
|
uint8_t data[] = { 187, 0xD0 };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -83,34 +83,35 @@ void si5351c_enable_xo_and_ms_fanout()
|
|||||||
* PLLA_SRC=0 (XTAL)
|
* PLLA_SRC=0 (XTAL)
|
||||||
* PLLB_SRC=1 (CLKIN)
|
* PLLB_SRC=1 (CLKIN)
|
||||||
*/
|
*/
|
||||||
void si5351c_configure_pll_sources(void)
|
void si5351c_configure_pll_sources(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 15, 0x08 };
|
uint8_t data[] = { 15, 0x08 };
|
||||||
|
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MultiSynth NA (PLLA) and NB (PLLB) */
|
/* MultiSynth NA (PLLA) and NB (PLLB) */
|
||||||
void si5351c_configure_pll_multisynth(void)
|
void si5351c_configure_pll_multisynth(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
//init plla to (0x0e00+512)/128*25mhz xtal = 800mhz -> int mode
|
//init plla to (0x0e00+512)/128*25mhz xtal = 800mhz -> int mode
|
||||||
uint8_t data[] = { 26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00 };
|
uint8_t data[] = { 26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00 };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
|
|
||||||
/* 10 MHz input on CLKIN for PLLB */
|
/* 10 MHz input on CLKIN for PLLB */
|
||||||
data[0] = 34;
|
data[0] = 34;
|
||||||
data[4] = 0x26;
|
data[4] = 0x26;
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void si5351c_reset_pll(void)
|
void si5351c_reset_pll(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
/* reset PLLA and PLLB */
|
/* reset PLLA and PLLB */
|
||||||
uint8_t data[] = { 177, 0xA0 };
|
uint8_t data[] = { 177, 0xA0 };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void si5351c_configure_multisynth(const uint_fast8_t ms_number,
|
void si5351c_configure_multisynth(si5351c_driver_t* const drv,
|
||||||
|
const uint_fast8_t ms_number,
|
||||||
const uint32_t p1, const uint32_t p2, const uint32_t p3,
|
const uint32_t p1, const uint32_t p2, const uint32_t p3,
|
||||||
const uint_fast8_t r_div)
|
const uint_fast8_t r_div)
|
||||||
{
|
{
|
||||||
@ -137,7 +138,7 @@ void si5351c_configure_multisynth(const uint_fast8_t ms_number,
|
|||||||
(((p3 >> 16) & 0xF) << 4) | (((p2 >> 16) & 0xF) << 0),
|
(((p3 >> 16) & 0xF) << 4) | (((p2 >> 16) & 0xF) << 0),
|
||||||
(p2 >> 8) & 0xFF,
|
(p2 >> 8) & 0xFF,
|
||||||
(p2 >> 0) & 0xFF };
|
(p2 >> 0) & 0xFF };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JELLYBEAN
|
#ifdef JELLYBEAN
|
||||||
@ -186,15 +187,15 @@ void si5351c_configure_multisynth(const uint_fast8_t ms_number,
|
|||||||
* CLK5_SRC=3 (MS5 as input source)
|
* CLK5_SRC=3 (MS5 as input source)
|
||||||
* CLK5_IDRV=3 (8mA)
|
* CLK5_IDRV=3 (8mA)
|
||||||
*/
|
*/
|
||||||
void si5351c_configure_clock_control()
|
void si5351c_configure_clock_control(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 16, 0x4F, 0x4B, 0x4B, 0x4B, 0x0F, 0x4F, 0xC0, 0xC0 };
|
uint8_t data[] = { 16, 0x4F, 0x4B, 0x4B, 0x4B, 0x0F, 0x4F, 0xC0, 0xC0 };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined JAWBREAKER || defined HACKRF_ONE)
|
#if (defined JAWBREAKER || defined HACKRF_ONE)
|
||||||
void si5351c_configure_clock_control(const enum pll_sources source)
|
void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll_sources source)
|
||||||
{
|
{
|
||||||
uint8_t pll;
|
uint8_t pll;
|
||||||
|
|
||||||
@ -215,54 +216,54 @@ void si5351c_configure_clock_control(const enum pll_sources source)
|
|||||||
,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
|
,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
|
||||||
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA)
|
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA)
|
||||||
};
|
};
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Enable CLK outputs 0, 1, 2, 3, 4, 5, 7 only. */
|
/* Enable CLK outputs 0, 1, 2, 3, 4, 5, 7 only. */
|
||||||
void si5351c_enable_clock_outputs()
|
void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 3, 0x40 };
|
uint8_t data[] = { 3, 0x40 };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void si5351c_set_int_mode(const uint_fast8_t ms_number, const uint_fast8_t on){
|
void si5351c_set_int_mode(si5351c_driver_t* const drv, const uint_fast8_t ms_number, const uint_fast8_t on){
|
||||||
uint8_t data[] = {16, 0};
|
uint8_t data[] = {16, 0};
|
||||||
|
|
||||||
if(ms_number < 8){
|
if(ms_number < 8){
|
||||||
data[0] = 16 + ms_number;
|
data[0] = 16 + ms_number;
|
||||||
data[1] = si5351c_read_single(data[0]);
|
data[1] = si5351c_read_single(drv, data[0]);
|
||||||
|
|
||||||
if(on)
|
if(on)
|
||||||
data[1] |= SI5351C_CLK_INT_MODE;
|
data[1] |= SI5351C_CLK_INT_MODE;
|
||||||
else
|
else
|
||||||
data[1] &= ~(SI5351C_CLK_INT_MODE);
|
data[1] &= ~(SI5351C_CLK_INT_MODE);
|
||||||
|
|
||||||
si5351c_write(data, 2);
|
si5351c_write(drv, data, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void si5351c_set_clock_source(const enum pll_sources source)
|
void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source)
|
||||||
{
|
{
|
||||||
si5351c_configure_clock_control(source);
|
si5351c_configure_clock_control(drv, source);
|
||||||
active_clock_source = source;
|
active_clock_source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
void si5351c_activate_best_clock_source(void)
|
void si5351c_activate_best_clock_source(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t device_status = si5351c_read_single(0);
|
uint8_t device_status = si5351c_read_single(drv, 0);
|
||||||
|
|
||||||
if (device_status & SI5351C_LOS) {
|
if (device_status & SI5351C_LOS) {
|
||||||
/* CLKIN not detected */
|
/* CLKIN not detected */
|
||||||
if (active_clock_source == PLL_SOURCE_CLKIN) {
|
if (active_clock_source == PLL_SOURCE_CLKIN) {
|
||||||
si5351c_set_clock_source(PLL_SOURCE_XTAL);
|
si5351c_set_clock_source(drv, PLL_SOURCE_XTAL);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* CLKIN detected */
|
/* CLKIN detected */
|
||||||
if (active_clock_source == PLL_SOURCE_XTAL) {
|
if (active_clock_source == PLL_SOURCE_XTAL) {
|
||||||
si5351c_set_clock_source(PLL_SOURCE_CLKIN);
|
si5351c_set_clock_source(drv, PLL_SOURCE_CLKIN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,8 @@ extern "C"
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "si5351c_drv.h"
|
||||||
|
|
||||||
#define SI_INTDIV(x) (x*128-512)
|
#define SI_INTDIV(x) (x*128-512)
|
||||||
|
|
||||||
#define SI5351C_CLK_POWERDOWN (1<<7)
|
#define SI5351C_CLK_POWERDOWN (1<<7)
|
||||||
@ -61,22 +63,23 @@ enum pll_sources {
|
|||||||
PLL_SOURCE_CLKIN = 1,
|
PLL_SOURCE_CLKIN = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
void si5351c_disable_all_outputs();
|
void si5351c_disable_all_outputs(si5351c_driver_t* const drv);
|
||||||
void si5351c_disable_oeb_pin_control();
|
void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv);
|
||||||
void si5351c_power_down_all_clocks();
|
void si5351c_power_down_all_clocks(si5351c_driver_t* const drv);
|
||||||
void si5351c_set_crystal_configuration();
|
void si5351c_set_crystal_configuration(si5351c_driver_t* const drv);
|
||||||
void si5351c_enable_xo_and_ms_fanout();
|
void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv);
|
||||||
void si5351c_configure_pll_sources(void);
|
void si5351c_configure_pll_sources(si5351c_driver_t* const drv);
|
||||||
void si5351c_configure_pll_multisynth(void);
|
void si5351c_configure_pll_multisynth(si5351c_driver_t* const drv);
|
||||||
void si5351c_reset_pll(void);
|
void si5351c_reset_pll(si5351c_driver_t* const drv);
|
||||||
void si5351c_configure_multisynth(const uint_fast8_t ms_number,
|
void si5351c_configure_multisynth(si5351c_driver_t* const drv,
|
||||||
|
const uint_fast8_t ms_number,
|
||||||
const uint32_t p1, const uint32_t p2, const uint32_t p3,
|
const uint32_t p1, const uint32_t p2, const uint32_t p3,
|
||||||
const uint_fast8_t r_div);
|
const uint_fast8_t r_div);
|
||||||
void si5351c_configure_clock_control(const enum pll_sources source);
|
void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll_sources source);
|
||||||
void si5351c_enable_clock_outputs();
|
void si5351c_enable_clock_outputs(si5351c_driver_t* const drv);
|
||||||
void si5351c_set_int_mode(const uint_fast8_t ms_number, const uint_fast8_t on);
|
void si5351c_set_int_mode(si5351c_driver_t* const drv, const uint_fast8_t ms_number, const uint_fast8_t on);
|
||||||
void si5351c_set_clock_source(const enum pll_sources source);
|
void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source);
|
||||||
void si5351c_activate_best_clock_source(void);
|
void si5351c_activate_best_clock_source(si5351c_driver_t* const drv);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -29,28 +29,28 @@
|
|||||||
/* FIXME return i2c0 status from each function */
|
/* FIXME return i2c0 status from each function */
|
||||||
|
|
||||||
/* write to single register */
|
/* write to single register */
|
||||||
void si5351c_write_single(uint8_t reg, uint8_t val)
|
void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val)
|
||||||
{
|
{
|
||||||
i2c0_tx_start();
|
i2c0_tx_start();
|
||||||
i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE);
|
i2c0_tx_byte((drv->i2c_address << 1) | I2C_WRITE);
|
||||||
i2c0_tx_byte(reg);
|
i2c0_tx_byte(reg);
|
||||||
i2c0_tx_byte(val);
|
i2c0_tx_byte(val);
|
||||||
i2c0_stop();
|
i2c0_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read single register */
|
/* read single register */
|
||||||
uint8_t si5351c_read_single(uint8_t reg)
|
uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg)
|
||||||
{
|
{
|
||||||
uint8_t val;
|
uint8_t val;
|
||||||
|
|
||||||
/* set register address with write */
|
/* set register address with write */
|
||||||
i2c0_tx_start();
|
i2c0_tx_start();
|
||||||
i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE);
|
i2c0_tx_byte((drv->i2c_address << 1) | I2C_WRITE);
|
||||||
i2c0_tx_byte(reg);
|
i2c0_tx_byte(reg);
|
||||||
|
|
||||||
/* read the value */
|
/* read the value */
|
||||||
i2c0_tx_start();
|
i2c0_tx_start();
|
||||||
i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_READ);
|
i2c0_tx_byte((drv->i2c_address << 1) | I2C_READ);
|
||||||
val = i2c0_rx_byte();
|
val = i2c0_rx_byte();
|
||||||
i2c0_stop();
|
i2c0_stop();
|
||||||
|
|
||||||
@ -61,12 +61,12 @@ uint8_t si5351c_read_single(uint8_t reg)
|
|||||||
* Write to one or more contiguous registers. data[0] should be the first
|
* Write to one or more contiguous registers. data[0] should be the first
|
||||||
* register number, one or more values follow.
|
* register number, one or more values follow.
|
||||||
*/
|
*/
|
||||||
void si5351c_write(uint8_t* const data, const uint_fast8_t data_count)
|
void si5351c_write(si5351c_driver_t* const drv, uint8_t* const data, const uint_fast8_t data_count)
|
||||||
{
|
{
|
||||||
uint_fast8_t i;
|
uint_fast8_t i;
|
||||||
|
|
||||||
i2c0_tx_start();
|
i2c0_tx_start();
|
||||||
i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE);
|
i2c0_tx_byte((drv->i2c_address << 1) | I2C_WRITE);
|
||||||
|
|
||||||
for (i = 0; i < data_count; i++)
|
for (i = 0; i < data_count; i++)
|
||||||
i2c0_tx_byte(data[i]);
|
i2c0_tx_byte(data[i]);
|
||||||
|
@ -30,9 +30,13 @@ extern "C"
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void si5351c_write_single(uint8_t reg, uint8_t val);
|
typedef struct {
|
||||||
uint8_t si5351c_read_single(uint8_t reg);
|
uint8_t i2c_address;
|
||||||
void si5351c_write(uint8_t* const data, const uint_fast8_t data_count);
|
} si5351c_driver_t;
|
||||||
|
|
||||||
|
void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val);
|
||||||
|
uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg);
|
||||||
|
void si5351c_write(si5351c_driver_t* const drv, uint8_t* const data, const uint_fast8_t data_count);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( _transceiver_mode != TRANSCEIVER_MODE_OFF ) {
|
if( _transceiver_mode != TRANSCEIVER_MODE_OFF ) {
|
||||||
si5351c_activate_best_clock_source();
|
si5351c_activate_best_clock_source(&clock_gen);
|
||||||
baseband_streaming_enable();
|
baseband_streaming_enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,9 @@
|
|||||||
|
|
||||||
#include "usb_api_register.h"
|
#include "usb_api_register.h"
|
||||||
|
|
||||||
|
#include <hackrf_core.h>
|
||||||
#include <usb_queue.h>
|
#include <usb_queue.h>
|
||||||
#include <max2837.h>
|
#include <max2837.h>
|
||||||
#include <si5351c_drv.h>
|
|
||||||
#include <rffc5071.h>
|
#include <rffc5071.h>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@ -75,7 +75,7 @@ usb_request_status_t usb_vendor_request_write_si5351c(
|
|||||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||||
if( endpoint->setup.index < 256 ) {
|
if( endpoint->setup.index < 256 ) {
|
||||||
if( endpoint->setup.value < 256 ) {
|
if( endpoint->setup.value < 256 ) {
|
||||||
si5351c_write_single(endpoint->setup.index, endpoint->setup.value);
|
si5351c_write_single(&clock_gen, endpoint->setup.index, endpoint->setup.value);
|
||||||
usb_transfer_schedule_ack(endpoint->in);
|
usb_transfer_schedule_ack(endpoint->in);
|
||||||
return USB_REQUEST_STATUS_OK;
|
return USB_REQUEST_STATUS_OK;
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ usb_request_status_t usb_vendor_request_read_si5351c(
|
|||||||
) {
|
) {
|
||||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||||
if( endpoint->setup.index < 256 ) {
|
if( endpoint->setup.index < 256 ) {
|
||||||
const uint8_t value = si5351c_read_single(endpoint->setup.index);
|
const uint8_t value = si5351c_read_single(&clock_gen, endpoint->setup.index);
|
||||||
endpoint->buffer[0] = value;
|
endpoint->buffer[0] = value;
|
||||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
Reference in New Issue
Block a user