diff --git a/build-iotthinks.sh b/build-iotthinks.sh index 42a897c8..fc8be31a 100644 --- a/build-iotthinks.sh +++ b/build-iotthinks.sh @@ -1,49 +1,52 @@ #!/usr/bin/env bash # ./build-iotthinks.sh -export FIRMWARE_VERSION="PowerSaving16" +export FIRMWARE_VERSION="PowerSaving17" ############# Repeaters ############# # Commonly-used boards ## ESP32 - 17 boards ./build.sh build-firmware \ +Heltec_ct62_repeater \ +Heltec_E290_repeater \ Heltec_v3_repeater \ -Heltec_WSL3_repeater \ heltec_v4_repeater \ +heltec_tracker_v2_repeater \ +Heltec_Wireless_Paper_repeater \ +Heltec_Wireless_Tracker_repeater \ +Heltec_WSL3_repeater \ +LilyGo_T3S3_sx1262_repeater \ +LilyGo_TBeam_1W_repeater \ Station_G2_repeater \ T_Beam_S3_Supreme_SX1262_repeater \ Tbeam_SX1262_repeater \ -LilyGo_T3S3_sx1262_repeater \ -Xiao_S3_WIO_repeater \ Xiao_C3_repeater \ Xiao_C6_repeater_ \ -Heltec_E290_repeater \ -Heltec_Wireless_Tracker_repeater \ -LilyGo_TBeam_1W_repeater \ Xiao_S3_repeater \ -heltec_tracker_v2_repeater \ -Heltec_Wireless_Paper_repeater \ -Heltec_ct62_repeater +Xiao_S3_WIO_repeater -## NRF52 - 17 boards +## NRF52 - 21 boards ./build.sh build-firmware \ -RAK_4631_repeater \ -Heltec_t114_repeater \ -Xiao_nrf52_repeater \ -Heltec_mesh_solar_repeater \ -ProMicro_repeater \ -SenseCap_Solar_repeater \ -t1000e_repeater \ -LilyGo_T-Echo_repeater \ -WioTrackerL1_repeater \ -RAK_3401_repeater \ -RAK_WisMesh_Tag_repeater \ GAT562_30S_Mesh_Kit_repeater \ GAT562_Mesh_Tracker_Pro_repeater \ +Heltec_mesh_solar_repeater \ +Heltec_t096_repeater \ +Heltec_t1_repeater \ +Heltec_t114_repeater \ ikoka_nano_nrf_22dbm_repeater \ ikoka_nano_nrf_30dbm_repeater \ ikoka_nano_nrf_33dbm_repeater \ +LilyGo_T-Echo_repeater \ +ProMicro_repeater \ +RAK_3401_repeater \ +RAK_4631_repeater \ +RAK_WisMesh_Tag_repeater \ +SenseCap_Solar_repeater \ +t1000e_repeater \ ThinkNode_M1_repeater \ -Heltec_t096_repeater +ThinkNode_M3_repeater \ +ThinkNode_M6_repeater \ +WioTrackerL1_repeater \ +Xiao_nrf52_repeater ## ESP32, SX1276 - 3 boards ./build.sh build-firmware \ @@ -56,64 +59,65 @@ Tbeam_SX1276_repeater ./build.sh build-firmware \ Heltec_v3_room_server \ heltec_v4_room_server \ -LilyGo_TBeam_1W_room_server \ -Heltec_WSL3_room_server \ -Xiao_S3_room_server \ heltec_tracker_v2_room_server \ -Heltec_Wireless_Paper_room_server +Heltec_Wireless_Paper_room_server \ +Heltec_WSL3_room_server \ +LilyGo_TBeam_1W_room_server \ +Xiao_S3_room_server -# NRF52 - 6 boards +# NRF52 - 7 boards ./build.sh build-firmware \ -RAK_4631_room_server \ +Heltec_t096_room_server \ Heltec_t114_room_server \ -Xiao_nrf52_room_server \ +RAK_3401_room_server \ +RAK_4631_room_server \ t1000e_room_server \ WioTrackerL1_room_server \ -RAK_3401_room_server \ -Heltec_t096_room_server +Xiao_nrf52_room_server ############# Companions BLE ############# -# NRF52 - 12 boards +# NRF52 - 15 boards ./build.sh build-firmware \ -RAK_4631_companion_radio_ble \ +Heltec_t096_companion_radio_ble_femon \ +Heltec_t096_companion_radio_ble_femoff \ +Heltec_t1_companion_radio_ble \ Heltec_t114_companion_radio_ble \ -Xiao_nrf52_companion_radio_ble \ -t1000e_companion_radio_ble \ LilyGo_T-Echo_companion_radio_ble \ -WioTrackerL1_companion_radio_ble \ RAK_3401_companion_radio_ble \ +RAK_4631_companion_radio_ble \ RAK_WisMesh_Tag_companion_radio_ble \ SenseCap_Solar_companion_radio_ble \ +t1000e_companion_radio_ble \ ThinkNode_M1_companion_radio_ble \ -Heltec_t096_companion_radio_ble_femon \ -Heltec_t096_companion_radio_ble_femoff +ThinkNode_M3_companion_radio_ble \ +ThinkNode_M6_companion_radio_ble \ +WioTrackerL1_companion_radio_ble \ +Xiao_nrf52_companion_radio_ble ############# Companions BLE PS ############# -# ESP32 - 20 builds +# ESP32 - 21 builds ./build.sh build-firmware \ -Heltec_v3_companion_radio_ble_ps \ -heltec_v4_companion_radio_ble_femon \ -heltec_v4_3_companion_radio_ble_femoff \ -Xiao_C3_companion_radio_ble_ps \ -Xiao_S3_companion_radio_ble_ps \ -Xiao_S3_WIO_companion_radio_ble_ps \ -Heltec_v2_companion_radio_ble_ps \ -LilyGo_TBeam_1W_companion_radio_ble_ps \ -Heltec_WSL3_companion_radio_ble_ps \ -Heltec_Wireless_Tracker_companion_radio_ble_ps \ +Heltec_ct62_companion_radio_ble_ps \ heltec_tracker_v2_companion_radio_ble_femon \ heltec_tracker_v2_companion_radio_ble_femoff \ -Heltec_Wireless_Paper_companion_radio_ble_ps \ -LilyGo_TLora_V2_1_1_6_companion_radio_ble_ps \ -Heltec_ct62_companion_radio_ble_ps \ -T_Beam_S3_Supreme_SX1262_companion_radio_ble_ps \ -Tbeam_SX1262_companion_radio_ble_ps \ +Heltec_v2_companion_radio_ble_ps \ +Heltec_v3_companion_radio_ble_ps \ +heltec_v4_3_companion_radio_ble_femoff \ +heltec_v4_companion_radio_ble_femon \ heltec_v4_expansionkit_tft_companion_radio_ble_femon \ heltec_v4_3_expansionkit_tft_companion_radio_ble_femoff \ -LilyGo_T3S3_sx1262_companion_radio_ble_ps - -# Not working -# Tbeam_SX1276_companion_radio_ble_ps +Heltec_Wireless_Paper_companion_radio_ble_ps \ +Heltec_Wireless_Tracker_companion_radio_ble_ps \ +Heltec_WSL3_companion_radio_ble_ps \ +LilyGo_T3S3_sx1262_companion_radio_ble_ps \ +LilyGo_TBeam_1W_companion_radio_ble_ps \ +LilyGo_TLora_V2_1_1_6_companion_radio_ble_ps \ +T_Beam_S3_Supreme_SX1262_companion_radio_ble_ps \ +Tbeam_SX1262_companion_radio_ble_ps \ +Tbeam_SX1276_companion_radio_ble_ps \ +Xiao_C3_companion_radio_ble_ps \ +Xiao_S3_companion_radio_ble_ps \ +Xiao_S3_WIO_companion_radio_ble_ps ############# Companions USB ############# ./build.sh build-firmware \ @@ -123,17 +127,17 @@ Heltec_t096_companion_radio_usb_femoff ############# Sample builds ############# # 14 boards ./build.sh build-firmware \ -Heltec_v3_repeater \ -heltec_v4_repeater \ -Xiao_C3_repeater \ -Xiao_C6_repeater_ \ -RAK_4631_repeater \ +Heltec_t096_companion_radio_ble_femon \ +Heltec_t096_companion_radio_ble_femoff \ Heltec_t096_repeater \ Heltec_v3_companion_radio_ble_ps \ -heltec_v4_companion_radio_ble_femon \ +Heltec_v3_repeater \ heltec_v4_3_companion_radio_ble_femoff \ -Xiao_C3_companion_radio_ble_ps \ -Xiao_C6_companion_radio_ble_ \ +heltec_v4_companion_radio_ble_femon \ +heltec_v4_repeater \ RAK_4631_companion_radio_ble \ -Heltec_t096_companion_radio_ble_femon \ -Heltec_t096_companion_radio_ble_femoff +RAK_4631_repeater \ +Xiao_C3_companion_radio_ble_ps \ +Xiao_C3_repeater \ +Xiao_C6_companion_radio_ble_ \ +Xiao_C6_repeater_ diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index a0cf3e56..3dbbe416 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -2,6 +2,7 @@ #include // needed for PlatformIO #include +#include "helpers/radiolib/RXPowerSaving.h" #if defined(WITH_MQTT_BRIDGE) && defined(ESP32_PLATFORM) && defined(WIFI_SSID) #include @@ -22,16 +23,6 @@ static uint32_t nextRadioApplyRetryDelay(uint8_t& failure_count) { static const uint32_t COMMAND_RADIO_APPLY_TIMEOUT_MS = 5000UL; -#ifndef RXPS_FIXED_ENABLED -#define RXPS_FIXED_ENABLED 0 -#endif -#ifndef RXPS_FIXED_LEVEL -#define RXPS_FIXED_LEVEL 2 -#endif -#ifndef RXPS_FIXED_PREAMBLE -#define RXPS_FIXED_PREAMBLE 16 -#endif - #if RXPS_FIXED_ENABLED #if RXPS_FIXED_LEVEL < 1 || RXPS_FIXED_LEVEL > 10 #error "RXPS_FIXED_LEVEL must be between 1 and 10" @@ -353,36 +344,10 @@ int MyMesh::getInterferenceThreshold() const { } #if RXPS_FIXED_ENABLED -static uint32_t ceilPositiveFloat(float value) { - uint32_t rounded = (uint32_t)value; - return value > (float)rounded ? rounded + 1 : rounded; -} - -static bool calcFixedRxPowerSaving(uint8_t sf, float bw, uint32_t* rx_us, uint32_t* sleep_us) { - if (RXPS_FIXED_LEVEL < 1 || RXPS_FIXED_LEVEL > 10 || sf < 5 || sf > 12 || - bw <= 0.0f || (RXPS_FIXED_PREAMBLE != 16 && RXPS_FIXED_PREAMBLE != 32)) { - return false; - } - - const float symbol_us = (1000.0f * (float)(1UL << sf)) / bw; - const float amount = (float)(RXPS_FIXED_LEVEL - 1) / 9.0f; - const float rx_start_symbols = RXPS_FIXED_PREAMBLE == 16 ? 12.0f : 16.0f; - const float sleep_start_symbols = RXPS_FIXED_PREAMBLE == 16 ? 2.0f : 15.0f; - const float rx_edge_symbols = 8.0f; - const float sleep_edge_symbols = (float)RXPS_FIXED_PREAMBLE + 4.25f - 8.0f; - - const float rx_symbols = rx_start_symbols + amount * (rx_edge_symbols - rx_start_symbols); - const float sleep_symbols = sleep_start_symbols + amount * (sleep_edge_symbols - sleep_start_symbols); - - *rx_us = ceilPositiveFloat(rx_symbols * symbol_us); - *sleep_us = (uint32_t)(sleep_symbols * symbol_us); - return true; -} - static mesh::RadioParamApplyResult applyFixedRadioParams(float freq, float bw, uint8_t sf, uint8_t cr) { uint32_t rx_us, sleep_us; - if (!calcFixedRxPowerSaving(sf, bw, &rx_us, &sleep_us)) { - MESH_DEBUG_PRINTLN("RX Power Saving fixed profile invalid"); + if (!calcRxPowerSavingLevel(RXPS_FIXED_LEVEL, sf, bw, RXPS_FIXED_PREAMBLE, &rx_us, &sleep_us)) { + POWERSAVING_DEBUG_PRINTLN("RX Power Saving fixed profile invalid"); return mesh::RadioParamApplyResult::FAILED; } @@ -394,14 +359,13 @@ static mesh::RadioParamApplyResult applyFixedRadioParams(float freq, float bw, u // transition on radios that do support it. mesh::RadioParamApplyResult result = radio_driver.trySetParams(freq, bw, sf, cr, supports_rxps ? timings : NULL); - MESH_DEBUG_PRINTLN("RX Power Saving fixed level %d p%d: %s (%lu/%lu us)", - RXPS_FIXED_LEVEL, - RXPS_FIXED_PREAMBLE, - result == mesh::RadioParamApplyResult::APPLIED - ? (supports_rxps ? "Enabled" : "Unsupported") - : (result == mesh::RadioParamApplyResult::BUSY ? "Busy" : "Apply failed"), - (unsigned long)rx_us, - (unsigned long)sleep_us); + POWERSAVING_DEBUG_PRINTLN( + "RX Power Saving fixed level %d p%d: %s (%lu/%lu us)", RXPS_FIXED_LEVEL, + RXPS_FIXED_PREAMBLE, + result == mesh::RadioParamApplyResult::APPLIED + ? (supports_rxps ? "Enabled" : "Unsupported") + : (result == mesh::RadioParamApplyResult::BUSY ? "Busy" : "Apply failed"), + (unsigned long)rx_us, (unsigned long)sleep_us); return result; } #endif diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index 26e2df9e..04f851bc 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #ifdef WITH_WEBCONFIG #include diff --git a/examples/simple_room_server/MyMesh.cpp b/examples/simple_room_server/MyMesh.cpp index ee0859be..779b93f9 100644 --- a/examples/simple_room_server/MyMesh.cpp +++ b/examples/simple_room_server/MyMesh.cpp @@ -1,5 +1,6 @@ #include "MyMesh.h" #include +#include #include #include #ifdef WITH_WEBCONFIG diff --git a/examples/simple_sensor/SensorMesh.cpp b/examples/simple_sensor/SensorMesh.cpp index f352c8e8..bc169275 100644 --- a/examples/simple_sensor/SensorMesh.cpp +++ b/examples/simple_sensor/SensorMesh.cpp @@ -1,5 +1,6 @@ #include "SensorMesh.h" #include +#include static uint32_t nextRadioApplyRetryDelay(uint8_t& failure_count) { uint8_t shift = failure_count < 5 ? failure_count : 5; diff --git a/platformio.ini b/platformio.ini index 6dabc57e..47fc9e6b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,14 +13,6 @@ extra_configs = variants/*/platformio.ini platformio.local.ini -[companion_rxps] -custom_rxps_level = 5 -custom_rxps_preamble = 16 -build_flags = - -D RXPS_FIXED_ENABLED=1 - -D RXPS_FIXED_LEVEL=${companion_rxps.custom_rxps_level} - -D RXPS_FIXED_PREAMBLE=${companion_rxps.custom_rxps_preamble} - [arduino_base] framework = arduino monitor_speed = 115200 diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 4c910354..ca816fdc 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -117,6 +117,8 @@ static void formatSdCardBytes(char* out, size_t out_len, uint64_t bytes) { } #endif +#include + // Believe it or not, this std C function is busted on some platforms! static uint32_t _atoi(const char* sp) { uint32_t n = 0; @@ -462,78 +464,21 @@ static const char* retryPresetName(uint8_t preset) { } } -static bool isValidRxPowerSavingPeriod(uint32_t us) { - return us >= RX_POWERSAVING_MIN_PERIOD_US && us <= RX_POWERSAVING_MAX_PERIOD_US; -} - -// MeshCore preamble convention used for the RX powersaving timing calculation. -// Must stay in sync with RadioLibWrapper::preambleLengthForSF() (the value the -// radio actually transmits); kept local here because CommonCLI is radio-agnostic. -static uint16_t rxPowerSavingPreambleForSF(uint8_t sf) { - return sf <= 8 ? 32 : 16; -} - -static bool isNumeric(const char* sp) { - if (!sp || !*sp) return false; - while (*sp) { - if (*sp < '0' || *sp > '9') return false; - sp++; - } - return true; -} - -static uint32_t ceilPositiveFloat(float value) { - uint32_t rounded = (uint32_t)value; - return value > (float)rounded ? rounded + 1 : rounded; -} - bool CommonCLI::calculateRxPowerSavingLevel(uint32_t level, uint8_t sf, float bw, uint32_t preamble, uint32_t* rx_us, uint32_t* sleep_us) { - if (level < 1 || level > 10 || sf < 5 || sf > 12 || bw <= 0.0f || (preamble != 16 && preamble != 32)) { + if (level < 1 || level > 10 || (preamble != 16 && preamble != 32)) { return false; } - - const float symbol_us = (1000.0f * (float)(1UL << sf)) / bw; - const float amount = (float)(level - 1) / 9.0f; - const float rx_start_symbols = preamble == 16 ? 12.0f : 16.0f; - const float sleep_start_symbols = preamble == 16 ? 2.0f : 15.0f; - const float rx_edge_symbols = 8.0f; - const float sleep_edge_symbols = (float)preamble + 4.25f - 8.0f; - - const float rx_symbols = rx_start_symbols + amount * (rx_edge_symbols - rx_start_symbols); - const float sleep_symbols = sleep_start_symbols + amount * (sleep_edge_symbols - sleep_start_symbols); - - *rx_us = ceilPositiveFloat(rx_symbols * symbol_us); - *sleep_us = (uint32_t)(sleep_symbols * symbol_us); - return true; -} - -static void ensureRxPowerSavingDefaults(NodePrefs* prefs) { - if (!isValidRxPowerSavingPeriod(prefs->rx_ps_rx_us)) { - prefs->rx_ps_rx_us = RX_POWERSAVING_DEFAULT_RX_US; - } - if (!isValidRxPowerSavingPeriod(prefs->rx_ps_sleep_us)) { - prefs->rx_ps_sleep_us = RX_POWERSAVING_DEFAULT_SLEEP_US; - } + return calcRxPowerSavingLevel((uint8_t)level, sf, bw, (uint8_t)preamble, rx_us, sleep_us); } // Recomputes rx_ps_rx_us/rx_ps_sleep_us from the stored level and the current // radio SF/BW. No-op (returns false) for manual timings (rx_ps_level == 0). // Lets level-based RX powersaving auto-retune when SF/BW change. bool CommonCLI::recalculateRxPowerSavingFromLevel(NodePrefs* prefs) { - if (prefs->rx_ps_level < 1 || prefs->rx_ps_level > 10) return false; // manual: nothing to recompute - uint32_t preamble = prefs->rx_ps_preamble ? prefs->rx_ps_preamble - : rxPowerSavingPreambleForSF(prefs->sf); - uint32_t rx_us, sleep_us; - if (!calculateRxPowerSavingLevel(prefs->rx_ps_level, prefs->sf, prefs->bw, preamble, &rx_us, &sleep_us)) { - return false; - } - if (!isValidRxPowerSavingPeriod(rx_us) || !isValidRxPowerSavingPeriod(sleep_us)) { - return false; - } - prefs->rx_ps_rx_us = rx_us; - prefs->rx_ps_sleep_us = sleep_us; - return true; + return recalcRxPowerSavingFromLevel(prefs->rx_ps_level, prefs->sf, prefs->bw, + prefs->rx_ps_preamble, &prefs->rx_ps_rx_us, + &prefs->rx_ps_sleep_us); } static void markDirectRetryPrefsValid(NodePrefs* prefs) { @@ -1524,8 +1469,10 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { if (_prefs->rx_ps_preamble != 16 && _prefs->rx_ps_preamble != 32) { _prefs->rx_ps_preamble = 0; // 0 = auto (derive from SF) } - ensureRxPowerSavingDefaults(_prefs); - recalculateRxPowerSavingFromLevel(_prefs); // retune level-based timings to the loaded SF/BW + ensureRxPowerSavingDefaults(&_prefs->rx_ps_rx_us, &_prefs->rx_ps_sleep_us); + recalcRxPowerSavingFromLevel(_prefs->rx_ps_level, _prefs->sf, _prefs->bw, _prefs->rx_ps_preamble, + &_prefs->rx_ps_rx_us, + &_prefs->rx_ps_sleep_us); // retune level-based timings to the loaded SF/BW file.close(); } @@ -3691,17 +3638,17 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep } else { strcpy(reply, "Error: state must be on or off"); } - } else if (memcmp(config, "radio.rxps ", 11) == 0) { + } else if (memcmp(config, "radio.rxps ", 11) == 0) { // RX PowerSaving const char* value = &config[11]; uint8_t enable = _prefs->rx_powersaving_enabled; uint32_t rx_us = _prefs->rx_ps_rx_us; uint32_t sleep_us = _prefs->rx_ps_sleep_us; - uint32_t level = 0; - uint32_t preamble = rxPowerSavingPreambleForSF(_prefs->sf); + uint8_t level = 0; + uint8_t preamble = rxPowerSavingPreambleForSF(_prefs->sf); bool level_requested = false; bool preamble_overridden = false; - ensureRxPowerSavingDefaults(_prefs); + ensureRxPowerSavingDefaults(&_prefs->rx_ps_rx_us, &_prefs->rx_ps_sleep_us); rx_us = _prefs->rx_ps_rx_us; sleep_us = _prefs->rx_ps_sleep_us; @@ -3810,7 +3757,9 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep _prefs->bw = bw; // Retune level-based RX powersaving to the new SF/BW. Persist only; the // radio itself is "reboot to apply", and begin() re-arms the timings then. - bool rxps_retuned = recalculateRxPowerSavingFromLevel(_prefs); + bool rxps_retuned = recalcRxPowerSavingFromLevel( + _prefs->rx_ps_level, _prefs->sf, _prefs->bw, _prefs->rx_ps_preamble, &_prefs->rx_ps_rx_us, + &_prefs->rx_ps_sleep_us); // retune level-based timings to the loaded SF/BW _callbacks->savePrefs(); strcpy(reply, rxps_retuned ? "OK - reboot to apply (rxps retuned)" : "OK - reboot to apply"); } else { @@ -3884,7 +3833,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep strcpy(reply, "OK"); } else { strcpy(reply, "Error, max 64"); - } + } } else if (memcmp(config, "flood.max.advert ", 17) == 0) { uint8_t m = atoi(&config[17]); if (m <= 64) { @@ -4576,8 +4525,8 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep _callbacks->formatScheduledRadioParams(true, skipSpacesConst(&config[11]), reply); } else if (memcmp(config, "radioat", 7) == 0 && (config[7] == 0 || config[7] == ' ')) { _callbacks->formatScheduledRadioParams(false, skipSpacesConst(&config[7]), reply); - } else if (memcmp(config, "radio.rxps", 10) == 0) { - ensureRxPowerSavingDefaults(_prefs); + } else if (memcmp(config, "radio.rxps", 10) == 0) { // RX PowerSaving + ensureRxPowerSavingDefaults(&_prefs->rx_ps_rx_us, &_prefs->rx_ps_sleep_us); sprintf(reply, "> %s,%lu,%lu", _prefs->rx_powersaving_enabled ? "on" : "off", (unsigned long)_prefs->rx_ps_rx_us, (unsigned long)_prefs->rx_ps_sleep_us); } else if (memcmp(config, "rxps.wd", 7) == 0) { diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index 4e8cacd4..836f671f 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -112,18 +112,6 @@ #define TELEMETRY_ACCESS_ALL 0 #define TELEMETRY_ACCESS_ACL 1 -#define RX_POWERSAVING_DEFAULT_RX_US 65625UL -#define RX_POWERSAVING_DEFAULT_SLEEP_US 60000UL -#define RX_POWERSAVING_MIN_PERIOD_US 1000UL -#define RX_POWERSAVING_MAX_PERIOD_US 30000000UL - -// The named profiles are level presets pinned to a 16-symbol preamble: most -// deployed senders still transmit 16-symbol preambles regardless of the newer -// SF-based rule (32 for SF <= 8). Revisit once the field has largely migrated. -#define RX_POWERSAVING_CONSERVATIVE_LEVEL 1UL -#define RX_POWERSAVING_BALANCED_LEVEL 5UL -#define RX_POWERSAVING_PROFILE_PREAMBLE 16UL - struct NodePrefs { // persisted to file float airtime_factor; char node_name[32]; diff --git a/src/helpers/radiolib/RXPowerSaving.h b/src/helpers/radiolib/RXPowerSaving.h new file mode 100644 index 00000000..afe50767 --- /dev/null +++ b/src/helpers/radiolib/RXPowerSaving.h @@ -0,0 +1,109 @@ +#pragma once +#include + +#define RX_POWERSAVING_DEFAULT_RX_US 65625UL +#define RX_POWERSAVING_DEFAULT_SLEEP_US 60000UL +#define RX_POWERSAVING_MIN_PERIOD_US 1000UL +#define RX_POWERSAVING_MAX_PERIOD_US 30000000UL + +// The named profiles are level presets pinned to a 16-symbol preamble: most +// deployed senders still transmit 16-symbol preambles regardless of the newer +// SF-based rule (32 for SF <= 8). Revisit once the field has largely migrated. +#define RX_POWERSAVING_CONSERVATIVE_LEVEL 1 +#define RX_POWERSAVING_BALANCED_LEVEL 5 +#define RX_POWERSAVING_PROFILE_PREAMBLE 16 + +// Fixed settings for companions. Build flags can still override these defaults. +#ifndef RXPS_FIXED_ENABLED +#define RXPS_FIXED_ENABLED 1 +#endif +#ifndef RXPS_FIXED_LEVEL +#define RXPS_FIXED_LEVEL RX_POWERSAVING_BALANCED_LEVEL +#endif +#ifndef RXPS_FIXED_PREAMBLE +#define RXPS_FIXED_PREAMBLE RX_POWERSAVING_PROFILE_PREAMBLE +#endif + +inline bool isValidRxPowerSavingPeriod(uint32_t us) { + return us >= RX_POWERSAVING_MIN_PERIOD_US && us <= RX_POWERSAVING_MAX_PERIOD_US; +} + +// MeshCore preamble convention used for the RX powersaving timing calculation. +// Must stay in sync with RadioLibWrapper::preambleLengthForSF() (the value the +// radio actually transmits); kept local here because CommonCLI is radio-agnostic. +inline uint8_t rxPowerSavingPreambleForSF(uint8_t sf) { + return sf <= 8 ? 32 : 16; +} + +inline bool isNumeric(const char *sp) { + if (!sp || !*sp) return false; + while (*sp) { + if (*sp < '0' || *sp > '9') return false; + sp++; + } + return true; +} + +inline uint32_t ceilPositiveFloat(float value) { + uint32_t rounded = (uint32_t)value; + return value > (float)rounded ? rounded + 1 : rounded; +} + +inline bool calcRxPowerSavingLevel(uint8_t level, uint8_t sf, float bw, uint8_t preamble, uint32_t *rx_us, + uint32_t *sleep_us) { + if (level < 1 || level > 10 || sf < 5 || sf > 12 || bw <= 0.0f || (preamble != 16 && preamble != 32)) { + return false; + } + + const float symbol_us = (1000.0f * (float)(1UL << sf)) / bw; + const float amount = (float)(level - 1) / 9.0f; + const float rx_start_symbols = preamble == 16 ? 12.0f : 16.0f; + const float sleep_start_symbols = preamble == 16 ? 2.0f : 15.0f; + const float rx_edge_symbols = 8.0f; + const float sleep_edge_symbols = (float)preamble + 4.25f - 8.0f; + + const float rx_symbols = rx_start_symbols + amount * (rx_edge_symbols - rx_start_symbols); + const float sleep_symbols = sleep_start_symbols + amount * (sleep_edge_symbols - sleep_start_symbols); + + *rx_us = ceilPositiveFloat(rx_symbols * symbol_us); + *sleep_us = (uint32_t)(sleep_symbols * symbol_us); + return true; +} + +inline void ensureRxPowerSavingDefaults(uint32_t *rx_ps_rx_us, uint32_t *rx_ps_sleep_us) { + if (!isValidRxPowerSavingPeriod(*rx_ps_rx_us)) { + *rx_ps_rx_us = RX_POWERSAVING_DEFAULT_RX_US; + } + + if (!isValidRxPowerSavingPeriod(*rx_ps_sleep_us)) { + *rx_ps_sleep_us = RX_POWERSAVING_DEFAULT_SLEEP_US; + } +} + +// Recomputes rx_ps_rx_us/rx_ps_sleep_us from the stored level and the current +// radio SF/BW. No-op (returns false) for manual timings (rx_ps_level == 0). +// Lets level-based RX powersaving auto-retune when SF/BW change. +inline bool recalcRxPowerSavingFromLevel(uint8_t level, uint8_t sf, float bw, uint8_t preamble, + uint32_t *rx_ps_rx_us, uint32_t *rx_ps_sleep_us) { + if (level < 1 || level > 10) { + return false; // manual: nothing to recompute + } + + if (preamble == 0) { + preamble = rxPowerSavingPreambleForSF(sf); + } + + uint32_t rx_us, sleep_us; + if (!calcRxPowerSavingLevel(level, sf, bw, preamble, &rx_us, &sleep_us)) { + return false; + } + + if (!isValidRxPowerSavingPeriod(rx_us) || !isValidRxPowerSavingPeriod(sleep_us)) { + return false; + } + + *rx_ps_rx_us = rx_us; + *rx_ps_sleep_us = sleep_us; + + return true; +} diff --git a/src/helpers/radiolib/RadioLibWrappers.cpp b/src/helpers/radiolib/RadioLibWrappers.cpp index ac8eae03..7607a7c8 100644 --- a/src/helpers/radiolib/RadioLibWrappers.cpp +++ b/src/helpers/radiolib/RadioLibWrappers.cpp @@ -536,6 +536,7 @@ bool RadioLibWrapper::isInRecvMode() const { return (state & ~STATE_INT_READY) == STATE_RX; } +// RX PowerSaving bool RadioLibWrapper::setRxPowerSaving(bool enabled, uint32_t rx_us, uint32_t sleep_us) { if (enabled && !supportsRxPowerSaving()) { return false; diff --git a/src/helpers/radiolib/RadioLibWrappers.h b/src/helpers/radiolib/RadioLibWrappers.h index b5a2861a..8c912366 100644 --- a/src/helpers/radiolib/RadioLibWrappers.h +++ b/src/helpers/radiolib/RadioLibWrappers.h @@ -6,8 +6,8 @@ // Fallback RX powersaving timings, only used until setRxPowerSaving() is called // (begin() always applies the persisted values). The authoritative defaults live -// in CommonCLI.h as RX_POWERSAVING_DEFAULT_RX_US / _SLEEP_US and are delivered -// via NodePrefs; keep these mirrored. +// in RXPowerSaving.h as RX_POWERSAVING_DEFAULT_RX_US / _SLEEP_US and are +// delivered via NodePrefs; keep these mirrored. #define RX_PS_FALLBACK_RX_US 65625UL #define RX_PS_FALLBACK_SLEEP_US 60000UL diff --git a/variants/heltec_t096/platformio.ini b/variants/heltec_t096/platformio.ini index 256453b7..be803bac 100644 --- a/variants/heltec_t096/platformio.ini +++ b/variants/heltec_t096/platformio.ini @@ -179,7 +179,6 @@ board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld board_upload.maximum_size = 712704 build_flags = ${Heltec_t096.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 @@ -210,7 +209,6 @@ board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld board_upload.maximum_size = 712704 build_flags = ${Heltec_t096.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 diff --git a/variants/heltec_t114/platformio.ini b/variants/heltec_t114/platformio.ini index 7cf8bfda..e9b76884 100644 --- a/variants/heltec_t114/platformio.ini +++ b/variants/heltec_t114/platformio.ini @@ -100,7 +100,6 @@ board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld board_upload.maximum_size = 712704 build_flags = ${Heltec_t114.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D DISPLAY_CLASS=NullDisplayDriver -D MAX_CONTACTS=350 @@ -125,7 +124,6 @@ board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld board_upload.maximum_size = 712704 build_flags = ${Heltec_t114.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D DISPLAY_CLASS=NullDisplayDriver -D MAX_CONTACTS=350 @@ -238,7 +236,6 @@ board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld board_upload.maximum_size = 712704 build_flags = ${Heltec_t114_with_display.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 @@ -263,7 +260,6 @@ board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld board_upload.maximum_size = 712704 build_flags = ${Heltec_t114_with_display.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 diff --git a/variants/heltec_tracker_v2/platformio.ini b/variants/heltec_tracker_v2/platformio.ini index 983afd0d..71e27f51 100644 --- a/variants/heltec_tracker_v2/platformio.ini +++ b/variants/heltec_tracker_v2/platformio.ini @@ -333,7 +333,6 @@ lib_deps = extends = Heltec_tracker_v2 build_flags = ${Heltec_tracker_v2.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 @@ -360,7 +359,6 @@ build_flags = extends = Heltec_tracker_v2 build_flags = ${Heltec_tracker_v2.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 @@ -392,7 +390,6 @@ build_flags = extends = Heltec_tracker_v2 build_flags = ${Heltec_tracker_v2.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 diff --git a/variants/heltec_v4/platformio.ini b/variants/heltec_v4/platformio.ini index c8e0d3c7..0ae12378 100644 --- a/variants/heltec_v4/platformio.ini +++ b/variants/heltec_v4/platformio.ini @@ -425,7 +425,6 @@ lib_deps = extends = heltec_v4_oled build_flags = ${heltec_v4_oled.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 @@ -452,7 +451,6 @@ build_flags = extends = heltec_v4_oled build_flags = ${heltec_v4_oled.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 @@ -483,7 +481,6 @@ build_flags = extends = heltec_v4_oled build_flags = ${heltec_v4_oled.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index 81cd2a2a..d26bee71 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -253,7 +253,6 @@ board_upload.maximum_size = 712704 build_flags = ${rak4631.build_flags} -D RAK4631_COMPANION_FORCE_LDO=1 - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D PIN_USER_BTN=9 -D PIN_USER_BTN_ANA=31 @@ -310,7 +309,6 @@ board_upload.maximum_size = 712704 build_flags = ${rak4631.build_flags} -D RAK4631_COMPANION_FORCE_LDO=1 - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D PIN_USER_BTN=9 -D PIN_USER_BTN_ANA=31 diff --git a/variants/t1000-e/platformio.ini b/variants/t1000-e/platformio.ini index 0c8fb91c..f32e8487 100644 --- a/variants/t1000-e/platformio.ini +++ b/variants/t1000-e/platformio.ini @@ -74,7 +74,6 @@ extends = t1000-e board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld board_upload.maximum_size = 708608 build_flags = ${t1000-e.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-orig -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 @@ -100,7 +99,6 @@ extends = t1000-e board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld board_upload.maximum_size = 708608 build_flags = ${t1000-e.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-orig -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 diff --git a/variants/thinknode_m3/platformio.ini b/variants/thinknode_m3/platformio.ini index 612410a3..f4554da6 100644 --- a/variants/thinknode_m3/platformio.ini +++ b/variants/thinknode_m3/platformio.ini @@ -75,7 +75,6 @@ extends = ThinkNode_M3 board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld board_upload.maximum_size = 708608 build_flags = ${ThinkNode_M3.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-orig -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 @@ -101,7 +100,6 @@ extends = ThinkNode_M3 board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld board_upload.maximum_size = 708608 build_flags = ${ThinkNode_M3.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-orig -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 diff --git a/variants/xiao_nrf52/platformio.ini b/variants/xiao_nrf52/platformio.ini index d6dc8248..2bc42388 100644 --- a/variants/xiao_nrf52/platformio.ini +++ b/variants/xiao_nrf52/platformio.ini @@ -50,7 +50,6 @@ board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld board_upload.maximum_size = 708608 build_flags = ${Xiao_nrf52.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-orig -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 @@ -74,7 +73,6 @@ board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld board_upload.maximum_size = 708608 build_flags = ${Xiao_nrf52.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-orig -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 diff --git a/variants/xiao_s3/platformio.ini b/variants/xiao_s3/platformio.ini index d92f3cf1..f5a12935 100644 --- a/variants/xiao_s3/platformio.ini +++ b/variants/xiao_s3/platformio.ini @@ -94,7 +94,6 @@ lib_deps = extends = Xiao_S3 build_flags = ${Xiao_S3.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 @@ -122,7 +121,6 @@ extends = env:Xiao_S3_companion_radio_ble extends = Xiao_S3 build_flags = ${Xiao_S3.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 diff --git a/variants/xiao_s3_wio/platformio.ini b/variants/xiao_s3_wio/platformio.ini index 98866a29..7194ff2c 100644 --- a/variants/xiao_s3_wio/platformio.ini +++ b/variants/xiao_s3_wio/platformio.ini @@ -204,7 +204,6 @@ lib_deps = extends = Xiao_S3_WIO build_flags = ${Xiao_S3_WIO.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 @@ -228,7 +227,6 @@ lib_deps = extends = Xiao_S3_WIO build_flags = ${Xiao_S3_WIO.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 @@ -256,7 +254,6 @@ extends = env:Xiao_S3_WIO_companion_radio_ble extends = Xiao_S3_WIO build_flags = ${Xiao_S3_WIO.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 @@ -285,7 +282,6 @@ build_src_filter = ${Xiao_S3_WIO.build_src_filter} +<../examples/companion_radio/*.cpp> build_flags = ${Xiao_S3_WIO.build_flags} - ${companion_rxps.build_flags} -I examples/companion_radio/ui-new -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40