From 2bc9b77ac4ca2ef9538ecd4aef1e3b60b88029c1 Mon Sep 17 00:00:00 2001 From: LongHairedHacker Date: Sun, 8 Jul 2018 02:06:25 +0200 Subject: [PATCH] Implemented wspr test --- firmware/Makefile | 4 +-- firmware/include/si5351.h | 11 +++++++- firmware/include/wspr.h | 45 +++++++++++++++++++++++++++++++++ firmware/main.c | 15 ++++++----- firmware/scripts/wspr_params.py | 10 +++++--- firmware/si5351.c | 39 +++++++++++++++------------- firmware/wspr.c | 14 ++++++++++ 7 files changed, 107 insertions(+), 31 deletions(-) create mode 100644 firmware/include/wspr.h create mode 100644 firmware/wspr.c diff --git a/firmware/Makefile b/firmware/Makefile index 26b86e4..ee09faf 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -4,8 +4,8 @@ ISPPORT ?= /dev/kaboard VERSION = 0.1 -HEADERS = include/twi.h include/si5351.h -SRC = main.c twi.c si5351.c +HEADERS = include/twi.h include/si5351.h include/wspr.h +SRC = main.c twi.c si5351.c wspr.c TARGET = cube-kl OBJDIR = bin diff --git a/firmware/include/si5351.h b/firmware/include/si5351.h index 4f8b796..6404d28 100644 --- a/firmware/include/si5351.h +++ b/firmware/include/si5351.h @@ -31,6 +31,11 @@ enum si5351_reg { }; +struct si5351_params { + uint32_t p1; + uint32_t p2; + uint32_t p3; +}; static inline uint8_t si5351_write8(uint8_t reg, uint8_t value) { uint8_t data[3] = {reg, value}; @@ -42,8 +47,12 @@ void si5351_ms_enable_output(enum si5351_multisynth synth); 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); +uint8_t si5351_write_params(uint8_t base, struct si5351_params params); + +static inline void si5351_ms_write_params(enum si5351_multisynth synth, struct si5351_params params) { + si5351_write_params(SI5351_MULTISYNTH_BASE[synth], params); +} #endif diff --git a/firmware/include/wspr.h b/firmware/include/wspr.h new file mode 100644 index 0000000..1f6fb1c --- /dev/null +++ b/firmware/include/wspr.h @@ -0,0 +1,45 @@ +#ifndef __WSPR_H__ +#define __WSPR_H__ __WSPR_H__ + + +#include + +#include "si5351.h" + + +// For PLL with 800MHz +static const struct si5351_params WSPR_SYMBOLS[4] = { + // 7040100.000000: 113 + 44687 / 70401 + // actual: 7040100.000000 + {14033, 17455, 70401}, + // 7040101.464844: 113 + 447801 / 705503 + // actual: 7040101.464844 + {14033, 172785, 705503}, + // 7040102.929688: 113 + 38515 / 60682 + // actual: 7040102.929688 + {14033, 14678, 60682}, + // 7040104.394531: 113 + 123233 / 194166 + // actual: 7040104.394531 + {14033, 46378, 194166}, +}; + + +static const uint8_t WSPR_LENGTH = 162; +static const uint16_t WSPR_PERIOD = 683; + +// DL1SSK at JN39we +static uint8_t default_wspr_msg[162] = { + 1, 1, 0, 0, 2, 0, 0, 2, 1, 0, 0, 0, 1, 3, 3, 2, 2, 2, 3, 2, 0, 1, 0, 3, 1, 1, 1, 0, 2, + 2, 0, 2, 2, 0, 3, 0, 0, 1, 0, 3, 2, 0, 0, 0, 0, 0, 3, 0, 1, 1, 0, 0, 3, 1, 2, 1, 0, 2, + 2, 3, 1, 2, 1, 2, 2, 2, 2, 3, 3, 2, 1, 2, 1, 2, 1, 2, 3, 2, 0, 3, 2, 0, 1, 0, 3, 3, 0, + 2, 2, 1, 1, 2, 1, 0, 1, 0, 2, 0, 1, 2, 2, 2, 0, 0, 3, 2, 2, 3, 0, 0, 1, 3, 3, 2, 3, 3, + 0, 2, 3, 1, 2, 1, 0, 2, 2, 3, 3, 3, 0, 2, 2, 0, 2, 1, 2, 1, 2, 0, 1, 3, 0, 0, 0, 0, 0, + 2, 0, 3, 1, 0, 1, 2, 3, 1, 2, 2, 2, 1, 1, 0, 0, 2 +}; + + + +void wspr_transmit(enum si5351_multisynth synth, uint8_t *msg); + + +#endif diff --git a/firmware/main.c b/firmware/main.c index 6021385..4c7334b 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -3,6 +3,7 @@ #include "twi.h" #include "si5351.h" +#include "wspr.h" int main(void) { @@ -10,16 +11,16 @@ int main(void) { si5351_init(25000000, 800000000, 500000000); si5351_ms_set_source(SI5351_MS0, SI5351_PLLA); - uint32_t base = 7165000; - uint32_t ppm_err = 9; - uint32_t err = base * ppm_err / 1000000; - uint32_t target = base - err; - - si5351_ms_set_freq(SI5351_MS0, target); - si5351_ms_enable_output(SI5351_MS0); + //si5351_ms_set_freq(SI5351_MS0, 7040100); + //si5351_ms_enable_output(SI5351_MS0); + //si5351_ms_write_params(SI5351_MS0, WSPR_SYMBOLS[3]); + + + wspr_transmit(SI5351_MS0, default_wspr_msg); + while(1); } diff --git a/firmware/scripts/wspr_params.py b/firmware/scripts/wspr_params.py index 10d96c4..f3ac660 100644 --- a/firmware/scripts/wspr_params.py +++ b/firmware/scripts/wspr_params.py @@ -3,7 +3,7 @@ from fractions import Fraction from math import floor -PLL_FREQ = 900.0 * 10**6 +PLL_FREQ = 800.0 * 10**6 SYMBOL_COUNT = 4 # http://www.g4jnt.com/wspr_coding_process.pdf @@ -17,7 +17,7 @@ MAX_DENOM = 0x0FFFFF def main(): - print("struct si5351_params wspr_symbols[%d] = {" % SYMBOL_COUNT) + print("struct si5351_params WSPR_SYMBOLS[%d] = {" % SYMBOL_COUNT) for i in range(0, SYMBOL_COUNT): symbol_freq = Fraction(BASE_FREQ) + Fraction(i) * FREQ_SHIFT @@ -30,15 +30,17 @@ def main(): c = divider.denominator print("\t// %f: %d + %d / %d" % (symbol_freq, a, b, c)) + actual = PLL_FREQ / (a + b/c) + print("\t// actual: %f" % actual) # See https://www.silabs.com/documents/public/application-notes/AN619.pdf - p1 = 128 * a + floor(128 * b/c) + 512 + p1 = 128 * a + floor(128 * b/c) - 512 p2 = 128 * b - c * floor(128 * b/c) p3 = c print("\t{%d, %d, %d}," % (p1, p2, p3)) - print("}") + print("};") if __name__ == '__main__': main() diff --git a/firmware/si5351.c b/firmware/si5351.c index 0542097..0249eca 100644 --- a/firmware/si5351.c +++ b/firmware/si5351.c @@ -27,10 +27,13 @@ void si5351_init(uint32_t freq_xtal, uint32_t freq_a, uint32_t freq_b) { uint32_t c = 0x0FFFFF; uint32_t a = (uint32_t) fdiv; uint32_t b = (uint32_t) ((uint64_t) rm * (uint64_t) c / (uint64_t) freq_xtal); - 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); + + struct si5351_params params = { + 128 * a + (128 * b / c) - 512, + 128 * b - c * (128 * b / c), + c + }; + si5351_write_params(SI5351_PLL_BASE_ADDR[i], params); } } @@ -64,25 +67,27 @@ void si5351_ms_set_freq(enum si5351_multisynth synth, uint32_t freq) { uint32_t a = fdiv; uint32_t b = (uint32_t) ((uint64_t) rm * (uint64_t) c / freq); - 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_MULTISYNTH_BASE[synth], p1, p2, p3); + struct si5351_params params = { + 128 * a + (128 * b / c) - 512, + 128 * b - c * (128 * b / c), + c + }; + si5351_write_params(SI5351_MULTISYNTH_BASE[synth], params); } -uint8_t si5351_write_params(uint8_t base, uint32_t p1, uint32_t p2, uint32_t p3) { +uint8_t si5351_write_params(uint8_t base, struct si5351_params params) { 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 + (params.p3 & 0x00FF00) >> 8, + params.p3 & 0x0000FF, + (params.p1 & 0x030000) >> 16, + (params.p1 & 0x00FF00) >> 8, + params.p1 & 0x0000FF, + ((params.p3 & 0x0F0000) >> 12) | ((params.p2 & 0x0F0000) >> 16), + (params.p2 & 0x00FF00) >> 8, + params.p2 & 0x0000FF }; return twi_write(SI5351_ADDRESS, data, 9); } diff --git a/firmware/wspr.c b/firmware/wspr.c new file mode 100644 index 0000000..b5d0e79 --- /dev/null +++ b/firmware/wspr.c @@ -0,0 +1,14 @@ +#include "wspr.h" + +#include + + +void wspr_transmit(enum si5351_multisynth synth, uint8_t *msg) { + si5351_ms_enable_output(synth); + for(uint8_t i = 0; i < WSPR_LENGTH; i++) { + uint8_t sym = msg[i]; + si5351_ms_write_params(synth, WSPR_SYMBOLS[sym]); + _delay_ms(WSPR_PERIOD); + } + si5351_ms_disable_output(synth); +}