Skip to content

Modulated continuous TX + active link-probe (adaptive-link building blocks)#178

Merged
josephnef merged 1 commit into
masterfrom
cont-tx-adaptive-link-probe
Jul 5, 2026
Merged

Modulated continuous TX + active link-probe (adaptive-link building blocks)#178
josephnef merged 1 commit into
masterfrom
cont-tx-adaptive-link-probe

Conversation

@josephnef

Copy link
Copy Markdown
Collaborator

The transmit-side counterpart to the RX sensing toolkit: a realistic active
stimulus, plus an active probe that composes it with the RX sensors into an
operating-point recommendation — building blocks for the energy-minimizing
adaptive link.

DEVOURER_CONT_TX — modulated continuous TX

The modulated sibling of DEVOURER_CW_TONE: instead of a bare carrier, a true
100%-duty full-channel modulated OFDM carrier at a real rate, on all three
chip generations via Realtek's MP hardware continuous-TX mode. SDR-verified as a
flat ~18 MHz OFDM block (tests/sdr_spectrum.py discriminates a modulated block
from a tone by occupied bandwidth), on every generation:

  • Jaguar1 — the 0x914 continuous-TX register (mpt_StartOfdmContTx).
  • Jaguar2 — the same register, once rCCAonSec (0x838)=0x6d is set
    first; without it the 0x914 bit wedges the USB TX FIFO.
  • Jaguar3 — the JGR3 PMAC packet generator: stop the normal TRX (pause the
    TX queues, disable OFDM/CCK CCA), define a legacy-6M PMAC packet, then enable
    PMAC + the 0x1ca4 continuous hold.

Each idle-holds the carrier until SIGINT, then restores the chip cleanly
(verified: an immediate re-run reproduces the carrier with no replug). Exposed
per-chip (StartContinuousTx/StopContinuousTx), reached by downcast from the
demo exactly like the CW tone.

Active link-probe

tests/link_probe.sh + tests/link_probe.py: one adapter emits a modulated
feed and sweeps its TX power in steps; the ground station reads its per-step SNR
and NHM; the analyzer aligns the two by wall-clock and reports the
margin-vs-power curve plus the minimum power that clears a target SNR — the
energy-min reflex made measurable (ride the least power that holds the link). The
same harness serves the MCS-headroom axis. Two adapters, no SDR.

Docs

docs/adaptive-link-building-blocks.md (new) catalogs the levers, sensors,
active stimuli, and probes an adaptive controller composes, and maps them onto
the energy-min design. The README entry is condensed to a pointer (kept light).

Testing

  • Build clean across the per-chip CI subsets; ctest green (4/4).
  • Hardware-validated, no changes to existing behaviour:
    • SDR spectrum: a flat ~18 MHz modulated OFDM block on all three generations
      (Jaguar1 8812AU, Jaguar2 8822BU, Jaguar3 8822CU), distinct from the CW
      tone's spike and from a beacon flood; clean chip restore on stop.
    • Link-probe: a monotonic SNR-vs-power curve in the noise-limited regime and
      the correct "minimum power that clears the target" recommendation.

🤖 Generated with Claude Code

…locks)

Add the transmit-side active stimulus the sensing toolkit was missing, and an
active link-probe that composes it with the RX sensors into an operating-point
recommendation — building blocks for the energy-minimizing adaptive link.

Modulated continuous TX (DEVOURER_CONT_TX): a true 100%-duty full-channel
modulated OFDM carrier — the modulated sibling of the CW tone — on all three
chip generations via Realtek's MP hardware continuous-TX mode:
  - Jaguar1: the 0x914 continuous-TX register (mpt_StartOfdmContTx).
  - Jaguar2: the same register once rCCAonSec (0x838)=0x6d is set first;
    without it the 0x914 bit wedges the USB TX FIFO.
  - Jaguar3: the JGR3 PMAC packet generator — stop the normal TRX (pause the
    TX queues, disable OFDM/CCK CCA), define a legacy-6M PMAC packet, then
    enable PMAC + the 0x1ca4 continuous hold.
Each idle-holds the carrier until SIGINT, then restores the chip cleanly.
Exposed per-chip (StartContinuousTx/StopContinuousTx), reached by downcast from
the demo like the CW tone; SDR-verified as a flat ~18 MHz OFDM block via the new
tests/sdr_spectrum.py (occupied-bandwidth / peakiness discriminates a modulated
block from a bare tone).

Active link-probe (tests/link_probe.sh + tests/link_probe.py): one adapter emits
a modulated feed and sweeps its TX power in steps; the ground station reads its
per-step SNR and NHM; the analyzer aligns the two by wall-clock and reports the
margin-vs-power curve plus the minimum power that clears a target SNR — the
energy-min reflex made measurable. The same harness serves the MCS-headroom axis.

Docs: docs/adaptive-link-building-blocks.md catalogs the levers, sensors, active
stimuli, and probes an adaptive controller composes, and maps them onto the
energy-min design (docs/adaptive-link.md); the README entry is condensed to a
pointer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@josephnef josephnef merged commit 40f2656 into master Jul 5, 2026
15 checks passed
@josephnef josephnef deleted the cont-tx-adaptive-link-probe branch July 5, 2026 16:13
josephnef added a commit that referenced this pull request Jul 5, 2026
Completes the active link-probe and adds the remaining adaptive-link
building-block
harnesses — follow-up to #178.

## MCS-headroom axis
`DEVOURER_TX_MCS_SWEEP="MCS0,MCS2,…"` steps the on-air rate through a
list (a
beacon-feed rate sweep, decoupled from the idle-hold continuous carrier
like the
power ramp), marking each step with `<devourer-contx>mcs=`.
`link_probe.py`
auto-detects the swept axis, aggregates per rate across sweep cycles,
and for the
MCS axis recommends the **highest rate whose ground SNR clears the
target** — the
"ride the fastest modulation the link holds" reflex. `link_probe.sh`
gains
`--axis power|mcs`. (The prior version claimed the harness served the
MCS case but
only implemented the power axis — this makes it real.)

## Thermal-budget overlay
The probe polls the emitter's PA thermal meter during the sweep and
reports the
drift, bounding the sustainable power/duty — the drone's local safety
input.

## Rendezvous beacon
`tests/rendezvous.sh`: the ground parks a modulated continuous beacon on
a
channel; the drone scans candidate channels with its frame-free energy
sensor and
locks onto the beacon's channel — the asymmetric-duty rendezvous
composed from the
continuous-TX stimulus and the RX energy sensor.

## Docs
Note that the continuous carrier is a spectral/thermal stimulus, **not**
a clean
frame source (its looped payload isn't FCS-valid), which is why the
probe uses a
beacon feed for decodable per-frame SNR; and flag the 100%-duty PA heat
as a
debug/characterisation caveat.

## Testing
- Build clean; `ctest` green (4/4).
- Hardware-validated (two adapters, no SDR):
- MCS axis: per-rate SNR curve + correct "highest rate that holds the
floor"
    recommendation.
- Power axis: unchanged (monotonic curve + "cheapest power"
recommendation).
- Rendezvous: the scanner locked onto the beacon's channel (energy ~27×
floor).
- Decodability characterised: the Jaguar1 continuous carrier is
PHY-decodable
(per-frame SNR available); the Jaguar3 PMAC carrier is a spectral
stimulus,
    not a frame stream — hence the probe's beacon feed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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