From 1a9f9329529ec69a312bf76f9790e36c290771bb Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Mon, 15 Dec 2025 20:04:21 -0600 Subject: [PATCH 1/7] Implement Long_Turbo preset --- protobufs | 2 +- src/DisplayFormatters.cpp | 3 +++ src/graphics/draw/MenuHandler.cpp | 12 +++++++----- src/mesh/RadioInterface.cpp | 24 ++++++++++++++++++++--- src/mesh/generated/meshtastic/config.pb.h | 3 ++- 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/protobufs b/protobufs index 1cf2783bdb0..9beb80f1d30 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 1cf2783bdb0735590ccf75d9bc825e233e20032a +Subproject commit 9beb80f1d302f70d05f9c4bc9dd543b8f7bc8796 diff --git a/src/DisplayFormatters.cpp b/src/DisplayFormatters.cpp index 246cf00223f..d88f9fc9fe7 100644 --- a/src/DisplayFormatters.cpp +++ b/src/DisplayFormatters.cpp @@ -31,6 +31,9 @@ const char *DisplayFormatters::getModemPresetDisplayName(meshtastic_Config_LoRaC case meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST: return useShortName ? "LongF" : "LongFast"; break; + case meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO: + return useShortName ? "LongT" : "LongTurbo"; + break; case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE: return useShortName ? "LongM" : "LongMod"; break; diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index 2a7f479b4e4..37e52e8e974 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -197,8 +197,9 @@ void menuHandler::DeviceRolePicker() void menuHandler::RadioPresetPicker() { - static const char *optionsArray[] = {"Back", "LongSlow", "LongModerate", "LongFast", "MediumSlow", - "MediumFast", "ShortSlow", "ShortFast", "ShortTurbo"}; + static const char *optionsArray[] = { + "Back", "LongModerate", "LongFast", "MediumSlow", "MediumFast", "ShortSlow", "ShortFast", "ShortTurbo", "LongTurbo", + }; enum optionsNumbers { Back = 0, radiopreset_LongSlow = 1, @@ -208,7 +209,8 @@ void menuHandler::RadioPresetPicker() radiopreset_MediumFast = 5, radiopreset_ShortSlow = 6, radiopreset_ShortFast = 7, - radiopreset_ShortTurbo = 8 + radiopreset_ShortTurbo = 8, + radiopreset_LongTurbo = 9 }; BannerOverlayOptions bannerOptions; bannerOptions.message = "Radio Preset"; @@ -219,8 +221,8 @@ void menuHandler::RadioPresetPicker() menuHandler::menuQueue = menuHandler::lora_Menu; screen->runNow(); return; - } else if (selected == radiopreset_LongSlow) { - config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW; + } else if (selected == radiopreset_LongTurbo) { + config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO; } else if (selected == radiopreset_LongModerate) { config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE; } else if (selected == radiopreset_LongFast) { diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 3c0da44944d..db86778219d 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -503,6 +503,11 @@ void RadioInterface::applyModemConfig() cr = 5; sf = 10; break; + case meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO: + bw = (myRegion->wideLora) ? 1625.0 : 500; + cr = 8; + sf = 11; + break; default: // Config_LoRaConfig_ModemPreset_LONG_FAST is default. Gracefully use this is preset is something illegal. bw = (myRegion->wideLora) ? 812.5 : 250; cr = 5; @@ -539,13 +544,26 @@ void RadioInterface::applyModemConfig() } if ((myRegion->freqEnd - myRegion->freqStart) < bw / 1000) { - static const char *err_string = "Regional frequency range is smaller than bandwidth. Fall back to default preset"; - LOG_ERROR(err_string); + const float regionSpanKHz = (myRegion->freqEnd - myRegion->freqStart) * 1000.0f; + const float requestedBwKHz = bw; + const bool isWideRequest = requestedBwKHz >= 499.5f; // treat as 500 kHz preset + const char *presetName = + DisplayFormatters::getModemPresetDisplayName(loraConfig.modem_preset, false, loraConfig.use_preset); + + char err_string[160]; + if (isWideRequest) { + snprintf(err_string, sizeof(err_string), "%s region too narrow for 500kHz preset (%s). Falling back to LongFast.", + myRegion->name, presetName); + } else { + snprintf(err_string, sizeof(err_string), "%s region span %.0fkHz < requested %.0fkHz. Falling back to LongFast.", + myRegion->name, regionSpanKHz, requestedBwKHz); + } + LOG_ERROR("%s", err_string); RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); cn->level = meshtastic_LogRecord_Level_ERROR; - sprintf(cn->message, err_string); + snprintf(cn->message, sizeof(cn->message), "%s", err_string); service->sendClientNotification(cn); // Set to default modem preset diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 57b855d9869..d4ef5bee49a 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -293,7 +293,8 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode { typedef enum _meshtastic_Config_LoRaConfig_ModemPreset { /* Long Range - Fast */ meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST = 0, - /* Long Range - Slow */ + /* Long Range - Slow + Deprecated in 2.7: Unpopular slow preset. */ meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW = 1, /* Very Long Range - Slow Deprecated in 2.5: Works only with txco and is unusably slow */ From 619f0fc0fa65447215a3ee3e2efa7aa8aad8dd52 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Mon, 15 Dec 2025 20:12:05 -0600 Subject: [PATCH 2/7] Oops --- src/graphics/draw/MenuHandler.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index 37e52e8e974..36e70824374 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -198,11 +198,11 @@ void menuHandler::DeviceRolePicker() void menuHandler::RadioPresetPicker() { static const char *optionsArray[] = { - "Back", "LongModerate", "LongFast", "MediumSlow", "MediumFast", "ShortSlow", "ShortFast", "ShortTurbo", "LongTurbo", + "Back", "LongTurbo", "LongModerate", "LongFast", "MediumSlow", "MediumFast", "ShortSlow", "ShortFast", "ShortTurbo", }; enum optionsNumbers { Back = 0, - radiopreset_LongSlow = 1, + radiopreset_LongTurbo = 1, radiopreset_LongModerate = 2, radiopreset_LongFast = 3, radiopreset_MediumSlow = 4, @@ -210,7 +210,6 @@ void menuHandler::RadioPresetPicker() radiopreset_ShortSlow = 6, radiopreset_ShortFast = 7, radiopreset_ShortTurbo = 8, - radiopreset_LongTurbo = 9 }; BannerOverlayOptions bannerOptions; bannerOptions.message = "Radio Preset"; From 85b4645180ca8962f242549fe51cdcd61a877a44 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Tue, 16 Dec 2025 06:42:55 -0600 Subject: [PATCH 3/7] Start to DRY up menu handler by actually using OO concepts instead of jank separate arrays --- src/graphics/draw/MenuHandler.cpp | 79 +++++++++++++++++-------------- src/graphics/draw/MenuHandler.h | 11 +++++ 2 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index 36e70824374..43ee3035584 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -21,11 +21,36 @@ #include "modules/TraceRouteModule.h" #include +#include extern uint16_t TFT_MESH; namespace graphics { + +namespace +{ + +template +BannerOverlayOptions createBannerOptions(const char *message, const MenuOption (&options)[N], Callback &&onSelection) +{ + static const char *labels[N]; + for (size_t i = 0; i < N; ++i) { + labels[i] = options[i].label; + } + + auto callback = std::forward(onSelection); + + BannerOverlayOptions bannerOptions; + bannerOptions.message = message; + bannerOptions.optionsArrayPtr = labels; + bannerOptions.optionsCount = static_cast(N); + bannerOptions.bannerCallback = [&options, callback](int selected) mutable -> void { callback(options[selected], selected); }; + return bannerOptions; +} + +} // namespace + menuHandler::screenMenus menuHandler::menuQueue = menu_none; bool test_enabled = false; uint8_t test_count = 0; @@ -197,49 +222,31 @@ void menuHandler::DeviceRolePicker() void menuHandler::RadioPresetPicker() { - static const char *optionsArray[] = { - "Back", "LongTurbo", "LongModerate", "LongFast", "MediumSlow", "MediumFast", "ShortSlow", "ShortFast", "ShortTurbo", - }; - enum optionsNumbers { - Back = 0, - radiopreset_LongTurbo = 1, - radiopreset_LongModerate = 2, - radiopreset_LongFast = 3, - radiopreset_MediumSlow = 4, - radiopreset_MediumFast = 5, - radiopreset_ShortSlow = 6, - radiopreset_ShortFast = 7, - radiopreset_ShortTurbo = 8, + + static const RadioPresetOption presetOptions[] = { + {"Back", OptionsAction::Back, meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST}, + {"LongTurbo", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO}, + {"LongModerate", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE}, + {"LongFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST}, + {"MediumSlow", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW}, + {"MediumFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST}, + {"ShortSlow", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW}, + {"ShortFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST}, + {"ShortTurbo", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO}, }; - BannerOverlayOptions bannerOptions; - bannerOptions.message = "Radio Preset"; - bannerOptions.optionsArrayPtr = optionsArray; - bannerOptions.optionsCount = 9; - bannerOptions.bannerCallback = [](int selected) -> void { - if (selected == Back) { + + auto bannerOptions = createBannerOptions("Radio Preset", presetOptions, [](const RadioPresetOption &option, int) -> void { + if (option.action == OptionsAction::Back) { menuHandler::menuQueue = menuHandler::lora_Menu; screen->runNow(); return; - } else if (selected == radiopreset_LongTurbo) { - config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO; - } else if (selected == radiopreset_LongModerate) { - config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE; - } else if (selected == radiopreset_LongFast) { - config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST; - } else if (selected == radiopreset_MediumSlow) { - config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW; - } else if (selected == radiopreset_MediumFast) { - config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST; - } else if (selected == radiopreset_ShortSlow) { - config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW; - } else if (selected == radiopreset_ShortFast) { - config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST; - } else if (selected == radiopreset_ShortTurbo) { - config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO; } + + config.lora.modem_preset = option.value; service->reloadConfig(SEGMENT_CONFIG); rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000); - }; + }); + screen->showOverlayBanner(bannerOptions); } diff --git a/src/graphics/draw/MenuHandler.h b/src/graphics/draw/MenuHandler.h index a611b7c9d03..5f434751042 100644 --- a/src/graphics/draw/MenuHandler.h +++ b/src/graphics/draw/MenuHandler.h @@ -99,5 +99,16 @@ class menuHandler static void BluetoothToggleMenu(); }; +/* Generic Menu Options designations */ +enum class OptionsAction { Back, Select }; + +template struct MenuOption { + const char *label; + OptionsAction action; + T value; +}; + +using RadioPresetOption = MenuOption; + } // namespace graphics #endif \ No newline at end of file From 50298cff588ee5ac6304719b4bf788c34f0e80da Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Tue, 16 Dec 2025 06:45:25 -0600 Subject: [PATCH 4/7] Move the implementation back into the method --- src/graphics/draw/MenuHandler.cpp | 1 + src/graphics/draw/MenuHandler.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index 43ee3035584..55ec9e1766f 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -222,6 +222,7 @@ void menuHandler::DeviceRolePicker() void menuHandler::RadioPresetPicker() { + using RadioPresetOption = MenuOption; static const RadioPresetOption presetOptions[] = { {"Back", OptionsAction::Back, meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST}, diff --git a/src/graphics/draw/MenuHandler.h b/src/graphics/draw/MenuHandler.h index 5f434751042..db3653391b7 100644 --- a/src/graphics/draw/MenuHandler.h +++ b/src/graphics/draw/MenuHandler.h @@ -108,7 +108,5 @@ template struct MenuOption { T value; }; -using RadioPresetOption = MenuOption; - } // namespace graphics #endif \ No newline at end of file From a24e9c8547696d5f441fb593e33faea6b7248ab0 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Tue, 16 Dec 2025 07:02:17 -0600 Subject: [PATCH 5/7] Dummy comment --- src/graphics/draw/MenuHandler.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index 55ec9e1766f..20e85c8fe5b 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -225,7 +225,8 @@ void menuHandler::RadioPresetPicker() using RadioPresetOption = MenuOption; static const RadioPresetOption presetOptions[] = { - {"Back", OptionsAction::Back, meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST}, + {"Back", OptionsAction::Back, + meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST}, // Dummy preset value here to satisfy generics {"LongTurbo", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO}, {"LongModerate", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE}, {"LongFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST}, From 392bd83a145c6109e1bce4b6a563579c95afc24f Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Tue, 16 Dec 2025 07:13:30 -0600 Subject: [PATCH 6/7] Listen to copilot feedback and prevent dangling pointer --- src/graphics/draw/MenuHandler.cpp | 43 +++++++++++++++++++------------ src/graphics/draw/MenuHandler.h | 2 ++ 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index 20e85c8fe5b..cd0bd022330 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -20,6 +20,8 @@ #include "modules/KeyVerificationModule.h" #include "modules/TraceRouteModule.h" +#include +#include #include #include @@ -32,20 +34,25 @@ namespace { template -BannerOverlayOptions createBannerOptions(const char *message, const MenuOption (&options)[N], Callback &&onSelection) +BannerOverlayOptions createBannerOptions(const char *message, const MenuOption (&options)[N], + std::array &labels, Callback &&onSelection) { - static const char *labels[N]; for (size_t i = 0; i < N; ++i) { labels[i] = options[i].label; } - auto callback = std::forward(onSelection); + std::array, N> optionsCopy{}; + std::copy(std::begin(options), std::end(options), optionsCopy.begin()); + + auto callback = std::function &, int)>(std::forward(onSelection)); BannerOverlayOptions bannerOptions; bannerOptions.message = message; - bannerOptions.optionsArrayPtr = labels; + bannerOptions.optionsArrayPtr = labels.data(); bannerOptions.optionsCount = static_cast(N); - bannerOptions.bannerCallback = [&options, callback](int selected) mutable -> void { callback(options[selected], selected); }; + bannerOptions.bannerCallback = [optionsCopy, callback](int selected) mutable -> void { + callback(optionsCopy[selected], selected); + }; return bannerOptions; } @@ -222,8 +229,6 @@ void menuHandler::DeviceRolePicker() void menuHandler::RadioPresetPicker() { - using RadioPresetOption = MenuOption; - static const RadioPresetOption presetOptions[] = { {"Back", OptionsAction::Back, meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST}, // Dummy preset value here to satisfy generics @@ -237,17 +242,21 @@ void menuHandler::RadioPresetPicker() {"ShortTurbo", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO}, }; - auto bannerOptions = createBannerOptions("Radio Preset", presetOptions, [](const RadioPresetOption &option, int) -> void { - if (option.action == OptionsAction::Back) { - menuHandler::menuQueue = menuHandler::lora_Menu; - screen->runNow(); - return; - } + constexpr size_t presetCount = sizeof(presetOptions) / sizeof(presetOptions[0]); + static std::array presetLabels{}; - config.lora.modem_preset = option.value; - service->reloadConfig(SEGMENT_CONFIG); - rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000); - }); + auto bannerOptions = + createBannerOptions("Radio Preset", presetOptions, presetLabels, [](const RadioPresetOption &option, int) -> void { + if (option.action == OptionsAction::Back) { + menuHandler::menuQueue = menuHandler::lora_Menu; + screen->runNow(); + return; + } + + config.lora.modem_preset = option.value; + service->reloadConfig(SEGMENT_CONFIG); + rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000); + }); screen->showOverlayBanner(bannerOptions); } diff --git a/src/graphics/draw/MenuHandler.h b/src/graphics/draw/MenuHandler.h index db3653391b7..5f434751042 100644 --- a/src/graphics/draw/MenuHandler.h +++ b/src/graphics/draw/MenuHandler.h @@ -108,5 +108,7 @@ template struct MenuOption { T value; }; +using RadioPresetOption = MenuOption; + } // namespace graphics #endif \ No newline at end of file From 15ffa994782615c4e30f046493a7606b8dbacac3 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Tue, 16 Dec 2025 11:13:45 -0600 Subject: [PATCH 7/7] Static and optional --- src/graphics/draw/MenuHandler.cpp | 22 +++++++++++----------- src/graphics/draw/MenuHandler.h | 8 ++++++++ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index cd0bd022330..586bdd4a66c 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -33,26 +33,23 @@ namespace graphics namespace { +// Caller must ensure the provided options array outlives the banner callback. template -BannerOverlayOptions createBannerOptions(const char *message, const MenuOption (&options)[N], - std::array &labels, Callback &&onSelection) +BannerOverlayOptions createStaticBannerOptions(const char *message, const MenuOption (&options)[N], + std::array &labels, Callback &&onSelection) { for (size_t i = 0; i < N; ++i) { labels[i] = options[i].label; } - std::array, N> optionsCopy{}; - std::copy(std::begin(options), std::end(options), optionsCopy.begin()); - + const MenuOption *optionsPtr = options; auto callback = std::function &, int)>(std::forward(onSelection)); BannerOverlayOptions bannerOptions; bannerOptions.message = message; bannerOptions.optionsArrayPtr = labels.data(); bannerOptions.optionsCount = static_cast(N); - bannerOptions.bannerCallback = [optionsCopy, callback](int selected) mutable -> void { - callback(optionsCopy[selected], selected); - }; + bannerOptions.bannerCallback = [optionsPtr, callback](int selected) -> void { callback(optionsPtr[selected], selected); }; return bannerOptions; } @@ -230,8 +227,7 @@ void menuHandler::DeviceRolePicker() void menuHandler::RadioPresetPicker() { static const RadioPresetOption presetOptions[] = { - {"Back", OptionsAction::Back, - meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST}, // Dummy preset value here to satisfy generics + {"Back", OptionsAction::Back}, {"LongTurbo", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO}, {"LongModerate", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE}, {"LongFast", OptionsAction::Select, meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST}, @@ -246,13 +242,17 @@ void menuHandler::RadioPresetPicker() static std::array presetLabels{}; auto bannerOptions = - createBannerOptions("Radio Preset", presetOptions, presetLabels, [](const RadioPresetOption &option, int) -> void { + createStaticBannerOptions("Radio Preset", presetOptions, presetLabels, [](const RadioPresetOption &option, int) -> void { if (option.action == OptionsAction::Back) { menuHandler::menuQueue = menuHandler::lora_Menu; screen->runNow(); return; } + if (!option.hasValue) { + return; + } + config.lora.modem_preset = option.value; service->reloadConfig(SEGMENT_CONFIG); rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000); diff --git a/src/graphics/draw/MenuHandler.h b/src/graphics/draw/MenuHandler.h index 5f434751042..df7c2739b9d 100644 --- a/src/graphics/draw/MenuHandler.h +++ b/src/graphics/draw/MenuHandler.h @@ -105,7 +105,15 @@ enum class OptionsAction { Back, Select }; template struct MenuOption { const char *label; OptionsAction action; + bool hasValue; T value; + + MenuOption(const char *labelIn, OptionsAction actionIn, T valueIn) + : label(labelIn), action(actionIn), hasValue(true), value(valueIn) + { + } + + MenuOption(const char *labelIn, OptionsAction actionIn) : label(labelIn), action(actionIn), hasValue(false), value() {} }; using RadioPresetOption = MenuOption;