diff --git a/src/mesh/Default.h b/src/mesh/Default.h index 686d0d77c..eda4e2b80 100644 --- a/src/mesh/Default.h +++ b/src/mesh/Default.h @@ -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(pow_of_2(config.lora.spread_factor)) / (bwKHz * 100.0f); + float throttlingFactor = static_cast(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(pow_of_2(config.lora.spread_factor)) / (bwKHz * 25.0f); + throttlingFactor = static_cast(pow_of_2(sf)) / (bwKHz * 25.0f); #endif // Scaling up traffic based on number of nodes over 40 diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index bbb0ee00f..07d956878 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -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) diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 419d2b773..9548f546f 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -23,6 +23,7 @@ #endif #include "Default.h" +#include "MeshRadio.h" #include "TypeConversions.h" #if !MESHTASTIC_EXCLUDE_MQTT @@ -756,20 +757,14 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) LOG_INFO("Set config: LoRa"); config.has_lora = true; - if (validatedLora.coding_rate < 4 || validatedLora.coding_rate > 8) { - LOG_WARN("Invalid coding_rate %d, setting to 5", validatedLora.coding_rate); - validatedLora.coding_rate = 5; + if (validatedLora.coding_rate != clampCodingRate(validatedLora.coding_rate)) { + LOG_WARN("Invalid coding_rate %d, setting to %d", validatedLora.coding_rate, LORA_CR_DEFAULT); + validatedLora.coding_rate = LORA_CR_DEFAULT; } - if (validatedLora.spread_factor < 7 || validatedLora.spread_factor > 12) { - LOG_WARN("Invalid spread_factor %d, setting to 11", validatedLora.spread_factor); - validatedLora.spread_factor = 11; - } - - if (validatedLora.bandwidth == 0) { - int originalBandwidth = validatedLora.bandwidth; - validatedLora.bandwidth = myRegion->wideLora ? 800 : 250; - LOG_WARN("Invalid bandwidth %d, setting to default", originalBandwidth); + if (validatedLora.spread_factor != clampSpreadFactor(validatedLora.spread_factor)) { + LOG_WARN("Invalid spread_factor %d, setting to %d", validatedLora.spread_factor, LORA_SF_DEFAULT); + validatedLora.spread_factor = LORA_SF_DEFAULT; } // If no lora radio parameters change, don't need to reboot