From 61ce1a2d18cb1a2b9318f52cec87e67a9838baaf Mon Sep 17 00:00:00 2001 From: philmoz Date: Sun, 25 Jan 2026 14:43:02 +1100 Subject: [PATCH] fix(firmware): global variable value and range may not be correct (#7009) --- radio/src/edgetx.cpp | 52 ++++++++++++++++++- radio/src/edgetx.h | 2 + .../src/gui/128x64/model_logical_switches.cpp | 4 +- .../gui/128x64/model_special_functions.cpp | 1 + .../src/gui/212x64/model_logical_switches.cpp | 4 +- .../gui/212x64/model_special_functions.cpp | 1 + .../colorlcd/model/model_logical_switches.cpp | 12 +---- .../gui/colorlcd/model/special_functions.cpp | 8 ++- .../src/gui/common/stdlcd/widgets_common.cpp | 9 +++- 9 files changed, 74 insertions(+), 19 deletions(-) diff --git a/radio/src/edgetx.cpp b/radio/src/edgetx.cpp index dc450fdbf..f32b54088 100644 --- a/radio/src/edgetx.cpp +++ b/radio/src/edgetx.cpp @@ -2031,4 +2031,54 @@ void getMixSrcRange(const int source, int16_t & valMin, int16_t & valMax, LcdFla valMin = -valMax; } } -// trigger CI + +bool validateLSV2Range(LogicalSwitchData* cs, int16_t& v2_min, int16_t& v2_max, LcdFlags* lf) +{ + getMixSrcRange(cs->v1, v2_min, v2_max, lf); + if ((cs->func == LS_FUNC_APOS) || (cs->func == LS_FUNC_ANEG)) { + if (v2_min >= 0) { + // min >= 0 && max >= 0 + } else if (v2_max < 0) { + // min < 0 && max < 0 + int16_t v = v2_min; + v2_min = -v2_max; + v2_max = -v; + } else { + // min < 0 && max >= 0 + v2_min = 0; + } + } else if (cs->func == LS_FUNC_DIFFEGREATER) { + // delta range (min - max) .. (max - min) + int16_t v = v2_min - v2_max; + v2_max = v2_max - v2_min; + v2_min = v; + } else if (cs->func == LS_FUNC_ADIFFEGREATER) { + // abs delta range 0 .. (max - min) + v2_max = v2_max - v2_min; + v2_min = 0; + } + + bool rv = false; + + if (cs->v2 < v2_min) { cs->v2 = v2_min; rv = true; } + else if (cs->v2 > v2_max) { cs->v2 = v2_max; rv = true; } + + return rv; +} + +bool validateSFGV(CustomFunctionData* cfn) +{ + bool rv = false; + + if (CFN_FUNC(cfn) == FUNC_ADJUST_GVAR && CFN_GVAR_MODE(cfn) == FUNC_ADJUST_GVAR_CONSTANT) { + int16_t v = CFN_PARAM(cfn); + int16_t vmin, vmax; + getMixSrcRange(CFN_GVAR_INDEX(cfn) + MIXSRC_FIRST_GVAR, vmin, vmax); + if (v < vmin) v = vmin; + else if (v > vmax) v = vmax; + if (CFN_PARAM(cfn) != v) rv = true; + CFN_PARAM(cfn) = v; + } + + return rv; +} diff --git a/radio/src/edgetx.h b/radio/src/edgetx.h index 295c9dea1..64dbde681 100644 --- a/radio/src/edgetx.h +++ b/radio/src/edgetx.h @@ -388,6 +388,8 @@ inline int calcRESXto100(int x) int expo(int x, int k); extern void getMixSrcRange(const int source, int16_t & valMin, int16_t & valMax, LcdFlags * flags = nullptr); +extern bool validateLSV2Range(LogicalSwitchData* cs, int16_t& v2_min, int16_t& v2_max, LcdFlags* lf); +extern bool validateSFGV(CustomFunctionData* cfn); void applyExpos(int16_t * anas, uint8_t mode, int16_t ovwrIdx=0, int16_t ovwrValue=0); int16_t applyLimits(uint8_t channel, int32_t value); diff --git a/radio/src/gui/128x64/model_logical_switches.cpp b/radio/src/gui/128x64/model_logical_switches.cpp index fe33e436c..997f815a8 100644 --- a/radio/src/gui/128x64/model_logical_switches.cpp +++ b/radio/src/gui/128x64/model_logical_switches.cpp @@ -184,9 +184,7 @@ void menuModelLogicalSwitchOne(event_t event) else { LcdFlags lf = attr | LEFT; - getMixSrcRange(cs->v1, v2_min, v2_max, &lf); - if ((cs->func == LS_FUNC_APOS) || (cs->func == LS_FUNC_ANEG) || (cs->func == LS_FUNC_ADIFFEGREATER)) - v2_min = 0; + if (validateLSV2Range(cs, v2_min, v2_max, &lf)) storageDirty(EE_MODEL); drawSourceCustomValue(CSWONE_2ND_COLUMN, y, cs->v1, (abs(cs->v1) <= MIXSRC_LAST_CH ? calc100toRESX(cs->v2) : cs->v2), lf); } } diff --git a/radio/src/gui/128x64/model_special_functions.cpp b/radio/src/gui/128x64/model_special_functions.cpp index decc79657..3d8f49b8c 100644 --- a/radio/src/gui/128x64/model_special_functions.cpp +++ b/radio/src/gui/128x64/model_special_functions.cpp @@ -261,6 +261,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF } #if defined(GVARS) else if (func == FUNC_ADJUST_GVAR) { + if (validateSFGV(cfn)) storageDirty(eeFlags); maxParam = MAX_GVARS - 1; drawStringWithIndex(lcdNextPos + 2, y, STR_GV, CFN_GVAR_INDEX(cfn)+1, attr); if (active) CFN_GVAR_INDEX(cfn) = checkIncDec(event, CFN_GVAR_INDEX(cfn), 0, maxParam, eeFlags); diff --git a/radio/src/gui/212x64/model_logical_switches.cpp b/radio/src/gui/212x64/model_logical_switches.cpp index 5c0cd7173..f9671786d 100644 --- a/radio/src/gui/212x64/model_logical_switches.cpp +++ b/radio/src/gui/212x64/model_logical_switches.cpp @@ -173,9 +173,7 @@ void menuModelLogicalSwitches(event_t event) INCDEC_ENABLE_CHECK(nullptr); } LcdFlags lf = attr2 | LEFT; - getMixSrcRange(v1_val, v2_min, v2_max, &lf); - if ((cs->func == LS_FUNC_APOS) || (cs->func == LS_FUNC_ANEG) || (cs->func == LS_FUNC_ADIFFEGREATER)) - v2_min = 0; + if (validateLSV2Range(cs, v2_min, v2_max, &lf)) storageDirty(EE_MODEL); drawSourceCustomValue(CSW_3RD_COLUMN, y, v1_val, (abs(v1_val) <= MIXSRC_LAST_CH ? calc100toRESX(cs->v2) : cs->v2), lf); } diff --git a/radio/src/gui/212x64/model_special_functions.cpp b/radio/src/gui/212x64/model_special_functions.cpp index ed193a719..ae912f9c6 100644 --- a/radio/src/gui/212x64/model_special_functions.cpp +++ b/radio/src/gui/212x64/model_special_functions.cpp @@ -249,6 +249,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF } #if defined(GVARS) else if (func == FUNC_ADJUST_GVAR) { + if (validateSFGV(cfn)) storageDirty(eeFlags); maxParam = MAX_GVARS-1; drawStringWithIndex(lcdNextPos + 2, y, STR_GV, CFN_GVAR_INDEX(cfn)+1, attr); if (active) CFN_GVAR_INDEX(cfn) = checkIncDec(event, CFN_GVAR_INDEX(cfn), 0, maxParam, eeFlags); diff --git a/radio/src/gui/colorlcd/model/model_logical_switches.cpp b/radio/src/gui/colorlcd/model/model_logical_switches.cpp index bd80787d6..8f42f52c8 100644 --- a/radio/src/gui/colorlcd/model/model_logical_switches.cpp +++ b/radio/src/gui/colorlcd/model/model_logical_switches.cpp @@ -90,14 +90,6 @@ class LogicalSwitchEditPage : public Page etx_font(headerSwitchName->getLvObj(), FONT_BOLD_INDEX, ETX_STATE_LS_ACTIVE); } - void getV2Range(LogicalSwitchData* cs, int16_t& v2_min, int16_t& v2_max) - { - getMixSrcRange(cs->v1, v2_min, v2_max); - if ((cs->func == LS_FUNC_APOS) || (cs->func == LS_FUNC_ANEG) || - (cs->func == LS_FUNC_ADIFFEGREATER)) - v2_min = 0; - } - void updateLogicalSwitchOneWindow() { SwitchChoice* choice; @@ -141,7 +133,7 @@ class LogicalSwitchEditPage : public Page cs->v1 = newValue; if (v2Edit != nullptr) { int16_t v2_min = 0, v2_max = 0; - getV2Range(cs, v2_min, v2_max); + validateLSV2Range(cs, v2_min, v2_max, nullptr); v2Edit->setMin(v2_min); v2Edit->setMax(v2_max); v2Edit->setValue(cs->v2); @@ -206,7 +198,7 @@ class LogicalSwitchEditPage : public Page break; default: int16_t v2_min = 0, v2_max = 0; - getV2Range(cs, v2_min, v2_max); + if (validateLSV2Range(cs, v2_min, v2_max, nullptr)) SET_DIRTY(); v2Edit = new NumberEdit(line, rect_t{}, v2_min, v2_max, GET_SET_DEFAULT(cs->v2)); diff --git a/radio/src/gui/colorlcd/model/special_functions.cpp b/radio/src/gui/colorlcd/model/special_functions.cpp index a3c9fdd59..73f0b9732 100644 --- a/radio/src/gui/colorlcd/model/special_functions.cpp +++ b/radio/src/gui/colorlcd/model/special_functions.cpp @@ -528,9 +528,15 @@ void FunctionEditPage::updateSpecialFunctionOneWindow() break; case FUNC_ADJUST_GVAR: { + if (validateSFGV(cfn)) SET_DIRTY(); new StaticText(line, rect_t{}, STR_GLOBALVAR); auto gvarchoice = new Choice(line, rect_t{}, 0, MAX_GVARS - 1, - GET_SET_DEFAULT(CFN_GVAR_INDEX(cfn))); + GET_DEFAULT(CFN_GVAR_INDEX(cfn)), + [=](int32_t newValue){ + CFN_GVAR_INDEX(cfn) = newValue; + SET_DIRTY(); + updateSpecialFunctionOneWindow(); + }); gvarchoice->setTextHandler([](int32_t value) { return std::string(getSourceString(value + MIXSRC_FIRST_GVAR)); }); diff --git a/radio/src/gui/common/stdlcd/widgets_common.cpp b/radio/src/gui/common/stdlcd/widgets_common.cpp index ed00e7f65..53933ae8b 100644 --- a/radio/src/gui/common/stdlcd/widgets_common.cpp +++ b/radio/src/gui/common/stdlcd/widgets_common.cpp @@ -136,9 +136,16 @@ void editGVarValue(coord_t x, coord_t y, event_t event, uint8_t gvar, uint8_t fl vmax = GVAR_MAX + MAX_FLIGHT_MODES - 1; } else { - drawGVarValue(x, y, gvar, *v, flags); vmin = GVAR_MIN + g_model.gvars[gvar].min; vmax = GVAR_MAX - g_model.gvars[gvar].max; + if (*v < vmin) { + *v = vmin; + storageDirty(EE_MODEL); + } else if (*v > vmax) { + *v = vmax; + storageDirty(EE_MODEL); + } + drawGVarValue(x, y, gvar, *v, flags); } if (flags & INVERS) {