Add rx888_ppm: online glitch-free ppm trim of the sample clock#33
Draft
ringof wants to merge 1 commit into
Draft
Add rx888_ppm: online glitch-free ppm trim of the sample clock#33ringof wants to merge 1 commit into
ringof wants to merge 1 commit into
Conversation
A stock-Python-3 tool (scripts/rx888_ppm.py) that bends the RX888 ADC sample clock by a few ppm while the receiver is streaming, for manual calibration against a known carrier when no GPSDO is present. It perturbs only the Si5351/MS5351M PLL-A feedback fractional divider (MSNA, regs 26-33) and never issues a PLL soft reset (reg 177). The PLL is an analog loop, so a small fractional change slews the VCO continuously; the output Multisynth divider is untouched, so the output counter never reloads and no clock edge is dropped. Writes go through fx3_cmd --force (EP0 control, no interface claim), so they coexist with a running rx888_stream/rx888d. The tool only ever writes the minimal reset-free register set (31-33, or 28-33 on a carry tick). Commands: read, baseline, nudge (relative), set (absolute vs baseline), zero, sweep (bench characterization with optional --check-lock). The hardware-free register decode/encode/ppm/write-planning math is covered by tests/rx888_ppm_selftest.py, wired into make check. Adds doc/rx888_ppm.md and a README pointer.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A stock-Python-3 tool —
scripts/rx888_ppm.py— that bends the RX888 ADC sample clock by a few ppm while the receiver is streaming, so you can null a known carrier (WWV/WWVH/CHU, a broadcast pilot, a signal generator) by hand. It's the manual-calibration path for a radio with no GPSDO: no restart, no rebuild, no reset.How it stays glitch-free
The sample clock is synthesized in the Si5351A (or the MS5351M clone):
reference → fractional-N PLL → output Multisynth divider → CLK. The tool perturbs only the PLL-A feedback fractional divider (MSNA, regs 26–33) and never issues a PLL soft reset (reg 177).b/cslews the VCO continuously.Because it moves the actual clock (not a software rate relabel), nulling one reference calibrates the whole span, at the true nominal rate.
Coexisting with a live stream
Writes go through
fx3_cmd --force(implies--no-claim): EP0 control transfers, no interface-0 claim, so they run alongsiderx888_stream/rx888d.fx3_cmdmarks the generici2cw/i2crstream-unsafe out of caution; this tool is the classified-safe wrapper — it writes only MSNA fractional bytes (regs 31–33, or 28–33 on a carry tick) and never the reset. Those registers sit outside the firmware's reserved-register fence.Commands
read·baseline·nudge <±ppm>(relative, the everyday knob) ·set <±ppm>(absolute vs baseline) ·zero·sweep <start> <stop> <step>(bench characterization).nudge/set/zero/sweeptake--check-lock(pollfx3_cmd stats_pll); global--dry-run,--claim,--max-ppm,--state,-v.Tests
tests/rx888_ppm_selftest.py— hardware-free coverage of the MSNA decode/encode round-trip, ppm math, carry-into-a, and the minimal reset-free write planner (P2-only vs the P1 carry tick; refuses acchange). Wired intomake check; fullmake checkpasses locally.fx3_cmd:readdecodes correctly, a +0.05 ppm nudge plans a 3-byte write to reg 0x1F (P2-only, no reset), and the applied value is reported honestly-quantized.Verifying it's really edge-clean (follow-up, needs hardware)
The PLL-slew argument is sound but worth measuring on the actual part, since a few Si5351 libraries reset unconditionally.
doc/rx888_ppm.mdspells out two checks:sweep --check-lock(PLL never drops lock), and — the real bar — nudging while a stream runs with the existingcounter_cf32.py/verify_cf32.pycontinuity tooling watching for a slipped sample count.Files
scripts/rx888_ppm.py— the tooltests/rx888_ppm_selftest.py— hardware-free math tests (inmake check)doc/rx888_ppm.md— how it works, commands, and the glitch-free verification planMakefile,README.md,.gitignore— wire-in and pointers🤖 Generated with Claude Code
https://claude.ai/code/session_011R1ghwtgxfeKNMPNq9k5vX
Generated by Claude Code