Skip to content

Jaguar1 + Jaguar2 CW single-tone (DEVOURER_CW_TONE) — SDR-validated#167

Merged
josephnef merged 1 commit into
masterfrom
jaguar12-cw-single-tone
Jul 4, 2026
Merged

Jaguar1 + Jaguar2 CW single-tone (DEVOURER_CW_TONE) — SDR-validated#167
josephnef merged 1 commit into
masterfrom
jaguar12-cw-single-tone

Conversation

@josephnef

Copy link
Copy Markdown
Collaborator

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_CHANNEL center 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 of InitWrite, idle-hold until SIGINT, then restore the chip.
  • DEVOURER_CW_TONE_GAIN=0..31 — RF gain index (RF 0x00[4:0], default 0).
  • Programmatic: RtlJaguarDevice / RtlJaguar2Device StartCwTone(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)

Chip Recipe Validation (ch6 @ 2437 MHz unless noted)
8812AU / 8821AU OFDM/CCK off + RFE pinmux → TX (+ ext-PA pins) carrier-to-spur 44–52 dB, monotonic power, clean stop + TX resume. 8812AU also ch36 (5 GHz).
8814AU CCA off + per-path TX-scale zero tightest drift of the family (span ~5 kHz/60 s).
8822BU OFDM/CCK off + RFE pinmux + RFE-inverse correct freq, gain-tunable, clean stop + TX resume (weaker/less-pure tone than the Jaguar-1 parts).

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_8812A threw 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_start reconfiguration) and is left as a follow-up.

🤖 Generated with Claude Code

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>
@josephnef josephnef merged commit 7a7ab38 into master Jul 4, 2026
13 checks passed
@josephnef josephnef deleted the jaguar12-cw-single-tone branch July 4, 2026 18:52
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>
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