diff --git a/companion/src/constants.h b/companion/src/constants.h index 14e54fd44..787016139 100644 --- a/companion/src/constants.h +++ b/companion/src/constants.h @@ -47,6 +47,7 @@ #define CPN_MAX_SCRIPT_INPUTS 10 #define CPN_MAX_SPACEMOUSE 6 #define CPN_MAX_INPUTS 32 // v2.10 replaces CPN_MAX_ANALOGS - the value is abitary as radio ADC refactor is still a WIP +#define CPN_MAX_FUNCTIONSWITCH_GROUP 3 // pre v2.10 #define CPN_MAX_POTS 8 diff --git a/companion/src/datamodels/compounditemmodels.cpp b/companion/src/datamodels/compounditemmodels.cpp index 466e0042f..a61b09488 100644 --- a/companion/src/datamodels/compounditemmodels.cpp +++ b/companion/src/datamodels/compounditemmodels.cpp @@ -115,6 +115,7 @@ RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSett addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, -firmware->getCapability(TrainerInputs)); addItems(SOURCE_TYPE_CYC, RawSource::SourcesGroup, -CPN_MAX_CYC); addItems(SOURCE_TYPE_CUSTOM_SWITCH, RawSource::SwitchesGroup, -firmware->getCapability(LogicalSwitches)); + addItems(SOURCE_TYPE_FUNCTIONSWITCH_GROUP, RawSource::SourcesGroup, -CPN_MAX_FUNCTIONSWITCH_GROUP); addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, -board->getCapability(Board::Switches)); addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, -1); addItems(SOURCE_TYPE_MIN, RawSource::SourcesGroup, -1); @@ -136,6 +137,7 @@ RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSett addItems(SOURCE_TYPE_MIN, RawSource::SourcesGroup, 1); addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, 1); addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, board->getCapability(Board::Switches)); + addItems(SOURCE_TYPE_FUNCTIONSWITCH_GROUP, RawSource::SourcesGroup, CPN_MAX_FUNCTIONSWITCH_GROUP); addItems(SOURCE_TYPE_CUSTOM_SWITCH, RawSource::SwitchesGroup, firmware->getCapability(LogicalSwitches)); addItems(SOURCE_TYPE_CYC, RawSource::SourcesGroup, CPN_MAX_CYC); addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, firmware->getCapability(TrainerInputs)); diff --git a/companion/src/firmwares/edgetx/yaml_rawsource.cpp b/companion/src/firmwares/edgetx/yaml_rawsource.cpp index 387f8cb42..87e555fd0 100644 --- a/companion/src/firmwares/edgetx/yaml_rawsource.cpp +++ b/companion/src/firmwares/edgetx/yaml_rawsource.cpp @@ -51,6 +51,9 @@ std::string YamlRawSourceEncode(const RawSource& rhs) case SOURCE_TYPE_VIRTUAL_INPUT: src_str += "I" + std::to_string(sval - 1); break; + case SOURCE_TYPE_FUNCTIONSWITCH_GROUP: + src_str += "GR" + std::to_string(sval); + break; case SOURCE_TYPE_LUA_OUTPUT: qr = div(sval - 1, 16); src_str += "lua("; @@ -168,7 +171,15 @@ RawSource YamlRawSourceDecode(const std::string& src_str) if (idx >= 0) { rhs = RawSource(SOURCE_TYPE_SWITCH, idx + 1); } + } else if ((val_len == 3 && + val[0] == 'G' && + val[1] >= 'R' && + val[2] >= '1' && val[2] <= '3')) { + int idx = std::stoi(src_str_tmp.substr(2)); + if (idx >= 0) { + rhs = RawSource(SOURCE_TYPE_FUNCTIONSWITCH_GROUP, idx); + } } else if (val_len > 4 && val[0] == 'l' && val[1] == 'u' && diff --git a/companion/src/firmwares/rawsource.cpp b/companion/src/firmwares/rawsource.cpp index 489128df6..0ca893d42 100644 --- a/companion/src/firmwares/rawsource.cpp +++ b/companion/src/firmwares/rawsource.cpp @@ -22,6 +22,7 @@ #include "eeprominterface.h" #include "radiodata.h" +#include "modeldata.h" #include "radiodataconversionstate.h" #include @@ -255,6 +256,9 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con case SOURCE_TYPE_SPACEMOUSE: return tr("sm%1").arg(QChar('A' + (index - 1))); + case SOURCE_TYPE_FUNCTIONSWITCH_GROUP: + return tr("GR%1").arg(index); + default: return QString(CPN_STR_UNKNOWN_ITEM); } @@ -284,9 +288,14 @@ bool RawSource::isAvailable(const ModelData * const model, const GeneralSettings if (type == SOURCE_TYPE_CH && abs(index) > CPN_MAX_CHNOUT) return false; + if (type == SOURCE_TYPE_FUNCTIONSWITCH_GROUP && index >= b.getCapability(Board::FunctionSwitches)) + return false; + if (type == SOURCE_TYPE_CUSTOM_SWITCH && abs(index) > CPN_MAX_LOGICAL_SWITCHES) return false; + if (type == SOURCE_TYPE_FUNCTIONSWITCH_GROUP && model->getFuncGroupSwitchCount(abs(index), CPN_MAX_SWITCHES_FUNCTION) == 0) + return false; if (type == SOURCE_TYPE_LUA_OUTPUT && div(abs(index - 1), 16).quot >= CPN_MAX_SCRIPTS) return false; diff --git a/companion/src/firmwares/rawsource.h b/companion/src/firmwares/rawsource.h index 4d654958a..baef765a3 100644 --- a/companion/src/firmwares/rawsource.h +++ b/companion/src/firmwares/rawsource.h @@ -181,6 +181,7 @@ enum RawSourceType { SOURCE_TYPE_TELEMETRY, SOURCE_TYPE_SPACEMOUSE, SOURCE_TYPE_TIMER, + SOURCE_TYPE_FUNCTIONSWITCH_GROUP, MAX_SOURCE_TYPE }; diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index 24a7bee09..db6642c62 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -1255,7 +1255,7 @@ bool FilteredGroupSwitchesModel::filterAcceptsRow(int sourceRow, const QModelInd return false; return true; } - if (m_model->getFuncSwitchGroup(sourceRow - 1) == m_group) + if ((int)m_model->getFuncSwitchGroup(sourceRow - 1) == m_group) return true; return false; } @@ -1503,6 +1503,7 @@ void FunctionSwitchesPanel::on_groupChanged(int value) model->setFuncGroupSwitchStart(oldGrp, model->getFuncGroupSwitchStart(oldGrp, switchcnt), switchcnt); update(); emit modified(); + emit updateDataModels(); } lock = false; } @@ -1524,12 +1525,12 @@ void FunctionSwitchesPanel::on_alwaysOnGroupChanged(int value) model->setFuncSwitchAlwaysOnGroup(grp, (unsigned int)value); if (value) { for (int i = 0; i < switchcnt; i += 1) { - if ((model->getFuncSwitchGroup(i) == grp) && (model->getFuncSwitchConfig(i) == ModelData::FUNC_SWITCH_CONFIG_TOGGLE)) + if (((int)model->getFuncSwitchGroup(i) == grp) && (model->getFuncSwitchConfig(i) == ModelData::FUNC_SWITCH_CONFIG_TOGGLE)) model->setFuncSwitchConfig(i, ModelData::FUNC_SWITCH_CONFIG_2POS); } - if (model->getFuncGroupSwitchStart(grp, switchcnt) == switchcnt + 1) { + if ((int)model->getFuncGroupSwitchStart(grp, switchcnt) == switchcnt + 1) { for (int i = 0; i < switchcnt; i += 1) { - if (model->getFuncSwitchGroup(i) == grp) + if ((int)model->getFuncSwitchGroup(i) == grp) model->setFuncSwitchStart(i, ModelData::FUNC_SWITCH_START_PREVIOUS); } } diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index 0f738a51c..fcc2f59f5 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -514,6 +514,10 @@ enum MixSources { MIXSRC_FIRST_SWITCH SKIP, MIXSRC_LAST_SWITCH SKIP = MIXSRC_FIRST_SWITCH + MAX_SWITCHES - 1, +#if defined(FUNCTION_SWITCHES) + MIXSRC_FIRST_CUSTOMSWITCH_GROUP SKIP, + MIXSRC_LAST_CUSTOMSWITCH_GROUP SKIP = MIXSRC_FIRST_CUSTOMSWITCH_GROUP + NUM_FUNCTIONS_GROUPS - 1, +#endif MIXSRC_FIRST_LOGICAL_SWITCH SKIP, MIXSRC_LAST_LOGICAL_SWITCH SKIP = MIXSRC_FIRST_LOGICAL_SWITCH + MAX_LOGICAL_SWITCHES - 1, diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index dd228c5b8..c4daededb 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -241,6 +241,11 @@ bool isSourceAvailable(int source) if (source >= MIXSRC_FIRST_TRAINER && source <= MIXSRC_LAST_TRAINER) return g_model.trainerData.mode > 0; +#if defined(FUNCTION_SWITCHES) + if (source >= MIXSRC_FIRST_CUSTOMSWITCH_GROUP && source <= MIXSRC_LAST_CUSTOMSWITCH_GROUP) + return getSwitchCountInFSGroup(source - MIXSRC_FIRST_CUSTOMSWITCH_GROUP + 1) > 0; +#endif + if (source >= MIXSRC_FIRST_CH && source <= MIXSRC_LAST_CH) { return isChannelUsed(source - MIXSRC_FIRST_CH); } @@ -323,6 +328,11 @@ bool isSourceAvailableInInputs(int source) if (source >= MIXSRC_FIRST_SWITCH && source <= MIXSRC_LAST_SWITCH) return SWITCH_EXISTS(source - MIXSRC_FIRST_SWITCH); +#if defined(FUNCTION_SWITCHES) + if (source >= MIXSRC_FIRST_CUSTOMSWITCH_GROUP && source <= MIXSRC_LAST_CUSTOMSWITCH_GROUP) + return getSwitchCountInFSGroup(source - MIXSRC_FIRST_CUSTOMSWITCH_GROUP + 1) > 0; +#endif + if (source >= MIXSRC_FIRST_CH && source <= MIXSRC_LAST_CH) return true; diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index 9242902fb..9b8b3dac2 100644 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -425,6 +425,30 @@ getvalue_t _getValue(mixsrc_t i, bool* valid) return _switch_3pos_lookup[switchGetPosition(sw_idx)]; } } +#if defined(FUNCTION_SWITCHES) + else if (i <= MIXSRC_LAST_CUSTOMSWITCH_GROUP) { + uint8_t group_idx = (uint8_t)(i - MIXSRC_FIRST_CUSTOMSWITCH_GROUP + 1); + uint8_t stepcount = getSwitchCountInFSGroup(group_idx); + if (stepcount == 0) + return 0; + + if (IS_FSWITCH_GROUP_ON(group_idx)) + stepcount--; + + int stepsize = (2 * RESX) / stepcount; + int value = -RESX; + + for (uint8_t i = 0; i < switchGetMaxFctSwitches(); i++) { + if(FSWITCH_GROUP(i) == group_idx) { + if (getFSLogicalState(i) == 1) + return value + (IS_FSWITCH_GROUP_ON(group_idx) ? 0 : stepsize); + else + value += stepsize; + } + } + return -RESX; + } +#endif else if (i <= MIXSRC_LAST_LOGICAL_SWITCH) { return getSwitch(SWSRC_FIRST_LOGICAL_SWITCH + i - MIXSRC_FIRST_LOGICAL_SWITCH) ? 1024 : -1024; diff --git a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp index 71c95a96d..9bfeb6d9e 100644 --- a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp @@ -215,7 +215,15 @@ static uint32_t r_mixSrcRaw(const YamlNode* node, const char* val, uint8_t val_l val += 3; val_len -= 3; // parse int and ignore closing ')' return yaml_str2uint(val, val_len) + MIXSRC_FIRST_GVAR; +#if defined(FUNCTION_SWITCHES) + } else if (val_len > 2 && + val[0] == 'G' && + val[1] == 'R' && + val[2] >= '1' && + val[2] <= '3') { + return MIXSRC_FIRST_CUSTOMSWITCH_GROUP + (val[2] - '1'); +#endif } else if (val_len > 5 && val[0] == 't' && val[1] == 'e' && @@ -353,6 +361,12 @@ static bool w_mixSrcRaw(const YamlNode* node, uint32_t val, yaml_writer_func wf, && val <= MIXSRC_LAST_SWITCH) { str = switchGetCanonicalName(val - MIXSRC_FIRST_SWITCH); } +#if defined(FUNCTION_SWITCHES) + else if (val >= MIXSRC_FIRST_CUSTOMSWITCH_GROUP + && val <= MIXSRC_LAST_CUSTOMSWITCH_GROUP) { + str = fsSwitchGroupGetCanonicalName(val - MIXSRC_FIRST_CUSTOMSWITCH_GROUP); + } +#endif else if (val >= MIXSRC_FIRST_LOGICAL_SWITCH && val <= MIXSRC_LAST_LOGICAL_SWITCH) { diff --git a/radio/src/strhelpers.cpp b/radio/src/strhelpers.cpp index a8739f410..01f0c7888 100644 --- a/radio/src/strhelpers.cpp +++ b/radio/src/strhelpers.cpp @@ -450,6 +450,13 @@ char *getFlightModeString(char *dest, int8_t idx) return dest; } +char *getCustomSwitchesGroupName(char *dest, uint8_t idx) +{ + dest = strAppendStringWithIndex(dest, "GR", idx + 1); + + return dest; +} + char *getSwitchName(char *dest, uint8_t idx) { if (switchHasCustomName(idx)) { @@ -738,6 +745,12 @@ char *getSourceString(char (&destRef)[L], mixsrc_t idx) idx -= MIXSRC_FIRST_SWITCH; char *pos = strAppend(dest, STR_CHAR_SWITCH, sizeof(STR_CHAR_SWITCH) - 1); getSwitchName(pos, idx); +#if defined(FUNCTION_SWITCHES) + } else if (idx <= MIXSRC_LAST_CUSTOMSWITCH_GROUP) { + idx -= MIXSRC_FIRST_CUSTOMSWITCH_GROUP; + char *pos = strAppend(dest, STR_CHAR_SWITCH, sizeof(STR_CHAR_SWITCH) - 1); + getCustomSwitchesGroupName(pos, idx); +#endif } else if (idx <= MIXSRC_LAST_LOGICAL_SWITCH) { // TODO: unnecessary, use the direct way instead idx -= MIXSRC_FIRST_LOGICAL_SWITCH; diff --git a/radio/src/strhelpers.h b/radio/src/strhelpers.h index 532372b65..85d51c9e5 100644 --- a/radio/src/strhelpers.h +++ b/radio/src/strhelpers.h @@ -109,6 +109,7 @@ const char *getMainControlLabel(uint8_t idx); const char *getTrimLabel(uint8_t idx); const char *getTrimSourceLabel(uint16_t src_raw, int8_t trim_src); const char *getPotLabel(uint8_t idx); +char *getCustomSwitchesGroupName(char *dest, uint8_t idx); template char *getSourceString(char (&dest)[L], mixsrc_t idx); diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp index 88a2c35a9..384d2dcd0 100644 --- a/radio/src/switches.cpp +++ b/radio/src/switches.cpp @@ -136,6 +136,23 @@ uint8_t getFSPreviousPhysicalState(uint8_t index) return (uint8_t )(bfSingleBitGet(fsPreviousState, index) >> (index)); } +uint8_t getSwitchCountInFSGroup(uint8_t index) +{ + uint8_t count = 0; + + for (uint8_t i = 0; i < switchGetMaxFctSwitches(); i++) { + if (FSWITCH_GROUP(i) == index) + count++; + } + + return count; +} + +bool isFSGroupUsed(uint8_t index) +{ + return getSwitchCountInFSGroup(index) != 0; +} + void evalFunctionSwitches() { uint8_t fct_switches = switchGetMaxFctSwitches(); @@ -312,6 +329,13 @@ const char* switchGetCanonicalName(uint8_t idx) return switchGetName(idx); } +const char* fsSwitchGroupGetCanonicalName(uint8_t idx) +{ + static const char fsgroupname[3][4] = {"GR1", "GR2", "GR3"}; + + return &fsgroupname[idx][0]; +} + SwitchConfig switchGetMaxType(uint8_t idx) { auto hw_type = switchGetHwType(idx); diff --git a/radio/src/switches.h b/radio/src/switches.h index a4e4a86b0..7bef0bae0 100644 --- a/radio/src/switches.h +++ b/radio/src/switches.h @@ -79,9 +79,11 @@ char switchGetLetter(uint8_t idx); const char* switchGetCanonicalName(uint8_t idx); // customizable switches supported +const char* fsSwitchGroupGetCanonicalName(uint8_t idx); void switchSetCustomName(uint8_t idx, const char* str, size_t len); const char* switchGetCustomName(uint8_t idx); bool switchHasCustomName(uint8_t idx); +uint8_t getSwitchCountInFSGroup(uint8_t index); SwitchConfig switchGetMaxType(uint8_t idx); diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index c4264f2c6..ef624a08e 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -328,6 +328,7 @@ void bluetoothDisable(); #if defined(FUNCTION_SWITCHES) #define NUM_FUNCTIONS_SWITCHES 6 +#define NUM_FUNCTIONS_GROUPS 3 #define DEFAULT_FS_CONFIG \ (SWITCH_2POS << 10) + (SWITCH_2POS << 8) + (SWITCH_2POS << 6) + \ (SWITCH_2POS << 4) + (SWITCH_2POS << 2) + (SWITCH_2POS << 0) diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 239877dd6..d95d69e05 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -110,6 +110,7 @@ uint32_t isBootloaderStart(const uint8_t * buffer); #if defined(FUNCTION_SWITCHES) #define NUM_FUNCTIONS_SWITCHES 6 +#define NUM_FUNCTIONS_GROUPS 3 #define DEFAULT_FS_CONFIG \ (SWITCH_2POS << 10) + (SWITCH_2POS << 8) + (SWITCH_2POS << 6) + \