From a83f1346de068d91e0cec95f852222836f579325 Mon Sep 17 00:00:00 2001 From: LongHairedHacker Date: Sat, 7 Jul 2018 01:51:20 +0200 Subject: [PATCH] Added some hacky ppm correction --- firmware/main.c | 12 ++++++-- firmware/scripts/parameter_test.py | 43 ++++++++++++++++++++++++++++ firmware/scripts/wspr_params.py | 44 +++++++++++++++++++++++++++++ firmware/si5351.c | 3 +- firmware/test | Bin 0 -> 8392 bytes 5 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 firmware/scripts/parameter_test.py create mode 100644 firmware/scripts/wspr_params.py create mode 100755 firmware/test 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 0000000000000000000000000000000000000000..007eb2f527de1adfb3b429387e0c0d89c76f113b GIT binary patch literal 8392 zcmeHMZ){sv6~B&~CjArJ?OGbzp+3rr(v3P!|AdUHtDWSv&k(m=n?PZ74>xuaBgf9{ z=aO!k$VfN(r1eU^$77`}KiBD1nL|Al* zCGh-|xL+)W@*;^@`miNHYo%M{nq@QLUXaM^YOnyeyr1k?a)c-;G_r7tz!Iy>QV2x? z$irAKwa6k!MP^tYqBy=ml6hD}UYU4h;<2nyU@W4c@>s?uV*L0%-LZ2$%)>JOAp5b?F0fSUST6%? zWgYy}cflV6T&ZLK&AZ^}dqW+20sS_J-P9?@a;c0lBy@dnJgyI=GVyfk$s`ofLeCrV zoS~1#QyHAYJWqIhEA+xjG#?l*(d29kD3ZxImoND(9O+me zr;-iFch0G7!+ETuu42RO>%lD>ZXZ*v6c3I$ZZrDPCT}!r#m0A+DnfhqjL}fNs7;=2 zo8XB1ST&_19|?p%yn&3w;j(TY1C zghF-o+!95UhoK>FG%5gi4$nCG*PjC2P|&~rI7TH-4gekcEDUiy3oSgSeuVHj^_F<) z%8GO9+(hNWhN60_57%-FSJ?1uSPF;8M|CmOVgz$AQuaz=|6(a1@L~;{2N&LU!EZPJuHr02E z1u(x6lVB^GMMGRxud$)y_wyavXMWgc-t0Bsk5pG()+T2> z+QaV_{)}VrvBQzCM-E3GkLWWe=k0N1$}vl$)B}y(SWq5P;L#3`rC5@GkUONvzoo$O ztn==`ZwAhlE{J3Tx+a_U_`*3~ zSHu^J_}aRCO1G~S?7MxGI1Iz?rwR*cbRkJtBE z(&IM^({W3PWh7fkt|rN%wr8Y$9=Q>0&)+3#o>)V~G6l+b8 zwKRp#h-_ao@!=CH%iP};D$h}%|DbX$ZmQ>hE%+SkuD6q45Gi>7zNe?>3rZWD>NY7| z!H!@^xPT62OQ@qOw0&!b7)-}A!^+WQE}zO~l+Iu%7*g7d_;9}cfZC@<4yt-*DAX_V zMdAy`+nn^X@VzgEj#>%*e455B_uE>?DAJenk(2nsancER09JqQe`c)$e5F`8Uv^5I zt>)#UcfrTVzk7T>4Y)E-ujQTxd_}_=!Rsq4euTJ~pQpS`oB|yCAx!;{B*Gbx0T@?Z zuJM1A?P(nHS?w2qqrJNy&XRqIKFE9yJP$a=>9+qZ;0ncH7w-eU!46RV6~I^G*W5KP zL@JXqf`ei(XXK5-&=6$jueo$%R3F5Pt~^|FC9?W(I(sCZ))PiHm)GNkaWR-39ZM&T zWFq+at=mHNjqr*srN?u*_%S`1F>=SmP%b{2)Dwl#(PKcdm2?coVQM7v7@e-~J`jni zy1KVlhZ{DhT|(%+U)>vtMSGkYd6fqcd^B}cBM(~d0io~d+t(fG)A#M(eNgS!`y<_b zDteU{fP?vhjQHPQ`6Ux^BThGo;jrVT(0z~SRwL88EQBhZH-~y6pVdd=nFQV{M)!eL zB9+k#`6M)PK053qC?Cn^$&I|N)OEO&$BACe<$zY^Ax*7HpA~>8W1V`fe5fMxr%K+JuM$XdE4#ZK=L6=LW<4B;~SlSRl z*`}b89EUuP7tm#87YCCgG(tuaz~z#~u!f4o;5;~vkERBp)-3pfM^IK^IfFhEK^U~7 zFc9lZlK%q2{W(l6_!e1-_e(5!e@<#?%XyTafgdg@%;$X-O9gcH#Oo1b+aZHfn)$r{ zVi_Vsp7y+*U_Tw8zX^L{=JPp$CCBgPlUuO^GI&N{KJVvPo+3kB*07(rem)=c0ET;U z=JUCP<#Ev26Z){HFF^tK{LJV5Axj?_bNp<_@(}3p48djIN3v9i?~b2fF$@{(OXl-_ zljRvQhJ8YxjrsMRD&+GPn8?KMoy$idW9KWx zt4TH_$^WNd`HYJnCO*q2xMN&=cKclypU=T8-P1CAel%;)`oi7pn{4t-