parent
a5009e7c69
commit
fb25e9a1b8
|
@ -7,20 +7,25 @@
|
||||||
|
|
||||||
static const uint8_t SI5351_ADDRESS = 96;
|
static const uint8_t SI5351_ADDRESS = 96;
|
||||||
|
|
||||||
enum si5351_param_base {
|
enum si5351_pll {
|
||||||
PLL_A = 26,
|
SI5351_PLLA = 0,
|
||||||
PLL_B = 34,
|
SI5351_PLLB = 1,
|
||||||
MULTISYNTH_0 = 42,
|
|
||||||
MULTOSYNTH_1 = 50,
|
|
||||||
MULTISYNTH_2 = 58
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const uint8_t SI5351_PLL_BASE_ADDR[] = {26, 34};
|
||||||
|
|
||||||
|
enum si5351_multisynth {
|
||||||
|
SI5351_MS0 = 0,
|
||||||
|
SI5351_MS1 = 1,
|
||||||
|
SI5351_MS2 = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t SI5351_MULTISYNTH_BASE[] = {42, 50, 58};
|
||||||
|
static const uint8_t SI5351_CLK_CTRL[] = {16, 17, 18};
|
||||||
|
|
||||||
enum si5351_reg {
|
enum si5351_reg {
|
||||||
CLK_ENABLE_CONTROL = 3,
|
CLK_ENABLE_CONTROL = 3,
|
||||||
PLLX_SRC = 15,
|
PLLX_SRC = 15,
|
||||||
CLK0_CONTROL = 16,
|
|
||||||
CLK1_CONTROL = 17,
|
|
||||||
CLK2_CONTROL = 18,
|
|
||||||
PLL_RESET = 177,
|
PLL_RESET = 177,
|
||||||
XTAL_LOAD_CAP = 183
|
XTAL_LOAD_CAP = 183
|
||||||
};
|
};
|
||||||
|
@ -33,8 +38,11 @@ static inline uint8_t si5351_write8(uint8_t reg, uint8_t value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void si5351_init(uint32_t freq_xtal, uint32_t freq_a, uint32_t freq_b);
|
void si5351_init(uint32_t freq_xtal, uint32_t freq_a, uint32_t freq_b);
|
||||||
void si5351_set_freq(enum si5351_param_base base, uint32_t freq);
|
void si5351_ms_enable_output(enum si5351_multisynth synth);
|
||||||
uint8_t si5351_write_params(enum si5351_param_base base, uint32_t p1, uint32_t p2, uint32_t p3);
|
void si5351_ms_disable_output(enum si5351_multisynth synth);
|
||||||
|
void si5351_ms_set_source(enum si5351_multisynth synth, enum si5351_pll pll);
|
||||||
|
void si5351_ms_set_freq(enum si5351_multisynth synth, uint32_t freq);
|
||||||
|
uint8_t si5351_write_params(uint8_t base, uint32_t p1, uint32_t p2, uint32_t p3);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,10 @@ int main(void) {
|
||||||
|
|
||||||
twi_init();
|
twi_init();
|
||||||
|
|
||||||
si5351_init(25000000, 400000000, 400000000);
|
si5351_init(25000000, 400000000, 300000000);
|
||||||
si5351_set_freq(MULTISYNTH_0, 7165000);
|
si5351_ms_set_source(SI5351_MS0, SI5351_PLLB);
|
||||||
|
si5351_ms_set_freq(SI5351_MS0, 7165000);
|
||||||
|
si5351_ms_enable_output(SI5351_MS0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,62 +1,79 @@
|
||||||
#include "si5351.h"
|
#include "si5351.h"
|
||||||
|
|
||||||
uint32_t si5351_freq_a;
|
uint32_t si5351_pll_freq[2];
|
||||||
uint32_t si5351_freq_b;
|
uint8_t si5351_multisynth_pll[3];
|
||||||
|
uint8_t si5351_outputs;
|
||||||
|
|
||||||
void si5351_init(uint32_t freq_xtal, uint32_t freq_a, uint32_t freq_b) {
|
void si5351_init(uint32_t freq_xtal, uint32_t freq_a, uint32_t freq_b) {
|
||||||
si5351_write8(CLK_ENABLE_CONTROL, 0x00); // Enable all outputs
|
si5351_pll_freq[SI5351_PLLA] = freq_a;
|
||||||
|
si5351_pll_freq[SI5351_PLLB] = freq_b;
|
||||||
|
|
||||||
|
si5351_outputs = 0xFF;
|
||||||
|
si5351_write8(CLK_ENABLE_CONTROL, si5351_outputs); // Disable all outputs
|
||||||
si5351_write8(XTAL_LOAD_CAP, 0xD2); //crystal load capacitor = 10pF
|
si5351_write8(XTAL_LOAD_CAP, 0xD2); //crystal load capacitor = 10pF
|
||||||
|
|
||||||
si5351_write8(CLK0_CONTROL, 0x0F); // PLLA to CLK0, 8 mA output
|
|
||||||
si5351_write8(PLL_RESET, 0xA0); // Reset both PLLs
|
si5351_write8(PLL_RESET, 0xA0); // Reset both PLLs
|
||||||
|
|
||||||
si5351_freq_a = freq_a;
|
for(uint8_t i = 0; i < 3; i++) {
|
||||||
si5351_freq_b = freq_b;
|
si5351_multisynth_pll[i] = 0; // == SI5351_PLLA
|
||||||
|
si5351_write8(SI5351_CLK_CTRL[i], 0x0F); // MSi as Source, PLLA to MSi, 8 mA output
|
||||||
|
}
|
||||||
|
|
||||||
double fdiv = (double) si5351_freq_a / (double) freq_xtal;
|
for(uint8_t i = 0; i < 2; i++) {
|
||||||
|
double fdiv = (double) si5351_pll_freq[i] / (double) freq_xtal;
|
||||||
|
|
||||||
|
//TODO: Find better way to determine c and b
|
||||||
|
uint32_t c = 0x0FFFFF;
|
||||||
|
uint32_t a = (uint32_t) fdiv;
|
||||||
|
//TODO: Use modulo
|
||||||
|
double rm = fdiv - a;
|
||||||
|
uint32_t b = rm * c;
|
||||||
|
uint32_t p1 = 128 * a + (128 * b / c) - 512;
|
||||||
|
uint32_t p2 = 128 * b - c * (128 * b / c);
|
||||||
|
uint32_t p3 = c;
|
||||||
|
si5351_write_params(SI5351_PLL_BASE_ADDR[i], p1, p2, p3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void si5351_ms_enable_output(enum si5351_multisynth synth) {
|
||||||
|
si5351_outputs &= ~(1 << synth);
|
||||||
|
si5351_write8(CLK_ENABLE_CONTROL, si5351_outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void si5351_ms_disable_output(enum si5351_multisynth synth) {
|
||||||
|
si5351_outputs |= (1 << synth);
|
||||||
|
si5351_write8(CLK_ENABLE_CONTROL, si5351_outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void si5351_ms_set_source(enum si5351_multisynth synth, enum si5351_pll pll) {
|
||||||
|
uint8_t value = 0x0F; // MS as Source, PLLA to MS, 8 mA output
|
||||||
|
si5351_multisynth_pll[synth] = 0; // == PLLA
|
||||||
|
|
||||||
|
if(pll == SI5351_PLLB) {
|
||||||
|
value |= (1 << 5); // Bit 5 set PLLB to MS
|
||||||
|
si5351_multisynth_pll[synth] = 1; // == PLLB
|
||||||
|
}
|
||||||
|
si5351_write8(SI5351_CLK_CTRL[synth], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void si5351_ms_set_freq(enum si5351_multisynth synth, uint32_t freq) {
|
||||||
|
double fdiv = (double) si5351_pll_freq[si5351_multisynth_pll[synth]] / (double) freq;
|
||||||
|
|
||||||
//TODO: Find better way to determine c and b
|
//TODO: Find better way to determine c and b
|
||||||
uint32_t c = 0x0FFFFF;
|
uint32_t c = 0x0FFFFF;
|
||||||
uint32_t a = (uint32_t) fdiv;
|
uint32_t a = (uint32_t) fdiv;
|
||||||
|
//TODO: Use modulo
|
||||||
double rm = fdiv - a;
|
double rm = fdiv - a;
|
||||||
uint32_t b = rm * c;
|
uint32_t b = rm * c;
|
||||||
uint32_t p1 = 128 * a + (128 * b / c) - 512;
|
uint32_t p1 = 128 * a + (128 * b / c) - 512;
|
||||||
uint32_t p2 = 128 * b - c * (128 * b / c);
|
uint32_t p2 = 128 * b - c * (128 * b / c);
|
||||||
uint32_t p3 = c;
|
uint32_t p3 = c;
|
||||||
si5351_write_params(PLL_A, p1, p2, p3);
|
si5351_write_params(SI5351_MULTISYNTH_BASE[synth], p1, p2, p3);
|
||||||
|
|
||||||
|
|
||||||
fdiv = (double) freq_xtal / (double) si5351_freq_a;
|
|
||||||
|
|
||||||
//TODO: Find better way to determine c and b
|
|
||||||
c = 0x0FFFFF;
|
|
||||||
a = (uint32_t) fdiv;
|
|
||||||
rm = fdiv - a;
|
|
||||||
b = rm * c;
|
|
||||||
p1 = 128 * a + (128 * b / c) - 512;
|
|
||||||
p2 = 128 * b - c * (128 * b / c);
|
|
||||||
p3 = c;
|
|
||||||
si5351_write_params(PLL_B, p1, p2, p3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void si5351_set_freq(enum si5351_param_base base, uint32_t freq) {
|
|
||||||
//TODO: Pick freq by clock source
|
|
||||||
double fdiv = (double) si5351_freq_a / (double) freq;
|
|
||||||
|
|
||||||
//TODO: Find better way to determine c and b
|
|
||||||
uint32_t c = 0x0FFFFF;
|
|
||||||
uint32_t a = (uint32_t) fdiv;
|
|
||||||
double rm = fdiv - a;
|
|
||||||
uint32_t b = rm * c;
|
|
||||||
uint32_t p1 = 128 * a + (128 * b / c) - 512;
|
|
||||||
uint32_t p2 = 128 * b - c * (128 * b / c);
|
|
||||||
uint32_t p3 = c;
|
|
||||||
si5351_write_params(base, p1, p2, p3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t si5351_write_params(enum si5351_param_base base, uint32_t p1, uint32_t p2, uint32_t p3) {
|
uint8_t si5351_write_params(uint8_t base, uint32_t p1, uint32_t p2, uint32_t p3) {
|
||||||
uint8_t data[9] = {
|
uint8_t data[9] = {
|
||||||
base,
|
base,
|
||||||
(p3 & 0x00FF00) >> 8,
|
(p3 & 0x00FF00) >> 8,
|
||||||
|
|
Loading…
Reference in New Issue