fix(radio): make limitPower() idempotent so chip re-inits don't compound PA gain subtraction - #11782
Conversation
…und PA gain subtraction limitPower() converts the member `power` in place (regulatory clamp, then the TX_GAIN_LORA/FEM subtraction) and relied on applyModemConfig() having just re-seeded it. Since meshtastic#10025 every driver calls it from both reinitChip() and programModemParams(), and the recovery paths added in meshtastic#11676/meshtastic#11678 run the two back-to-back, so each recovery re-converts an already-converted value. On a RAK13302 (22-entry gain table) one recovery walks a 30 dBm request 30 -> 22 -> 13 dBm and a second one down toward the -9 dBm floor, while config.lora.tx_power still reads 30. Seed `power` from config.lora.tx_power at the top of limitPower(); applyModemConfig() always writes the resolved value back there, so a single call is unchanged.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review. 📝 WalkthroughWalkthrough
ChangesPower limiting
Priority: ⬇️ Low Estimated code review effort: 1 (Trivial) | ~2 minutes Merge Risk: ⚪ Minimal · up to Radio recovery now consistently recalculates transmit power from the configured value before applying limits, preventing power from decreasing across repeated recoveries. The reported recovery and target-build checks support merge readiness. Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Integrate meshtastic/firmware meshtastic#11732 (73c4110), meshtastic#11780 (3829806), and meshtastic#11782 (42d32fc). Preserve the Superbase runtime Bluetooth, navigation, notification, GPS and radio customizations. Add PhoneAPI config-dump regressions to the mandatory native suite and pin the reviewed integration with normalized source hashes. Validation before commit: Muzi build, source preservation audit, Trunk formatting and production-body nRF52 Bluetooth sanitizer checks passed. Full native CI runs on this commit.
What
limitPower()converts the memberpowerin place (regulatory clamp, then theTX_GAIN_LORA/ FEM PA-gain subtraction). Re-seedpowerfromconfig.lora.tx_powerat the top so a second call yields the same result as the first.Why
limitPower()assumedapplyModemConfig()had just re-seededpower. Since #10025 (fixing #10022) every driver calls it from bothreinitChip()andprogramModemParams(), and the chip-state recovery paths from #11676 / #11678 run those two back-to-back - so each recovery converts an already-converted value. With RAK13302's 22-entry gain table one recovery walks a 30 dBm request 30 -> 22 -> 13 dBm at the chip and a second heads for the -9 dBm floor, whileconfig.lora.tx_powerstill reads 30: the node silently transmits at a fraction of its configured power. Likely the mechanism behind #10979 / #11089 once a recovery has occurred (unverified on those exact setups).Captured on RAK3401 + RAK13302 before the fix, one recovery:
How it works
applyModemConfig()resolves regional/licensed limits and writes the result back toconfig.lora.tx_power, so it is the right value to re-derive from. A singlelimitPower()call is unchanged; only later calls in a re-init sequence change. Audited every caller (SX126x, LR11x0, RF95, LR20x0): none adjustspowerbefore callinglimitPower(), so the re-seed clobbers nothing. LR11x0'srecoverChipStateLoss()has the identical double-call shape, so this fixes it there too.What it changes
One line in
RadioInterface::limitPower()plus its docstring. No API, config or wire-format change. Normal path unchanged; the recovery path on every FEM/PA board is fixed.Testing
RAK3401 + RAK13302 (nRF52840) on
developwith this commit, live mesh, 5.2 h: 5 chip-state-loss recoveries via #11678, each runningreinitChip()thenprogramModemParams(). BothlimitPower()calls read 30 -> 22 dBm every time (Final Tx power: 22x10, never 13 or 4), and each re-init succeeded with the queued packet sent. Compile-verified forrak3401-1watt.🤝 Attestations
Tested on RAK WisBlock RAK3401 + RAK13302 (1 W, nRF52840). Regression testing on other FEM/PA boards (Heltec V4, E22-based modules, LR11x0) is welcome.
🤖 Generated with Claude Code
Summary by CodeRabbit