From 0a6d3d0f72fdf3436aaef3c366740fa7384459ad Mon Sep 17 00:00:00 2001 From: norulers Date: Thu, 16 Jul 2026 07:50:17 +0800 Subject: [PATCH] fix(switches): widen fsPreviousState to 32-bit to fix toggle detection for more than 16 switches (#7560) Co-authored-by: Claude Fable 5 --- radio/src/switches.cpp | 6 +++--- radio/src/tests/switches.cpp | 42 ++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp index d6a72355d..be3bbd848 100644 --- a/radio/src/switches.cpp +++ b/radio/src/switches.cpp @@ -92,7 +92,7 @@ uint8_t potsPos[MAX_POTS]; // Non pushed : SWSRC_Sx0 = -1024 = Sx(up) = state 0 // Pushed : SWSRC_Sx2 = +1024 = Sx(down) = state 1 -uint16_t fsPreviousState = 0; +uint32_t fsPreviousState = 0; uint8_t isSwitch3Pos(uint8_t idx) { @@ -149,7 +149,7 @@ bool getFSPhysicalState(uint8_t index) static bool getFSPreviousPhysicalState(uint8_t index) { - return (uint8_t)(bfSingleBitGet(fsPreviousState, index) >> (index)); + return (fsPreviousState >> index) & 1; } uint8_t getSwitchCountInFSGroup(uint8_t index) @@ -206,7 +206,7 @@ void evalFunctionSwitches() } } - fsPreviousState ^= 1 << i; // Toggle state + fsPreviousState ^= uint32_t(1) << i; // Toggle state storageDirty(EE_MODEL); } diff --git a/radio/src/tests/switches.cpp b/radio/src/tests/switches.cpp index ebcb533f1..1758c9a09 100644 --- a/radio/src/tests/switches.cpp +++ b/radio/src/tests/switches.cpp @@ -428,3 +428,45 @@ TEST(FlexSwitches, getSwitch) EXPECT_FALSE(getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 1)); EXPECT_TRUE(getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 2)); } + +#if defined(FUNCTION_SWITCHES) +TEST(FunctionSwitches, holdIsNotRepeatedToggle) +{ + MODEL_RESET(); + setModelDefaults(); + switchInit(); + + for (uint8_t i = 0; i < switchGetMaxSwitches(); i++) { + if (!switchIsCustomSwitch(i)) continue; + // Toggle type with no group, so a phantom "switch moved" event + // flips the logical state and is observable + g_model.cfsSetType(i, SWITCH_TOGGLE); + g_model.cfsSetGroup(i, 0); + simuSetSwitch(i, -1); + } + + setFSStartupPosition(); + evalFunctionSwitches(); // sync previous state with all switches released + + for (uint8_t i = 0; i < switchGetMaxSwitches(); i++) { + if (!switchIsCustomSwitch(i)) continue; + + bool released = g_model.cfsState(i); + simuSetSwitch(i, 1); + evalFunctionSwitches(); + bool pressed = g_model.cfsState(i); + EXPECT_NE(released, pressed) << "press did not toggle switch index " << (int)i; + + // holding the switch must not generate further toggles + evalFunctionSwitches(); + EXPECT_EQ(pressed, g_model.cfsState(i)) + << "hold re-toggled switch index " << (int)i; + evalFunctionSwitches(); + EXPECT_EQ(pressed, g_model.cfsState(i)) + << "hold re-toggled switch index " << (int)i; + + simuSetSwitch(i, -1); + evalFunctionSwitches(); + } +} +#endif