FHSS-grade hop latency: write-only compose cache + kick diet (0.55-2.5 ms on every generation)#187
Merged
Merged
Conversation
One machine-parseable <devourer-hop-prof> line per fast hop with per-stage microseconds — the instrument behind the hop-latency work (every hop microsecond is USB control transfers; the profile is what localises them). Zero overhead when unset. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A masked phy_set_bb_reg is a read-modify-write — two USB control transfers — and the hop's cost is purely transfer count x EP0 latency (DEVOURER_HOP_PROF-measured ~0.21 ms/op on the 8822CU). Prime the full dwords of everything the hop touches once per epoch (lazily, on the first fast hop — init calibration rewrites registers after the full set), compose bit changes in memory, and write whole dwords: the steady hop is nine write-only transfers (3-wire bracket, RF18 window A/B, anapar A/B, BB-reset triple), with SCO/DFIR as composed single writes on bucket change (DFIR's two nibbles in one dword). Top bits ride along from the prime, so untouched fields are written back as read — correct by construction. The compose caches invalidate wherever those registers are written outside the channel paths (TXAGC-gate writers, the NB divider recipe). Measured (1/6/11 hop set): 8822CU 3.6 -> 1.9 ms, 8812EU 4.3 -> 2.4 ms median. Register parity PASS on both variants (20/40 MHz + NB shapes); B210 hop order PASS (~100 cycles); 12,000 consecutive dwell-1 per-packet hops with zero bulk-OUT failures. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… ms) The first Jaguar2 fast path spent 17 of its 19 USB transfers on the vendor switch_channel tail (RF 0xb8 toggle, RX-path toggle, IGI toggle — each masked write a read+write round-trip, at the T3U's ~1 ms EP0 latency). Hardware A/B on both variants, both directions, shows a hop does not need that kick: a hopping receiver catches a parked beacon at identical per-dwell medians with and without it (no decay over ~850 kickless retunes, zero dead dwells), and hopping-TX delivery is unchanged. The kick stays in the full path only. The rest goes write-only via the same compose cache as Jaguar1/Jaguar3: RF18 primed once and composed per hop (the 8821CU hop is a single LSSI write), AGC/fc/RF-0xBE as composed writes on bucket change. Measured (1/6/11 hop set): 8822BU 18.2 -> 2.5 ms, 8821CU 5.6 -> 0.55 ms median. Register parity PASS both variants (2.4/5 GHz); B210 hop order PASS (~100 cycles); 9,000 consecutive dwell-1 per-packet hops with zero bulk-OUT failures. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
RF 0x1a is not written by any channel path on the 8822C (it is the 8822E's RXBB register) and its bit17 floats — observed flipping between two full-path control runs. Static exclusion for the C PIDs only; on the E it is real RXBB config and stays checked. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The ports table gains the per-DUT USB-op cost and op count (the whole cost model: transfer count x EP0 latency, which varies 5x across the family), the two techniques that carried the newer generations to 0.55-2.5 ms (the compose cache generalising the cached-write trick to every masked register write; the hardware-measured finding that a hop needs no per-hop RX kick), and the FHSS soak results. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
cbf4285 to
c9a2d98
Compare
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.
Follow-up to #186: bring every generation's hop latency down to the RTL8812AU's level, so a robust FHSS layer can sit on top. FastRetune medians (1/6/11 hop set):
The cost model
DEVOURER_HOP_PROF=1(new,src/HopProf.h) emits per-stage timing for every fast hop. It reduced the problem to one equation: hop cost = USB op count × the chip's EP0 control-transfer latency. A register read or write is one synchronous control transfer; a maskedphy_set_bb_regis secretly two (read-modify-write). EP0 latency is a per-chip firmware property varying 5× across the family (0.21 ms/op on the 8822CU, ~1 ms/op on the Archer T3U), so the only code lever is op count — the 8812AU's famous 1.6 ms was never exotic, it is simply two ops per hop.What changed
switch_channeltail (RF 0xb8 toggle, RX-path toggle, IGI toggle) was 17 of the first port's 19 transfers. Hardware A/B on both variants, both directions: a hopping receiver catches a parked beacon at identical per-dwell medians with and without it (no decay over ~850 kickless retunes, zero dead dwells), and hopping-TX delivery is unchanged. The kick stays in the full path only — a hop needs the channel write, not the state-machine kick.Testing
ctestgreen (5/5).🤖 Generated with Claude Code