diff --git a/companion/src/firmwares/customfunctiondata.cpp b/companion/src/firmwares/customfunctiondata.cpp index 4d3ef911280..51a952a24c8 100644 --- a/companion/src/firmwares/customfunctiondata.cpp +++ b/companion/src/firmwares/customfunctiondata.cpp @@ -199,16 +199,8 @@ QString CustomFunctionData::repeatToString(const int value) QString CustomFunctionData::enabledToString() const { - if ((func >= FuncOverrideCH1 && func <= FuncOverrideCHLast) || - (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) || - (func == FuncReset) || - (func >= FuncSetTimer1 && func <= FuncSetTimerLast) || - (func == FuncVolume) || - (func == FuncBacklight) || - (func <= FuncInstantTrim)) { - if (!enabled) { - return tr("DISABLED"); - } + if (!enabled) { + return tr("DISABLED"); } return ""; } diff --git a/companion/src/firmwares/edgetx/yaml_customfunctiondata.cpp b/companion/src/firmwares/edgetx/yaml_customfunctiondata.cpp index 50f82a1fbd9..e268cc1b71d 100644 --- a/companion/src/firmwares/edgetx/yaml_customfunctiondata.cpp +++ b/companion/src/firmwares/edgetx/yaml_customfunctiondata.cpp @@ -216,15 +216,15 @@ Node convert::encode(const CustomFunctionData& rhs) break; } - if (fnHasEnable(rhs.func)) { - if (add_comma) { - def += ","; - } - def += std::to_string((int)rhs.enabled); - } else if(fnHasRepeat(rhs.func)) { - if (add_comma) { - def += ","; - } + if (add_comma) { + def += ","; + } + + def += std::to_string((int)rhs.enabled); + + if(fnHasRepeat(rhs.func)) { + def += ","; + if (rhs.repeatParam == 0) { def += "1x"; } else if (rhs.repeatParam == -1) { @@ -367,11 +367,14 @@ bool convert::decode(const Node& node, def.ignore(); } - if (fnHasEnable(rhs.func)) { - int en = 0; - def >> en; - rhs.enabled = en; - } else if(fnHasRepeat(rhs.func)) { + int en = 0; + def >> en; + rhs.enabled = en; + + if(fnHasRepeat(rhs.func)) { + if (def.peek() == ',') { + def.ignore(); + } std::string repeat; getline(def, repeat); if (repeat == "1x") { diff --git a/companion/src/modeledit/customfunctions.cpp b/companion/src/modeledit/customfunctions.cpp index af6430b6ced..bbbc1d7ef01 100644 --- a/companion/src/modeledit/customfunctions.cpp +++ b/companion/src/modeledit/customfunctions.cpp @@ -99,7 +99,7 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, playIcon.addImage("stop.png", QIcon::Normal, QIcon::On); QStringList headerLabels; - headerLabels << "#" << tr("Switch") << tr("Action") << tr("Parameters") << ""; + headerLabels << "#" << tr("Switch") << tr("Action") << tr("Parameters") << tr("Repeat") << tr("Enable") << ""; TableLayout * tableLayout = new TableLayout(this, fswCapability, headerLabels); for (int i = 0; i < fswCapability; i++) { @@ -199,11 +199,12 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, repeatLayout->addWidget(fswtchRepeat[i], i + 1); connect(fswtchRepeat[i], SIGNAL(currentIndexChanged(int)), this, SLOT(customFunctionEdited())); + QHBoxLayout *enableLayout = new QHBoxLayout(); + tableLayout->addLayout(i, 5, enableLayout); fswtchEnable[i] = new QCheckBox(this); fswtchEnable[i]->setProperty("index", i); - fswtchEnable[i]->setText(tr("ON")); fswtchEnable[i]->setFixedWidth(200); - repeatLayout->addWidget(fswtchEnable[i], i + 1); + enableLayout->addWidget(fswtchEnable[i], i + 1); connect(fswtchEnable[i], SIGNAL(stateChanged(int)), this, SLOT(customFunctionEdited())); } @@ -324,6 +325,7 @@ void CustomFunctionsPanel::functionEdited() functions[index].clear(); functions[index].swtch = swtch; functions[index].func = (AssignFunc)fswtchFunc[index]->currentData().toInt(); + functions[index].enabled = true; refreshCustomFunction(index); emit modified(); lock = false; @@ -344,10 +346,11 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) else { fswtchSwtch[i]->setCurrentIndex(fswtchSwtch[i]->findData(cfn.swtch.toValue())); fswtchFunc[i]->setCurrentIndex(fswtchFunc[i]->findData(cfn.func)); + fswtchEnable[i]->setChecked(cfn.enabled); } if (!cfn.isEmpty()) { - widgetsMask |= CUSTOM_FUNCTION_SHOW_FUNC; + widgetsMask |= CUSTOM_FUNCTION_SHOW_FUNC | CUSTOM_FUNCTION_ENABLE; if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32) { if (model) { @@ -360,7 +363,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) cfn.param = fswtchParam[i]->value(); } fswtchParam[i]->setValue(cfn.param); - widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM | CUSTOM_FUNCTION_ENABLE; + widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM; } } else if (func == FuncLogs) { @@ -378,7 +381,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) if (modified) cfn.adjustMode = fswtchGVmode[i]->currentData().toInt(); fswtchGVmode[i]->setCurrentIndex(fswtchGVmode[i]->findData(cfn.adjustMode)); - widgetsMask |= CUSTOM_FUNCTION_GV_MODE | CUSTOM_FUNCTION_ENABLE; + widgetsMask |= CUSTOM_FUNCTION_GV_MODE; if (cfn.adjustMode == FUNC_ADJUST_GVAR_CONSTANT || cfn.adjustMode == FUNC_ADJUST_GVAR_INCDEC) { if (modified) cfn.param = fswtchParam[i]->value() * model->gvarData[gvidx].multiplierSet(); @@ -409,7 +412,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) if (modified) cfn.param = fswtchParamT[i]->currentData().toInt(); populateFuncParamCB(fswtchParamT[i], func, cfn.param); - widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM | CUSTOM_FUNCTION_ENABLE; + widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM; } else if (func >= FuncSetTimer1 && func <= FuncSetTimer3) { if (modified) @@ -417,16 +420,13 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) RawSourceRange range = RawSource(SOURCE_TYPE_SPECIAL, func - FuncSetTimer1 + 2).getRange(model, generalSettings); fswtchParamTime[i]->setTimeRange((int)range.min, (int)range.max); fswtchParamTime[i]->setTime(cfn.param); - widgetsMask |= CUSTOM_FUNCTION_TIME_PARAM | CUSTOM_FUNCTION_ENABLE; - } - else if (func >= FuncSetFailsafe && func <= FuncBindExternalModule) { - widgetsMask |= CUSTOM_FUNCTION_ENABLE; + widgetsMask |= CUSTOM_FUNCTION_TIME_PARAM; } else if (func == FuncVolume || func == FuncBacklight) { if (modified) cfn.param = fswtchParamT[i]->currentData().toInt(); populateFuncParamCB(fswtchParamT[i], func, cfn.param); - widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM | CUSTOM_FUNCTION_ENABLE; + widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM; } else if (func == FuncPlaySound || func == FuncPlayHaptic || func == FuncPlayValue || func == FuncPlayPrompt || func == FuncPlayBoth || func == FuncBackgroundMusic || func == FuncSetScreen) { if (func != FuncBackgroundMusic) { @@ -533,11 +533,12 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) fswtchParam[i]->setDecimals(0); fswtchParam[i]->setSingleStep(1); fswtchParam[i]->setValue(cfn.param); - if (func <= FuncInstantTrim) { - widgetsMask |= CUSTOM_FUNCTION_ENABLE; - } + widgetsMask |= CUSTOM_FUNCTION_ENABLE; } } + else { + cfn.enabled = true; + } fswtchFunc[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_SHOW_FUNC); fswtchParam[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_NUMERIC_PARAM); @@ -546,10 +547,6 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) fswtchParamT[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_SOURCE_PARAM); fswtchParamArmT[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_FILE_PARAM); fswtchEnable[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_ENABLE); - if (widgetsMask & CUSTOM_FUNCTION_ENABLE) - fswtchEnable[i]->setChecked(cfn.enabled); - else - fswtchEnable[i]->setChecked(false); fswtchRepeat[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_REPEAT); fswtchGVmode[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_GV_MODE); playBT[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_PLAY); diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index 5f8364e3b62..c403ffeaa84 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -172,7 +172,8 @@ PACK(struct CustomFunctionData { NOBACKUP(CFN_SPARE_TYPE val2); }) clear); }) NAME(fp) SKIP; - uint8_t active SKIP; + uint8_t active : 1 SKIP; + int8_t repeat:7 SKIP; bool isEmpty() const { diff --git a/radio/src/gui/128x64/model_special_functions.cpp b/radio/src/gui/128x64/model_special_functions.cpp index 3f821ea0af9..ff9d3023093 100644 --- a/radio/src/gui/128x64/model_special_functions.cpp +++ b/radio/src/gui/128x64/model_special_functions.cpp @@ -21,14 +21,17 @@ #include "opentx.h" -#define MODEL_SPECIAL_FUNC_1ST_COLUMN (0) -#define MODEL_SPECIAL_FUNC_2ND_COLUMN (4*FW-1) -#define MODEL_SPECIAL_FUNC_3RD_COLUMN (15*FW-3) -#define MODEL_SPECIAL_FUNC_4TH_COLUMN (20*FW) +#define MODEL_SPECIAL_FUNC_1ST_COLUMN (0) +#define MODEL_SPECIAL_FUNC_2ND_COLUMN (4*FW-1) +#define MODEL_SPECIAL_FUNC_3RD_COLUMN (15*FW-3) #if defined(GRAPHICS) - #define MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF (20*FW) + #define MODEL_SPECIAL_FUNC_4TH_COLUMN (19 * FW - 3) + #define MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF (19 * FW - 3) + #define MODEL_SPECIAL_FUNC_5TH_COLUMN_ONOFF (20 * FW + 1) #else - #define MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF (18*FW+2) + #define MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF (17 * FW) + #define MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF (17 * FW) + #define MODEL_SPECIAL_FUNC_5TH_COLUMN_ONOFF (18 * FW + 3) #endif #if defined(SDCARD) @@ -179,12 +182,13 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF CustomFunctionData * cfn = &functions[k]; uint8_t func = CFN_FUNC(cfn); - for (uint8_t j=0; j<5; j++) { + for (uint8_t j=0; j<6; j++) { uint8_t attr = ((sub==k && menuHorizontalPosition==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0); uint8_t active = (attr && s_editMode > 0); switch (j) { case 0: if (sub==k && menuHorizontalPosition < 1 && CFN_SWITCH(cfn) == SWSRC_NONE) { + CFN_ACTIVE(cfn) = 1; drawSwitch(MODEL_SPECIAL_FUNC_1ST_COLUMN, y, CFN_SWITCH(cfn), attr | INVERS | ((functionsContext->activeSwitches & ((MASK_CFN_TYPE)1 << k)) ? BOLD : 0)); if (active) CHECK_INCDEC_SWITCH(event, CFN_SWITCH(cfn), SWSRC_FIRST, SWSRC_LAST, eeFlags, isSwitchAvailableInCustomFunctions); } @@ -203,6 +207,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF if (active) { CFN_FUNC(cfn) = checkIncDec(event, CFN_FUNC(cfn), 0, FUNC_MAX-1, eeFlags, isAssignableFunctionAvailable); if (checkIncDec_Ret) CFN_RESET(cfn); + CFN_ACTIVE(cfn) = 1; // Enable if function is being changed } } else { @@ -427,26 +432,27 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF } case 4: - if (HAS_ENABLE_PARAM(func)) { - drawCheckBox(MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF, y, CFN_ACTIVE(cfn), attr); - if (active) CFN_ACTIVE(cfn) = checkIncDec(event, CFN_ACTIVE(cfn), 0, 1, eeFlags); - } - else if (HAS_REPEAT_PARAM(func)) { + if (HAS_REPEAT_PARAM(func)) { if (CFN_PLAY_REPEAT(cfn) == 0) { lcdDrawChar(MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF+3, y, '-', attr); } - else if (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) { + else if (CFN_PLAY_REPEAT(cfn) == (int8_t)CFN_PLAY_REPEAT_NOSTART) { lcdDrawText(MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF+1, y, "!-", attr); } else { lcdDrawNumber(MODEL_SPECIAL_FUNC_4TH_COLUMN+2+FW, y, CFN_PLAY_REPEAT(cfn)*CFN_PLAY_REPEAT_MUL, RIGHT | attr); } - if (active) CFN_PLAY_REPEAT(cfn) = checkIncDec(event, CFN_PLAY_REPEAT(cfn)==CFN_PLAY_REPEAT_NOSTART?-1:CFN_PLAY_REPEAT(cfn), -1, 60/CFN_PLAY_REPEAT_MUL, eeFlags); + if (active) CFN_PLAY_REPEAT(cfn) = checkIncDec(event, CFN_PLAY_REPEAT(cfn)==(int8_t)CFN_PLAY_REPEAT_NOSTART?-1:CFN_PLAY_REPEAT(cfn), -1, 60/CFN_PLAY_REPEAT_MUL, eeFlags); } else if (attr) { REPEAT_LAST_CURSOR_MOVE(); } break; + + case 5: + drawCheckBox(MODEL_SPECIAL_FUNC_5TH_COLUMN_ONOFF, y, CFN_ACTIVE(cfn), attr); + if (active) CFN_ACTIVE(cfn) = checkIncDec(event, CFN_ACTIVE(cfn), 0, 1, eeFlags); + break; } } #if defined(NAVIGATION_X7) @@ -465,7 +471,7 @@ void menuModelSpecialFunctions(event_t event) menuHorizontalPosition = 0; } #endif - MENU(STR_MENUCUSTOMFUNC, menuTabModel, MENU_MODEL_SPECIAL_FUNCTIONS, HEADER_LINE+MAX_SPECIAL_FUNCTIONS, { HEADER_LINE_COLUMNS NAVIGATION_LINE_BY_LINE|4/*repeated*/ }); + MENU(STR_MENUCUSTOMFUNC, menuTabModel, MENU_MODEL_SPECIAL_FUNCTIONS, HEADER_LINE+MAX_SPECIAL_FUNCTIONS, { HEADER_LINE_COLUMNS NAVIGATION_LINE_BY_LINE|5/*repeated*/ }); menuSpecialFunctions(event, g_model.customFn, &modelFunctionsContext); diff --git a/radio/src/gui/212x64/model_special_functions.cpp b/radio/src/gui/212x64/model_special_functions.cpp index a12e61e3554..7eeb69fa081 100644 --- a/radio/src/gui/212x64/model_special_functions.cpp +++ b/radio/src/gui/212x64/model_special_functions.cpp @@ -24,7 +24,7 @@ #define MODEL_SPECIAL_FUNC_1ST_COLUMN (4*FW+2) #define MODEL_SPECIAL_FUNC_2ND_COLUMN (8*FW+2) #define MODEL_SPECIAL_FUNC_3RD_COLUMN (21*FW) -#define MODEL_SPECIAL_FUNC_4TH_COLUMN (33*FW-3) +#define MODEL_SPECIAL_FUNC_4TH_COLUMN (31*FW-3) #define MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF (34*FW-3) void onCustomFunctionsFileSelectionMenu(const char * result) @@ -141,8 +141,9 @@ enum CustomFunctionsItems { ITEM_CUSTOM_FUNCTIONS_PARAM1, ITEM_CUSTOM_FUNCTIONS_PARAM2, ITEM_CUSTOM_FUNCTIONS_REPEAT, + ITEM_CUSTOM_FUNCTIONS_ENABLE, ITEM_CUSTOM_FUNCTIONS_COUNT, - ITEM_CUSTOM_FUNCTIONS_LAST = ITEM_CUSTOM_FUNCTIONS_COUNT-1 + ITEM_CUSTOM_FUNCTIONS_LAST = ITEM_CUSTOM_FUNCTIONS_COUNT - 1 }; void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomFunctionsContext * functionsContext) @@ -177,11 +178,12 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF CustomFunctionData * cfn = &functions[k]; uint8_t func = CFN_FUNC(cfn); - for (uint8_t j=0; j<5; j++) { + for (uint8_t j=0; j<6; j++) { uint8_t attr = ((sub==k && menuHorizontalPosition==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0); uint8_t active = (attr && s_editMode>0); switch (j) { case ITEM_CUSTOM_FUNCTIONS_SWITCH: + if(CFN_SWITCH(cfn) == SWSRC_NONE) CFN_ACTIVE(cfn) = 1; // Enable new function by default drawSwitch(MODEL_SPECIAL_FUNC_1ST_COLUMN, y, CFN_SWITCH(cfn), attr | ((functionsContext->activeSwitches & ((MASK_CFN_TYPE)1 << k)) ? BOLD : 0)); if (active || AUTOSWITCH_ENTER_LONG()) CHECK_INCDEC_SWITCH(event, CFN_SWITCH(cfn), SWSRC_FIRST, SWSRC_LAST, eeFlags, isSwitchAvailableInCustomFunctions); if (func == FUNC_OVERRIDE_CHANNEL && functions != g_model.customFn) { @@ -195,6 +197,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF if (active) { func = CFN_FUNC(cfn) = checkIncDec(event, CFN_FUNC(cfn), 0, FUNC_MAX-1, eeFlags, isAssignableFunctionAvailable); if (checkIncDec_Ret) CFN_RESET(cfn); + CFN_ACTIVE(cfn) = 1; // Enable if function is being changed } } else { @@ -405,15 +408,11 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF } case ITEM_CUSTOM_FUNCTIONS_REPEAT: - if (HAS_ENABLE_PARAM(func)) { - drawCheckBox(MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF, y, CFN_ACTIVE(cfn), attr); - if (active) CFN_ACTIVE(cfn) = checkIncDec(event, CFN_ACTIVE(cfn), 0, 1, eeFlags); - } - else if (HAS_REPEAT_PARAM(func)) { + if (HAS_REPEAT_PARAM(func)) { if (CFN_PLAY_REPEAT(cfn) == 0) { lcdDrawText(MODEL_SPECIAL_FUNC_4TH_COLUMN+2, y, "1x", attr); } - else if (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) { + else if (CFN_PLAY_REPEAT(cfn) == (int8_t)CFN_PLAY_REPEAT_NOSTART) { lcdDrawChar(MODEL_SPECIAL_FUNC_4TH_COLUMN-1, y, '!', attr); lcdDrawText(MODEL_SPECIAL_FUNC_4TH_COLUMN+2, y, "1x", attr); } @@ -421,12 +420,20 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF lcdDrawNumber(MODEL_SPECIAL_FUNC_4TH_COLUMN+2+FW, y, CFN_PLAY_REPEAT(cfn)*CFN_PLAY_REPEAT_MUL, attr|RIGHT); lcdDrawChar(MODEL_SPECIAL_FUNC_4TH_COLUMN+2+FW, y, 's', attr); } - if (active) CFN_PLAY_REPEAT(cfn) = checkIncDec(event, CFN_PLAY_REPEAT(cfn)==CFN_PLAY_REPEAT_NOSTART?-1:CFN_PLAY_REPEAT(cfn), -1, 60/CFN_PLAY_REPEAT_MUL, eeFlags); + if (active) CFN_PLAY_REPEAT(cfn) = checkIncDec(event, CFN_PLAY_REPEAT(cfn)==(int8_t)CFN_PLAY_REPEAT_NOSTART?-1:CFN_PLAY_REPEAT(cfn), -1, 60/CFN_PLAY_REPEAT_MUL, eeFlags); } else if (attr) { REPEAT_LAST_CURSOR_MOVE(); } break; + + case ITEM_CUSTOM_FUNCTIONS_ENABLE: + drawCheckBox(MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF, y, CFN_ACTIVE(cfn), + attr); + if (active) + CFN_ACTIVE(cfn) = + checkIncDec(event, CFN_ACTIVE(cfn), 0, 1, eeFlags); + break; } } } @@ -434,6 +441,6 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF void menuModelSpecialFunctions(event_t event) { - MENU(STR_MENUCUSTOMFUNC, menuTabModel, MENU_MODEL_SPECIAL_FUNCTIONS, MAX_SPECIAL_FUNCTIONS, { NAVIGATION_LINE_BY_LINE|4/*repeated*/ }); + MENU(STR_MENUCUSTOMFUNC, menuTabModel, MENU_MODEL_SPECIAL_FUNCTIONS, MAX_SPECIAL_FUNCTIONS, { NAVIGATION_LINE_BY_LINE|5/*repeated*/ }); return menuSpecialFunctions(event, g_model.customFn, &modelFunctionsContext); } diff --git a/radio/src/gui/colorlcd/special_functions.cpp b/radio/src/gui/colorlcd/special_functions.cpp index ac6fc243f8e..7e2631e3db2 100644 --- a/radio/src/gui/colorlcd/special_functions.cpp +++ b/radio/src/gui/colorlcd/special_functions.cpp @@ -352,13 +352,8 @@ class SpecialFunctionEditPage : public Page line = specialFunctionOneWindow->newLine(&grid); } } - - if (HAS_ENABLE_PARAM(func)) { - new StaticText(line, rect_t{}, STR_ENABLE, 0, COLOR_THEME_PRIMARY1); - new CheckBox(line, rect_t{}, - GET_SET_DEFAULT(CFN_ACTIVE(cfn))); - line = specialFunctionOneWindow->newLine(&grid); - } else if (HAS_REPEAT_PARAM(func)) { // !1x 1x 1s 2s 3s ... + + if (HAS_REPEAT_PARAM(func)) { // !1x 1x 1s 2s 3s ... new StaticText(line, rect_t{}, STR_REPEAT, 0, COLOR_THEME_PRIMARY1); auto repeat = new NumberEdit( @@ -377,6 +372,12 @@ class SpecialFunctionEditPage : public Page }); line = specialFunctionOneWindow->newLine(&grid); } + + { + new StaticText(line, rect_t{}, STR_ENABLE, 0, COLOR_THEME_PRIMARY1); + new CheckBox(line, rect_t{}, GET_SET_DEFAULT(CFN_ACTIVE(cfn))); + line = specialFunctionOneWindow->newLine(&grid); + } } void buildBody(FormWindow *window) @@ -387,7 +388,11 @@ class SpecialFunctionEditPage : public Page CustomFunctionData *cfn = &functions[index]; - // Switch + // Set new function to "enabled" by default + if (!CFN_SWITCH(cfn)) + CFN_ACTIVE(cfn) = true; + + // Switch auto line = window->newLine(&grid); new StaticText(line, rect_t{}, STR_SWITCH, 0, COLOR_THEME_PRIMARY1); auto switchChoice = @@ -421,6 +426,7 @@ class SpecialFunctionEditPage : public Page functionChoice->setSetValueHandler([=](int32_t newValue) { CFN_FUNC(cfn) = newValue; CFN_RESET(cfn); + CFN_ACTIVE(cfn) = 1; SET_DIRTY(); updateSpecialFunctionOneWindow(); }); @@ -439,6 +445,8 @@ static constexpr coord_t line2 = line1 + PAGE_LINE_HEIGHT; static constexpr coord_t col1 = 20; static constexpr coord_t col2 = (LCD_W - 100) / 3 + col1; static constexpr coord_t col3 = ((LCD_W - 100) / 3) * 2 + col1 + 20; +// Special location used only for "enabled" check-box +static constexpr coord_t col4 = (LCD_W - 100); static const char* _failsafe_module[] = { "Ext.", "Int.", @@ -595,12 +603,13 @@ class SpecialFunctionButton : public Button } } } - if (HAS_ENABLE_PARAM(func)) { - theme->drawCheckBox(dc, CFN_ACTIVE(cfn), col3, line2); - } else if (HAS_REPEAT_PARAM(func)) { + + theme->drawCheckBox(dc, CFN_ACTIVE(cfn), col4, line2); + + if (HAS_REPEAT_PARAM(func)) { if (CFN_PLAY_REPEAT(cfn) == 0) { dc->drawText(col3, line2, "1x", COLOR_THEME_SECONDARY1); - } else if (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) { + } else if (CFN_PLAY_REPEAT(cfn) == int8_t(CFN_PLAY_REPEAT_NOSTART)) { dc->drawText(col3, line2, "!1x", COLOR_THEME_SECONDARY1); } else { dc->drawNumber(col3 + 12, line2, CFN_PLAY_REPEAT(cfn) * CFN_PLAY_REPEAT_MUL, COLOR_THEME_SECONDARY1 | RIGHT, 0, nullptr, "s"); @@ -610,11 +619,16 @@ class SpecialFunctionButton : public Button void paint(BitmapBuffer *dc) override { - if (active) - dc->drawSolidFilledRect(0, 0, rect.w, rect.h, COLOR_THEME_ACTIVE); - else - dc->drawSolidFilledRect(0, 0, rect.w, rect.h, COLOR_THEME_PRIMARY2); + const CustomFunctionData *cfn = &functions[index]; + if(CFN_ACTIVE(cfn)) { + if (active) + dc->drawSolidFilledRect(0, 0, rect.w, rect.h, COLOR_THEME_ACTIVE); + else + dc->drawSolidFilledRect(0, 0, rect.w, rect.h, COLOR_THEME_PRIMARY2); + } else { + dc->drawSolidFilledRect(0, 0, rect.w, rect.h, COLOR_THEME_SECONDARY3); + } paintSpecialFunctionLine(dc); // The bounding rect diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 84e74307cfc..4f0b20a92b8 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -73,7 +73,7 @@ #define CFN_CH_INDEX(p) ((p)->all.param) #define CFN_GVAR_INDEX(p) ((p)->all.param) #define CFN_TIMER_INDEX(p) ((p)->all.param) -#define CFN_PLAY_REPEAT(p) ((p)->active) +#define CFN_PLAY_REPEAT(p) ((p)->repeat) #define CFN_PLAY_REPEAT_MUL 1 #define CFN_PLAY_REPEAT_NOSTART 0xFF #define CFN_GVAR_MODE(p) ((p)->all.mode) diff --git a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp index da804d3f291..4c2c8eaa30d 100644 --- a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp @@ -1463,28 +1463,31 @@ static void r_customFn(void* user, uint8_t* data, uint32_t bitoffs, val++; val_len--; } - if (HAS_ENABLE_PARAM(func)) { - // "0/1" - if (val_len > 0) { - if (val[0] == '0') { - CFN_ACTIVE(cfn) = 0; - } else if (val[0] == '1') { - CFN_ACTIVE(cfn) = 1; - } + // "0/1" + if (val_len > 0) { + if (val[0] == '0') { + CFN_ACTIVE(cfn) = 0; + } else if (val[0] == '1') { + CFN_ACTIVE(cfn) = 1; } - } else if (HAS_REPEAT_PARAM(func)) { - if (val_len == 2 - && val[0] == '1' - && val[1] == 'x') { - CFN_PLAY_REPEAT(cfn) = 0; - } else if (val_len == 3 - && val[0] == '!' - && val[1] == '1' - && val[2] == 'x') { - CFN_PLAY_REPEAT(cfn) = CFN_PLAY_REPEAT_NOSTART; + } else return; + + if (HAS_REPEAT_PARAM(func)) { + // eat_comma unconditionally + val += l_sep; + val_len -= l_sep; + if (val_len == 0 || val[0] != ',') return; + val++; + val_len--; + + if (val_len == 2 && val[0] == '1' && val[1] == 'x') { + CFN_PLAY_REPEAT(cfn) = 0; + } else if (val_len == 3 && val[0] == '!' && val[1] == '1' && + val[2] == 'x') { + CFN_PLAY_REPEAT(cfn) = (int8_t)CFN_PLAY_REPEAT_NOSTART; } else { - // repeat time in seconds - CFN_PLAY_REPEAT(cfn) = yaml_str2uint(val,val_len) / CFN_PLAY_REPEAT_MUL; + // repeat time in seconds + CFN_PLAY_REPEAT(cfn) = yaml_str2uint(val, val_len) / CFN_PLAY_REPEAT_MUL; } } } @@ -1609,26 +1612,24 @@ static bool w_customFn(void* user, uint8_t* data, uint32_t bitoffs, break; default: - add_comma = false; + //add_comma = false; break; } - if (HAS_ENABLE_PARAM(func)) { - if (add_comma) { - // "," - if (!wf(opaque,",",1)) return false; - } - // "0/1" - if (!wf(opaque,CFN_ACTIVE(cfn) ? "1":"0",1)) return false; - } else if (HAS_REPEAT_PARAM(func)) { - if (add_comma) { - // "," - if (!wf(opaque,",",1)) return false; - } + if (add_comma) { + // "," + if (!wf(opaque, ",", 1)) return false; + } + + // "0/1" + if (!wf(opaque, CFN_ACTIVE(cfn) ? "1" : "0", 1)) return false; + + if (HAS_REPEAT_PARAM(func)) { + if (!wf(opaque,",",1)) return false; if (CFN_PLAY_REPEAT(cfn) == 0) { // "1x" if (!wf(opaque,"1x",2)) return false; - } else if (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) { + } else if (CFN_PLAY_REPEAT(cfn) == (int8_t)CFN_PLAY_REPEAT_NOSTART) { // "!1x" if (!wf(opaque,"!1x",3)) return false; } else { @@ -1637,6 +1638,7 @@ static bool w_customFn(void* user, uint8_t* data, uint32_t bitoffs, if (!wf(opaque, str, strlen(str))) return false; } } + if (!wf(opaque, "\"", 1)) return false; return true; }