Skip to content

Satellite count drops for ~28 s at every GPS week rollover (ch->week is not advanced with ch->tow) #89

Description

@tomojitakasu

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions