diff --git a/companion/src/constants.h b/companion/src/constants.h index ea7fd5b93..14e54fd44 100644 --- a/companion/src/constants.h +++ b/companion/src/constants.h @@ -92,6 +92,8 @@ #define CPN_STR_SW_INDICATOR_NEUT QCoreApplication::translate("RawSwitch", "-") // Switch neutral (middle) position indicator. #define CPN_STR_SW_INDICATOR_REV QCoreApplication::translate("RawSwitch", "!") // Switch reversed logic (NOT) indicator. +#define CPN_STR_SRC_INDICATOR_INVERT QCoreApplication::translate("RawSource", "!") // Source inverted logic indicator. + #define EDGETX_HOME_PAGE_URL "https://edgetx.org" #define CPN_ADC_REFACTOR_VERSION "2.10.0" diff --git a/companion/src/datamodels/compounditemmodels.cpp b/companion/src/datamodels/compounditemmodels.cpp index 2a3efd6a5..466e0042f 100644 --- a/companion/src/datamodels/compounditemmodels.cpp +++ b/companion/src/datamodels/compounditemmodels.cpp @@ -106,11 +106,31 @@ RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSett setId(IMID_RawSource); setUpdateMask(IMUE_All &~ (IMUE_Curves | IMUE_Scripts)); + // Descending source direction: inverted (!) sources + addItems(SOURCE_TYPE_TELEMETRY, RawSource::TelemGroup, -firmware->getCapability(Sensors) * 3); + addItems(SOURCE_TYPE_TIMER, RawSource::TelemGroup, -firmware->getCapability(Timers)); + addItems(SOURCE_TYPE_SPECIAL, RawSource::TelemGroup, -(SOURCE_TYPE_SPECIAL_COUNT - 1)); + addItems(SOURCE_TYPE_GVAR, RawSource::GVarsGroup, -firmware->getCapability(Gvars)); + addItems(SOURCE_TYPE_CH, RawSource::SourcesGroup, -firmware->getCapability(Outputs)); + 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_SWITCH, RawSource::SwitchesGroup, -board->getCapability(Board::Switches)); + addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, -1); + addItems(SOURCE_TYPE_MIN, RawSource::SourcesGroup, -1); + addItems(SOURCE_TYPE_SPACEMOUSE, RawSource::SourcesGroup, -CPN_MAX_SPACEMOUSE); + addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, -board->getCapability(Board::NumTrims)); + addItems(SOURCE_TYPE_INPUT, RawSource::SourcesGroup, -board->getCapability(Board::Inputs)); + addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, -firmware->getCapability(VirtualInputs)); + for (int i = firmware->getCapability(LuaScripts) - 1; i >= 0; i--) + addItems(SOURCE_TYPE_LUA_OUTPUT, RawSource::ScriptsGroup, -firmware->getCapability(LuaOutputsPerScript), -i * 16); + + // Ascending source direction (including zero) addItems(SOURCE_TYPE_NONE, RawSource::NoneGroup, 1); for (int i = 0; i < firmware->getCapability(LuaScripts); i++) addItems(SOURCE_TYPE_LUA_OUTPUT, RawSource::ScriptsGroup, firmware->getCapability(LuaOutputsPerScript), i * 16); addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, firmware->getCapability(VirtualInputs)); - addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, board->getCapability(Board::Inputs)); + addItems(SOURCE_TYPE_INPUT, RawSource::SourcesGroup, board->getCapability(Board::Inputs)); addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, board->getCapability(Board::NumTrims)); addItems(SOURCE_TYPE_SPACEMOUSE, RawSource::SourcesGroup, CPN_MAX_SPACEMOUSE); addItems(SOURCE_TYPE_MIN, RawSource::SourcesGroup, 1); @@ -121,7 +141,8 @@ RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSett addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, firmware->getCapability(TrainerInputs)); addItems(SOURCE_TYPE_CH, RawSource::SourcesGroup, firmware->getCapability(Outputs)); addItems(SOURCE_TYPE_GVAR, RawSource::GVarsGroup, firmware->getCapability(Gvars)); - addItems(SOURCE_TYPE_SPECIAL, RawSource::TelemGroup, SOURCE_TYPE_SPECIAL_COUNT); + addItems(SOURCE_TYPE_SPECIAL, RawSource::TelemGroup, SOURCE_TYPE_SPECIAL_COUNT - 1); + addItems(SOURCE_TYPE_TIMER, RawSource::TelemGroup, firmware->getCapability(Timers)); addItems(SOURCE_TYPE_TELEMETRY, RawSource::TelemGroup, firmware->getCapability(Sensors) * 3); } @@ -131,14 +152,19 @@ void RawSourceItemModel::setDynamicItemData(QStandardItem * item, const RawSourc item->setData(src.isAvailable(modelData, generalSettings, boardType), IMDR_Available); } -void RawSourceItemModel::addItems(const RawSourceType & type, const int group, const int count, const int start) +void RawSourceItemModel::addItems(const RawSourceType & type, const int group, int count, const int start) { - for (int i = start; i < start + count; i++) { - const RawSource src = RawSource(type, i); + const int idxAdj = (type == SOURCE_TYPE_NONE ? -1 : 0); + + int first = start + count < 0 ? start + count : start + 1; + int last = start + count < 0 ? start : start + count + 1; + + for (int i = first; i < last; ++i) { + const RawSource src = RawSource(type, i + idxAdj); QStandardItem * modelItem = new QStandardItem(); modelItem->setData(src.toValue(), IMDR_Id); modelItem->setData(type, IMDR_Type); - modelItem->setData(group, IMDR_Flags); + modelItem->setData((group | (i + idxAdj < 0 ? RawSource::NegativeGroup : i > 0 ? RawSource::PositiveGroup : 0)), IMDR_Flags); setDynamicItemData(modelItem, src); appendRow(modelItem); } diff --git a/companion/src/datamodels/compounditemmodels.h b/companion/src/datamodels/compounditemmodels.h index 65adfed2d..a3f857213 100644 --- a/companion/src/datamodels/compounditemmodels.h +++ b/companion/src/datamodels/compounditemmodels.h @@ -197,7 +197,7 @@ class RawSourceItemModel: public AbstractDynamicItemModel protected: virtual void setDynamicItemData(QStandardItem * item, const RawSource & src) const; - void addItems(const RawSourceType & type, const int group, const int count, const int start = 0); + void addItems(const RawSourceType & type, const int group, int count, const int start = 0); }; class RawSwitchItemModel: public AbstractDynamicItemModel diff --git a/companion/src/firmwares/adjustmentreference.cpp b/companion/src/firmwares/adjustmentreference.cpp index ae487effa..7bd7bb8f3 100644 --- a/companion/src/firmwares/adjustmentreference.cpp +++ b/companion/src/firmwares/adjustmentreference.cpp @@ -61,7 +61,7 @@ QString AdjustmentReference::toString(const ModelData * model, const bool sign) switch(type) { case ADJUST_REF_GVAR: - ret = RawSource(SOURCE_TYPE_GVAR, abs(value) - 1).toString(model); + ret = RawSource(SOURCE_TYPE_GVAR, abs(value)).toString(model); if (value < 0) ret.prepend("-"); else if (sign) diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp index f3bbfedd8..a05be97b0 100644 --- a/companion/src/firmwares/boards.cpp +++ b/companion/src/firmwares/boards.cpp @@ -80,8 +80,7 @@ Boards::Boards(Board::Type board) : legacyTrimSourcesLookupTable(legacyTrimSourcesLut), trimSwitchesLookupTable(trimSwitchesLut), rawSwitchTypesLookupTable(RawSwitch::getRawSwitchTypesLookupTable()), - rawSourceSpecialTypesLookupTable(RawSource::getSpecialTypesLookupTable()), - rawSourceCyclicLookupTable(RawSource::getCyclicLookupTable()) + rawSourceSpecialTypesLookupTable(RawSource::getSpecialTypesLookupTable()) { setBoardType(board); } diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index fb18d4834..68493d5af 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -355,7 +355,6 @@ class Boards STRINGTAGMAPPINGFUNCS(trimSwitchesLookupTable, TrimSwitch); STRINGTAGMAPPINGFUNCS(rawSwitchTypesLookupTable, RawSwitchType); STRINGTAGMAPPINGFUNCS(rawSourceSpecialTypesLookupTable, RawSourceSpecialType); - STRINGTAGMAPPINGFUNCS(rawSourceCyclicLookupTable, RawSourceCyclic); static bool isInputAvailable(int index, Board::Type board = Board::BOARD_UNKNOWN); static bool isInputCalibrated(int index, Board::Type board = Board::BOARD_UNKNOWN); @@ -382,7 +381,6 @@ class Boards const StringTagMappingTable trimSwitchesLookupTable; const StringTagMappingTable rawSwitchTypesLookupTable; const StringTagMappingTable rawSourceSpecialTypesLookupTable; - const StringTagMappingTable rawSourceCyclicLookupTable; static StringTagMappingTable getLegacyAnalogsLookupTable(Board::Type board = Board::BOARD_UNKNOWN); }; diff --git a/companion/src/firmwares/customfunctiondata.cpp b/companion/src/firmwares/customfunctiondata.cpp index e1fdf250e..69ddac14a 100644 --- a/companion/src/firmwares/customfunctiondata.cpp +++ b/companion/src/firmwares/customfunctiondata.cpp @@ -62,7 +62,7 @@ QString CustomFunctionData::funcToString(const ModelData * model) const QString CustomFunctionData::funcToString(const AssignFunc func, const ModelData * model) { if (func >= FuncOverrideCH1 && func <= FuncOverrideCHLast) - return tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString(model)); + return tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func + 1).toString(model)); else if (func == FuncTrainer) return tr("Trainer Axis"); else if (func == FuncTrainerRUD) @@ -84,7 +84,7 @@ QString CustomFunctionData::funcToString(const AssignFunc func, const ModelData else if (func == FuncReset) return tr("Reset"); else if (func >= FuncSetTimer1 && func <= FuncSetTimerLast) - return tr("Set %1").arg(RawSource(SOURCE_TYPE_SPECIAL, SOURCE_TYPE_SPECIAL_FIRST_TIMER + func - FuncSetTimer1).toString(model)); + return tr("Set %1").arg(RawSource(SOURCE_TYPE_TIMER, func - FuncSetTimer1 + 1).toString(model)); else if (func == FuncVario) return tr("Vario"); else if (func == FuncPlayPrompt) @@ -108,7 +108,7 @@ QString CustomFunctionData::funcToString(const AssignFunc func, const ModelData else if (func == FuncBackgroundMusicPause) return tr("Background Music Pause"); else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) - return tr("Adjust %1").arg(RawSource(SOURCE_TYPE_GVAR, func - FuncAdjustGV1).toString(model)); + return tr("Adjust %1").arg(RawSource(SOURCE_TYPE_GVAR, func - FuncAdjustGV1 + 1).toString(model)); else if (func == FuncSetFailsafe) return tr("Set Failsafe"); else if (func == FuncRangeCheckInternalModule) @@ -281,7 +281,7 @@ QString CustomFunctionData::resetToString(const int value, const ModelData * mod if (value < step) { if (value < firmware->getCapability(Timers)) - return RawSource(SOURCE_TYPE_SPECIAL, value + SOURCE_TYPE_SPECIAL_FIRST_TIMER).toString(model); + return RawSource(SOURCE_TYPE_TIMER, value).toString(model); else return QString(CPN_STR_UNKNOWN_ITEM); } @@ -293,7 +293,7 @@ QString CustomFunctionData::resetToString(const int value, const ModelData * mod return tr("Telemetry"); if (value < step + firmware->getCapability(Sensors)) - return RawSource(SOURCE_TYPE_TELEMETRY, 3 * (value - step)).toString(model); + return RawSource(SOURCE_TYPE_TELEMETRY, 3 * (value - step + 1)).toString(model); return QString(CPN_STR_UNKNOWN_ITEM); } diff --git a/companion/src/firmwares/customfunctiondata.h b/companion/src/firmwares/customfunctiondata.h index 6f5a503ca..b52d9f0cb 100644 --- a/companion/src/firmwares/customfunctiondata.h +++ b/companion/src/firmwares/customfunctiondata.h @@ -36,7 +36,6 @@ class AbstractStaticItemModel; enum AssignFunc { FuncOverrideCH1 = 0, FuncOverrideCHLast = FuncOverrideCH1 + CPN_MAX_CHNOUT - 1, - FuncOverrideCH32 = FuncOverrideCHLast, // TODO remove FuncTrainer, FuncTrainerRUD, FuncTrainerELE, @@ -48,8 +47,6 @@ enum AssignFunc { FuncPlayHaptic, FuncReset, FuncSetTimer1, - FuncSetTimer2, // TODO remove - FuncSetTimer3, // TODO remove FuncSetTimerLast = FuncSetTimer1 + CPN_MAX_TIMERS - 1, FuncVario, FuncPlayPrompt, diff --git a/companion/src/firmwares/edgetx/yaml_modeldata.cpp b/companion/src/firmwares/edgetx/yaml_modeldata.cpp index edab2d43a..e3270ddc6 100644 --- a/companion/src/firmwares/edgetx/yaml_modeldata.cpp +++ b/companion/src/firmwares/edgetx/yaml_modeldata.cpp @@ -167,7 +167,7 @@ struct YamlThrTrace { YamlThrTrace(unsigned int cpn_value) { if (cpn_value == 0) { - src = RawSource(SOURCE_TYPE_STICK, 2/* throttle */); + src = RawSource(SOURCE_TYPE_INPUT, 2/* throttle */); return; } cpn_value--; @@ -175,7 +175,7 @@ struct YamlThrTrace { int pots = board.getCapability(Board::Pots); int sliders = board.getCapability(Board::Sliders); if (cpn_value < (unsigned int)(pots + sliders)) { - src = RawSource(SOURCE_TYPE_STICK, 4/* sticks */ + cpn_value); + src = RawSource(SOURCE_TYPE_INPUT, 4/* sticks */ + cpn_value); } else { cpn_value -= pots + sliders; @@ -186,7 +186,7 @@ struct YamlThrTrace { unsigned int toCpn() { switch (src.type) { - case SOURCE_TYPE_STICK: + case SOURCE_TYPE_INPUT: if (src.index == 2 /* throttle */) { return 0; } else { diff --git a/companion/src/firmwares/edgetx/yaml_rawsource.cpp b/companion/src/firmwares/edgetx/yaml_rawsource.cpp index 35d596166..387f8cb42 100644 --- a/companion/src/firmwares/edgetx/yaml_rawsource.cpp +++ b/companion/src/firmwares/edgetx/yaml_rawsource.cpp @@ -23,37 +23,47 @@ #include "boardjson.h" static const YamlLookupTable spacemouseLut = { - { 0, "SPACEMOUSE_A" }, - { 1, "SPACEMOUSE_B" }, - { 2, "SPACEMOUSE_C" }, - { 3, "SPACEMOUSE_D" }, - { 4, "SPACEMOUSE_E" }, - { 5, "SPACEMOUSE_F" }, + { 0, "INVALID" }, + { 1, "SPACEMOUSE_A" }, + { 2, "SPACEMOUSE_B" }, + { 3, "SPACEMOUSE_C" }, + { 4, "SPACEMOUSE_D" }, + { 5, "SPACEMOUSE_E" }, + { 6, "SPACEMOUSE_F" }, }; - std::string YamlRawSourceEncode(const RawSource& rhs) { Board::Type board = getCurrentBoard(); Boards b = Boards(board); std::string src_str; + div_t qr; char c = 'A'; + + int32_t sval = rhs.index; + + if (rhs.index < 0) { + sval = -sval; + src_str += "!"; + } + switch (rhs.type) { case SOURCE_TYPE_VIRTUAL_INPUT: - src_str += "I" + std::to_string(rhs.index); + src_str += "I" + std::to_string(sval - 1); break; case SOURCE_TYPE_LUA_OUTPUT: + qr = div(sval - 1, 16); src_str += "lua("; - src_str += std::to_string(rhs.index / 16); + src_str += std::to_string(qr.quot); src_str += ","; - src_str += std::to_string(rhs.index % 16); + src_str += std::to_string(qr.rem); src_str += ")"; break; - case SOURCE_TYPE_STICK: - src_str = Boards::getInputYamlName(rhs.index, BoardJson::YLT_REF).toStdString(); + case SOURCE_TYPE_INPUT: + src_str += Boards::getInputYamlName(sval - 1, BoardJson::YLT_REF).toStdString(); break; case SOURCE_TYPE_TRIM: - src_str = Boards::getTrimYamlName(rhs.index, BoardJson::YLT_REF).toStdString(); + src_str += Boards::getTrimYamlName(sval - 1, BoardJson::YLT_REF).toStdString(); break; case SOURCE_TYPE_MIN: src_str += "MIN"; @@ -62,37 +72,41 @@ std::string YamlRawSourceEncode(const RawSource& rhs) src_str += "MAX"; break; case SOURCE_TYPE_SWITCH: - src_str += Boards::getSwitchYamlName(rhs.index, BoardJson::YLT_REF).toStdString(); + src_str += Boards::getSwitchYamlName(sval - 1, BoardJson::YLT_REF).toStdString(); break; case SOURCE_TYPE_CUSTOM_SWITCH: src_str += "ls("; - src_str += std::to_string(rhs.index + 1); + src_str += std::to_string(sval); src_str += ")"; break; case SOURCE_TYPE_CYC: - src_str = b.getRawSourceCyclicTag(rhs.index); + src_str += "CYC" + std::to_string(sval); break; case SOURCE_TYPE_PPM: src_str += "tr("; - src_str += std::to_string(rhs.index); + src_str += std::to_string(sval - 1); src_str += ")"; break; case SOURCE_TYPE_CH: src_str += "ch("; - src_str += std::to_string(rhs.index); + src_str += std::to_string(sval - 1); src_str += ")"; break; case SOURCE_TYPE_GVAR: src_str += "gv("; - src_str += std::to_string(rhs.index); + src_str += std::to_string(sval - 1); src_str += ")"; break; case SOURCE_TYPE_SPECIAL: - src_str = b.getRawSourceSpecialTypeTag(rhs.index); + src_str += b.getRawSourceSpecialTypeTag(sval); + break; + case SOURCE_TYPE_TIMER: + src_str += "Tmr" + std::to_string(sval); break; case SOURCE_TYPE_TELEMETRY: - src_str = "tele("; - switch (rhs.index % 3) { + qr = div(sval - 1, 3); + src_str += "tele("; + switch (qr.rem) { case 0: break; case 1: @@ -102,12 +116,12 @@ std::string YamlRawSourceEncode(const RawSource& rhs) src_str += '+'; break; } - src_str += std::to_string(rhs.index / 3); + src_str += std::to_string(qr.quot); src_str += ")"; break; case SOURCE_TYPE_SPACEMOUSE: - src_str = "SPACEMOUSE_"; - c += rhs.index; + src_str += "SPACEMOUSE_"; + c += sval - 1; src_str += c; break; default: @@ -124,13 +138,22 @@ RawSource YamlRawSourceDecode(const std::string& src_str) RawSource rhs; const char* val = src_str.data(); size_t val_len = src_str.size(); + std::string src_str_tmp = src_str; + bool neg = false; + + if (val_len > 0 && val[0] == '!') { + neg = true; + val++; + val_len--; + src_str_tmp = src_str_tmp.substr(1); + } if (val_len > 1 && val[0] == 'I' && (val[1] >= '0') && (val[1] <= '9')) { - int idx = std::stoi(src_str.substr(1)); + int idx = std::stoi(src_str_tmp.substr(1)); if (idx < CPN_MAX_INPUTS) { - rhs = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, idx); + rhs = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, idx + 1); } } else if ((val_len == 2 && @@ -141,9 +164,9 @@ RawSource YamlRawSourceDecode(const std::string& src_str) (val[0] == 'S' && val[1] == 'W')) && val[2] >= '1' && val[2] <= '9')) { - int idx = Boards::getSwitchYamlIndex(src_str.c_str(), BoardJson::YLT_REF); + int idx = Boards::getSwitchYamlIndex(src_str_tmp.c_str(), BoardJson::YLT_REF); if (idx >= 0) { - rhs = RawSource(SOURCE_TYPE_SWITCH, idx); + rhs = RawSource(SOURCE_TYPE_SWITCH, idx + 1); } } else if (val_len > 4 && @@ -152,24 +175,24 @@ RawSource YamlRawSourceDecode(const std::string& src_str) val[2] == 'a' && val[3] == '(') { - std::stringstream src(src_str.substr(4)); + std::stringstream src(src_str_tmp.substr(4)); int script = 0, output = 0; // TODO: check rename outputs to inputs??? src >> script; src.ignore(); src >> output; if (script < CPN_MAX_SCRIPTS && output < CPN_MAX_SCRIPT_INPUTS) - rhs = RawSource(SOURCE_TYPE_LUA_OUTPUT, script * 16 + output); + rhs = RawSource(SOURCE_TYPE_LUA_OUTPUT, script * 16 + output + 1); } else if (val_len > 3 && val[0] == 'l' && val[1] == 's' && val[2] == '(') { - std::stringstream src(src_str.substr(3)); + std::stringstream src(src_str_tmp.substr(3)); int ls = 0; src >> ls; if (ls > 0 && ls <= CPN_MAX_LOGICAL_SWITCHES) - rhs = RawSource(SOURCE_TYPE_CUSTOM_SWITCH, ls - 1); + rhs = RawSource(SOURCE_TYPE_CUSTOM_SWITCH, ls); // appears depreciated - maybe early support for T20 as SWn the current std and no match in encode } else if (val_len > 3 && @@ -177,13 +200,13 @@ RawSource YamlRawSourceDecode(const std::string& src_str) val[1] == 's' && val[2] == '(') { - std::stringstream src(src_str.substr(3)); + std::stringstream src(src_str_tmp.substr(3)); int fs = 0; src >> fs; if (fs > 0) { int fsidx = Boards::getSwitchYamlIndex(QString("SW%1").arg(fs), BoardJson::YLT_REF); if (fsidx >= 0) - rhs = RawSource(SOURCE_TYPE_SWITCH, fsidx); + rhs = RawSource(SOURCE_TYPE_SWITCH, fsidx + 1); } } else if (val_len > 3 && @@ -191,33 +214,33 @@ RawSource YamlRawSourceDecode(const std::string& src_str) val[1] == 'r' && val[2] == '(') { - std::stringstream src(src_str.substr(3)); + std::stringstream src(src_str_tmp.substr(3)); int tr = 0; src >> tr; if (tr < getCurrentFirmware()->getCapability(TrainerInputs)) - rhs = RawSource(SOURCE_TYPE_PPM, tr); + rhs = RawSource(SOURCE_TYPE_PPM, tr + 1); } else if (val_len > 3 && val[0] == 'c' && val[1] == 'h' && val[2] == '(') { - std::stringstream src(src_str.substr(3)); + std::stringstream src(src_str_tmp.substr(3)); int ch = 0; src >> ch; if (ch < CPN_MAX_CHNOUT) - rhs = RawSource(SOURCE_TYPE_CH, ch); + rhs = RawSource(SOURCE_TYPE_CH, ch + 1); } else if (val_len > 3 && val[0] == 'g' && val[1] == 'v' && val[2] == '(') { - std::stringstream src(src_str.substr(3)); + std::stringstream src(src_str_tmp.substr(3)); int gv = 0; src >> gv; if (gv < CPN_MAX_GVARS) - rhs = RawSource(SOURCE_TYPE_GVAR, gv); + rhs = RawSource(SOURCE_TYPE_GVAR, gv + 1); } else if (val_len > 5 && val[0] == 't' && @@ -226,7 +249,7 @@ RawSource YamlRawSourceDecode(const std::string& src_str) val[3] == 'e' && val[4] == '(') { - std::stringstream src(src_str.substr(5)); + std::stringstream src(src_str_tmp.substr(5)); // parse sign uint8_t sign = 0; @@ -242,22 +265,32 @@ RawSource YamlRawSourceDecode(const std::string& src_str) int sensor = 0; src >> sensor; if (sensor < CPN_MAX_SENSORS) - rhs = RawSource(SOURCE_TYPE_TELEMETRY, sensor * 3 + sign); + rhs = RawSource(SOURCE_TYPE_TELEMETRY, sensor * 3 + sign + 1); + + } else if (val_len > 3 && + val[0] == 'C' && + val[1] == 'Y' && + val[2] == 'C' && + val[3] >= '1' && val[3] <= '3') { + + std::stringstream src(src_str_tmp.substr(3)); + int cyc = 0; + src >> cyc; + if (cyc <= CPN_MAX_CYC) + rhs = RawSource(SOURCE_TYPE_CYC, cyc); } else { - YAML::Node node(src_str); + YAML::Node node(src_str_tmp); if (node.IsScalar() && node.as() == "MAX") { rhs.type = SOURCE_TYPE_MAX; - rhs.index = 0; - return rhs; + rhs.index = 1; } if (node.IsScalar() && node.as() == "MIN") { rhs.type = SOURCE_TYPE_MIN; - rhs.index = 0; - return rhs; + rhs.index = 1; } std::string ana_str; @@ -272,16 +305,15 @@ RawSource YamlRawSourceDecode(const std::string& src_str) int ana_idx = Boards::getInputYamlIndex(ana_str.c_str(), BoardJson::YLT_REF); if (ana_idx >= 0) { - rhs.type = SOURCE_TYPE_STICK; - rhs.index = ana_idx; - return rhs; + rhs.type = SOURCE_TYPE_INPUT; + rhs.index = ana_idx + 1; } std::string trim_str; node >> trim_str; if (modelSettingsVersion < SemanticVersion(QString(CPN_ADC_REFACTOR_VERSION))) { - int idx = b.getLegacyTrimSourceIndex(src_str.c_str()); + int idx = b.getLegacyTrimSourceIndex(src_str_tmp.c_str()); if (idx >= 0) trim_str = Boards::getTrimYamlName(idx, BoardJson::YLT_REF).toStdString(); } @@ -289,31 +321,32 @@ RawSource YamlRawSourceDecode(const std::string& src_str) int trm_idx = Boards::getTrimYamlIndex(trim_str.c_str(), BoardJson::YLT_REF); if (trm_idx >= 0) { rhs.type = SOURCE_TYPE_TRIM; - rhs.index = trm_idx; - return rhs; + rhs.index = trm_idx + 1; + } + + std::string timer_str; + node >> timer_str; + + if (modelSettingsVersion < SemanticVersion(QString(CPN_ADC_REFACTOR_VERSION))) { + if (timer_str.size() == 6 && timer_str.substr(0, 5) == "TIMER") { + timer_str = "Tmr" + timer_str.substr(5, 1); + } + } + + if (timer_str.substr(0, 3) == "Tmr" && timer_str.substr(3, 1) >= "1" && timer_str.substr(3, 1) <= "9") { + if (std::stoi(timer_str.substr(3, 1)) <= CPN_MAX_TIMERS) { + rhs.type = SOURCE_TYPE_TIMER; + rhs.index = std::stoi(timer_str.substr(3, 1)); + } } std::string special_str; node >> special_str; - if (modelSettingsVersion < SemanticVersion(QString(CPN_ADC_REFACTOR_VERSION))) { - if (special_str.size() == 6 && special_str.substr(0, 5) == "TIMER") { - special_str = "Tmr" + special_str.substr(5, 1); - } - } - int sp_idx = b.getRawSourceSpecialTypeIndex(special_str.c_str()); - if (sp_idx >= 0) { + if (sp_idx > 0) { rhs.type = SOURCE_TYPE_SPECIAL; rhs.index = sp_idx; - return rhs; - } - - int cyc_idx = b.getRawSourceCyclicIndex(src_str.c_str()); - if (cyc_idx >= 0) { - rhs.type = SOURCE_TYPE_CYC; - rhs.index = cyc_idx; - return rhs; } if (node.IsScalar() && node.as().size() == 12 && node.as().substr(0, 11) == "SPACEMOUSE_") { @@ -321,12 +354,14 @@ RawSource YamlRawSourceDecode(const std::string& src_str) node >> spacemouseLut >> sm_idx; if (sm_idx >= 0) { rhs.type = SOURCE_TYPE_SPACEMOUSE; - rhs.index = sm_idx; - return rhs; + rhs.index = sm_idx + 1; } } } + if (neg) + rhs.index = -rhs.index; + return rhs; } diff --git a/companion/src/firmwares/edgetx/yaml_rawswitch.cpp b/companion/src/firmwares/edgetx/yaml_rawswitch.cpp index ec4cade4c..0897fe545 100644 --- a/companion/src/firmwares/edgetx/yaml_rawswitch.cpp +++ b/companion/src/firmwares/edgetx/yaml_rawswitch.cpp @@ -98,7 +98,8 @@ RawSwitch YamlRawSwitchDecode(const std::string& sw_str) // yaml-cpp does not escape this if (val_len > 0 && val[0] == '\\') { - val++; val_len--; + val++; + val_len--; sw_str_tmp = sw_str_tmp.substr(1); } diff --git a/companion/src/firmwares/er9x/er9xeeprom.cpp b/companion/src/firmwares/er9x/er9xeeprom.cpp index 82655d1d3..d25857d4a 100644 --- a/companion/src/firmwares/er9x/er9xeeprom.cpp +++ b/companion/src/firmwares/er9x/er9xeeprom.cpp @@ -187,14 +187,14 @@ t_Er9xMixData::operator MixData () c9x.sOffset=gvar; } else { c9x.sOffset=sOffset; - } + } c9x.swtch = er9xToSwitch(swtch); if (srcRaw == 0) { c9x.srcRaw = RawSource(SOURCE_TYPE_NONE); } else if (srcRaw <= 7) { - c9x.srcRaw = RawSource(SOURCE_TYPE_STICK, srcRaw-1); + c9x.srcRaw = RawSource(SOURCE_TYPE_INPUT, srcRaw-1); } else if (srcRaw == 8) { c9x.srcRaw = RawSource(SOURCE_TYPE_MAX); @@ -221,9 +221,9 @@ t_Er9xMixData::operator MixData () } else if (srcRaw <=37) { c9x.srcRaw = RawSource(SOURCE_TYPE_CH, srcRaw-21); - } + } else { - c9x.srcRaw = RawSource(SOURCE_TYPE_GVAR, srcRaw-38); + c9x.srcRaw = RawSource(SOURCE_TYPE_GVAR, srcRaw-38); } if (differential==1) { @@ -257,7 +257,7 @@ RawSource er9xToSource(int8_t value) return RawSource(SOURCE_TYPE_NONE); } else if (value <= 7) { - return RawSource(SOURCE_TYPE_STICK, value - 1); + return RawSource(SOURCE_TYPE_INPUT, value - 1); } else if (value == 8) { return RawSource(SOURCE_TYPE_MAX); @@ -285,7 +285,7 @@ Er9xLogicalSwitchData::operator LogicalSwitchData () c9x.func = func; c9x.val1 = v1; c9x.val2 = v2; - + if ((c9x.func >= LS_FN_VPOS && c9x.func <= LS_FN_ANEG) || c9x.func >= LS_FN_EQUAL) { c9x.val1 = er9xToSource(v1).toValue(); } diff --git a/companion/src/firmwares/ersky9x/ersky9xeeprom.cpp b/companion/src/firmwares/ersky9x/ersky9xeeprom.cpp index d390d96fc..4cd255029 100644 --- a/companion/src/firmwares/ersky9x/ersky9xeeprom.cpp +++ b/companion/src/firmwares/ersky9x/ersky9xeeprom.cpp @@ -186,7 +186,7 @@ t_Ersky9xMixData_v10::operator MixData () c9x.srcRaw = RawSource(SOURCE_TYPE_NONE); } else if (srcRaw <= 7) { - c9x.srcRaw = RawSource(SOURCE_TYPE_STICK, srcRaw-1); + c9x.srcRaw = RawSource(SOURCE_TYPE_INPUT, srcRaw-1); } else if (srcRaw == 8) { c9x.srcRaw = RawSource(SOURCE_TYPE_MAX); @@ -256,7 +256,7 @@ t_Ersky9xMixData_v11::operator MixData () c9x.srcRaw = RawSource(SOURCE_TYPE_NONE); } else if (srcRaw <= 7) { - c9x.srcRaw = RawSource(SOURCE_TYPE_STICK, srcRaw-1); + c9x.srcRaw = RawSource(SOURCE_TYPE_INPUT, srcRaw-1); } else if (srcRaw == 8) { c9x.srcRaw = RawSource(SOURCE_TYPE_MAX); @@ -318,7 +318,7 @@ RawSource ersky9xToSource_v10(int8_t value) return RawSource(SOURCE_TYPE_NONE); } else if (value <= 7) { - return RawSource(SOURCE_TYPE_STICK, value - 1); + return RawSource(SOURCE_TYPE_INPUT, value - 1); } else if (value == 8) { return RawSource(SOURCE_TYPE_MAX); @@ -346,7 +346,7 @@ RawSource ersky9xToSource_v11(int8_t value) return RawSource(SOURCE_TYPE_NONE); } else if (value <= 7) { - return RawSource(SOURCE_TYPE_STICK, value - 1); + return RawSource(SOURCE_TYPE_INPUT, value - 1); } else if (value == 8) { return RawSource(SOURCE_TYPE_MAX); diff --git a/companion/src/firmwares/generalsettings.cpp b/companion/src/firmwares/generalsettings.cpp index 173b72ef0..c81a97618 100644 --- a/companion/src/firmwares/generalsettings.cpp +++ b/companion/src/firmwares/generalsettings.cpp @@ -382,7 +382,7 @@ RawSource GeneralSettings::getDefaultSource(unsigned int channel) const { int stick = getDefaultStick(channel); if (stick >= 0) - return RawSource(SOURCE_TYPE_STICK, stick); + return RawSource(SOURCE_TYPE_INPUT, stick + 1); else return RawSource(SOURCE_TYPE_NONE); } diff --git a/companion/src/firmwares/input_data.cpp b/companion/src/firmwares/input_data.cpp index 28d290416..1605f64f2 100644 --- a/companion/src/firmwares/input_data.cpp +++ b/companion/src/firmwares/input_data.cpp @@ -59,7 +59,7 @@ AbstractStaticItemModel * ExpoData::carryTrimItemModel() mdl->setName(AIM_EXPO_CARRYTRIM); ExpoData tmp = ExpoData(); - tmp.srcRaw = RawSource(SOURCE_TYPE_STICK, 0); + tmp.srcRaw = RawSource(SOURCE_TYPE_INPUT, 0); for (int i = -CARRYTRIM_STICK_OFF; i <= Boards::getBoardCapability(getCurrentBoard(), Board::NumTrims); i++) { tmp.carryTrim = -i; diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index e5cdcdb73..3800a988c 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -210,7 +210,7 @@ void ModelData::setDefaultMixes(const GeneralSettings & settings) MixData * mix = &mixData[i]; mix->destCh = i + 1; mix->weight = 100; - mix->srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i); + mix->srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i + 1); } } @@ -446,7 +446,7 @@ void ModelData::convert(RadioDataConversionState & cstate) cstate.setComponent("Settings", 0); if (thrTraceSrc && (int)thrTraceSrc < cstate.fromBoard.getCapability(Board::Pots) + cstate.fromBoard.getCapability(Board::Sliders)) { cstate.setSubComp(tr("Throttle Source")); - thrTraceSrc = RawSource(SOURCE_TYPE_STICK, (int)thrTraceSrc + 3).convert(cstate).index - 3; + thrTraceSrc = RawSource(SOURCE_TYPE_INPUT, (int)thrTraceSrc + 3).convert(cstate).index - 3; } Firmware *fw = getCurrentFirmware(); @@ -603,12 +603,8 @@ int ModelData::updateReference() updRefInfo.occurences = 3; break; case REF_UPD_TYPE_TIMER: - updRefInfo.srcType = SOURCE_TYPE_SPECIAL; + updRefInfo.srcType = SOURCE_TYPE_TIMER; updRefInfo.maxindex = fw->getCapability(Timers); - // rawsource index offset TODO refactor timers so be own category - updRefInfo.index1 += 2; - updRefInfo.index2 += 2; - updRefInfo.maxindex += 2; break; default: qDebug() << "Error - unhandled reference type:" << updRefInfo.type; @@ -1030,7 +1026,7 @@ void ModelData::updateAssignFunc(CustomFunctionData * cfd) switch (updRefInfo.type) { case REF_UPD_TYPE_CHANNEL: - if(cfd->func < FuncOverrideCH1 || cfd->func > FuncOverrideCH32) // TODO refactor to FuncOverrideCHLast + if(cfd->func < FuncOverrideCH1 || cfd->func > FuncOverrideCHLast) return; idxAdj = FuncOverrideCH1; break; @@ -1040,9 +1036,9 @@ void ModelData::updateAssignFunc(CustomFunctionData * cfd) idxAdj = FuncAdjustGV1; break; case REF_UPD_TYPE_TIMER: - if (cfd->func < FuncSetTimer1 || cfd->func > FuncSetTimer3) // TODO refactor to FuncSetTimerLast + if (cfd->func < FuncSetTimer1 || cfd->func > FuncSetTimerLast) return; - idxAdj = FuncSetTimer1 - 2; // reverse earlier offset required for rawsource + idxAdj = FuncSetTimer1; break; default: return; @@ -1526,7 +1522,7 @@ bool ModelData::isThrTraceSrcAvailable(const GeneralSettings * generalSettings, const Board::Type board = getCurrentBoard(); if (index > 0 && index <= Boards::getCapability(board, Board::Pots) + Boards::getCapability(board, Board::Sliders)) - return RawSource(SOURCE_TYPE_STICK, index + Boards::getCapability(board, Board::Sticks) - 1).isAvailable(this, generalSettings, board); + return RawSource(SOURCE_TYPE_INPUT, index + Boards::getCapability(board, Board::Sticks) - 1).isAvailable(this, generalSettings, board); else return true; } diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index b6b4c6ebc..9288606f9 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -381,13 +381,13 @@ class ModelData { void updateTelemetryRef(int & idx); void updateTelemetryRef(unsigned int & idx); void updateModuleFailsafes(ModuleData * md); - inline void updateSourceRef(RawSource & src) { updateTypeIndexRef(src, updRefInfo.srcType); } + inline void updateSourceRef(RawSource & src) { updateTypeIndexRef(src, updRefInfo.srcType, 1); } inline void updateSwitchRef(RawSwitch & swtch) { updateTypeIndexRef(swtch, updRefInfo.swtchType, 1); } inline void updateTimerMode(RawSwitch & swtch) { updateTypeIndexRef(swtch, updRefInfo.swtchType, 1, false, (int)SWITCH_TYPE_TIMER_MODE, 0); } inline void updateSourceIntRef(int & value) { RawSource src = RawSource(value); - updateTypeIndexRef(src, updRefInfo.srcType); + updateTypeIndexRef(src, updRefInfo.srcType, 1); if (value != src.toValue()) value = src.toValue(); } diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index b4d1320af..a1061c02c 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -307,6 +307,7 @@ inline int MAX_TRIMS(Board::Type board) #define ROTENC_COUNT(board, version) ((IS_STM32(board) && version >= 218) ? 0 : 1) #define MAX_AUX_TRIMS(board) ((IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board)) ? 2 : 0) #define MAX_SOURCE_TYPE_SPECIAL(board, version) SOURCE_TYPE_SPECIAL_COUNT +#define MAX_TIMERS(board, version) 3 inline int switchIndex(int i, Board::Type board, unsigned int version) { @@ -457,7 +458,7 @@ class SourcesConversionTable: public ConversionTable { } if (version >= 218 || IS_STM32(board)) { - for (int i=0; i<32; i++) { + for (int i=1; i<=32; i++) { addConversion(RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i), val++); } } @@ -465,7 +466,7 @@ class SourcesConversionTable: public ConversionTable { if (IS_STM32(board)) { for (int i = 0; i < MAX_SCRIPTS(board); i++) { for (int j = 0; j < 6; j++) { - addConversion(RawSource(SOURCE_TYPE_LUA_OUTPUT, i * 16 + j), val++); + addConversion(RawSource(SOURCE_TYPE_LUA_OUTPUT, i * 16 + j + 1), val++); } } } @@ -484,10 +485,12 @@ class SourcesConversionTable: public ConversionTable { int offset = 0; if (version <= 218 && IS_HORUS_X10(board) && i >= CPN_MAX_STICKS + MAX_POTS_STORAGE(board, version)) offset += 2; + + // ADC refactor shuffles + //if (version <= 220 && (IS_HORUS_X10(board) || IS_FAMILY_T16(board)) && i >= CPN_MAX_STICKS + MAX_POTS_STORAGE(board, version)) // offset += 2; - // ADC refactor shuffles if (IS_FAMILY_HORUS_OR_T16(board)) { if (i >= 7 && i <= 8) offset += 2; @@ -502,47 +505,50 @@ class SourcesConversionTable: public ConversionTable { } // end ADC refactor shuffles - addConversion(RawSource(SOURCE_TYPE_STICK, i + offset), val++); - //qDebug() << "i:" << i << "offset:" << offset << "index:" << i + offset << "desc:" << RawSource(SOURCE_TYPE_STICK, i + offset).toString() << "val:" << val; + addConversion(RawSource(SOURCE_TYPE_INPUT, i + offset + 1), val++); + // qDebug() << "i:" << i << "offset:" << offset << "index:" << i + offset + 1 << "desc:" << RawSource(SOURCE_TYPE_STICK, i + offset).toString() << "val:" << val; } - for (int i=0; iinputConfig[index].name).trimmed(); + case SOURCE_TYPE_INPUT: + dfltName = Boards::getInputName(index - 1, board); + if (generalSettings && index <= CPN_MAX_INPUTS) + custName = QString(generalSettings->inputConfig[index - 1].name).trimmed(); return DataHelpers::getCompositeName(dfltName, custName, prefixCustomName); case SOURCE_TYPE_TRIM: @@ -188,53 +190,53 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con return tr("MAX"); case SOURCE_TYPE_SWITCH: - dfltName = Boards::getSwitchInfo(index, board).name.c_str(); - if (Boards::isSwitchFunc(index, board)) { - if (model) { - int fsindex = Boards::getSwitchTagNum(index, board) - 1; + dfltName = Boards::getSwitchInfo(index - 1, board).name.c_str(); + if (Boards::isSwitchFunc(index - 1, board)) { + if (model && index <= CPN_MAX_SWITCHES_FUNCTION) { + int fsindex = Boards::getSwitchTagNum(index - 1, board) - 1; custName = QString(model->functionSwitchNames[fsindex]).trimmed(); } } else { - if (generalSettings) { - custName = QString(generalSettings->switchConfig[index].name).trimmed(); + if (generalSettings && index <= CPN_MAX_SWITCHES) { + custName = QString(generalSettings->switchConfig[index - 1].name).trimmed(); } } return DataHelpers::getCompositeName(dfltName, custName, prefixCustomName); case SOURCE_TYPE_CUSTOM_SWITCH: - return RawSwitch(SWITCH_TYPE_VIRTUAL, index + 1).toString(); + return RawSwitch(SWITCH_TYPE_VIRTUAL, index).toString(); // RawSwitch uses 1 based index case SOURCE_TYPE_CYC: - return tr("CYC%1").arg(index + 1); + return tr("CYC%1").arg(index); case SOURCE_TYPE_PPM: - return RadioData::getElementName(tr("TR", "as in Trainer"), index + 1); + return RadioData::getElementName(tr("TR", "as in Trainer"), index); case SOURCE_TYPE_CH: - if (model) - result = QString(model->limitData[index].nameToString(index)).trimmed(); + if (model && index <= CPN_MAX_CHNOUT) + result = QString(model->limitData[index - 1].nameToString(index - 1)).trimmed(); if (result.isEmpty()) - return LimitData().nameToString(index); + return LimitData().nameToString(index - 1); + return result; case SOURCE_TYPE_SPECIAL: - if (index >= SOURCE_TYPE_SPECIAL_FIRST_TIMER && index <= SOURCE_TYPE_SPECIAL_LAST_TIMER) { - if (model) - result = QString(model->timers[index - SOURCE_TYPE_SPECIAL_FIRST_TIMER].nameToString(index - SOURCE_TYPE_SPECIAL_FIRST_TIMER)).trimmed(); - if (result.isEmpty()) - result = TimerData().nameToString(index - SOURCE_TYPE_SPECIAL_FIRST_TIMER); - } - else - result = CHECK_IN_ARRAY(special, index); + return CHECK_IN_ARRAY(special, index); + + case SOURCE_TYPE_TIMER: + if (model && index <= CPN_MAX_TIMERS) + result = QString(model->timers[index - 1].nameToString(index - 1)).trimmed(); + if (result.isEmpty()) + result = TimerData().nameToString(index - 1); return result; case SOURCE_TYPE_TELEMETRY: { - div_t qr = div(index, 3); - if (model) + div_t qr = div(index - 1, 3); + if (model && qr.quot < CPN_MAX_SENSORS) result = QString(model->sensorData[qr.quot].nameToString(qr.quot)).trimmed(); if (result.isEmpty()) result = SensorData().nameToString(qr.quot); @@ -244,14 +246,14 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con } case SOURCE_TYPE_GVAR: - if (model) - result = QString(model->gvarData[index].nameToString(index)).trimmed(); + if (model && index <= CPN_MAX_GVARS) + result = QString(model->gvarData[index - 1].nameToString(index - 1)).trimmed(); if (result.isEmpty()) - result = GVarData().nameToString(index); + result = GVarData().nameToString(index - 1); return result; case SOURCE_TYPE_SPACEMOUSE: - return tr("sm%1").arg(QChar('A' + index)); + return tr("sm%1").arg(QChar('A' + (index - 1))); default: return QString(CPN_STR_UNKNOWN_ITEM); @@ -263,87 +265,100 @@ bool RawSource::isStick(Board::Type board) const if (board == Board::BOARD_UNKNOWN) board = getCurrentBoard(); - if (type == SOURCE_TYPE_STICK && index < Boards::getCapability(board, Board::Sticks)) { + if (type == SOURCE_TYPE_INPUT && index - 1 < Boards::getCapability(board, Board::Sticks)) { return true; } return false; } -bool RawSource::isTimeBased(Board::Type board) const -{ - return (type == SOURCE_TYPE_SPECIAL && index >= SOURCE_TYPE_SPECIAL_FIRST_TIMER && index <= SOURCE_TYPE_SPECIAL_LAST_TIMER); -} - bool RawSource::isAvailable(const ModelData * const model, const GeneralSettings * const gs, Board::Type board) const { + if (type == SOURCE_TYPE_NONE && index == 0) + return true; + if (board == Board::BOARD_UNKNOWN) board = getCurrentBoard(); Boards b(board); - if (type == SOURCE_TYPE_STICK && index >= b.getCapability(Board::Inputs)) + if (type == SOURCE_TYPE_CH && abs(index) > CPN_MAX_CHNOUT) return false; - if (type == SOURCE_TYPE_SWITCH && index >= b.getCapability(Board::Switches)) + if (type == SOURCE_TYPE_CUSTOM_SWITCH && abs(index) > CPN_MAX_LOGICAL_SWITCHES) return false; - if (type == SOURCE_TYPE_SPECIAL && index >= SOURCE_TYPE_SPECIAL_FIRST_RESERVED && index <= SOURCE_TYPE_SPECIAL_LAST_RESERVED) - return false; + + if (type == SOURCE_TYPE_LUA_OUTPUT && div(abs(index - 1), 16).quot >= CPN_MAX_SCRIPTS) + return false; + + if (type == SOURCE_TYPE_INPUT && abs(index) > b.getCapability(Board::Inputs)) + return false; + + if (type == SOURCE_TYPE_SWITCH && abs(index) > b.getCapability(Board::Switches)) + return false; + + if (type == SOURCE_TYPE_SPECIAL && abs(index) >= SOURCE_TYPE_SPECIAL_FIRST_RESERVED) + return false; + + if (type == SOURCE_TYPE_TIMER && abs(index) > CPN_MAX_TIMERS) + return false; + + if (type == SOURCE_TYPE_TELEMETRY && div(abs(index), 3).quot > CPN_MAX_SENSORS) + return false; if (model) { - if (type == SOURCE_TYPE_SPECIAL && index >= SOURCE_TYPE_SPECIAL_FIRST_TIMER && index <= SOURCE_TYPE_SPECIAL_LAST_TIMER && - model->timers[index - SOURCE_TYPE_SPECIAL_FIRST_TIMER].isModeOff()) + if (type == SOURCE_TYPE_TIMER && model->timers[abs(index) - 1].isModeOff()) return false; - if (type == SOURCE_TYPE_SWITCH && b.isSwitchFunc(index, board) && - !model->isFunctionSwitchSourceAllowed(b.getSwitchTagNum(index, board) - 1)) + if (type == SOURCE_TYPE_SWITCH && b.isSwitchFunc(abs(index) - 1, board) && + !model->isFunctionSwitchSourceAllowed(b.getSwitchTagNum(abs(index) - 1, board) - 1)) return false; - if (type == SOURCE_TYPE_VIRTUAL_INPUT && !model->isInputValid(index)) + if (type == SOURCE_TYPE_VIRTUAL_INPUT && !model->isInputValid(abs(index) - 1)) return false; if (type == SOURCE_TYPE_PPM && model->trainerMode == TRAINER_MODE_OFF) return false; - if (type == SOURCE_TYPE_CUSTOM_SWITCH && model->logicalSw[index].isEmpty()) + if (type == SOURCE_TYPE_CUSTOM_SWITCH && model->logicalSw[abs(index) - 1].isEmpty()) return false; if (type == SOURCE_TYPE_TELEMETRY) { - if (!model->sensorData[div(index, 3).quot].isAvailable()) { + if (!model->sensorData[div(abs(index) - 1, 3).quot].isAvailable()) { return false; } } - if (type == SOURCE_TYPE_CH && !model->hasMixes(index)) + if (type == SOURCE_TYPE_CH && !model->hasMixes(abs(index) - 1)) return false; } if (gs) { - if (type == SOURCE_TYPE_STICK) { - if (!gs->isInputAvailable(index)) + if (type == SOURCE_TYPE_INPUT) { + if (!gs->isInputAvailable(abs(index) - 1)) return false; - if (gs->inputConfig[index].flexType == Board::FLEX_SWITCH) + if (gs->inputConfig[abs(index) - 1].flexType == Board::FLEX_SWITCH) return false; } - if (type == SOURCE_TYPE_SWITCH && !b.isSwitchFunc(index, board) && IS_HORUS_OR_TARANIS(board) && - !gs->switchSourceAllowed(index)) + if (type == SOURCE_TYPE_SWITCH && !b.isSwitchFunc(abs(index) - 1, board) && IS_HORUS_OR_TARANIS(board) && + !gs->switchSourceAllowed(abs(index) - 1)) return false; } else { - if (type == SOURCE_TYPE_STICK) { - if (!Boards::isInputAvailable(index, board)) + if (type == SOURCE_TYPE_INPUT) { + if (!Boards::isInputAvailable(abs(index) - 1, board)) return false; - if (Boards::getInputInfo(index, board).flexType == Board::FLEX_SWITCH) + if (Boards::getInputInfo(abs(index) - 1, board).flexType == Board::FLEX_SWITCH) return false; } } - if (type == SOURCE_TYPE_TRIM && index >= b.getCapability(Board::NumTrims)) + if (type == SOURCE_TYPE_TRIM && abs(index) > b.getCapability(Board::NumTrims)) return false; if (type == SOURCE_TYPE_SPACEMOUSE && - (index >= CPN_MAX_SPACEMOUSE || + (abs(index) > CPN_MAX_SPACEMOUSE || (!(gs->serialPort[GeneralSettings::SP_AUX1] == GeneralSettings::AUX_SERIAL_SPACEMOUSE || gs->serialPort[GeneralSettings::SP_AUX2] == GeneralSettings::AUX_SERIAL_SPACEMOUSE)))) return false; @@ -356,7 +371,7 @@ RawSource RawSource::convert(RadioDataConversionState & cstate) cstate.setItemType(tr("SRC"), 1); RadioDataConversionState::LogField oldData(index, toString(cstate.fromModel(), cstate.fromGS(), cstate.fromType)); - if (type == SOURCE_TYPE_STICK) + if (type == SOURCE_TYPE_INPUT) index = Boards::getInputIndex(Boards::getInputTag(oldData.id, cstate.fromType), Board::LVT_TAG, cstate.toType); else if (type == SOURCE_TYPE_SWITCH) index = Boards::getSwitchIndex(Boards::getSwitchTag(oldData.id, cstate.fromType), Board::LVT_TAG, cstate.toType); @@ -376,6 +391,7 @@ StringTagMappingTable RawSource::getSpecialTypesLookupTable() StringTagMappingTable tbl; tbl.insert(tbl.end(), { + {std::to_string(SOURCE_TYPE_SPECIAL_NONE), "NONE"}, {std::to_string(SOURCE_TYPE_SPECIAL_TX_BATT), "TX_VOLTAGE"}, {std::to_string(SOURCE_TYPE_SPECIAL_TX_TIME), "TX_TIME"}, {std::to_string(SOURCE_TYPE_SPECIAL_TX_GPS), "TX_GPS"}, @@ -383,23 +399,6 @@ tbl.insert(tbl.end(), { {std::to_string(SOURCE_TYPE_SPECIAL_RESERVED2), "RESERVED2"}, {std::to_string(SOURCE_TYPE_SPECIAL_RESERVED3), "RESERVED3"}, {std::to_string(SOURCE_TYPE_SPECIAL_RESERVED4), "RESERVED4"}, - {std::to_string(SOURCE_TYPE_SPECIAL_TIMER1), "Tmr1"}, - {std::to_string(SOURCE_TYPE_SPECIAL_TIMER2), "Tmr2"}, - {std::to_string(SOURCE_TYPE_SPECIAL_TIMER3), "Tmr3"}, - }); - - return tbl; -} - -// static -StringTagMappingTable RawSource::getCyclicLookupTable() -{ - StringTagMappingTable tbl; - -tbl.insert(tbl.end(), { - {"0", "CYC1"}, - {"1", "CYC2"}, - {"2", "CYC3"}, }); return tbl; diff --git a/companion/src/firmwares/rawsource.h b/companion/src/firmwares/rawsource.h index a931c0c3c..4d654958a 100644 --- a/companion/src/firmwares/rawsource.h +++ b/companion/src/firmwares/rawsource.h @@ -31,6 +31,7 @@ class ModelData; class GeneralSettings; class RadioDataConversionState; +// TODO remove and refactor to use dynamic board switches enum Switches { SWITCH_NONE, @@ -101,6 +102,7 @@ enum HeliSwashTypes { }; enum TelemetrySource { + TELEMETRY_SOURCE_NONE, TELEMETRY_SOURCE_TX_BATT, TELEMETRY_SOURCE_TX_TIME, TELEMETRY_SOURCE_TIMER1, @@ -163,7 +165,7 @@ enum RawSourceType { SOURCE_TYPE_NONE, SOURCE_TYPE_VIRTUAL_INPUT, SOURCE_TYPE_LUA_OUTPUT, - SOURCE_TYPE_STICK, // and POTS and Flex pots TODO rename to more appropriate + SOURCE_TYPE_INPUT, SOURCE_TYPE_ROTARY_ENCODER, SOURCE_TYPE_TRIM, SOURCE_TYPE_MIN, @@ -178,10 +180,12 @@ enum RawSourceType { SOURCE_TYPE_SPECIAL, SOURCE_TYPE_TELEMETRY, SOURCE_TYPE_SPACEMOUSE, + SOURCE_TYPE_TIMER, MAX_SOURCE_TYPE }; enum RawSourceTypeSpecial { + SOURCE_TYPE_SPECIAL_NONE, SOURCE_TYPE_SPECIAL_TX_BATT, SOURCE_TYPE_SPECIAL_TX_TIME, SOURCE_TYPE_SPECIAL_TX_GPS, @@ -191,15 +195,10 @@ enum RawSourceTypeSpecial { SOURCE_TYPE_SPECIAL_RESERVED3, SOURCE_TYPE_SPECIAL_RESERVED4, SOURCE_TYPE_SPECIAL_LAST_RESERVED = SOURCE_TYPE_SPECIAL_RESERVED4, - SOURCE_TYPE_SPECIAL_FIRST_TIMER, - SOURCE_TYPE_SPECIAL_TIMER1 = SOURCE_TYPE_SPECIAL_FIRST_TIMER, - SOURCE_TYPE_SPECIAL_TIMER2, - SOURCE_TYPE_SPECIAL_TIMER3, - SOURCE_TYPE_SPECIAL_LAST_TIMER = SOURCE_TYPE_SPECIAL_TIMER3, SOURCE_TYPE_SPECIAL_COUNT }; -constexpr int SOURCE_TYPE_STICK_THR_IDX { 3 }; // TODO is there a function to determine index? +constexpr int SOURCE_TYPE_INPUT_THR_IDX { 3 }; // TODO is there a function to determine index? class RawSourceRange { @@ -241,6 +240,8 @@ class RawSource { TelemGroup = 0x020, InputsGroup = 0x040, ScriptsGroup = 0x080, + NegativeGroup = 0x100, + PositiveGroup = 0x200, InputSourceGroups = NoneGroup | SourcesGroup | TrimsGroup | SwitchesGroup | InputsGroup, AllSourceGroups = InputSourceGroups | GVarsGroup | TelemGroup | ScriptsGroup @@ -249,14 +250,14 @@ class RawSource { RawSource() { clear(); } explicit RawSource(int value): - type(RawSourceType(abs(value)/65536)), - index(value >= 0 ? abs(value)%65536 : -(abs(value)%65536)) + type(RawSourceType(abs(value) / 65536)), + index(value >= 0 ? abs(value) % 65536 : -(abs(value) % 65536)) { } - RawSource(RawSourceType type, int index=0): + RawSource(RawSourceType type, int index = 0): type(type), - index(index) + index(type != SOURCE_TYPE_NONE && index == 0 ? 1 : index) { } diff --git a/companion/src/modeledit/customfunctions.cpp b/companion/src/modeledit/customfunctions.cpp index c6477c82a..fee36f12f 100644 --- a/companion/src/modeledit/customfunctions.cpp +++ b/companion/src/modeledit/customfunctions.cpp @@ -383,7 +383,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) if (!cfn.isEmpty()) { widgetsMask |= CUSTOM_FUNCTION_SHOW_FUNC | CUSTOM_FUNCTION_ENABLE; - if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32) { + if (func >= FuncOverrideCH1 && func <= FuncOverrideCHLast) { if (model) { int channelsMax = model->getChannelsMax(true); fswtchParam[i]->setDecimals(0); @@ -445,10 +445,10 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) populateFuncParamCB(fswtchParamT[i], func, cfn.param); widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM; } - else if (func >= FuncSetTimer1 && func <= FuncSetTimer3) { + else if (func >= FuncSetTimer1 && func <= FuncSetTimerLast) { if (modified) cfn.param = fswtchParamTime[i]->timeInSeconds(); - RawSourceRange range = RawSource(SOURCE_TYPE_SPECIAL, func - FuncSetTimer1 + 2).getRange(model, generalSettings); + RawSourceRange range = RawSource(SOURCE_TYPE_TIMER, func - FuncSetTimer1 + 1).getRange(model, generalSettings); fswtchParamTime[i]->setTimeRange((int)range.min, (int)range.max); fswtchParamTime[i]->setTime(cfn.param); widgetsMask |= CUSTOM_FUNCTION_TIME_PARAM; @@ -663,39 +663,50 @@ void CustomFunctionsPanel::populateFuncParamCB(QComboBox *b, uint function, unsi { QStringList qs; b->setModel(new QStandardItemModel(b)); // clear combo box but not any shared item model + if (function == FuncPlaySound) { b->setModel(tabModelFactory->getItemModel(playSoundId)); b->setCurrentIndex(b->findData(value)); + if (b->currentIndex() < 0) + b->setCurrentIndex(0); } else if (function == FuncPlayHaptic) { b->setModel(tabModelFactory->getItemModel(harpicId)); b->setCurrentIndex(b->findData(value)); + if (b->currentIndex() < 0) + b->setCurrentIndex(0); } else if (function == FuncReset) { b->setModel(tabFilterFactory->getItemModel(funcResetParamId)); b->setCurrentIndex(b->findData(value)); + if (b->currentIndex() < 0) + b->setCurrentIndex(0); } else if (function == FuncVolume || function == FuncBacklight) { b->setModel(tabFilterFactory->getItemModel(rawSourceInputsId)); b->setCurrentIndex(b->findData(value)); + if (b->currentIndex() < 0 && value == 0) + b->setCurrentIndex(b->count() / 2); // '----' not in list so set to first positive value } else if (function == FuncPlayValue) { b->setModel(tabFilterFactory->getItemModel(rawSourceAllId)); b->setCurrentIndex(b->findData(value)); + if (b->currentIndex() < 0 && value == 0) + b->setCurrentIndex(b->count() / 2); // '----' not in list so set to first positive value } else if (function >= FuncAdjustGV1 && function <= FuncAdjustGVLast) { switch (adjustmode) { case 1: b->setModel(tabFilterFactory->getItemModel(rawSourceInputsId)); b->setCurrentIndex(b->findData(value)); - if (b->currentIndex() < 0) - b->setCurrentIndex(0); + if (b->currentIndex() < 0 && value == 0) + b->setCurrentIndex(b->count() / 2); // '----' not in list so set to first positive value break; case 2: b->setModel(tabFilterFactory->getItemModel(rawSourceGVarsId)); b->setCurrentIndex(b->findData(value)); - if (b->currentIndex() < 0) - b->setCurrentIndex(0); + if (b->currentIndex() < 0 && value == 0) + b->setCurrentIndex(b->count() / 2); // '----' not in list so set to first positive value break; } } diff --git a/companion/src/modeledit/expodialog.cpp b/companion/src/modeledit/expodialog.cpp index 14a08d1df..eeef6866a 100644 --- a/companion/src/modeledit/expodialog.cpp +++ b/companion/src/modeledit/expodialog.cpp @@ -48,7 +48,7 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G cb_fp[i] = tmp[i]; } - RawSourceType srcType = (firmware->getCapability(VirtualInputs) ? SOURCE_TYPE_VIRTUAL_INPUT : SOURCE_TYPE_STICK); + RawSourceType srcType = (firmware->getCapability(VirtualInputs) ? SOURCE_TYPE_VIRTUAL_INPUT : SOURCE_TYPE_INPUT); setWindowTitle(tr("Edit %1").arg(RawSource(srcType, ed->chn).toString(&model, &generalSettings))); id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef)), "GVarRef"); @@ -109,6 +109,8 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G flags), "RawSource"); ui->sourceCB->setModel(dialogFilteredItemModels->getItemModel(id)); ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(ed->srcRaw.toValue())); + if (ui->sourceCB->currentIndex() < 0 && ed->srcRaw.toValue() == 0) + ui->sourceCB->setCurrentIndex(ui->sourceCB->count() / 2); // '----' not in list so set to first positive entry ui->inputName->setValidator(new NameValidator(board, this)); ui->inputName->setText(inputName); } diff --git a/companion/src/modeledit/logicalswitches.cpp b/companion/src/modeledit/logicalswitches.cpp index c512153e1..6db5ecef7 100644 --- a/companion/src/modeledit/logicalswitches.cpp +++ b/companion/src/modeledit/logicalswitches.cpp @@ -277,7 +277,7 @@ bool LogicalSwitchesPanel::offsetChangedAt(int index) { RawSource source = RawSource(model->logicalSw[index].val1); RawSourceRange range = source.getRange(model, generalSettings, model->logicalSw[index].getRangeFlags()); - double currVal = source.isTimeBased() ? teOffset[index]->timeInSeconds() : dsbOffset[index]->value(); + double currVal = source.type == SOURCE_TYPE_TIMER ? teOffset[index]->timeInSeconds() : dsbOffset[index]->value(); value = round((currVal - range.offset) / range.step); mod = (mod || value != model->logicalSw[index].val2); model->logicalSw[index].val2 = value; @@ -366,7 +366,7 @@ void LogicalSwitchesPanel::updateLine(int i) double value = range.step * model->logicalSw[i].val2 + range.offset; /* TODO+source.getRawOffset(model)*/ cbSource1[i]->setModel(rawSourceFilteredModel); cbSource1[i]->setCurrentIndex(cbSource1[i]->findData(source.toValue())); - if (source.isTimeBased()) { + if (source.type == SOURCE_TYPE_TIMER) { mask |= VALUE_TO_VISIBLE; teOffset[i]->setTimeRange(range.min, range.max); teOffset[i]->setSingleStep(range.step); diff --git a/companion/src/modeledit/mixerdialog.cpp b/companion/src/modeledit/mixerdialog.cpp index e9125b454..f7d4f4520 100644 --- a/companion/src/modeledit/mixerdialog.cpp +++ b/companion/src/modeledit/mixerdialog.cpp @@ -55,6 +55,8 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, "RawSource"); ui->sourceCB->setModel(dialogFilteredItemModels->getItemModel(id)); ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(md->srcRaw.toValue())); + if (ui->sourceCB->currentIndex() < 0 && md->srcRaw.toValue() == 0) + ui->sourceCB->setCurrentIndex(ui->sourceCB->count() / 2); // '----' not in list so set to first positive entry int limit = firmware->getCapability(OffsetWeight); @@ -206,7 +208,7 @@ void MixerDialog::valuesChanged() lock = true; md->srcRaw = RawSource(ui->sourceCB->itemData(ui->sourceCB->currentIndex()).toInt()); if (firmware->getCapability(HasNoExpo)) { - bool drVisible = (md->srcRaw.type == SOURCE_TYPE_STICK && md->srcRaw.index < CPN_MAX_STICKS); + bool drVisible = (md->srcRaw.type == SOURCE_TYPE_INPUT && md->srcRaw.index < CPN_MAX_STICKS); ui->MixDR_CB->setEnabled(drVisible); ui->label_MixDR->setEnabled(drVisible); } diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index 6059f2c67..9de213ce6 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -1610,7 +1610,7 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge const int ttlInputs = ttlSticks + ttlFlexInputs; for (int i = 0; i < ttlInputs + firmware->getCapability(RotaryEncoders); i++) { - RawSource src((i < ttlInputs) ? SOURCE_TYPE_STICK : SOURCE_TYPE_ROTARY_ENCODER, (i < ttlInputs) ? i : ttlInputs - i); + RawSource src((i < ttlInputs) ? SOURCE_TYPE_INPUT : SOURCE_TYPE_ROTARY_ENCODER, (i < ttlInputs) ? i : ttlInputs - i); QCheckBox * checkbox = new QCheckBox(this); checkbox->setProperty("index", i); checkbox->setText(src.toString(&model, &generalSettings)); @@ -1674,7 +1674,7 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge if (IS_HORUS_OR_TARANIS(board) && ttlInputs > 0) { for (int i = ttlSticks; i < ttlInputs; i++) { - RawSource src(SOURCE_TYPE_STICK, i); + RawSource src(SOURCE_TYPE_INPUT, i); QCheckBox * cb = new QCheckBox(this); cb->setProperty("index", i - ttlSticks); cb->setText(src.toString(&model, &generalSettings)); diff --git a/companion/src/modeledit/telemetry_customscreens.cpp b/companion/src/modeledit/telemetry_customscreens.cpp index e9cb7c3f9..099aa9902 100644 --- a/companion/src/modeledit/telemetry_customscreens.cpp +++ b/companion/src/modeledit/telemetry_customscreens.cpp @@ -158,7 +158,7 @@ void CustomScreen::updateBar(int line) float maxVal = screen.body.bars[line].barMax; maxVal = range.getValue(maxVal); - if (source.isTimeBased()) { + if (source.type == SOURCE_TYPE_TIMER) { minTime[line]->setVisible(true); minTime[line]->setTimeRange(range.min, range.max); minTime[line]->setSingleStep(range.step); diff --git a/companion/src/modelprinter.cpp b/companion/src/modelprinter.cpp index 6b62d4c3d..c1a28cb61 100644 --- a/companion/src/modelprinter.cpp +++ b/companion/src/modelprinter.cpp @@ -159,7 +159,7 @@ QString ModelPrinter::printEEpromSize() QString ModelPrinter::printChannelName(int idx) { - QString str = RawSource(SOURCE_TYPE_CH, idx).toString(&model, &generalSettings); + QString str = RawSource(SOURCE_TYPE_CH, idx + 1).toString(&model, &generalSettings); if (firmware->getCapability(ChannelsName)) { str = str.leftJustified(firmware->getCapability(ChannelsName) + 5, ' ', false); } @@ -273,7 +273,7 @@ QString ModelPrinter::printCenterBeep() for (int i = 0; i < inputs + firmware->getCapability(RotaryEncoders); i++) { if (model.beepANACenter & (0x01 << i)) { - RawSource src((i < inputs) ? SOURCE_TYPE_STICK : SOURCE_TYPE_ROTARY_ENCODER, (i < inputs) ? i : inputs - i); + RawSource src((i < inputs) ? SOURCE_TYPE_INPUT : SOURCE_TYPE_ROTARY_ENCODER, (i < inputs) ? i : inputs - i); strl << src.toString(&model, &generalSettings); } } @@ -338,8 +338,8 @@ QString ModelPrinter::printRotaryEncoder(int flightModeIndex, int reIndex) QString ModelPrinter::printInputName(int idx) { - RawSourceType srcType = (firmware->getCapability(VirtualInputs) ? SOURCE_TYPE_VIRTUAL_INPUT : SOURCE_TYPE_STICK); - return RawSource(srcType, idx).toString(&model, &generalSettings).toHtmlEscaped(); + RawSourceType srcType = (firmware->getCapability(VirtualInputs) ? SOURCE_TYPE_VIRTUAL_INPUT : SOURCE_TYPE_INPUT); + return RawSource(srcType, idx + 1).toString(&model, &generalSettings).toHtmlEscaped(); } QString ModelPrinter::printInputLine(int idx) @@ -785,7 +785,7 @@ QString ModelPrinter::printPotWarnings() for (int i = Boards::getCapability(board, Board::Sticks); i < Boards::getCapability(board, Board::Inputs); i++) { if (generalSettings.isInputAvailable(i) && (generalSettings.isInputPot(i) || generalSettings.isInputSlider(i))) { if (model.potsWarnEnabled[i]) { - RawSource src(SOURCE_TYPE_STICK, i); + RawSource src(SOURCE_TYPE_INPUT, i); str += src.toString(&model, &generalSettings); } } @@ -1075,7 +1075,7 @@ QString ModelPrinter::printTelemetryScreen(unsigned int idx, unsigned int line, QString unit; QString minstr; QString maxstr; - if (source.isTimeBased()){ + if (source.type == SOURCE_TYPE_TIMER) { minstr = printTimeValue((float)screen.body.bars[line].barMin, MASK_TIMEVALUE_HRSMINS); maxstr = printTimeValue((float)screen.body.bars[line].barMax, MASK_TIMEVALUE_HRSMINS); } diff --git a/companion/src/simulation/joystickdialog.cpp b/companion/src/simulation/joystickdialog.cpp index c408baa34..710583a07 100644 --- a/companion/src/simulation/joystickdialog.cpp +++ b/companion/src/simulation/joystickdialog.cpp @@ -162,7 +162,7 @@ void joystickDialog::populateSourceCombo(QComboBox * cb) if (radioSettings.isInputStick(i)) wname = Boards::getAxisName(i); else - wname = RawSource(RawSourceType::SOURCE_TYPE_STICK, i).toString(nullptr, &radioSettings); + wname = RawSource(RawSourceType::SOURCE_TYPE_INPUT, i).toString(nullptr, &radioSettings); cb->addItem(wname, i); } } diff --git a/companion/src/simulation/simulatorwidget.cpp b/companion/src/simulation/simulatorwidget.cpp index 8e95be3e4..0c241a052 100644 --- a/companion/src/simulation/simulatorwidget.cpp +++ b/companion/src/simulation/simulatorwidget.cpp @@ -632,7 +632,7 @@ void SimulatorWidget::setupRadioWidgets() if (!(radioSettings.isInputAvailable(i) && radioSettings.isInputPot(i))) continue; - wname = RawSource(RawSourceType::SOURCE_TYPE_STICK, i).toString(nullptr, &radioSettings, Board::BOARD_UNKNOWN, false); + wname = RawSource(RawSourceType::SOURCE_TYPE_INPUT, i).toString(nullptr, &radioSettings, Board::BOARD_UNKNOWN, false); RadioKnobWidget * pot = new RadioKnobWidget(radioSettings.inputConfig[i].flexType, wname, 0, ui->radioWidgetsHT); pot->setIndex(i); ui->radioWidgetsHTLayout->insertWidget(midpos++, pot); @@ -646,7 +646,7 @@ void SimulatorWidget::setupRadioWidgets() if (!(radioSettings.isInputAvailable(i) && radioSettings.isInputSlider(i))) continue; - wname = RawSource(RawSourceType::SOURCE_TYPE_STICK, i).toString(nullptr, &radioSettings, Board::BOARD_UNKNOWN, false); + wname = RawSource(RawSourceType::SOURCE_TYPE_INPUT, i).toString(nullptr, &radioSettings, Board::BOARD_UNKNOWN, false); RadioFaderWidget * sl = new RadioFaderWidget(wname, 0, ui->radioWidgetsVC); sl->setIndex(i); ui->VCGridLayout->addWidget(sl, 0, fc++, 1, 1); diff --git a/companion/src/tests/conversions.cpp b/companion/src/tests/conversions.cpp index a4c3ac2e8..6ccf13ee4 100644 --- a/companion/src/tests/conversions.cpp +++ b/companion/src/tests/conversions.cpp @@ -245,7 +245,7 @@ TEST(Conversions, ConversionX10From22) EXPECT_EQ(RawSwitch(SWITCH_TYPE_ON), settings.customFn[1].swtch); EXPECT_EQ(FuncVolume, settings.customFn[1].func); - EXPECT_EQ(RawSource(SOURCE_TYPE_STICK, 4+5+1).toValue(), settings.customFn[1].param); // RS + EXPECT_EQ(RawSource(SOURCE_TYPE_INPUT, 4+5+1).toValue(), settings.customFn[1].param); // RS EXPECT_STREQ("Tes", settings.switchName[0]); EXPECT_EQ(Board::SWITCH_3POS, settings.switchConfig[0]); @@ -265,7 +265,7 @@ TEST(Conversions, ConversionX10From22) EXPECT_EQ(0, model.beepANACenter); EXPECT_EQ(80, model.mixData[0].weight); EXPECT_EQ(RawSource(SOURCE_TYPE_MAX), model.mixData[2].srcRaw); // MAX - EXPECT_EQ(RawSource(SOURCE_TYPE_STICK, 4+5), model.mixData[3].srcRaw); // LS + EXPECT_EQ(RawSource(SOURCE_TYPE_INPUT, 4+5), model.mixData[3].srcRaw); // LS EXPECT_EQ(RawSource(SOURCE_TYPE_PPM, 0), model.mixData[5].srcRaw); EXPECT_EQ(RawSwitch(SWITCH_TYPE_TELEMETRY, 1), model.mixData[5].swtch); EXPECT_EQ(900, model.limitData[0].max); // -100 @@ -321,7 +321,7 @@ TEST(Conversions, ConversionX12SFrom22) EXPECT_EQ(RawSwitch(SWITCH_TYPE_ON), settings.customFn[1].swtch); EXPECT_EQ(FuncVolume, settings.customFn[1].func); - EXPECT_EQ(RawSource(SOURCE_TYPE_STICK, 4+5+1).toValue(), settings.customFn[1].param); // RS + EXPECT_EQ(RawSource(SOURCE_TYPE_INPUT, 4+5+1).toValue(), settings.customFn[1].param); // RS EXPECT_STREQ("Tes", settings.switchName[0]); EXPECT_EQ(Board::SWITCH_3POS, settings.switchConfig[0]); @@ -341,7 +341,7 @@ TEST(Conversions, ConversionX12SFrom22) EXPECT_EQ(0, model.beepANACenter); EXPECT_EQ(80, model.mixData[0].weight); EXPECT_EQ(RawSource(SOURCE_TYPE_MAX), model.mixData[2].srcRaw); // MAX - EXPECT_EQ(RawSource(SOURCE_TYPE_STICK, 4+5), model.mixData[3].srcRaw); // LS + EXPECT_EQ(RawSource(SOURCE_TYPE_INPUT, 4+5), model.mixData[3].srcRaw); // LS EXPECT_EQ(RawSource(SOURCE_TYPE_PPM, 0), model.mixData[5].srcRaw); EXPECT_EQ(RawSwitch(SWITCH_TYPE_TELEMETRY, 1), model.mixData[5].swtch); EXPECT_EQ(900, model.limitData[0].max); // -100 diff --git a/companion/src/wizarddata.cpp b/companion/src/wizarddata.cpp index 81d2ef302..873944577 100644 --- a/companion/src/wizarddata.cpp +++ b/companion/src/wizarddata.cpp @@ -54,7 +54,7 @@ void WizMix::maxMixSwitch(char *name, MixData &mix, int channel, int sw, int wei strncpy(mix.name, name, sizeof(mix.name)-1); mix.destCh = channel; mix.srcRaw = RawSource(SOURCE_TYPE_MAX); - mix.swtch = RawSwitch(SWITCH_TYPE_SWITCH, sw); + mix.swtch = RawSwitch(SWITCH_TYPE_SWITCH, sw + 1); mix.weight = weight; } @@ -63,13 +63,13 @@ void WizMix::addMix(ModelData &model, Input input, int weight, int channel, int if (input != NO_INPUT) { if (input >= RUDDER_INPUT && input <= AILERONS_INPUT) { MixData & mix = model.mixData[mixIndex++]; - mix.destCh = channel+1; + mix.destCh = channel + 1; if (IS_SKY9X(getCurrentBoard())) { - mix.srcRaw = RawSource(SOURCE_TYPE_STICK, input-1); + mix.srcRaw = RawSource(SOURCE_TYPE_INPUT, input + 1); } else { - int channel = settings.getDefaultChannel(input-1); - mix.srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, channel); + int channel = settings.getDefaultChannel(input - 1); + mix.srcRaw = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, channel + 1); } mix.weight = weight; @@ -118,7 +118,7 @@ WizMix::operator ModelData() // Add the Throttle Cut option MixData & mix = model.mixData[mixIndex++]; mix.destCh = i+1; - mix.srcRaw = SOURCE_TYPE_MAX; + mix.srcRaw = RawSource(SOURCE_TYPE_MAX); mix.weight = -100; mix.swtch.type = SWITCH_TYPE_SWITCH; mix.swtch.index = IS_SKY9X(getCurrentBoard()) ? SWITCH_THR : SWITCH_SF0; diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index acf1b0807..70f59a76f 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -535,6 +535,8 @@ enum MixSources { MIXSRC_FIRST_TELEM SKIP, MIXSRC_LAST_TELEM SKIP = MIXSRC_FIRST_TELEM + 3 * MAX_TELEMETRY_SENSORS - 1, + + MIXSRC_INVERT SKIP, }; diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index 5fb2a88f3..ba05e2bac 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -74,7 +74,7 @@ PACK(struct CurveRef { PACK(struct MixData { int16_t weight:11 CUST(in_read_weight,in_write_weight); // GV1=-1024, -GV1=1023 uint16_t destCh:5; - uint16_t srcRaw:10 CUST(r_mixSrcRaw,w_mixSrcRaw); // srcRaw=0 means not used + int16_t srcRaw:10 CUST(r_mixSrcRawEx,w_mixSrcRawEx); // srcRaw=0 means not used uint16_t carryTrim:1; uint16_t mixWarn:2; // mixer warning uint16_t mltpx:2 ENUM(MixerMultiplex); @@ -99,7 +99,7 @@ PACK(struct ExpoData { uint16_t scale:14; CUST_ATTR(carryTrim, r_carryTrim, nullptr); //pre 2.9 int16_t trimSource:6; - uint16_t srcRaw:10 ENUM(MixSources) CUST(r_mixSrcRaw,w_mixSrcRaw); + int16_t srcRaw:10 ENUM(MixSources) CUST(r_mixSrcRawEx,w_mixSrcRawEx); uint32_t chn:5; int32_t swtch:10 CUST(r_swtchSrc,w_swtchSrc); uint32_t flightModes:9 CUST(r_flightModes, w_flightModes); diff --git a/radio/src/gui/128x64/gui.h b/radio/src/gui/128x64/gui.h index 8666ddc23..60677f6a9 100644 --- a/radio/src/gui/128x64/gui.h +++ b/radio/src/gui/128x64/gui.h @@ -125,7 +125,7 @@ extern int8_t s_copySrcRow; extern int8_t s_copyTgtOfs; extern uint8_t s_currIdx; extern uint8_t s_currIdxSubMenu; -extern uint16_t s_currSrcRaw; +extern mixsrc_t s_currSrcRaw; extern uint16_t s_currScale; extern uint8_t s_copySrcIdx; extern uint8_t s_copySrcCh; diff --git a/radio/src/gui/128x64/lcd.cpp b/radio/src/gui/128x64/lcd.cpp index bcc4b4457..058ba9145 100644 --- a/radio/src/gui/128x64/lcd.cpp +++ b/radio/src/gui/128x64/lcd.cpp @@ -657,23 +657,34 @@ void putsVBat(coord_t x, coord_t y, LcdFlags att) putsVolts(x, y, g_vbat100mV, att); } -void drawSource(coord_t x, coord_t y, uint32_t idx, LcdFlags att) +void drawSource(coord_t x, coord_t y, mixsrc_t idx, LcdFlags att) { - if (idx == MIXSRC_NONE) { + uint16_t aidx = abs(idx); + bool inverted = idx < 0; + + if (aidx == MIXSRC_NONE) { lcdDrawText(x, y, STR_EMPTY, att); } - else if (idx <= MIXSRC_LAST_INPUT) { + else if (aidx <= MIXSRC_LAST_INPUT) { + if (inverted) { + lcdDrawChar(x, y, '!'); + x += 2; + } lcdDrawChar(x+2, y+1, CHR_INPUT, TINSIZE); lcdDrawSolidFilledRect(x, y, 7, 7); - if (g_model.inputNames[idx-MIXSRC_FIRST_INPUT][0]) - lcdDrawSizedText(x+8, y, g_model.inputNames[idx-MIXSRC_FIRST_INPUT], LEN_INPUT_NAME, att); + if (g_model.inputNames[aidx-MIXSRC_FIRST_INPUT][0]) + lcdDrawSizedText(x+8, y, g_model.inputNames[aidx-MIXSRC_FIRST_INPUT], LEN_INPUT_NAME, att); else - lcdDrawNumber(x+8, y, idx, att|LEADING0|LEFT, 2); + lcdDrawNumber(x+8, y, aidx, att|LEADING0|LEFT, 2); } #if defined(LUA_INPUTS) - else if (idx <= MIXSRC_LAST_LUA) { - div_t qr = div(idx-MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS); + else if (aidx <= MIXSRC_LAST_LUA) { + div_t qr = div((uint16_t)(aidx-MIXSRC_FIRST_LUA), MAX_SCRIPT_OUTPUTS); #if defined(LUA_MODEL_SCRIPTS) + if (inverted) { + lcdDrawChar(x, y, '!'); + x += 2; + } if (qr.quot < MAX_SCRIPTS && qr.rem < scriptInputsOutputs[qr.quot].outputsCount) { lcdDrawChar(x+2, y+1, '1'+qr.quot, TINSIZE); lcdDrawFilledRect(x, y, 7, 7, 0); diff --git a/radio/src/gui/128x64/menu_model.cpp b/radio/src/gui/128x64/menu_model.cpp index 7dd3fadfd..e7c4ccf8d 100644 --- a/radio/src/gui/128x64/menu_model.cpp +++ b/radio/src/gui/128x64/menu_model.cpp @@ -70,5 +70,5 @@ void editSingleName(coord_t x, coord_t y, const char* label, char* name, uint8_t s_currIdx; uint8_t s_currIdxSubMenu; -uint16_t s_currSrcRaw; +mixsrc_t s_currSrcRaw; uint16_t s_currScale; diff --git a/radio/src/gui/128x64/model_input_edit.cpp b/radio/src/gui/128x64/model_input_edit.cpp index eda89de1d..5cac0c572 100644 --- a/radio/src/gui/128x64/model_input_edit.cpp +++ b/radio/src/gui/128x64/model_input_edit.cpp @@ -79,7 +79,7 @@ void menuModelExpoOne(event_t event) uint8_t old_editMode = s_editMode; SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, - {0, 0, 0, ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)0 : (uint8_t)HIDDEN_ROW, 0, 0, LABEL(Curve), 1, + {0, 0, 0, abs(ed->srcRaw) >= MIXSRC_FIRST_TELEM ? (uint8_t)0 : (uint8_t)HIDDEN_ROW, 0, 0, LABEL(Curve), 1, CASE_FLIGHT_MODES(FM_ROW(LABEL(Flight Mode))) CASE_FLIGHT_MODES(FM_ROW((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE)) 0 /*, ...*/}); int8_t sub = menuVerticalPosition; @@ -112,14 +112,14 @@ void menuModelExpoOne(event_t event) lcdDrawTextAlignedLeft(y, STR_SOURCE); drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, RIGHT|STREXPANDED|attr); if (attr) - ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailableInInputs); + ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|INCDEC_SOURCE_INVERT|NO_INCDEC_MARKS, isSourceAvailableInInputs); break; case EXPO_FIELD_SCALE: lcdDrawTextAlignedLeft(y, STR_SCALE); - drawSensorCustomValue(EXPO_ONE_2ND_COLUMN, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), RIGHT | attr); + drawSensorCustomValue(EXPO_ONE_2ND_COLUMN, y, (abs(ed->srcRaw) - MIXSRC_FIRST_TELEM)/3, convertTelemValue(abs(ed->srcRaw) - MIXSRC_FIRST_TELEM + 1, ed->scale), RIGHT | attr); if (attr) - ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL); + ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(abs(ed->srcRaw) - MIXSRC_FIRST_TELEM + 1), EE_MODEL); break; case EXPO_FIELD_WEIGHT: @@ -161,13 +161,13 @@ void menuModelExpoOne(event_t event) case EXPO_FIELD_TRIM: lcdDrawTextAlignedLeft(y, STR_TRIM); { - const char* trim_str = getTrimSourceLabel(ed->srcRaw, ed->trimSource); + const char* trim_str = getTrimSourceLabel(abs(ed->srcRaw), ed->trimSource); LcdFlags flags = RIGHT | (menuHorizontalPosition==0 ? attr : 0); lcdDrawText(EXPO_ONE_2ND_COLUMN, y, trim_str, flags); if (attr) { int8_t min = TRIM_ON; - if (ed->srcRaw >= MIXSRC_FIRST_STICK && ed->srcRaw <= MIXSRC_LAST_STICK) { + if (abs(ed->srcRaw) >= MIXSRC_FIRST_STICK && abs(ed->srcRaw) <= MIXSRC_LAST_STICK) { min = -TRIM_OFF; } ed->trimSource = -checkIncDecModel(event, -ed->trimSource, min, keysGetMaxTrims()); diff --git a/radio/src/gui/128x64/model_logical_switches.cpp b/radio/src/gui/128x64/model_logical_switches.cpp index 73b335b24..f314f81db 100644 --- a/radio/src/gui/128x64/model_logical_switches.cpp +++ b/radio/src/gui/128x64/model_logical_switches.cpp @@ -116,7 +116,7 @@ void menuModelLogicalSwitchOne(event_t event) else { v1_val = cs->v1; drawSource(CSWONE_2ND_COLUMN, y, v1_val, attr); - INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE); + INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE | INCDEC_SOURCE_INVERT); INCDEC_ENABLE_CHECK(isSourceAvailable); } if (attr) { @@ -152,7 +152,7 @@ void menuModelLogicalSwitchOne(event_t event) } else if (cstate == LS_FAMILY_COMP) { drawSource(CSWONE_2ND_COLUMN, y, cs->v2, attr); - INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE); + INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE | INCDEC_SOURCE_INVERT); INCDEC_ENABLE_CHECK(isSourceAvailable); } else { @@ -175,7 +175,7 @@ void menuModelLogicalSwitchOne(event_t event) 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; - drawSourceCustomValue(CSWONE_2ND_COLUMN, y, v1_val, (v1_val <= MIXSRC_LAST_CH ? calc100toRESX(cs->v2) : cs->v2), lf); + drawSourceCustomValue(CSWONE_2ND_COLUMN, y, v1_val, (abs(v1_val) <= MIXSRC_LAST_CH ? calc100toRESX(cs->v2) : cs->v2), lf); } } @@ -313,7 +313,7 @@ void menuModelLogicalSwitches(event_t event) lcdDrawNumber(CSW_3RD_COLUMN, y, lswTimerValue(cs->v2), LEFT|PREC1); } else { - source_t v1 = cs->v1; + mixsrc_t v1 = cs->v1; drawSource(CSW_2ND_COLUMN, y, v1, 0); if (v1 >= MIXSRC_FIRST_TELEM) { drawSourceCustomValue(CSW_3RD_COLUMN, y, v1, convertLswTelemValue(cs), LEFT); diff --git a/radio/src/gui/128x64/model_mix_edit.cpp b/radio/src/gui/128x64/model_mix_edit.cpp index ea6ddc5a2..eff9027f7 100644 --- a/radio/src/gui/128x64/model_mix_edit.cpp +++ b/radio/src/gui/128x64/model_mix_edit.cpp @@ -138,7 +138,8 @@ void menuModelMixOne(event_t event) case MIX_FIELD_SOURCE: lcdDrawTextAlignedLeft(y, STR_SOURCE); drawSource(MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr); - if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST); + if (attr) + md2->srcRaw = checkIncDec(event, md2->srcRaw, 1, MIXSRC_LAST, EE_MODEL|INCDEC_SOURCE|INCDEC_SOURCE_INVERT|NO_INCDEC_MARKS, isSourceAvailable); break; case MIX_FIELD_WEIGHT: diff --git a/radio/src/gui/128x64/model_special_functions.cpp b/radio/src/gui/128x64/model_special_functions.cpp index dfc97ec26..84789b081 100644 --- a/radio/src/gui/128x64/model_special_functions.cpp +++ b/radio/src/gui/128x64/model_special_functions.cpp @@ -351,7 +351,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF val_max = MIXSRC_LAST_TELEM; drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN - (val_displayed == 0 ? 0 : 2 * FW), y, val_displayed, attr); if (active) { - INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE); + INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE | INCDEC_SOURCE_INVERT); INCDEC_ENABLE_CHECK(functionsContext == &globalFunctionsContext ? isSourceAvailableInGlobalFunctions : isSourceAvailable); } } @@ -360,7 +360,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF val_max = MIXSRC_LAST_CH; drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr); if (active) { - INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE); + INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE | INCDEC_SOURCE_INVERT); INCDEC_ENABLE_CHECK(isSourceAvailable); } } @@ -368,7 +368,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF val_max = MIXSRC_LAST_CH; drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr); if (active) { - INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE); + INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE | INCDEC_SOURCE_INVERT); INCDEC_ENABLE_CHECK(isSourceAvailable); } } @@ -397,7 +397,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF val_max = MIXSRC_LAST_CH; drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr); if (active) { - INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE); + INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE | INCDEC_SOURCE_INVERT); INCDEC_ENABLE_CHECK(isSourceAvailable); } break; diff --git a/radio/src/gui/128x64/popups.h b/radio/src/gui/128x64/popups.h index 6f8a31ab4..1c3329575 100644 --- a/radio/src/gui/128x64/popups.h +++ b/radio/src/gui/128x64/popups.h @@ -36,7 +36,7 @@ #define WARNING_LINE_X 12 #define WARNING_LINE_Y MESSAGEBOX_Y + 2 -#define POPUP_MENU_MAX_LINES 12 +#define POPUP_MENU_MAX_LINES 13 #define MENU_MAX_DISPLAY_LINES 6 #define MENU_LINE_LENGTH (LEN_MODEL_NAME+12) diff --git a/radio/src/gui/212x64/gui.h b/radio/src/gui/212x64/gui.h index 0bdfba10c..0bc2fc393 100644 --- a/radio/src/gui/212x64/gui.h +++ b/radio/src/gui/212x64/gui.h @@ -146,7 +146,7 @@ extern int8_t s_copySrcRow; extern int8_t s_copyTgtOfs; extern uint8_t s_currIdx; extern uint8_t s_currIdxSubMenu; -extern uint16_t s_currSrcRaw; +extern mixsrc_t s_currSrcRaw; extern uint16_t s_currScale; extern uint8_t s_copySrcIdx; extern uint8_t s_copySrcCh; diff --git a/radio/src/gui/212x64/lcd.cpp b/radio/src/gui/212x64/lcd.cpp index c44960afd..7a76042d5 100644 --- a/radio/src/gui/212x64/lcd.cpp +++ b/radio/src/gui/212x64/lcd.cpp @@ -627,23 +627,34 @@ void drawMainControlLabel(coord_t x, coord_t y, uint8_t idx, LcdFlags att) lcdDrawSizedText(x, y, getMainControlLabel(idx), UINT8_MAX, att); } -void drawSource(coord_t x, coord_t y, uint32_t idx, LcdFlags att) +void drawSource(coord_t x, coord_t y, mixsrc_t idx, LcdFlags att) { - if (idx == MIXSRC_NONE) { + uint16_t aidx = abs(idx); + bool inverted = idx < 0; + + if (aidx == MIXSRC_NONE) { lcdDrawText(x, y, STR_EMPTY, att); } - else if (idx <= MIXSRC_LAST_INPUT) { + else if (aidx <= MIXSRC_LAST_INPUT) { + if (inverted) { + lcdDrawChar(x, y, '!'); + x += 2; + } lcdDrawChar(x+2, y+1, CHR_INPUT, TINSIZE); lcdDrawFilledRect(x, y, 7, 7); - if (ZEXIST(g_model.inputNames[idx-MIXSRC_FIRST_INPUT])) - lcdDrawSizedText(x+8, y, g_model.inputNames[idx-MIXSRC_FIRST_INPUT], LEN_INPUT_NAME, att); + if (ZEXIST(g_model.inputNames[aidx-MIXSRC_FIRST_INPUT])) + lcdDrawSizedText(x+8, y, g_model.inputNames[aidx-MIXSRC_FIRST_INPUT], LEN_INPUT_NAME, att); else - lcdDrawNumber(x+8, y, idx, att|LEADING0|LEFT, 2); + lcdDrawNumber(x+8, y, aidx, att|LEADING0|LEFT, 2); } - else if (idx <= MIXSRC_LAST_LUA) { - div_t qr = div(idx-MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS); + else if (aidx <= MIXSRC_LAST_LUA) { + div_t qr = div((uint16_t)(aidx-MIXSRC_FIRST_LUA), MAX_SCRIPT_OUTPUTS); #if defined(LUA_MODEL_SCRIPTS) + if (inverted) { + lcdDrawChar(x, y, '!'); + x += 2; + } if (qr.quot < MAX_SCRIPTS && qr.rem < scriptInputsOutputs[qr.quot].outputsCount) { lcdDrawChar(x+2, y+1, '1'+qr.quot, TINSIZE); lcdDrawFilledRect(x, y, 7, 7); diff --git a/radio/src/gui/212x64/lcd.h b/radio/src/gui/212x64/lcd.h index c7d6a3fa2..3b9b416c8 100644 --- a/radio/src/gui/212x64/lcd.h +++ b/radio/src/gui/212x64/lcd.h @@ -112,7 +112,7 @@ void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags mode=0); void drawModelName(coord_t x, coord_t y, char *name, uint8_t id, LcdFlags att); void drawSwitch(coord_t x, coord_t y, int32_t swtch, LcdFlags att=0, bool autoBold = true); void drawMainControlLabel(coord_t x, coord_t y, uint8_t idx, LcdFlags att=0); -void drawSource(coord_t x, coord_t y, uint32_t idx, LcdFlags att=0); +void drawSource(coord_t x, coord_t y, mixsrc_t idx, LcdFlags att=0); void drawCurveName(coord_t x, coord_t y, int8_t idx, LcdFlags att=0); void drawTimerMode(coord_t x, coord_t y, swsrc_t mode, LcdFlags att=0); diff --git a/radio/src/gui/212x64/menu_model.cpp b/radio/src/gui/212x64/menu_model.cpp index fd2d120f4..5e43745fc 100644 --- a/radio/src/gui/212x64/menu_model.cpp +++ b/radio/src/gui/212x64/menu_model.cpp @@ -74,5 +74,5 @@ void editSingleName(coord_t x, coord_t y, const char * label, char *name, uint8_ uint8_t s_currIdx; uint8_t s_currIdxSubMenu; -uint16_t s_currSrcRaw; +mixsrc_t s_currSrcRaw; uint16_t s_currScale; diff --git a/radio/src/gui/212x64/model_input_edit.cpp b/radio/src/gui/212x64/model_input_edit.cpp index fbaff3091..78705292d 100644 --- a/radio/src/gui/212x64/model_input_edit.cpp +++ b/radio/src/gui/212x64/model_input_edit.cpp @@ -103,10 +103,10 @@ void menuModelExpoOne(event_t event) lcdDrawTextAlignedLeft(y, STR_SOURCE); drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, STREXPANDED|attr); if (attr && menuHorizontalPosition==0) - ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailableInInputs); - if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { - drawSensorCustomValue(EXPO_ONE_2ND_COLUMN+30, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, getValue(ed->srcRaw), LEFT|(menuHorizontalPosition==1?attr:0)); - if (attr && menuHorizontalPosition == 1) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL); + ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|INCDEC_SOURCE_INVERT|NO_INCDEC_MARKS, isSourceAvailableInInputs); + if (abs(ed->srcRaw) >= MIXSRC_FIRST_TELEM) { + drawSensorCustomValue(EXPO_ONE_2ND_COLUMN+30, y, (abs(ed->srcRaw) - MIXSRC_FIRST_TELEM)/3, getValue(ed->srcRaw), LEFT|(menuHorizontalPosition==1?attr:0)); + if (attr && menuHorizontalPosition == 1) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(abs(ed->srcRaw) - MIXSRC_FIRST_TELEM + 1), EE_MODEL); } else if (attr) { menuHorizontalPosition = 0; @@ -115,8 +115,8 @@ void menuModelExpoOne(event_t event) case EXPO_FIELD_SCALE: lcdDrawTextAlignedLeft(y, STR_SCALE); - drawSensorCustomValue(EXPO_ONE_2ND_COLUMN, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|attr); - if (attr) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL); + drawSensorCustomValue(EXPO_ONE_2ND_COLUMN, y, (abs(ed->srcRaw) - MIXSRC_FIRST_TELEM)/3, convertTelemValue(abs(ed->srcRaw) - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|attr); + if (attr) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(abs(ed->srcRaw) - MIXSRC_FIRST_TELEM + 1), EE_MODEL); break; case EXPO_FIELD_WEIGHT: @@ -152,13 +152,13 @@ void menuModelExpoOne(event_t event) case EXPO_FIELD_TRIM: lcdDrawTextAlignedLeft(y, STR_TRIM); { - const char* trim_str = getTrimSourceLabel(ed->srcRaw, ed->trimSource); + const char* trim_str = getTrimSourceLabel(abs(ed->srcRaw), ed->trimSource); LcdFlags flags = RIGHT | (menuHorizontalPosition==0 ? attr : 0); lcdDrawText(EXPO_ONE_2ND_COLUMN, y, trim_str, flags); if (attr) { int8_t min = TRIM_ON; - if (ed->srcRaw >= MIXSRC_FIRST_STICK && ed->srcRaw <= MIXSRC_LAST_STICK) { + if (abs(ed->srcRaw) >= MIXSRC_FIRST_STICK && abs(ed->srcRaw) <= MIXSRC_LAST_STICK) { min = -TRIM_OFF; } ed->trimSource = -checkIncDecModel(event, -ed->trimSource, min, keysGetMaxTrims()); diff --git a/radio/src/gui/212x64/model_logical_switches.cpp b/radio/src/gui/212x64/model_logical_switches.cpp index 0c940d357..797858964 100644 --- a/radio/src/gui/212x64/model_logical_switches.cpp +++ b/radio/src/gui/212x64/model_logical_switches.cpp @@ -117,7 +117,7 @@ void menuModelLogicalSwitches(event_t event) // CSW params unsigned int cstate = lswFamily(cs->func); - int v1_val = cs->v1; + mixsrc_t v1_val = cs->v1; int16_t v1_min = 0, v1_max = MIXSRC_LAST_TELEM; int16_t v2_min = 0, v2_max = MIXSRC_LAST_TELEM; int16_t v3_min =-1, v3_max = 100; @@ -149,7 +149,7 @@ void menuModelLogicalSwitches(event_t event) v1_val = cs->v1; drawSource(CSW_2ND_COLUMN, y, v1_val, attr1); drawSource(CSW_3RD_COLUMN, y, cs->v2, attr2); - INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE); + INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE | INCDEC_SOURCE_INVERT); INCDEC_ENABLE_CHECK(isSourceAvailable); } else if (cstate == LS_FAMILY_TIMER) { @@ -164,7 +164,7 @@ void menuModelLogicalSwitches(event_t event) v1_val = cs->v1; drawSource(CSW_2ND_COLUMN, y, v1_val, attr1); if (horz == 1) { - INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE); + INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE | INCDEC_SOURCE_INVERT); INCDEC_ENABLE_CHECK(isSourceAvailableInCustomSwitches); } else { @@ -175,7 +175,7 @@ void menuModelLogicalSwitches(event_t event) 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; - drawSourceCustomValue(CSW_3RD_COLUMN, y, v1_val, (v1_val <= MIXSRC_LAST_CH ? calc100toRESX(cs->v2) : cs->v2), lf); + drawSourceCustomValue(CSW_3RD_COLUMN, y, v1_val, (abs(v1_val) <= MIXSRC_LAST_CH ? calc100toRESX(cs->v2) : cs->v2), lf); } // CSW AND switch @@ -228,14 +228,14 @@ void menuModelLogicalSwitches(event_t event) cs->v1 = CHECK_INCDEC_PARAM(event, v1_val, v1_min, v1_max); break; case LS_FIELD_V2: - if (v1_val >= MIXSRC_FIRST_TIMER) { + if (abs(v1_val) >= MIXSRC_FIRST_TIMER) { INCDEC_SET_FLAG(EE_MODEL | INCDEC_REP10 | NO_INCDEC_MARKS); } cs->v2 = CHECK_INCDEC_PARAM(event, cs->v2, v2_min, v2_max); if (cstate==LS_FAMILY_OFS && cs->v1!=0 && event==EVT_KEY_LONG(KEY_ENTER)) { killEvents(event); getvalue_t x = getValue(v1_val); - if (v1_val <= MIXSRC_LAST_CH) { + if (abs(v1_val) <= MIXSRC_LAST_CH) { cs->v2 = calcRESXto100(x); } storageDirty(EE_MODEL); diff --git a/radio/src/gui/212x64/model_mix_edit.cpp b/radio/src/gui/212x64/model_mix_edit.cpp index bbd2cd76a..90398472d 100644 --- a/radio/src/gui/212x64/model_mix_edit.cpp +++ b/radio/src/gui/212x64/model_mix_edit.cpp @@ -126,7 +126,8 @@ void menuModelMixOne(event_t event) case MIX_FIELD_SOURCE: lcdDrawTextAlignedLeft(y, STR_SOURCE); drawSource(MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr); - if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST); + if (attr) + md2->srcRaw = checkIncDec(event, md2->srcRaw, 1, MIXSRC_LAST, EE_MODEL|INCDEC_SOURCE|INCDEC_SOURCE_INVERT|NO_INCDEC_MARKS, isSourceAvailable); break; case MIX_FIELD_WEIGHT: diff --git a/radio/src/gui/212x64/model_special_functions.cpp b/radio/src/gui/212x64/model_special_functions.cpp index 229d995e0..4067b01ee 100644 --- a/radio/src/gui/212x64/model_special_functions.cpp +++ b/radio/src/gui/212x64/model_special_functions.cpp @@ -326,7 +326,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF val_max = MIXSRC_LAST_TELEM; drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr); if (active) { - INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE); + INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE | INCDEC_SOURCE_INVERT); INCDEC_ENABLE_CHECK(functionsContext == &globalFunctionsContext ? isSourceAvailableInGlobalFunctions : isSourceAvailable); } } @@ -335,7 +335,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF val_max = MIXSRC_LAST_CH; drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr); if (active) { - INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE); + INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE | INCDEC_SOURCE_INVERT); INCDEC_ENABLE_CHECK(isSourceAvailable); } } @@ -354,7 +354,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF val_max = MIXSRC_LAST_CH; drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr); if (active) { - INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE); + INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE | INCDEC_SOURCE_INVERT); INCDEC_ENABLE_CHECK(isSourceAvailable); } } @@ -372,7 +372,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF val_max = MIXSRC_LAST_CH; drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr); if (active) { - INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE); + INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE | INCDEC_SOURCE_INVERT); INCDEC_ENABLE_CHECK(isSourceAvailable); } break; diff --git a/radio/src/gui/212x64/popups.h b/radio/src/gui/212x64/popups.h index b8acecb5d..b70806058 100644 --- a/radio/src/gui/212x64/popups.h +++ b/radio/src/gui/212x64/popups.h @@ -34,7 +34,7 @@ #define WARNING_LINE_X 16 #define WARNING_LINE_Y MESSAGEBOX_Y + 2 -#define POPUP_MENU_MAX_LINES 12 +#define POPUP_MENU_MAX_LINES 13 #define MENU_MAX_DISPLAY_LINES 6 #define MENU_LINE_LENGTH (LEN_MODEL_NAME+12) diff --git a/radio/src/gui/colorlcd/curveedit.cpp b/radio/src/gui/colorlcd/curveedit.cpp index 62c83396b..939e957a0 100644 --- a/radio/src/gui/colorlcd/curveedit.cpp +++ b/radio/src/gui/colorlcd/curveedit.cpp @@ -193,7 +193,7 @@ void CurveDataEdit::update() } } -void CurveEdit::SetCurrentSource(uint32_t source) +void CurveEdit::SetCurrentSource(mixsrc_t source) { CurveEdit::currentSource = source; if (source) diff --git a/radio/src/gui/colorlcd/curveedit.h b/radio/src/gui/colorlcd/curveedit.h index 63158ef0c..c97f22ffd 100644 --- a/radio/src/gui/colorlcd/curveedit.h +++ b/radio/src/gui/colorlcd/curveedit.h @@ -31,7 +31,7 @@ class CurveEdit: public Window { public: CurveEdit(Window * parent, const rect_t & rect, uint8_t index); - static void SetCurrentSource(uint32_t source); + static void SetCurrentSource(mixsrc_t source); void deleteLater(bool detach = true, bool trash = true) override { diff --git a/radio/src/gui/colorlcd/input_source.cpp b/radio/src/gui/colorlcd/input_source.cpp index ceeffbb30..2eb58a67e 100644 --- a/radio/src/gui/colorlcd/input_source.cpp +++ b/radio/src/gui/colorlcd/input_source.cpp @@ -95,14 +95,14 @@ InputSource::InputSource(Window *parent, ExpoData *input) : lv_obj_set_flex_flow(lvobj, LV_FLEX_FLOW_COLUMN); lv_obj_set_size(lvobj, lv_pct(100), LV_SIZE_CONTENT); - new SourceChoice(this, rect_t{}, INPUTSRC_FIRST, INPUTSRC_LAST, - GET_DEFAULT(input->srcRaw), [=](int32_t newValue) { - input->srcRaw = newValue; - lv_event_send(lvobj, LV_EVENT_VALUE_CHANGED, nullptr); - SET_DIRTY(); - }); - lv_obj_add_event_cb(lvobj, InputSource::value_changed, LV_EVENT_VALUE_CHANGED, - nullptr); + new SourceChoice( + this, rect_t{}, INPUTSRC_FIRST, INPUTSRC_LAST, GET_DEFAULT(input->srcRaw), + [=](int32_t newValue) { + input->srcRaw = newValue; + lv_event_send(lvobj, LV_EVENT_VALUE_CHANGED, nullptr); + SET_DIRTY(); + }, true); + lv_obj_add_event_cb(lvobj, InputSource::value_changed, LV_EVENT_VALUE_CHANGED, nullptr); sensor_form = new Window(this, rect_t{}); sensor_form->padAll(PAD_TINY); diff --git a/radio/src/gui/colorlcd/mixer_edit.cpp b/radio/src/gui/colorlcd/mixer_edit.cpp index 2ea122c6b..ae2dd043f 100644 --- a/radio/src/gui/colorlcd/mixer_edit.cpp +++ b/radio/src/gui/colorlcd/mixer_edit.cpp @@ -110,7 +110,7 @@ void MixEditWindow::buildBody(Window *form) line = form->newLine(grid); new StaticText(line, rect_t{}, STR_SOURCE); new SourceChoice(line, rect_t{}, 0, MIXSRC_LAST, - GET_SET_DEFAULT(mix->srcRaw)); + GET_SET_DEFAULT(mix->srcRaw), true); CurveEdit::SetCurrentSource(mix->srcRaw); // Weight diff --git a/radio/src/gui/colorlcd/model_logical_switches.cpp b/radio/src/gui/colorlcd/model_logical_switches.cpp index fefba82be..b3f5631d3 100644 --- a/radio/src/gui/colorlcd/model_logical_switches.cpp +++ b/radio/src/gui/colorlcd/model_logical_switches.cpp @@ -122,7 +122,7 @@ class LogicalSwitchEditPage : public Page break; case LS_FAMILY_COMP: new SourceChoice(line, rect_t{}, 0, MIXSRC_LAST_TELEM, - GET_SET_DEFAULT(cs->v1)); + GET_SET_DEFAULT(cs->v1), true); break; case LS_FAMILY_TIMER: timer = @@ -144,7 +144,7 @@ class LogicalSwitchEditPage : public Page v2Edit->setValue(cs->v2); } SET_DIRTY(); - }); + }, true); break; } @@ -191,7 +191,7 @@ class LogicalSwitchEditPage : public Page } break; case LS_FAMILY_COMP: new SourceChoice(line, rect_t{}, 0, MIXSRC_LAST_TELEM, - GET_SET_DEFAULT(cs->v2)); + GET_SET_DEFAULT(cs->v2), true); break; case LS_FAMILY_TIMER: timer = @@ -208,7 +208,7 @@ class LogicalSwitchEditPage : public Page GET_SET_DEFAULT(cs->v2)); v2Edit->setDisplayHandler([=](int value) -> std::string { - if (cs->v1 <= MIXSRC_LAST_CH) value = calc100toRESX(value); + if (abs(cs->v1) <= MIXSRC_LAST_CH) value = calc100toRESX(value); std::string txt = getSourceCustomValueString(cs->v1, value, 0); return txt; }); diff --git a/radio/src/gui/colorlcd/sourcechoice.cpp b/radio/src/gui/colorlcd/sourcechoice.cpp index 224b28001..190bf599c 100644 --- a/radio/src/gui/colorlcd/sourcechoice.cpp +++ b/radio/src/gui/colorlcd/sourcechoice.cpp @@ -38,7 +38,7 @@ class SourceChoiceMenuToolbar : public MenuToolbar { public: - SourceChoiceMenuToolbar(SourceChoice *choice, Menu *menu) : + SourceChoiceMenuToolbar(SourceChoice* choice, Menu* menu) : MenuToolbar(choice, menu, FILTER_COLUMNS) { addButton(STR_CHAR_INPUT, MIXSRC_FIRST_INPUT, MIXSRC_LAST_INPUT, nullptr, @@ -104,9 +104,79 @@ class SourceChoiceMenuToolbar : public MenuToolbar if ((nxtBtnPos > filterColumns) && choice->isValueAvailable && choice->isValueAvailable(0)) addButton(STR_SELECT_MENU_CLR, 0, 0, nullptr, nullptr, true); + +#if defined(HARDWARE_TOUCH) + if (choice->canInvert) { + invertBtn = new MenuToolbarButton(this, {0, 0, LV_PCT(100), 0}, + STR_SELECT_MENU_INV); + invertBtn->check(choice->inverted); + lv_obj_align(invertBtn->getLvObj(), LV_ALIGN_BOTTOM_MID, 0, 0); + + invertBtn->setPressHandler([=]() { + lv_obj_clear_state(invertBtn->getLvObj(), LV_STATE_FOCUSED); + invertChoice(); + return choice->inverted; + }); + } +#endif } + + void invertChoice() + { + SourceChoice* sourceChoice = (SourceChoice*)choice; + if (sourceChoice->canInvert) { + sourceChoice->inverted = !sourceChoice->inverted; + auto idx = menu->selection(); + sourceChoice->fillMenu(menu, filter); + menu->select(idx); +#if defined(HARDWARE_TOUCH) + invertBtn->check(sourceChoice->inverted); +#endif + } + } + + void longPress() + { + lv_indev_t* indev = lv_indev_get_act(); + if (indev->driver->type == LV_INDEV_TYPE_KEYPAD) { + invertChoice(); + } + } + + protected: +#if defined(HARDWARE_TOUCH) + MenuToolbarButton* invertBtn = nullptr; +#endif }; +void SourceChoice::LongPressHandler(void* data) +{ + SourceChoice* src = (SourceChoice*)data; + if (src && src->canInvert) { + int16_t val = src->_getValue(); + if (src->isValueAvailable && src->isValueAvailable(-val)) { + src->setValue(-val); + src->invalidate(); + } + } +} + +void SourceChoice::setValue(int value) +{ + if (inMenu) { + if (inverted) value = -value; + inMenu = false; + } + Choice::setValue(value); +} + +int SourceChoice::getIntValue() const +{ + int value = Choice::getIntValue(); + if (inMenu) value = abs(value); + return value; +} + // defined in gui/gui_common.cpp uint8_t switchToMix(uint8_t source); @@ -114,6 +184,9 @@ void SourceChoice::openMenu() { setEditMode(true); // this needs to be done first before menu is created. + inverted = getIntValue() < 0; + inMenu = true; + auto menu = new Menu(this); if (menuTitle) menu->setTitle(menuTitle); @@ -149,15 +222,19 @@ void SourceChoice::openMenu() SourceChoice::SourceChoice(Window *parent, const rect_t &rect, int16_t vmin, int16_t vmax, std::function getValue, - std::function setValue) : - Choice(parent, rect, vmin, vmax, getValue, setValue, STR_SOURCE) + std::function setValue, bool allowInvert) : + Choice(parent, rect, vmin, vmax, getValue, setValue, STR_SOURCE), canInvert(allowInvert) { setTextHandler([=](int value) { + if (inMenu && inverted) value = -value; + if (isValueAvailable && !isValueAvailable(value)) return std::to_string(0); // we will fix this later return std::string(getSourceString(value)); }); + set_lv_LongPressHandler(LongPressHandler, this); + setAvailableHandler([](int v) { return isSourceAvailable(v); }); } diff --git a/radio/src/gui/colorlcd/sourcechoice.h b/radio/src/gui/colorlcd/sourcechoice.h index de8c28314..08a7fc368 100644 --- a/radio/src/gui/colorlcd/sourcechoice.h +++ b/radio/src/gui/colorlcd/sourcechoice.h @@ -33,11 +33,21 @@ class SourceChoice : public Choice public: SourceChoice(Window* parent, const rect_t& rect, int16_t vmin, int16_t vmax, std::function getValue, - std::function setValue); + std::function setValue, bool allowInvert = false); + + static void LongPressHandler(void* data); protected: friend SourceChoiceMenuToolbar; + bool inMenu = false; + bool canInvert = false; + + void setValue(int value) override; + int getIntValue() const override; + + void invertChoice(); + void openMenu() override; #if defined(DEBUG_WINDOWS) diff --git a/radio/src/gui/colorlcd/special_functions.cpp b/radio/src/gui/colorlcd/special_functions.cpp index d31e6ce50..304d33afe 100644 --- a/radio/src/gui/colorlcd/special_functions.cpp +++ b/radio/src/gui/colorlcd/special_functions.cpp @@ -373,7 +373,7 @@ void FunctionEditPage::addSourceChoice(FormLine *line, const char *title, CustomFunctionData *cfn, int16_t vmax) { new StaticText(line, rect_t{}, title); - new SourceChoice(line, rect_t{}, 0, vmax, GET_SET_DEFAULT(CFN_PARAM(cfn))); + new SourceChoice(line, rect_t{}, 0, vmax, GET_SET_DEFAULT(CFN_PARAM(cfn)), true); } NumberEdit *FunctionEditPage::addNumberEdit(FormLine *line, const char *title, diff --git a/radio/src/gui/colorlcd/switchchoice.cpp b/radio/src/gui/colorlcd/switchchoice.cpp index 864292731..9c162801a 100644 --- a/radio/src/gui/colorlcd/switchchoice.cpp +++ b/radio/src/gui/colorlcd/switchchoice.cpp @@ -98,7 +98,9 @@ class SwitchChoiceMenuToolbar : public MenuToolbar } protected: +#if defined(HARDWARE_TOUCH) MenuToolbarButton* invertBtn = nullptr; +#endif }; void SwitchChoice::LongPressHandler(void* data) diff --git a/radio/src/gui/common/stdlcd/draw_functions.cpp b/radio/src/gui/common/stdlcd/draw_functions.cpp index 913954eff..d69f58bb8 100644 --- a/radio/src/gui/common/stdlcd/draw_functions.cpp +++ b/radio/src/gui/common/stdlcd/draw_functions.cpp @@ -460,8 +460,10 @@ void drawSensorCustomValue(coord_t x, coord_t y, uint8_t sensor, int32_t value, } } -void drawSourceCustomValue(coord_t x, coord_t y, source_t source, int32_t value, LcdFlags flags) +void drawSourceCustomValue(coord_t x, coord_t y, mixsrc_t source, int32_t value, LcdFlags flags) { + source = abs(source); + if (source >= MIXSRC_FIRST_TELEM) { source = (source-MIXSRC_FIRST_TELEM) / 3; drawSensorCustomValue(x, y, source, value, flags); diff --git a/radio/src/gui/common/stdlcd/model_curves.cpp b/radio/src/gui/common/stdlcd/model_curves.cpp index e7f66391c..e4721de03 100644 --- a/radio/src/gui/common/stdlcd/model_curves.cpp +++ b/radio/src/gui/common/stdlcd/model_curves.cpp @@ -175,11 +175,13 @@ void drawFunction(FnFuncP fn, uint8_t offset) void drawCursor(FnFuncP fn, uint8_t offset) { + int16_t src = abs(s_currSrcRaw); + int x512 = getValue(s_currSrcRaw); - if (s_currSrcRaw >= MIXSRC_FIRST_TELEM) { + if (src >= MIXSRC_FIRST_TELEM) { if (s_currScale > 0) - x512 = (x512 * 1024) / convertTelemValue(s_currSrcRaw - MIXSRC_FIRST_TELEM + 1, s_currScale); - drawSensorCustomValue(LCD_W - FW - offset, 6 * FH, (s_currSrcRaw - MIXSRC_FIRST_TELEM) / 3, x512, 0); + x512 = (x512 * 1024) / convertTelemValue(src - MIXSRC_FIRST_TELEM + 1, s_currScale); + drawSensorCustomValue(LCD_W - FW - offset, 6 * FH, (src - MIXSRC_FIRST_TELEM) / 3, x512, 0); } else { lcdDrawNumber(LCD_W - FW - offset, 6*FH, calcRESXto1000(x512), RIGHT | PREC1); diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index b3dee95d3..743b3e209 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -179,7 +179,7 @@ int getChannelsUsed() bool isSourceAvailable(int source) { if (source < 0) - return false; + source = -source; if (source >= MIXSRC_FIRST_INPUT && source <= MIXSRC_LAST_INPUT) { return isInputAvailable(source - MIXSRC_FIRST_INPUT); diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 4b017e2fd..bcbe3c84e 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -129,7 +129,7 @@ void drawTelemScreenDate(coord_t x, coord_t y, source_t sensor, LcdFlags flags=0 void drawGPSPosition(coord_t x, coord_t y, int32_t longitude, int32_t latitude, LcdFlags flags=0); void drawGPSSensorValue(coord_t x, coord_t y, TelemetryItem & telemetryItem, LcdFlags flags=0); void drawSensorCustomValue(coord_t x, coord_t y, uint8_t sensor, int32_t value, LcdFlags flags=0); -void drawSourceCustomValue(coord_t x, coord_t y, source_t channel, int32_t val, LcdFlags flags=0); +void drawSourceCustomValue(coord_t x, coord_t y, mixsrc_t channel, int32_t val, LcdFlags flags=0); void drawSourceValue(coord_t x, coord_t y, source_t channel, LcdFlags flags=0); // model_setup Defines that are used in all uis in the same way diff --git a/radio/src/gui/navigation/common.cpp b/radio/src/gui/navigation/common.cpp index 985d971c8..f40b5eb16 100644 --- a/radio/src/gui/navigation/common.cpp +++ b/radio/src/gui/navigation/common.cpp @@ -115,6 +115,8 @@ void onSourceLongEnterPress(const char * result) break; } } + } else if (result == STR_MENU_INVERT) { + checkIncDecSelection = MIXSRC_INVERT; } } diff --git a/radio/src/gui/navigation/navigation.h b/radio/src/gui/navigation/navigation.h index bb6d2a394..07ee6b15b 100644 --- a/radio/src/gui/navigation/navigation.h +++ b/radio/src/gui/navigation/navigation.h @@ -73,6 +73,7 @@ extern int8_t s_editMode; // global editmode #define INCDEC_SOURCE 0x10 #define INCDEC_REP10 0x40 #define NO_DBLKEYS 0x80 +#define INCDEC_SOURCE_INVERT 0x100 int checkIncDec(event_t event, int val, int i_min, int i_max, unsigned int i_flags = 0, IsValueAvailable isValueAvailable = nullptr, @@ -96,7 +97,7 @@ void check(event_t event, uint8_t curr, const MenuHandler *menuTab, vertpos_t rowcount, uint8_t flags = 0); #define INCDEC_DECLARE_VARS(f) \ - uint8_t incdecFlag = (f); \ + uint16_t incdecFlag = (f); \ IsValueAvailable isValueAvailable = nullptr #define INCDEC_SET_FLAG(f) incdecFlag = (f) diff --git a/radio/src/gui/navigation/navigation_x7.cpp b/radio/src/gui/navigation/navigation_x7.cpp index 201321895..6e21792fb 100644 --- a/radio/src/gui/navigation/navigation_x7.cpp +++ b/radio/src/gui/navigation/navigation_x7.cpp @@ -61,6 +61,13 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, #endif if (s_editMode > 0) { + bool invert = false; + if ((i_flags & INCDEC_SOURCE_INVERT) && (newval < 0)) { + invert = true; + newval = -newval; + val = -val; + } + if (event == evt_rot_inc || event == EVT_KEY_FIRST(KEY_PLUS) || event == EVT_KEY_REPT(KEY_PLUS)) { @@ -119,22 +126,19 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, #endif } #endif + + if (invert) { + newval = -newval; + val = -val; + } } - + if (!READ_ONLY() && i_min == 0 && i_max == 1 && event == EVT_KEY_BREAK(KEY_ENTER)) { s_editMode = 0; newval = !val; } - if (newval != val) { - storageDirty(i_flags & (EE_GENERAL|EE_MODEL)); - checkIncDec_Ret = (newval > val ? 1 : -1); - } - else { - checkIncDec_Ret = 0; - } - if (i_flags & INCDEC_SOURCE) { if (event == EVT_KEY_LONG(KEY_ENTER)) { killEvents(event); @@ -178,10 +182,11 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, } } } + if (i_flags & INCDEC_SOURCE_INVERT) POPUP_MENU_ADD_ITEM(STR_MENU_INVERT); POPUP_MENU_START(onSourceLongEnterPress); } if (checkIncDecSelection != 0) { - newval = checkIncDecSelection; + newval = (checkIncDecSelection == MIXSRC_INVERT ? -newval : checkIncDecSelection); if (checkIncDecSelection != MIXSRC_MIN && checkIncDecSelection != MIXSRC_MAX) s_editMode = EDIT_MODIFY_FIELD; checkIncDecSelection = 0; @@ -212,6 +217,15 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, checkIncDecSelection = 0; } } + + if (newval != val) { + storageDirty(i_flags & (EE_GENERAL|EE_MODEL)); + checkIncDec_Ret = (newval > val ? 1 : -1); + } + else { + checkIncDec_Ret = 0; + } + return newval; } diff --git a/radio/src/gui/navigation/navigation_x9d.cpp b/radio/src/gui/navigation/navigation_x9d.cpp index 1ec40ac27..b077ddf3f 100644 --- a/radio/src/gui/navigation/navigation_x9d.cpp +++ b/radio/src/gui/navigation/navigation_x9d.cpp @@ -61,6 +61,13 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, #endif if (s_editMode > 0) { + bool invert = false; + if ((i_flags & INCDEC_SOURCE_INVERT) && (newval < 0)) { + invert = true; + newval = -newval; + val = -val; + } + if (event == evt_rot_inc || event == EVT_KEY_FIRST(KEY_PLUS) || event == EVT_KEY_REPT(KEY_PLUS)) { @@ -119,6 +126,11 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, #endif } #endif + + if (invert) { + newval = -newval; + val = -val; + } } if (!READ_ONLY() && i_min == 0 && i_max == 1 && @@ -127,27 +139,6 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, newval = !val; } - if (newval != val) { -#if !defined(ROTARY_ENCODER_NAVIGATION) - if (!(i_flags & NO_INCDEC_MARKS) && (newval != i_max) && - (newval != i_min) && stops.contains(newval)) { - bool pause = (newval > val ? !stops.contains(newval + 1) - : !stops.contains(newval - 1)); - if (pause) { - pauseEvents(event); // delay before auto-repeat continues - } - } - if (!IS_KEY_REPT(event)) { - AUDIO_KEY_PRESS(); - } -#endif - storageDirty(i_flags & (EE_GENERAL|EE_MODEL)); - checkIncDec_Ret = (newval > val ? 1 : -1); - } - else { - checkIncDec_Ret = 0; - } - if (i_flags & INCDEC_SOURCE) { if (event == EVT_KEY_LONG(KEY_ENTER)) { killEvents(event); @@ -191,10 +182,11 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, } } } + if (i_flags & INCDEC_SOURCE_INVERT) POPUP_MENU_ADD_ITEM(STR_MENU_INVERT); POPUP_MENU_START(onSourceLongEnterPress); } if (checkIncDecSelection != 0) { - newval = checkIncDecSelection; + newval = (checkIncDecSelection == MIXSRC_INVERT ? -newval : checkIncDecSelection); if (checkIncDecSelection != MIXSRC_MIN && checkIncDecSelection != MIXSRC_MAX) s_editMode = EDIT_MODIFY_FIELD; checkIncDecSelection = 0; @@ -225,6 +217,49 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, checkIncDecSelection = 0; } } + + if (newval != val) { +#if !defined(ROTARY_ENCODER_NAVIGATION) + if (!(i_flags & NO_INCDEC_MARKS) && (newval != i_max) && + (newval != i_min) && stops.contains(newval)) { + bool pause = (newval > val ? !stops.contains(newval + 1) + : !stops.contains(newval - 1)); + if (pause) { + pauseEvents(event); // delay before auto-repeat continues + } + } + if (!IS_KEY_REPT(event)) { + AUDIO_KEY_PRESS(); + } +#endif + storageDirty(i_flags & (EE_GENERAL|EE_MODEL)); + checkIncDec_Ret = (newval > val ? 1 : -1); + } + else { + checkIncDec_Ret = 0; + } + + if (newval != val) { +#if !defined(ROTARY_ENCODER_NAVIGATION) + if (!(i_flags & NO_INCDEC_MARKS) && (newval != i_max) && + (newval != i_min) && stops.contains(newval)) { + bool pause = (newval > val ? !stops.contains(newval + 1) + : !stops.contains(newval - 1)); + if (pause) { + pauseEvents(event); // delay before auto-repeat continues + } + } + if (!IS_KEY_REPT(event)) { + AUDIO_KEY_PRESS(); + } +#endif + storageDirty(i_flags & (EE_GENERAL|EE_MODEL)); + checkIncDec_Ret = (newval > val ? 1 : -1); + } + else { + checkIncDec_Ret = 0; + } + return newval; } diff --git a/radio/src/gui/navigation/navigation_xlite.cpp b/radio/src/gui/navigation/navigation_xlite.cpp index 029cab28b..ffaeb43ba 100644 --- a/radio/src/gui/navigation/navigation_xlite.cpp +++ b/radio/src/gui/navigation/navigation_xlite.cpp @@ -50,6 +50,13 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, int newval = val; if (s_editMode > 0) { + bool invert = false; + if ((i_flags & INCDEC_SOURCE_INVERT) && (newval < 0)) { + invert = true; + newval = -newval; + val = -val; + } + if (event == EVT_KEY_FIRST(KEY_RIGHT) || event == EVT_KEY_REPT(KEY_RIGHT) || event == EVT_KEY_FIRST(KEY_UP) || event == EVT_KEY_REPT(KEY_UP)) { do { @@ -109,6 +116,11 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, #endif } #endif + + if (invert) { + newval = -newval; + val = -val; + } } if (!READ_ONLY() && i_min == 0 && i_max == 1 && @@ -179,10 +191,11 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, } } } + if (i_flags & INCDEC_SOURCE_INVERT) POPUP_MENU_ADD_ITEM(STR_MENU_INVERT); POPUP_MENU_START(onSourceLongEnterPress); } if (checkIncDecSelection != 0) { - newval = checkIncDecSelection; + newval = (checkIncDecSelection == MIXSRC_INVERT ? -newval : checkIncDecSelection); if (checkIncDecSelection != MIXSRC_MIN && checkIncDecSelection != MIXSRC_MAX) s_editMode = EDIT_MODIFY_FIELD; checkIncDecSelection = 0; diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index 63821901b..9242902fb 100644 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -155,29 +155,31 @@ int expo(int x, int k) return neg ? -y : y; } -void applyExpos(int16_t * anas, uint8_t mode, uint8_t ovwrIdx, int16_t ovwrValue) +void applyExpos(int16_t * anas, uint8_t mode, int16_t ovwrIdx, int16_t ovwrValue) { int8_t cur_chn = -1; for (uint8_t i=0; isrcRaw; + mixsrc_t src = abs(srcRaw); if (!EXPO_VALID(ed)) break; // end of list if (ed->chn == cur_chn) continue; if (ed->flightModes & (1<srcRaw >= MIXSRC_FIRST_TRAINER && ed->srcRaw <= MIXSRC_LAST_TRAINER && !isTrainerValid()) + if (src >= MIXSRC_FIRST_TRAINER && src <= MIXSRC_LAST_TRAINER && !isTrainerValid()) continue; if (getSwitch(ed->swtch)) { int32_t v; - if (ed->srcRaw == ovwrIdx) { + if (srcRaw == ovwrIdx) { v = ovwrValue; } else { - v = getValue(ed->srcRaw); - if (ed->srcRaw >= MIXSRC_FIRST_TELEM && ed->scale > 0) { - v = (v * 1024) / convertTelemValue(ed->srcRaw-MIXSRC_FIRST_TELEM+1, ed->scale); + v = getValue(srcRaw); + if (src >= MIXSRC_FIRST_TELEM && ed->scale > 0) { + v = (v * 1024) / convertTelemValue(src-MIXSRC_FIRST_TELEM+1, ed->scale); } v = limit(-1024, v, 1024); } @@ -201,11 +203,12 @@ void applyExpos(int16_t * anas, uint8_t mode, uint8_t ovwrIdx, int16_t ovwrValue //========== TRIMS ================ if (ed->trimSource < TRIM_ON) virtualInputsTrims[cur_chn] = -ed->trimSource - 1; - else if (ed->trimSource == TRIM_ON && ed->srcRaw >= MIXSRC_FIRST_STICK && - ed->srcRaw <= MIXSRC_LAST_STICK) - virtualInputsTrims[cur_chn] = ed->srcRaw - MIXSRC_FIRST_STICK; + else if (ed->trimSource == TRIM_ON && src >= MIXSRC_FIRST_STICK && + src <= MIXSRC_LAST_STICK) + virtualInputsTrims[cur_chn] = src - MIXSRC_FIRST_STICK; else virtualInputsTrims[cur_chn] = -1; + // if (srcRaw < 0) v = -v; anas[cur_chn] = v; } } @@ -313,7 +316,7 @@ static const getvalue_t _switch_3pos_lookup[] = { // TODO same naming convention than the drawSource // *valid added to return status to Lua for invalid sources -getvalue_t getValue(mixsrc_t i, bool* valid) +getvalue_t _getValue(mixsrc_t i, bool* valid) { if (i == MIXSRC_NONE) { if (valid != nullptr) *valid = false; @@ -325,7 +328,7 @@ getvalue_t getValue(mixsrc_t i, bool* valid) #if defined(LUA_INPUTS) else if (i <= MIXSRC_LAST_LUA) { #if defined(LUA_MODEL_SCRIPTS) - div_t qr = div(i-MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS); + div_t qr = div((uint16_t)(i-MIXSRC_FIRST_LUA), MAX_SCRIPT_OUTPUTS); return scriptInputsOutputs[qr.quot].outputs[qr.rem].value; #else if (valid != nullptr) *valid = false; @@ -464,7 +467,7 @@ getvalue_t getValue(mixsrc_t i, bool* valid) return 0; } i -= MIXSRC_FIRST_TELEM; - div_t qr = div(i, 3); + div_t qr = div((uint16_t)i, 3); TelemetryItem & telemetryItem = telemetryItems[qr.quot]; switch (qr.rem) { case 1: @@ -595,6 +598,18 @@ void evalInputs(uint8_t mode) } } +getvalue_t getValue(mixsrc_t i, bool* valid) +{ + bool invert = false; + if (i < 0) { + invert = true; + i = -i; + } + getvalue_t v = _getValue(i, valid); + if (invert) v = -v; + return v; +} + #if defined(SURFACE_RADIO) constexpr int IDLE_TRIM_SCALE = 1; #else diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 46eab3058..3f7c73bf3 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -1881,43 +1881,45 @@ bool modelTelemetryEnabled() { void getMixSrcRange(const int source, int16_t & valMin, int16_t & valMax, LcdFlags * flags) { - if (source >= MIXSRC_FIRST_TRIM && source <= MIXSRC_LAST_TRIM) { + int asrc = abs(source); + + if (asrc >= MIXSRC_FIRST_TRIM && asrc <= MIXSRC_LAST_TRIM) { valMax = g_model.extendedTrims ? TRIM_EXTENDED_MAX : TRIM_MAX; valMin = -valMax; } #if defined(LUA_INPUTS) - else if (source >= MIXSRC_FIRST_LUA && source <= MIXSRC_LAST_LUA) { + else if (asrc >= MIXSRC_FIRST_LUA && asrc <= MIXSRC_LAST_LUA) { valMax = 30000; valMin = -valMax; } #endif - else if (source < MIXSRC_FIRST_CH) { + else if (asrc < MIXSRC_FIRST_CH) { valMax = 100; valMin = -valMax; } - else if (source <= MIXSRC_LAST_CH) { + else if (asrc <= MIXSRC_LAST_CH) { valMax = g_model.extendedLimits ? LIMIT_EXT_PERCENT : 100; valMin = -valMax; } #if defined(GVARS) - else if (source >= MIXSRC_FIRST_GVAR && source <= MIXSRC_LAST_GVAR) { - valMax = min(CFN_GVAR_CST_MAX, MODEL_GVAR_MAX(source-MIXSRC_FIRST_GVAR)); - valMin = max(CFN_GVAR_CST_MIN, MODEL_GVAR_MIN(source-MIXSRC_FIRST_GVAR)); - if (flags && g_model.gvars[source-MIXSRC_FIRST_GVAR].prec) + else if (asrc >= MIXSRC_FIRST_GVAR && asrc <= MIXSRC_LAST_GVAR) { + valMax = min(CFN_GVAR_CST_MAX, MODEL_GVAR_MAX(asrc-MIXSRC_FIRST_GVAR)); + valMin = max(CFN_GVAR_CST_MIN, MODEL_GVAR_MIN(asrc-MIXSRC_FIRST_GVAR)); + if (flags && g_model.gvars[asrc-MIXSRC_FIRST_GVAR].prec) *flags |= PREC1; } #endif - else if (source == MIXSRC_TX_VOLTAGE) { + else if (asrc == MIXSRC_TX_VOLTAGE) { valMax = 255; valMin = 0; if (flags) *flags |= PREC1; } - else if (source == MIXSRC_TX_TIME) { + else if (asrc == MIXSRC_TX_TIME) { valMax = 23 * 60 + 59; valMin = 0; } - else if (source >= MIXSRC_FIRST_TIMER && source <= MIXSRC_LAST_TIMER) { + else if (asrc >= MIXSRC_FIRST_TIMER && asrc <= MIXSRC_LAST_TIMER) { valMax = 9 * 60 * 60 - 1; valMin = -valMax; if (flags) diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 4adc68546..75bddbc22 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -401,7 +401,7 @@ int expo(int x, int k); extern void getMixSrcRange(const int source, int16_t & valMin, int16_t & valMax, LcdFlags * flags = nullptr); -void applyExpos(int16_t * anas, uint8_t mode, uint8_t ovwrIdx=0, int16_t ovwrValue=0); +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); void evalInputs(uint8_t mode); diff --git a/radio/src/opentx_types.h b/radio/src/opentx_types.h index 9fee82c69..1784c7479 100644 --- a/radio/src/opentx_types.h +++ b/radio/src/opentx_types.h @@ -83,7 +83,7 @@ typedef uint16_t event_t; typedef uint32_t tmr10ms_t; typedef int32_t rotenc_t; typedef int32_t getvalue_t; -typedef uint32_t mixsrc_t; +typedef int32_t mixsrc_t; typedef int32_t swsrc_t; typedef int16_t safetych_t; typedef int16_t gvar_t; diff --git a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp index 83021a1dd..6d3a8eb41 100644 --- a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp @@ -395,7 +395,7 @@ static const struct YamlNode struct_CurveRef[] = { static const struct YamlNode struct_MixData[] = { YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), @@ -429,7 +429,7 @@ static const struct YamlNode struct_ExpoData[] = { YAML_UNSIGNED( "scale", 14 ), YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "chn", 5 ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), diff --git a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp index 960c4161f..71c95a96d 100644 --- a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp @@ -417,6 +417,38 @@ static bool w_mixSrcRaw(const YamlNode* node, uint32_t val, yaml_writer_func wf, return true; } +static uint32_t r_mixSrcRawEx(const YamlNode* node, const char* val, uint8_t val_len) +{ + bool invert = false; + if (val[0] == '!') { + invert = true; + val += 1; + val_len -= 1; + } + int32_t rv = r_mixSrcRaw(node, val, val_len); + if (invert) + rv = -rv; + return (uint32_t)rv; +} + +static bool w_mixSrcRawExNoQuote(const YamlNode* node, uint32_t val, yaml_writer_func wf, void* opaque) +{ + // Check for negative 10 bit value. TODO: handle this better! + val &= 0x3FF; + if (val >= 512) { + if (!wf(opaque, "!", 1)) return false; + val = 1024 - val; + } + return w_mixSrcRaw(node, val, wf, opaque); +} + +static bool w_mixSrcRawEx(const YamlNode* node, uint32_t val, yaml_writer_func wf, void* opaque) +{ + if (!wf(opaque, "\"", 1)) return false; + if (!w_mixSrcRawExNoQuote(node, val, wf, opaque)) return false; + return wf(opaque, "\"", 1); +} + static void r_rssiDisabled(void* user, uint8_t* data, uint32_t bitoffs, const char* val, uint8_t val_len) { @@ -1459,7 +1491,7 @@ static void r_customFn(void* user, uint8_t* data, uint32_t bitoffs, case FUNC_BACKLIGHT: case FUNC_PLAY_VALUE: // find "," and cut val_len - CFN_PARAM(cfn) = r_mixSrcRaw(nullptr, val, l_sep); + CFN_PARAM(cfn) = r_mixSrcRawEx(nullptr, val, l_sep); break; case FUNC_PLAY_SOUND: @@ -1554,10 +1586,10 @@ static void r_customFn(void* user, uint8_t* data, uint32_t bitoffs, CFN_PARAM(cfn) = yaml_str2int(val, l_sep); break; case FUNC_ADJUST_GVAR_SOURCE: - CFN_PARAM(cfn) = r_mixSrcRaw(nullptr, val, l_sep); + CFN_PARAM(cfn) = r_mixSrcRawEx(nullptr, val, l_sep); break; case FUNC_ADJUST_GVAR_GVAR: { - uint32_t gvar = r_mixSrcRaw(nullptr, val, l_sep); + uint32_t gvar = r_mixSrcRawEx(nullptr, val, l_sep); if (gvar >= MIXSRC_FIRST_GVAR) { CFN_PARAM(cfn) = gvar - MIXSRC_FIRST_GVAR; } @@ -1680,7 +1712,7 @@ static bool w_customFn(void* user, uint8_t* data, uint32_t bitoffs, case FUNC_VOLUME: case FUNC_BACKLIGHT: case FUNC_PLAY_VALUE: - if (!w_mixSrcRaw(nullptr, CFN_PARAM(cfn), wf, opaque)) return false; + if (!w_mixSrcRawExNoQuote(nullptr, CFN_PARAM(cfn), wf, opaque)) return false; break; case FUNC_PLAY_SOUND: @@ -1739,10 +1771,10 @@ static bool w_customFn(void* user, uint8_t* data, uint32_t bitoffs, if (!wf(opaque, str, strlen(str))) return false; break; case FUNC_ADJUST_GVAR_SOURCE: - if (!w_mixSrcRaw(nullptr, CFN_PARAM(cfn), wf, opaque)) return false; + if (!w_mixSrcRawExNoQuote(nullptr, CFN_PARAM(cfn), wf, opaque)) return false; break; case FUNC_ADJUST_GVAR_GVAR: - if (!w_mixSrcRaw(nullptr, CFN_PARAM(cfn) + MIXSRC_FIRST_GVAR, wf, opaque)) return false; + if (!w_mixSrcRawExNoQuote(nullptr, CFN_PARAM(cfn) + MIXSRC_FIRST_GVAR, wf, opaque)) return false; break; } break; @@ -1837,11 +1869,11 @@ static void r_logicSw(void* user, uint8_t* data, uint32_t bitoffs, break; case LS_FAMILY_COMP: - ls->v1 = r_mixSrcRaw(nullptr, val, l_sep); + ls->v1 = r_mixSrcRawEx(nullptr, val, l_sep); val += l_sep; val_len -= l_sep; if (!val_len || val[0] != ',') return; val++; val_len--; - ls->v2 = r_mixSrcRaw(nullptr, val, val_len); + ls->v2 = r_mixSrcRawEx(nullptr, val, val_len); break; case LS_FAMILY_TIMER: @@ -1853,7 +1885,7 @@ static void r_logicSw(void* user, uint8_t* data, uint32_t bitoffs, break; default: - ls->v1 = r_mixSrcRaw(nullptr, val, l_sep); + ls->v1 = r_mixSrcRawEx(nullptr, val, l_sep); val += l_sep; val_len -= l_sep; if (!val_len || val[0] != ',') return; val++; val_len--; @@ -1902,9 +1934,9 @@ static bool w_logicSw(void* user, uint8_t* data, uint32_t bitoffs, break; case LS_FAMILY_COMP: - if (!w_mixSrcRaw(nullptr, ls->v1, wf, opaque)) return false; + if (!w_mixSrcRawExNoQuote(nullptr, ls->v1, wf, opaque)) return false; if (!wf(opaque,",",1)) return false; - if (!w_mixSrcRaw(nullptr, ls->v2, wf, opaque)) return false; + if (!w_mixSrcRawExNoQuote(nullptr, ls->v2, wf, opaque)) return false; break; case LS_FAMILY_TIMER: @@ -1916,7 +1948,7 @@ static bool w_logicSw(void* user, uint8_t* data, uint32_t bitoffs, break; default: - if (!w_mixSrcRaw(nullptr, ls->v1, wf, opaque)) return false; + if (!w_mixSrcRawExNoQuote(nullptr, ls->v1, wf, opaque)) return false; if (!wf(opaque,",",1)) return false; // TODO?: ls->v1 <= MIXSRC_LAST_CH ? calc100toRESX(ls->v2) : ls->v2 str = yaml_signed2str(ls->v2); diff --git a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp index a9f1fa523..b5c9a1c9f 100644 --- a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp @@ -422,7 +422,7 @@ static const struct YamlNode struct_CurveRef[] = { static const struct YamlNode struct_MixData[] = { YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), @@ -456,7 +456,7 @@ static const struct YamlNode struct_ExpoData[] = { YAML_UNSIGNED( "scale", 14 ), YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "chn", 5 ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), diff --git a/radio/src/storage/yaml/yaml_datastructs_pl18.cpp b/radio/src/storage/yaml/yaml_datastructs_pl18.cpp index 68e81c152..d56d4ef9d 100644 --- a/radio/src/storage/yaml/yaml_datastructs_pl18.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_pl18.cpp @@ -422,7 +422,7 @@ static const struct YamlNode struct_CurveRef[] = { static const struct YamlNode struct_MixData[] = { YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), @@ -456,7 +456,7 @@ static const struct YamlNode struct_ExpoData[] = { YAML_UNSIGNED( "scale", 14 ), YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "chn", 5 ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), diff --git a/radio/src/storage/yaml/yaml_datastructs_t20.cpp b/radio/src/storage/yaml/yaml_datastructs_t20.cpp index 8420ff429..7466c566a 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t20.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t20.cpp @@ -395,7 +395,7 @@ static const struct YamlNode struct_CurveRef[] = { static const struct YamlNode struct_MixData[] = { YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), @@ -429,7 +429,7 @@ static const struct YamlNode struct_ExpoData[] = { YAML_UNSIGNED( "scale", 14 ), YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "chn", 5 ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), diff --git a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp index 163f323e1..4819a80e8 100644 --- a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp @@ -395,7 +395,7 @@ static const struct YamlNode struct_CurveRef[] = { static const struct YamlNode struct_MixData[] = { YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), @@ -429,7 +429,7 @@ static const struct YamlNode struct_ExpoData[] = { YAML_UNSIGNED( "scale", 14 ), YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "chn", 5 ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), diff --git a/radio/src/storage/yaml/yaml_datastructs_x10.cpp b/radio/src/storage/yaml/yaml_datastructs_x10.cpp index ccf905dd9..83518353b 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x10.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x10.cpp @@ -424,7 +424,7 @@ static const struct YamlNode struct_CurveRef[] = { static const struct YamlNode struct_MixData[] = { YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), @@ -458,7 +458,7 @@ static const struct YamlNode struct_ExpoData[] = { YAML_UNSIGNED( "scale", 14 ), YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "chn", 5 ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), diff --git a/radio/src/storage/yaml/yaml_datastructs_x12s.cpp b/radio/src/storage/yaml/yaml_datastructs_x12s.cpp index ccf905dd9..83518353b 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x12s.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x12s.cpp @@ -424,7 +424,7 @@ static const struct YamlNode struct_CurveRef[] = { static const struct YamlNode struct_MixData[] = { YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), @@ -458,7 +458,7 @@ static const struct YamlNode struct_ExpoData[] = { YAML_UNSIGNED( "scale", 14 ), YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "chn", 5 ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), diff --git a/radio/src/storage/yaml/yaml_datastructs_x9d.cpp b/radio/src/storage/yaml/yaml_datastructs_x9d.cpp index 24d8b7c44..fb3956937 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9d.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9d.cpp @@ -395,7 +395,7 @@ static const struct YamlNode struct_CurveRef[] = { static const struct YamlNode struct_MixData[] = { YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), @@ -429,7 +429,7 @@ static const struct YamlNode struct_ExpoData[] = { YAML_UNSIGNED( "scale", 14 ), YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "chn", 5 ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), diff --git a/radio/src/storage/yaml/yaml_datastructs_x9e.cpp b/radio/src/storage/yaml/yaml_datastructs_x9e.cpp index a359f0209..45151a111 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9e.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9e.cpp @@ -396,7 +396,7 @@ static const struct YamlNode struct_CurveRef[] = { static const struct YamlNode struct_MixData[] = { YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), @@ -430,7 +430,7 @@ static const struct YamlNode struct_ExpoData[] = { YAML_UNSIGNED( "scale", 14 ), YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "chn", 5 ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), diff --git a/radio/src/storage/yaml/yaml_datastructs_xlites.cpp b/radio/src/storage/yaml/yaml_datastructs_xlites.cpp index 1e7d745cc..babd92b66 100644 --- a/radio/src/storage/yaml/yaml_datastructs_xlites.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_xlites.cpp @@ -398,7 +398,7 @@ static const struct YamlNode struct_CurveRef[] = { static const struct YamlNode struct_MixData[] = { YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), @@ -432,7 +432,7 @@ static const struct YamlNode struct_ExpoData[] = { YAML_UNSIGNED( "scale", 14 ), YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), - YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "chn", 5 ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), diff --git a/radio/src/strhelpers.cpp b/radio/src/strhelpers.cpp index 2772fe9c3..2337616d6 100644 --- a/radio/src/strhelpers.cpp +++ b/radio/src/strhelpers.cpp @@ -609,9 +609,17 @@ const char *getPotLabel(uint8_t idx) // this should be declared in header, but it used so much foreign symbols that // we declare it in cpp-file and pre-instantiate it for the uses template -char *getSourceString(char (&dest)[L], mixsrc_t idx) +char *getSourceString(char (&destRef)[L], mixsrc_t idx) { size_t dest_len = L; + char* dest = destRef; + + if (idx < 0) { + idx = -idx; + dest[0] = '!'; + dest += 1; + dest_len -= 1; + } if (idx == MIXSRC_NONE) { strncpy(dest, STR_EMPTY, dest_len - 1); @@ -634,7 +642,7 @@ char *getSourceString(char (&dest)[L], mixsrc_t idx) #if defined(LUA_INPUTS) else if (idx <= MIXSRC_LAST_LUA) { #if defined(LUA_MODEL_SCRIPTS) - div_t qr = div(idx - MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS); + div_t qr = div((uint16_t)(idx - MIXSRC_FIRST_LUA), MAX_SCRIPT_OUTPUTS); if (qr.quot < MAX_SCRIPTS && qr.rem < scriptInputsOutputs[qr.quot].outputsCount) { static_assert(L > sizeof(STR_CHAR_LUA) - 1, "dest string too small"); @@ -658,7 +666,7 @@ char *getSourceString(char (&dest)[L], mixsrc_t idx) } } #else - strncpy(dest, "N/A", L - 1); + strncpy(dest, "N/A", dest_len-1); #endif } #endif @@ -723,7 +731,7 @@ char *getSourceString(char (&dest)[L], mixsrc_t idx) } else if (idx <= MIXSRC_LAST_CH) { auto ch = idx - MIXSRC_FIRST_CH; if (g_model.limitData[ch].name[0] != '\0') { - copyToTerminated(dest, g_model.limitData[ch].name); + strAppend(dest, g_model.limitData[ch].name, LEN_CHANNEL_NAME); } else { strAppendStringWithIndex(dest, STR_CH, ch + 1); } @@ -759,21 +767,21 @@ char *getSourceString(char (&dest)[L], mixsrc_t idx) } else if (idx <= MIXSRC_LAST_TIMER) { idx -= MIXSRC_FIRST_TIMER; if (g_model.timers[idx].name[0] != '\0') { - copyToTerminated(dest, g_model.timers[idx].name); + strAppend(dest, g_model.timers[idx].name, LEN_TIMER_NAME); } else { strAppendStringWithIndex(dest, STR_SRC_TIMER, idx + 1); } } else { idx -= MIXSRC_FIRST_TELEM; - div_t qr = div(idx, 3); - char *pos = strAppend(dest, STR_CHAR_TELEMETRY, 2); + div_t qr = div((uint16_t)idx, 3); + char* pos = strAppend(dest, STR_CHAR_TELEMETRY, 2); pos = strAppend(pos, g_model.telemetrySensors[qr.quot].label, sizeof(g_model.telemetrySensors[qr.quot].label)); if (qr.rem) *pos = (qr.rem == 2 ? '+' : '-'); *++pos = '\0'; } - dest[L - 1] = '\0'; // assert the termination - return dest; + destRef[L - 1] = '\0'; // assert the termination + return destRef; } // pre-instantiate for use from external @@ -850,9 +858,10 @@ char *getSensorCustomValueString(char (&dest)[L], uint8_t sensor, int32_t val, } template -char *getSourceCustomValueString(char (&dest)[L], source_t source, int32_t val, +char *getSourceCustomValueString(char (&dest)[L], mixsrc_t source, int32_t val, LcdFlags flags) { + source = abs(source); size_t len = L - 1; if (source >= MIXSRC_FIRST_TELEM) { source = (source - MIXSRC_FIRST_TELEM) / 3; @@ -967,7 +976,7 @@ std::string formatNumberAsString(int32_t val, LcdFlags flags, uint8_t len, return std::string(s); } -char *getSourceCustomValueString(source_t source, int32_t val, LcdFlags flags) +char *getSourceCustomValueString(mixsrc_t source, int32_t val, LcdFlags flags) { return getSourceCustomValueString(_static_str_buffer, source, val, flags); } diff --git a/radio/src/strhelpers.h b/radio/src/strhelpers.h index 4c3cf84fc..be4f42884 100644 --- a/radio/src/strhelpers.h +++ b/radio/src/strhelpers.h @@ -112,7 +112,7 @@ template char *getSourceString(char (&dest)[L], mixsrc_t idx); template -char *getSourceCustomValueString(char (&dest)[L], source_t source, int32_t val, +char *getSourceCustomValueString(char (&dest)[L], mixsrc_t source, int32_t val, LcdFlags flags); #endif @@ -120,7 +120,7 @@ char *getSourceCustomValueString(char (&dest)[L], source_t source, int32_t val, char *getFlightModeString(char *dest, int8_t idx); char *getSourceString(mixsrc_t idx); -char *getSourceCustomValueString(source_t source, int32_t val, LcdFlags flags); +char *getSourceCustomValueString(mixsrc_t source, int32_t val, LcdFlags flags); char *getSwitchPositionName(swsrc_t idx); char *getCurveString(int idx); char *getTimerString(int32_t tme, TimerOptions timerOptions = {.options = 0}); @@ -151,20 +151,6 @@ void clearStruct(S &s) template using offset_t = std::integral_constant; -template -void copyToTerminated(char (&dest)[DL], const char (&src)[SL], - const offset_t = offset_t<0>{}) -{ - // unfortinately std::min() isn't constexpr in C++11 - // static constexpr size_t len = std::min(DL - O - 1, SL); - static constexpr size_t dl{DL - O - 1}; - static_assert(dl > 0, "wrong sizes or offset"); - static constexpr size_t len = (dl < SL) ? dl : SL; - strncpy(&dest[O], &src[0], len); - static_assert((len + O) < DL, "wrong sizes of offset"); - dest[len + O] = '\0'; -} - template int strncasecmp(char (&s1)[L1], const char (&s2)[L2]) { diff --git a/radio/src/thirdparty/libopenui/src/menutoolbar.cpp b/radio/src/thirdparty/libopenui/src/menutoolbar.cpp index 05d89b4e2..508d90f4b 100644 --- a/radio/src/thirdparty/libopenui/src/menutoolbar.cpp +++ b/radio/src/thirdparty/libopenui/src/menutoolbar.cpp @@ -22,8 +22,6 @@ #include "themes/etx_lv_theme.h" #include "translations.h" -constexpr uint32_t MENUS_TOOLBAR_BUTTON_WIDTH = 32; - static const lv_obj_class_t menu_button_class = { .base_class = &button_class, .constructor_cb = nullptr, diff --git a/radio/src/thirdparty/libopenui/src/menutoolbar.h b/radio/src/thirdparty/libopenui/src/menutoolbar.h index 70166cd7b..cf54f5565 100644 --- a/radio/src/thirdparty/libopenui/src/menutoolbar.h +++ b/radio/src/thirdparty/libopenui/src/menutoolbar.h @@ -21,6 +21,8 @@ #include "button.h" #include "choice.h" +constexpr uint32_t MENUS_TOOLBAR_BUTTON_WIDTH = 32; + class Menu; class MenuToolbarButton : public ButtonBase