feat(RadioInterface): Tx power gain calculation rework (#6796)

- Rename REGULATORY_GAIN_LORA to TX_GAIN_LORA
- Move gain-based Tx power clamping from RadioInterface::applyModemConfig() to RadioInterface::limitPower()
  - User-configured Tx power now matches the Tx power out of the device connector
- Re-order [LoRa Chip]Interface.cpp limitPower() to take place before the final Tx power clamping so we clamp based on the pre-PA Tx power rather than user-configured Tx power

Tested on XIAO BLE variant.

Signed-off-by: Andrew Yong <me@ndoo.sg>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
This commit is contained in:
Andrew Yong 2025-05-25 18:26:31 +07:00 committed by GitHub
parent 9b69c2a9af
commit e29588d2e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 24 additions and 19 deletions

View File

@ -80,10 +80,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Override user saved region, for producing region-locked builds
// #define REGULATORY_LORA_REGIONCODE meshtastic_Config_LoRaConfig_RegionCode_SG_923
// Total system gain in dBm to subtract from Tx power to remain within regulatory ERP limit for non-licensed operators
// This value should be set in variant.h and is PA gain + antenna gain (if system ships with an antenna)
#ifndef REGULATORY_GAIN_LORA
#define REGULATORY_GAIN_LORA 0
// Total system gain in dBm to subtract from Tx power to remain within regulatory and Tx PA limits
// This value should be set in variant.h and is PA gain + antenna gain (if variant has a non-removable antenna)
#ifndef TX_GAIN_LORA
#define TX_GAIN_LORA 0
#endif
// -----------------------------------------------------------------------------

View File

@ -71,6 +71,8 @@ template <typename T> bool LR11x0Interface<T>::init()
RadioLibInterface::init();
limitPower();
if (power > LR1110_MAX_POWER) // Clamp power to maximum defined level
power = LR1110_MAX_POWER;
@ -80,8 +82,6 @@ template <typename T> bool LR11x0Interface<T>::init()
preambleLength = 12; // 12 is the default for operation above 2GHz
}
limitPower();
#ifdef LR11X0_RF_SWITCH_SUBGHZ
pinMode(LR11X0_RF_SWITCH_SUBGHZ, OUTPUT);
digitalWrite(LR11X0_RF_SWITCH_SUBGHZ, getFreq() < 1e9 ? HIGH : LOW);

View File

@ -122,11 +122,11 @@ bool RF95Interface::init()
power = dacDbValues.db;
#endif
limitPower();
if (power > RF95_MAX_POWER) // This chip has lower power limits than some
power = RF95_MAX_POWER;
limitPower();
iface = lora = new RadioLibRF95(&module);
#ifdef RF95_TCXO

View File

@ -528,8 +528,8 @@ void RadioInterface::applyModemConfig()
power = loraConfig.tx_power;
if ((power == 0) || ((power + REGULATORY_GAIN_LORA > myRegion->powerLimit) && !devicestate.owner.is_licensed))
power = myRegion->powerLimit - REGULATORY_GAIN_LORA;
if ((power == 0) || ((power > myRegion->powerLimit) && !devicestate.owner.is_licensed))
power = myRegion->powerLimit;
if (power == 0)
power = 17; // Default to this power level if we don't have a valid regional power limit (powerLimit of myRegion defaults
@ -616,7 +616,12 @@ void RadioInterface::limitPower()
power = maxPower;
}
LOG_INFO("Set radio: final power level=%d", power);
if (TX_GAIN_LORA > 0) {
LOG_INFO("Requested Tx power: %d dBm; Device LoRa Tx gain: %d dB", power, TX_GAIN_LORA);
power -= TX_GAIN_LORA;
}
LOG_INFO("Final Tx power: %d dBm", power);
}
void RadioInterface::deliverToReceiver(meshtastic_MeshPacket *p)

View File

@ -25,11 +25,11 @@ bool STM32WLE5JCInterface::init()
lora.setRfSwitchTable(rfswitch_pins, rfswitch_table);
limitPower();
if (power > STM32WLx_MAX_POWER) // This chip has lower power limits than some
power = STM32WLx_MAX_POWER;
limitPower();
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage);
LOG_INFO("STM32WLx init result %d", res);

View File

@ -69,11 +69,11 @@ template <typename T> bool SX126xInterface<T>::init()
RadioLibInterface::init();
limitPower();
if (power > SX126X_MAX_POWER) // Clamp power to maximum defined level
power = SX126X_MAX_POWER;
limitPower();
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage, useRegulatorLDO);
// \todo Display actual typename of the adapter, not just `SX126x`
LOG_INFO("SX126x init result %d", res);

View File

@ -62,11 +62,11 @@ template <typename T> bool SX128xInterface<T>::init()
RadioLibInterface::init();
limitPower();
if (power > SX128X_MAX_POWER) // This chip has lower power limits than some
power = SX128X_MAX_POWER;
limitPower();
preambleLength = 12; // 12 is the default for this chip, 32 does not RX at all
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength);

View File

@ -145,12 +145,12 @@ static const uint8_t SCK = PIN_SPI_SCK;
#ifdef EBYTE_E22_900M30S
// 10dB PA gain and 30dB rated output; based on measurements from
// https://github.com/S5NC/EBYTE_ESP32-S3/blob/main/E22-900M30S%20power%20output%20testing.txt
#define REGULATORY_GAIN_LORA 7
#define TX_GAIN_LORA 7
#define SX126X_MAX_POWER 22
#endif
#ifdef EBYTE_E22_900M33S
// 25dB PA gain and 33dB rated output; based on TX Power Curve from E22-900M33S_UserManual_EN_v1.0.pdf
#define REGULATORY_GAIN_LORA 25
#define TX_GAIN_LORA 25
#define SX126X_MAX_POWER 8
#endif
#endif