rtl8733b: port FastRetune — intra-band hop with TSSI tracking kept live - #398
Conversation
The full SetMonitorChannel on this USB-HS part costs ~330-440 ms, profiled per-stage as ~165 ms TSSI disable/re-enable, ~90 ms band+bandwidth switches it does not need on a same-band same-width hop, and ~60 ms channel switch. Phy8733b::fast_retune keeps the subset a hop needs: the RF18 synth program from a compose cache (bandwidth bits preserved; primed by one read on the first fast hop after a full set), RF19 sub-band bits and the channel-keyed BB constants on bucket change only, then the BB reset + IGI toggle that restart the RX engine. TSSI tracking stays enabled across the hop with the per-channel rate-offset dwords rewritten in place when the plan differs — the OpenIPC#389 shape. Everything that can refuse is computed before the first chip write, so a declined hop (band/width change, cold radio) leaves the chip untouched and the device wrapper falls back to the full path per the IRtlDevice contract. AdapterCaps now states fastretune_ok. Measured on the validation unit (0bda:f72b, USB HS, 20-cycle settle harness, 1 kHz witness emitter): call ~55 ms, radio-live 10.0 ms p50 from hop start (min 3.6 / p90 12.9 / max 40.3 — a 1-in-20 tail), vs 70-100 ms radio-live through the full path. Channel-state readback parity held 7/7 hops; a 300-frame post-hop burst decoded 299/300 at an RTL8812AU witness, so the TSSI-live claim is air-verified. One unit, no SDR: radiated power across a hop stays uncharacterized, like every RF-domain quantity on this backend. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hri3rWJfbvw8iCyDDwXRit
PR Summary by QodoRTL8733B: add FastRetune for intra-band hops with live TSSI tracking
AI Description
Diagram
High-Level Assessment
Files changed (7)
|
Code Review by Qodo
1.
|
…n place Review finding on the first cut (qodo, PR OpenIPC#398): fast_retune kept TSSI tracking live but rewrote only the 0x3a00 rate-offset dwords, which are band-keyed and never change intra-band. The channel-varying TSSI calibration is the DE offsets from tssi_de_plan, whose 2.4 GHz buckets are ~3 channels wide — so nearly every hop crossed one and kept tracking with the previous channel's DE calibration until the next full set. prepare_tssi_offsets now records the applied DE plan and the EFUSE calibration that derives it; fast_retune recomputes the target plan before its first chip write (declining to the full path when it cannot) and, on bucket change, replays prepare's field sequence minus the 0x4318 tracking-disable write. disable_tssi_tracking drops the cache. Measured on the validation unit, 22 ch1->ch13 fast hops (every one bucket-crossing): DE readback parity 22/22, tracking-enable field held at 7 throughout, settle p50 unchanged at 10.4 ms. The selftest pins the bucket property the trigger depends on: plans equal within a bucket, different across a boundary. Also aligns the GetAdapterCaps timing comment with the documented measurements (~55 ms call / ~10 ms p50 radio-live). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hri3rWJfbvw8iCyDDwXRit
…keeping on a failed hop The SCO fc tables, the ch14 TX shape and the AGC/SCO bucket ladders were duplicated verbatim between switch_channel and fast_retune — an edit to one that missed the other would be a full-vs-fast register parity divergence only a hardware parity run could catch. Hoisted to file-scope constexpr shared by both paths. A transport failure after fast_retune's first chip write used to propagate with _fr_plan still recording the old channel while the radio sat part-hopped; a later fast hop would then bucket-compare against a baseline the chip no longer holds and could skip a needed write. The catch now drops the fast-path bookkeeping so the next call declines to the full-path fallback, which reprograms everything. Also: disable_tssi_tracking resets _fr_tssi_power with its two siblings, and the FastRetune override no longer re-declares the cache_rf default (it binds at the IRtlDevice declaration, like the Jaguar overrides). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
josephnef
left a comment
There was a problem hiding this comment.
Reviewed against the full path, register by register:
- The DE rewrite sequence is
prepare_tssi_offsetsbyte-for-byte minus its0x4318tracking-disable write, including the repeated ht40 lane writes. - RF18/RF19 compose masks match
switch_channeland preserve the bandwidth bits (10/11), so the cached word carries width as claimed. - Every write the fast path skips is genuinely band-keyed or constant (
0x1ea8, the 2.4 GHz0x18acpair,spur_cancellation,0x2a38[27]— touched nowhere else, so already 0 after the prior full set the fast path requires). - Refuse-before-first-write holds: both TSSI plans and the cache-priming reads complete before the first chip write.
- The TSSI invariants hold:
_tssi_tracking == trueimplies bothprepare_tssi_offsets(readback-matched, DE plan + EFUSE recorded) andenable_tssi_tracking(offsets + path recorded) succeeded, with the same target cap at enable and hop. - The selftest addition pins exactly the bucket-boundary property the DE rewrite depends on.
Build + ctest 53/53 verified locally. The docs carry their adversarial counterparts (1-in-20 tail, one unit, no SDR) per the repo rule.
Two findings, both applied in 5c51692 rather than requested back:
- The SCO fc tables, ch14 TX shape and AGC/SCO bucket ladders were duplicated verbatim between
switch_channelandfast_retune— a one-sided edit would be a full-vs-fast parity divergence only a hardware parity run could catch. Hoisted to shared file-scope constexpr. - A transport failure after the first chip write propagated with
_fr_planstill recording the old channel while the radio sat part-hopped; a later fast hop would bucket-compare against a baseline the chip no longer holds. The catch now drops the fast-path bookkeeping so the next call declines to the full-path fallback.
Plus two nits in the same commit: disable_tssi_tracking resets _fr_tssi_power with its siblings, and the override no longer re-declares the cache_rf default (binds at the interface, like the Jaguar overrides).
🤖 Generated with Claude Code
What
Ports
FastRetuneto the RTL8733B backend — the last generation without a fast path. Intra-band, same-width hops only; a band/width change or cold radio declines with the chip untouched and the wrapper falls back to the fullSetMonitorChannel, per theIRtlDevicecontract.AdapterCaps.fastretune_oknow states it.Why / how it was sized
Per-stage profiling of the full path on the USB-HS validation unit (
0bda:f72b, cut D): ~330–440 ms total = ~165 ms TSSI disable/re-enable + ~90 ms band/bandwidth switches + ~60 ms channel switch + HALMAC/readback. A same-band same-width hop needs almost none of that. The fast path keeps: RF18 synth program from a compose cache (bandwidth bits preserved; primed by one read on the first fast hop after each full set), RF19 sub-band bits and channel-keyed BB constants on bucket change only, BB reset + IGI toggle. TSSI tracking stays enabled across the hop, with the per-channel rate-offset dwords rewritten in place only when the plan differs — the in-place-with-tracking-live shape #389 validated. Everything that can refuse is computed before the first chip write.Measured (one unit — the standing 8733B caveat — no SDR)
read_channel_state().matches(plan)+ synth-ready held on 7/7 fast hops (5180→5805).Docs updated (
src/rtl8733b/CLAUDE.md, rootCLAUDE.mdfrequency-hopping section,docs/rtl8733b.mddeferred matrix) with the adversarial counterparts alongside the numbers, per the repo rule.🤖 Generated with Claude Code
https://claude.ai/code/session_01Hri3rWJfbvw8iCyDDwXRit