icE1usb fw/gpsdo: Attempt to recover from bad tuning
If we're in hold over mode and getting a bunch of invalid
frequency measurement despite a good fix, then we most likely
ended up on a bad tuning value and we need to recover by starting
from scratch.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Change-Id: If8503a3eaf695e02a0ef0a3b6536de985d247c20
diff --git a/firmware/ice40-riscv/icE1usb/gpsdo.c b/firmware/ice40-riscv/icE1usb/gpsdo.c
index c94a5ed..057490f 100644
--- a/firmware/ice40-riscv/icE1usb/gpsdo.c
+++ b/firmware/ice40-riscv/icE1usb/gpsdo.c
@@ -280,6 +280,7 @@
if (!gps_has_valid_fix()) {
/* No GPS fix, go to hold-over */
g_gpsdo.state = STATE_HOLD_OVER;
+ g_gpsdo.meas.invalid = 0;
return;
}
@@ -293,10 +294,22 @@
return;
}
} else {
- /* Count invalid measurements and if too many of
- * them, we go back to hold-over */
- if (++g_gpsdo.meas.invalid >= MAX_INVALID)
- g_gpsdo.state = STATE_HOLD_OVER;
+ /* Count invalid measurements */
+ if (++g_gpsdo.meas.invalid >= MAX_INVALID) {
+ if (g_gpsdo.state != STATE_HOLD_OVER) {
+ /* We go back to hold-over */
+ g_gpsdo.state = STATE_HOLD_OVER;
+ g_gpsdo.meas.invalid = 0;
+ } else {
+ /* We're in hold-over, with valid fix, and
+ * still get a bunch of invalid. Reset tuning */
+ g_gpsdo.tune.coarse = 2048;
+ g_gpsdo.tune.fine = 2048;
+
+ pdm_set(PDM_CLK_HI, true, g_gpsdo.tune.coarse, false);
+ pdm_set(PDM_CLK_LO, true, g_gpsdo.tune.fine, false);
+ }
+ }
/* In all cases, invalid measurements are not used */
return;