Skip to content

Adaptive FHSS: prove restoration on air, and draw it in the RF primer - #339

Merged
josephnef merged 6 commits into
masterfrom
hopset-tx-restore-onair
Jul 26, 2026
Merged

Adaptive FHSS: prove restoration on air, and draw it in the RF primer#339
josephnef merged 6 commits into
masterfrom
hopset-tx-restore-onair

Conversation

@josephnef

@josephnef josephnef commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

Two small things, both closing gaps left by #265.

1. An autonomous exclusion had never been undone on hardware

MODE=failsafe stopped at the exclusion, so the transmitter's own probe-driven restoration — the probe_good_runProposeRestore path in HopsetSense.h — had unit tests and no on-air evidence. That is the shape of dead code, and #265 lists "jammer removal: autonomous exclusions recover through keyed probes" as a hardware criterion.

It matters beyond box-ticking: an autonomous exclusion that cannot be undone means the link shrinks permanently the first time something transient sits on a channel, and with the receiver mute there is no other evidence that could bring it back.

The mode now runs the same jammer-removal phase the receiver-driven modes already did, and asserts the transmitter aired keyed probes on the channel it excluded, restored it from them, and that the receiver followed back to the full hopset.

Measured with the receiver muted throughout:

PASS: TX aired keyed probes
PASS: the transmitter restored the channel from its own probes
PASS: receiver ended on the full hopset again (0xf)
== ALL PASS ==
"origin":"failsafe","kind":"exclude"    x1
"origin":"failsafe","kind":"restore"    x1
hopset.probe  base_idx 1  ch 5  delivered true
activate: gen 1 mask 0xd  ->  gen 2 mask 0xf

2. The README still described a link that only hops

Both places it covers hopping were written before the schedule could change: they promise a fast keyed hop and stop there. The link now also drops a channel that stops delivering, by authenticated agreement between the two ends, and revisits it later by keyed probes — which is the part a reader evaluating this for a contested band actually wants to know. The deeper-reading entry now says what the design article argues rather than only what it covers.

No library code touched: tests and documentation only.

🤖 Generated with Claude Code

The failsafe mode stopped at the exclusion, so the transmitter's own
probe-driven restoration had never run on hardware — a merged path with unit
tests and no on-air evidence, which is the shape of dead code.

An autonomous exclusion that cannot be undone is worse than none: the link
shrinks permanently the first time something transient sits on a channel, and
with the receiver mute there is no other evidence that could bring it back.
The mode now runs the same jammer-removal phase the receiver-driven modes do,
and asserts the transmitter aired keyed probes on the channel it excluded,
restored it from them, and that the receiver followed back to the full hopset.

Measured, receiver muted throughout: exclude then restore, both attributed to
the failsafe origin; probes on the excluded channel delivering; mask history
gen 1 mask 0xd then gen 2 mask 0xf.
Both places the README describes hopping were written before the schedule could
change: they promise a fast keyed hop and stop there. The link now also drops a
channel that stops delivering, by authenticated agreement between the two ends,
and revisits it later by keyed probes in case it recovers — which is the part a
reader evaluating this for a contested band actually wants to know.

The deeper-reading entry now says what the design article argues rather than
only what it covers: which endpoint decides and why it is the one that has to
decode, what standing the other has to object, and what stops an adversary who
can make channels look bad from herding the link onto one it then jams.
@josephnef josephnef changed the title tests: prove an autonomous exclusion can be undone on air tests: prove an autonomous exclusion can be undone on air; README: the hopset adapts now Jul 26, 2026
josephnef and others added 4 commits July 26, 2026 20:53
The primer's hopping section stopped at the textbook result — spread the
energy, a parked interferer clips one dwell in N, the outer FEC eats the
erasure. Nothing in that picture is something this project does.

Add the second half: the receiver scores what it decodes and proposes
dropping the channel it keeps losing, the transmitter commits the new
schedule at a named future slot so both ends swap together, and a keyed
probe still revisits the excluded channel so the exclusion can be undone.

The figure uses the same channel set and the same parked interferer as
hop_pattern.gif so the two read as one story, but fills a fixed time axis
left to right instead of scrolling — the whole point is the contrast
between the two halves, which a moving window can't hold.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The figure draws a stationary occupant, and that is the case worth
drawing — most interference is a fixed AP, another link, a microwave, and
exclusion against it is a permanent win. But the section read as though
the result generalized, and the measurements say it does not.

Two of them. Against a blind parked jammer a keyed hop order and a
sequential one deliver identically, so secrecy only pays against an
adversary that reacts. And against one that follows the exclusions the
link does not improve — it settles at its minimum active set and stays
there, which is a pass rather than a win, because the exclusion loop is
itself an attack surface: anything that can make a channel look bad can
otherwise steer the schedule down to one frequency of its choosing.

That is what the timid policy is for, and it is the actual advantage —
not that the link learns, but that it learns without becoming teachable.
Scope the figure's subtitle to the stationary case to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The previous commit said in prose that a following interferer changes the
outcome, then illustrated only the case where it doesn't. The picture was
still a victory lap, so it showed nothing the reader didn't already
believe.

Draw the other ending, on the four channels and the floor of three the
herding run was actually measured with. The link excludes the jammed
channel and recovers — the stationary case, in the first half. Then the
interferer moves onto a channel that is still active, delivery collapses
again, the receiver proposes a second exclusion, and the transmitter
refuses it: granting it leaves two channels and the move after that
leaves one. The loss counter keeps climbing to the last frame, because
it does. Better to bleed on three channels than be herded onto one.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The two adaptive figures were drawn on different bands — eight channels
in the first because it inherited them from the plain-hopping figure,
four in the second because that is the geometry the herding run was
measured on and the only one where the floor of three actually binds.
Each choice was locally defensible and the pair was unreadable: you
cannot compare two pictures that do not share an axis, and a "floor 3"
readout next to eight active channels never does anything.

Put both on the eight channels of hop_pattern.gif, with the interferer
starting on the ch 52 it occupies there, so the section reads as one
band observed three times.

The walk-down is the better picture for it anyway. On four channels the
floor binds after a single exclusion and there is nothing to see; on
eight the staircase is the whole argument — five granted exclusions,
each individually correct, the band closing row by row, and then the
sixth refused with three channels left. Prose follows the figure, and
still names the four-channel bench for the measured numbers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@josephnef josephnef changed the title tests: prove an autonomous exclusion can be undone on air; README: the hopset adapts now Adaptive FHSS: prove restoration on air, and draw it in the RF primer Jul 26, 2026
@josephnef
josephnef merged commit 420f977 into master Jul 26, 2026
18 checks passed
@josephnef
josephnef deleted the hopset-tx-restore-onair branch July 26, 2026 18:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant