Jaguar1 + Jaguar2 CW single-tone (DEVOURER_CW_TONE) — SDR-validated#167
Merged
Conversation
Add a Realtek MP single-tone (bare RF local-oscillator carrier) emit mode for the Jaguar-1 and Jaguar-2 USB chips, a slice of TODO T4. The chip radiates a clean CW carrier at the DEVOURER_CHANNEL center frequency with no packets or modulation — a controllable narrowband interferer / MP tone source (e.g. for the beamforming-sounding reciprocity work that needs a <=1 MHz on-channel tone a wideband AP can't provide). Interface (WiFiDriverTxDemo): DEVOURER_CW_TONE=1 arms the tone at the end of InitWrite and idle-holds until SIGINT, then restores the chip; DEVOURER_CW_TONE_ GAIN=0..31 sets the RF gain index (RF 0x00[4:0]). Programmatic API: RtlJaguarDevice / RtlJaguar2Device StartCwTone(gain) / StopCwTone(), each snapshotting the pre-tone RF/BB state and restoring it on stop (plus a destructor safety net). Per-chip recipes, ported from the vendor MP source and SDR-validated on a USRP B210 (single carrier at center, carrier-to-spur, monotonic power vs gain, clean stop + normal TX resume, frequency drift): - 8812AU / 8821AU (hal_mpt_SetSingleToneTx JAGUAR branch): OFDM/CCK modulators off + RFE pinmux forced to TX (+ ext-PA pins). Validated: 8812AU ch6 & ch36, 8821AU ch6 — carrier-to-spur 44-52 dB. - 8814AU (mpt_SetSingleTone_8814A): CCA off + per-path TX-scale zero. Validated ch6 — the tightest drift of the family. - 8822BU (hal_mpt_SetSingleToneTx 8822B branch): OFDM/CCK off + RFE pinmux + RFE-inverse. Validated ch6 (weaker/less-pure tone than the Jaguar-1 parts). Also fix an unrelated 8812AU cold-init crash surfaced during bring-up: when the EFUSE TX-power PG bytes read back blank (a transient read glitch, not an unprogrammed part), hal_InitPGData_8812A threw a not-implemented stub and core-dumped. Now it retries the EFUSE map read and, if still blank, proceeds with the IC-default PG table (LoadTxPowerInfo's existing per-cell fallback) — matching the kernel driver's autoload-fail behaviour instead of aborting. SDR validation harness: tests/cw_tone_probe.py (B210 Welch-PSD peak/spur/drift) and tests/cw_tone_sdr.sh (per-DUT presence + purity + power sweep + clean stop + drift). Jaguar-3 (8822C/E) single-tone needs the halbb MP-mode framework and is left as a follow-up. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jul 4, 2026
josephnef
added a commit
that referenced
this pull request
Jul 4, 2026
Extends the `DEVOURER_CW_TONE` MP single-tone (bare RF local-oscillator carrier, from #165) to the **Jaguar3** family — RTL8822CU (rtl8822c) and RTL8812EU/8822EU (rtl8822e) — the last USB generation without it. SDR-validated on a USRP B210. Builds on #167 (Jaguar1+Jaguar2) and current master (#169). ## Why Jaguar3 needs a different recipe The halbb/halrf generation needs two things the older chips don't (ported from the vendor `phydm_mp_set_single_tone_jgr3` + `phydm_set_pmac_txon_jgr3`): 1. **RF 0x00 is write-only through the HSSI 3-wire port** (`0x1808`/`0x4108`). The direct BB→RF window (`0x3c00`) is a *read-only shadow* for RF 0x00, so a window write is silently dropped. (RF 0x58 / LO-enable is a normal reg and still uses the window.) 2. **The BB must be held in continuous TX** (`0x1c3c`/`0x1a00`/`0x1ca4` + PMAC/TX-OFDM `0x1d08`/`0x1e70`), or the RF state machine re-drives RF 0x00 back to RX within milliseconds and no carrier comes out. `RtlJaguar3Device::StartCwTone`/`StopCwTone` implement the full recipe (path A, CCA off, serialized on the coex `_reg_mu`); the coex runtime thread isn't started for a tone. ## SDR results | Device | 2.4 GHz | 5 GHz | |---|---|---| | **RTL8822CU** (2T2R) | +38 dBFS, carrier-to-spur **62 dB** | c2s **51–58 dB** | | **RTL8812EU** (BL-M8812EU2, 1T1R, rfe 21) | radiates (weak — **no 2.4 GHz PA**) | radiates, weaker (bare-LO output is low on this module), center carrier, gain-responsive | ## 8812EU 5 GHz bring-up robustness (two fixes) - **DACK/IQK USB-read crash:** the status-poll loops issue tens of thousands of USB control-IN reads; a single glitch made `rtw_read` throw `std::ios_base::failure` and aborted bring-up. Wrapped `dac_calibrate()` + `phy_iq_calibrate()` in a bounded retry (`HalJaguar3::retry_cal`), mirroring `StartRxLoop`'s existing retry. - **Post-bring-up read NAK:** on the 8812EU at 5 GHz the FW power-mode/coex H2C steps and the `GPIO_MUXCFG` RFE-pin write leave the chip NAKing control-IN reads, so `StartCwTone`'s BB reads failed. For a CW tone, arm *early* (after the channel/RFE config, before those steps) and return — a bare tone needs no per-rate power/coex/FW-coex. The 5 GHz PA still needs its RFE-enable pins driven, so snapshot `0x40`/`0x64`, arm, then **blind-write** the PA pins (the read-breaking write happens last). The plain (non-CW) TX path is unchanged. ## Scope / notes - `tests/cw_tone_sdr.sh` gains `8822cu`/`8822eu` cells. - 8822CU regression-checked after the restructure: still +38 dBFS. - The 8812EU intermittently drops control-IN under *rapid repeated* ch36 bring-ups (a device-USB trait); single clean launches work. Closes the Jaguar3 follow-up noted in #165. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.
Implements the CW single-tone / bare RF-carrier emit mode requested in #165 for the Jaguar-1 and Jaguar-2 USB chips (a slice of TODO T4). The chip radiates a clean local-oscillator carrier at the
DEVOURER_CHANNELcenter frequency — no packets, no modulation — as a controllable narrowband interferer / MP tone source.Interface
DEVOURER_CW_TONE=1(WiFiDriverTxDemo) — arm the tone at the end ofInitWrite, idle-hold until SIGINT, then restore the chip.DEVOURER_CW_TONE_GAIN=0..31— RF gain index (RF 0x00[4:0], default 0).RtlJaguarDevice/RtlJaguar2DeviceStartCwTone(gain)/StopCwTone()— each snapshots and restores the pre-tone RF/BB state (plus a destructor safety net).Per-chip recipes (ported from vendor MP source, SDR-validated on a USRP B210)
Each was checked for: single carrier at center, spectral purity (carrier-to-spur), monotonic power vs gain, clean stop (carrier gone + normal beacon TX resumes), and frequency drift.
Drive-by fix: 8812AU cold-init EFUSE crash
Surfaced during bring-up: when the 8812AU's EFUSE TX-power PG bytes read back blank (a transient read glitch, not an unprogrammed part),
hal_InitPGData_8812Athrew a not-implemented stub (Hal_readPGDataFromConfigFile) and core-dumped every launch (reproduced with a plain non-CW run). Now it retries the EFUSE map read and, if still blank, proceeds with the IC-default PG table —LoadTxPowerInfo's existing per-cell fallback — matching the kernel driver's autoload-fail behaviour instead of aborting.SDR validation harness
tests/cw_tone_probe.py— B210 (gr-uhd) Welch-PSD probe: peak offset, carrier-to-spur, power, drift.tests/cw_tone_sdr.sh— per-DUT orchestrator: presence + purity + gain sweep + clean-stop + drift.Scope
Jaguar-3 (8822C/8822E) single-tone needs the halbb MP-mode framework (a direct RF-mode write doesn't stick without the full
mp_startreconfiguration) and is left as a follow-up.🤖 Generated with Claude Code