Add some lora parameter clamping logic to coalesce to defaults and enforce some bounds (#9808)

This commit is contained in:
Ben Meadors
2026-03-04 07:55:34 -06:00
committed by GitHub
co-authored by GitHub
parent 3972fe1fd0
commit 65bf1630b3
3 changed files with 64 additions and 17 deletions
+18 -5
View File
@@ -66,9 +66,22 @@ class Default
if (numOnlineNodes <= 40) {
return 1.0;
} else {
// Get bandwidth in kHz - convert from code if not using preset
float bwKHz =
config.lora.use_preset ? modemPresetToBwKHz(config.lora.modem_preset, false) : bwCodeToKHz(config.lora.bandwidth);
// Resolve SF and BW from preset or manual config
// When use_preset is true, config.lora.spread_factor and bandwidth may be 0
// because applyModemConfig() sets them on RadioInterface, not on config.lora
float bwKHz;
uint8_t sf;
uint8_t cr;
if (config.lora.use_preset) {
modemPresetToParams(config.lora.modem_preset, false, bwKHz, sf, cr);
} else {
sf = config.lora.spread_factor;
bwKHz = bwCodeToKHz(config.lora.bandwidth);
}
// Guard against invalid values
sf = clampSpreadFactor(sf);
bwKHz = clampBandwidthKHz(bwKHz);
// throttlingFactor = 2^SF / (BW_in_kHz * scaling_divisor)
// With scaling_divisor=100:
@@ -76,11 +89,11 @@ class Default
// In SF10 and BW=250khz (mediumslow), this gives 0.04096 rather than the original 0.04
// In SF9 and BW=250khz (mediumfast), this gives 0.02048 rather than the original 0.02
// In SF7 and BW=250khz (shortfast), this gives 0.00512 rather than the original 0.01
float throttlingFactor = static_cast<float>(pow_of_2(config.lora.spread_factor)) / (bwKHz * 100.0f);
float throttlingFactor = static_cast<float>(pow_of_2(sf)) / (bwKHz * 100.0f);
#if USERPREFS_EVENT_MODE
// If we are in event mode, scale down the throttling factor by 4
throttlingFactor = static_cast<float>(pow_of_2(config.lora.spread_factor)) / (bwKHz * 25.0f);
throttlingFactor = static_cast<float>(pow_of_2(sf)) / (bwKHz * 25.0f);
#endif
// Scaling up traffic based on number of nodes over 40
+39
View File
@@ -24,6 +24,45 @@ extern const RegionInfo *myRegion;
extern void initRegion();
// Valid LoRa spread factor range and defaults
constexpr uint8_t LORA_SF_MIN = 7;
constexpr uint8_t LORA_SF_MAX = 12;
constexpr uint8_t LORA_SF_DEFAULT = 11; // LONG_FAST default
// Valid LoRa coding rate range and default
constexpr uint8_t LORA_CR_MIN = 4;
constexpr uint8_t LORA_CR_MAX = 8;
constexpr uint8_t LORA_CR_DEFAULT = 5; // LONG_FAST default
// Default bandwidth in kHz (LONG_FAST)
constexpr float LORA_BW_DEFAULT_KHZ = 250.0f;
/// Clamp spread factor to the valid LoRa range [7, 12].
/// Out-of-range values (including 0 from unset preset mode) return LORA_SF_DEFAULT.
static inline uint8_t clampSpreadFactor(uint8_t sf)
{
if (sf < LORA_SF_MIN || sf > LORA_SF_MAX)
return LORA_SF_DEFAULT;
return sf;
}
/// Clamp coding rate to the valid LoRa range [4, 8].
/// Out-of-range values return LORA_CR_DEFAULT.
static inline uint8_t clampCodingRate(uint8_t cr)
{
if (cr < LORA_CR_MIN || cr > LORA_CR_MAX)
return LORA_CR_DEFAULT;
return cr;
}
/// Ensure bandwidth is positive. Non-positive values return LORA_BW_DEFAULT_KHZ.
static inline float clampBandwidthKHz(float bwKHz)
{
if (bwKHz <= 0.0f)
return LORA_BW_DEFAULT_KHZ;
return bwKHz;
}
static inline float bwCodeToKHz(uint16_t bwCode)
{
if (bwCode == 31)