Permalink
Browse files

activated CLKOUT (always on) and CLKIN (automatically used when detec…

…ted)
  • Loading branch information...
mossmann committed Mar 15, 2014
1 parent 0fab315 commit ca04d7c04ba42750de16e990caf5dedb6fab770e
Showing with 69 additions and 19 deletions.
  1. +4 −8 firmware/common/hackrf_core.c
  2. +47 −9 firmware/common/si5351c.c
  3. +11 −2 firmware/common/si5351c.h
  4. +7 −0 firmware/hackrf_usb/hackrf_usb.c
@@ -136,9 +136,6 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
si5351c_configure_multisynth(2, 0, 0, 0, 0);//p1 doesn't matter

/* MS0/CLK3 is the source for the external clock output. */
//si5351c_configure_multisynth(3, p1, 0, 1, 0); // no clk out

return true;
}

@@ -248,9 +245,6 @@ bool sample_rate_set(const uint32_t sample_rate_hz) {
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
si5351c_configure_multisynth(2, p1, 0, 1, 0);//p1 doesn't matter

/* MS0/CLK3 is the source for the external clock output. */
//si5351c_configure_multisynth(3, p1, 0, 1, 0); // no clk out

return true;
#endif
}
@@ -274,8 +268,7 @@ void cpu_clock_init(void)
si5351c_power_down_all_clocks();
si5351c_set_crystal_configuration();
si5351c_enable_xo_and_ms_fanout();
si5351c_configure_pll_sources_for_xtal();
si5351c_configure_pll1_multisynth();
si5351c_set_clock_source(PLL_SOURCE_XTAL);

#ifdef JELLYBEAN
/*
@@ -313,6 +306,9 @@ void cpu_clock_init(void)
* CLK7 -> LPC4330 (but LPC4330 starts up on its own crystal)
*/

/* MS3/CLK3 is the source for the external clock output. */
si5351c_configure_multisynth(3, 80*128-512, 0, 1, 0); /* 800/80 = 10MHz */

/* MS4/CLK4 is the source for the RFFC5071 mixer. */
si5351c_configure_multisynth(4, 16*128-512, 0, 1, 0); /* 800/16 = 50MHz */

@@ -23,6 +23,8 @@
#include "si5351c.h"
#include <libopencm3/lpc43xx/i2c.h>

enum pll_sources active_clock_source;

/* FIXME return i2c0 status from each function */

/* write to single register */
@@ -117,7 +119,7 @@ void si5351c_set_crystal_configuration()
*/
void si5351c_enable_xo_and_ms_fanout()
{
uint8_t data[] = { 187, 0x50 };
uint8_t data[] = { 187, 0xD0 };
si5351c_write(data, sizeof(data));
}

@@ -127,18 +129,29 @@ void si5351c_enable_xo_and_ms_fanout()
* PLLB_SRC=0 (XTAL input)
* PLLA_SRC=0 (XTAL input)
*/
void si5351c_configure_pll_sources_for_xtal()
void si5351c_configure_pll_sources(const enum pll_sources source)
{
uint8_t data[] = { 15, 0x00 };

if (source == PLL_SOURCE_CLKIN) {
data[1] = 0x0C;
}

si5351c_write(data, sizeof(data));
}

/* MultiSynth NA (PLL1) */
void si5351c_configure_pll1_multisynth()
void si5351c_configure_pll1_multisynth(const enum pll_sources source)
{
//init plla and pllb to (0x0e00+512)/128*25mhz xtal = 800mhz -> int mode
uint8_t data[] = { 26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00 };
si5351c_write(data, sizeof(data));
//init plla to (0x0e00+512)/128*25mhz xtal = 800mhz -> int mode
uint8_t data[] = { 26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00 };

if (source == PLL_SOURCE_CLKIN) {
/* 10 MHz input on CLKIN instead of 25 MHz XTAL */
data[4] = 0x26;
}

si5351c_write(data, sizeof(data));
//~ data[0] =34;// pllb
//~ si5351c_write(data, sizeof(data));
}
@@ -233,7 +246,7 @@ void si5351c_configure_clock_control()
,SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA)
,SI5351C_CLK_POWERDOWN /*not connected, clock out*/
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA)
,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
@@ -243,10 +256,10 @@ void si5351c_configure_clock_control()
}
#endif

/* Enable CLK outputs 0, 1, 2, 4, 5, 7 only. */
/* Enable CLK outputs 0, 1, 2, 3, 4, 5, 7 only. */
void si5351c_enable_clock_outputs()
{
uint8_t data[] = { 3, 0x48 };
uint8_t data[] = { 3, 0x40 };
si5351c_write(data, sizeof(data));
}

@@ -267,3 +280,28 @@ void si5351c_configure_clock_control()
}

}

void si5351c_set_clock_source(const enum pll_sources source)
{
si5351c_configure_pll_sources(source);
si5351c_configure_pll1_multisynth(source);

active_clock_source = source;
}

void si5351c_activate_best_clock_source(void)
{
uint8_t device_status = si5351c_read_single(0);

if (device_status & SI5351C_LOS) {
/* CLKIN not detected */
if (active_clock_source == PLL_SOURCE_CLKIN) {
si5351c_set_clock_source(PLL_SOURCE_XTAL);
}
} else {
/* CLKIN detected */
if (active_clock_source == PLL_SOURCE_XTAL) {
si5351c_set_clock_source(PLL_SOURCE_CLKIN);
}
}
}
@@ -55,13 +55,20 @@ extern "C"
#define SI5351C_CLK_IDRV_6MA 2
#define SI5351C_CLK_IDRV_8MA 3

#define SI5351C_LOS (1<<4)

enum pll_sources {
PLL_SOURCE_XTAL = 0,
PLL_SOURCE_CLKIN = 1,
};

void si5351c_disable_all_outputs();
void si5351c_disable_oeb_pin_control();
void si5351c_power_down_all_clocks();
void si5351c_set_crystal_configuration();
void si5351c_enable_xo_and_ms_fanout();
void si5351c_configure_pll_sources_for_xtal();
void si5351c_configure_pll1_multisynth();
void si5351c_configure_pll_sources(const enum pll_sources source);
void si5351c_configure_pll1_multisynth(const enum pll_sources source);
void si5351c_configure_multisynth(const uint_fast8_t ms_number,
const uint32_t p1, const uint32_t p2, const uint32_t p3,
const uint_fast8_t r_div);
@@ -72,6 +79,8 @@ void si5351c_set_int_mode(const uint_fast8_t ms_number, const uint_fast8_t on);
void si5351c_write_single(uint8_t reg, uint8_t val);
uint8_t si5351c_read_single(uint8_t reg);
void si5351c_write(uint8_t* const data, const uint_fast8_t data_count);
void si5351c_set_clock_source(const enum pll_sources source);
void si5351c_activate_best_clock_source(void);

#ifdef __cplusplus
}
@@ -43,6 +43,7 @@
#include "rf_path.h"
#include "sgpio_isr.h"
#include "usb_bulk_buffer.h"
#include "si5351c.h"

static volatile transceiver_mode_t _transceiver_mode = TRANSCEIVER_MODE_OFF;

@@ -210,12 +211,18 @@ int main(void) {

rf_path_init();

uint16_t periodic_event_counter = 0;

unsigned int phase = 0;
while(true) {
// Check whether we need to initiate a CPLD update
if (start_cpld_update)
cpld_update();

if (++periodic_event_counter == 0) {
si5351c_activate_best_clock_source();
}

// Set up IN transfer of buffer 0.
if ( usb_bulk_buffer_offset >= 16384
&& phase == 1

0 comments on commit ca04d7c

Please sign in to comment.