tests: host-side Si5351 continued-fraction synthesis math harness (#133)#134
Draft
ringof wants to merge 5 commits into
Draft
tests: host-side Si5351 continued-fraction synthesis math harness (#133)#134ringof wants to merge 5 commits into
ringof wants to merge 5 commits into
Conversation
Adds a standalone, hardware-free TAP harness (tests/si5351_math_test.c) to validate a best-rational-approximation (continued fraction) algorithm for Si5351 multisynth register selection ahead of any firmware change (issue #133). The harness ports rational_approximation() from the fventuri/DFC-transceiver reference, packs results into the real Si5351 P1/P2/P3 register fields and decodes them back (exercising the packing, not just the math), reproduces the current integer algorithm from SDDC_FX3/driver/Si5351.c for comparison, and reports synthesized-frequency error in Hz/ppm. Coverage: common ADC rates, exactly-synthesizable rates, fractional/ppb targets, and a 20,000- point deterministic random sweep over 2-129.6 MHz. Adds a `si5351_math_test` build target and `make check-math` to the tests Makefile, and ignores the new binary. No firmware files touched. https://claude.ai/code/session_018Yua5VMUvZHY7XYeyF2KaL
Companion to si5351_math_test.c (issue #133). Sweeps requested output frequency 10 kHz-135 MHz at the 27 MHz reference and characterizes the synthesis error of the continued-fraction algorithm against both the current integer algorithm and a brute-force hardware optimum that exhaustively searches every feedback denominator c in [1, 2^20-1]. Findings: the continued-fraction result is bit-identical to the brute-force optimum across the sweep (the algorithm is optimal; residual error is the chip's fractional-N resolution limit), ~46% of random frequencies synthesize exactly, and the only algorithm-vs-hardware gap (~0.4 ppm worst case) comes from the reference routine's epsilon=1e-5 early-exit on near-integer feedback ratios -- a tunable software limit, not a hardware one. Adds `si5351_mc` build target and `make mc-plot` (emits scatter + CDF PNGs via gnuplot). Generated CSV/PNG/binary are gitignored and reproducible. https://claude.ai/code/session_018Yua5VMUvZHY7XYeyF2KaL
Committed snapshots of the Monte-Carlo scatter and CDF plots (generated by `make -C tests mc-plot`) so they can be referenced from the issue thread. The tests/ outputs remain gitignored/reproducible; these are intentional documentation snapshots. https://claude.ai/code/session_018Yua5VMUvZHY7XYeyF2KaL
Extends the harness (issue #133) to measure an exact integer/rational continued-fraction solver with semiconvergents head-to-head against the floating-point reference, plus a spur-aware divider search. Adds two analyses and plots: - feedback-level epsilon probe: drives the feedback fractional part from 1e-8 to 1e-2 and compares float-CF vs exact-rational vs the exhaustive optimum. Shows the float routine's epsilon=1e-5 early-out leaves up to ~0.3 ppm where an exact fraction exists (denom <= 2^20-1), while the exact-rational solver reaches 0. - chosen feedback denominator distribution: single divider vs spur-aware divider search. Integer-PLL (b==0) is ~0% for arbitrary rates on a 27 MHz reference; spur-aware search trims the median denominator only modestly. The dominant spectral lever (integer even output divider) is already used regardless. Generated CSV/PNG are gitignored; plot snapshots committed under docs/assets/issue-133/ for the discussion thread. https://claude.ai/code/session_018Yua5VMUvZHY7XYeyF2KaL
Benchmarks three solver strategies (issue #133) to quantify the cost of a thorough divider search on the FX3: a lightweight single-divider exact solve, a full search with the straddling output divider computed directly, and a full search that scans D=8..2048 linearly (the ka9q-style form). Findings: the linear D scan (~81k inner iterations/solve) is the only heavy part and is avoidable by computing D = floor(pll_target/(fout*R)) directly, which yields an identical solution ~20x faster. Even the unoptimized scan estimates to ~tens of ms on the FX3 -- well under the ~2 s EP0 handler budget and smaller than the ~100 ms PLL-lock poll already performed. Adds a `si5351_bench` target and `make bench`; binary is gitignored. https://claude.ai/code/session_018Yua5VMUvZHY7XYeyF2KaL
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.
Summary
Groundwork for issue #133 (continued-fraction Si5351 multisynth selection +
STARTADCFP). This PR adds only a host-side, hardware-free test harness to validate the best-rational-approximation math before any firmware change is made — no firmware files are touched and no shipping behavior changes.tests/si5351_math_test.c:rational_approximation()verbatim from thefventuri/DFC-transceiverreference.a + b/cinto the real Si5351P1/P2/P3register fields and decodes them back, so the register packing is exercised, not just the math.SDDC_FX3/driver/Si5351.c(si5351aSetFrequencyA) for side-by-side comparison.Coverage: common ADC rates, constructed exactly-synthesizable rates, fractional/ppb targets, and a 20,000-point deterministic (fixed-seed) random sweep over 2–129.6 MHz.
tests/Makefile: adds asi5351_math_testtarget (links onlylibm) and amake check-mathconvenience target;.gitignoreignores the binary.Results (current run)
STARTADCtoday.Test plan
make -C tests check-math→ expect1..31and# 31/31 passed, exit 0.make -C tests fx3_cmdstill builds (independent of the new target).Not in this PR (follow-ups for #133)
SDDC_FX3/driver/Si5351.c(generalize the integer-only output divider; double-precision core).STARTADCFPvendor command (8-byte IEEE-754 LE double) +STARTADCbecoming a thin integer wrapper.fx3_cmd.c) +docs/api.mdupdates andfw_test.shintegration.Open questions are tracked in the issue comment: opcode choice, out-of-range failure semantics, whether CLK2 gets the same treatment, and the confirmed supported frequency window.
https://claude.ai/code/session_018Yua5VMUvZHY7XYeyF2KaL
Generated by Claude Code