From 4b917b762c578061c8f422feaa65ddbb7f4b1faa Mon Sep 17 00:00:00 2001 From: philmoz Date: Fri, 26 Jul 2024 20:51:21 +1000 Subject: [PATCH] feat: use any source for expo/weight/offset (#5220) Co-authored-by: philmoz Co-authored-by: 3djc <3djc@gh.com> Co-authored-by: elecpower --- companion/src/constants.h | 2 +- .../src/datamodels/filtereditemmodels.cpp | 2 - companion/src/firmwares/CMakeLists.txt | 1 + companion/src/firmwares/curvereference.cpp | 177 ++-- companion/src/firmwares/curvereference.h | 48 +- .../src/firmwares/edgetx/yaml_expodata.cpp | 8 +- .../src/firmwares/edgetx/yaml_mixdata.cpp | 64 +- companion/src/firmwares/edgetx/yaml_mixdata.h | 4 +- .../src/firmwares/edgetx/yaml_modeldata.cpp | 2 + .../src/firmwares/opentx/opentxeeprom.cpp | 32 + companion/src/firmwares/rawsource.cpp | 2 +- companion/src/firmwares/sourcenumref.cpp | 156 +++ companion/src/firmwares/sourcenumref.h | 96 ++ companion/src/helpers.cpp | 31 + companion/src/helpers.h | 2 + companion/src/modeledit/channels.cpp | 56 +- companion/src/modeledit/channels.h | 4 +- companion/src/modeledit/curves.cpp | 2 +- companion/src/modeledit/expodialog.cpp | 59 +- companion/src/modeledit/expodialog.h | 16 +- companion/src/modeledit/expodialog.ui | 938 +++++++++--------- companion/src/modeledit/mixerdialog.cpp | 93 +- companion/src/modeledit/mixerdialog.h | 11 +- companion/src/modeledit/mixerdialog.ui | 845 ++++++++-------- companion/src/modelprinter.cpp | 13 +- companion/src/shared/curveimagewidget.cpp | 12 +- companion/src/shared/curveimagewidget.h | 3 +- radio/src/curves.cpp | 26 +- radio/src/dataconstants.h | 1 + radio/src/datastructs.h | 20 +- radio/src/datastructs_private.h | 38 +- radio/src/gui/128x64/gui.h | 11 +- radio/src/gui/128x64/lcd.cpp | 49 - radio/src/gui/128x64/lcd.h | 1 - radio/src/gui/128x64/model_input_edit.cpp | 28 +- radio/src/gui/128x64/model_mix_edit.cpp | 23 +- radio/src/gui/128x64/widgets.cpp | 24 + radio/src/gui/212x64/gui.h | 9 +- radio/src/gui/212x64/lcd.cpp | 45 - radio/src/gui/212x64/lcd.h | 1 - radio/src/gui/212x64/model_input_edit.cpp | 10 +- radio/src/gui/212x64/model_mix_edit.cpp | 21 +- radio/src/gui/212x64/widgets.cpp | 24 + radio/src/gui/colorlcd/CMakeLists.txt | 1 + radio/src/gui/colorlcd/curve.cpp | 6 +- radio/src/gui/colorlcd/curve_param.cpp | 63 +- radio/src/gui/colorlcd/curve_param.h | 26 +- radio/src/gui/colorlcd/input_edit.cpp | 74 +- radio/src/gui/colorlcd/input_edit.h | 6 +- radio/src/gui/colorlcd/list_line_button.cpp | 19 +- radio/src/gui/colorlcd/list_line_button.h | 5 +- radio/src/gui/colorlcd/mixer_edit.cpp | 15 +- radio/src/gui/colorlcd/model_inputs.cpp | 42 +- radio/src/gui/colorlcd/model_mixes.cpp | 31 +- radio/src/gui/colorlcd/source_numberedit.cpp | 147 +++ radio/src/gui/colorlcd/source_numberedit.h | 67 ++ .../src/gui/common/stdlcd/draw_functions.cpp | 97 +- radio/src/gui/common/stdlcd/draw_functions.h | 5 +- radio/src/gui/common/stdlcd/model_curves.cpp | 27 +- radio/src/gui/common/stdlcd/model_inputs.cpp | 15 +- radio/src/gui/common/stdlcd/model_mixes.cpp | 14 +- radio/src/gui/navigation/common.cpp | 2 + radio/src/gui/navigation/navigation.h | 2 + radio/src/gui/navigation/navigation_9x.cpp | 113 ++- radio/src/gui/navigation/navigation_x7.cpp | 57 +- radio/src/gui/navigation/navigation_x9d.cpp | 52 +- radio/src/gui/navigation/navigation_xlite.cpp | 54 +- radio/src/lua/api_model.cpp | 36 +- radio/src/mixer.cpp | 27 +- radio/src/myeeprom.h | 8 - .../storage/yaml/yaml_datastructs_128x64.cpp | 24 +- .../storage/yaml/yaml_datastructs_funcs.cpp | 34 + .../storage/yaml/yaml_datastructs_nv14.cpp | 24 +- .../storage/yaml/yaml_datastructs_pl18.cpp | 24 +- .../src/storage/yaml/yaml_datastructs_t15.cpp | 24 +- .../src/storage/yaml/yaml_datastructs_t20.cpp | 24 +- .../storage/yaml/yaml_datastructs_tpro.cpp | 24 +- .../src/storage/yaml/yaml_datastructs_x10.cpp | 24 +- .../storage/yaml/yaml_datastructs_x12s.cpp | 24 +- .../src/storage/yaml/yaml_datastructs_x9d.cpp | 24 +- .../src/storage/yaml/yaml_datastructs_x9e.cpp | 24 +- .../storage/yaml/yaml_datastructs_xlites.cpp | 24 +- radio/src/strhelpers.cpp | 22 +- radio/src/strhelpers.h | 3 + radio/src/tests/lua.cpp | 7 +- radio/src/tests/mixer.cpp | 68 +- radio/src/thirdparty/libopenui/src/choice.cpp | 3 +- 87 files changed, 2751 insertions(+), 1671 deletions(-) create mode 100644 companion/src/firmwares/sourcenumref.cpp create mode 100644 companion/src/firmwares/sourcenumref.h create mode 100644 radio/src/gui/colorlcd/source_numberedit.cpp create mode 100644 radio/src/gui/colorlcd/source_numberedit.h diff --git a/companion/src/constants.h b/companion/src/constants.h index 787016139..fd1f9c170 100644 --- a/companion/src/constants.h +++ b/companion/src/constants.h @@ -93,7 +93,7 @@ #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 CPN_STR_SRC_INDICATOR_NEG QCoreApplication::translate("RawSource", "-") // Source negative value indicator. #define EDGETX_HOME_PAGE_URL "https://edgetx.org" diff --git a/companion/src/datamodels/filtereditemmodels.cpp b/companion/src/datamodels/filtereditemmodels.cpp index 4f4e27262..b5e24875f 100644 --- a/companion/src/datamodels/filtereditemmodels.cpp +++ b/companion/src/datamodels/filtereditemmodels.cpp @@ -222,8 +222,6 @@ CurveRefFilteredFactory::CurveRefFilteredFactory(CompoundItemModelFactory * shar registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_Curve), curveFlags), fidToString(CRFIM_CURVE), CRFIM_CURVE); - registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef), gvarRefFlags), - fidToString(CRFIM_GVARREF), CRFIM_GVARREF); registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_CurveRefType)), fidToString(CRFIM_TYPE), CRFIM_TYPE); registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_CurveRefFunc)), diff --git a/companion/src/firmwares/CMakeLists.txt b/companion/src/firmwares/CMakeLists.txt index 436587730..b7dc976b9 100644 --- a/companion/src/firmwares/CMakeLists.txt +++ b/companion/src/firmwares/CMakeLists.txt @@ -28,6 +28,7 @@ set(${PROJECT_NAME}_NAMES rawsource rawswitch sensordata + sourcenumref telem_data timerdata ersky9x/ersky9xeeprom diff --git a/companion/src/firmwares/curvereference.cpp b/companion/src/firmwares/curvereference.cpp index 315fb5269..651479d32 100644 --- a/companion/src/firmwares/curvereference.cpp +++ b/companion/src/firmwares/curvereference.cpp @@ -19,14 +19,16 @@ */ #include "curvereference.h" -#include "adjustmentreference.h" #include "helpers.h" #include "modeldata.h" +#include "generalsettings.h" #include "filtereditemmodels.h" #include "curveimagewidget.h" #include "curvedialog.h" +#include "sourcenumref.h" -const QString CurveReference::toString(const ModelData * model, bool verbose) const +const QString CurveReference::toString(const ModelData * model, bool verbose, const GeneralSettings * const generalSettings, + Board::Type board, bool prefixCustomName) const { if (value == 0) return CPN_STR_NONE_ITEM; @@ -37,7 +39,7 @@ const QString CurveReference::toString(const ModelData * model, bool verbose) co switch(type) { case CURVE_REF_DIFF: case CURVE_REF_EXPO: - ret = AdjustmentReference(value).toString(model); + ret = SourceNumRef(value).toString(model, generalSettings, board, prefixCustomName); break; case CURVE_REF_FUNC: ret = functionToString(value); @@ -48,7 +50,7 @@ const QString CurveReference::toString(const ModelData * model, bool verbose) co else ret = CurveData().nameToString(idx); if (value < 0) - ret.prepend(CPN_STR_SW_INDICATOR_REV); + ret.prepend(CPN_STR_SRC_INDICATOR_NEG); break; default: return CPN_STR_UNKNOWN_ITEM; @@ -62,7 +64,7 @@ const QString CurveReference::toString(const ModelData * model, bool verbose) co const bool CurveReference::isValueNumber() const { - return (type == CURVE_REF_DIFF || type == CURVE_REF_EXPO) && AdjustmentReference(value).type == AdjustmentReference::ADJUST_REF_VALUE; + return (type == CURVE_REF_DIFF || type == CURVE_REF_EXPO) && SourceNumRef(value).isNumber(); } const bool CurveReference::isAvailable() const @@ -74,7 +76,7 @@ const bool CurveReference::isAvailable() const int CurveReference::getDefaultValue(const CurveRefType type, const bool isGVar) { if (isGVar && (type == CURVE_REF_DIFF || type == CURVE_REF_EXPO)) - return AdjustmentReference(AdjustmentReference::ADJUST_REF_GVAR, 1).toValue(); + return SourceNumRef(SOURCE_TYPE_GVAR, 1).toValue(); else if (type == CURVE_REF_FUNC) return 1; else @@ -146,54 +148,50 @@ int CurveReference::functionCount() * CurveReferenceUIManager */ -CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveTypeCB, QCheckBox * curveGVarCB, QSpinBox * curveValueSB, - QComboBox * curveValueCB, QLabel * curveLabelImage, +CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * cboType, QCheckBox * chkUseSource, QSpinBox * sbxValue, + QComboBox * cboSource, QComboBox * cboCurveFunc, CurveImageWidget * curveImage, CurveReference & curveRef, ModelData & model, CompoundItemModelFactory * sharedItemModels, - CurveRefFilteredFactory * curveRefFilteredFactory, QObject * parent) : + CurveRefFilteredFactory * curveRefFilteredFactory, FilteredItemModel * sourceItemModel, + QObject * parent) : QObject(parent), - curveTypeCB(curveTypeCB), - curveGVarCB(curveGVarCB), - curveValueSB(curveValueSB), - curveValueCB(curveValueCB), + cboType(cboType), + chkUseSource(chkUseSource), + sbxValue(sbxValue), + cboSource(cboSource), + cboCurveFunc(cboCurveFunc), + curveImage(curveImage), curveRef(curveRef), model(model), - sharedItemModels(sharedItemModels), filteredModelFactory(curveRefFilteredFactory), lock(false), - curveImageWidget(nullptr) + srcNumRefEditor(nullptr) { connectItemModelEvents(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_CURVE)); - hasCapabilityGvars = getCurrentFirmware()->getCapability(Gvars); + if (chkUseSource || sbxValue || cboSource) + srcNumRefEditor = new SourceNumRefEditor(curveRef.value, chkUseSource, sbxValue, cboSource, 0, -100, 100, 1, model, sourceItemModel); - if (curveTypeCB) { - curveTypeCB->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_TYPE)); - curveTypeCB->setCurrentIndex(curveTypeCB->findData((int)curveRef.type)); - connect(curveTypeCB, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int))); + if (cboType) { + cboType->setSizeAdjustPolicy(QComboBox::AdjustToContents); + cboType->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_TYPE)); + cboType->setCurrentIndex(cboType->findData((int)curveRef.type)); + connect(cboType, QOverload::of(&QComboBox::currentIndexChanged), this, &CurveReferenceUIManager::cboTypeChanged); } - if (curveGVarCB) - connect(curveGVarCB, SIGNAL(stateChanged(int)), this, SLOT(gvarCBChanged(int))); - - if (curveValueSB) { - curveValueSB->setMinimum(-100); - curveValueSB->setMaximum(100); - connect(curveValueSB, SIGNAL(editingFinished()), this, SLOT(valueSBChanged())); - } - - if (curveValueCB) { - curveValueCB->setSizeAdjustPolicy(QComboBox::AdjustToContents); - curveValueCB->setMaxVisibleItems(10); - connect(curveValueCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valueCBChanged())); - - if (curveLabelImage) { - curveImageWidget = qobject_cast(curveLabelImage); - if (curveImageWidget) { - curveImageWidget->set(&model, getCurrentFirmware(), sharedItemModels, abs(curveRef.value) - 1, Qt::black, 3); - curveImageWidget->setGrid(Qt::gray, 2); - connect(curveImageWidget, &CurveImageWidget::doubleClicked, this, &CurveReferenceUIManager::curveImageDoubleClicked); - } + if (cboCurveFunc) { + if (!cboType) { + cboCurveFunc->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_CURVE)); + cboCurveFunc->setCurrentIndex(cboCurveFunc->findData(curveRef.value)); } + cboCurveFunc->setSizeAdjustPolicy(QComboBox::AdjustToContents); + cboCurveFunc->setMaxVisibleItems(10); + connect(cboCurveFunc, QOverload::of(&QComboBox::currentIndexChanged), this, &CurveReferenceUIManager::cboCurveFuncChanged); + } + + if (curveImage) { + curveImage->set(&model, getCurrentFirmware(), sharedItemModels, curveRef.value, Qt::black, 3); + curveImage->setGrid(Qt::gray, 2); + connect(curveImage, &CurveImageWidget::doubleClicked, this, &CurveReferenceUIManager::curveImageDoubleClicked); } update(); @@ -201,10 +199,10 @@ CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveTypeCB, QCheck CurveReferenceUIManager::~CurveReferenceUIManager() { - + delete srcNumRefEditor; } -#define CURVE_REF_UI_GVAR_SHOW (1 << 0) +#define CURVE_REF_UI_SRC_SHOW (1 << 0) #define CURVE_REF_UI_VALUE_SHOW (1 << 1) #define CURVE_REF_UI_REF_SHOW (1 << 2) #define CURVE_REF_UI_CURVE_SHOW (1 << 3) @@ -212,89 +210,72 @@ CurveReferenceUIManager::~CurveReferenceUIManager() void CurveReferenceUIManager::update() { lock = true; + + if (srcNumRefEditor) + srcNumRefEditor->setLock(true); + int widgetsMask = 0; - if (curveRef.type == CurveReference::CURVE_REF_DIFF || curveRef.type == CurveReference::CURVE_REF_EXPO) { - if (hasCapabilityGvars) - widgetsMask |= CURVE_REF_UI_GVAR_SHOW; - if (curveRef.isValueNumber()) { - curveGVarCB->setChecked(false); - curveValueSB->setValue(curveRef.value); - widgetsMask |= CURVE_REF_UI_VALUE_SHOW; + if (srcNumRefEditor) { + if (curveRef.type == CurveReference::CURVE_REF_DIFF || curveRef.type == CurveReference::CURVE_REF_EXPO) { + srcNumRefEditor->setVisible(true); + srcNumRefEditor->update(); } else { - curveGVarCB->setChecked(true); + srcNumRefEditor->setVisible(false); widgetsMask |= CURVE_REF_UI_REF_SHOW; } } - else { + else widgetsMask |= CURVE_REF_UI_REF_SHOW; - } - if (curveRef.type == CurveReference::CURVE_REF_CUSTOM) + if (curveRef.type == CurveReference::CURVE_REF_CUSTOM && curveRef.value != 0) widgetsMask |= CURVE_REF_UI_CURVE_SHOW; + if (cboType) + cboType->setCurrentIndex(cboType->findData(curveRef.type)); - if (curveTypeCB) { - curveTypeCB->setCurrentIndex(curveTypeCB->findData(curveRef.type)); - curveTypeCB->show(); - } - - if (curveGVarCB) - curveGVarCB->setVisible(widgetsMask & CURVE_REF_UI_GVAR_SHOW); - - if (curveValueSB) - curveValueSB->setVisible(widgetsMask & CURVE_REF_UI_VALUE_SHOW); - - if (curveValueCB) { + if (cboCurveFunc) { if (curveRef.isValueReference()) - populateValueCB(curveValueCB); - curveValueCB->setVisible(widgetsMask & CURVE_REF_UI_REF_SHOW); + populateValueCB(cboCurveFunc); + cboCurveFunc->setVisible(widgetsMask & CURVE_REF_UI_REF_SHOW); } - if (curveValueCB && curveImageWidget) { - curveImageWidget->draw(); - curveImageWidget->setVisible(widgetsMask & CURVE_REF_UI_CURVE_SHOW); + if (curveImage) { + if (widgetsMask & CURVE_REF_UI_CURVE_SHOW) { + curveImage->setIndex(curveRef.value); + if (abs(curveRef.value) > 0 && abs(curveRef.value) <= CPN_MAX_CURVES) + curveImage->setPen(colors[abs(curveRef.value) - 1], 3); + else + curveImage->setPen(Qt::black, 3); + } + curveImage->draw(); + curveImage->setVisible(widgetsMask & CURVE_REF_UI_CURVE_SHOW); } emit resized(); + if (srcNumRefEditor) + srcNumRefEditor->setLock(false); + lock = false; } -void CurveReferenceUIManager::gvarCBChanged(int state) +void CurveReferenceUIManager::cboTypeChanged(int index) { if (!lock) { - curveRef.value = CurveReference::getDefaultValue(curveRef.type, state); - update(); - } -} - -void CurveReferenceUIManager::typeChanged(int value) -{ - if (!lock) { - CurveReference::CurveRefType type = (CurveReference::CurveRefType)curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt(); + CurveReference::CurveRefType type = (CurveReference::CurveRefType)cboType->itemData(index).toInt(); curveRef = CurveReference(type, CurveReference::getDefaultValue(type)); - if (curveImageWidget && curveRef.type == CurveReference::CURVE_REF_CUSTOM) - curveImageWidget->setIndex(abs(curveRef.value) - 1); update(); } } -void CurveReferenceUIManager::valueSBChanged() +void CurveReferenceUIManager::cboCurveFuncChanged(int index) { if (!lock) { - curveRef.value = curveValueSB->value(); - update(); - } -} - -void CurveReferenceUIManager::valueCBChanged() -{ - if (!lock) { - curveRef.value = curveValueCB->itemData(curveValueCB->currentIndex()).toInt(); - if (curveImageWidget && curveRef.type == CurveReference::CURVE_REF_CUSTOM) - curveImageWidget->setIndex(abs(curveRef.value) - 1); + if (!cboType) + curveRef.type = CurveReference::CURVE_REF_CUSTOM; + curveRef.value = cboCurveFunc->itemData(index).toInt(); update(); } } @@ -303,10 +284,6 @@ void CurveReferenceUIManager::populateValueCB(QComboBox * cb) { if (cb) { switch (curveRef.type) { - case CurveReference::CURVE_REF_DIFF: - case CurveReference::CURVE_REF_EXPO: - cb->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_GVARREF)); - break; case CurveReference::CURVE_REF_FUNC: cb->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_FUNC)); break; @@ -324,7 +301,7 @@ void CurveReferenceUIManager::populateValueCB(QComboBox * cb) void CurveReferenceUIManager::curveImageDoubleClicked() { if (curveRef.type == CurveReference::CURVE_REF_CUSTOM && abs(curveRef.value) > 0) - curveImageWidget->edit(); + curveImage->edit(); } void CurveReferenceUIManager::connectItemModelEvents(const FilteredItemModel * itemModel) diff --git a/companion/src/firmwares/curvereference.h b/companion/src/firmwares/curvereference.h index 5bdad30dc..c1d34cabe 100644 --- a/companion/src/firmwares/curvereference.h +++ b/companion/src/firmwares/curvereference.h @@ -20,6 +20,8 @@ #pragma once +#include "rawsource.h" + #include #include #include @@ -27,11 +29,13 @@ #include #include +class GeneralSettings; class ModelData; class CurveRefFilteredFactory; class CompoundItemModelFactory; class FilteredItemModel; class CurveImageWidget; +class SourceNumRefEditor; class CurveReference { @@ -64,7 +68,8 @@ class CurveReference { const bool isSet() const { return !isEmpty(); } const bool isValueNumber() const; const bool isValueReference() const { return !isValueNumber(); } - const QString toString(const ModelData * model = nullptr, bool verbose = true) const; + const QString toString(const ModelData * model = nullptr, bool verbose = true, const GeneralSettings * const generalSettings = nullptr, + Board::Type board = Board::BOARD_UNKNOWN, bool prefixCustomName = true) const; const bool isAvailable() const; CurveRefType type; @@ -91,13 +96,17 @@ class CurveReferenceUIManager : public QObject { Q_OBJECT public: - explicit CurveReferenceUIManager(QComboBox *curveTypeCB, QCheckBox *curveGVarCB, QSpinBox *curveValueSB, QComboBox *curveValueCB, - QLabel *curveImage, CurveReference & curve, ModelData & model, CompoundItemModelFactory * sharedItemModels, - CurveRefFilteredFactory * curveRefFilteredFactory, QObject * parent = nullptr); + explicit CurveReferenceUIManager(QComboBox * cboType, QCheckBox * chkUseSource, QSpinBox * sbxValue, QComboBox * cboSource, + QComboBox * cboCurveFunc, CurveImageWidget * curveImage, CurveReference & curveRef, + ModelData & model, CompoundItemModelFactory * sharedItemModels, + CurveRefFilteredFactory * curveRefFilteredFactory, FilteredItemModel * sourceItemModel, + QObject * parent = nullptr); - explicit CurveReferenceUIManager(QComboBox *curveValueCB, CurveReference & curve, ModelData & model, CompoundItemModelFactory * sharedItemModels, - CurveRefFilteredFactory * curveRefFilteredFactory, QObject * parent = nullptr) : - CurveReferenceUIManager(nullptr, nullptr, nullptr, curveValueCB, nullptr, curve, model, sharedItemModels, curveRefFilteredFactory, parent) {} + explicit CurveReferenceUIManager(QComboBox *cboCurveFunc, CurveImageWidget * curveImage, CurveReference & curveRef, ModelData & model, + CompoundItemModelFactory * sharedItemModels, CurveRefFilteredFactory * curveRefFilteredFactory, + QObject * parent = nullptr) : + CurveReferenceUIManager(nullptr, nullptr, nullptr, nullptr, cboCurveFunc, curveImage, curveRef, model, sharedItemModels, + curveRefFilteredFactory, nullptr, parent) {} virtual ~CurveReferenceUIManager(); @@ -105,28 +114,25 @@ class CurveReferenceUIManager : public QObject { void resized(); protected slots: - void gvarCBChanged(int); - void typeChanged(int); - void valueSBChanged(); - void valueCBChanged(); + void cboTypeChanged(int); + void cboCurveFuncChanged(int); void update(); void curveImageDoubleClicked(); void onItemModelAboutToBeUpdated(); void onItemModelUpdateComplete(); private: - QComboBox *curveTypeCB; - QCheckBox *curveGVarCB; - QSpinBox *curveValueSB; - QComboBox *curveValueCB; - CurveReference & curveRef; - ModelData & model; - CompoundItemModelFactory *sharedItemModels; + QComboBox *cboType; + QCheckBox *chkUseSource; + QSpinBox *sbxValue; + QComboBox *cboSource; + QComboBox *cboCurveFunc; + CurveImageWidget *curveImage; + CurveReference &curveRef; + ModelData &model; CurveRefFilteredFactory *filteredModelFactory; bool lock; - CurveImageWidget *curveImageWidget = nullptr; - - bool hasCapabilityGvars; + SourceNumRefEditor *srcNumRefEditor; void connectItemModelEvents(const FilteredItemModel * itemModel); void populateValueCB(QComboBox * cb); diff --git a/companion/src/firmwares/edgetx/yaml_expodata.cpp b/companion/src/firmwares/edgetx/yaml_expodata.cpp index 547c85ff4..f0cfa2e91 100644 --- a/companion/src/firmwares/edgetx/yaml_expodata.cpp +++ b/companion/src/firmwares/edgetx/yaml_expodata.cpp @@ -35,8 +35,8 @@ Node convert::encode(const ExpoData& rhs) node["chn"] = rhs.chn; node["swtch"] = rhs.swtch; node["flightModes"] = YamlWriteFlightModes(rhs.flightModes); - node["weight"] = YamlWriteMixWeight(rhs.weight); - node["offset"] = YamlWriteMixWeight(rhs.offset); + node["weight"] = YamlSourceNumRefEncode(rhs.weight); + node["offset"] = YamlSourceNumRefEncode(rhs.offset); node["curve"] = rhs.curve; node["trimSource"] = rhs.carryTrim; // temporary for 2.8.1, trimSource in 2.9 node["name"] = rhs.name; @@ -54,10 +54,10 @@ bool convert::decode(const Node& node, ExpoData& rhs) rhs.flightModes = YamlReadFlightModes(node["flightModes"]); } if (node["weight"]) { - rhs.weight = YamlReadMixWeight(node["weight"]); + rhs.weight = YamlSourceNumRefDecode(node["weight"]); } if (node["offset"]) { - rhs.offset = YamlReadMixWeight(node["offset"]); + rhs.offset = YamlSourceNumRefDecode(node["offset"]); } node["curve"] >> rhs.curve; if (node["carryTrim"]) { // 2.9 - change bugged carryTrim to trimSource diff --git a/companion/src/firmwares/edgetx/yaml_mixdata.cpp b/companion/src/firmwares/edgetx/yaml_mixdata.cpp index cb5f39e09..971556a44 100644 --- a/companion/src/firmwares/edgetx/yaml_mixdata.cpp +++ b/companion/src/firmwares/edgetx/yaml_mixdata.cpp @@ -22,6 +22,7 @@ #include "yaml_rawswitch.h" #include "yaml_rawsource.h" #include "curvereference.h" +#include "sourcenumref.h" static const YamlLookupTable mixMultiplexLut = { { MLTPX_ADD, "ADD" }, @@ -32,46 +33,55 @@ static const YamlLookupTable mixMultiplexLut = { #define GVAR_SMALL 128 #define CPN_GV1 1024 -int32_t YamlReadMixWeight(const YAML::Node& node) +int32_t YamlSourceNumRefDecode(const YAML::Node& node) { std::string val = node.as(); - if ((val.size() >= 4) + + if (modelSettingsVersion < SemanticVersion(QString("2.11.0"))) { + if ((val.size() >= 4) && (val[0] == '-') && (val[1] == 'G') && (val[2] == 'V') && (val[3] >= '1') && (val[3] <= '9')) { - return -10000 - std::stoi(val.substr(3)); - } + std::stringstream src(val.substr(3)); + int gv = 0; + src >> gv; + return RawSource(SOURCE_TYPE_GVAR, gv).toValue() * -1; + } - if ((val.size() >= 3) + if ((val.size() >= 3) && (val[0] == 'G') && (val[1] == 'V') && (val[2] >= '1') && (val[2] <= '9')) { - return 10000 + std::stoi(val.substr(2)); + std::stringstream src(val.substr(2)); + int gv = 0; + src >> gv; + return RawSource(SOURCE_TYPE_GVAR, gv).toValue(); + } } - try { - return std::stoi(val); - } catch(...) { - throw YAML::TypedBadConversion(node.Mark()); - } + int i = val[0] == '-' ? 1 : 0; + + if (val[i] >= '0' && val[i] <= '9') + try { + return std::stoi(val); + } catch(...) { + throw YAML::TypedBadConversion(node.Mark()); + } + else + return YamlRawSourceDecode(val).toValue(); } -std::string YamlWriteMixWeight(int32_t sval) +std::string YamlSourceNumRefEncode(int32_t sval) { - if (sval < -10000) { - int n = -sval - 10000; - return std::string("-GV") + std::to_string(n); - } else if (sval > 10000) { - int n = sval - 10000; - return std::string("GV") + std::to_string(n); - } - - return std::to_string(sval); + if (SourceNumRef(sval).isNumber()) + return std::to_string(sval); + else + return YamlRawSourceEncode(RawSource(sval)); } uint32_t YamlReadFlightModes(const YAML::Node& node) @@ -108,7 +118,7 @@ Node convert::encode(const CurveReference& rhs) { Node node; node["type"] = (int)rhs.type; - node["value"] = YamlWriteMixWeight(rhs.value); + node["value"] = YamlSourceNumRefEncode(rhs.value); return node; } @@ -119,7 +129,7 @@ bool convert::decode(const Node& node, CurveReference& rhs) node["type"] >> type; rhs.type = (CurveReference::CurveRefType)type; if (node["value"]) { - rhs.value = YamlReadMixWeight(node["value"]); + rhs.value = YamlSourceNumRefDecode(node["value"]); } return true; } @@ -129,7 +139,7 @@ Node convert::encode(const MixData& rhs) Node node; node["destCh"] = rhs.destCh - 1; node["srcRaw"] = rhs.srcRaw; - node["weight"] = YamlWriteMixWeight(rhs.weight); + node["weight"] = YamlSourceNumRefEncode(rhs.weight); node["swtch"] = rhs.swtch; node["curve"] = rhs.curve; node["delayUp"] = rhs.delayUp; @@ -141,7 +151,7 @@ Node convert::encode(const MixData& rhs) node["mltpx"] = rhs.mltpx; node["mixWarn"] = rhs.mixWarn; node["flightModes"] = YamlWriteFlightModes(rhs.flightModes); - node["offset"] = YamlWriteMixWeight(rhs.sOffset); + node["offset"] = YamlSourceNumRefEncode(rhs.sOffset); node["name"] = rhs.name; return node; } @@ -151,7 +161,7 @@ bool convert::decode(const Node& node, MixData& rhs) node["destCh"] >> ioffset_int((int&)rhs.destCh, -1); node["srcRaw"] >> rhs.srcRaw; if (node["weight"]) { - rhs.weight = YamlReadMixWeight(node["weight"]); + rhs.weight = YamlSourceNumRefDecode(node["weight"]); } node["swtch"] >> rhs.swtch; node["curve"] >> rhs.curve; @@ -167,7 +177,7 @@ bool convert::decode(const Node& node, MixData& rhs) rhs.flightModes = YamlReadFlightModes(node["flightModes"]); } if (node["offset"]) { - rhs.sOffset = YamlReadMixWeight(node["offset"]); + rhs.sOffset = YamlSourceNumRefDecode(node["offset"]); } node["name"] >> rhs.name; return true; diff --git a/companion/src/firmwares/edgetx/yaml_mixdata.h b/companion/src/firmwares/edgetx/yaml_mixdata.h index 0b08702f6..7c1d2b0c6 100644 --- a/companion/src/firmwares/edgetx/yaml_mixdata.h +++ b/companion/src/firmwares/edgetx/yaml_mixdata.h @@ -21,8 +21,8 @@ #include "yaml_ops.h" #include "mixdata.h" -int32_t YamlReadMixWeight(const YAML::Node& node); -std::string YamlWriteMixWeight(int32_t sval); +int32_t YamlSourceNumRefDecode(const YAML::Node& node); +std::string YamlSourceNumRefEncode(int32_t sval); uint32_t YamlReadFlightModes(const YAML::Node& node); std::string YamlWriteFlightModes(uint32_t val); diff --git a/companion/src/firmwares/edgetx/yaml_modeldata.cpp b/companion/src/firmwares/edgetx/yaml_modeldata.cpp index 84cbf433d..37936eb74 100644 --- a/companion/src/firmwares/edgetx/yaml_modeldata.cpp +++ b/companion/src/firmwares/edgetx/yaml_modeldata.cpp @@ -546,6 +546,7 @@ struct convert { node["symetrical"] = (int)rhs.symetrical; node["name"] = rhs.name; node["curve"] = rhs.curve.value; + // rhs.curve.type is not encoded return node; } @@ -565,6 +566,7 @@ struct convert { node["symetrical"] >> rhs.symetrical; node["name"] >> rhs.name; node["curve"] >> rhs.curve.value; + rhs.curve.type = CurveReference::CURVE_REF_CUSTOM; // this is not encoded but needed internally so force type return true; } }; diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index f72e5f020..aa2a14edd 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -25,6 +25,8 @@ #include "opentxeeprom.h" #include "customdebug.h" #include "opentxinterface.h" +#include "sourcenumref.h" +#include "adjustmentreference.h" using namespace Board; @@ -805,6 +807,11 @@ class CurveReferenceField: public TransformedField { { curve.type = (CurveReference::CurveRefType)_curve_type; curve.value = smallGvarExport(_curve_value); + // 2,11 num or gvar changed to SourceNumRef + if ((curve.type == CurveReference::CURVE_REF_DIFF || curve.type == CurveReference::CURVE_REF_EXPO) && + AdjustmentReference(curve.value).type == AdjustmentReference::ADJUST_REF_GVAR) + curve.value = RawSource(SOURCE_TYPE_GVAR, AdjustmentReference(curve.value).value).toValue(); + qCDebug(eepromImport) << QString("imported CurveReference(%1)").arg(curve.toString()); } @@ -1114,8 +1121,20 @@ class MixField: public TransformedField { } } + // 2.11 + if ((mix.curve.type == CurveReference::CURVE_REF_DIFF || mix.curve.type == CurveReference::CURVE_REF_EXPO) && + AdjustmentReference(mix.curve.value).type == AdjustmentReference::ADJUST_REF_GVAR) + mix.curve.value = RawSource(SOURCE_TYPE_GVAR, AdjustmentReference(mix.curve.value).value).toValue(); + importGvarParam(mix.weight, _weight, version); + // 2.11 + if (AdjustmentReference(mix.weight).type == AdjustmentReference::ADJUST_REF_GVAR) + mix.weight = RawSource(SOURCE_TYPE_GVAR, AdjustmentReference(mix.weight).value).toValue(); + importGvarParam(mix.sOffset, _offset, version); + // 2.11 + if (AdjustmentReference(mix.sOffset).type == AdjustmentReference::ADJUST_REF_GVAR) + mix.sOffset = RawSource(SOURCE_TYPE_GVAR, AdjustmentReference(mix.sOffset).value).toValue(); qCDebug(eepromImport) << QString("imported %1: ch %2, name '%3'").arg(internalField.getName()).arg(mix.destCh).arg(mix.name); } @@ -1222,9 +1241,15 @@ class InputField: public TransformedField { } expo.weight = smallGvarExport(_weight); + // 2.11 + if (AdjustmentReference(expo.weight).type == AdjustmentReference::ADJUST_REF_GVAR) + expo.weight = RawSource(SOURCE_TYPE_GVAR, AdjustmentReference(expo.weight).value).toValue(); if (IS_STM32(board) || version >= 218) { expo.offset = smallGvarExport(_offset); + // 2.11 + if (AdjustmentReference(expo.offset).type == AdjustmentReference::ADJUST_REF_GVAR) + expo.offset = RawSource(SOURCE_TYPE_GVAR, AdjustmentReference(expo.offset).value).toValue(); } if (!IS_TARANIS(board) && version < 218) { @@ -1235,6 +1260,13 @@ class InputField: public TransformedField { else expo.curve = CurveReference(CurveReference::CURVE_REF_FUNC, _curveParam); } + + // 2.11 + if ((expo.curve.type == CurveReference::CURVE_REF_DIFF || expo.curve.type == CurveReference::CURVE_REF_EXPO) && + AdjustmentReference(expo.curve.value).type == AdjustmentReference::ADJUST_REF_GVAR) + expo.curve.value = RawSource(SOURCE_TYPE_GVAR, AdjustmentReference(expo.curve.value).value).toValue(); + + qCDebug(eepromImport) << QString("imported %1: ch %2 name '%3'").arg(internalField.getName()).arg(expo.chn).arg(expo.name); } diff --git a/companion/src/firmwares/rawsource.cpp b/companion/src/firmwares/rawsource.cpp index d43c6a063..eb42903a6 100644 --- a/companion/src/firmwares/rawsource.cpp +++ b/companion/src/firmwares/rawsource.cpp @@ -131,7 +131,7 @@ RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSetting QString RawSource::toString(const ModelData * model, const GeneralSettings * const generalSettings, Board::Type board, bool prefixCustomName) const { if (index < 0) - return CPN_STR_SRC_INDICATOR_INVERT % RawSource(type, -index).toString(model, generalSettings, board, prefixCustomName); + return CPN_STR_SRC_INDICATOR_NEG % RawSource(type, -index).toString(model, generalSettings, board, prefixCustomName); if (board == Board::BOARD_UNKNOWN) board = getCurrentBoard(); diff --git a/companion/src/firmwares/sourcenumref.cpp b/companion/src/firmwares/sourcenumref.cpp new file mode 100644 index 000000000..520e44ee1 --- /dev/null +++ b/companion/src/firmwares/sourcenumref.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "sourcenumref.h" +#include "filtereditemmodels.h" +#include "helpers.h" + +QString SourceNumRef::toString(const ModelData * model, const GeneralSettings * const generalSettings, + Board::Type board, bool prefixCustomName) const +{ + if (srcNum.type == SOURCE_TYPE_NONE) + return QString::number(srcNum.index); + else + return srcNum.toString(model, generalSettings, board, prefixCustomName); +} + +// static +int SourceNumRef::getDefault(int useSource, int dflt) +{ + if (useSource) + return 0; + else + return dflt; +} + + +/* + * SourceNumRefEditor +*/ + +SourceNumRefEditor::SourceNumRefEditor(int & srcNumValue, QCheckBox * chkUseSource, QSpinBox * sbxValue, QComboBox * cboValue, + int defValue, int minValue, int maxValue, int step, + ModelData & model, FilteredItemModel * sourceItemModel, QObject * parent) : + QObject(parent), + srcNumValue(srcNumValue), + chkUseSource(chkUseSource), + sbxValue(sbxValue), + cboValue(cboValue), + defValue(defValue), + model(model), + lock(false) +{ + if (chkUseSource) { + connect(chkUseSource, &QCheckBox::stateChanged, this, &SourceNumRefEditor::chkUseSourceChanged); + } + + if (sbxValue) { + sbxValue->setMinimum(minValue); + sbxValue->setMaximum(maxValue); + sbxValue->setSingleStep(step); + sbxValue->setValue(defValue); + connect(sbxValue, &QSpinBox::editingFinished, this, &SourceNumRefEditor::sbxValueChanged); + } + + if (cboValue) { + cboValue->setModel(sourceItemModel); + cboValue->setSizeAdjustPolicy(QComboBox::AdjustToContents); + cboValue->setMaxVisibleItems(10); + cboValue->setCurrentIndex(Helpers::getFirstPosValueIndex(cboValue)); + connect(cboValue, QOverload::of(&QComboBox::currentIndexChanged), this, &SourceNumRefEditor::cboValueChanged); + } + + update(); +} + +void SourceNumRefEditor::chkUseSourceChanged(int state) +{ + if (!lock) { + srcNumValue = SourceNumRef::getDefault(state, defValue); + + if (state == Qt::Checked) { + cboValue->setCurrentIndex(cboValue->findData(srcNumValue)); + if (cboValue->currentIndex() < 0) + cboValue->setCurrentIndex(Helpers::getFirstPosValueIndex(cboValue)); + } + else + sbxValue->setValue(srcNumValue); + + update(); + } +} + +void SourceNumRefEditor::sbxValueChanged() +{ + if (!lock) { + srcNumValue = sbxValue->value(); + update(); + } +} + +void SourceNumRefEditor::cboValueChanged(int index) +{ + if (!lock) { + srcNumValue = cboValue->itemData(index).toInt(); + update(); + } +} + +void SourceNumRefEditor::setVisible(bool state) +{ + chkUseSource->setVisible(state); + cboValue->setVisible(state); + sbxValue->setVisible(state); +} + +void SourceNumRefEditor::update() +{ + lock = true; + + if (SourceNumRef(srcNumValue).isNumber()) { + if (chkUseSource) + chkUseSource->setChecked(false); + + if (sbxValue) { + sbxValue->setValue(srcNumValue); + sbxValue->setVisible(true); + } + + if (cboValue) + cboValue->setVisible(false); + } + else { + if (chkUseSource) + chkUseSource->setChecked(true); + + if (sbxValue) + sbxValue->setVisible(false); + + if (cboValue) { + cboValue->setCurrentIndex(cboValue->findData(srcNumValue)); + cboValue->setVisible(true); + } + } + + emit resized(); + + lock = false; +} diff --git a/companion/src/firmwares/sourcenumref.h b/companion/src/firmwares/sourcenumref.h new file mode 100644 index 000000000..a5e9c1bc8 --- /dev/null +++ b/companion/src/firmwares/sourcenumref.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#include "rawsource.h" + +#include +#include +#include +#include + +class FilteredItemModel; + +/* + This class takes advantage of RawSource's assumption that small values must be SOURCE_TYPE_NONE ie zero + albeit anything other than value zero is unexpected. However there is no setter validation to stop unknown values. + + Also SOURCE_TYPE_NONE must be excluded from selection lists. + It would not make sense anyway as it equates to value 0 and thus ambiguous. +*/ + +class SourceNumRef { + + Q_DECLARE_TR_FUNCTIONS(SourceNumRef) + + public: + SourceNumRef() : srcNum(RawSource()) {} + explicit SourceNumRef(int value) : srcNum(RawSource(value)) {} + SourceNumRef(RawSourceType type, int index = 0) : srcNum(RawSource(type, index)) {} + + virtual ~SourceNumRef() {} + + int toValue() { return srcNum.toValue(); } + + QString toString(const ModelData * model = nullptr, const GeneralSettings * const generalSettings = nullptr, + Board::Type board = Board::BOARD_UNKNOWN, bool prefixCustomName = true) const; + + const bool isNumber() const { return srcNum.type == SOURCE_TYPE_NONE; } + const bool isSource() const { return srcNum.type != SOURCE_TYPE_NONE; } + static int getDefault(int useSource, int dflt); + + private: + RawSource srcNum; +}; + +class SourceNumRefEditor : public QObject { + + Q_OBJECT + + public: + explicit SourceNumRefEditor(int & srcNumValue, QCheckBox * chkUseSource, QSpinBox * sbxValue, QComboBox * cboValue, + int defValue, int minValue, int maxValue, int step, + ModelData & model, FilteredItemModel * sourceItemModel, QObject * parent = nullptr); + + virtual ~SourceNumRefEditor() {} + + void setLock(bool state) { lock = state; } + void setVisible(bool state); + void update(); + + signals: + void resized(); + + protected slots: + void chkUseSourceChanged(int state); + void sbxValueChanged(); + void cboValueChanged(int index); + + protected: + int &srcNumValue; + QCheckBox *chkUseSource; + QSpinBox *sbxValue; + QComboBox *cboValue; + int defValue; + ModelData &model; + bool lock; +}; diff --git a/companion/src/helpers.cpp b/companion/src/helpers.cpp index 2b8fa1d9a..e034cd0bb 100644 --- a/companion/src/helpers.cpp +++ b/companion/src/helpers.cpp @@ -324,6 +324,37 @@ void Helpers::setBitmappedValue(unsigned int & field, unsigned int value, unsign field = (field & ~fieldmask) | (value << (numbits * index + offset)); } +// return index of 'none' ie zero or first positive data entry in potentially an asymetrical list +int Helpers::getFirstPosValueIndex(QComboBox * cbo) +{ + const int cnt = cbo->count(); + if (cnt == 0) + return -1; + + const int idx = cnt / 2; + const int val = cbo->itemData(idx).toInt(); + + if (val == 0) + return idx; + + const int step = val > 0 ? -1 : 1; + + for (int i = idx + step; i >= 0 && i < cbo->count(); i += step) { + if (cbo->findData(i) == 0) + return i; + else if (step < 0 && cbo->itemData(i).toInt() < 0) { + if (i++ < cbo->count()) + return i++; + else + return -1; + } + else if (step > 0 && cbo->itemData(i).toInt() > 0) + return i; + } + + return -1; +} + #ifdef __APPLE__ // Flag when simulator is running static bool simulatorRunning = false; diff --git a/companion/src/helpers.h b/companion/src/helpers.h index 89633a7d9..d535af0ba 100644 --- a/companion/src/helpers.h +++ b/companion/src/helpers.h @@ -30,6 +30,7 @@ #include #include #include +#include extern const QColor colors[CPN_MAX_CURVES]; @@ -117,6 +118,7 @@ namespace Helpers QString removeAccents(const QString & str); unsigned int getBitmappedValue(const unsigned int & field, const unsigned int index = 0, const unsigned int numbits = 1, const unsigned int offset = 0); void setBitmappedValue(unsigned int & field, unsigned int value, unsigned int index = 0, unsigned int numbits = 1, unsigned int offset = 0); + int getFirstPosValueIndex(QComboBox * cbo); } // namespace Helpers diff --git a/companion/src/modeledit/channels.cpp b/companion/src/modeledit/channels.cpp index 2e1ffb6f4..41e991342 100644 --- a/companion/src/modeledit/channels.cpp +++ b/companion/src/modeledit/channels.cpp @@ -104,6 +104,9 @@ ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSetting int gvid = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef)), "GVarRef"); + curveRefFilteredItemModels = new CurveRefFilteredFactory(sharedItemModels, + firmware->getCapability(HasMixerExpo) ? 0 : FilteredItemModel::PositiveFilter); + QStringList headerLabels; headerLabels << "#"; if (channelNameMaxLen > 0) { @@ -162,20 +165,15 @@ ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSetting if (IS_HORUS_OR_TARANIS(firmware->getBoard())) { curveCB[i] = new QComboBox(this); curveCB[i]->setProperty("index", i); - curveCB[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents); - curveCB[i]->setModel(dialogFilteredItemModels->getItemModel(crvid)); - connect(curveCB[i], SIGNAL(currentIndexChanged(int)), this, SLOT(curveEdited())); tableLayout->addWidget(i, col++, curveCB[i]); curveImage[i] = new CurveImageWidget(this); - int crvidx = model.limitData[i].curve.value - 1; - QColor pencolor = colors[crvidx >= 0 ? crvidx : Qt::black]; - curveImage[i]->set(&model, firmware, sharedItemModels, crvidx, pencolor, 3); - curveImage[i]->setGrid(Qt::gray, 2); curveImage[i]->setProperty("index", i); curveImage[i]->setFixedSize(QSize(100, 100)); - connect(curveImage[i], &CurveImageWidget::doubleClicked, this, &ChannelsPanel::on_curveImageDoubleClicked); tableLayout->addWidget(i, col++, curveImage[i]); + + curveGroup[i] = new CurveReferenceUIManager(curveCB[i], curveImage[i], model.limitData[i].curve, model, sharedItemModels, + curveRefFilteredItemModels, this); } // PPM center @@ -201,6 +199,7 @@ ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSetting tableLayout->addWidget(i, col++, symlimitsChk[i]); } } + update(); disableMouseScrolling(); @@ -222,8 +221,10 @@ ChannelsPanel::~ChannelsPanel() delete curveCB[i]; delete centerSB[i]; delete symlimitsChk[i]; + delete curveGroup[i]; } delete dialogFilteredItemModels; + delete curveRefFilteredItemModels; } void ChannelsPanel::symlimitsEdited() @@ -270,24 +271,6 @@ void ChannelsPanel::invEdited() } } -void ChannelsPanel::curveEdited() -{ - if (!lock) { - QComboBox *cb = qobject_cast(sender()); - int index = cb->property("index").toInt(); - // ignore unnecessary updates that could be triggered by updates to the data model - LimitData &ld = model->limitData[index]; - if (ld.curve != CurveReference(CurveReference::CURVE_REF_CUSTOM, cb->itemData(cb->currentIndex()).toInt())) { - ld.curve = CurveReference(CurveReference::CURVE_REF_CUSTOM, cb->itemData(cb->currentIndex()).toInt()); - curveImage[index]->setIndex(abs(ld.curve.value) - 1); - if (abs(ld.curve.value) > 0) - curveImage[index]->setPen(colors[abs(ld.curve.value) - 1], 3); - updateLine(index); - emit modified(); - } - } -} - void ChannelsPanel::ppmcenterEdited() { if (!lock) { @@ -317,16 +300,6 @@ void ChannelsPanel::updateLine(int i) chnMin[i]->setValue(chn.min); chnMax[i]->setValue(chn.max); invCB[i]->setCurrentIndex((chn.revert) ? 1 : 0); - if (IS_HORUS_OR_TARANIS(firmware->getBoard())) { - curveCB[i]->setCurrentIndex(curveCB[i]->findData(chn.curve.value)); - if (chn.curve.value == 0) { - curveImage[i]->setVisible(false); - } - else { - curveImage[i]->setVisible(true); - curveImage[i]->draw(); - } - } if (firmware->getCapability(PPMCenter)) { centerSB[i]->setValue(chn.ppmCenter + 1500); } @@ -496,14 +469,3 @@ void ChannelsPanel::updateItemModels() sharedItemModels->update(AbstractItemModel::IMUE_Channels); emit modified(); } - -void ChannelsPanel::on_curveImageDoubleClicked() -{ - bool ok = false; - int index = sender()->property("index").toInt(&ok); - - if (ok && curveImage[abs(index)]->edit()) { - updateLine(index); - emit modified(); - } -} diff --git a/companion/src/modeledit/channels.h b/companion/src/modeledit/channels.h index a3db0e73a..885bbf14f 100644 --- a/companion/src/modeledit/channels.h +++ b/companion/src/modeledit/channels.h @@ -70,7 +70,6 @@ class ChannelsPanel : public ModelPanel void symlimitsEdited(); void nameEdited(); void invEdited(); - void curveEdited(); void ppmcenterEdited(); void update(); void updateLine(int index); @@ -86,7 +85,6 @@ class ChannelsPanel : public ModelPanel void onCustomContextMenuRequested(QPoint pos); void onItemModelAboutToBeUpdated(); void onItemModelUpdateComplete(); - void on_curveImageDoubleClicked(); private: QLineEdit *name[CPN_MAX_CHNOUT]; @@ -102,6 +100,8 @@ class ChannelsPanel : public ModelPanel int chnCapability; CompoundItemModelFactory *sharedItemModels; FilteredItemModelFactory *dialogFilteredItemModels; + CurveRefFilteredFactory *curveRefFilteredItemModels; + CurveReferenceUIManager *curveGroup[CPN_MAX_CHNOUT]; bool hasClipboardData(QByteArray * data = nullptr) const; bool insertAllowed() const; diff --git a/companion/src/modeledit/curves.cpp b/companion/src/modeledit/curves.cpp index b47d6759d..d1d100729 100644 --- a/companion/src/modeledit/curves.cpp +++ b/companion/src/modeledit/curves.cpp @@ -55,7 +55,7 @@ CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & tableLayout->addWidget(i, col++, label); image[i] = new CurveImageWidget(this); - image[i]->set(&model, firmware, sharedItemModels, i, colors[i], 3); + image[i]->set(&model, firmware, sharedItemModels, i + 1, colors[i], 3); image[i]->setGrid(Qt::gray, 2); image[i]->setProperty("index", i); image[i]->setFixedSize(QSize(100, 100)); diff --git a/companion/src/modeledit/expodialog.cpp b/companion/src/modeledit/expodialog.cpp index eeef6866a..2929fc388 100644 --- a/companion/src/modeledit/expodialog.cpp +++ b/companion/src/modeledit/expodialog.cpp @@ -1,7 +1,8 @@ /* - * Copyright (C) OpenTX + * Copyright (C) EdgeTX * * Based on code named + * opentx - https://github.com/opentx/opentx * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x @@ -23,6 +24,7 @@ #include "filtereditemmodels.h" #include "helpers.h" #include "namevalidator.h" +#include "sourcenumref.h" ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, GeneralSettings & generalSettings, Firmware * firmware, QString & inputName, CompoundItemModelFactory * sharedItemModels) : @@ -33,14 +35,12 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G firmware(firmware), ed(expoData), inputName(inputName), - modelPrinter(firmware, generalSettings, model), lock(false) { ui->setupUi(this); Board::Type board = firmware->getBoard(); dialogFilteredItemModels = new FilteredItemModelFactory(); - int id; QLabel * lb_fp[CPN_MAX_FLIGHT_MODES] = {ui->lb_FP0, ui->lb_FP1, ui->lb_FP2, ui->lb_FP3, ui->lb_FP4, ui->lb_FP5, ui->lb_FP6, ui->lb_FP7, ui->lb_FP8 }; QCheckBox * tmp[CPN_MAX_FLIGHT_MODES] = {ui->cb_FP0, ui->cb_FP1, ui->cb_FP2, ui->cb_FP3, ui->cb_FP4, ui->cb_FP5, ui->cb_FP6, ui->cb_FP7, ui->cb_FP8 }; @@ -51,28 +51,35 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G 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"); - gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, -100, 100, 1.0, - dialogFilteredItemModels->getItemModel(id)); + int imId = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), + (RawSource::AllSourceGroups & ~RawSource::NoneGroup & ~RawSource::ScriptsGroup & ~RawSource::InputsGroup)), + "EditorSource"); - gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, ed->offset, model, 0, -100, 100, 1.0, - dialogFilteredItemModels->getItemModel(id)); + FilteredItemModel *esMdl = dialogFilteredItemModels->getItemModel(imId); + + weightEditor = new SourceNumRefEditor(ed->weight, ui->chkWeightUseSource, ui->sbWeightValue, ui->cboWeightSource, 100, -100, 100, 1.0, + model, esMdl); + + connect(weightEditor, &SourceNumRefEditor::resized, this, [=] () { shrink(); }); + + offsetEditor = new SourceNumRefEditor(ed->offset, ui->chkOffsetUseSource, ui->sbOffsetValue, ui->cboOffsetSource, 0, -100, 100, 1.0, + model, esMdl); + + connect(offsetEditor, &SourceNumRefEditor::resized, this, [=] () { shrink(); }); curveRefFilteredItemModels = new CurveRefFilteredFactory(sharedItemModels, firmware->getCapability(HasInputDiff) ? 0 : FilteredItemModel::PositiveFilter); - curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, ui->curveImage, ed->curve, model, - sharedItemModels, curveRefFilteredItemModels, this); + curveGroup = new CurveReferenceUIManager(ui->cboCurveType, ui->chkCurveUseSource, ui->sbCurveValue, ui->cboCurveSource, ui->cboCurveFunc, + ui->imgCurve, ed->curve, model, sharedItemModels, curveRefFilteredItemModels, esMdl, this); - connect(curveGroup, &CurveReferenceUIManager::resized, this, [=] () { - this->adjustSize(); - this->adjustSize(); // second call seems to be required when hidden fields otherwise not all padding removed - }); + connect(curveGroup, &CurveReferenceUIManager::resized, this, [=] () { shrink(); }); - id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), + imId = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), RawSwitch::MixesContext), "RawSwitch"); - ui->switchesCB->setModel(dialogFilteredItemModels->getItemModel(id)); + ui->switchesCB->setSizeAdjustPolicy(QComboBox::AdjustToContents); + ui->switchesCB->setModel(dialogFilteredItemModels->getItemModel(imId)); ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(ed->swtch.toValue())); ui->sideCB->setCurrentIndex(ed->mode - 1); @@ -105,12 +112,13 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G ui->inputName->setMaxLength(firmware->getCapability(InputsLength)); int flags = RawSource::InputSourceGroups & ~RawSource::NoneGroup & ~RawSource::InputsGroup; flags |= RawSource::GVarsGroup | RawSource::TelemGroup; - id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), + imId = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), flags), "RawSource"); - ui->sourceCB->setModel(dialogFilteredItemModels->getItemModel(id)); + ui->sourceCB->setSizeAdjustPolicy(QComboBox::AdjustToContents); + ui->sourceCB->setModel(dialogFilteredItemModels->getItemModel(imId)); 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->sourceCB->setCurrentIndex(Helpers::getFirstPosValueIndex(ui->sourceCB)); ui->inputName->setValidator(new NameValidator(board, this)); ui->inputName->setText(inputName); } @@ -164,15 +172,16 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G connect(ui->inputName, SIGNAL(editingFinished()), this, SLOT(valuesChanged())); } - adjustSize(); + shrink(); } ExpoDialog::~ExpoDialog() { delete ui; - delete gvWeightGroup; - delete gvOffsetGroup; + delete weightEditor; + delete offsetEditor; delete dialogFilteredItemModels; + delete curveRefFilteredItemModels; } void ExpoDialog::updateScale() @@ -278,3 +287,9 @@ void ExpoDialog::fmInvertAll() lock = false; valuesChanged(); } + +void ExpoDialog::shrink() +{ + this->adjustSize(); + this->resize(0, 0); +} diff --git a/companion/src/modeledit/expodialog.h b/companion/src/modeledit/expodialog.h index fcc17cbda..9dff13a71 100644 --- a/companion/src/modeledit/expodialog.h +++ b/companion/src/modeledit/expodialog.h @@ -1,7 +1,8 @@ /* - * Copyright (C) OpenTX + * Copyright (C) EdgeTX * * Based on code named + * opentx - https://github.com/opentx/opentx * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x @@ -20,15 +21,15 @@ #pragma once -#include #include "eeprominterface.h" -#include "modelprinter.h" -class GVarGroup; +#include + class CompoundItemModelFactory; class FilteredItemModelFactory; class CurveRefFilteredFactory; class CurveReferenceUIManager; +class SourceNumRefEditor; namespace Ui { class ExpoDialog; @@ -58,13 +59,14 @@ class ExpoDialog : public QDialog { Firmware * firmware; ExpoData * ed; QString & inputName; - GVarGroup * gvWeightGroup; - GVarGroup * gvOffsetGroup; + SourceNumRefEditor * weightEditor; + SourceNumRefEditor * offsetEditor; CurveReferenceUIManager * curveGroup; - ModelPrinter modelPrinter; bool lock; QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES]; FilteredItemModelFactory *dialogFilteredItemModels; CurveRefFilteredFactory *curveRefFilteredItemModels; int carryTrimFilterFlags = 0; + + void shrink(); }; diff --git a/companion/src/modeledit/expodialog.ui b/companion/src/modeledit/expodialog.ui index 04237a9d9..1b2be11c7 100644 --- a/companion/src/modeledit/expodialog.ui +++ b/companion/src/modeledit/expodialog.ui @@ -6,8 +6,8 @@ 0 0 - 442 - 411 + 671 + 490 @@ -29,61 +29,502 @@ :/icon.png:/icon.png - - - - - - NEG - - - - - POS - - - - - ALL - - - - - - - - + + + + + - GV + Source - - - - - - - The source for the mixer + + + + Weight - - - - Qt::Horizontal + + + + + 0 + 0 + - - - 40 - 0 - + + Include Trim - + + + + + + Scale + + + + + + + Line name + + + + + + + Input name + + + + + + + Flight modes + + + + + + + Stick Side + + + + + + + Curve + + + + + + + Offset + + + + + + + Switch + + + + + + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 1 + + + + + + + unit + + + + + + + + + + + Source + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 1 + + + Qt::AlignCenter + + + + + + + 6 + + + Qt::AlignCenter + + + + + + + + + + + + + + 7 + + + Qt::AlignCenter + + + + + + + 0 + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 + + + Qt::AlignCenter + + + + + + + + + + + + + + 2 + + + Qt::AlignCenter + + + + + + + 4 + + + Qt::AlignCenter + + + + + + + 5 + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + + + + + 3 + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + Curve applied to the source. + + + + + + + Source + + + + + + + + + + + + + + + + + + + + + 100 + 100 + + + + + 100 + 100 + + + + image + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Source + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + The source for the mixer + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + + + + NEG + + + + + POS + + + + + ALL + + + + + + - + @@ -98,394 +539,7 @@ QDialogButtonBox::Cancel|QDialogButtonBox::Ok - true - - - - - - - - - - 6 - - - - - - - Curve - - - - - - - Switch - - - - - - - Flight modes - - - - - - - Stick Side - - - - - - - Weight - - - - - - - - - GV - - - - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Switch used to enable the line. -If blank then the input is considered to be "ON" all the time. - - - - - - - Offset - - - - - - - Source - - - - - - - Input name - - - - - - - Source for the mixer. - - - - - - - 6 - - - - - - - - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 1 - - - - - - - unit - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - 0 - - - Qt::AlignCenter - - - - - - - 1 - - - Qt::AlignCenter - - - - - - - 2 - - - Qt::AlignCenter - - - - - - - 3 - - - Qt::AlignCenter - - - - - - - 4 - - - Qt::AlignCenter - - - - - - - 5 - - - Qt::AlignCenter - - - - - - - 6 - - - Qt::AlignCenter - - - - - - - 7 - - - Qt::AlignCenter - - - - - - - 8 - - - Qt::AlignCenter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Scale - - - - - - - - - - - - Curve applied to the source. - - - - - - - GV - - - - - - - - - - - - - - - - - - 100 - 100 - - - - - 100 - 100 - - - - image - - - - - - - - - Include Trim - - - - - - - Line name + false @@ -499,21 +553,6 @@ If blank then the input is considered to be "ON" all the time. - inputName - lineName - sourceCB - dsbScale - trimCB - weightGV - weightSB - weightCB - offsetGV - offsetSB - offsetCB - curveTypeCB - curveGVarCB - curveValueCB - curveValueSB cb_FP0 cb_FP1 cb_FP2 @@ -522,9 +561,6 @@ If blank then the input is considered to be "ON" all the time.cb_FP5 cb_FP6 cb_FP7 - cb_FP8 - switchesCB - sideCB buttonBox diff --git a/companion/src/modeledit/mixerdialog.cpp b/companion/src/modeledit/mixerdialog.cpp index f7d4f4520..ae156619b 100644 --- a/companion/src/modeledit/mixerdialog.cpp +++ b/companion/src/modeledit/mixerdialog.cpp @@ -1,7 +1,8 @@ /* - * Copyright (C) OpenTX + * Copyright (C) EdgeTX * * Based on code named + * opentx - https://github.com/opentx/opentx * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x @@ -24,6 +25,7 @@ #include "filtereditemmodels.h" #include "helpers.h" #include "namevalidator.h" +#include "sourcenumref.h" MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels) : @@ -40,7 +42,6 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, Board::Type board = firmware->getBoard(); dialogFilteredItemModels = new FilteredItemModelFactory(); - int id; QLabel * lb_fp[CPN_MAX_FLIGHT_MODES] = {ui->lb_FP0, ui->lb_FP1, ui->lb_FP2, ui->lb_FP3, ui->lb_FP4, ui->lb_FP5, ui->lb_FP6, ui->lb_FP7, ui->lb_FP8 }; QCheckBox * tmp[CPN_MAX_FLIGHT_MODES] = {ui->cb_FP0, ui->cb_FP1, ui->cb_FP2, ui->cb_FP3, ui->cb_FP4, ui->cb_FP5, ui->cb_FP6, ui->cb_FP7, ui->cb_FP8 }; @@ -50,34 +51,41 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, this->setWindowTitle(tr("DEST -> %1").arg(RawSource(SOURCE_TYPE_CH, md->destCh - 1).toString(&model, &generalSettings))); - id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), - (RawSource::InputSourceGroups & ~RawSource::NoneGroup) | RawSource::ScriptsGroup), - "RawSource"); - ui->sourceCB->setModel(dialogFilteredItemModels->getItemModel(id)); + int imId = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), + (RawSource::InputSourceGroups & ~RawSource::NoneGroup) | RawSource::ScriptsGroup), + "RawSource"); + + ui->sourceCB->setSizeAdjustPolicy(QComboBox::AdjustToContents); + ui->sourceCB->setModel(dialogFilteredItemModels->getItemModel(imId)); 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 + ui->sourceCB->setCurrentIndex(Helpers::getFirstPosValueIndex(ui->sourceCB)); int limit = firmware->getCapability(OffsetWeight); - id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef)), "GVarRef"); + imId = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), + (RawSource::AllSourceGroups & ~RawSource::NoneGroup & ~RawSource::ScriptsGroup)), + "EditorSource"); - gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, md->weight, model, 100, -limit, limit, 1.0, - dialogFilteredItemModels->getItemModel(id)); + FilteredItemModel *esMdl = dialogFilteredItemModels->getItemModel(imId); - gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, md->sOffset, model, 0, -limit, limit, 1.0, - dialogFilteredItemModels->getItemModel(id)); + weightEditor = new SourceNumRefEditor(md->weight, ui->chkWeightUseSource, ui->sbWeightValue, ui->cboWeightSource, 100, -limit, limit, 1, + model, esMdl, this); + + connect(weightEditor, &SourceNumRefEditor::resized, this, [=] () { shrink(); }); + + offsetEditor = new SourceNumRefEditor(md->sOffset, ui->chkOffsetUseSource, ui->sbOffsetValue, ui->cboOffsetSource, 0, -limit, limit, 1, + model, esMdl, this); + + connect(offsetEditor, &SourceNumRefEditor::resized, this, [=] () { shrink(); }); curveRefFilteredItemModels = new CurveRefFilteredFactory(sharedItemModels, firmware->getCapability(HasMixerExpo) ? 0 : FilteredItemModel::PositiveFilter); - curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, ui->curveImage, md->curve, - model, sharedItemModels, curveRefFilteredItemModels, this); + curveGroup = new CurveReferenceUIManager(ui->cboCurveType, ui->chkCurveUseSource, ui->sbCurveValue, ui->cboCurveSource, ui->cboCurveFunc, + ui->imgCurve, md->curve, model, sharedItemModels, curveRefFilteredItemModels, esMdl, this); - connect(curveGroup, &CurveReferenceUIManager::resized, this, [=] () { - this->adjustSize(); - this->adjustSize(); // second call seems to be required when hidden fields otherwise not all padding removed - }); + connect(curveGroup, &CurveReferenceUIManager::resized, this, [=] () { shrink(); }); ui->MixDR_CB->setChecked(md->noExpo == 0); @@ -129,9 +137,11 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, } } - id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), - RawSwitch::MixesContext), "RawSwitch"); - ui->switchesCB->setModel(dialogFilteredItemModels->getItemModel(id)); + imId = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), + RawSwitch::MixesContext), + "RawSwitch"); + ui->switchesCB->setSizeAdjustPolicy(QComboBox::AdjustToContents); + ui->switchesCB->setModel(dialogFilteredItemModels->getItemModel(imId)); ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(md->swtch.toValue())); ui->warningCB->setCurrentIndex(md->mixWarn); ui->mltpxCB->setCurrentIndex(md->mltpx); @@ -161,32 +171,33 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, valuesChanged(); - connect(ui->mixerName,SIGNAL(editingFinished()),this,SLOT(valuesChanged())); - connect(ui->sourceCB,SIGNAL(currentIndexChanged(int)),this,SLOT(valuesChanged())); - connect(ui->trimCB,SIGNAL(currentIndexChanged(int)),this,SLOT(valuesChanged())); - connect(ui->MixDR_CB,SIGNAL(toggled(bool)),this,SLOT(valuesChanged())); - connect(ui->switchesCB,SIGNAL(currentIndexChanged(int)),this,SLOT(valuesChanged())); - connect(ui->warningCB,SIGNAL(currentIndexChanged(int)),this,SLOT(valuesChanged())); - connect(ui->mltpxCB,SIGNAL(currentIndexChanged(int)),this,SLOT(valuesChanged())); - connect(ui->delayDownSB,SIGNAL(editingFinished()),this,SLOT(valuesChanged())); - connect(ui->delayUpSB,SIGNAL(editingFinished()),this,SLOT(valuesChanged())); - connect(ui->speedPrecCB,SIGNAL(currentIndexChanged(int)),this,SLOT(valuesChanged())); - connect(ui->slowDownSB,SIGNAL(editingFinished()),this,SLOT(valuesChanged())); - connect(ui->slowUpSB,SIGNAL(editingFinished()),this,SLOT(valuesChanged())); + connect(ui->mixerName, SIGNAL(editingFinished()), this, SLOT(valuesChanged())); + connect(ui->sourceCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged())); + connect(ui->trimCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged())); + connect(ui->MixDR_CB, SIGNAL(toggled(bool)), this, SLOT(valuesChanged())); + connect(ui->switchesCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged())); + connect(ui->warningCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged())); + connect(ui->mltpxCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged())); + connect(ui->delayDownSB, SIGNAL(editingFinished()), this, SLOT(valuesChanged())); + connect(ui->delayUpSB, SIGNAL(editingFinished()), this, SLOT(valuesChanged())); + connect(ui->speedPrecCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesChanged())); + connect(ui->slowDownSB, SIGNAL(editingFinished()), this, SLOT(valuesChanged())); + connect(ui->slowUpSB, SIGNAL(editingFinished()), this, SLOT(valuesChanged())); - for (int i=0; iadjustSize(); + this->resize(0, 0); +} diff --git a/companion/src/modeledit/mixerdialog.h b/companion/src/modeledit/mixerdialog.h index bf201a8ff..7581454aa 100644 --- a/companion/src/modeledit/mixerdialog.h +++ b/companion/src/modeledit/mixerdialog.h @@ -1,7 +1,8 @@ /* - * Copyright (C) OpenTX + * Copyright (C) EdgeTX * * Based on code named + * opentx - https://github.com/opentx/opentx * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x @@ -23,11 +24,11 @@ #include #include "eeprominterface.h" -class GVarGroup; class CompoundItemModelFactory; class FilteredItemModelFactory; class CurveRefFilteredFactory; class CurveReferenceUIManager; +class SourceNumRefEditor; namespace Ui { class MixerDialog; @@ -57,10 +58,12 @@ class MixerDialog : public QDialog { Firmware * firmware; MixData *md; bool lock; - GVarGroup * gvWeightGroup; - GVarGroup * gvOffsetGroup; + SourceNumRefEditor * weightEditor; + SourceNumRefEditor * offsetEditor; CurveReferenceUIManager * curveGroup; QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES]; FilteredItemModelFactory *dialogFilteredItemModels; CurveRefFilteredFactory *curveRefFilteredItemModels; + + void shrink(); }; diff --git a/companion/src/modeledit/mixerdialog.ui b/companion/src/modeledit/mixerdialog.ui index 92f62e3c1..1e6620e6c 100644 --- a/companion/src/modeledit/mixerdialog.ui +++ b/companion/src/modeledit/mixerdialog.ui @@ -6,7 +6,7 @@ 0 0 - 556 + 752 623 @@ -29,46 +29,24 @@ - - - - Switch used by the mix. -If blank then the mix is considered to be "ON" all the time. - - - - - - - The source for the mixer - - - - - - - Curve - - - - + - GV + Source - + The source for the mixer - + @@ -85,17 +63,97 @@ If blank then the mix is considered to be "ON" all the time. - - - - Multiplexer - -This determines how mixer values are added. - -"+" means the value of the current mix is added to the previous mixes in the same channel. -"*" means the value of the current mix is amultiplied with the previous mixes in the same channel. -"R" means the value replaces the previous values. If the switch is off the value will be ignored. + + + + Slow up/dn prec + + + + + + + + + Include Trim + + + + + + + + 0.0 + + + + + 0.00 + + + + + + + + + + + + + Source + + + + + + + The source for the mixer + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Warning + + + + + + + Weight + + + + + + + Switch + + + + + ADD @@ -113,39 +171,36 @@ This determines how mixer values are added. - - - - - - GV - - - - - - - The source for the mixer - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + + Include DR/Expo + + + + + + + Source + + + + + + + Multiplex + + + + + + + Curve + + + + + @@ -161,32 +216,11 @@ This determines how mixer values are added. - - + + - Mixer warning. -Setting this value will cause a beep to be emmitted when this value is active. + The curve used by the mix - - - OFF - - - - - 1 Beep - - - - - 2 Beep - - - - - 3 Beep - - @@ -196,55 +230,6 @@ Setting this value will cause a beep to be emmitted when this value is active. - - - - Switch - - - - - - - Flight modes - - - - - - - Include DR/Expo - - - - - - - Warning - - - - - - - The curve used by the mix - - - - - - - Multiplex - - - - - - - Source - - - @@ -252,212 +237,30 @@ Setting this value will cause a beep to be emmitted when this value is active. - - - - - - 0 - - - Qt::AlignCenter - - - - - - - 1 - - - Qt::AlignCenter - - - - - - - 2 - - - Qt::AlignCenter - - - - - - - 3 - - - Qt::AlignCenter - - - - - - - 4 - - - Qt::AlignCenter - - - - - - - 5 - - - Qt::AlignCenter - - - - - - - 6 - - - Qt::AlignCenter - - - - - - - 7 - - - Qt::AlignCenter - - - - - - - 8 - - - Qt::AlignCenter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - - - - - - Offset - - - - - - - Include Trim - - - - - - - 6 - - - - + - + - GV + Source - + The source for the mixer - + - + + + + 100 @@ -475,27 +278,227 @@ Setting this value will cause a beep to be emmitted when this value is active. + + + + Qt::Horizontal + + + + 40 + 20 + + + + - - + + - Slow up/dn prec + Flight modes - - + + - 0.0 + OFF - 0.00 + 1 Beep + + + 2 Beeps + + + + + 3 Beeps + + + + + + + + + + 4 + + + Qt::AlignCenter + + + + + + + 3 + + + Qt::AlignCenter + + + + + + + 7 + + + Qt::AlignCenter + + + + + + + + + + + + + + 2 + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + + + + + 8 + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + Qt::AlignCenter + + + + + + + 0 + + + Qt::AlignCenter + + + + + + + 6 + + + Qt::AlignCenter + + + + + + + + + + + + + + 5 + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Offset + @@ -517,41 +520,7 @@ Setting this value will cause a beep to be emmitted when this value is active. - - - - - Delay - - - - - - - Slow - - - - - - - Up - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Down - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - + @@ -565,35 +534,6 @@ p, li { white-space: pre-wrap; } <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Delay is not zero the actuation of the mix will be delayed by the specified amount of seconds.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Slow is not zero then the speed of the mix will be set by the value specified -&gt; the value states the number of seconds it takes to transit from -100 to 100.</p></body></html> - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 1 - - - 7.500000000000000 - - - 0.500000000000000 - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Delay ans Slow</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600; text-decoration: underline;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These values control the speed and delay of the output of the mix. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Delay is not zero the actuation of the mix will be delayed by the specified amount of seconds.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Slow is not zero then the speed of the mix will be set by the value specified -&gt; the value states the number of seconds it takes to transit from -100 to 100.</p></body></html> @@ -633,6 +573,76 @@ p, li { white-space: pre-wrap; } + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Delay ans Slow</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600; text-decoration: underline;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These values control the speed and delay of the output of the mix. </p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Delay is not zero the actuation of the mix will be delayed by the specified amount of seconds.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Slow is not zero then the speed of the mix will be set by the value specified -&gt; the value states the number of seconds it takes to transit from -100 to 100.</p></body></html> + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 1 + + + 7.500000000000000 + + + 0.500000000000000 + + + + + + + + + + + + + + Down + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Up + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Delay + + + + + + + Slow + + + @@ -668,18 +678,16 @@ p, li { white-space: pre-wrap; } - mixerName - sourceCB - weightGV - weightCB - weightSB - offsetGV - offsetCB - offsetSB - curveTypeCB - curveGVarCB - curveValueCB - curveValueSB + chkWeightUseSource + cboWeightSource + sbWeightValue + chkOffsetUseSource + cboOffsetSource + sbOffsetValue + cboCurveType + chkCurveUseSource + cboCurveSource + sbCurveValue trimCB MixDR_CB cb_FP0 @@ -691,9 +699,6 @@ p, li { white-space: pre-wrap; } cb_FP6 cb_FP7 cb_FP8 - switchesCB - warningCB - mltpxCB delayUpSB delayDownSB slowUpSB diff --git a/companion/src/modelprinter.cpp b/companion/src/modelprinter.cpp index a6f3e034a..e1d5e3746 100644 --- a/companion/src/modelprinter.cpp +++ b/companion/src/modelprinter.cpp @@ -26,6 +26,7 @@ #include "appdata.h" #include "adjustmentreference.h" #include "curveimage.h" +#include "sourcenumref.h" #include #include @@ -366,9 +367,9 @@ QString ModelPrinter::printInputLine(const ExpoData & input) str += " " + tr("Scale(%1)").arg(input.scale * range.step).toHtmlEscaped(); } - str += " " + tr("Weight(%1)").arg(AdjustmentReference(input.weight).toString(&model, true)).toHtmlEscaped(); + str += " " + tr("Weight(%1)").arg(SourceNumRef(input.weight).toString(&model, &generalSettings)).toHtmlEscaped(); if (input.curve.value) - str += " " + input.curve.toString(&model).toHtmlEscaped(); + str += " " + input.curve.toString(&model, true, &generalSettings).toHtmlEscaped(); QString flightModesStr = printFlightModes(input.flightModes); if (!flightModesStr.isEmpty()) @@ -386,7 +387,7 @@ QString ModelPrinter::printInputLine(const ExpoData & input) } if (input.offset) - str += " " + tr("Offset(%1)").arg(AdjustmentReference(input.offset).toString(&model)).toHtmlEscaped(); + str += " " + tr("Offset(%1)").arg(SourceNumRef(input.offset).toString(&model, &generalSettings)).toHtmlEscaped(); if (firmware->getCapability(HasExpoNames) && input.name[0]) str += QString(" [%1]").arg(input.name).toHtmlEscaped(); @@ -417,7 +418,7 @@ QString ModelPrinter::printMixerLine(const MixData & mix, bool showMultiplex, in if (mix.mltpx == MLTPX_MUL && !showMultiplex) str += " " + tr("MULT!").toHtmlEscaped(); else - str += " " + tr("Weight(%1)").arg(AdjustmentReference(mix.weight).toString(&model, true)).toHtmlEscaped(); + str += " " + tr("Weight(%1)").arg(SourceNumRef(mix.weight).toString(&model, &generalSettings)).toHtmlEscaped(); QString flightModesStr = printFlightModes(mix.flightModes); if (!flightModesStr.isEmpty()) @@ -434,9 +435,9 @@ QString ModelPrinter::printMixerLine(const MixData & mix, bool showMultiplex, in if (firmware->getCapability(HasNoExpo) && mix.noExpo) str += " " + tr("No DR/Expo").toHtmlEscaped(); if (mix.sOffset) - str += " " + tr("Offset(%1)").arg(AdjustmentReference(mix.sOffset).toString(&model)).toHtmlEscaped(); + str += " " + tr("Offset(%1)").arg(SourceNumRef(mix.sOffset).toString(&model, &generalSettings)).toHtmlEscaped(); if (mix.curve.value) - str += " " + mix.curve.toString(&model).toHtmlEscaped(); + str += " " + mix.curve.toString(&model, true, &generalSettings).toHtmlEscaped(); int scale = firmware->getCapability(SlowScale); if (scale == 0) scale = 1; diff --git a/companion/src/shared/curveimagewidget.cpp b/companion/src/shared/curveimagewidget.cpp index 4d2d81ac8..87547ef18 100644 --- a/companion/src/shared/curveimagewidget.cpp +++ b/companion/src/shared/curveimagewidget.cpp @@ -44,7 +44,7 @@ void CurveImageWidget::set(ModelData * model, Firmware * firmware, CompoundItemM void CurveImageWidget::setIndex(int index) { - this->index = (index >= 0 && index < CPN_MAX_CURVES) ? index : -1; + this->index = index; } void CurveImageWidget::setGrid(QColor color, qreal width) @@ -63,8 +63,8 @@ int CurveImageWidget::edit() { int ret = 0; - if (index >= 0 && index < CPN_MAX_CURVES) { - CurveDialog *dlg = new CurveDialog(this, *model, index, firmware, sharedItemModels); + if (abs(index) > 0 && abs(index) <= CPN_MAX_CURVES) { + CurveDialog *dlg = new CurveDialog(this, *model, abs(index) - 1, firmware, sharedItemModels); ret = dlg->exec(); delete dlg; } @@ -74,11 +74,13 @@ int CurveImageWidget::edit() void CurveImageWidget::draw() { - if (index >= 0 && index < CPN_MAX_CURVES) { + if (abs(index) > 0 && abs(index) <= CPN_MAX_CURVES) { CurveImage *curveImage = new CurveImage(gridColor, gridWidth); - curveImage->drawCurve(model->curves[index], penColor, penWidth); + curveImage->drawCurve(model->curves[abs(index) - 1], penColor, penWidth); QImage image = curveImage->get(); + if (index < 0) + image = image.mirrored(true, false); setPixmap(QPixmap::fromImage(image.scaled(height(), width()))); delete curveImage; diff --git a/companion/src/shared/curveimagewidget.h b/companion/src/shared/curveimagewidget.h index aad8b6ee5..ddc9de33a 100644 --- a/companion/src/shared/curveimagewidget.h +++ b/companion/src/shared/curveimagewidget.h @@ -34,7 +34,8 @@ class CurveImageWidget : public QLabel CurveImageWidget(QWidget * parent); virtual ~CurveImageWidget() {} - void set(ModelData * model, Firmware * firmware, CompoundItemModelFactory * sharedItemModels, int index, QColor penColor = Qt::black, qreal penWidth = 2); + void set(ModelData * model, Firmware * firmware, CompoundItemModelFactory * sharedItemModels, int index, QColor penColor = Qt::black, + qreal penWidth = 2); void setIndex(int index); void setGrid(QColor color = Qt::darkGray, qreal width = 1); void setPen(QColor color = Qt::black, qreal width = 2); diff --git a/radio/src/curves.cpp b/radio/src/curves.cpp index ad8715ec2..dc9670038 100644 --- a/radio/src/curves.cpp +++ b/radio/src/curves.cpp @@ -25,6 +25,8 @@ #include "libopenui.h" #endif +extern int32_t getSourceNumFieldValue(int16_t val, int16_t min, int16_t max); + constexpr int DEFAULT_POINTS = 5; constexpr int STD_CURVE_POINTS(int p) { return p + DEFAULT_POINTS; } constexpr int CUSTOM_CURVE_POINTS(int p) { return 2 * p + (2 * DEFAULT_POINTS - 2); } @@ -318,10 +320,13 @@ int intpol(int x, uint8_t idx) // -100, -75, -50, -25, 0 ,25 ,50, 75, 100 int applyCurve(int x, CurveRef & curve) { + SourceNumVal v; + v.rawValue = curve.value; + switch (curve.type) { case CURVE_REF_DIFF: { - int curveParam = GET_GVAR_PREC1(curve.value, -100, 100, mixerCurrentFlightMode); + int curveParam = getSourceNumFieldValue(curve.value, -100, 100); if (curveParam > 0 && x < 0) x = (x * (1000 - curveParam)) / 1000; else if (curveParam < 0 && x > 0) @@ -331,12 +336,12 @@ int applyCurve(int x, CurveRef & curve) case CURVE_REF_EXPO: { - int curveParam = GET_GVAR_PREC1(curve.value, -100, 100, mixerCurrentFlightMode) / 10; + int curveParam = getSourceNumFieldValue(curve.value, -100, 100) / 10; return expo(x, curveParam); } case CURVE_REF_FUNC: - switch (curve.value) { + switch (v.value) { case CURVE_X_GT0: if (x < 0) x = 0; //x|x>0 return x; @@ -356,7 +361,7 @@ int applyCurve(int x, CurveRef & curve) case CURVE_REF_CUSTOM: { - int curveParam = curve.value; + int curveParam = v.value; if (curveParam < 0) { x = -x; curveParam = -curveParam; @@ -423,24 +428,27 @@ char *getCurveRefString(char *dest, size_t len, const CurveRef& curve) if (!len) return dest; char *s = dest; - if (curve.value != 0) { + SourceNumVal v; + v.rawValue = curve.value; + + if (v.value != 0) { switch (curve.type) { case CURVE_REF_DIFF: *(s++) = 'D'; if (--len == 0) return dest; - getValueOrGVarString(s, len, curve.value, -100, 100, 0, "%"); + getValueOrSrcVarString(s, len, curve.value, -100, 100, 0, "%"); return dest; case CURVE_REF_EXPO: *(s++) = 'E'; if (--len == 0) return dest; - getValueOrGVarString(s, len, curve.value, -100, 100, 0, "%"); + getValueOrSrcVarString(s, len, curve.value, -100, 100, 0, "%"); return dest; case CURVE_REF_FUNC: - strAppend(dest, STR_VCURVEFUNC[curve.value], len); + strAppend(dest, STR_VCURVEFUNC[v.value], len); return dest; case CURVE_REF_CUSTOM: - return getCurveString(dest, curve.value); + return getCurveString(dest, v.value); } } diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index 147c4dc12..2700006f1 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -541,6 +541,7 @@ enum MixSources { MIXSRC_LAST_TELEM SKIP = MIXSRC_FIRST_TELEM + 3 * MAX_TELEMETRY_SENSORS - 1, MIXSRC_INVERT SKIP, + MIXSRC_VALUE SKIP, // Special case to trigger source as value conversion }; diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index f0e9c3339..03ab30ab5 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -42,7 +42,7 @@ static inline void check_struct() CHKSIZE(CurveRef, 2); CHKSIZE(VarioData, 5); CHKSIZE(MixData, 20); - CHKSIZE(ExpoData, 17); + CHKSIZE(ExpoData, 18); CHKSIZE(SwashRingData, 8); CHKSIZE(CurveHeader, 4); CHKSIZE(LogicalSwitchData, 9); @@ -91,23 +91,23 @@ static inline void check_struct() #endif #if defined(RADIO_TPRO) || defined(RADIO_TPROV2) - CHKSIZE(ModelData, 6290); + CHKSIZE(ModelData, 6354); #elif defined(RADIO_FAMILY_T20) - CHKSIZE(ModelData, 6326); + CHKSIZE(ModelData, 6390); #elif defined(PCBX9E) - CHKSIZE(ModelData, 6707); + CHKSIZE(ModelData, 6771); #elif defined(PCBX9D) || defined(PCBX9DP) - CHKSIZE(ModelData, 6706); + CHKSIZE(ModelData, 6770); #elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBX9LITE) - CHKSIZE(ModelData, 6265); + CHKSIZE(ModelData, 6329); #elif defined(PCBNV14) - CHKSIZE(ModelData, 15591); + CHKSIZE(ModelData, 15655); #elif defined(PCBPL18) - CHKSIZE(ModelData, 15771); + CHKSIZE(ModelData, 15835); #elif defined(RADIO_T15) - CHKSIZE(ModelData, 15760); + CHKSIZE(ModelData, 15824); #elif defined(PCBHORUS) - CHKSIZE(ModelData, 15735); + CHKSIZE(ModelData, 15799); #else #error CHKSIZE not set up #endif diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index b86616f30..0013434b7 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -62,26 +62,43 @@ #include "storage/yaml/yaml_defs.h" +PACK(union SourceNumVal { + struct { + int16_t value:10; + bool isSource:1; + }; + uint16_t rawValue:11; +}); + +inline uint16_t makeSourceNumVal(int16_t val, bool isSource = false) +{ + SourceNumVal v; + v.value = val; + v.isSource= isSource; + return v.rawValue; +} + /* * Mixer structure */ PACK(struct CurveRef { - uint8_t type; - int8_t value CUST(in_read_weight,in_write_weight); + uint16_t type:5; + int16_t value:11 CUST(r_sourceNumVal,w_sourceNumVal); }); PACK(struct MixData { - int16_t weight:11 CUST(in_read_weight,in_write_weight); // GV1=-1024, -GV1=1023 uint16_t destCh:5; 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); uint16_t speedPrec:1; - int32_t offset:13 CUST(in_read_weight,in_write_weight); + uint16_t flightModes:9 CUST(r_flightModes, w_flightModes); + uint16_t spare:2; + uint32_t weight:11 CUST(r_sourceNumVal,w_sourceNumVal); + uint32_t offset:11 CUST(r_sourceNumVal,w_sourceNumVal); int32_t swtch:10 CUST(r_swtchSrc,w_swtchSrc); - uint32_t flightModes:9 CUST(r_flightModes, w_flightModes); CurveRef curve; uint8_t delayUp; uint8_t delayDown; @@ -100,13 +117,14 @@ PACK(struct ExpoData { CUST_ATTR(carryTrim, r_carryTrim, nullptr); //pre 2.9 int16_t trimSource:6; int16_t srcRaw:10 ENUM(MixSources) CUST(r_mixSrcRawEx,w_mixSrcRawEx); - uint32_t chn:5; + uint32_t weight:11 CUST(r_sourceNumVal,w_sourceNumVal); + uint32_t offset:11 CUST(r_sourceNumVal,w_sourceNumVal); int32_t swtch:10 CUST(r_swtchSrc,w_swtchSrc); - uint32_t flightModes:9 CUST(r_flightModes, w_flightModes); - int32_t weight:8 CUST(in_read_weight,in_write_weight); - NOBACKUP(char name[LEN_EXPOMIX_NAME]); - int8_t offset CUST(in_read_weight,in_write_weight); CurveRef curve; + uint16_t chn:5; + uint16_t flightModes:9 CUST(r_flightModes, w_flightModes); + uint16_t spare:2; + NOBACKUP(char name[LEN_EXPOMIX_NAME]); }); /* diff --git a/radio/src/gui/128x64/gui.h b/radio/src/gui/128x64/gui.h index d57f44261..ffbe96402 100644 --- a/radio/src/gui/128x64/gui.h +++ b/radio/src/gui/128x64/gui.h @@ -47,7 +47,7 @@ #define CURVE_CENTER_X (LCD_W-CURVE_SIDE_WIDTH-3) #define CURVE_CENTER_Y (LCD_H/2) -#define MIXES_2ND_COLUMN (12*FW) +#define MIXES_2ND_COLUMN (10*FW) // Temporary no highlight extern uint8_t noHighlightCounter; @@ -80,6 +80,10 @@ uint8_t editCheckBox(uint8_t value, coord_t x, coord_t y, const char *label, swsrc_t editSwitch(coord_t x, coord_t y, swsrc_t value, LcdFlags attr, event_t event); +uint16_t editSrcVarFieldValue(coord_t x, coord_t y, const char* title, uint16_t value, + int16_t min, int16_t max, LcdFlags attr, event_t event, + IsValueAvailable isValueAvailable, int16_t sourceMin); + #if defined(GVARS) #define GVAR_MENU_ITEM(x, y, v, min, max, attr, editflags, event) \ @@ -110,8 +114,6 @@ int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, #endif -void gvarWeightItem(coord_t x, coord_t y, MixData * md, LcdFlags attr, event_t event); - void editName(coord_t x, coord_t y, char *name, uint8_t size, event_t event, uint8_t active, LcdFlags attr, uint8_t old_editMode); @@ -198,7 +200,8 @@ void showAlertBox(const char * title, const char * text, const char * action , u #define IS_TELEMETRY_VIEW_DISPLAYED() menuHandlers[0] == menuViewTelemetry #define IS_OTHER_VIEW_DISPLAYED() menuHandlers[0] == menuChannelsView -void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlags flags); +void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlags flags, + IsValueAvailable isValueAvailable, int16_t sourceMin); #if defined(FLIGHT_MODES) void displayFlightModes(coord_t x, coord_t y, FlightModesType value); diff --git a/radio/src/gui/128x64/lcd.cpp b/radio/src/gui/128x64/lcd.cpp index 21ef551e1..456b51092 100644 --- a/radio/src/gui/128x64/lcd.cpp +++ b/radio/src/gui/128x64/lcd.cpp @@ -662,55 +662,6 @@ void putsVBat(coord_t x, coord_t y, LcdFlags att) putsVolts(x, y, g_vbat100mV, att); } -void drawSource(coord_t x, coord_t y, mixsrc_t idx, LcdFlags att) -{ - uint16_t aidx = abs(idx); - bool inverted = idx < 0; - - if (aidx == MIXSRC_NONE) { - lcdDrawText(x, y, STR_EMPTY, att); - } - 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[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, aidx, att|LEADING0|LEFT, 2); - } -#if defined(LUA_INPUTS) - 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); - lcdDrawSizedText(x+8, y, scriptInputsOutputs[qr.quot].outputs[qr.rem].name, att & STREXPANDED ? 9 : 4, att); - } - else -#endif - { - drawStringWithIndex(x, y, "LUA", qr.quot+1, att); - lcdDrawChar(lcdLastRightPos, y, 'a' + qr.rem, att); - } - } -#endif - else { - const char* s = getSourceString(idx); - if (idx >= MIXSRC_FIRST_TELEM && idx <= MIXSRC_LAST_TELEM) - s += strlen(STR_CHAR_TELEMETRY); - lcdDrawText(x, y, s, att); - } -} - void putsChnLetter(coord_t x, coord_t y, uint8_t idx, LcdFlags att) { lcdDrawText(x, y, getAnalogShortLabel(idx), att); diff --git a/radio/src/gui/128x64/lcd.h b/radio/src/gui/128x64/lcd.h index 452d7215d..021d21e80 100644 --- a/radio/src/gui/128x64/lcd.h +++ b/radio/src/gui/128x64/lcd.h @@ -116,7 +116,6 @@ void lcdDraw8bitsNumber(coord_t x, coord_t y, int8_t val); void drawModelName(coord_t x, coord_t y, char * name, uint8_t id, LcdFlags att); #if !defined(BOOT) // TODO not here ... void drawSwitch(coord_t x, coord_t y, swsrc_t swtch, LcdFlags att=0, bool autoBold = true); -void drawSource(coord_t x, coord_t y, mixsrc_t idx, LcdFlags att=0); #endif 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/128x64/model_input_edit.cpp b/radio/src/gui/128x64/model_input_edit.cpp index 46759dd5c..5b0ab920d 100644 --- a/radio/src/gui/128x64/model_input_edit.cpp +++ b/radio/src/gui/128x64/model_input_edit.cpp @@ -21,7 +21,7 @@ #include "opentx.h" -#define EXPO_ONE_2ND_COLUMN (7*FW+3*FW+2) +#define EXPO_ONE_2ND_COLUMN (6*FW+1) int expoFn(int x) { @@ -91,39 +91,39 @@ void menuModelExpoOne(event_t event) switch (i) { case EXPO_FIELD_INPUT_NAME: - editSingleName(EXPO_ONE_2ND_COLUMN - LEN_INPUT_NAME * FW, y, + editSingleName(EXPO_ONE_2ND_COLUMN, y, STR_INPUTNAME, g_model.inputNames[ed->chn], LEN_INPUT_NAME, event, (attr != 0), old_editMode); break; case EXPO_FIELD_LINE_NAME: - editSingleName(EXPO_ONE_2ND_COLUMN - LEN_EXPOMIX_NAME * FW, y, + editSingleName(EXPO_ONE_2ND_COLUMN, y, STR_EXPONAME, ed->name, LEN_EXPOMIX_NAME, event, (attr != 0), old_editMode); break; case EXPO_FIELD_SOURCE: lcdDrawTextAlignedLeft(y, STR_SOURCE); - drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, RIGHT|STREXPANDED|attr); + drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, STREXPANDED|attr); if (attr) 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, (abs(ed->srcRaw) - MIXSRC_FIRST_TELEM)/3, convertTelemValue(abs(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), 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: - lcdDrawTextAlignedLeft(y, STR_WEIGHT); - ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, -100, 100, RIGHT | attr, 0, event); + ed->weight = editSrcVarFieldValue(EXPO_ONE_2ND_COLUMN, y, STR_WEIGHT, ed->weight, + -100, 100, attr, event, isSourceAvailableInInputs, INPUTSRC_FIRST); break; case EXPO_FIELD_OFFSET: - lcdDrawTextAlignedLeft(y, STR_OFFSET); - ed->offset = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->offset, -100, 100, RIGHT | attr, 0, event); + ed->offset = editSrcVarFieldValue(EXPO_ONE_2ND_COLUMN, y, STR_OFFSET, ed->offset, + -100, 100, attr, event, isSourceAvailableInInputs, INPUTSRC_FIRST); break; case EXPO_FIELD_CURVE_LABEL: @@ -131,7 +131,7 @@ void menuModelExpoOne(event_t event) break; case EXPO_FIELD_CURVE: - editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, RIGHT | attr); + editCurveRef(FW + 1, y, ed->curve, event, attr, isSourceAvailableInInputs, INPUTSRC_FIRST); break; #if defined(FLIGHT_MODES) @@ -140,23 +140,23 @@ void menuModelExpoOne(event_t event) break; case EXPO_FIELD_FLIGHT_MODES: - ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN-9*FW+1, y, event, ed->flightModes, attr); + ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN-5*FW-2, y, event, ed->flightModes, attr); break; #endif case EXPO_FIELD_SWITCH: - ed->swtch = editSwitch(EXPO_ONE_2ND_COLUMN, y, ed->swtch, RIGHT | attr, event); + ed->swtch = editSwitch(EXPO_ONE_2ND_COLUMN, y, ed->swtch, attr, event); break; case EXPO_FIELD_SIDE: - ed->mode = 4 - editChoice(EXPO_ONE_2ND_COLUMN, y, STR_SIDE, STR_VCURVEFUNC, 4-ed->mode, 1, 3, RIGHT | attr, event); + ed->mode = 4 - editChoice(EXPO_ONE_2ND_COLUMN, y, STR_SIDE, STR_VCURVEFUNC, 4-ed->mode, 1, 3, attr, event); break; case EXPO_FIELD_TRIM: lcdDrawTextAlignedLeft(y, STR_TRIM); { const char* trim_str = getTrimSourceLabel(abs(ed->srcRaw), ed->trimSource); - LcdFlags flags = RIGHT | (menuHorizontalPosition==0 ? attr : 0); + LcdFlags flags = (menuHorizontalPosition==0 ? attr : 0); lcdDrawText(EXPO_ONE_2ND_COLUMN, y, trim_str, flags); if (attr) { diff --git a/radio/src/gui/128x64/model_mix_edit.cpp b/radio/src/gui/128x64/model_mix_edit.cpp index 87d2f858a..14d708bdf 100644 --- a/radio/src/gui/128x64/model_mix_edit.cpp +++ b/radio/src/gui/128x64/model_mix_edit.cpp @@ -43,13 +43,15 @@ enum MixFields { extern uint8_t FM_ROW(uint8_t); +extern int32_t getSourceNumFieldValue(int16_t val, int16_t min, int16_t max); + void drawOffsetBar(uint8_t x, uint8_t y, MixData * md) { const int gaugeWidth = 33; const int gaugeHeight = 6; - int offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); - int weight = GET_GVAR(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); + int offset = getSourceNumFieldValue(md->offset, MIX_OFFSET_MIN, MIX_OFFSET_MAX) / 10; + int weight = getSourceNumFieldValue(md->weight, MIX_WEIGHT_MIN, MIX_WEIGHT_MAX) / 10; int barMin = offset - weight; int barMax = offset + weight; if (y > 15) { @@ -137,20 +139,15 @@ void menuModelMixOne(event_t event) break; case MIX_FIELD_WEIGHT: - lcdDrawTextAlignedLeft(y, STR_WEIGHT); - gvarWeightItem(MIXES_2ND_COLUMN, y, md2, attr|LEFT, event); + md2->weight = editSrcVarFieldValue(MIXES_2ND_COLUMN, y, STR_WEIGHT, md2->weight, + MIX_WEIGHT_MIN, MIX_WEIGHT_MAX, attr, event, isSourceAvailable, 1); break; case MIX_FIELD_OFFSET: - { - lcdDrawTextAlignedLeft(y, STR_OFFSET); - u_int8int16_t offset; - MD_OFFSET_TO_UNION(md2, offset); - offset.word = GVAR_MENU_ITEM(MIXES_2ND_COLUMN, y, offset.word, MIX_OFFSET_MIN, MIX_OFFSET_MAX, attr|LEFT, 0, event); - MD_UNION_TO_OFFSET(offset, md2); - drawOffsetBar(MIXES_2ND_COLUMN+22, y, md2); + md2->offset = editSrcVarFieldValue(MIXES_2ND_COLUMN, y, STR_OFFSET, md2->offset, + MIX_OFFSET_MIN, MIX_OFFSET_MAX, attr, event, isSourceAvailable, 1); + drawOffsetBar(LCD_W - 33, y, md2); break; - } case MIX_FIELD_TRIM: lcdDrawTextAlignedLeft(y, STR_TRIM); @@ -162,7 +159,7 @@ void menuModelMixOne(event_t event) lcdDrawTextAlignedLeft(y, STR_CURVE); s_currSrcRaw = md2->srcRaw; s_currScale = 0; - editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, event, attr); + editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, event, attr, isSourceAvailable, 1); break; #if defined(FLIGHT_MODES) diff --git a/radio/src/gui/128x64/widgets.cpp b/radio/src/gui/128x64/widgets.cpp index 35fdaea36..b63429776 100644 --- a/radio/src/gui/128x64/widgets.cpp +++ b/radio/src/gui/128x64/widgets.cpp @@ -162,6 +162,30 @@ void drawSlider(coord_t x, coord_t y, uint8_t value, uint8_t max, uint8_t attr) drawSlider(x, y, 5*FW - 1, value, max, attr); } +uint16_t editSrcVarFieldValue(coord_t x, coord_t y, const char* title, uint16_t value, + int16_t min, int16_t max, LcdFlags attr, event_t event, + IsValueAvailable isValueAvailable, int16_t sourceMin) +{ + if (title) + lcdDrawTextAlignedLeft(y, title); + SourceNumVal v; + v.rawValue = value; + if (v.isSource) { + drawSource(x, y, v.value, attr); + if (attr & (~RIGHT)) { + value = checkIncDec(event, value, sourceMin, MIXSRC_LAST, + EE_MODEL|INCDEC_SOURCE|INCDEC_SOURCE_VALUE|INCDEC_SOURCE_INVERT|NO_INCDEC_MARKS, isValueAvailable); + } + } else { + lcdDrawNumber(x, y, v.value, attr); + if (attr & (~RIGHT)) { + value = checkIncDec(event, value, min, max, + EE_MODEL|INCDEC_SOURCE_VALUE|NO_INCDEC_MARKS|(sourceMin == INPUTSRC_FIRST ? INCDEC_SOURCE_NOINPUTS : 0)); + } + } + return value; +} + #if defined(GVARS) void drawGVarValue(coord_t x, coord_t y, uint8_t gvar, gvar_t value, LcdFlags flags) { diff --git a/radio/src/gui/212x64/gui.h b/radio/src/gui/212x64/gui.h index 9475ead12..bbeac7bc0 100644 --- a/radio/src/gui/212x64/gui.h +++ b/radio/src/gui/212x64/gui.h @@ -91,6 +91,10 @@ uint8_t editCheckBox(uint8_t value, coord_t x, coord_t y, const char *label, swsrc_t editSwitch(coord_t x, coord_t y, swsrc_t value, LcdFlags attr, event_t event); +uint16_t editSrcVarFieldValue(coord_t x, coord_t y, const char* title, uint16_t value, + int16_t min, int16_t max, LcdFlags attr, event_t event, + IsValueAvailable isValueAvailable, int16_t sourceMin); + #if defined(GVARS) void drawGVarValue(coord_t x, coord_t y, uint8_t gvar, gvar_t value, LcdFlags flags = 0); @@ -117,9 +121,8 @@ int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, #endif -void gvarWeightItem(coord_t x, coord_t y, MixData * md, LcdFlags attr, event_t event); - -void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlags flags); +void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlags flags, + IsValueAvailable isValueAvailable, int16_t sourceMin); extern uint8_t editNameCursorPos; diff --git a/radio/src/gui/212x64/lcd.cpp b/radio/src/gui/212x64/lcd.cpp index e0f081a7a..51da41cdc 100644 --- a/radio/src/gui/212x64/lcd.cpp +++ b/radio/src/gui/212x64/lcd.cpp @@ -632,51 +632,6 @@ 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, mixsrc_t idx, LcdFlags att) -{ - uint16_t aidx = abs(idx); - bool inverted = idx < 0; - - if (aidx == MIXSRC_NONE) { - lcdDrawText(x, y, STR_EMPTY, att); - } - 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[aidx-MIXSRC_FIRST_INPUT])) - lcdDrawSizedText(x+8, y, g_model.inputNames[aidx-MIXSRC_FIRST_INPUT], LEN_INPUT_NAME, att); - else - lcdDrawNumber(x+8, y, aidx, att|LEADING0|LEFT, 2); - } - - 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); - lcdDrawSizedText(x+8, y, scriptInputsOutputs[qr.quot].outputs[qr.rem].name, att & STREXPANDED ? 9 : 4, att); - } - else -#endif - { - drawStringWithIndex(x, y, "LUA", qr.quot+1, att); - lcdDrawChar(lcdLastRightPos, y, 'a'+qr.rem, att); - } - } - else { - lcdDrawText(x, y, getSourceString(idx), att); - } -} - void putsChnLetter(coord_t x, coord_t y, uint8_t idx, LcdFlags att) { lcdDrawText(x, y, getAnalogShortLabel(idx), att); diff --git a/radio/src/gui/212x64/lcd.h b/radio/src/gui/212x64/lcd.h index 41c3da703..d47d17136 100644 --- a/radio/src/gui/212x64/lcd.h +++ b/radio/src/gui/212x64/lcd.h @@ -114,7 +114,6 @@ 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, 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/model_input_edit.cpp b/radio/src/gui/212x64/model_input_edit.cpp index d12b67c7d..3a887b21e 100644 --- a/radio/src/gui/212x64/model_input_edit.cpp +++ b/radio/src/gui/212x64/model_input_edit.cpp @@ -119,18 +119,18 @@ void menuModelExpoOne(event_t event) break; case EXPO_FIELD_WEIGHT: - lcdDrawTextAlignedLeft(y, STR_WEIGHT); - ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, -100, 100, LEFT|attr, 0, event); + ed->weight = editSrcVarFieldValue(EXPO_ONE_2ND_COLUMN, y, STR_WEIGHT, ed->weight, + -100, 100, attr, event, isSourceAvailableInInputs, INPUTSRC_FIRST); break; case EXPO_FIELD_OFFSET: - lcdDrawTextAlignedLeft(y, STR_OFFSET); - ed->offset = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->offset, -100, 100, LEFT|attr, 0, event); + ed->offset = editSrcVarFieldValue(EXPO_ONE_2ND_COLUMN, y, STR_OFFSET, ed->offset, + -100, 100, attr, event, isSourceAvailableInInputs, INPUTSRC_FIRST); break; case EXPO_FIELD_CURVE: lcdDrawTextAlignedLeft(y, STR_CURVE); - editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, attr); + editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, attr, isSourceAvailableInInputs, INPUTSRC_FIRST); break; #if defined(FLIGHT_MODES) diff --git a/radio/src/gui/212x64/model_mix_edit.cpp b/radio/src/gui/212x64/model_mix_edit.cpp index e9ca8b0d9..43a0eb6f3 100644 --- a/radio/src/gui/212x64/model_mix_edit.cpp +++ b/radio/src/gui/212x64/model_mix_edit.cpp @@ -43,13 +43,15 @@ enum MixFields { extern uint8_t FM_ROW(uint8_t); +extern int32_t getSourceNumFieldValue(int16_t val, int16_t min, int16_t max); + void drawOffsetBar(uint8_t x, uint8_t y, MixData * md) { const int gaugeWidth = 33; const int gaugeHeight = 6; - int offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); - int weight = GET_GVAR(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); + int offset = getSourceNumFieldValue(md->offset, MIX_OFFSET_MIN, MIX_OFFSET_MAX) / 10; + int weight = getSourceNumFieldValue(md->weight, MIX_WEIGHT_MIN, MIX_WEIGHT_MAX) / 10; int barMin = offset - weight; int barMax = offset + weight; if (y > 15) { @@ -130,20 +132,15 @@ void menuModelMixOne(event_t event) break; case MIX_FIELD_WEIGHT: - lcdDrawTextAlignedLeft(y, STR_WEIGHT); - gvarWeightItem(MIXES_2ND_COLUMN, y, md2, attr|LEFT, event); + md2->weight = editSrcVarFieldValue(MIXES_2ND_COLUMN, y, STR_WEIGHT, md2->weight, + MIX_WEIGHT_MIN, MIX_WEIGHT_MAX, attr, event, isSourceAvailable, 1); break; case MIX_FIELD_OFFSET: - { - lcdDrawTextAlignedLeft(y, STR_OFFSET); - u_int8int16_t offset; - MD_OFFSET_TO_UNION(md2, offset); - offset.word = GVAR_MENU_ITEM(MIXES_2ND_COLUMN, y, offset.word, MIX_OFFSET_MIN, MIX_OFFSET_MAX, attr|LEFT, 0, event); - MD_UNION_TO_OFFSET(offset, md2); + md2->offset = editSrcVarFieldValue(MIXES_2ND_COLUMN, y, STR_OFFSET, md2->offset, + MIX_OFFSET_MIN, MIX_OFFSET_MAX, attr, event, isSourceAvailable, 1); drawOffsetBar(MIXES_2ND_COLUMN+35, y, md2); break; - } case MIX_FIELD_TRIM: lcdDrawTextAlignedLeft(y, STR_TRIM); @@ -157,7 +154,7 @@ void menuModelMixOne(event_t event) lcdDrawTextAlignedLeft(y, STR_CURVE); s_currSrcRaw = md2->srcRaw; s_currScale = 0; - editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, event, attr); + editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, event, attr, isSourceAvailable, 1); break; #if defined(FLIGHT_MODES) diff --git a/radio/src/gui/212x64/widgets.cpp b/radio/src/gui/212x64/widgets.cpp index 1b526dac7..73e3af66e 100644 --- a/radio/src/gui/212x64/widgets.cpp +++ b/radio/src/gui/212x64/widgets.cpp @@ -120,6 +120,30 @@ void drawSlider(coord_t x, coord_t y, uint8_t value, uint8_t max, uint8_t attr) if (attr && (!(attr & BLINK) || !BLINK_ON_PHASE)) lcdDrawFilledRect(x, y, 5*FW-1, FH-1); } +uint16_t editSrcVarFieldValue(coord_t x, coord_t y, const char* title, uint16_t value, + int16_t min, int16_t max, LcdFlags attr, event_t event, + IsValueAvailable isValueAvailable, int16_t sourceMin) +{ + if (title) + lcdDrawTextAlignedLeft(y, title); + SourceNumVal v; + v.rawValue = value; + if (v.isSource) { + drawSource(x, y, v.value, attr); + if (attr & (~RIGHT)) { + value = checkIncDec(event, value, sourceMin, + MIXSRC_LAST, EE_MODEL|INCDEC_SOURCE|INCDEC_SOURCE_VALUE|INCDEC_SOURCE_INVERT|NO_INCDEC_MARKS, isValueAvailable); + } + } else { + lcdDrawNumber(x, y, v.value, attr); + if (attr & (~RIGHT)) { + value = checkIncDec(event, value, min, max, + EE_MODEL|INCDEC_SOURCE_VALUE|NO_INCDEC_MARKS|(sourceMin == INPUTSRC_FIRST ? INCDEC_SOURCE_NOINPUTS : 0)); + } + } + return value; +} + #if defined(GVARS) void drawGVarValue(coord_t x, coord_t y, uint8_t gvar, gvar_t value, LcdFlags flags) { diff --git a/radio/src/gui/colorlcd/CMakeLists.txt b/radio/src/gui/colorlcd/CMakeLists.txt index 00af42705..e53d73256 100644 --- a/radio/src/gui/colorlcd/CMakeLists.txt +++ b/radio/src/gui/colorlcd/CMakeLists.txt @@ -111,6 +111,7 @@ set(GUI_SRC radio_tools.cpp radio_trainer.cpp radio_version.cpp + source_numberedit.cpp ) macro(add_gui_src src) diff --git a/radio/src/gui/colorlcd/curve.cpp b/radio/src/gui/colorlcd/curve.cpp index fffce35ef..0ea93ae23 100644 --- a/radio/src/gui/colorlcd/curve.cpp +++ b/radio/src/gui/colorlcd/curve.cpp @@ -243,7 +243,11 @@ void Curve::clearPoints() update(); } -void Curve::update() { base.update(); } +void Curve::update() +{ + base.update(); + updatePosition(); +} void Curve::checkEvents() { diff --git a/radio/src/gui/colorlcd/curve_param.cpp b/radio/src/gui/colorlcd/curve_param.cpp index 103818b4e..7ec898922 100644 --- a/radio/src/gui/colorlcd/curve_param.cpp +++ b/radio/src/gui/colorlcd/curve_param.cpp @@ -22,6 +22,7 @@ #include "curve_param.h" #include "gvar_numberedit.h" +#include "source_numberedit.h" #include "model_curves.h" #include "opentx.h" @@ -37,21 +38,12 @@ void CurveParam::LongPressHandler(void* data) } } -void CurveParam::value_changed(lv_event_t* e) -{ - auto obj = lv_event_get_target(e); - auto param = (CurveParam*)lv_obj_get_user_data(obj); - if (!param) return; - - param->update(); -} - class CurveChoice : public Choice { public: - CurveChoice(Window* parent, CurveRef* ref, std::function setRefValue, std::function refreshView) : - Choice(parent, rect_t{}, -MAX_CURVES, MAX_CURVES, GET_DEFAULT(ref->value), setRefValue), - ref(ref), refreshView(refreshView) + CurveChoice(Window* parent, std::function getRefValue, std::function setRefValue, std::function refreshView) : + Choice(parent, rect_t{}, -MAX_CURVES, MAX_CURVES, getRefValue, setRefValue), + refreshView(std::move(refreshView)) { setTextHandler([](int value) { return getCurveString(value); }); } @@ -59,21 +51,21 @@ class CurveChoice : public Choice bool onLongPress() override { if (modelCurvesEnabled()) { - if (ref->value) { - ModelCurvesPage::pushEditCurve(abs(ref->value) - 1, refreshView); + if (_getValue()) { + ModelCurvesPage::pushEditCurve(abs(_getValue()) - 1, refreshView); } } return true; } protected: - CurveRef* ref; std::function refreshView; }; CurveParam::CurveParam(Window* parent, const rect_t& rect, CurveRef* ref, - std::function setRefValue, std::function refreshView) : - Window(parent, rect), ref(ref) + std::function setRefValue, int16_t sourceMin, + std::function refreshView) : + Window(parent, rect), ref(ref), refreshView(std::move(refreshView)) { padAll(PAD_TINY); lv_obj_set_flex_flow(lvobj, LV_FLEX_FLOW_ROW_WRAP); @@ -85,23 +77,42 @@ CurveParam::CurveParam(Window* parent, const rect_t& rect, CurveRef* ref, ref->type = newValue; ref->value = 0; SET_DIRTY(); - lv_event_send(lvobj, LV_EVENT_VALUE_CHANGED, nullptr); + update(); }); - lv_obj_add_event_cb(lvobj, CurveParam::value_changed, LV_EVENT_VALUE_CHANGED, - nullptr); // CURVE_REF_DIFF // CURVE_REF_EXPO - auto gv = new GVarNumberEdit(this, -100, 100, GET_DEFAULT(ref->value), setRefValue); + auto gv = new SourceNumberEdit(this, -100, 100, GET_DEFAULT(ref->value), setRefValue, sourceMin); gv->setSuffix("%"); value_edit = gv; // CURVE_REF_FUNC func_choice = new Choice(this, rect_t{}, STR_VCURVEFUNC, 0, CURVE_BASE - 1, - GET_DEFAULT(ref->value), setRefValue); + [=]() { + SourceNumVal v; + v.rawValue = ref->value; + return v.value; + }, + [=](int32_t newValue) { + SourceNumVal v; + v.isSource = false; + v.value = newValue; + setRefValue(v.rawValue); + }); // CURVE_REF_CUSTOM - cust_choice = new CurveChoice(this, ref, setRefValue, refreshView); + cust_choice = new CurveChoice(this, + [=]() { + SourceNumVal v; + v.rawValue = ref->value; + return v.value; + }, + [=](int32_t newValue) { + SourceNumVal v; + v.isSource = false; + v.value = newValue; + setRefValue(v.rawValue); + }, refreshView); update(); } @@ -117,14 +128,17 @@ void CurveParam::update() switch (ref->type) { case CURVE_REF_DIFF: case CURVE_REF_EXPO: + value_edit->update(); act_field = value_edit; break; case CURVE_REF_FUNC: + func_choice->update(); act_field = func_choice; break; case CURVE_REF_CUSTOM: + cust_choice->update(); act_field = cust_choice; break; @@ -133,10 +147,11 @@ void CurveParam::update() } act_field->show(); + if (refreshView) + refreshView(); auto act_obj = act_field->getLvObj(); if (has_focus) { lv_group_focus_obj(act_obj); } - lv_event_send(act_obj, LV_EVENT_VALUE_CHANGED, nullptr); } diff --git a/radio/src/gui/colorlcd/curve_param.h b/radio/src/gui/colorlcd/curve_param.h index f5859fdee..6c1cec176 100644 --- a/radio/src/gui/colorlcd/curve_param.h +++ b/radio/src/gui/colorlcd/curve_param.h @@ -24,24 +24,30 @@ #include "window.h" struct CurveRef; +class Choice; +class SourceNumberEdit; class CurveParam : public Window { + public: + CurveParam(Window* parent, const rect_t& rect, CurveRef* ref, + std::function setRefValue, + int16_t sourceMin, + std::function refreshView = nullptr); + + protected: // Curve CurveRef* ref; // Controls - Window* value_edit; - Window* func_choice; - Window* cust_choice; + SourceNumberEdit* value_edit; + Choice* func_choice; + Choice* cust_choice; Window* act_field = nullptr; - void update(); - static void value_changed(lv_event_t* e); - static void LongPressHandler(void* data); + std::function refreshView; - public: - CurveParam(Window* parent, const rect_t& rect, CurveRef* ref, - std::function setRefValue, - std::function refreshView = nullptr); + void update(); + + static void LongPressHandler(void* data); }; diff --git a/radio/src/gui/colorlcd/input_edit.cpp b/radio/src/gui/colorlcd/input_edit.cpp index f99a4cacf..7554decbd 100644 --- a/radio/src/gui/colorlcd/input_edit.cpp +++ b/radio/src/gui/colorlcd/input_edit.cpp @@ -24,6 +24,7 @@ #include "curve_param.h" #include "curveedit.h" #include "gvar_numberedit.h" +#include "source_numberedit.h" #include "input_edit_adv.h" #include "input_source.h" #include "opentx.h" @@ -106,23 +107,23 @@ void InputEditWindow::buildBody(Window* form) line = form->newLine(grid); new StaticText(line, rect_t{}, STR_WEIGHT); auto gvar = - new GVarNumberEdit(line, -100, 100, GET_DEFAULT(input->weight), - [=](int32_t newValue) { - input->weight = newValue; - preview->update(); - SET_DIRTY(); - }); + new SourceNumberEdit(line, -100, 100, GET_DEFAULT(input->weight), + [=](int32_t newValue) { + input->weight = newValue; + preview->update(); + SET_DIRTY(); + }, INPUTSRC_FIRST); gvar->setSuffix("%"); // Offset line = form->newLine(grid); new StaticText(line, rect_t{}, STR_OFFSET); - gvar = new GVarNumberEdit(line, -100, 100, - GET_DEFAULT(input->offset), [=](int32_t newValue) { - input->offset = newValue; - preview->update(); - SET_DIRTY(); - }); + gvar = new SourceNumberEdit(line, -100, 100, + GET_DEFAULT(input->offset), [=](int32_t newValue) { + input->offset = newValue; + preview->update(); + SET_DIRTY(); + }, INPUTSRC_FIRST); gvar->setSuffix("%"); // Switch @@ -138,11 +139,13 @@ void InputEditWindow::buildBody(Window* form) new CurveParam(line, rect_t{}, &input->curve, [=](int32_t newValue) { input->curve.value = newValue; - preview->update(); + if (preview) + preview->update(); SET_DIRTY(); - }, + }, INPUTSRC_FIRST, [=]() { - preview->update(); + if (preview) + preview->update(); }); lv_obj_set_style_grid_cell_x_align(param->getLvObj(), LV_GRID_ALIGN_STRETCH, 0); @@ -164,3 +167,44 @@ void InputEditWindow::deleteLater(bool detach, bool trash) Page::deleteLater(detach, trash); } } + +void InputEditWindow::checkEvents() +{ + ExpoData* input = expoAddress(index); + + bool updatePreview = false; + getvalue_t val; + SourceNumVal v; + + v.rawValue = input->weight; + if (v.isSource) { + val = getValue(v.value); + if (val != lastWeightVal) { + lastWeightVal = val; + updatePreview = true; + } + } + + v.rawValue = input->offset; + if (v.isSource) { + val = getValue(v.value); + if (val != lastOffsetVal) { + lastOffsetVal = val; + updatePreview = true; + } + } + + v.rawValue = input->curve.value; + if (v.isSource) { + val = getValue(v.value); + if (val != lastCurveVal) { + lastCurveVal = val; + updatePreview = true; + } + } + + if (updatePreview) + preview->update(); + + Page::checkEvents(); +} diff --git a/radio/src/gui/colorlcd/input_edit.h b/radio/src/gui/colorlcd/input_edit.h index 8af4e588a..2349f53de 100644 --- a/radio/src/gui/colorlcd/input_edit.h +++ b/radio/src/gui/colorlcd/input_edit.h @@ -38,9 +38,13 @@ class InputEditWindow : public Page protected: uint8_t input; uint8_t index; - Curve* preview; + Curve* preview = nullptr; + getvalue_t lastWeightVal = 0; + getvalue_t lastOffsetVal = 0; + getvalue_t lastCurveVal = 0; void buildBody(Window *window); + void checkEvents() override; void deleteLater(bool detach = true, bool trash = true) override; }; diff --git a/radio/src/gui/colorlcd/list_line_button.cpp b/radio/src/gui/colorlcd/list_line_button.cpp index 708480cd1..143644e6d 100644 --- a/radio/src/gui/colorlcd/list_line_button.cpp +++ b/radio/src/gui/colorlcd/list_line_button.cpp @@ -71,6 +71,7 @@ InputMixButtonBase::InputMixButtonBase(Window* parent, uint8_t index) : weight = lv_label_create(lvobj); lv_obj_set_pos(weight, WGT_X, WGT_Y); lv_obj_set_size(weight, WGT_W, WGT_H); + etx_font(weight, FONT_XS_INDEX, LV_STATE_USER_1); source = lv_label_create(lvobj); lv_obj_set_pos(source, SRC_X, SRC_Y); @@ -79,6 +80,7 @@ InputMixButtonBase::InputMixButtonBase(Window* parent, uint8_t index) : opts = lv_label_create(lvobj); lv_obj_set_pos(opts, OPT_X, OPT_Y); lv_obj_set_size(opts, OPT_W, OPT_H); + etx_font(opts, FONT_XS_INDEX, LV_STATE_USER_1); } InputMixButtonBase::~InputMixButtonBase() @@ -89,7 +91,12 @@ InputMixButtonBase::~InputMixButtonBase() void InputMixButtonBase::setWeight(gvar_t value, gvar_t min, gvar_t max) { char s[32]; - getValueOrGVarString(s, sizeof(s), value, min, max, 0, "%"); + getValueOrSrcVarString(s, sizeof(s), value, min, max, 0, "%"); + if (getTextWidth(s, 0, FONT(STD)) > WGT_W) + lv_obj_add_state(weight, LV_STATE_USER_1); + else + lv_obj_clear_state(weight, LV_STATE_USER_1); + lv_label_set_text(weight, s); } @@ -99,6 +106,16 @@ void InputMixButtonBase::setSource(mixsrc_t idx) lv_label_set_text(source, s); } +void InputMixButtonBase::setOpts(const char* s) +{ + if (getTextWidth(s, 0, FONT(STD)) > OPT_W) + lv_obj_add_state(opts, LV_STATE_USER_1); + else + lv_obj_clear_state(opts, LV_STATE_USER_1); + + lv_label_set_text(opts, s); +} + void InputMixButtonBase::setFlightModes(uint16_t modes) { if (!modelFMEnabled()) return; diff --git a/radio/src/gui/colorlcd/list_line_button.h b/radio/src/gui/colorlcd/list_line_button.h index fab50457f..a7886e1bc 100644 --- a/radio/src/gui/colorlcd/list_line_button.h +++ b/radio/src/gui/colorlcd/list_line_button.h @@ -54,6 +54,7 @@ class InputMixButtonBase : public ListLineButton void setWeight(gvar_t value, gvar_t min, gvar_t max); void setSource(mixsrc_t idx); + void setOpts(const char* s); void setFlightModes(uint16_t modes); virtual void updatePos(coord_t x, coord_t y) = 0; @@ -66,7 +67,7 @@ class InputMixButtonBase : public ListLineButton static LAYOUT_VAL(BTN_W, 389, 229) static constexpr coord_t WGT_X = PAD_TINY; static constexpr coord_t WGT_Y = PAD_TINY; - static LAYOUT_VAL(WGT_W, 43, 43) + static LAYOUT_VAL(WGT_W, 50, 50) static LAYOUT_VAL(WGT_H, 21, 21) static constexpr coord_t SRC_X = WGT_X + WGT_W + PAD_TINY; static constexpr coord_t SRC_Y = WGT_Y; @@ -74,7 +75,7 @@ class InputMixButtonBase : public ListLineButton static constexpr coord_t SRC_H = WGT_H; static constexpr coord_t OPT_X = SRC_X + SRC_W + PAD_TINY; static constexpr coord_t OPT_Y = WGT_Y; - static LAYOUT_VAL(OPT_W, 171, 106) + static LAYOUT_VAL(OPT_W, 164, 99) static constexpr coord_t OPT_H = WGT_H; static LAYOUT_VAL(LN_X, 73, 73) static LAYOUT_VAL(FM_X, (OPT_X + OPT_W + PAD_TINY), 12) diff --git a/radio/src/gui/colorlcd/mixer_edit.cpp b/radio/src/gui/colorlcd/mixer_edit.cpp index a64a26c11..d8071df6f 100644 --- a/radio/src/gui/colorlcd/mixer_edit.cpp +++ b/radio/src/gui/colorlcd/mixer_edit.cpp @@ -22,8 +22,9 @@ #include "mixer_edit.h" #include "channel_bar.h" -#include "curve_param.h" #include "gvar_numberedit.h" +#include "source_numberedit.h" +#include "curve_param.h" #include "mixer_edit_adv.h" #include "mixes.h" #include "opentx.h" @@ -108,14 +109,14 @@ void MixEditWindow::buildBody(Window *form) // Weight line = form->newLine(grid); new StaticText(line, rect_t{}, STR_WEIGHT); - auto gvar = new GVarNumberEdit(line, MIX_WEIGHT_MIN, MIX_WEIGHT_MAX, - GET_SET_DEFAULT(mix->weight)); - gvar->setSuffix("%"); + auto svar = new SourceNumberEdit(line, MIX_WEIGHT_MIN, MIX_WEIGHT_MAX, + GET_SET_DEFAULT(mix->weight), 0); + svar->setSuffix("%"); // Offset new StaticText(line, rect_t{}, STR_OFFSET); - gvar = new GVarNumberEdit(line, MIX_OFFSET_MIN, MIX_OFFSET_MAX, - GET_SET_DEFAULT(mix->offset)); + auto gvar = new SourceNumberEdit(line, MIX_OFFSET_MIN, MIX_OFFSET_MAX, + GET_SET_DEFAULT(mix->offset), 0); gvar->setSuffix("%"); // Switch @@ -126,7 +127,7 @@ void MixEditWindow::buildBody(Window *form) // Curve new StaticText(line, rect_t{}, STR_CURVE); - new CurveParam(line, rect_t{}, &mix->curve, SET_DEFAULT(mix->curve.value)); + new CurveParam(line, rect_t{}, &mix->curve, SET_DEFAULT(mix->curve.value), 0); line = form->newLine(grid); line->padAll(PAD_LARGE); diff --git a/radio/src/gui/colorlcd/model_inputs.cpp b/radio/src/gui/colorlcd/model_inputs.cpp index 4c1db5628..aa14d763a 100644 --- a/radio/src/gui/colorlcd/model_inputs.cpp +++ b/radio/src/gui/colorlcd/model_inputs.cpp @@ -129,29 +129,29 @@ class InputLineButton : public InputMixButtonBase } } - if (line.swtch || line.curve.value) { - if (line.swtch) { - char* sw_pos = getSwitchPositionName(line.swtch); - int cnt = lv_snprintf(s, maxlen, "%s ", sw_pos); - if ((size_t)cnt >= maxlen) - maxlen = 0; - else { - maxlen -= cnt; - s += cnt; - } - } - if (line.curve.value != 0) { - getCurveRefString(s, maxlen, line.curve); - int cnt = strnlen(s, maxlen); - if ((size_t)cnt >= maxlen) - maxlen = 0; - else { - maxlen -= cnt; - s += cnt; - } + if (line.swtch) { + char* sw_pos = getSwitchPositionName(line.swtch); + int cnt = lv_snprintf(s, maxlen, "%s ", sw_pos); + if ((size_t)cnt >= maxlen) + maxlen = 0; + else { + maxlen -= cnt; + s += cnt; } } - lv_label_set_text_fmt(opts, "%.*s", (int)sizeof(tmp_str), tmp_str); + + if (line.curve.value != 0) { + getCurveRefString(s, maxlen, line.curve); + int cnt = strnlen(s, maxlen); + if ((size_t)cnt >= maxlen) + maxlen = 0; + else { + maxlen -= cnt; + s += cnt; + } + } + + setOpts(s); setFlightModes(line.flightModes); } diff --git a/radio/src/gui/colorlcd/model_mixes.cpp b/radio/src/gui/colorlcd/model_mixes.cpp index 9b901df73..d4665132a 100644 --- a/radio/src/gui/colorlcd/model_mixes.cpp +++ b/radio/src/gui/colorlcd/model_mixes.cpp @@ -98,32 +98,25 @@ class MixLineButton : public InputMixButtonBase setSource(line.srcRaw); char tmp_str[64]; - size_t maxlen = sizeof(tmp_str); - char *s = tmp_str; *s = '\0'; if (line.name[0]) { - int cnt = lv_snprintf(s, maxlen, "%.*s ", (int)sizeof(line.name), line.name); - if ((size_t)cnt >= maxlen) maxlen = 0; - else { maxlen -= cnt; s += cnt; } + s = strAppend(s, line.name, LEN_EXPOMIX_NAME); } - if (line.swtch || line.curve.value) { - if (line.swtch) { - char* sw_pos = getSwitchPositionName(line.swtch); - int cnt = lv_snprintf(s, maxlen, "%s ", sw_pos); - if ((size_t)cnt >= maxlen) maxlen = 0; - else { maxlen -= cnt; s += cnt; } - } - if (line.curve.value != 0) { - getCurveRefString(s, maxlen, line.curve); - int cnt = strnlen(s, maxlen); - if ((size_t)cnt >= maxlen) maxlen = 0; - else { maxlen -= cnt; s += cnt; } - } + if (line.swtch) { + if (tmp_str[0]) s = strAppend(s, " "); + char* sw_pos = getSwitchPositionName(line.swtch); + s = strAppend(s, sw_pos); } - lv_label_set_text_fmt(opts, "%.*s", (int)sizeof(tmp_str), tmp_str); + + if (line.curve.value != 0) { + if (tmp_str[0]) s = strAppend(s, " "); + getCurveRefString(s, sizeof(tmp_str) - (s - tmp_str), line.curve); + } + + setOpts(tmp_str); mplex->refresh(); diff --git a/radio/src/gui/colorlcd/source_numberedit.cpp b/radio/src/gui/colorlcd/source_numberedit.cpp new file mode 100644 index 000000000..dd3aec81b --- /dev/null +++ b/radio/src/gui/colorlcd/source_numberedit.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "source_numberedit.h" + +#include "opentx.h" +#include "sourcechoice.h" + +void SourceNumberEdit::value_changed(lv_event_t* e) +{ + auto obj = lv_event_get_target(e); + auto edit = (SourceNumberEdit*)lv_obj_get_user_data(obj); + if (!edit) return; + + edit->update(); +} + +SourceNumberEdit::SourceNumberEdit(Window* parent, + int32_t vmin, int32_t vmax, + std::function getValue, + std::function setValue, + int16_t sourceMin, + LcdFlags textFlags, int32_t voffset, + int32_t vdefault) : + Window(parent, {0, 0, NUM_EDIT_W + SRC_BTN_W + PAD_TINY * 3, EdgeTxStyles::UI_ELEMENT_HEIGHT + PAD_TINY * 2}), + vmin(vmin), + vmax(vmax), + getValue(getValue), + setValue(setValue), + textFlags(textFlags), + voffset(voffset) +{ + padAll(PAD_TINY); + lv_obj_set_flex_flow(lvobj, LV_FLEX_FLOW_ROW_WRAP); + lv_obj_set_style_flex_cross_place(lvobj, LV_FLEX_ALIGN_CENTER, 0); + lv_obj_set_size(lvobj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + + // Source field + source_field = new SourceChoice( + this, {0, 0, NUM_EDIT_W, 0}, sourceMin, INPUTSRC_LAST, + [=]() { + SourceNumVal v; + v.rawValue = getValue(); + return v.value; + }, + [=](int newValue) { + SourceNumVal v = {(int16_t)newValue, true}; + setValue(v.rawValue); + }, true); + + num_field = new NumberEdit( + this, {0, 0, NUM_EDIT_W, 0}, vmin, vmax, + [=]() { + SourceNumVal v; + v.rawValue = getValue(); + return v.value; + }, + [=](int newValue) { + SourceNumVal v = {(int16_t)newValue, false}; + setValue(v.rawValue); + }, + textFlags); + num_field->setDefault(vdefault); + + // The Source button + m_srcBtn = new TextButton(this, {NUM_EDIT_W + PAD_TINY, 0, SRC_BTN_W, 0}, "SRC", [=]() { + switchSourceMode(); + return isSource(); + }); + m_srcBtn->check(isSource()); + + lv_obj_add_event_cb(lvobj, SourceNumberEdit::value_changed, + LV_EVENT_VALUE_CHANGED, nullptr); + + // update field type based on value + update(); +} + +bool SourceNumberEdit::isSource() +{ + SourceNumVal v; + v.rawValue = getValue(); + return v.isSource; +} + +void SourceNumberEdit::switchSourceMode() +{ + SourceNumVal v; + v.rawValue = getValue(); + v.isSource = !v.isSource; + // TODO: convert value??? + v.value = 0; + setValue(v.rawValue); + + // update field type based on value + update(); +} + +void SourceNumberEdit::setSuffix(std::string value) +{ + num_field->setSuffix(value); +} + +void SourceNumberEdit::update() +{ + bool has_focus = act_field && act_field->hasFocus(); + + source_field->hide(); + num_field->hide(); + + if (isSource()) { + // Source mode + act_field = source_field; + source_field->show(); + source_field->update(); + lv_event_send(source_field->getLvObj(), LV_EVENT_VALUE_CHANGED, nullptr); + } else { + // number edit mode + act_field = num_field; + num_field->show(); + num_field->update(); + } + + m_srcBtn->check(isSource()); + + if (has_focus) { + lv_group_focus_obj(act_field->getLvObj()); + } +} diff --git a/radio/src/gui/colorlcd/source_numberedit.h b/radio/src/gui/colorlcd/source_numberedit.h new file mode 100644 index 000000000..1f3322297 --- /dev/null +++ b/radio/src/gui/colorlcd/source_numberedit.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#include "choice.h" +#include "form.h" +#include "numberedit.h" + +class TextButton; + +class SourceNumberEdit : public Window +{ + public: + SourceNumberEdit(Window* parent, int32_t vmin, int32_t vmax, + std::function getValue, + std::function setValue, + int16_t sourceMin, + LcdFlags textFlags = 0, int32_t voffset = 0, + int32_t vdefault = 0); + + void switchSourceMode(); + void setSuffix(std::string value); + + void setFastStep(int value) { num_field->setFastStep(value); } + void setAccelFactor(int value) { num_field->setAccelFactor(value); } + + void update(); + + static LAYOUT_VAL(NUM_EDIT_W, 84, 74) + static LAYOUT_VAL(SRC_BTN_W, 38, 38) + + protected: + Choice* source_field = nullptr; + NumberEdit* num_field = nullptr; + FormField* act_field = nullptr; + TextButton* m_srcBtn = nullptr; + + int32_t vmin; + int32_t vmax; + std::function getValue; + std::function setValue; + LcdFlags textFlags; + int32_t voffset; + + bool isSource(); + + static void value_changed(lv_event_t* e); +}; diff --git a/radio/src/gui/common/stdlcd/draw_functions.cpp b/radio/src/gui/common/stdlcd/draw_functions.cpp index 1ad92e099..02181f23f 100644 --- a/radio/src/gui/common/stdlcd/draw_functions.cpp +++ b/radio/src/gui/common/stdlcd/draw_functions.cpp @@ -292,14 +292,6 @@ void editName(coord_t x, coord_t y, char* name, uint8_t size, event_t event, } } -void gvarWeightItem(coord_t x, coord_t y, MixData * md, LcdFlags attr, event_t event) -{ - u_int8int16_t weight; - MD_WEIGHT_TO_UNION(md, weight); - weight.word = GVAR_MENU_ITEM(x, y, weight.word, MIX_WEIGHT_MIN, MIX_WEIGHT_MAX, attr, 0, event); - MD_UNION_TO_WEIGHT(weight, md); -} - void drawGVarName(coord_t x, coord_t y, int8_t idx, LcdFlags flags) { char s[8]; @@ -405,12 +397,12 @@ void drawCurveRef(coord_t x, coord_t y, CurveRef & curve, LcdFlags att) switch (curve.type) { case CURVE_REF_DIFF: lcdDrawText(x, y, "D", att); - GVAR_MENU_ITEM(lcdNextPos, y, curve.value, -100, 100, LEFT|att, 0, 0); + editSrcVarFieldValue(lcdNextPos, y, nullptr, curve.value, -100, 100, LEFT|att, 0, 0, 0); break; case CURVE_REF_EXPO: lcdDrawText(x, y, "E", att); - GVAR_MENU_ITEM(lcdNextPos, y, curve.value, -100, 100, LEFT|att, 0, 0); + editSrcVarFieldValue(lcdNextPos, y, nullptr, curve.value, -100, 100, LEFT|att, 0, 0, 0); break; case CURVE_REF_FUNC: @@ -543,3 +535,88 @@ void runFatalErrorScreen(const char * message) } } } + +void drawSource(coord_t x, coord_t y, mixsrc_t idx, LcdFlags att) +{ + uint16_t aidx = abs(idx); + bool inverted = idx < 0; + + if (aidx == MIXSRC_NONE) { + lcdDrawText(x, y, STR_EMPTY, att); + } + else if (aidx <= MIXSRC_LAST_INPUT) { + if (att & RIGHT) { + if (g_model.inputNames[aidx-MIXSRC_FIRST_INPUT][0]) + lcdDrawSizedText(x, y, g_model.inputNames[aidx-MIXSRC_FIRST_INPUT], LEN_INPUT_NAME, att); + else + lcdDrawNumber(x, y, aidx, att|LEADING0, 2); + x = lcdLastLeftPos - 5; + if (inverted) + lcdDrawChar(x-5, y, '-'); + lcdDrawChar(x, y+1, CHR_INPUT, RIGHT|TINSIZE); + lcdDrawSolidFilledRect(x-1, y, 5, 7); + } else { + if (inverted) { + lcdDrawChar(x-1, y, '-'); + x += 3; + } + lcdDrawChar(x+1, y+1, CHR_INPUT, TINSIZE); + lcdDrawSolidFilledRect(x, y, 5, 7); + if (g_model.inputNames[aidx-MIXSRC_FIRST_INPUT][0]) + lcdDrawSizedText(x+6, y, g_model.inputNames[aidx-MIXSRC_FIRST_INPUT], LEN_INPUT_NAME, att); + else + lcdDrawNumber(x+6, y, aidx, att|LEADING0, 2); + } + } +#if defined(LUA_INPUTS) + else if (aidx <= MIXSRC_LAST_LUA) { + div_t qr = div((uint16_t)(aidx-MIXSRC_FIRST_LUA), MAX_SCRIPT_OUTPUTS); + if (att & RIGHT) { +#if defined(LUA_MODEL_SCRIPTS) + if (qr.quot < MAX_SCRIPTS && qr.rem < scriptInputsOutputs[qr.quot].outputsCount) { + lcdDrawSizedText(x, y, scriptInputsOutputs[qr.quot].outputs[qr.rem].name, att & STREXPANDED ? 9 : 4, att); + x = lcdLastLeftPos - 4; + if (inverted) + lcdDrawChar(x-5, y, '-'); + lcdDrawChar(x, y+1, '1'+qr.quot, TINSIZE); + lcdDrawFilledRect(x-1, y, 5, 7, SOLID); + } + else +#endif + { + lcdDrawChar(x, y, 'a' + qr.rem, att); + drawStringWithIndex(lcdLastLeftPos, y, "LUA", qr.quot+1, att); +#if defined(LUA_MODEL_SCRIPTS) + if (inverted) + lcdDrawChar(lcdLastLeftPos, y, '-', att); +#endif + } + } else { +#if defined(LUA_MODEL_SCRIPTS) + if (inverted) { + lcdDrawChar(x-1, y, '-'); + x += 3; + } + if (qr.quot < MAX_SCRIPTS && qr.rem < scriptInputsOutputs[qr.quot].outputsCount) { + lcdDrawChar(x+1, y+1, '1'+qr.quot, TINSIZE); + lcdDrawFilledRect(x, y, 5, 7, SOLID); + lcdDrawSizedText(x+5, y, scriptInputsOutputs[qr.quot].outputs[qr.rem].name, att & STREXPANDED ? 9 : 4, att); + } + else +#endif + { + drawStringWithIndex(x, y, "LUA", qr.quot+1, att); + lcdDrawChar(lcdLastRightPos, y, 'a' + qr.rem, att); + } + } + } +#endif + else { + const char* s = getSourceString(idx); +#if LCD_W < 212 + if (idx >= MIXSRC_FIRST_TELEM && idx <= MIXSRC_LAST_TELEM) + s += strlen(STR_CHAR_TELEMETRY); +#endif + lcdDrawText(x, y, s, att); + } +} diff --git a/radio/src/gui/common/stdlcd/draw_functions.h b/radio/src/gui/common/stdlcd/draw_functions.h index d0c15f09f..0f22d8548 100644 --- a/radio/src/gui/common/stdlcd/draw_functions.h +++ b/radio/src/gui/common/stdlcd/draw_functions.h @@ -19,8 +19,7 @@ * GNU General Public License for more details. */ -#ifndef _STDLCD_DRAW_FUNCTIONS_H_ -#define _STDLCD_DRAW_FUNCTIONS_H_ +#pragma once #include "lcd.h" void lcdDrawMultiProtocolString(coord_t x, coord_t y, uint8_t moduleIdx, uint8_t protocol, LcdFlags flags = 0); @@ -55,4 +54,4 @@ void drawFunction(FnFuncP fn, uint8_t offset = 0); void drawCursor(FnFuncP fn, uint8_t offset = 0); void drawCurve(coord_t offset = 0); -#endif // _STDLCD_DRAW_FUNCTIONS_H_ +void drawSource(coord_t x, coord_t y, mixsrc_t idx, LcdFlags att=0); diff --git a/radio/src/gui/common/stdlcd/model_curves.cpp b/radio/src/gui/common/stdlcd/model_curves.cpp index b0ea6998d..46812b981 100644 --- a/radio/src/gui/common/stdlcd/model_curves.cpp +++ b/radio/src/gui/common/stdlcd/model_curves.cpp @@ -96,7 +96,8 @@ void menuModelCurvesAll(event_t event) } } -void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlags flags) +void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlags flags, + IsValueAvailable isValueAvailable, int16_t sourceMin) { coord_t x1 = x; LcdFlags flags1 = flags; @@ -126,24 +127,36 @@ void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlag switch (curve.type) { case CURVE_REF_DIFF: case CURVE_REF_EXPO: - curve.value = GVAR_MENU_ITEM(x, y, curve.value, -100, 100, LEFT | flags, 0, event); + curve.value = editSrcVarFieldValue(x, y, nullptr, curve.value, -100, 100, flags, event, isValueAvailable, sourceMin); break; case CURVE_REF_FUNC: - lcdDrawTextAtIndex(x, y, STR_VCURVEFUNC, curve.value, flags); - if (active && menuHorizontalPosition==1) CHECK_INCDEC_MODELVAR_ZERO(event, curve.value, CURVE_BASE-1); + { + SourceNumVal v; + v.rawValue = curve.value; + lcdDrawTextAtIndex(x, y, STR_VCURVEFUNC, v.value, flags); + if (active && menuHorizontalPosition==1) { + CHECK_INCDEC_MODELVAR_ZERO(event, v.value, CURVE_BASE-1); + curve.value = v.rawValue; + } break; + } case CURVE_REF_CUSTOM: - drawCurveName(x, y, curve.value, flags); + { + SourceNumVal v; + v.rawValue = curve.value; + drawCurveName(x, y, v.value, flags); if (active && menuHorizontalPosition == 1) { - if (event == EVT_KEY_LONG(KEY_ENTER) && curve.value != 0) { + if (event == EVT_KEY_LONG(KEY_ENTER) && v.value != 0) { s_currIdxSubMenu = abs(curve.value) - 1; pushMenu(menuModelCurveOne); } else { - CHECK_INCDEC_MODELVAR(event, curve.value, -MAX_CURVES, MAX_CURVES); + CHECK_INCDEC_MODELVAR(event, v.value, -MAX_CURVES, MAX_CURVES); + curve.value = v.rawValue; } } break; + } } } diff --git a/radio/src/gui/common/stdlcd/model_inputs.cpp b/radio/src/gui/common/stdlcd/model_inputs.cpp index 86b2cd16d..e5416e084 100644 --- a/radio/src/gui/common/stdlcd/model_inputs.cpp +++ b/radio/src/gui/common/stdlcd/model_inputs.cpp @@ -391,7 +391,7 @@ void menuModelExposAll(event_t event) coord_t y = MENU_HEADER_HEIGHT+1+(cur-menuVerticalOffset)*FH; if (ichn+1 == ch && EXPO_VALID(ed)) { if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { - drawSource(0, y, ch, 0); + drawSource(0, y, ch, ((s_copyMode || sub != cur) ? 0 : INVERS)); } uint8_t mixCnt = 0; do { @@ -410,10 +410,10 @@ void menuModelExposAll(event_t event) s_currIdx = i; } if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { - LcdFlags attr = ((s_copyMode || sub != cur) ? 0 : INVERS); - - GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, -100, 100, RIGHT | attr | (isExpoActive(i) ? BOLD : 0), 0, 0); - displayExpoLine(y, ed, attr); + editSrcVarFieldValue(EXPO_LINE_WEIGHT_POS, y, nullptr, ed->weight, + -100, 100, RIGHT | (isExpoActive(i) ? BOLD : 0), + 0, 0, 0); + displayExpoLine(y, ed, 0); if (s_copyMode) { if ((s_copyMode==COPY_MODE || s_copyTgtOfs == 0) && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { @@ -422,11 +422,14 @@ void menuModelExposAll(event_t event) } if (cur == sub) { /* invert the raw when it's the current one */ - lcdDrawSolidFilledRect(EXPO_LINE_SELECT_POS+1, y, LCD_W-EXPO_LINE_SELECT_POS-2, 7); + lcdDrawSolidFilledRect(0, y, LCD_W, 7); } } } cur++; y+=FH; mixCnt++; i++; ed++; + if (sub == cur && ed->chn+1 == ch) { + lcdDrawText(INDENT_WIDTH, y, "->", ((s_copyMode || sub != cur) ? 0 : INVERS)); + } } while (ichn+1 == ch && EXPO_VALID(ed)); if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { lcdDrawRect(EXPO_LINE_SELECT_POS, y-1, LCD_W-EXPO_LINE_SELECT_POS, 9, DOTTED); diff --git a/radio/src/gui/common/stdlcd/model_mixes.cpp b/radio/src/gui/common/stdlcd/model_mixes.cpp index 826cb8a80..23315854b 100644 --- a/radio/src/gui/common/stdlcd/model_mixes.cpp +++ b/radio/src/gui/common/stdlcd/model_mixes.cpp @@ -307,7 +307,7 @@ void menuModelMixAll(event_t event) MixData * md = mixAddress(i); if (i < getMixCount() && (md->destCh + 1 == ch)) { if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { - putsChn(0, y, ch, 0); // show CHx + putsChn(0, y, ch, ((s_copyMode || sub != cur) ? 0 : INVERS)); // show CHx } uint8_t mixCnt = 0; do { @@ -326,17 +326,17 @@ void menuModelMixAll(event_t event) s_currIdx = i; } if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { - LcdFlags attr = ((s_copyMode || sub != cur) ? 0 : INVERS); - - if (mixCnt > 0) lcdDrawTextAtIndex(FW, y, STR_VMLTPX2, md->mltpx, 0); + if (mixCnt > 0) lcdDrawTextAtIndex(FW, y, STR_VMLTPX2, md->mltpx, ((s_copyMode || sub != cur) ? 0 : INVERS)); drawSource(MIX_LINE_SRC_POS, y, md->srcRaw, 0); if (mixCnt == 0 && md->mltpx == 1) { - lcdDrawText(MIX_LINE_WEIGHT_POS, y, "MULT!", RIGHT | attr | (isMixActive(i) ? BOLD : 0)); + lcdDrawText(MIX_LINE_WEIGHT_POS, y, "MULT!", RIGHT | ((isMixActive(i) ? BOLD : 0))); } else { - gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, RIGHT | attr | (isMixActive(i) ? BOLD : 0), 0); + editSrcVarFieldValue(MIX_LINE_WEIGHT_POS, y, nullptr, md->weight, + MIX_WEIGHT_MIN, MIX_WEIGHT_MAX, RIGHT | ((isMixActive(i) ? BOLD : 0)), + 0, 0, 0); } #if LCD_W >= 212 @@ -352,7 +352,7 @@ void menuModelMixAll(event_t event) } if (cur == sub) { /* invert the raw when it's the current one */ - lcdDrawSolidFilledRect(23, y, LCD_W-24, 7); + lcdDrawSolidFilledRect(0, y, LCD_W, 7); } } } diff --git a/radio/src/gui/navigation/common.cpp b/radio/src/gui/navigation/common.cpp index f40b5eb16..38147b507 100644 --- a/radio/src/gui/navigation/common.cpp +++ b/radio/src/gui/navigation/common.cpp @@ -117,6 +117,8 @@ void onSourceLongEnterPress(const char * result) } } else if (result == STR_MENU_INVERT) { checkIncDecSelection = MIXSRC_INVERT; + } else if (result == STR_CONSTANT) { + checkIncDecSelection = MIXSRC_VALUE; } } diff --git a/radio/src/gui/navigation/navigation.h b/radio/src/gui/navigation/navigation.h index 07ee6b15b..8d4004f38 100644 --- a/radio/src/gui/navigation/navigation.h +++ b/radio/src/gui/navigation/navigation.h @@ -74,6 +74,8 @@ extern int8_t s_editMode; // global editmode #define INCDEC_REP10 0x40 #define NO_DBLKEYS 0x80 #define INCDEC_SOURCE_INVERT 0x100 +#define INCDEC_SOURCE_VALUE 0x200 // Field can be source or value +#define INCDEC_SOURCE_NOINPUTS 0x400 // Do not allow Inputs in source selection int checkIncDec(event_t event, int val, int i_min, int i_max, unsigned int i_flags = 0, IsValueAvailable isValueAvailable = nullptr, diff --git a/radio/src/gui/navigation/navigation_9x.cpp b/radio/src/gui/navigation/navigation_9x.cpp index df3f8b808..521f1a2c6 100644 --- a/radio/src/gui/navigation/navigation_9x.cpp +++ b/radio/src/gui/navigation/navigation_9x.cpp @@ -51,7 +51,26 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, { int newval = val; + bool isSource = false; + bool origIsSource = false; + if (i_flags & INCDEC_SOURCE_VALUE) { + SourceNumVal v; + v.rawValue = val; + // Save isSource flag; + origIsSource = isSource = v.isSource; + // Remove isSource flag; + val = v.value; + newval = v.value; + } + 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_UP) || event == EVT_KEY_REPT(KEY_UP) || event == EVT_KEY_FIRST(KEY_RIGHT) || event == EVT_KEY_REPT(KEY_RIGHT)) { do { @@ -94,10 +113,17 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, #endif #if defined(AUTOSOURCE) - if (i_flags & INCDEC_SOURCE) { - int8_t source = GET_MOVED_SOURCE(i_min, i_max); + if (i_flags & (INCDEC_SOURCE|INCDEC_SOURCE_VALUE)) { + int source = GET_MOVED_SOURCE(i_min, i_max); if (source) { - newval = source; + if (i_flags & INCDEC_SOURCE_VALUE) { + if (isSource) { + // Only use moved source if already a source value + newval = source; + } + } else { + newval = source; + } } #if defined(AUTOSWITCH) else { @@ -109,6 +135,11 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, #endif } #endif + + if (invert) { + newval = -newval; + val = -val; + } } if (i_min == 0 && i_max == 1 && @@ -117,6 +148,75 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, newval = !val; } + if (i_flags & (INCDEC_SOURCE | INCDEC_SOURCE_VALUE)) { + if (event == EVT_KEY_LONG(KEY_ENTER)) { + checkIncDecSelection = MIXSRC_NONE; + + if (i_flags & INCDEC_SOURCE_VALUE && isSource) { + POPUP_MENU_ADD_ITEM(STR_CONSTANT); + } + + if (i_min <= MIXSRC_FIRST_INPUT && i_max >= MIXSRC_FIRST_INPUT) { + if (getFirstAvailable(MIXSRC_FIRST_INPUT, MIXSRC_LAST_INPUT, isInputAvailable) != MIXSRC_NONE && + (i_flags & INCDEC_SOURCE_NOINPUTS) == 0) { + POPUP_MENU_ADD_ITEM(STR_MENU_INPUTS); + } + } +#if defined(LUA_MODEL_SCRIPTS) + if (i_min <= MIXSRC_FIRST_LUA && i_max >= MIXSRC_FIRST_LUA) { + if (getFirstAvailable(MIXSRC_FIRST_LUA, MIXSRC_LAST_LUA, isSourceAvailable) != MIXSRC_NONE) { + POPUP_MENU_ADD_ITEM(STR_MENU_LUA); + } + } +#endif + if (i_min <= MIXSRC_FIRST_STICK && i_max >= MIXSRC_FIRST_STICK) POPUP_MENU_ADD_ITEM(STR_MENU_STICKS); + if (i_min <= MIXSRC_FIRST_POT && i_max >= MIXSRC_FIRST_POT) POPUP_MENU_ADD_ITEM(STR_MENU_POTS); + if (i_min <= MIXSRC_MIN && i_max >= MIXSRC_MIN) POPUP_MENU_ADD_ITEM(STR_MENU_MIN); + if (i_min <= MIXSRC_MAX && i_max >= MIXSRC_MAX) POPUP_MENU_ADD_ITEM(STR_MENU_MAX); +#if defined(HELI) + if (modelHeliEnabled()) + if (i_min <= MIXSRC_FIRST_HELI && i_max >= MIXSRC_FIRST_HELI && isValueAvailable && isValueAvailable(MIXSRC_FIRST_HELI)) + POPUP_MENU_ADD_ITEM(STR_MENU_HELI); +#endif + if (i_min <= MIXSRC_FIRST_TRIM && i_max >= MIXSRC_FIRST_TRIM) POPUP_MENU_ADD_ITEM(STR_MENU_TRIMS); + if (i_min <= MIXSRC_FIRST_SWITCH && i_max >= MIXSRC_FIRST_SWITCH) POPUP_MENU_ADD_ITEM(STR_MENU_SWITCHES); + if (i_min <= MIXSRC_FIRST_TRAINER && i_max >= MIXSRC_FIRST_TRAINER) POPUP_MENU_ADD_ITEM(STR_MENU_TRAINER); + if (i_min <= MIXSRC_FIRST_CH && i_max >= MIXSRC_FIRST_CH) POPUP_MENU_ADD_ITEM(STR_MENU_CHANNELS); + if (i_min <= MIXSRC_FIRST_GVAR && i_max >= MIXSRC_FIRST_GVAR && isValueAvailable && isValueAvailable(MIXSRC_FIRST_GVAR)) { + POPUP_MENU_ADD_ITEM(STR_MENU_GVARS); + } + + if (modelTelemetryEnabled() && i_min <= MIXSRC_FIRST_TELEM && i_max >= MIXSRC_FIRST_TELEM) { + for (int i = 0; i < MAX_TELEMETRY_SENSORS; i++) { + TelemetrySensor * sensor = & g_model.telemetrySensors[i]; + if (sensor->isAvailable()) { + POPUP_MENU_ADD_ITEM(STR_MENU_TELEMETRY); + break; + } + } + } + if (i_flags & INCDEC_SOURCE_INVERT) POPUP_MENU_ADD_ITEM(STR_MENU_INVERT); + POPUP_MENU_START(onSourceLongEnterPress); + } + if (checkIncDecSelection != 0) { + if (i_flags & INCDEC_SOURCE_VALUE) { + if (checkIncDecSelection == MIXSRC_VALUE) { + newval = 0; + isSource = false; + } else { + newval = (checkIncDecSelection == MIXSRC_INVERT ? -newval : checkIncDecSelection); + if (checkIncDecSelection != MIXSRC_INVERT) + isSource = true; + } + } else { + newval = (checkIncDecSelection == MIXSRC_INVERT ? -newval : checkIncDecSelection); + } + if (checkIncDecSelection != MIXSRC_MIN && checkIncDecSelection != MIXSRC_MAX) + s_editMode = EDIT_MODIFY_FIELD; + checkIncDecSelection = 0; + } + } + if (newval != val) { if (!(i_flags & NO_INCDEC_MARKS) && (newval != i_max) && (newval != i_min) && stops.contains(newval)) { @@ -136,6 +236,13 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, checkIncDec_Ret = 0; } + if (i_flags & INCDEC_SOURCE_VALUE) { + SourceNumVal v; + v.isSource = isSource; + v.value = newval; + newval = v.rawValue; + } + return newval; } diff --git a/radio/src/gui/navigation/navigation_x7.cpp b/radio/src/gui/navigation/navigation_x7.cpp index 95c128dbe..07f63eb30 100644 --- a/radio/src/gui/navigation/navigation_x7.cpp +++ b/radio/src/gui/navigation/navigation_x7.cpp @@ -60,6 +60,18 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, } #endif + bool isSource = false; + bool origIsSource = false; + if (i_flags & INCDEC_SOURCE_VALUE) { + SourceNumVal v; + v.rawValue = val; + // Save isSource flag; + origIsSource = isSource = v.isSource; + // Remove isSource flag; + val = v.value; + newval = v.value; + } + if (s_editMode > 0) { bool invert = false; if ((i_flags & INCDEC_SOURCE_INVERT) && (newval < 0)) { @@ -111,10 +123,17 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, #endif #if defined(AUTOSOURCE) - if (i_flags & INCDEC_SOURCE) { + if (i_flags & (INCDEC_SOURCE|INCDEC_SOURCE_VALUE)) { int source = GET_MOVED_SOURCE(i_min, i_max); if (source) { - newval = source; + if (i_flags & INCDEC_SOURCE_VALUE) { + if (isSource) { + // Only use moved source if already a source value + newval = source; + } + } else { + newval = source; + } } #if defined(AUTOSWITCH) else { @@ -139,18 +158,24 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, newval = !val; } - if (i_flags & INCDEC_SOURCE) { + if (i_flags & (INCDEC_SOURCE | INCDEC_SOURCE_VALUE)) { if (event == EVT_KEY_LONG(KEY_ENTER)) { checkIncDecSelection = MIXSRC_NONE; + if (i_flags & INCDEC_SOURCE_VALUE && isSource) { + POPUP_MENU_ADD_ITEM(STR_CONSTANT); + } + if (i_min <= MIXSRC_FIRST_INPUT && i_max >= MIXSRC_FIRST_INPUT) { - if (getFirstAvailable(MIXSRC_FIRST_INPUT, MIXSRC_LAST_INPUT, isInputAvailable) != MIXSRC_NONE) { + if (getFirstAvailable(MIXSRC_FIRST_INPUT, MIXSRC_LAST_INPUT, isInputAvailable) != MIXSRC_NONE && + (i_flags & INCDEC_SOURCE_NOINPUTS) == 0) { POPUP_MENU_ADD_ITEM(STR_MENU_INPUTS); } } #if defined(LUA_MODEL_SCRIPTS) if (i_min <= MIXSRC_FIRST_LUA && i_max >= MIXSRC_FIRST_LUA) { - if (getFirstAvailable(MIXSRC_FIRST_LUA, MIXSRC_LAST_LUA, isSourceAvailable) != MIXSRC_NONE) { + if (getFirstAvailable(MIXSRC_FIRST_LUA, MIXSRC_LAST_LUA, isSourceAvailable) != MIXSRC_NONE && + (i_flags & INCDEC_SOURCE_NOINPUTS) == 0) { POPUP_MENU_ADD_ITEM(STR_MENU_LUA); } } @@ -185,7 +210,18 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, POPUP_MENU_START(onSourceLongEnterPress); } if (checkIncDecSelection != 0) { - newval = (checkIncDecSelection == MIXSRC_INVERT ? -newval : checkIncDecSelection); + if (i_flags & INCDEC_SOURCE_VALUE) { + if (checkIncDecSelection == MIXSRC_VALUE) { + newval = 0; + isSource = false; + } else { + newval = (checkIncDecSelection == MIXSRC_INVERT ? -newval : checkIncDecSelection); + if (checkIncDecSelection != MIXSRC_INVERT) + isSource = true; + } + } else { + newval = (checkIncDecSelection == MIXSRC_INVERT ? -newval : checkIncDecSelection); + } if (checkIncDecSelection != MIXSRC_MIN && checkIncDecSelection != MIXSRC_MAX) s_editMode = EDIT_MODIFY_FIELD; checkIncDecSelection = 0; @@ -216,7 +252,7 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, } } - if (newval != val) { + if (newval != val || isSource != origIsSource) { storageDirty(i_flags & (EE_GENERAL|EE_MODEL)); checkIncDec_Ret = (newval > val ? 1 : -1); } @@ -224,6 +260,13 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, checkIncDec_Ret = 0; } + if (i_flags & INCDEC_SOURCE_VALUE) { + SourceNumVal v; + v.isSource = isSource; + v.value = newval; + newval = v.rawValue; + } + return newval; } diff --git a/radio/src/gui/navigation/navigation_x9d.cpp b/radio/src/gui/navigation/navigation_x9d.cpp index 2be7accb2..9d52a6abc 100644 --- a/radio/src/gui/navigation/navigation_x9d.cpp +++ b/radio/src/gui/navigation/navigation_x9d.cpp @@ -60,6 +60,18 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, } #endif + bool isSource = false; + bool origIsSource = false; + if (i_flags & INCDEC_SOURCE_VALUE) { + SourceNumVal v; + v.rawValue = val; + // Save isSource flag; + origIsSource = isSource = v.isSource; + // Remove isSource flag; + val = v.value; + newval = v.value; + } + if (s_editMode > 0) { bool invert = false; if ((i_flags & INCDEC_SOURCE_INVERT) && (newval < 0)) { @@ -111,10 +123,17 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, #endif #if defined(AUTOSOURCE) - if (i_flags & INCDEC_SOURCE) { + if (i_flags & (INCDEC_SOURCE|INCDEC_SOURCE_VALUE)) { int source = GET_MOVED_SOURCE(i_min, i_max); if (source) { - newval = source; + if (i_flags & INCDEC_SOURCE_VALUE) { + if (isSource) { + // Only use moved source if already a source value + newval = source; + } + } else { + newval = source; + } } #if defined(AUTOSWITCH) else { @@ -139,12 +158,17 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, newval = !val; } - if (i_flags & INCDEC_SOURCE) { + if (i_flags & (INCDEC_SOURCE | INCDEC_SOURCE_VALUE)) { if (event == EVT_KEY_LONG(KEY_ENTER)) { checkIncDecSelection = MIXSRC_NONE; + if (i_flags & INCDEC_SOURCE_VALUE && isSource) { + POPUP_MENU_ADD_ITEM(STR_CONSTANT); + } + if (i_min <= MIXSRC_FIRST_INPUT && i_max >= MIXSRC_FIRST_INPUT) { - if (getFirstAvailable(MIXSRC_FIRST_INPUT, MIXSRC_LAST_INPUT, isInputAvailable) != MIXSRC_NONE) { + if (getFirstAvailable(MIXSRC_FIRST_INPUT, MIXSRC_LAST_INPUT, isInputAvailable) != MIXSRC_NONE && + (i_flags & INCDEC_SOURCE_NOINPUTS) == 0) { POPUP_MENU_ADD_ITEM(STR_MENU_INPUTS); } } @@ -185,7 +209,18 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, POPUP_MENU_START(onSourceLongEnterPress); } if (checkIncDecSelection != 0) { - newval = (checkIncDecSelection == MIXSRC_INVERT ? -newval : checkIncDecSelection); + if (i_flags & INCDEC_SOURCE_VALUE) { + if (checkIncDecSelection == MIXSRC_VALUE) { + newval = 0; + isSource = false; + } else { + newval = (checkIncDecSelection == MIXSRC_INVERT ? -newval : checkIncDecSelection); + if (checkIncDecSelection != MIXSRC_INVERT) + isSource = true; + } + } else { + newval = (checkIncDecSelection == MIXSRC_INVERT ? -newval : checkIncDecSelection); + } if (checkIncDecSelection != MIXSRC_MIN && checkIncDecSelection != MIXSRC_MAX) s_editMode = EDIT_MODIFY_FIELD; checkIncDecSelection = 0; @@ -258,6 +293,13 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, checkIncDec_Ret = 0; } + if (i_flags & INCDEC_SOURCE_VALUE) { + SourceNumVal v; + v.isSource = isSource; + v.value = newval; + newval = v.rawValue; + } + return newval; } diff --git a/radio/src/gui/navigation/navigation_xlite.cpp b/radio/src/gui/navigation/navigation_xlite.cpp index fcd6406b0..4c36d2a86 100644 --- a/radio/src/gui/navigation/navigation_xlite.cpp +++ b/radio/src/gui/navigation/navigation_xlite.cpp @@ -49,6 +49,18 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, { int newval = val; + bool isSource = false; + bool origIsSource = false; + if (i_flags & INCDEC_SOURCE_VALUE) { + SourceNumVal v; + v.rawValue = val; + // Save isSource flag; + origIsSource = isSource = v.isSource; + // Remove isSource flag; + val = v.value; + newval = v.value; + } + if (s_editMode > 0) { bool invert = false; if ((i_flags & INCDEC_SOURCE_INVERT) && (newval < 0)) { @@ -101,10 +113,17 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, #endif #if defined(AUTOSOURCE) - if (i_flags & INCDEC_SOURCE) { - int8_t source = GET_MOVED_SOURCE(i_min, i_max); + if (i_flags & (INCDEC_SOURCE|INCDEC_SOURCE_VALUE)) { + int source = GET_MOVED_SOURCE(i_min, i_max); if (source) { - newval = source; + if (i_flags & INCDEC_SOURCE_VALUE) { + if (isSource) { + // Only use moved source if already a source value + newval = source; + } + } else { + newval = source; + } } #if defined(AUTOSWITCH) else { @@ -148,12 +167,17 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, checkIncDec_Ret = 0; } - if (i_flags & INCDEC_SOURCE) { + if (i_flags & (INCDEC_SOURCE | INCDEC_SOURCE_VALUE)) { if (event == EVT_KEY_LONG(KEY_ENTER) && !keysGetState(KEY_SHIFT)) { checkIncDecSelection = MIXSRC_NONE; + if (i_flags & INCDEC_SOURCE_VALUE && isSource) { + POPUP_MENU_ADD_ITEM(STR_CONSTANT); + } + if (i_min <= MIXSRC_FIRST_INPUT && i_max >= MIXSRC_FIRST_INPUT) { - if (getFirstAvailable(MIXSRC_FIRST_INPUT, MIXSRC_LAST_INPUT, isInputAvailable) != MIXSRC_NONE) { + if (getFirstAvailable(MIXSRC_FIRST_INPUT, MIXSRC_LAST_INPUT, isInputAvailable) != MIXSRC_NONE && + (i_flags & INCDEC_SOURCE_NOINPUTS) == 0) { POPUP_MENU_ADD_ITEM(STR_MENU_INPUTS); } } @@ -194,7 +218,18 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, POPUP_MENU_START(onSourceLongEnterPress); } if (checkIncDecSelection != 0) { - newval = (checkIncDecSelection == MIXSRC_INVERT ? -newval : checkIncDecSelection); + if (i_flags & INCDEC_SOURCE_VALUE) { + if (checkIncDecSelection == MIXSRC_VALUE) { + newval = 0; + isSource = false; + } else { + newval = (checkIncDecSelection == MIXSRC_INVERT ? -newval : checkIncDecSelection); + if (checkIncDecSelection != MIXSRC_INVERT) + isSource = true; + } + } else { + newval = (checkIncDecSelection == MIXSRC_INVERT ? -newval : checkIncDecSelection); + } if (checkIncDecSelection != MIXSRC_MIN && checkIncDecSelection != MIXSRC_MAX) s_editMode = EDIT_MODIFY_FIELD; checkIncDecSelection = 0; @@ -225,6 +260,13 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, } } + if (i_flags & INCDEC_SOURCE_VALUE) { + SourceNumVal v; + v.isSource = isSource; + v.value = newval; + newval = v.rawValue; + } + return newval; } diff --git a/radio/src/lua/api_model.cpp b/radio/src/lua/api_model.cpp index 8caaef276..d2b5622f9 100644 --- a/radio/src/lua/api_model.cpp +++ b/radio/src/lua/api_model.cpp @@ -681,10 +681,18 @@ static int luaModelInsertInput(lua_State *L) expo->scale = luaL_checkinteger(L, -1); } else if (!strcmp(key, "weight")) { - expo->weight = luaL_checkinteger(L, -1); + int val = luaL_checkinteger(L, -1); + SourceNumVal v; + v.isSource = (abs(val) >= 1024); + v.value = val; + expo->weight = v.rawValue; } else if (!strcmp(key, "offset")) { - expo->offset = luaL_checkinteger(L, -1); + int val = luaL_checkinteger(L, -1); + SourceNumVal v; + v.isSource = (abs(val) >= 1024); + v.value = val; + expo->offset = v.rawValue; } else if (!strcmp(key, "switch")) { expo->swtch = luaL_checkinteger(L, -1); @@ -693,7 +701,11 @@ static int luaModelInsertInput(lua_State *L) expo->curve.type = luaL_checkinteger(L, -1); } else if (!strcmp(key, "curveValue")) { - expo->curve.value = luaL_checkinteger(L, -1); + int val = luaL_checkinteger(L, -1); + SourceNumVal v; + v.isSource = (abs(val) >= 1024); + v.value = val; + expo->curve.value = v.rawValue; } else if (!strcmp(key, "trimSource")) { expo->trimSource = - luaL_checkinteger(L, -1); @@ -904,10 +916,18 @@ static int luaModelInsertMix(lua_State *L) mix->srcRaw = luaL_checkinteger(L, -1); } else if (!strcmp(key, "weight")) { - mix->weight = luaL_checkinteger(L, -1); + int val = luaL_checkinteger(L, -1); + SourceNumVal v; + v.isSource = (abs(val) >= 1024); + v.value = val; + mix->weight = v.rawValue; } else if (!strcmp(key, "offset")) { - mix->offset = luaL_checkinteger(L, -1); + int val = luaL_checkinteger(L, -1); + SourceNumVal v; + v.isSource = (abs(val) >= 1024); + v.value = val; + mix->offset = v.rawValue; } else if (!strcmp(key, "switch")) { mix->swtch = luaL_checkinteger(L, -1); @@ -916,7 +936,11 @@ static int luaModelInsertMix(lua_State *L) mix->curve.type = luaL_checkinteger(L, -1); } else if (!strcmp(key, "curveValue")) { - mix->curve.value = luaL_checkinteger(L, -1); + int val = luaL_checkinteger(L, -1); + SourceNumVal v; + v.isSource = (abs(val) >= 1024); + v.value = val; + mix->curve.value = v.rawValue; } else if (!strcmp(key, "multiplex")) { mix->mltpx = luaL_checkinteger(L, -1); diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index 9b8b3dac2..92c4dc54e 100644 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -53,6 +53,25 @@ int16_t ex_chans[MAX_OUTPUT_CHANNELS] = {0}; // Outputs (before LIMITS) of the l int16_t cyc_anas[3] = {0}; #endif +// TOOD: find better home for this. +int32_t getSourceNumFieldValue(int16_t val, int16_t min, int16_t max) +{ + int32_t result; + SourceNumVal v; v.rawValue = val; + if (v.isSource) { + result = getValue(v.value); + if (v.value >= MIXSRC_FIRST_GVAR && v.value <= MIXSRC_LAST_GVAR) { + // Mimic behviour of GET_GVAR_PREC1 + result = result * 10; + } else { + result = calcRESXto1000(result); + } + } else { + result = v.value * 10; + } + return limit(min * 10, result, max * 10); +} + // #define EXTENDED_EXPO // increases range of expo curve but costs about 82 bytes flash @@ -193,11 +212,11 @@ void applyExpos(int16_t * anas, uint8_t mode, int16_t ovwrIdx, int16_t ovwrValue } //========== WEIGHT =============== - int32_t weight = GET_GVAR_PREC1(ed->weight, -100, 100, mixerCurrentFlightMode); + int32_t weight = getSourceNumFieldValue(ed->weight, -100, 100); v = divRoundClosest((int32_t)v * weight, 1000); //========== OFFSET =============== - int32_t offset = GET_GVAR_PREC1(ed->offset, -100, 100, mixerCurrentFlightMode); + int32_t offset = getSourceNumFieldValue(ed->offset, -100, 100); if (offset) v += divRoundClosest(calc100toRESX(offset), 10); //========== TRIMS ================ @@ -951,7 +970,7 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms) } } - int32_t weight = GET_GVAR_PREC1(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); + int32_t weight = getSourceNumFieldValue(md->weight, -RESX, RESX); weight = calc100to256_16Bits(weight); //========== SPEED =============== // now its on input side, but without weight compensation. More like other remote controls @@ -1006,7 +1025,7 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms) //========== OFFSET / AFTER =============== if (applyOffsetAndCurve) { - int32_t offset = GET_GVAR_PREC1(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); + int32_t offset = getSourceNumFieldValue(md->offset, -RESX, RESX); if (offset) dv += divRoundClosest(calc100toRESX_16Bits(offset), 10) << 8; } diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 02834701a..fef8f775a 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -272,14 +272,6 @@ enum DisplayTrims extern RadioData g_eeGeneral; extern ModelData g_model; -PACK(union u_int8int16_t { - struct { - int8_t lo; - uint8_t hi; - } bytes_t; - int16_t word; -}); - constexpr uint8_t EE_GENERAL = 0x01; constexpr uint8_t EE_MODEL = 0x02; constexpr uint8_t EE_LABELS = 0x04; diff --git a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp index 2c59383ed..c3e68ef19 100644 --- a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp @@ -391,21 +391,22 @@ static const struct YamlNode struct_TimerData[] = { YAML_END }; static const struct YamlNode struct_CurveRef[] = { - YAML_UNSIGNED( "type", 8 ), - YAML_SIGNED_CUST( "value", 8, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "type", 5 ), + YAML_SIGNED_CUST( "value", 11, r_sourceNumVal, w_sourceNumVal ), YAML_END }; static const struct YamlNode struct_MixData[] = { - YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), YAML_UNSIGNED( "speedPrec", 1 ), - YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ), - YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), YAML_UNSIGNED( "delayUp", 8 ), YAML_UNSIGNED( "delayDown", 8 ), @@ -433,13 +434,14 @@ static const struct YamlNode struct_ExpoData[] = { YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), - YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), - YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), - YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ), - YAML_STRING("name", 6), - YAML_SIGNED_CUST( "offset", 8, in_read_weight, in_write_weight ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_STRING("name", 6), YAML_END }; static const struct YamlNode struct_CurveHeader[] = { @@ -798,7 +800,7 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), YAML_ARRAY("limitData", 88, 32, struct_LimitData, NULL), - YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL), + YAML_ARRAY("expoData", 144, 64, struct_ExpoData, NULL), YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL), YAML_ARRAY("points", 8, 512, struct_signed_8, NULL), YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp index 5df9fd216..437bf7b26 100644 --- a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp @@ -463,6 +463,40 @@ static bool w_mixSrcRawEx(const YamlNode* node, uint32_t val, yaml_writer_func w return wf(opaque, "\"", 1); } +static uint32_t r_sourceNumVal(const YamlNode* node, const char* val, uint8_t val_len) +{ + SourceNumVal v; + + if (((val[0] == '-') && (val[1] >= '0' && val[1] <= '9')) || (val[0] >= '0' && val[0] <= '9')) { + v.isSource = 0; + v.value = (uint32_t)yaml_str2int(val, val_len); + } else if ((val[0] == '-') && (val[1] == 'G')) { + v.isSource = 1; + v.value = -((val[3] - '0') + MIXSRC_FIRST_GVAR - 1); + } else if (val[0] == 'G') { + v.isSource = 1; + v.value = (val[2] - '0') + MIXSRC_FIRST_GVAR - 1; + } else { + v.isSource = 1; + v.value = r_mixSrcRawEx(node, val, val_len); + } + + return v.rawValue; +} + +bool w_sourceNumVal(const YamlNode* node, uint32_t val, yaml_writer_func wf, + void* opaque) +{ + SourceNumVal v; + v.rawValue = val; + + if (v.isSource) + return w_mixSrcRawEx(node, v.value, wf, opaque); + + char* s = yaml_signed2str(v.value); + return wf(opaque, s, strlen(s)); +} + static void r_rssiDisabled(void* user, uint8_t* data, uint32_t bitoffs, const char* val, uint8_t val_len) { diff --git a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp index 3c83987e9..32b50c3c0 100644 --- a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp @@ -417,21 +417,22 @@ static const struct YamlNode struct_TimerData[] = { YAML_END }; static const struct YamlNode struct_CurveRef[] = { - YAML_UNSIGNED( "type", 8 ), - YAML_SIGNED_CUST( "value", 8, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "type", 5 ), + YAML_SIGNED_CUST( "value", 11, r_sourceNumVal, w_sourceNumVal ), YAML_END }; static const struct YamlNode struct_MixData[] = { - YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), YAML_UNSIGNED( "speedPrec", 1 ), - YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ), - YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), YAML_UNSIGNED( "delayUp", 8 ), YAML_UNSIGNED( "delayDown", 8 ), @@ -459,13 +460,14 @@ static const struct YamlNode struct_ExpoData[] = { YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), - YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), - YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), - YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ), - YAML_STRING("name", 6), - YAML_SIGNED_CUST( "offset", 8, in_read_weight, in_write_weight ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_STRING("name", 6), YAML_END }; static const struct YamlNode struct_CurveHeader[] = { @@ -832,7 +834,7 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), YAML_ARRAY("limitData", 104, 32, struct_LimitData, NULL), - YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL), + YAML_ARRAY("expoData", 144, 64, struct_ExpoData, NULL), YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL), YAML_ARRAY("points", 8, 512, struct_signed_8, NULL), YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_pl18.cpp b/radio/src/storage/yaml/yaml_datastructs_pl18.cpp index 95f3c6476..878719171 100644 --- a/radio/src/storage/yaml/yaml_datastructs_pl18.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_pl18.cpp @@ -417,21 +417,22 @@ static const struct YamlNode struct_TimerData[] = { YAML_END }; static const struct YamlNode struct_CurveRef[] = { - YAML_UNSIGNED( "type", 8 ), - YAML_SIGNED_CUST( "value", 8, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "type", 5 ), + YAML_SIGNED_CUST( "value", 11, r_sourceNumVal, w_sourceNumVal ), YAML_END }; static const struct YamlNode struct_MixData[] = { - YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), YAML_UNSIGNED( "speedPrec", 1 ), - YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ), - YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), YAML_UNSIGNED( "delayUp", 8 ), YAML_UNSIGNED( "delayDown", 8 ), @@ -459,13 +460,14 @@ static const struct YamlNode struct_ExpoData[] = { YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), - YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), - YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), - YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ), - YAML_STRING("name", 6), - YAML_SIGNED_CUST( "offset", 8, in_read_weight, in_write_weight ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_STRING("name", 6), YAML_END }; static const struct YamlNode struct_CurveHeader[] = { @@ -832,7 +834,7 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), YAML_ARRAY("limitData", 104, 32, struct_LimitData, NULL), - YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL), + YAML_ARRAY("expoData", 144, 64, struct_ExpoData, NULL), YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL), YAML_ARRAY("points", 8, 512, struct_signed_8, NULL), YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_t15.cpp b/radio/src/storage/yaml/yaml_datastructs_t15.cpp index f611bcec2..4a68b20a5 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t15.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t15.cpp @@ -419,21 +419,22 @@ static const struct YamlNode struct_TimerData[] = { YAML_END }; static const struct YamlNode struct_CurveRef[] = { - YAML_UNSIGNED( "type", 8 ), - YAML_SIGNED_CUST( "value", 8, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "type", 5 ), + YAML_SIGNED_CUST( "value", 11, r_sourceNumVal, w_sourceNumVal ), YAML_END }; static const struct YamlNode struct_MixData[] = { - YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), YAML_UNSIGNED( "speedPrec", 1 ), - YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ), - YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), YAML_UNSIGNED( "delayUp", 8 ), YAML_UNSIGNED( "delayDown", 8 ), @@ -461,13 +462,14 @@ static const struct YamlNode struct_ExpoData[] = { YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), - YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), - YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), - YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ), - YAML_STRING("name", 6), - YAML_SIGNED_CUST( "offset", 8, in_read_weight, in_write_weight ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_STRING("name", 6), YAML_END }; static const struct YamlNode struct_CurveHeader[] = { @@ -838,7 +840,7 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), YAML_ARRAY("limitData", 104, 32, struct_LimitData, NULL), - YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL), + YAML_ARRAY("expoData", 144, 64, struct_ExpoData, NULL), YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL), YAML_ARRAY("points", 8, 512, struct_signed_8, NULL), YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_t20.cpp b/radio/src/storage/yaml/yaml_datastructs_t20.cpp index f0ed26934..e91042a06 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t20.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t20.cpp @@ -391,21 +391,22 @@ static const struct YamlNode struct_TimerData[] = { YAML_END }; static const struct YamlNode struct_CurveRef[] = { - YAML_UNSIGNED( "type", 8 ), - YAML_SIGNED_CUST( "value", 8, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "type", 5 ), + YAML_SIGNED_CUST( "value", 11, r_sourceNumVal, w_sourceNumVal ), YAML_END }; static const struct YamlNode struct_MixData[] = { - YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), YAML_UNSIGNED( "speedPrec", 1 ), - YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ), - YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), YAML_UNSIGNED( "delayUp", 8 ), YAML_UNSIGNED( "delayDown", 8 ), @@ -433,13 +434,14 @@ static const struct YamlNode struct_ExpoData[] = { YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), - YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), - YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), - YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ), - YAML_STRING("name", 6), - YAML_SIGNED_CUST( "offset", 8, in_read_weight, in_write_weight ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_STRING("name", 6), YAML_END }; static const struct YamlNode struct_CurveHeader[] = { @@ -798,7 +800,7 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), YAML_ARRAY("limitData", 88, 32, struct_LimitData, NULL), - YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL), + YAML_ARRAY("expoData", 144, 64, struct_ExpoData, NULL), YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL), YAML_ARRAY("points", 8, 512, struct_signed_8, NULL), YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp index 7eaa8a03d..2a9ccc5e9 100644 --- a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp @@ -391,21 +391,22 @@ static const struct YamlNode struct_TimerData[] = { YAML_END }; static const struct YamlNode struct_CurveRef[] = { - YAML_UNSIGNED( "type", 8 ), - YAML_SIGNED_CUST( "value", 8, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "type", 5 ), + YAML_SIGNED_CUST( "value", 11, r_sourceNumVal, w_sourceNumVal ), YAML_END }; static const struct YamlNode struct_MixData[] = { - YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), YAML_UNSIGNED( "speedPrec", 1 ), - YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ), - YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), YAML_UNSIGNED( "delayUp", 8 ), YAML_UNSIGNED( "delayDown", 8 ), @@ -433,13 +434,14 @@ static const struct YamlNode struct_ExpoData[] = { YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), - YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), - YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), - YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ), - YAML_STRING("name", 6), - YAML_SIGNED_CUST( "offset", 8, in_read_weight, in_write_weight ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_STRING("name", 6), YAML_END }; static const struct YamlNode struct_CurveHeader[] = { @@ -798,7 +800,7 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), YAML_ARRAY("limitData", 88, 32, struct_LimitData, NULL), - YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL), + YAML_ARRAY("expoData", 144, 64, struct_ExpoData, NULL), YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL), YAML_ARRAY("points", 8, 512, struct_signed_8, NULL), YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_x10.cpp b/radio/src/storage/yaml/yaml_datastructs_x10.cpp index 4a51da3db..18640aba4 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x10.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x10.cpp @@ -419,21 +419,22 @@ static const struct YamlNode struct_TimerData[] = { YAML_END }; static const struct YamlNode struct_CurveRef[] = { - YAML_UNSIGNED( "type", 8 ), - YAML_SIGNED_CUST( "value", 8, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "type", 5 ), + YAML_SIGNED_CUST( "value", 11, r_sourceNumVal, w_sourceNumVal ), YAML_END }; static const struct YamlNode struct_MixData[] = { - YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), YAML_UNSIGNED( "speedPrec", 1 ), - YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ), - YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), YAML_UNSIGNED( "delayUp", 8 ), YAML_UNSIGNED( "delayDown", 8 ), @@ -461,13 +462,14 @@ static const struct YamlNode struct_ExpoData[] = { YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), - YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), - YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), - YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ), - YAML_STRING("name", 6), - YAML_SIGNED_CUST( "offset", 8, in_read_weight, in_write_weight ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_STRING("name", 6), YAML_END }; static const struct YamlNode struct_CurveHeader[] = { @@ -833,7 +835,7 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), YAML_ARRAY("limitData", 104, 32, struct_LimitData, NULL), - YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL), + YAML_ARRAY("expoData", 144, 64, struct_ExpoData, NULL), YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL), YAML_ARRAY("points", 8, 512, struct_signed_8, NULL), YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_x12s.cpp b/radio/src/storage/yaml/yaml_datastructs_x12s.cpp index 4a51da3db..18640aba4 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x12s.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x12s.cpp @@ -419,21 +419,22 @@ static const struct YamlNode struct_TimerData[] = { YAML_END }; static const struct YamlNode struct_CurveRef[] = { - YAML_UNSIGNED( "type", 8 ), - YAML_SIGNED_CUST( "value", 8, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "type", 5 ), + YAML_SIGNED_CUST( "value", 11, r_sourceNumVal, w_sourceNumVal ), YAML_END }; static const struct YamlNode struct_MixData[] = { - YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), YAML_UNSIGNED( "speedPrec", 1 ), - YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ), - YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), YAML_UNSIGNED( "delayUp", 8 ), YAML_UNSIGNED( "delayDown", 8 ), @@ -461,13 +462,14 @@ static const struct YamlNode struct_ExpoData[] = { YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), - YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), - YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), - YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ), - YAML_STRING("name", 6), - YAML_SIGNED_CUST( "offset", 8, in_read_weight, in_write_weight ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_STRING("name", 6), YAML_END }; static const struct YamlNode struct_CurveHeader[] = { @@ -833,7 +835,7 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), YAML_ARRAY("limitData", 104, 32, struct_LimitData, NULL), - YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL), + YAML_ARRAY("expoData", 144, 64, struct_ExpoData, NULL), YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL), YAML_ARRAY("points", 8, 512, struct_signed_8, NULL), YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_x9d.cpp b/radio/src/storage/yaml/yaml_datastructs_x9d.cpp index 7ceaa7f5c..05b4e35a8 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9d.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9d.cpp @@ -390,21 +390,22 @@ static const struct YamlNode struct_TimerData[] = { YAML_END }; static const struct YamlNode struct_CurveRef[] = { - YAML_UNSIGNED( "type", 8 ), - YAML_SIGNED_CUST( "value", 8, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "type", 5 ), + YAML_SIGNED_CUST( "value", 11, r_sourceNumVal, w_sourceNumVal ), YAML_END }; static const struct YamlNode struct_MixData[] = { - YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), YAML_UNSIGNED( "speedPrec", 1 ), - YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ), - YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), YAML_UNSIGNED( "delayUp", 8 ), YAML_UNSIGNED( "delayDown", 8 ), @@ -432,13 +433,14 @@ static const struct YamlNode struct_ExpoData[] = { YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), - YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), - YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), - YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ), - YAML_STRING("name", 6), - YAML_SIGNED_CUST( "offset", 8, in_read_weight, in_write_weight ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_STRING("name", 6), YAML_END }; static const struct YamlNode struct_CurveHeader[] = { @@ -797,7 +799,7 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), YAML_ARRAY("limitData", 104, 32, struct_LimitData, NULL), - YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL), + YAML_ARRAY("expoData", 144, 64, struct_ExpoData, NULL), YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL), YAML_ARRAY("points", 8, 512, struct_signed_8, NULL), YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_x9e.cpp b/radio/src/storage/yaml/yaml_datastructs_x9e.cpp index d2796fcd5..b60ad2d93 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9e.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9e.cpp @@ -391,21 +391,22 @@ static const struct YamlNode struct_TimerData[] = { YAML_END }; static const struct YamlNode struct_CurveRef[] = { - YAML_UNSIGNED( "type", 8 ), - YAML_SIGNED_CUST( "value", 8, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "type", 5 ), + YAML_SIGNED_CUST( "value", 11, r_sourceNumVal, w_sourceNumVal ), YAML_END }; static const struct YamlNode struct_MixData[] = { - YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), YAML_UNSIGNED( "speedPrec", 1 ), - YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ), - YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), YAML_UNSIGNED( "delayUp", 8 ), YAML_UNSIGNED( "delayDown", 8 ), @@ -433,13 +434,14 @@ static const struct YamlNode struct_ExpoData[] = { YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), - YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), - YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), - YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ), - YAML_STRING("name", 6), - YAML_SIGNED_CUST( "offset", 8, in_read_weight, in_write_weight ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_STRING("name", 6), YAML_END }; static const struct YamlNode struct_CurveHeader[] = { @@ -798,7 +800,7 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), YAML_ARRAY("limitData", 104, 32, struct_LimitData, NULL), - YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL), + YAML_ARRAY("expoData", 144, 64, struct_ExpoData, NULL), YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL), YAML_ARRAY("points", 8, 512, struct_signed_8, NULL), YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_xlites.cpp b/radio/src/storage/yaml/yaml_datastructs_xlites.cpp index b55a1abfd..6299d1c31 100644 --- a/radio/src/storage/yaml/yaml_datastructs_xlites.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_xlites.cpp @@ -394,21 +394,22 @@ static const struct YamlNode struct_TimerData[] = { YAML_END }; static const struct YamlNode struct_CurveRef[] = { - YAML_UNSIGNED( "type", 8 ), - YAML_SIGNED_CUST( "value", 8, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "type", 5 ), + YAML_SIGNED_CUST( "value", 11, r_sourceNumVal, w_sourceNumVal ), YAML_END }; static const struct YamlNode struct_MixData[] = { - YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), YAML_UNSIGNED( "destCh", 5 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), YAML_UNSIGNED( "carryTrim", 1 ), YAML_UNSIGNED( "mixWarn", 2 ), YAML_ENUM("mltpx", 2, enum_MixerMultiplex), YAML_UNSIGNED( "speedPrec", 1 ), - YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ), - YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), YAML_UNSIGNED( "delayUp", 8 ), YAML_UNSIGNED( "delayDown", 8 ), @@ -436,13 +437,14 @@ static const struct YamlNode struct_ExpoData[] = { YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), YAML_SIGNED( "trimSource", 6 ), YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), - YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), - YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), - YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ), - YAML_STRING("name", 6), - YAML_SIGNED_CUST( "offset", 8, in_read_weight, in_write_weight ), YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_UNSIGNED( "spare", 2 ), + YAML_STRING("name", 6), YAML_END }; static const struct YamlNode struct_CurveHeader[] = { @@ -801,7 +803,7 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), YAML_ARRAY("limitData", 88, 32, struct_LimitData, NULL), - YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL), + YAML_ARRAY("expoData", 144, 64, struct_ExpoData, NULL), YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL), YAML_ARRAY("points", 8, 512, struct_signed_8, NULL), YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL), diff --git a/radio/src/strhelpers.cpp b/radio/src/strhelpers.cpp index 01f0c7888..5a457c3cd 100644 --- a/radio/src/strhelpers.cpp +++ b/radio/src/strhelpers.cpp @@ -380,7 +380,7 @@ char *getCurveString(char *dest, int idx) char *s = dest; if (idx < 0) { - *s++ = '!'; + *s++ = '-'; idx = -idx; } @@ -429,6 +429,24 @@ char *getValueOrGVarString(char *dest, size_t len, gvar_t value, gvar_t vmin, formatNumberAsString(dest, len, value, flags, 0, nullptr, suffix); return dest; } + +char *getValueOrSrcVarString(char *dest, size_t len, gvar_t value, gvar_t vmin, + gvar_t vmax, LcdFlags flags, const char *suffix, + gvar_t offset, bool usePPMUnit) +{ + SourceNumVal v; + v.rawValue = value; + if (v.isSource) { + const char* s = getSourceString(v.value); + strncpy(dest, s, len); + } else { + v.value += offset; + if (usePPMUnit && g_eeGeneral.ppmunit == PPM_US) + v.value = v.value * 128 / 25; + formatNumberAsString(dest, len, v.value, flags, 0, nullptr, suffix); + } + return dest; +} #endif char *getFlightModeString(char *dest, int8_t idx) @@ -640,7 +658,7 @@ char *getSourceString(char (&destRef)[L], mixsrc_t idx) if (idx < 0) { idx = -idx; - dest[0] = '!'; + dest[0] = '-'; dest += 1; dest_len -= 1; } diff --git a/radio/src/strhelpers.h b/radio/src/strhelpers.h index 85d51c9e5..2212124d8 100644 --- a/radio/src/strhelpers.h +++ b/radio/src/strhelpers.h @@ -98,6 +98,9 @@ char *getGVarString(int idx); char *getValueOrGVarString(char *dest, size_t len, gvar_t value, gvar_t vmin, gvar_t vmax, LcdFlags flags = 0, const char *suffix = nullptr, gvar_t offset = 0, bool usePPMUnit = false); +char *getValueOrSrcVarString(char *dest, size_t len, gvar_t value, gvar_t vmin, + gvar_t vmax, LcdFlags flags = 0, + const char *suffix = nullptr, gvar_t offset = 0, bool usePPMUnit = false); const char *getSwitchWarnSymbol(uint8_t pos); const char *getSwitchPositionSymbol(uint8_t pos); char *getSwitchPositionName(char *dest, swsrc_t idx); diff --git a/radio/src/tests/lua.cpp b/radio/src/tests/lua.cpp index 3cf9258c5..adfeeee24 100644 --- a/radio/src/tests/lua.cpp +++ b/radio/src/tests/lua.cpp @@ -134,7 +134,9 @@ TEST(Lua, testModelInputs) EXPECT_EQ(3, (int)g_model.expoData[0].chn); EXPECT_STRNEQ("test2", g_model.expoData[0].name); EXPECT_EQ(MIXSRC_FIRST_STICK, g_model.expoData[0].srcRaw); - EXPECT_EQ(-56, g_model.expoData[0].weight); + SourceNumVal v; + v.rawValue = g_model.expoData[0].weight; + EXPECT_EQ(-56, v.value); EXPECT_EQ(0, g_model.expoData[0].offset); EXPECT_EQ(0, g_model.expoData[0].swtch); @@ -155,7 +157,8 @@ TEST(Lua, testModelInputs) EXPECT_EQ(3, (int)g_model.expoData[0].chn); EXPECT_STRNEQ("test2", g_model.expoData[0].name); EXPECT_EQ(MIXSRC_FIRST_STICK, g_model.expoData[0].srcRaw); - EXPECT_EQ(-56, g_model.expoData[0].weight); + v.rawValue = g_model.expoData[0].weight; + EXPECT_EQ(-56, v.value); EXPECT_EQ(0, g_model.expoData[0].offset); EXPECT_EQ(0, g_model.expoData[0].swtch); diff --git a/radio/src/tests/mixer.cpp b/radio/src/tests/mixer.cpp index af067eecb..43e36c24e 100644 --- a/radio/src/tests/mixer.cpp +++ b/radio/src/tests/mixer.cpp @@ -279,7 +279,7 @@ TEST_F(TrimsTest, throttleTrimWithZeroWeightOnThrottle) g_model.thrTrim = 1; // the input already exists ExpoData *expo = expoAddress(THR_STICK); - expo->weight = 0; + expo->weight = makeSourceNumVal(0); // stick max + trim max anaSetFiltered(THR_STICK, +1024); setTrimValue(0, THR_STICK, TRIM_MAX); @@ -350,7 +350,7 @@ TEST_F(TrimsTest, invertedThrottlePlusthrottleTrimWithZeroWeightOnThrottle) g_model.thrTrim = 1; // the input already exists ExpoData *expo = expoAddress(THR_STICK); - expo->weight = 0; + expo->weight = makeSourceNumVal(0); // stick max + trim max anaSetFiltered(THR_STICK, +1024); setTrimValue(0, THR_STICK, TRIM_MAX); @@ -579,7 +579,7 @@ TEST_F(TrimsTest, InstantTrimNegativeCurve) { ExpoData *expo = expoAddress(AIL_STICK); expo->curve.type = CURVE_REF_CUSTOM; - expo->curve.value = 1; + expo->curve.value = makeSourceNumVal(1); g_model.points[0] = -100; g_model.points[1] = -75; g_model.points[2] = -50; @@ -616,13 +616,13 @@ TEST_F(MixerTest, InfiniteRecursiveChannels) { g_model.mixData[0].destCh = 0; g_model.mixData[0].srcRaw = MIXSRC_FIRST_CH + 1; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); g_model.mixData[1].destCh = 1; g_model.mixData[1].srcRaw = MIXSRC_FIRST_CH + 2; - g_model.mixData[1].weight = 100; + g_model.mixData[1].weight = makeSourceNumVal(100); g_model.mixData[2].destCh = 2; g_model.mixData[2].srcRaw = MIXSRC_FIRST_CH; - g_model.mixData[2].weight = 100; + g_model.mixData[2].weight = makeSourceNumVal(100); evalFlightModeMixes(e_perout_mode_normal, 0); EXPECT_EQ(chans[2], 0); EXPECT_EQ(chans[1], 0); @@ -633,7 +633,7 @@ TEST_F(MixerTest, BlockingChannel) { g_model.mixData[0].destCh = 0; g_model.mixData[0].srcRaw = MIXSRC_FIRST_CH; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); evalFlightModeMixes(e_perout_mode_normal, 0); EXPECT_EQ(chans[0], 0); } @@ -643,14 +643,14 @@ TEST_F(MixerTest, RecursiveAddChannel) g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_MAX; - g_model.mixData[0].weight = 50; + g_model.mixData[0].weight = makeSourceNumVal(50); g_model.mixData[1].destCh = 0; g_model.mixData[1].mltpx = MLTPX_ADD; g_model.mixData[1].srcRaw = MIXSRC_FIRST_CH + 1; - g_model.mixData[1].weight = 100; + g_model.mixData[1].weight = makeSourceNumVal(100); g_model.mixData[2].destCh = 1; g_model.mixData[2].srcRaw = MIXSRC_FIRST_STICK; - g_model.mixData[2].weight = 100; + g_model.mixData[2].weight = makeSourceNumVal(100); anaSetFiltered(0, 0); evalFlightModeMixes(e_perout_mode_normal, 0); @@ -665,15 +665,15 @@ TEST_F(MixerTest, RecursiveAddChannelAfterInactivePhase) g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_FIRST_CH + 1; g_model.mixData[0].flightModes = 0b11110; - g_model.mixData[0].weight = 50; + g_model.mixData[0].weight = makeSourceNumVal(50); g_model.mixData[1].destCh = 0; g_model.mixData[1].mltpx = MLTPX_ADD; g_model.mixData[1].srcRaw = MIXSRC_MAX; g_model.mixData[1].flightModes = 0b11101; - g_model.mixData[1].weight = 50; + g_model.mixData[1].weight = makeSourceNumVal(50); g_model.mixData[2].destCh = 1; g_model.mixData[2].srcRaw = MIXSRC_MAX; - g_model.mixData[2].weight = 100; + g_model.mixData[2].weight = makeSourceNumVal(100); simuSetSwitch(3, -1); evalMixes(1); EXPECT_EQ(chans[0], CHANNEL_MAX/2); @@ -691,7 +691,7 @@ TEST_F(MixerTest, SlowOnPhase) g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_MAX; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); g_model.mixData[0].flightModes = 0x2 + 0x4 + 0x8 + 0x10 /*only enabled in phase 0*/; g_model.mixData[0].speedUp = 50; g_model.mixData[0].speedDown = 50; @@ -714,7 +714,7 @@ TEST_F(MixerTest, SlowOnSwitchSource) g_eeGeneral.switchConfig = 0x03; g_model.mixData[0].srcRaw = MIXSRC_FIRST_SWITCH; int switchIndex = 0; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); g_model.mixData[0].speedUp = 50; g_model.mixData[0].speedDown = 50; @@ -734,7 +734,7 @@ TEST_F(MixerTest, SlowOnPhasePrec10ms) g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_MAX; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); g_model.mixData[0].flightModes = 0x2 + 0x4 + 0x8 + 0x10 /*only enabled in phase 0*/; g_model.mixData[0].speedUp = 50; g_model.mixData[0].speedDown = 50; @@ -758,7 +758,7 @@ TEST_F(MixerTest, SlowOnSwitchSourcePrec10ms) g_eeGeneral.switchConfig = 0x03; g_model.mixData[0].srcRaw = MIXSRC_FIRST_SWITCH; int switchIndex = 0; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); g_model.mixData[0].speedUp = 50; g_model.mixData[0].speedDown = 50; g_model.mixData[0].speedPrec = 1; @@ -778,7 +778,7 @@ TEST_F(MixerTest, SlowDisabledOnStartup) g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_MAX; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); g_model.mixData[0].speedUp = 50; g_model.mixData[0].speedDown = 50; @@ -791,7 +791,7 @@ TEST_F(MixerTest, DelayOnSwitch) g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_MAX; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); g_model.mixData[0].swtch = SWSRC_FIRST_SWITCH + 2; g_model.mixData[0].delayUp = 50; g_model.mixData[0].delayDown = 50; @@ -822,7 +822,7 @@ TEST_F(MixerTest, DelayOnSwitch2) g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_FIRST_SWITCH; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); // g_model.mixData[0].swtch = SWSRC_ON; g_model.mixData[0].delayUp = 50; g_model.mixData[0].delayDown = 50; @@ -851,11 +851,11 @@ TEST_F(MixerTest, SlowOnMultiply) g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_MAX; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); g_model.mixData[1].destCh = 0; g_model.mixData[1].mltpx = MLTPX_MUL; g_model.mixData[1].srcRaw = MIXSRC_MAX; - g_model.mixData[1].weight = 100; + g_model.mixData[1].weight = makeSourceNumVal(100); g_model.mixData[1].swtch = SWSRC_FIRST_SWITCH; g_model.mixData[1].speedUp = 50; g_model.mixData[1].speedDown = 50; @@ -877,11 +877,11 @@ TEST_F(MixerTest, SlowOnMultiplyPrec10ms) g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_MAX; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); g_model.mixData[1].destCh = 0; g_model.mixData[1].mltpx = MLTPX_MUL; g_model.mixData[1].srcRaw = MIXSRC_MAX; - g_model.mixData[1].weight = 100; + g_model.mixData[1].weight = makeSourceNumVal(100); g_model.mixData[1].swtch = SWSRC_FIRST_SWITCH; g_model.mixData[1].speedUp = 50; g_model.mixData[1].speedDown = 50; @@ -938,15 +938,15 @@ TEST(Heli, BasicTest) g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_CYC1; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); g_model.mixData[1].destCh = 1; g_model.mixData[1].mltpx = MLTPX_ADD; g_model.mixData[1].srcRaw = MIXSRC_CYC2; - g_model.mixData[1].weight = 100; + g_model.mixData[1].weight = makeSourceNumVal(100); g_model.mixData[2].destCh = 2; g_model.mixData[2].mltpx = MLTPX_ADD; g_model.mixData[2].srcRaw = MIXSRC_CYC3; - g_model.mixData[2].weight = 100; + g_model.mixData[2].weight = makeSourceNumVal(100); anaSetFiltered(THR_STICK, 0); anaSetFiltered(ELE_STICK, 1024); anaSetFiltered(AIL_STICK, 0); @@ -974,15 +974,15 @@ TEST(Heli, Mode2Test) g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_CYC1; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); g_model.mixData[1].destCh = 1; g_model.mixData[1].mltpx = MLTPX_ADD; g_model.mixData[1].srcRaw = MIXSRC_CYC2; - g_model.mixData[1].weight = 100; + g_model.mixData[1].weight = makeSourceNumVal(100); g_model.mixData[2].destCh = 2; g_model.mixData[2].mltpx = MLTPX_ADD; g_model.mixData[2].srcRaw = MIXSRC_CYC3; - g_model.mixData[2].weight = 100; + g_model.mixData[2].weight = makeSourceNumVal(100); anaSetFiltered(THR_STICK, 0); anaSetFiltered(ELE_STICK, 1024); anaSetFiltered(AIL_STICK, 0); @@ -1003,7 +1003,7 @@ TEST(Trainer, UnpluggedTest) g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_FIRST_TRAINER; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); g_model.mixData[0].delayUp = 50; g_model.mixData[0].delayDown = 50; trainerSetTimer(0); @@ -1026,12 +1026,12 @@ TEST_F(MixerTest, flightModeTransition) g_model.mixData[0].mltpx = MLTPX_REPL; g_model.mixData[0].srcRaw = MIXSRC_MAX; g_model.mixData[0].flightModes = 0b11110; - g_model.mixData[0].weight = 100; + g_model.mixData[0].weight = makeSourceNumVal(100); g_model.mixData[1].destCh = 0; g_model.mixData[1].mltpx = MLTPX_REPL; g_model.mixData[1].srcRaw = MIXSRC_MAX; g_model.mixData[1].flightModes = 0b11101; - g_model.mixData[1].weight = -10; + g_model.mixData[1].weight = makeSourceNumVal(-10); evalMixes(1); simuSetSwitch(0, 1); CHECK_FLIGHT_MODE_TRANSITION(0, 1000, 1024, -102); @@ -1050,7 +1050,7 @@ TEST_F(MixerTest, flightModeOverflow) g_model.mixData[0].mltpx = MLTPX_REPL; g_model.mixData[0].srcRaw = MIXSRC_MAX; g_model.mixData[0].flightModes = 0; - g_model.mixData[0].weight = 250; + g_model.mixData[0].weight = makeSourceNumVal(250); evalMixes(1); simuSetSwitch(0, 1); CHECK_FLIGHT_MODE_TRANSITION(0, 1000, 1024, 1024); diff --git a/radio/src/thirdparty/libopenui/src/choice.cpp b/radio/src/thirdparty/libopenui/src/choice.cpp index 40e519a3e..a7f823206 100644 --- a/radio/src/thirdparty/libopenui/src/choice.cpp +++ b/radio/src/thirdparty/libopenui/src/choice.cpp @@ -153,7 +153,8 @@ void Choice::setValue(int val) void Choice::onClicked() { - openMenu(); + if (!deleted()) + openMenu(); } void Choice::fillMenu(Menu* menu, const FilterFct& filter)