Dwell-1 A/B injection: a two-context per-slot data plane (exp 4/5)#321
Merged
Conversation
The data-plane experiment #271 could not run on MCC (rejected) reframed onto the ordinary channel switch: examples/dwelltx spends one wall-clock slot per channel on an A/B schedule and admits exactly one data frame per slot inside a bounded window, so a frame built for context A can never air on B. Each frame carries a HopSyncMarker whose slot maps to the expected channel, so a fixed-channel oracle that decodes an out-of-context frame is a self-evident wrong-channel event — attribution needs no cross-clock alignment. Pure caller policy; the library is unchanged. On-air (RTL8822BU DUT, two oracles; tests/dwell1_ab.py): over 100,013 A/B slots at 20 ms, zero wrong-channel, zero duplicate re-airs, 96.2 % delivered on the correct channel, 7 late-drops (0.007 %); admit jitter p99-p1 132 us. Late enqueue past the slot deadline drops deterministically (511/516), never mis-airs. A single receiver acquires the schedule from the markers alone and re-acquires from a cold restart (889 / 861 lockstep decodes). Key finding — the two switch primitives have opposite sweet spots. The synchronous FastRetune carries dwell-1 cleanly; the fire-and-confirm-later firmware switch (DEVOURER_FASTRETUNE_FW, which halves continuous-hop dark time in exp 2-3) needs >12 ms of settle inside a 20 ms slot because its RF completes late in the sparse dwell-1 call pattern — firmware switch for throughput hopping, synchronous switch for deterministic slot placement. Go: advance to exp 5. Full note: docs/dwell1-ab-injection.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
josephnef
force-pushed
the
dwell1-ab-injection
branch
from
July 20, 2026 13:19
f8c6de1 to
53fde02
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.
Closes #272.
Fourth in the standard-driver FHSS series. #272 was premised on the MCC/FCS scheduler from #271, which #271 rejected — so this reframes onto the vehicle the series already validated (the ordinary channel switch) and answers #272's actual question: can firmware-grade channel time-slicing carry a real per-slot data plane with deterministic queue ownership? It can.
What it is
A new
examples/dwelltxdemo runs a two-context A/B schedule — one wall-clock slot per channel — and admits exactly one data-frame opportunity per slot ("dwell-1") inside a bounded window that guarantees the frame finishes airing before the slot flips. Past the deadline the frame is dropped with a structured reason, so a frame built for context A can never air on B. This bounded admission is pure caller policy; the library is unchanged.Each per-slot frame carries a
HopSyncMarker(src/HopSchedule.h) whose slot maps, through the shared schedule, to the channel that slot belongs to — so a fixed-channel oracle that decodes an out-of-context frame is a self-evident wrong-channel event, and attribution needs no cross-clock alignment.tests/dwell1_ab.pydrives two oracles (A/B) with per-slot accounting, fault injection, and the switch-primitive comparison.On-air results (RTL8822BU DUT, 8821AU + 8812CU oracles)
Key finding — the two switch primitives have opposite sweet spots
Running the identical loop over the firmware switch (
DEVOURER_FASTRETUNE_FW) inverts the dwell-1 schedule at 20 ms slots: in the sparse one-retune-per-slot pattern its fire-and-confirm-later RF completes far later than the ~1 ms it shows under continuous hopping (settle sweep: 3 % → 82 % delivery as settle goes 2 → 12 ms). The synchronousFastRetune— RF programmed by the time the call returns — places the frame deterministically with a ~2 ms settle and is the correct dwell-1 primitive. This composes with experiments 2–3 rather than contradicting them: firmware switch for throughput hopping, synchronous switch for deterministic slot placement.Go/no-go: go — advance to experiment 5, using the synchronous switch for the slot data plane. Full note:
docs/dwell1-ab-injection.md.🤖 Generated with Claude Code