From f0f8d4f1d8c3281eb18af1bc6626c0b945a602dc Mon Sep 17 00:00:00 2001 From: LongHairedHacker Date: Wed, 20 Jun 2018 01:22:31 +0200 Subject: [PATCH] Some output, wrong frequency --- firmware/Makefile | 4 +-- firmware/include/si5351.h | 31 ++++++++++++++--- firmware/main.c | 9 ++--- firmware/si5351.c | 72 +++++++++++++++++++++++++++++++++++++++ firmware/test.c | 43 +++++++++++++++++++++++ 5 files changed, 146 insertions(+), 13 deletions(-) create mode 100644 firmware/si5351.c create mode 100644 firmware/test.c diff --git a/firmware/Makefile b/firmware/Makefile index 30a03ce..26b86e4 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -4,8 +4,8 @@ ISPPORT ?= /dev/kaboard VERSION = 0.1 -HEADERS = include/twi.h -SRC = main.c twi.c +HEADERS = include/twi.h include/si5351.h +SRC = main.c twi.c si5351.c TARGET = cube-kl OBJDIR = bin diff --git a/firmware/include/si5351.h b/firmware/include/si5351.h index 54edb89..6a0eb1a 100644 --- a/firmware/include/si5351.h +++ b/firmware/include/si5351.h @@ -5,16 +5,37 @@ #include "twi.h" -const uint8_t SI5351_ADDRESS = 96; +static const uint8_t SI5351_ADDRESS = 96; + +enum si5351_param_base { + PLL_A = 26, + PLL_B = 34, + MULTISYNTH_0 = 42, + MULTOSYNTH_1 = 50, + MULTISYNTH_2 = 58 +}; + +enum si5351_reg { + CLK_ENABLE_CONTROL = 3, + PLLX_SRC = 15, + CLK0_CONTROL = 16, + CLK1_CONTROL = 17, + CLK2_CONTROL = 18, + PLL_RESET = 177, + XTAL_LOAD_CAP = 183 +}; + + static inline uint8_t si5351_write8(uint8_t reg, uint8_t value) { uint8_t data[3] = {reg, value}; return twi_write(SI5351_ADDRESS, data, 2); } -static inline uint8_t si5351_write16(uint8_t reg, uint16_t value) { - uint8_t data[3] = {reg, value & 0xFF, (value & 0xFF00) >> 8}; - return twi_write(SI5351_ADDRESS, data, 3); -} +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); +uint8_t si5351_write_params(enum si5351_param_base base, uint32_t p1, uint32_t p2, uint32_t p3); + + #endif diff --git a/firmware/main.c b/firmware/main.c index 8d480fc..1ccf974 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -8,13 +8,10 @@ int main(void) { twi_init(); - // Disable outputs - si5351_write8(3, 0xFF); + si5351_init(25000000, 900000000, 900000000); + si5351_set_freq(MULTISYNTH_0, 10000000); + - // Powerdown output drivers - si5351_write8(16, 0x80); - si5351_write8(17, 0x80); - si5351_write8(18, 0x80); while(1); } diff --git a/firmware/si5351.c b/firmware/si5351.c new file mode 100644 index 0000000..a65ac3f --- /dev/null +++ b/firmware/si5351.c @@ -0,0 +1,72 @@ +#include "si5351.h" + +uint32_t si5351_freq_a; +uint32_t si5351_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_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_freq_a = freq_a; + si5351_freq_b = freq_b; + + double fdiv = (double) si5351_freq_a / (double) freq_xtal; + + //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(PLL_A, 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) freq / (double) si5351_freq_a; + + //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 data[9] = { + base, + (p3 & 0x00FF00) >> 8, + p3 & 0x0000FF, + (p1 & 0x030000) >> 16, + (p1 & 0x00FF00) >> 8, + p1 & 0x0000FF, + ((p3 & 0x0F0000) >> 12) | ((p2 & 0x0F0000) >> 16), + (p2 & 0x00FF00) >> 8, + p2 & 0x0000FF + }; + return twi_write(SI5351_ADDRESS, data, 9); +} diff --git a/firmware/test.c b/firmware/test.c new file mode 100644 index 0000000..96d6846 --- /dev/null +++ b/firmware/test.c @@ -0,0 +1,43 @@ +#include +#include + +int main(void) { + uint32_t si5351_freq_a = 400000000; + uint32_t freq_xtal = 25000000; + uint32_t out_freq = 400000000; + + + double fdiv = (double) si5351_freq_a / (double) freq_xtal; + + //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; + + printf("%u + %u / %u\n", a, b, c); + + uint32_t p1 = 128 * a + (128 * b / c) - 512; + uint32_t p2 = 128 * b - c * (128 * b / c); + uint32_t p3 = c; + + printf("%u %u %u\n", p1, p2, p3); + + fdiv = (double) out_freq / (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; + + printf("%u + %u / %u\n", a, b, c); + + p1 = 128 * a + (128 * b / c) - 512; + p2 = 128 * b - c * (128 * b / c); + p3 = c; + + printf("%u %u %u\n", p1, p2, p3); + + return 0; +}