Summary
Running pocket_trk / pocket_web across a GPS week boundary (Sunday 00:00:00
GPST), the satellite count in the PVT solution drops from ~33 to ~5 and takes
about 28 s to recover.
update_tow() in src/sdr_ch.c wraps ch->tow at the end of the week but does
not advance ch->week, which is only updated when a subframe carrying WN is
decoded. gen_prng() in src/sdr_pvt.c then adds a spurious one week to every
pseudorange, so tau becomes ~604800 s and all observations are rejected by the
tau < -0.02 || tau > 0.167 check.
Observed
$GNGGA satellite count (UTC = GPST - 18 s), identical on 2026-08-02, 08-09 and
08-16, so fully deterministic:
| UTC |
23:59:42 |
23:59:43 |
23:59:49 |
23:59:57 |
00:00:10 |
| GPST |
00:00:00 |
00:00:01 |
00:00:07 |
00:00:15 |
00:00:28 |
| NSat |
33 |
5 |
15 |
19 |
32 |
$CH records show the TOW wrapping while the week stays behind:
148277.540 G07 L1CA tow=604799927 week=2431 <- GPST 00:00:00
148278.540 G07 L1CA tow= 927 week=2431 <- TOW wrapped, week did not
$LOG,148278.540,G07,L1CA,7,PSEUDORANGE OUT OF RANGE (604800.073022)
148284.540 G07 L1CA tow= 6927 week=2432 <- recovers when SF1 is decoded
148305.540 E03 E1B tow= 27924 week=2432 <- Galileo recovers at +28 s
The staggered recovery matches the WN repetition period of each signal:
GPS/QZSS LNAV SF1 (+7 s), BDS D2 (+15 s), Galileo I/NAV word 5 (+28 s).
GLONASS is unaffected because ch->week stays 0 and the tow_v == 2 path in
gen_prng() does not use the week - the 5 surviving satellites are exactly the
GLONASS ones.
Suggested fix
static void update_tow(sdr_ch_t *ch, double sec)
{
if (ch->tow < 0) return;
ch->tow += (int)floor(sec / 1e-3 + 0.5);
// the week has to follow the TOW rollover until the next week is decoded
if (ch->tow >= 86400 * 7 * 1000) {
ch->tow -= 86400 * 7 * 1000;
if (ch->week > 0) ch->week++;
} else if (ch->tow < 0) {
ch->tow += 86400 * 7 * 1000;
if (ch->week > 0) ch->week--;
}
}
BeiDou needs one more change: SOW + GPST_BDT (14 s) exceeds 604800 for the
14 s after the GPS week end (the BDT week ends later), raising
TOW MISMATCH 0.016 -> 604800.016 and forcing a TOW re-latch. The week has to
be advanced together with the TOW there, since GPST week = BDT week + 1356
alone leaves BeiDou one week behind. NavIC L1-SPS has the same overflow.
I have this implemented and tested locally and can open a PR if useful.
Environment
PocketSDR library 0.20 (SDR_LIB_VER), master at 03787da, Windows 11 /
MSYS2 UCRT64 gcc 15.2.0, 8 ch front end, GPS/GLONASS/Galileo/BeiDou/QZSS.
Summary
Running
pocket_trk/pocket_webacross a GPS week boundary (Sunday 00:00:00GPST), the satellite count in the PVT solution drops from ~33 to ~5 and takes
about 28 s to recover.
update_tow()insrc/sdr_ch.cwrapsch->towat the end of the week but doesnot advance
ch->week, which is only updated when a subframe carrying WN isdecoded.
gen_prng()insrc/sdr_pvt.cthen adds a spurious one week to everypseudorange, so
taubecomes ~604800 s and all observations are rejected by thetau < -0.02 || tau > 0.167check.Observed
$GNGGAsatellite count (UTC = GPST - 18 s), identical on 2026-08-02, 08-09 and08-16, so fully deterministic:
$CHrecords show the TOW wrapping while the week stays behind:The staggered recovery matches the WN repetition period of each signal:
GPS/QZSS LNAV SF1 (+7 s), BDS D2 (+15 s), Galileo I/NAV word 5 (+28 s).
GLONASS is unaffected because
ch->weekstays 0 and thetow_v == 2path ingen_prng()does not use the week - the 5 surviving satellites are exactly theGLONASS ones.
Suggested fix
BeiDou needs one more change:
SOW + GPST_BDT(14 s) exceeds 604800 for the14 s after the GPS week end (the BDT week ends later), raising
TOW MISMATCH 0.016 -> 604800.016and forcing a TOW re-latch. The week has tobe advanced together with the TOW there, since
GPST week = BDT week + 1356alone leaves BeiDou one week behind. NavIC L1-SPS has the same overflow.
I have this implemented and tested locally and can open a PR if useful.
Environment
PocketSDR library 0.20 (
SDR_LIB_VER), master at 03787da, Windows 11 /MSYS2 UCRT64 gcc 15.2.0, 8 ch front end, GPS/GLONASS/Galileo/BeiDou/QZSS.