Skip to content

Jaguar2 thermal TX-power tracking (8822B/8821C)#218

Merged
josephnef merged 1 commit into
masterfrom
jaguar2-thermal-tracking
Jul 8, 2026
Merged

Jaguar2 thermal TX-power tracking (8822B/8821C)#218
josephnef merged 1 commit into
masterfrom
jaguar2-thermal-tracking

Conversation

@josephnef

Copy link
Copy Markdown
Collaborator

What

Jaguar2 was the only devourer chip family with no thermal TX-power tracking. HalJaguar2::apply_tx_power programs the efuse-calibrated TXAGC once at bring-up and it never moves again. On a sustained TX session (the OpenIPC long-range video case) the PA heats, gain drops, and on-air power drifts down with nothing correcting it — the droop that Jaguar1 (PowerTracking8812a) and Jaguar3 (Halrf8822c/e::pwr_track) both compensate.

This ports the vendor-faithful MIX_MODE power tracking for both variants.

How

A ~2 s tick (dedicated thread) per chip:

  1. Reads the RF 0x42[15:10] thermal meter, 4-sample rolling average.
  2. delta = |avg − efuse_baseline(0xBA)|, clamped to the table.
  3. Looks up the per-variant / per-band delta-swing table (2.4 GHz + 5 GHz three sub-bands), transcribed from the vendor halhwimg88{22b,21c}_rf.c.
  4. Writes the compensation as the vendor's get_mix_mode_tx_agc_bb_swing_offset_8822b split: coarse steps → TXAGC 0xc94/0xe94, remnant → BB scale 0xc1c/0xe1c via tx_scaling_table_jaguar.
  • 8822B (2T2R): both PA chains driven from the single die thermal sensor (path B's 0x42 reads 0 — its sensor isn't enabled), each with its own swing curve; writes 0xc94[29:25].
  • 8821C (1T1R): path A only; writes 0xc94[6:1].
  • No LCK retrigger — the vendor #if 0s it for these chips.

The thread starts at the end of bring_up, so it covers both Init (RX) and InitWrite (TX-only, the sustained-TX case the RX-only DIG thread never reaches). A new _reg_mu serialises the tick's RF-window read/writes against SetMonitorChannel / FastRetune / the TX-power setters / GetThermalStatus.

Default on. DEVOURER_THERMAL_TRACK=0 disables it; an unprogrammed efuse baseline (0xFF) disables it automatically.

Validation

Build + ctest green (no warnings on the new code). Hardware-tested on a T3U (8822B) and CF-811AC (8821C):

  • Functional soak (both variants, TX-only, max duty): thread starts, meter reads live and rises under heating, swing applied, TX alive, DEVOURER_THERMAL_TRACK=0 fully inert, clean shutdown.
  • Two-adapter on-air (8822B → 8812AU, ch6/1M): 38 rx.txhit of the canonical beacon with tracking live.
  • USRP power measurement at a matched hot state (the definitive proof): tracking ON delivers +3.74 dB more on-air power than OFF, matching the driver-logged swing index of 8 (≈ +4.0 dB expected, 0.5 dB/step) — the compensation reaches the antenna and restores exactly the PA droop that OFF leaves uncorrected.

New regression scripts: tests/jaguar2_thermal_track.sh (functional + off-inert), tests/jaguar2_thermal_track_onair.sh (two-adapter txhit), tests/jaguar2_thermal_track_sdr.py + tests/run_jaguar2_thermal_track_sdr.sh (SDR power proof).

Closes #184.

🤖 Generated with Claude Code

Jaguar2 was the only devourer chip family with no thermal TX-power
tracking: HalJaguar2::apply_tx_power programs the efuse-calibrated TXAGC
once at bring-up and it never moves. On a sustained TX session (the
OpenIPC long-range video case) the PA heats, gain drops, and on-air
power drifts down with nothing correcting it — the droop Jaguar1
(PowerTracking8812a) and Jaguar3 (Halrf8822c/e::pwr_track) both
compensate.

Port the vendor-faithful MIX_MODE power tracking for both variants. A
~2 s tick reads the RF 0x42[15:10] thermal meter (4-sample rolling
average), computes the delta vs the efuse baseline (0xBA), looks up the
per-variant/per-band delta-swing table, and writes the compensation as
the vendor's coarse-TXAGC (0xc94/0xe94) + BB-scale (0xc1c/0xe1c) split
(get_mix_mode_tx_agc_bb_swing_offset_8822b). Both 2.4 and 5 GHz;
8822B is 2T2R (both PA chains driven from the single die sensor, each
with its own swing curve), 8821C is 1T1R (path A, 0xc94[6:1]). No LCK
retrigger — the vendor disables it for these chips.

The tick runs on a dedicated thread started at the end of bring_up so it
covers both Init (RX) and InitWrite (TX-only, the sustained-TX case the
DIG thread never reaches), serialized against the channel set and
TX-power setters by a new _reg_mu (the RF read window must not tear).
Default on; DEVOURER_THERMAL_TRACK=0 disables it, and an unprogrammed
efuse baseline (0xFF) disables it automatically.

Hardware validated on a T3U (8822B) and CF-811AC (8821C):
- functional soak (both variants, TX-only, max duty): thread starts,
  meter reads live and rises under heating, swing applied, TX alive,
  off-inert, clean shutdown.
- two-adapter on-air txhit (8822B -> 8812AU, ch6/1M): canonical beacon
  aired + received with tracking live.
- USRP power measurement at a matched hot state: tracking ON delivers
  +3.74 dB more on-air power than OFF, matching the logged swing index
  of 8 (~+4.0 dB expected) — the compensation reaches the antenna and
  restores the PA droop OFF leaves uncorrected.

Tests: tests/jaguar2_thermal_track.sh (functional + off-inert),
tests/jaguar2_thermal_track_onair.sh (two-adapter txhit),
tests/jaguar2_thermal_track_sdr.py + run_*.sh (SDR power proof).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@josephnef josephnef merged commit d396f58 into master Jul 8, 2026
15 checks passed
@josephnef josephnef deleted the jaguar2-thermal-tracking branch July 8, 2026 12:19
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.

Jaguar2 (8822BU/8821CU): port thermal TX-power tracking — only family with no thermal compensation

1 participant