Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions firmware/common/hackrf_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program)
}

/* Reset PLL to synchronize output clock phase. */
si5351c_reset_pll(&clock_gen);
si5351c_reset_pll(&clock_gen, SI5351C_PLL_A);
#endif

if (streaming) {
Expand Down Expand Up @@ -622,7 +622,7 @@ void clock_gen_init(void)
si5351c_configure_clock_control(&clock_gen);
si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL);
// soft reset
si5351c_reset_pll(&clock_gen);
si5351c_reset_pll(&clock_gen, SI5351C_PLL_BOTH);
si5351c_enable_clock_outputs(&clock_gen);
}

Expand Down
77 changes: 58 additions & 19 deletions firmware/common/si5351c.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
static enum pll_sources active_clock_source = PLL_SOURCE_UNINITIALIZED;
/* External clock output default is deactivated as it creates noise */
static bool clkout_enabled = false;
static uint8_t outputs_disabled = 0xff;

/* write to single register */
void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val)
Expand Down Expand Up @@ -73,7 +74,30 @@ void si5351c_write(
/* Disable all CLKx outputs. */
void si5351c_disable_all_outputs(si5351c_driver_t* const drv)
{
uint8_t data[] = {3, 0xFF};
outputs_disabled = 0xff;
uint8_t data[] = {3, outputs_disabled};
si5351c_write(drv, data, sizeof(data));
}

/* Disable all CLKx outputs using selected PLL. */
void si5351c_disable_pll_outputs(si5351c_driver_t* const drv, si5351c_pll_t pll)
{
/*
* Bitmask defines outputs using PLL B. Other outputs are assumed to
* use PLL A.
*/
uint8_t pllb_outputs = 0x00;
if (detected_platform() == BOARD_ID_PRALINE) {
pllb_outputs = 0x30;
}

if (pll & SI5351C_PLL_A) {
outputs_disabled |= ~pllb_outputs;
}
if (pll & SI5351C_PLL_B) {
outputs_disabled |= pllb_outputs;
}
uint8_t data[] = {3, outputs_disabled};
si5351c_write(drv, data, sizeof(data));
}

Expand Down Expand Up @@ -156,11 +180,19 @@ void si5351c_configure_pll_multisynth(
si5351c_write(drv, data, sizeof(data));
}

void si5351c_reset_pll(si5351c_driver_t* const drv)
void si5351c_reset_pll(si5351c_driver_t* const drv, si5351c_pll_t pll)
{
si5351c_disable_all_outputs(drv);
/* reset PLLA and PLLB */
uint8_t data[] = {177, 0xA0};
uint8_t value = 0;

if (pll & SI5351C_PLL_A) {
value |= 0x20;
}
if (pll & SI5351C_PLL_B) {
value |= 0x80;
}

si5351c_disable_pll_outputs(drv, pll);
uint8_t data[] = {177, value};
si5351c_write(drv, data, sizeof(data));
delay_us_at_mhz(2000, 204);
si5351c_enable_clock_outputs(drv);
Expand Down Expand Up @@ -202,11 +234,10 @@ void si5351c_configure_multisynth(

void si5351c_configure_clock_control(si5351c_driver_t* const drv)
{
const uint8_t pll = SI5351C_CLK_PLL_SRC_A;
uint8_t clkout_ctrl;

if (clkout_enabled) {
clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA);
} else {
Expand All @@ -217,20 +248,20 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv)
/* External clock output is kept in current state */
uint8_t data[] = {
16,
SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) |
SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
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_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA) | SI5351C_CLK_INV,
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA),
clkout_ctrl,
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA) | SI5351C_CLK_INV,
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA),
SI5351C_CLK_POWERDOWN |
Expand All @@ -239,10 +270,10 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv)
SI5351C_CLK_INT_MODE /* not connected, but: PLL B int mode */
};
if (detected_platform() == BOARD_ID_HACKRF1_R9) {
data[1] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC_A |
data[1] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA);
data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC_A |
data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA);
data[3] = clkout_ctrl;
Expand All @@ -252,20 +283,27 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv)
}
#ifdef PRALINE
/* CLK0: AFE_CLK */
data[1] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) |
data[1] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA);
/* CLK1: SCT_CLK and FPGA_CLK */
data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) |
data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA);
/* CLK3: CLKOUT */
clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA);
/* CLK4: XCVR_CLK */
data[5] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
data[5] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA) | SI5351C_CLK_INV;
data[6] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA);
if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) {
/* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */
data[3] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) |
data[3] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA);
} else {
Expand Down Expand Up @@ -317,6 +355,7 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
SI5351C_CLK_DISABLE(clkout);
uint8_t data[] = {SI5351C_REG_OUTPUT_EN, value};
si5351c_write(drv, data, sizeof(data));
outputs_disabled = value;

#if defined(HACKRF_ONE)
if (detected_platform() == BOARD_ID_HACKRF1_R9) {
Expand Down Expand Up @@ -375,7 +414,7 @@ void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_source
}
si5351c_configure_pll_multisynth(drv, source);
active_clock_source = source;
si5351c_reset_pll(drv);
si5351c_reset_pll(drv, SI5351C_PLL_BOTH);
}

bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv)
Expand Down
14 changes: 9 additions & 5 deletions firmware/common/si5351c.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@ extern "C" {
#define SI5351C_CLK_INT_MODE (1 << 6)
#define SI5351C_CLK_FRAC_MODE (0 << 6)

#define SI5351C_CLK_PLL_SRC(x) (x << 5)
#define SI5351C_CLK_PLL_SRC_A 0
#define SI5351C_CLK_PLL_SRC_B 1

#define SI5351C_CLK_INV (1 << 4)

#define SI5351C_CLK_SRC(x) (x << 2)
Expand All @@ -60,6 +56,14 @@ extern "C" {
#define SI5351C_LOS (1 << 4)
#define SI5351C_REVID 0x03

typedef enum {
SI5351C_PLL_A = 1,
SI5351C_PLL_B = 2,
SI5351C_PLL_BOTH = 3,
} si5351c_pll_t;

#define SI5351C_CLK_PLL_SRC(x) ((x & SI5351C_PLL_B) << 4)

enum pll_sources {
PLL_SOURCE_UNINITIALIZED = -1,
PLL_SOURCE_XTAL = 0,
Expand All @@ -82,7 +86,7 @@ void si5351c_configure_pll_sources(
void si5351c_configure_pll_multisynth(
si5351c_driver_t* const drv,
const enum pll_sources source);
void si5351c_reset_pll(si5351c_driver_t* const drv);
void si5351c_reset_pll(si5351c_driver_t* const drv, si5351c_pll_t pll);
void si5351c_configure_multisynth(
si5351c_driver_t* const drv,
const uint_fast8_t ms_number,
Expand Down
Loading