diff --git a/firmware/main.c b/firmware/main.c index 9d1d016..6021385 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -8,12 +8,18 @@ int main(void) { twi_init(); - si5351_init(25000000, 400000000, 300000000); - si5351_ms_set_source(SI5351_MS0, SI5351_PLLB); - si5351_ms_set_freq(SI5351_MS0, 7165000); + 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); + while(1); } diff --git a/firmware/scripts/parameter_test.py b/firmware/scripts/parameter_test.py new file mode 100644 index 0000000..ab72569 --- /dev/null +++ b/firmware/scripts/parameter_test.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 + +import numpy as np +import matplotlib.pyplot as plt + +PLL_FREQ = 800*10**6 # Mhz + +def main(): + # 8kHz to 150MHz + out_freq = np.uint32(np.arange(1*10**6, 160*10**6, 10)) + + fdiv = PLL_FREQ / out_freq + rm = PLL_FREQ % out_freq + + c = np.uint32(0x0FFFFF); + a = np.uint32(fdiv) + b = np.uint32(np.uint64(c) * np.uint64(rm) / out_freq) + + ideal_freq = PLL_FREQ / fdiv + real_freq = PLL_FREQ / (a + b/c) + + err = (ideal_freq - real_freq) + out_freq = out_freq / 10**6 + ideal_freq = ideal_freq / 10**6 + real_freq = real_freq / 10**6 + + + p1 = 128 * a + np.floor(128 * b / c) - 512; + p2 = 128 * b - c * np.uint32(128 * b / c); + + + #plt.plot(out_freq, ideal_freq) + #plt.plot(out_freq, real_freq) + + plt.plot(out_freq, err) + + + + + plt.show() + +if __name__ == '__main__': + main() diff --git a/firmware/scripts/wspr_params.py b/firmware/scripts/wspr_params.py new file mode 100644 index 0000000..10d96c4 --- /dev/null +++ b/firmware/scripts/wspr_params.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +from fractions import Fraction +from math import floor + + +PLL_FREQ = 900.0 * 10**6 + +SYMBOL_COUNT = 4 +# http://www.g4jnt.com/wspr_coding_process.pdf +FREQ_SHIFT = Fraction(12000,8192) # What the fractional fuck? + +# 7.040000 - 7.040200 +BASE_FREQ = 7.040100 * 10**6 + +# Maximum c +MAX_DENOM = 0x0FFFFF + + +def main(): + 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 + + divider = Fraction(PLL_FREQ) / symbol_freq + divider = divider.limit_denominator(MAX_DENOM) + + a = floor(divider.numerator / divider.denominator) + b = divider.numerator % divider.denominator + c = divider.denominator + + print("\t// %f: %d + %d / %d" % (symbol_freq, a, b, c)) + + # See https://www.silabs.com/documents/public/application-notes/AN619.pdf + 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("}") + +if __name__ == '__main__': + main() diff --git a/firmware/si5351.c b/firmware/si5351.c index 9e88960..0542097 100644 --- a/firmware/si5351.c +++ b/firmware/si5351.c @@ -62,7 +62,8 @@ void si5351_ms_set_freq(enum si5351_multisynth synth, uint32_t freq) { //TODO: Find better way to determine c and b uint32_t c = 0x0FFFFF; uint32_t a = fdiv; - uint32_t b = (uint32_t) ((uint64_t) rm * (uint64_t) c / (uint64_t) freq); + 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; diff --git a/firmware/test b/firmware/test new file mode 100755 index 0000000..007eb2f Binary files /dev/null and b/firmware/test differ