Skip to content

Self-learning holdover temperature compensation#2

Closed
peterlewis wants to merge 1 commit into
pcc-firmware-proposalsfrom
tempcomp
Closed

Self-learning holdover temperature compensation#2
peterlewis wants to merge 1 commit into
pcc-firmware-proposalsfrom
tempcomp

Conversation

@peterlewis

Copy link
Copy Markdown
Owner

Stacked on mitxela#5 (pcc-firmware-proposals) — review that first; this PR's own diff is just the temperature-compensation feature, which consumes the $PMTXTS telemetry mitxela#5 adds.

What this adds

While GPS-locked, the clock learns how each oscillator's frequency error varies with die temperature (binned per-oscillator, weighted least-squares). During a GPS-loss holdover it then:

  • tc_apply — steers the SysTick display timebase from the HSE model to cancel temperature-driven drift (the dominant holdover error);
  • tc_rtc — optionally trims RTC->CALR from the LSE model, so if power is lost during an outage the battery RTC hands over far better time on the next boot.

All three enables (tc_learn / tc_apply / tc_rtc) default off — with them unset, behaviour is identical to stock.

Design notes

  • No maths in the ISR. All model fitting / evaluation runs in the main loop (the calibrateRTC float precedent); the tick ISR only does an integer Bresenham SysTick->LOAD stretch from three precomputed values — a true fractional-ppm rate steer with no phase steps.
  • Origin-free HSE model. The PPS handlers re-zero the ms cascade each edge, so each capture is a self-contained one-second accumulation with an arbitrary standing offset. The model is learned in ticks with that arbitrary origin; steering only ever applies model(T_now) − model(T_at_loss), so the origin cancels and the per-edge phase snap makes re-lock instantly neutral. (It therefore corrects temperature-driven drift; the absolute TCXO offset at loss is its spec ~±1–2 ppm — re-lock anchoring is a possible follow-up.)
  • Ticks-per-ppm derived at runtime from the captured SysTick period — no core-clock constant baked in.
  • tc_dump = on over serial prints the learned coefficients as paste-ready config.txt lines (plus a checksummed $PMTXTC sentence for host tools); pasting them back freezes the model. tc_reset = on clears it. Both are serial-only (guarded so a stray line in config.txt can't fire on every reload).
  • MODE_TEMPCOMP diagnostic display pages die temp / model offset / sample count on the date row.
  • CALR trims happen only in holdover (never contends with calibrateRTC, which owns CALR while locked); the WPR sequence runs IRQ-off against PendSV's write_rtc.

Status

Hardware-validated on an Mk IV — the LSE model learned 18.68 ppm vs 18.9 ppm measured directly (~1%). Builds clean (arm-none-eabi-gcc -O3, zero warnings in changed code). Survived an adversarial review pass (ISR-safety, integer math, sign conventions, re-lock neutrality, off-means-identical). Draft pending broader holdover-steering validation on the bench.

Builds on the $PMTXTS telemetry: while GPS-locked the clock learns each
oscillator's frequency error vs die temperature (binned, per-oscillator), then
during a GPS-loss holdover it steers the SysTick timebase from the HSE model to
cancel temperature-driven drift, and optionally trims RTC->CALR from the LSE
model so the battery RTC hands over better time across a power loss.

- tc_learn / tc_apply / tc_rtc config keys (all default off = stock behaviour)
- steering is a Bresenham SysTick->LOAD stretch inside the tick ISR (integer
  only; all model maths is main-loop); origin-free HSE model so only the
  temperature DIFFERENCE since GPS loss is applied, and the per-edge PPS phase
  snap makes re-lock instantly neutral
- 'tc_dump = on' over serial prints the learned coefficients as paste-ready
  config lines (+ a $PMTXTC sentence); pasting them back freezes the model
- MODE_TEMPCOMP diagnostic display: die temp / model offset / sample count
- ticks-per-ppm derived from the runtime SysTick period (no core-clock assumption)

Hardware-validated on an Mk IV: the LSE model learned 18.68 ppm vs 18.9 ppm
measured directly (~1%). Survived an adversarial review pass (ISR-safety,
integer math, sign conventions, re-lock neutrality, off-means-identical).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@peterlewis

Copy link
Copy Markdown
Owner Author

Superseded by mitxela#9 (draft, targets upstream). Branch kept for the clean stacked diff against pcc-firmware-proposals.

@peterlewis peterlewis closed this Jul 5, 2026
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