Skip to content

TX power: generalize SetTxPowerRateDiffs (per-rate power diff table) beyond the 8822E to J1/J2/J3(/Kestrel) #332

Description

@josephnef

Summary

Generalize the caller-supplied per-rate TX-power diff table (SetTxPowerRateDiffs) from the 8822E-only implementation to the other supported generations (Jaguar1, Jaguar2, Jaguar3-8822C, and ideally Kestrel). This is Realtek's "dynamic power by rate" lever — an efuse-shaped per-rate/per-path power offset (TxPwrByRateOffset[band][path][rate], PHY_GetTxPowerByRate* in the vendor hal_com_phycfg.c) — and it is the range-relevant power knob for a fixed-rate FPV link.

Motivation

  • The link-relevant use is boosting CCK / low-MCS power (or trimming high-MCS) for range and PA headroom, independent of the descriptor rate — the natural companion to devourer's fixed-rate injection.
  • The mechanism is already implemented and validated for the 8822E (SetTxPowerRateDiffs(TxRateDiffsQdb), examples/txpower/ --rate-diffs, register-checked by tests/txpwr_rate_diffs_regcheck.sh). Every other generation's SetTxPowerRateDiffs currently just returns false, which is an artificial capability gap — the underlying per-rate power table exists on all Jaguar chips.

Current state

  • 8822E (reference impl): a caller table (cck, legacy, mcs0..7, signed qdB) replaces the default phy_reg_pg per-rate walk, folded on top of the active reference (efuse table or flat override). Sticks across SetMonitorChannel, FastRetune, and override set/clear. std::nullopt restores the default walk. See src/TxPower.h, the 8822E HAL, and docs/CLAUDE.md.
  • All other generations: SetTxPowerRateDiffs returns false (no-op). But the vendor per-rate power table (TxPwrByRate, phy_reg_pg) is a Jaguar-family-wide construct — the fold point exists; only the caller-override hook is missing.

Proposed work

  1. Lift the fold seam to the shared TX-power path. Factor the 8822E's "caller diff table replaces the default per-rate walk" logic into the generation-neutral src/TxPower.* layer so each HAL only supplies its per-rate walk + register-write primitive. Preserve the exact stickiness contract (channel switch, FastRetune, override set/clear re-apply, nullopt = restore default).
  2. Per-generation wiring:
    • Jaguar2 (8822B/8821C): TXAGC block is write-only → software shadow (hw_readback=false), matching the existing 8822E/Jaguar2 power-state reporting.
    • Jaguar1 (8812A/8821A/8814A): fold into the BB-swing / packed-port path; the 8814A packed port is write-only (shadow only).
    • Jaguar3-8822C: shares the 8822E family fold; should be near-free.
    • Kestrel: map onto the fixed-dBm BB target rewrite if it fits; otherwise explicitly out of scope for v1.
    • Family step preserved via GetTxPowerCaps (0.5 dB J1/J2, 0.25 dB J3).
  3. Extend the reference consumer + regression: examples/txpower/ --rate-diffs cck,legacy,m0..m7|clear already exists — make it work on the newly-wired chips; extend tests/txpwr_rate_diffs_regcheck.sh to cover each generation (register/shadow validation).
  4. Caps: advertise support per generation (a per_rate_txpwr_diffs flag or by making the API return true only where wired).

Validation

  • tests/txpwr_rate_diffs_regcheck.sh per generation (register-level or shadow, matching each chip's readback capability).
  • One on-air confirmation per newly-wired chip that a CCK/low-MCS boost actually raises radiated power (SDR / tests/txpkt_pwr_ofset_onair.sh style), since the diff table folds on top of the efuse reference.

Scope / caveats

  • Preserve byte-identical behaviour for the 8822E path (it is on-air + register validated).
  • Keep the neutral library env-free — this stays a construction/runtime setter, driven by the demo env mapping as today.
  • Kestrel may be deferred if its fixed-dBm model doesn't map cleanly onto a per-rate diff table.

🤖 Filed with Claude Code after a code + vendor-reference investigation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions