Summary
In decode_CNV2() (src/sdr_nav.c) the CNAV-2 TOW is computed as
update_tow(ch, getbitu(data, 22, 8) * 7200.0 + (toi - 1) * 18.0 + TOFF_L1CD);
which assumes TOI counts 1...400. The TOI actually carried in subframe 1 is
(frame index + 1) mod 400, so the last frame of every ITOW interval carries
TOI = 0, not 400. (toi - 1) * 18.0 then evaluates to -18 and the resulting
TOW is one ITOW interval (7200 s) short. Every L1C channel therefore fails the
TOW consistency check and loses its TOW every 2 hours.
Observed
TOW MISMATCH <propagated> -> <decoded> at each 2-hour boundary
(pocket_web continuous log, 2026-08-16, QZSS):
pocket_20260816_0200.log J03/J04/J07/J08 L1CD TOW MISMATCH 7200.520 -> 0.520
pocket_20260816_0400.log J02/J03/J04/J07/J08 14400.520 -> 7200.520
pocket_20260816_0600.log J02/J03/J04/J07/J08 21600.520 -> 14400.520
The propagated value on the left is the correct one. ch->tow is invalidated
and all L1CD observations disappear until the TOW is re-latched and confirmed -
about 37 s (two CNAV-2 frames) each time:
155477.540 J04 1S present <- last epoch before the ITOW boundary
155478.540 J04 1S gone <- TOW MISMATCH
155514.540 J04 1S present <- back after ~37 s
L1CP (1L) is unaffected because the pilot uses the tow_v == 2 path.
Evidence for the TOI convention
Decoding the raw $NAV frames of J04 L1CD around the 2026-08-16 week boundary
(WN = bits 9-21, ITOW = bits 22-29, TOI = bits 0-8):
| frame start (GPST) |
WN |
ITOW |
TOI |
| 604782 of week 2431 (last frame of the week) |
2431 |
83 |
0 |
| 0 of week 2432 |
2432 |
0 |
1 |
| 18 of week 2432 |
2432 |
0 |
2 |
So WN / ITOW describe the current frame, and TOI is the index of the next
frame within its interval, wrapping to 0 at the interval end.
Suggested fix
// TOI = 0 means the next frame is in the next ITOW interval
double tow = getbitu(data, 22, 8) * 7200.0 +
(toi > 0 ? toi - 1 : 399) * 18.0 + TOFF_L1CD;
update_tow(ch, tow);
At the end of the week this yields 604800.520, which has to be wrapped to
0.520 with the week number incremented.
Note that the TOI of NavIC L1-SPS in decode_IRNV1() uses a different, 0-based
convention and is correct as written (ITOW * 7200 + toi * 18 + TOFF_I1SD, no
mismatch at 2-hour boundaries in the same logs). The two should not be unified.
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, QZSS L1CD/L1CP.
Summary
In
decode_CNV2()(src/sdr_nav.c) the CNAV-2 TOW is computed aswhich assumes
TOIcounts 1...400. The TOI actually carried in subframe 1 is(frame index + 1) mod 400, so the last frame of every ITOW interval carriesTOI = 0, not 400.(toi - 1) * 18.0then evaluates to -18 and the resultingTOW is one ITOW interval (7200 s) short. Every L1C channel therefore fails the
TOW consistency check and loses its TOW every 2 hours.
Observed
TOW MISMATCH <propagated> -> <decoded>at each 2-hour boundary(pocket_web continuous log, 2026-08-16, QZSS):
The propagated value on the left is the correct one.
ch->towis invalidatedand all L1CD observations disappear until the TOW is re-latched and confirmed -
about 37 s (two CNAV-2 frames) each time:
L1CP (
1L) is unaffected because the pilot uses thetow_v == 2path.Evidence for the TOI convention
Decoding the raw
$NAVframes of J04 L1CD around the 2026-08-16 week boundary(
WN= bits 9-21,ITOW= bits 22-29,TOI= bits 0-8):So
WN/ITOWdescribe the current frame, andTOIis the index of the nextframe within its interval, wrapping to 0 at the interval end.
Suggested fix
At the end of the week this yields 604800.520, which has to be wrapped to
0.520 with the week number incremented.
Note that the TOI of NavIC L1-SPS in
decode_IRNV1()uses a different, 0-basedconvention and is correct as written (
ITOW * 7200 + toi * 18 + TOFF_I1SD, nomismatch at 2-hour boundaries in the same logs). The two should not be unified.
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, QZSS L1CD/L1CP.