Skip to content

Stop the DT indicator jumping on a well-synced rig - #915

Merged
patrickrb merged 1 commit into
devfrom
fix/dt-indicator-stability
Sep 26, 2026
Merged

patrickrb merged 1 commit into
devfrom
fix/dt-indicator-stability

Conversation

@patrickrb

Copy link
Copy Markdown
Owner

Why

Reported: "my Delta time indicator will say it's 2.5 seconds off or 1.5 or whatever even though it seems like it's working stations perfectly. It makes the app look unstable and bad."

It was. The clock-sync pill showed the raw arithmetic mean of a slot's decode DTs, re-posted on every decode pass:

  • A mean has no defence against one bad decode. DT is per-station — a station transmitting late, or a marginal decode the searcher placed a couple of seconds off, carries its own big DT. Three good decodes at +0.1 s plus one at +7 s average to +1.8 s: a red "clock off" verdict produced entirely by somebody else's clock.
  • Every pass re-posted. A slot is decoded several times (fast pass, then deep/late passes that dig out the weakest signals — exactly the decodes with the sloppiest DT), so the number jumped several times within one 15 s slot.
  • No slot-to-slot smoothing, so even clean data bounced between a 2-decode slot and a 9-decode one.

The kicker: ClockSelfSync, the estimator that actually corrects the clock, has always been robust (median + MAD rejection + multi-slot confirmation). So the display and the correction openly disagreed — the pill flashed "2.5 s off" while auto-sync, looking at the same decodes, correctly concluded there was nothing to do.

What changed

New DecodeDtDisplay (pure Java, next to ClockSelfSync, reusing its median/MAD helpers so both paths measure the same way):

before after
per slot arithmetic mean MAD-rejected median
multiple passes on one slot each replaced the reading accumulate into that slot, refining its median
across slots none median of the last 3 slots
tiny changes re-posted every time held below a 0.05 s deadband
after a clock correction averaged across it window dropped, reading re-acquires

A real, sustained error is still followed within ~2 slots (tested). The manual "suggested correction" in Settings → Time Sync reads the same value, so it gets steadier too.

Also logs DT: raw=+2.31 shown=+0.12 n=5 once per slot — a debug.log now shows directly whether a wandering raw mean is being smoothed or a clock is genuinely drifting.

Verification

  • Full testDebugUnitTest suite — pass. DecodeDtDisplayTest adds 12 cases, including the exact reported shape (three in-time decodes + one station 7 s late must not move the reading) and the converse (a genuine +1 s drift must still be followed).
  • Built and installed on an emulator; app runs clean.

Not verified against live signals — the emulator decodes nothing and no rig/phone was attached to this machine. Worth a session on the air before merging: the DT: raw=… shown=… lines make it easy to confirm from debug.log.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Lbd9brnZDMCzipgsu9n8Xg

The clock-sync pill showed the raw arithmetic MEAN of a slot's decode DTs,
re-posted on every decode pass. On a rig working stations perfectly it would
announce "+2.5 s" and turn red, which reads as an unstable app.

Three separate reasons it did that:

- A mean has no defence against one bad decode. DT is per-station: a station
  transmitting late, or a marginal decode placed a couple of seconds off,
  carries its own large DT. Three good decodes at +0.1 s plus one at +7 s
  average to +1.8 s — a red "clock off" verdict produced entirely by somebody
  else's clock.
- Every pass re-posted. A slot is decoded several times (fast, then deep and
  late passes that dig out the weakest signals — exactly the ones with the
  sloppiest DT), so the number visibly jumped several times per slot.
- No slot-to-slot smoothing at all.

Meanwhile the estimator that actually corrects the clock (ClockSelfSync) has
always been robust — median, MAD rejection, multi-slot confirmation — so the
display and the correction openly disagreed: the pill flashed "clock off"
while auto-sync, reading the same decodes, correctly did nothing.

New DecodeDtDisplay puts the display on the same footing: MAD-rejected median
per slot, passes accumulating into their slot instead of replacing the
reading, the median of the last 3 slots, and a 0.05 s publish deadband so the
last digit stops twitching. A deliberate clock change (manual, GPS/NTP or
self-sync) drops the window so the reading re-acquires instead of averaging
across a correction. A real, sustained error is still followed within ~2 slots.

Also logs "DT: raw=... shown=... n=..." once per slot, so a debug.log shows
directly whether a wandering raw mean is being smoothed or a clock is
genuinely drifting.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lbd9brnZDMCzipgsu9n8Xg
@codecov

codecov Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 41.50%. Comparing base (c603d1c) to head (d75b212).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##                dev     #915   +/-   ##
=========================================
  Coverage     41.50%   41.50%           
  Complexity      252      252           
=========================================
  Files           280      280           
  Lines         33973    33973           
  Branches       4033     4033           
=========================================
  Hits          14100    14100           
  Misses        19584    19584           
  Partials        289      289           
Flag Coverage Δ
android 17.59% <ø> (ø)
native 9.93% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...app/src/main/kotlin/radio/ks3ckc/ft8af/FT8AFApp.kt 0.37% <ø> (ø)
...tlin/radio/ks3ckc/ft8af/ui/components/ClockSync.kt 25.31% <ø> (ø)
...n/radio/ks3ckc/ft8af/ui/settings/TimeCorrection.kt 100.00% <ø> (ø)
...radio/ks3ckc/ft8af/ui/settings/TimeSyncSettings.kt 0.00% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@patrickrb
patrickrb merged commit 0677e40 into dev Sep 26, 2026
18 checks passed
@patrickrb
patrickrb deleted the fix/dt-indicator-stability branch September 26, 2026 16:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant