diff --git a/companion/src/firmwares/edgetx/yaml_generalsettings.cpp b/companion/src/firmwares/edgetx/yaml_generalsettings.cpp index 373e4d42307..bed5664c518 100644 --- a/companion/src/firmwares/edgetx/yaml_generalsettings.cpp +++ b/companion/src/firmwares/edgetx/yaml_generalsettings.cpp @@ -117,6 +117,12 @@ const YamlLookupTable internalModuleLut = { { MODULE_TYPE_LEMON_DSMP, "TYPE_LEMON_DSMP" }, }; +static const YamlLookupTable hatsModeLut = { + { GeneralSettings::HATSMODE_TRIMS_ONLY, "TRIMS_ONLY" }, + { GeneralSettings::HATSMODE_KEYS_ONLY, "KEYS_ONLY" }, + { GeneralSettings::HATSMODE_SWITCHABLE, "SWITCHABLE" }, +}; + YamlTelemetryBaudrate::YamlTelemetryBaudrate( const unsigned int* moduleBaudrate) { @@ -181,6 +187,7 @@ Node convert::encode(const GeneralSettings& rhs) node["disableAlarmWarning"] = (int)rhs.disableAlarmWarning; node["disableRssiPoweroffAlarm"] = (int)rhs.disableRssiPoweroffAlarm; node["USBMode"] = rhs.usbMode; + node["hatsMode"] = hatsModeLut << rhs.hatsMode; node["stickDeadZone"] = rhs.stickDeadZone; node["jackMode"] = rhs.jackMode; node["hapticMode"] = rhs.hapticMode; @@ -431,6 +438,7 @@ bool convert::decode(const Node& node, GeneralSettings& rhs) node["disableAlarmWarning"] >> rhs.disableAlarmWarning; node["disableRssiPoweroffAlarm"] >> rhs.disableRssiPoweroffAlarm; node["USBMode"] >> rhs.usbMode; + node["hatsMode"] >> hatsModeLut >> rhs.hatsMode; node["stickDeadZone"] >> rhs.stickDeadZone; node["jackMode"] >> rhs.jackMode; node["hapticMode"] >> rhs.hapticMode; diff --git a/companion/src/firmwares/edgetx/yaml_modeldata.cpp b/companion/src/firmwares/edgetx/yaml_modeldata.cpp index 0059bc92141..cc210f261d6 100644 --- a/companion/src/firmwares/edgetx/yaml_modeldata.cpp +++ b/companion/src/firmwares/edgetx/yaml_modeldata.cpp @@ -88,6 +88,13 @@ static const YamlLookupTable usbJoystickIfModeLut = { { 2, "MULTIAXIS" }, }; +static const YamlLookupTable hatsModeLut = { + { GeneralSettings::HATSMODE_TRIMS_ONLY, "TRIMS_ONLY" }, + { GeneralSettings::HATSMODE_KEYS_ONLY, "KEYS_ONLY" }, + { GeneralSettings::HATSMODE_SWITCHABLE, "SWITCHABLE" }, + { GeneralSettings::HATSMODE_GLOBAL, "GLOBAL" }, +}; + struct YamlTrim { int mode = 0; int ref = 0; @@ -1104,6 +1111,7 @@ Node convert::encode(const ModelData& rhs) } node["modelRegistrationID"] = rhs.registrationId; + node["hatsMode"] = hatsModeLut << rhs.hatsMode; if (Boards::getCapability(board, Board::FunctionSwitches)) { node["functionSwitchConfig"] = rhs.functionSwitchConfig; @@ -1342,6 +1350,7 @@ bool convert::decode(const Node& node, ModelData& rhs) node["view"] >> rhs.view; node["modelRegistrationID"] >> rhs.registrationId; + node["hatsMode"] >> hatsModeLut >> rhs.hatsMode; node["functionSwitchConfig"] >> rhs.functionSwitchConfig; node["functionSwitchGroup"] >> rhs.functionSwitchGroup; diff --git a/companion/src/firmwares/generalsettings.cpp b/companion/src/firmwares/generalsettings.cpp index 1e9b7958a10..60826f1e00f 100644 --- a/companion/src/firmwares/generalsettings.cpp +++ b/companion/src/firmwares/generalsettings.cpp @@ -129,6 +129,8 @@ void GeneralSettings::init() backlightDelay = 2; // 2 * 5 = 10 secs inactivityTimer = 10; + hatsMode = HATSMODE_SWITCHABLE; + // backlightBright = 0; // 0 = 100% if (IS_FAMILY_HORUS_OR_T16(board)) { @@ -675,6 +677,42 @@ AbstractStaticItemModel * GeneralSettings::uartSampleModeItemModel() return mdl; } +QString GeneralSettings::hatsModeToString() const +{ + return hatsModeToString(hatsMode); +} + +// static +QString GeneralSettings::hatsModeToString(int value) +{ + switch(value) { + case HATSMODE_TRIMS_ONLY: + return tr("Trims only"); + case HATSMODE_KEYS_ONLY: + return tr("Keys only"); + case HATSMODE_SWITCHABLE: + return tr("Switchable"); + case HATSMODE_GLOBAL: + return tr("Global"); + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + +// static +AbstractStaticItemModel * GeneralSettings::hatsModeItemModel(bool radio_setup) +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName(AIM_GS_HATSMODE); + + for (int i = 0; i < HATSMODE_COUNT; i++) { + mdl->appendToItemList(hatsModeToString(i), i, i == HATSMODE_GLOBAL && radio_setup ? false : true); + } + + mdl->loadItemList(); + return mdl; +} + /* TrainerMix */ diff --git a/companion/src/firmwares/generalsettings.h b/companion/src/firmwares/generalsettings.h index f651716f40c..794067ebd0c 100644 --- a/companion/src/firmwares/generalsettings.h +++ b/companion/src/firmwares/generalsettings.h @@ -42,6 +42,7 @@ constexpr char AIM_GS_SERIALMODE[] {"gs.serialmode"}; constexpr char AIM_GS_INTMODULEBAUDRATE[] {"gs.intmodulebaudrate"}; constexpr char AIM_GS_STICKDEADZONE[] {"gs.stickdeadzone"}; constexpr char AIM_GS_UARTSAMPLEMODE[] {"gs.uartsamplemode"}; +constexpr char AIM_GS_HATSMODE[] {"gs.hatsmode"}; constexpr char AIM_TRAINERMIX_MODE[] {"trainermix.mode"}; constexpr char AIM_TRAINERMIX_SRC[] {"trainermix.src"}; @@ -171,6 +172,14 @@ class GeneralSettings { UART_SAMPLE_MODE_COUNT }; + enum HatsMode { + HATSMODE_TRIMS_ONLY, + HATSMODE_KEYS_ONLY, + HATSMODE_SWITCHABLE, + HATSMODE_GLOBAL, + HATSMODE_COUNT + }; + GeneralSettings() { clear(); } void clear(); void init(); @@ -206,6 +215,7 @@ class GeneralSettings { bool disableAlarmWarning; bool disableRssiPoweroffAlarm; unsigned int usbMode; + unsigned int hatsMode; unsigned int stickDeadZone; unsigned int jackMode; bool sportPower; @@ -311,6 +321,7 @@ class GeneralSettings { QString serialPortModeToString(int port_nr) const; QString internalModuleBaudrateToString() const; QString uartSampleModeToString() const; + QString hatsModeToString() const; static QString antennaModeToString(int value); static QString bluetoothModeToString(int value); @@ -319,6 +330,7 @@ class GeneralSettings { static FieldRange getPPM_MultiplierRange(); static FieldRange getTxCurrentCalibration(); static QString uartSampleModeToString(int value); + static QString hatsModeToString(int value); static AbstractStaticItemModel * antennaModeItemModel(bool model_setup = false); static AbstractStaticItemModel * bluetoothModeItemModel(); @@ -326,4 +338,5 @@ class GeneralSettings { static AbstractStaticItemModel * internalModuleBaudrateItemModel(); static AbstractStaticItemModel * stickDeadZoneItemModel(); static AbstractStaticItemModel * uartSampleModeItemModel(); + static AbstractStaticItemModel * hatsModeItemModel(bool radio_setup = true); }; diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index 669ce84ea0a..b8a7ee96b94 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -181,6 +181,8 @@ void ModelData::clear() const char * layoutId = "Layout2P1"; // currently all using same default though might change for NV14 RadioLayout::init(layoutId, customScreens); + + hatsMode = GeneralSettings::HATSMODE_GLOBAL; } bool ModelData::isEmpty() const diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index 8df7a30f7c1..632fd4660ed 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -192,6 +192,7 @@ class ModelData { unsigned int view; char registrationId[8+1]; + unsigned int hatsMode; // Radio level tabs control (global settings) unsigned int radioThemesDisabled; diff --git a/companion/src/generaledit/generalsetup.cpp b/companion/src/generaledit/generalsetup.cpp index 14ac57b23b7..f58c932d1c9 100644 --- a/companion/src/generaledit/generalsetup.cpp +++ b/companion/src/generaledit/generalsetup.cpp @@ -20,6 +20,9 @@ #include "generalsetup.h" #include "ui_generalsetup.h" +#include "compounditemmodels.h" +#include "filtereditemmodels.h" +#include "autocombobox.h" GeneralSetupPanel::GeneralSetupPanel(QWidget * parent, GeneralSettings & generalSettings, Firmware * firmware): GeneralPanel(parent, generalSettings, firmware), @@ -27,10 +30,12 @@ ui(new Ui::GeneralSetup) { ui->setupUi(this); + Board::Type board = firmware->getBoard(); + QLabel *pmsl[] = {ui->ro_label, ui->ro1_label, ui->ro2_label, ui->ro3_label, ui->ro4_label, ui->ro5_label, ui->ro6_label, ui->ro7_label, ui->ro8_label, NULL}; QSlider *tpmsld[] = {ui->chkSA, ui->chkSB, ui->chkSC, ui->chkSD, ui->chkSE, ui->chkSF, ui->chkSG, ui->chkSH, NULL}; - if (IS_TARANIS(firmware->getBoard())) { + if (IS_TARANIS(board)) { if (firmware->getId().contains("readonly")) { uint16_t switchstate = generalSettings.switchUnlockStates; ui->chkSA->setValue(switchstate & 0x3); @@ -153,14 +158,14 @@ ui(new Ui::GeneralSetup) ui->timezoneLE->setTime((generalSettings.timezone * 3600) + (generalSettings.timezoneMinutes/*quarter hours*/ * 15 * 60)); - if (IS_HORUS_OR_TARANIS(firmware->getBoard())) { + if (IS_HORUS_OR_TARANIS(board)) { ui->adjustRTC->setChecked(generalSettings.adjustRTC); } else { ui->adjustRTC->hide(); } - if (IS_STM32(firmware->getBoard())) { + if (IS_STM32(board)) { ui->usbModeCB->setCurrentIndex(generalSettings.usbMode); } else { @@ -168,6 +173,15 @@ ui(new Ui::GeneralSetup) ui->usbModeCB->hide(); } + if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board)) { + ui->hatsModeCB->setModel(new FilteredItemModel(GeneralSettings::hatsModeItemModel())); + ui->hatsModeCB->setField(generalSettings.hatsMode, this); + } + else { + ui->hatsModeLabel->hide(); + ui->hatsModeCB->hide(); + } + if (firmware->getCapability(HasSwitchableJack)) { ui->jackModeCB->setCurrentIndex(generalSettings.jackMode); } @@ -200,13 +214,13 @@ ui(new Ui::GeneralSetup) ui->label_BLBright->hide(); } - if (!IS_FAMILY_HORUS_OR_T16(firmware->getBoard())) { + if (!IS_FAMILY_HORUS_OR_T16(board)) { ui->OFFBright_SB->hide(); ui->OFFBright_SB->setDisabled(true); ui->label_OFFBright->hide(); } - if (!IS_JUMPER_T18(firmware->getBoard())) { + if (!IS_JUMPER_T18(board)) { ui->keysBl_ChkB->hide(); ui->keysBl_ChkB->setDisabled(true); ui->label_KeysBl->hide(); @@ -262,7 +276,7 @@ ui(new Ui::GeneralSetup) ui->pwrOffDelayLabel->hide(); ui->pwrOffDelay->hide(); } - else if (!IS_TARANIS(firmware->getBoard())) { + else if (!IS_TARANIS(board)) { ui->pwrOnDelayLabel->hide(); ui->pwrOnDelay->hide(); } @@ -279,7 +293,7 @@ ui(new Ui::GeneralSetup) connect(tpmsld[i], SIGNAL(valueChanged(int)),this,SLOT(unlockSwitchEdited())); } - if (!IS_HORUS_OR_TARANIS(firmware->getBoard())) { + if (!IS_HORUS_OR_TARANIS(board)) { ui->stickReverse1->setChecked(generalSettings.stickReverse & (1 << 0)); ui->stickReverse2->setChecked(generalSettings.stickReverse & (1 << 1)); ui->stickReverse3->setChecked(generalSettings.stickReverse & (1 << 2)); @@ -297,7 +311,7 @@ ui(new Ui::GeneralSetup) ui->stickReverse4->hide(); } - if (IS_TARANIS_PLUS(firmware->getBoard())) { + if (IS_TARANIS_PLUS(board)) { ui->backlightColor_SL->setValue(generalSettings.backlightColor); } else { @@ -396,7 +410,6 @@ void GeneralSetupPanel::on_jackModeCB_currentIndexChanged(int index) } } - void GeneralSetupPanel::on_backlightColor_SL_valueChanged() { if (!lock) { diff --git a/companion/src/generaledit/generalsetup.ui b/companion/src/generaledit/generalsetup.ui index 68a514176b3..c151b300b2c 100644 --- a/companion/src/generaledit/generalsetup.ui +++ b/companion/src/generaledit/generalsetup.ui @@ -1682,6 +1682,16 @@ p, li { white-space: pre-wrap; } + + + + Hats Mode + + + + + + diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index cf5aaa0d42a..4d9d144f790 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -36,6 +36,7 @@ constexpr char FIM_TIMERSWITCH[] {"Timer Switch"}; constexpr char FIM_THRSOURCE[] {"Throttle Source"}; constexpr char FIM_TRAINERMODE[] {"Trainer Mode"}; constexpr char FIM_ANTENNAMODE[] {"Antenna Mode"}; +constexpr char FIM_HATSMODE[] {"Hats Mode"}; TimerPanel::TimerPanel(QWidget * parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, QWidget * prevFocus, FilteredItemModelFactory * panelFilteredModels, CompoundItemModelFactory * panelItemModels): @@ -1474,6 +1475,8 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge panelItemModels->registerItemModel(TimerData::persistentItemModel()); panelItemModels->registerItemModel(TimerData::modeItemModel()); panelItemModels->registerItemModel(TimerData::showElapsedItemModel()); + panelFilteredModels->registerItemModel(new FilteredItemModel(GeneralSettings::hatsModeItemModel(false)), FIM_HATSMODE); + Board::Type board = firmware->getBoard(); memset(modules, 0, sizeof(modules)); @@ -1693,6 +1696,15 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge ui->trimsDisplay->setField(model.trimsDisplay, this); + if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board)) { + ui->cboHatsMode->setModel(panelFilteredModels->getItemModel(FIM_HATSMODE)); + ui->cboHatsMode->setField(model.hatsMode, this); + } + else { + ui->lblHatsMode->hide(); + ui->cboHatsMode->hide(); + } + if (Boards::getCapability(firmware->getBoard(), Board::FunctionSwitches) > 0) { funcswitches = new FunctionSwitchesPanel(this, model, generalSettings, firmware); ui->functionSwitchesLayout->addWidget(funcswitches); diff --git a/companion/src/modeledit/setup.ui b/companion/src/modeledit/setup.ui index 9ff59393630..de0498958ab 100644 --- a/companion/src/modeledit/setup.ui +++ b/companion/src/modeledit/setup.ui @@ -184,7 +184,7 @@ - + 50 @@ -192,7 +192,7 @@ - + Hats Mode Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -627,6 +627,9 @@ + + + diff --git a/companion/src/modelprinter.cpp b/companion/src/modelprinter.cpp index 64113fc95f2..5501340990f 100644 --- a/companion/src/modelprinter.cpp +++ b/companion/src/modelprinter.cpp @@ -840,6 +840,10 @@ QString ModelPrinter::printSettingsTrim() str << printLabelValue(tr("Step"), printTrimIncrementMode()); str << printLabelValue(tr("Display"), printTrimsDisplayMode()); str << printLabelValue(tr("Extended"), printBoolean(model.extendedTrims, BOOLEAN_YESNO)); + Board::Type board = firmware->getBoard(); + if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board)) { + str << printLabelValue(tr("Hats Mode"), printHatsMode()); + } return str.join(" "); } @@ -869,6 +873,22 @@ QString ModelPrinter::printTrimsDisplayMode() } } +QString ModelPrinter::printHatsMode() +{ + switch (model.hatsMode) { + case GeneralSettings::HATSMODE_TRIMS_ONLY: + return tr("Trims only"); + case GeneralSettings::HATSMODE_KEYS_ONLY: + return tr("Keys only"); + case GeneralSettings::HATSMODE_SWITCHABLE: + return tr("Switchable"); + case GeneralSettings::HATSMODE_GLOBAL: + return tr("Global"); + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + QString ModelPrinter::printModuleType(int idx) { return ModuleData::indexToString(idx, firmware); diff --git a/companion/src/modelprinter.h b/companion/src/modelprinter.h index e101d24b612..a9aae03bf67 100644 --- a/companion/src/modelprinter.h +++ b/companion/src/modelprinter.h @@ -79,6 +79,7 @@ class ModelPrinter: public QObject QString printModuleType(int idx); QString printThrottleSource(int idx); QString printTrimsDisplayMode(); + QString printHatsMode(); QString printSettingsTrim(); QString printSwitchWarnings(); QString printPotWarnings(); diff --git a/companion/src/translations/companion_cs.ts b/companion/src/translations/companion_cs.ts index 54d2c86ad4a..2cad1514195 100644 --- a/companion/src/translations/companion_cs.ts +++ b/companion/src/translations/companion_cs.ts @@ -5621,6 +5621,31 @@ Použitelné hodnoty jsou 5v..10v {3v?} {12v?} USB Serial (CDC) + + + Hats Mode + Režim kloboučků + + + + Trims only + Pouze trimy + + + + Keys only + Pouze tlačítka + + + + Switchable + Přepinatelné + + + + Global + Globální + Stick Mode diff --git a/companion/src/translations/companion_da.ts b/companion/src/translations/companion_da.ts index 0b5ac146db7..51fe99cf3f7 100644 --- a/companion/src/translations/companion_da.ts +++ b/companion/src/translations/companion_da.ts @@ -6035,6 +6035,31 @@ Tilstand 4: USB Serial (CDC) Seriel USB (CDC) + + + Hats Mode + Joystik indstilling + + + + Trims only + Kun trim + + + + Keys only + Kun knap + + + + Switchable + Trim / Knap + + + + Global + Global + Owner Registration ID diff --git a/companion/src/translations/companion_de.ts b/companion/src/translations/companion_de.ts index cedcce63865..eab3bbd589f 100644 --- a/companion/src/translations/companion_de.ts +++ b/companion/src/translations/companion_de.ts @@ -5596,6 +5596,31 @@ Werte liegen zwischen 5-10V {3v?} {12v?} USB Serial (CDC) USB Serial (CDC) + + + Hats Mode + Joystick Modus + + + + Trims only + Nur Trimmung + + + + Keys only + Nur Tasten + + + + Switchable + Umschaltbar + + + + Global + Global + Stick Mode diff --git a/companion/src/translations/companion_en.ts b/companion/src/translations/companion_en.ts index 1979b5d2c8d..8b997b53e17 100644 --- a/companion/src/translations/companion_en.ts +++ b/companion/src/translations/companion_en.ts @@ -5351,6 +5351,26 @@ Mode 4: USB Serial (CDC) + + + Hats Mode + + + + + Trims only + + + + + Keys only + + + + + Switchable + + <html><head/><body><p>Channel order</p><p><br/></p><p>Defines the order of the default mixes created on a new model.</p></body></html> diff --git a/companion/src/translations/companion_es.ts b/companion/src/translations/companion_es.ts index c0bb8429720..85059188119 100644 --- a/companion/src/translations/companion_es.ts +++ b/companion/src/translations/companion_es.ts @@ -5670,6 +5670,26 @@ Los valores aceptables son 5v..10v {3v?} {12v?} USB Serial (CDC) USB Serial (CDC) + + + Hats Mode + + + + + Trims only + + + + + Keys only + + + + + Switchable + + Stick Mode diff --git a/companion/src/translations/companion_fi.ts b/companion/src/translations/companion_fi.ts index df67de65203..082d3b85919 100644 --- a/companion/src/translations/companion_fi.ts +++ b/companion/src/translations/companion_fi.ts @@ -5649,6 +5649,26 @@ Hyväksytty arvo: 5v - 10v {3v?} {12v?} USB Serial (CDC) + + + Hats Mode + + + + + Trims only + + + + + Keys only + + + + + Switchable + + Stick Mode diff --git a/companion/src/translations/companion_fr.ts b/companion/src/translations/companion_fr.ts index 89388e23338..c40d977f658 100644 --- a/companion/src/translations/companion_fr.ts +++ b/companion/src/translations/companion_fr.ts @@ -5648,6 +5648,31 @@ Plage de valeurs: 3v...12v USB Serial (CDC) Port série USB (Debug) + + + Hats Mode + Mode joystick + + + + Trims only + Trims uniquement + + + + Keys only + Touches uniquement + + + + Switchable + Commutable + + + + Global + Global + Stick Mode diff --git a/companion/src/translations/companion_he.ts b/companion/src/translations/companion_he.ts index 976bcb97366..cfe071230d9 100644 --- a/companion/src/translations/companion_he.ts +++ b/companion/src/translations/companion_he.ts @@ -5815,6 +5815,31 @@ p, li { white-space: pre-wrap; } USB Serial (CDC) + + + Hats Mode + מצב כובעונים + + + + Trims only + קיזוזים בלבד + + + + Keys only + ניווט בלבד + + + + Switchable + משולב + + + + Global + גלובאלי + Measurement Units diff --git a/companion/src/translations/companion_it.ts b/companion/src/translations/companion_it.ts index abb2d520e93..8d94c926b9d 100644 --- a/companion/src/translations/companion_it.ts +++ b/companion/src/translations/companion_it.ts @@ -5614,6 +5614,31 @@ Mode 4: USB Serial (CDC) + + + Hats Mode + Modo joystick + + + + Trims only + Solo trims + + + + Keys only + Solo keys + + + + Switchable + Commutabile + + + + Global + Globale + Stick Mode diff --git a/companion/src/translations/companion_ja.ts b/companion/src/translations/companion_ja.ts index 8072e380b74..9264410648a 100644 --- a/companion/src/translations/companion_ja.ts +++ b/companion/src/translations/companion_ja.ts @@ -5977,6 +5977,31 @@ Mode 4: USB Serial (CDC) USBシリアル (CDC) + + + Hats Mode + アナログスティック + + + + Trims only + トリムのみ + + + + Keys only + キーのみ + + + + Switchable + スイッチ + + + + Global + すべて + GeneralSetupPanel diff --git a/companion/src/translations/companion_nl.ts b/companion/src/translations/companion_nl.ts index 3c8dc05026c..7edf9e0bbe4 100644 --- a/companion/src/translations/companion_nl.ts +++ b/companion/src/translations/companion_nl.ts @@ -5815,6 +5815,26 @@ p, li { white-space: pre-wrap; } USB Serial (CDC) + + + Hats Mode + + + + + Trims only + + + + + Keys only + + + + + Switchable + + Measurement Units diff --git a/companion/src/translations/companion_pl.ts b/companion/src/translations/companion_pl.ts index 40152048750..10c705cf8c5 100644 --- a/companion/src/translations/companion_pl.ts +++ b/companion/src/translations/companion_pl.ts @@ -5949,6 +5949,31 @@ Dopuszczalne wartości 5v-10v {3v?} {12v?} USB Serial (CDC) + + + Hats Mode + Tryb grzybków + + + + Trims only + Tylko trymy + + + + Keys only + Tylko przyciski + + + + Switchable + Przełączane + + + + Global + Globalne + Stick reverse diff --git a/companion/src/translations/companion_pt.ts b/companion/src/translations/companion_pt.ts index 44b20223314..ff57229d571 100644 --- a/companion/src/translations/companion_pt.ts +++ b/companion/src/translations/companion_pt.ts @@ -5815,6 +5815,26 @@ p, li { white-space: pre-wrap; } USB Serial (CDC) + + + Hats Mode + + + + + Trims only + + + + + Keys only + + + + + Switchable + + Measurement Units diff --git a/companion/src/translations/companion_ru.ts b/companion/src/translations/companion_ru.ts index 0e772f353b5..a4fbfa529b0 100644 --- a/companion/src/translations/companion_ru.ts +++ b/companion/src/translations/companion_ru.ts @@ -5873,6 +5873,26 @@ p, li { white-space: pre-wrap; } USB Serial (CDC) Последовательный порт + + + Hats Mode + + + + + Trims only + + + + + Keys only + + + + + Switchable + + Measurement Units diff --git a/companion/src/translations/companion_sv.ts b/companion/src/translations/companion_sv.ts index 44a750dd5a7..74d1e7f5186 100644 --- a/companion/src/translations/companion_sv.ts +++ b/companion/src/translations/companion_sv.ts @@ -6026,7 +6026,31 @@ Mode 4: Seriell USB (CDC) - + + Hats Mode + Hattläge + + + + Trims only + Endast trimm + + + + Keys only + Endast knapp + + + + Switchable + Ändringsbar + + + + Global + Global + + Owner Registration ID ID för ägarregistrering diff --git a/companion/src/translations/companion_zh_CN.ts b/companion/src/translations/companion_zh_CN.ts index 64762408afa..ff1ec6c1554 100644 --- a/companion/src/translations/companion_zh_CN.ts +++ b/companion/src/translations/companion_zh_CN.ts @@ -5703,6 +5703,31 @@ Acceptable values are 3v..12v USB Serial (CDC) + + + Hats Mode + 按键帽模式 + + + + Trims only + 微调 + + + + Keys only + 导航键 + + + + Switchable + 可切换 + + + + Global + 全局 + Stick Mode diff --git a/companion/src/translations/companion_zh_TW.ts b/companion/src/translations/companion_zh_TW.ts index c8f002168e6..4bbb9b6efd3 100644 --- a/companion/src/translations/companion_zh_TW.ts +++ b/companion/src/translations/companion_zh_TW.ts @@ -5703,6 +5703,31 @@ Acceptable values are 3v..12v USB Serial (CDC) + + + Hats Mode + 按鍵帽模式 + + + + Trims only + 微調 + + + + Keys only + 導航鍵 + + + + Switchable + 可切換 + + + + Global + 全局 + Stick Mode diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index 03ece165595..645a625f236 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -658,6 +658,13 @@ enum BluetoothModes { #endif }; +enum HatsMode { + HATSMODE_TRIMS_ONLY, + HATSMODE_KEYS_ONLY, + HATSMODE_SWITCHABLE, + HATSMODE_GLOBAL +}; + enum UartSampleModes { UART_SAMPLE_MODE_NORMAL = 0, UART_SAMPLE_MODE_ONEBIT, diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index 347730b1357..b10efab5afe 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -679,7 +679,8 @@ PACK(struct ModelData { uint8_t disableTelemetryWarning:1; uint8_t showInstanceIds:1; uint8_t checklistInteractive:1; - uint8_t spare3:4 SKIP; // padding to 8-bit aligment + NOBACKUP(uint8_t hatsMode:2 ENUM(HatsMode)); + uint8_t spare3:2 SKIP; // padding to 8-bit aligment int8_t customThrottleWarningPosition; BeepANACenter beepANACenter; MixData mixData[MAX_MIXERS] NO_IDX; @@ -841,7 +842,8 @@ PACK(struct RadioData { // Real attributes NOBACKUP(uint8_t manuallyEdited:1); int8_t timezoneMinutes:3; // -3 to +3 ==> (-45 to 45 minutes in 15 minute increments) - NOBACKUP(int8_t spare0:4 SKIP); + NOBACKUP(uint8_t hatsMode:2 ENUM(HatsMode)); + NOBACKUP(int8_t spare0:2 SKIP); CUST_ATTR(semver,nullptr,w_semver); CUST_ATTR(board,nullptr,w_board); CalibData calib[MAX_CALIB_ANALOG_INPUTS] NO_IDX; diff --git a/radio/src/gui/colorlcd/LvglWrapper.cpp b/radio/src/gui/colorlcd/LvglWrapper.cpp index 6c7109feb51..cd27aa238cf 100644 --- a/radio/src/gui/colorlcd/LvglWrapper.cpp +++ b/radio/src/gui/colorlcd/LvglWrapper.cpp @@ -235,7 +235,27 @@ extern "C" void touchDriverRead(lv_indev_drv_t *drv, lv_indev_data_t *data) #endif } -#if defined(ROTARY_ENCODER_NAVIGATION) +#if defined(USE_HATS_AS_KEYS) + +int16_t getEmuRotaryData(); + +static void rotaryDriverRead(lv_indev_drv_t *drv, lv_indev_data_t *data) +{ + int16_t diff = getEmuRotaryData(); + + if(diff != 0) { + reset_inactivity(); + audioKeyPress(); + + data->enc_diff = diff; + data->state = LV_INDEV_STATE_RELEASED; + } +} + +// libopenui_depends.h +int8_t rotaryEncoderGetAccel() { return 0; } + +#elif defined(ROTARY_ENCODER_NAVIGATION) extern volatile uint32_t rotencDt; static int8_t _rotary_enc_accel = 0; diff --git a/radio/src/gui/colorlcd/radio_ghost_module_config.cpp b/radio/src/gui/colorlcd/radio_ghost_module_config.cpp index a328687ef3a..f5976861f1c 100644 --- a/radio/src/gui/colorlcd/radio_ghost_module_config.cpp +++ b/radio/src/gui/colorlcd/radio_ghost_module_config.cpp @@ -130,7 +130,7 @@ RadioGhostModuleConfig::RadioGhostModuleConfig(uint8_t moduleIdx) : lv_group_set_editing(lv_group_get_default(), true); lv_obj_add_event_cb(lvobj, ghostmoduleconfig_cb, LV_EVENT_KEY, this); #if defined(TRIMS_EMULATE_BUTTONS) - setTrimsAsButtons(true); // Use trim joysticks to operate menu (e.g. on NV14) + setHatsAsKeys(true); // Use trim joysticks to operate menu (e.g. on NV14) #endif } @@ -156,7 +156,7 @@ void RadioGhostModuleConfig::onEvent(event_t event) RTOS_WAIT_MS(10); Page::onEvent(event); #if defined(TRIMS_EMULATE_BUTTONS) - setTrimsAsButtons(false); // switch trims back to normal + setHatsAsKeys(false); // switch trims back to normal #endif break; } @@ -175,7 +175,7 @@ void RadioGhostModuleConfig::checkEvents() RTOS_WAIT_MS(10); deleteLater(); #if defined(TRIMS_EMULATE_BUTTONS) - setTrimsAsButtons(false); // switch trims back to normal + setHatsAsKeys(false); // switch trims back to normal #endif } } diff --git a/radio/src/gui/colorlcd/radio_setup.cpp b/radio/src/gui/colorlcd/radio_setup.cpp index e81e7823bcb..49b907401aa 100644 --- a/radio/src/gui/colorlcd/radio_setup.cpp +++ b/radio/src/gui/colorlcd/radio_setup.cpp @@ -803,7 +803,7 @@ void RadioSetupPage::build(FormWindow * window) new Choice(line, rect_t{}, STR_USBMODES, USB_UNSELECTED_MODE, USB_MAX_MODE, GET_SET_DEFAULT(g_eeGeneral.USBMode)); -#if defined(ROTARY_ENCODER_NAVIGATION) +#if defined(ROTARY_ENCODER_NAVIGATION) && !defined(USE_HATS_AS_KEYS) line = window->newLine(&grid); new StaticText(line, rect_t{}, STR_ROTARY_ENC_MODE, 0, COLOR_THEME_PRIMARY1); new Choice(line, rect_t{}, STR_ROTARY_ENC_OPT, ROTARY_ENCODER_MODE_NORMAL, @@ -811,6 +811,13 @@ void RadioSetupPage::build(FormWindow * window) GET_SET_DEFAULT(g_eeGeneral.rotEncMode)); #endif +#if defined(USE_HATS_AS_KEYS) + line = window->newLine(&grid); + new StaticText(line, rect_t{}, STR_HATSMODE, 0, COLOR_THEME_PRIMARY1); + new Choice(line, rect_t{}, STR_HATSOPT, HATSMODE_TRIMS_ONLY, HATSMODE_SWITCHABLE, + GET_SET_DEFAULT(g_eeGeneral.hatsMode)); +#endif + // RX channel order line = window->newLine(&grid); new StaticText(line, rect_t{}, STR_DEF_CHAN_ORD, 0, diff --git a/radio/src/gui/colorlcd/tabsgroup.cpp b/radio/src/gui/colorlcd/tabsgroup.cpp index 4e87c61a5a4..ba66d01c84e 100644 --- a/radio/src/gui/colorlcd/tabsgroup.cpp +++ b/radio/src/gui/colorlcd/tabsgroup.cpp @@ -274,7 +274,7 @@ void TabsGroup::onEvent(event_t event) #if defined(HARDWARE_KEYS) TRACE_WINDOWS("%s received event 0x%X", getWindowDebugString().c_str(), event); -#if defined(KEYS_GPIO_REG_PAGEUP) +#if defined(KEYS_GPIO_REG_PAGEUP) || defined(USE_HATS_AS_KEYS) if (event == EVT_KEY_FIRST(KEY_PAGEDN)) { #else if (event == EVT_KEY_BREAK(KEY_PAGEDN)) { @@ -283,7 +283,7 @@ void TabsGroup::onEvent(event_t event) uint8_t current = header.carousel.getCurrentIndex() + 1; setCurrentTab(current >= tabs.size() ? 0 : current); } -#if defined(KEYS_GPIO_REG_PAGEUP) +#if defined(KEYS_GPIO_REG_PAGEUP) || defined(USE_HATS_AS_KEYS) else if (event == EVT_KEY_FIRST(KEY_PAGEUP)) { #else else if (event == EVT_KEY_LONG(KEY_PAGEDN)) { diff --git a/radio/src/gui/colorlcd/trims_setup.cpp b/radio/src/gui/colorlcd/trims_setup.cpp index 25df41ef811..d355bc1b979 100644 --- a/radio/src/gui/colorlcd/trims_setup.cpp +++ b/radio/src/gui/colorlcd/trims_setup.cpp @@ -55,6 +55,14 @@ TrimsSetup::TrimsSetup() : Page(ICON_MODEL_SETUP) auto btn_obj = btn->getLvObj(); lv_obj_set_width(btn_obj, lv_pct(100)); +#if defined(USE_HATS_AS_KEYS) + // Hats mode for NV14/EL18 + line = body.newLine(&grid); + new StaticText(line, rect_t{}, STR_HATSMODE, 0, COLOR_THEME_PRIMARY1); + new Choice(line, rect_t{}, STR_HATSOPT, HATSMODE_TRIMS_ONLY, HATSMODE_GLOBAL, + GET_SET_DEFAULT(g_model.hatsMode)); +#endif + // Trim step line = body.newLine(&grid); new StaticText(line, rect_t{}, STR_TRIMINC, 0, diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 8c4bc52d827..3c8e690c244 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -280,7 +280,7 @@ void ViewMain::onEvent(event_t event) new ScreenMenu(); break; -#if defined(KEYS_GPIO_REG_PAGEUP) +#if defined(KEYS_GPIO_REG_PAGEUP) || defined(USE_HATS_AS_KEYS) case EVT_KEY_FIRST(KEY_PAGEDN): #else case EVT_KEY_BREAK(KEY_PAGEDN): @@ -293,7 +293,7 @@ void ViewMain::onEvent(event_t event) //TODO: these need to go away! // -> board code should map the keys as required -#if defined(KEYS_GPIO_REG_PAGEUP) +#if defined(KEYS_GPIO_REG_PAGEUP) || defined(USE_HATS_AS_KEYS) case EVT_KEY_FIRST(KEY_PAGEUP): #else case EVT_KEY_LONG(KEY_PAGEDN): diff --git a/radio/src/keys.cpp b/radio/src/keys.cpp index f10af2cc84c..f169a8b23ac 100644 --- a/radio/src/keys.cpp +++ b/radio/src/keys.cpp @@ -18,6 +18,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ +#if !defined(BOOT) && defined(USE_HATS_AS_KEYS) +#include "opentx.h" +#endif #include "keys.h" @@ -290,27 +293,121 @@ uint8_t keysGetTrimState(uint8_t trim) return trim_keys[trim].pressed(); } -#if defined(USE_TRIMS_AS_BUTTONS) +#if defined(USE_HATS_AS_KEYS) +#define ROTARY_EMU_KEY_REPEAT_RATE 12 // times 10 [ms] + static bool _trims_as_buttons = false; +static bool _trims_as_buttons_LUA = false; -void setTrimsAsButtons(bool val) { _trims_as_buttons = val; } -bool getTrimsAsButtons() { return _trims_as_buttons; } +void setHatsAsKeys(bool val) { _trims_as_buttons = val; } +bool getHatsAsKeys() { return _trims_as_buttons; } -static uint32_t transpose_trims() +void setTransposeHatsForLUA(bool val) { _trims_as_buttons_LUA = val; } +bool getTransposeHatsForLUA() { return _trims_as_buttons_LUA; } + +int16_t getEmuRotaryData() { - uint32_t keys = 0; + static bool rotaryTrimPressed = false; + static tmr10ms_t timePressed = 0; + + if (getHatsAsKeys() || getTransposeHatsForLUA()) { + tmr10ms_t now = get_tmr10ms(); + + if (rotaryTrimPressed) { + if (now < (timePressed + ROTARY_EMU_KEY_REPEAT_RATE)) return 0; + + rotaryTrimPressed = false; + } + + auto trims = readTrims(); + + if (trims & (1 << 4)) { + rotaryTrimPressed = true; + timePressed = now; + return 1; + } + + if (trims & (1 << 5)) { + rotaryTrimPressed = true; + timePressed = now; + return -1; + } + } + + return 0; +} + +static void transpose_trims(uint32_t *keys) +{ +#if defined(BOOT) auto trims = readTrims(); - if (trims & (1 << 0)) keys |= 1 << KEY_SYS; - if (trims & (1 << 1)) keys |= 1 << KEY_TELE; - if (trims & (1 << 2)) keys |= 1 << KEY_PAGEUP; - if (trims & (1 << 3)) keys |= 1 << KEY_PAGEDN; - if (trims & (1 << 4)) keys |= 1 << KEY_DOWN; - if (trims & (1 << 5)) keys |= 1 << KEY_UP; - if (trims & (1 << 6)) keys |= 1 << KEY_LEFT; - if (trims & (1 << 7)) keys |= 1 << KEY_RIGHT; + if (trims & (1 << 4)) *keys |= 1 << KEY_DOWN; // right hat, down 0x10 + if (trims & (1 << 5)) *keys |= 1 << KEY_UP; // right hat, up 0x20 +#else + static uint8_t state = 0; + + bool allowModeSwitch = ((g_model.hatsMode == HATSMODE_GLOBAL && + g_eeGeneral.hatsMode == HATSMODE_SWITCHABLE) || + (g_model.hatsMode == HATSMODE_SWITCHABLE)) && + !getTransposeHatsForLUA(); + + if (allowModeSwitch) { + static bool lastExitState = false; + static bool lastEnterState = false; + + bool exitState = + *keys & (1 << KEY_EXIT); // edge detection for EXIT and ENTER keys + bool enterState = *keys & (1 << KEY_ENTER); + + bool exitPressed = !lastExitState && exitState; + bool exitReleased = lastExitState && !exitState; + bool enterPressed = !lastEnterState && enterState; + + lastExitState = exitState; + lastEnterState = enterState; + + switch (state) { + case 0: // idle state waiting for EXIT or ENTER key + if (exitPressed) { + state = 1; + } + break; + + case 1: // state EXIT received + if (exitReleased) { // if exit released go back to idle state + state = 0; + break; + } + + if (enterPressed) { // ENTER received with EXIT still pressed + setHatsAsKeys(!getHatsAsKeys()); // change mode and don't forward + // EXIT and ENTER keys + killEvents(KEY_EXIT); + killEvents(KEY_ENTER); + state = 0; // go to for EXIT to be released + break; + } + break; + } + } else + state = 0; // state machine in idle if not in mode "BOTH" + + if (getHatsAsKeys() || // map hats to keys in button mode or LUA active + getTransposeHatsForLUA()) { + auto trims = readTrims(); + + // spare key in buttons mode: left hat left + // if (trims & (1 << 0)) *keys |= 1 << tbd; // left hat, left 0x01 + if (trims & (1 << 1)) *keys |= 1 << KEY_MODEL; // left hat, right 0x02 + if (trims & (1 << 2)) *keys |= 1 << KEY_TELE; // left hat, down 0x04 + if (trims & (1 << 3)) *keys |= 1 << KEY_SYS; // left hat, up 0x08 + + if (trims & (1 << 6)) *keys |= 1 << KEY_PAGEUP; // rht, left 0x40 + if (trims & (1 << 7)) *keys |= 1 << KEY_PAGEDN; // rht, right 0x80 + } - return keys; +#endif } #endif @@ -319,9 +416,10 @@ bool keysPollingCycle() uint32_t trims_input; uint32_t keys_input = readKeys(); -#if defined(USE_TRIMS_AS_BUTTONS) - if (getTrimsAsButtons()) { - keys_input |= transpose_trims(); +#if defined(USE_HATS_AS_KEYS) + transpose_trims(&keys_input); + + if (getHatsAsKeys() || getTransposeHatsForLUA()) { trims_input = 0; } else { trims_input = readTrims(); diff --git a/radio/src/keys.h b/radio/src/keys.h index 406b442e730..a2c6619f0e5 100644 --- a/radio/src/keys.h +++ b/radio/src/keys.h @@ -180,9 +180,11 @@ uint8_t keysGetTrimState(uint8_t trim); bool keysPollingCycle(); bool rotaryEncoderPollingCycle(); -#if defined(USE_TRIMS_AS_BUTTONS) -void setTrimsAsButtons(bool val); -bool getTrimsAsButtons(); +#if defined(USE_HATS_AS_KEYS) +void setHatsAsKeys(bool val); +bool getHatsAsKeys(); +void setTransposeHatsForLUA(bool val); +bool getTransposeHatsForLUA(); #endif struct InactivityData diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 427486ad6af..f6d9b9560d6 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -886,7 +886,7 @@ Return rotary encoder mode */ static int luaGetRotEncMode(lua_State * L) { -#if defined(ROTARY_ENCODER_NAVIGATION) +#if defined(ROTARY_ENCODER_NAVIGATION) && !defined(USE_HATS_AS_KEYS) lua_pushunsigned(L, g_eeGeneral.rotEncMode); #else lua_pushunsigned(L, 0); @@ -3030,7 +3030,7 @@ LROT_BEGIN(etxcst, NULL, 0) #endif // Virtual events -#if defined(ROTARY_ENCODER_NAVIGATION) +#if defined(ROTARY_ENCODER_NAVIGATION) || defined(USE_TRIMS_AS_BUTTOS) LROT_NUMENTRY( EVT_VIRTUAL_PREV, EVT_ROTARY_LEFT ) LROT_NUMENTRY( EVT_VIRTUAL_NEXT, EVT_ROTARY_RIGHT ) LROT_NUMENTRY( EVT_VIRTUAL_DEC, EVT_ROTARY_LEFT ) @@ -3090,12 +3090,9 @@ LROT_BEGIN(etxcst, NULL, 0) LROT_NUMENTRY( EVT_VIRTUAL_ENTER_LONG, EVT_KEY_LONG(KEY_ENTER) ) LROT_NUMENTRY( EVT_VIRTUAL_EXIT, EVT_KEY_BREAK(KEY_EXIT) ) #elif defined(COLORLCD) -#if defined(KEYS_GPIO_REG_PAGEUP) +#if defined(KEYS_GPIO_REG_PAGEUP) || defined(USE_HATS_AS_KEYS) LROT_NUMENTRY( EVT_VIRTUAL_PREV_PAGE, EVT_KEY_BREAK(KEY_PAGEUP) ) LROT_NUMENTRY( EVT_VIRTUAL_NEXT_PAGE, EVT_KEY_BREAK(KEY_PAGEDN) ) -#elif defined(PCBNV14) - LROT_NUMENTRY( EVT_VIRTUAL_PREV_PAGE, EVT_KEY_BREAK(KEY_LEFT) ) - LROT_NUMENTRY( EVT_VIRTUAL_NEXT_PAGE, EVT_KEY_BREAK(KEY_RIGHT) ) #else LROT_NUMENTRY( EVT_VIRTUAL_PREV_PAGE, EVT_KEY_LONG(KEY_PAGEDN) ) LROT_NUMENTRY( EVT_VIRTUAL_NEXT_PAGE, EVT_KEY_BREAK(KEY_PAGEDN) ) @@ -3107,6 +3104,7 @@ LROT_BEGIN(etxcst, NULL, 0) LROT_NUMENTRY( EVT_VIRTUAL_EXIT, EVT_KEY_BREAK(KEY_EXIT) ) #endif + // key events LROT_NUMENTRY( EVT_EXIT_BREAK, EVT_KEY_BREAK(KEY_EXIT) ) #if defined(KEYS_GPIO_REG_ENTER) @@ -3117,19 +3115,19 @@ LROT_BEGIN(etxcst, NULL, 0) KEY_EVENTS(MENU, KEY_MENU) #endif -#if defined(KEYS_GPIO_REG_RIGHT) && defined(COLORLCD) +#if defined(KEYS_GPIO_REG_RIGHT) && defined(COLORLCD) || defined(USE_HATS_AS_KEYS) KEY_EVENTS(TELEM, KEY_TELE) #elif defined(KEYS_GPIO_REG_RIGHT) KEY_EVENTS(RIGHT, KEY_RIGHT) #endif -#if defined(KEYS_GPIO_REG_UP) && defined(COLORLCD) +#if defined(KEYS_GPIO_REG_UP) && defined(COLORLCD) || defined(USE_HATS_AS_KEYS) KEY_EVENTS(MODEL, KEY_MODEL) #elif defined(KEYS_GPIO_REG_UP) KEY_EVENTS(UP, KEY_UP) #endif -#if defined(KEYS_GPIO_REG_LEFT) && defined(COLORLCD) +#if defined(KEYS_GPIO_REG_LEFT) && defined(COLORLCD) || defined(USE_HATS_AS_KEYS) KEY_EVENTS(SYS, KEY_SYS) #elif defined(KEYS_GPIO_REG_LEFT) KEY_EVENTS(LEFT, KEY_LEFT) @@ -3141,11 +3139,11 @@ LROT_BEGIN(etxcst, NULL, 0) KEY_EVENTS(DOWN, KEY_DOWN) #endif -#if defined(KEYS_GPIO_REG_PAGEUP) +#if defined(KEYS_GPIO_REG_PAGEUP) || defined(USE_HATS_AS_KEYS) KEY_EVENTS(PAGEUP, KEY_PAGEUP) #endif -#if defined(KEYS_GPIO_REG_PAGEDN) +#if defined(KEYS_GPIO_REG_PAGEDN) || defined(USE_HATS_AS_KEYS) KEY_EVENTS(PAGEDN, KEY_PAGEDN) #endif @@ -3165,12 +3163,13 @@ LROT_BEGIN(etxcst, NULL, 0) KEY_EVENTS(MINUS, KEY_MINUS) #endif -#if defined(ROTARY_ENCODER_NAVIGATION) +#if defined(ROTARY_ENCODER_NAVIGATION) || defined(USE_HATS_AS_KEYS) KEY_EVENTS(ROT, KEY_ENTER) LROT_NUMENTRY( EVT_ROT_LEFT, EVT_ROTARY_LEFT ) LROT_NUMENTRY( EVT_ROT_RIGHT, EVT_ROTARY_RIGHT ) #endif +// touch events #if defined(HARDWARE_TOUCH) LROT_NUMENTRY( EVT_TOUCH_FIRST, EVT_TOUCH_FIRST ) LROT_NUMENTRY( EVT_TOUCH_BREAK, EVT_TOUCH_BREAK ) @@ -3178,6 +3177,7 @@ LROT_BEGIN(etxcst, NULL, 0) LROT_NUMENTRY( EVT_TOUCH_TAP, EVT_TOUCH_TAP ) #endif +// misc definitions #if LCD_DEPTH > 1 && !defined(COLORLCD) LROT_NUMENTRY( FILL_WHITE, FILL_WHITE ) LROT_NUMENTRY( GREY_DEFAULT, GREY_DEFAULT ) diff --git a/radio/src/lua/interface.cpp b/radio/src/lua/interface.cpp index 07028156eff..33aabea37c1 100644 --- a/radio/src/lua/interface.cpp +++ b/radio/src/lua/interface.cpp @@ -79,7 +79,7 @@ struct our_longjmp * global_lj = 0; uint32_t luaExtraMemoryUsage = 0; #endif -#if defined(USE_TRIMS_AS_BUTTONS) +#if defined(USE_HATS_AS_KEYS) static bool _is_standalone_script() { return scriptInternalData[0].reference == SCRIPT_STANDALONE; @@ -254,8 +254,8 @@ void luaDisable() POPUP_WARNING("Lua disabled!"); luaState = INTERPRETER_PANIC; -#if defined(USE_TRIMS_AS_BUTTONS) - if (_is_standalone_script()) setTrimsAsButtons(false); +#if defined(USE_HATS_AS_KEYS) + if (_is_standalone_script()) setTransposeHatsForLUA(false); #endif } @@ -1255,8 +1255,8 @@ bool luaTask(event_t evt, bool allowLcdUsage) init = true; luaState = INTERPRETER_LOADING; -#if defined(USE_TRIMS_AS_BUTTONS) - if (_is_standalone_script()) setTrimsAsButtons(false); +#if defined(USE_HATS_AS_KEYS) + if (_is_standalone_script()) setTransposeHatsForLUA(false); #endif case INTERPRETER_LOADING: @@ -1271,8 +1271,8 @@ bool luaTask(event_t evt, bool allowLcdUsage) init = true; luaState = INTERPRETER_RUNNING; -#if defined(USE_TRIMS_AS_BUTTONS) - if (_is_standalone_script()) setTrimsAsButtons(true); +#if defined(USE_HATS_AS_KEYS) + if (_is_standalone_script()) setTransposeHatsForLUA(true); #endif case INTERPRETER_RUNNING: diff --git a/radio/src/lua/lua_widget.cpp b/radio/src/lua/lua_widget.cpp index 4a7cc453047..dee0855961e 100644 --- a/radio/src/lua/lua_widget.cpp +++ b/radio/src/lua/lua_widget.cpp @@ -175,7 +175,7 @@ void LuaEventHandler::onEvent(event_t event) if (event == EVT_KEY_LONG(KEY_EXIT)) { killEvents(KEY_EXIT); } -#if !defined(KEYS_GPIO_REG_PAGEUP) +#if !defined(KEYS_GPIO_REG_PAGEUP) && !defined(USE_HATS_AS_KEYS) else if (event == EVT_KEY_LONG(KEY_PAGEDN)) { killEvents(KEY_PAGEDN); } diff --git a/radio/src/main.cpp b/radio/src/main.cpp index 3026090e22e..625f92e8ddc 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -268,6 +268,33 @@ void checkSpeakerVolume() } } +#if defined(USE_HATS_AS_KEYS) +void checkHatsAsKeys() +{ + uint8_t hatsMode = g_model.hatsMode == HATSMODE_GLOBAL ? g_eeGeneral.hatsMode + : g_model.hatsMode; + + static bool oldHatsModeKeys = hatsMode == HATSMODE_KEYS_ONLY; + + if (hatsMode == HATSMODE_TRIMS_ONLY) { + setHatsAsKeys(false); + } + + if (hatsMode == HATSMODE_KEYS_ONLY) { + setHatsAsKeys(true); + } + + bool hatsModeKeys = getHatsAsKeys(); + + if (hatsModeKeys == oldHatsModeKeys) return; + + oldHatsModeKeys = !oldHatsModeKeys; + + audioKeyPress(); + POPUP_BUBBLE(hatsModeKeys ? STR_HATSMODE_KEYS : STR_HATSMODE_TRIMS, 2000); +} +#endif + #if defined(EEPROM) void checkEeprom() { @@ -527,6 +554,10 @@ void perMain() checkBacklight(); +#if defined(USE_HATS_AS_KEYS) + checkHatsAsKeys(); +#endif + #if !defined(LIBOPENUI) event_t evt = getEvent(); #endif diff --git a/radio/src/model_init.cpp b/radio/src/model_init.cpp index c122a5f4142..b7ebb8956b4 100644 --- a/radio/src/model_init.cpp +++ b/radio/src/model_init.cpp @@ -133,6 +133,8 @@ void applyDefaultTemplate() g_model.switchWarningState |= (1 << (3 * i)); } #endif + + g_model.hatsMode = HATSMODE_GLOBAL; } void setModelDefaults(uint8_t id) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 866ca3f860f..0ae6ab6b3da 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -346,6 +346,8 @@ void generalDefault() // disable Custom Script g_eeGeneral.modelCustomScriptsDisabled = true; + g_eeGeneral.hatsMode = HATSMODE_SWITCHABLE; + g_eeGeneral.chkSum = 0xFFFF; } diff --git a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp index 48660a06e04..b1a214daefd 100644 --- a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp @@ -4,6 +4,13 @@ // Enums first // +const struct YamlIdStr enum_HatsMode[] = { + { HATSMODE_TRIMS_ONLY, "TRIMS_ONLY" }, + { HATSMODE_KEYS_ONLY, "KEYS_ONLY" }, + { HATSMODE_SWITCHABLE, "SWITCHABLE" }, + { HATSMODE_GLOBAL, "GLOBAL" }, + { 0, NULL } +}; const struct YamlIdStr enum_BacklightMode[] = { { e_backlight_mode_off, "backlight_mode_off" }, { e_backlight_mode_keys, "backlight_mode_keys" }, @@ -267,7 +274,8 @@ static const struct YamlNode struct_CustomFunctionData[] = { static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "manuallyEdited", 1 ), YAML_SIGNED( "timezoneMinutes", 3 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_CUSTOM("semver",nullptr,w_semver), YAML_CUSTOM("board",nullptr,w_board), YAML_ARRAY("calib", 48, 12, struct_CalibData, NULL), @@ -791,7 +799,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "disableTelemetryWarning", 1 ), YAML_UNSIGNED( "showInstanceIds", 1 ), YAML_UNSIGNED( "checklistInteractive", 1 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_SIGNED( "customThrottleWarningPosition", 8 ), YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp index cd51f89baf6..20caa171ccb 100644 --- a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp @@ -4,6 +4,13 @@ // Enums first // +const struct YamlIdStr enum_HatsMode[] = { + { HATSMODE_TRIMS_ONLY, "TRIMS_ONLY" }, + { HATSMODE_KEYS_ONLY, "KEYS_ONLY" }, + { HATSMODE_SWITCHABLE, "SWITCHABLE" }, + { HATSMODE_GLOBAL, "GLOBAL" }, + { 0, NULL } +}; const struct YamlIdStr enum_BacklightMode[] = { { e_backlight_mode_off, "backlight_mode_off" }, { e_backlight_mode_keys, "backlight_mode_keys" }, @@ -278,7 +285,8 @@ static const struct YamlNode struct_CustomFunctionData[] = { static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "manuallyEdited", 1 ), YAML_SIGNED( "timezoneMinutes", 3 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_CUSTOM("semver",nullptr,w_semver), YAML_CUSTOM("board",nullptr,w_board), YAML_ARRAY("calib", 48, 22, struct_CalibData, NULL), @@ -814,7 +822,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "disableTelemetryWarning", 1 ), YAML_UNSIGNED( "showInstanceIds", 1 ), YAML_UNSIGNED( "checklistInteractive", 1 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_SIGNED( "customThrottleWarningPosition", 8 ), YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_t20.cpp b/radio/src/storage/yaml/yaml_datastructs_t20.cpp index d62ea630724..dc4c3701427 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t20.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t20.cpp @@ -4,6 +4,13 @@ // Enums first // +const struct YamlIdStr enum_HatsMode[] = { + { HATSMODE_TRIMS_ONLY, "TRIMS_ONLY" }, + { HATSMODE_KEYS_ONLY, "KEYS_ONLY" }, + { HATSMODE_SWITCHABLE, "SWITCHABLE" }, + { HATSMODE_GLOBAL, "GLOBAL" }, + { 0, NULL } +}; const struct YamlIdStr enum_BacklightMode[] = { { e_backlight_mode_off, "backlight_mode_off" }, { e_backlight_mode_keys, "backlight_mode_keys" }, @@ -267,7 +274,8 @@ static const struct YamlNode struct_CustomFunctionData[] = { static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "manuallyEdited", 1 ), YAML_SIGNED( "timezoneMinutes", 3 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_CUSTOM("semver",nullptr,w_semver), YAML_CUSTOM("board",nullptr,w_board), YAML_ARRAY("calib", 48, 12, struct_CalibData, NULL), @@ -789,7 +797,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "disableTelemetryWarning", 1 ), YAML_UNSIGNED( "showInstanceIds", 1 ), YAML_UNSIGNED( "checklistInteractive", 1 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_SIGNED( "customThrottleWarningPosition", 8 ), YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp index 1bbd825dcd6..21d19838917 100644 --- a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp @@ -4,6 +4,13 @@ // Enums first // +const struct YamlIdStr enum_HatsMode[] = { + { HATSMODE_TRIMS_ONLY, "TRIMS_ONLY" }, + { HATSMODE_KEYS_ONLY, "KEYS_ONLY" }, + { HATSMODE_SWITCHABLE, "SWITCHABLE" }, + { HATSMODE_GLOBAL, "GLOBAL" }, + { 0, NULL } +}; const struct YamlIdStr enum_BacklightMode[] = { { e_backlight_mode_off, "backlight_mode_off" }, { e_backlight_mode_keys, "backlight_mode_keys" }, @@ -267,7 +274,8 @@ static const struct YamlNode struct_CustomFunctionData[] = { static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "manuallyEdited", 1 ), YAML_SIGNED( "timezoneMinutes", 3 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_CUSTOM("semver",nullptr,w_semver), YAML_CUSTOM("board",nullptr,w_board), YAML_ARRAY("calib", 48, 12, struct_CalibData, NULL), @@ -789,7 +797,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "disableTelemetryWarning", 1 ), YAML_UNSIGNED( "showInstanceIds", 1 ), YAML_UNSIGNED( "checklistInteractive", 1 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_SIGNED( "customThrottleWarningPosition", 8 ), YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_x10.cpp b/radio/src/storage/yaml/yaml_datastructs_x10.cpp index 25e150d391a..eeb89c5bf9f 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x10.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x10.cpp @@ -4,6 +4,13 @@ // Enums first // +const struct YamlIdStr enum_HatsMode[] = { + { HATSMODE_TRIMS_ONLY, "TRIMS_ONLY" }, + { HATSMODE_KEYS_ONLY, "KEYS_ONLY" }, + { HATSMODE_SWITCHABLE, "SWITCHABLE" }, + { HATSMODE_GLOBAL, "GLOBAL" }, + { 0, NULL } +}; const struct YamlIdStr enum_BacklightMode[] = { { e_backlight_mode_off, "backlight_mode_off" }, { e_backlight_mode_keys, "backlight_mode_keys" }, @@ -286,7 +293,8 @@ static const struct YamlNode struct_CustomFunctionData[] = { static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "manuallyEdited", 1 ), YAML_SIGNED( "timezoneMinutes", 3 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_CUSTOM("semver",nullptr,w_semver), YAML_CUSTOM("board",nullptr,w_board), YAML_ARRAY("calib", 48, 22, struct_CalibData, NULL), @@ -822,7 +830,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "disableTelemetryWarning", 1 ), YAML_UNSIGNED( "showInstanceIds", 1 ), YAML_UNSIGNED( "checklistInteractive", 1 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_SIGNED( "customThrottleWarningPosition", 8 ), YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_x12s.cpp b/radio/src/storage/yaml/yaml_datastructs_x12s.cpp index 25e150d391a..eeb89c5bf9f 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x12s.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x12s.cpp @@ -4,6 +4,13 @@ // Enums first // +const struct YamlIdStr enum_HatsMode[] = { + { HATSMODE_TRIMS_ONLY, "TRIMS_ONLY" }, + { HATSMODE_KEYS_ONLY, "KEYS_ONLY" }, + { HATSMODE_SWITCHABLE, "SWITCHABLE" }, + { HATSMODE_GLOBAL, "GLOBAL" }, + { 0, NULL } +}; const struct YamlIdStr enum_BacklightMode[] = { { e_backlight_mode_off, "backlight_mode_off" }, { e_backlight_mode_keys, "backlight_mode_keys" }, @@ -286,7 +293,8 @@ static const struct YamlNode struct_CustomFunctionData[] = { static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "manuallyEdited", 1 ), YAML_SIGNED( "timezoneMinutes", 3 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_CUSTOM("semver",nullptr,w_semver), YAML_CUSTOM("board",nullptr,w_board), YAML_ARRAY("calib", 48, 22, struct_CalibData, NULL), @@ -822,7 +830,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "disableTelemetryWarning", 1 ), YAML_UNSIGNED( "showInstanceIds", 1 ), YAML_UNSIGNED( "checklistInteractive", 1 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_SIGNED( "customThrottleWarningPosition", 8 ), YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_x9d.cpp b/radio/src/storage/yaml/yaml_datastructs_x9d.cpp index a7538158f29..4c144a6bbdd 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9d.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9d.cpp @@ -4,6 +4,13 @@ // Enums first // +const struct YamlIdStr enum_HatsMode[] = { + { HATSMODE_TRIMS_ONLY, "TRIMS_ONLY" }, + { HATSMODE_KEYS_ONLY, "KEYS_ONLY" }, + { HATSMODE_SWITCHABLE, "SWITCHABLE" }, + { HATSMODE_GLOBAL, "GLOBAL" }, + { 0, NULL } +}; const struct YamlIdStr enum_BacklightMode[] = { { e_backlight_mode_off, "backlight_mode_off" }, { e_backlight_mode_keys, "backlight_mode_keys" }, @@ -267,7 +274,8 @@ static const struct YamlNode struct_CustomFunctionData[] = { static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "manuallyEdited", 1 ), YAML_SIGNED( "timezoneMinutes", 3 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_CUSTOM("semver",nullptr,w_semver), YAML_CUSTOM("board",nullptr,w_board), YAML_ARRAY("calib", 48, 12, struct_CalibData, NULL), @@ -792,7 +800,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "disableTelemetryWarning", 1 ), YAML_UNSIGNED( "showInstanceIds", 1 ), YAML_UNSIGNED( "checklistInteractive", 1 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_SIGNED( "customThrottleWarningPosition", 8 ), YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_x9e.cpp b/radio/src/storage/yaml/yaml_datastructs_x9e.cpp index 1ec97e579f2..ba2ea2741f3 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9e.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9e.cpp @@ -4,6 +4,13 @@ // Enums first // +const struct YamlIdStr enum_HatsMode[] = { + { HATSMODE_TRIMS_ONLY, "TRIMS_ONLY" }, + { HATSMODE_KEYS_ONLY, "KEYS_ONLY" }, + { HATSMODE_SWITCHABLE, "SWITCHABLE" }, + { HATSMODE_GLOBAL, "GLOBAL" }, + { 0, NULL } +}; const struct YamlIdStr enum_BacklightMode[] = { { e_backlight_mode_off, "backlight_mode_off" }, { e_backlight_mode_keys, "backlight_mode_keys" }, @@ -267,7 +274,8 @@ static const struct YamlNode struct_CustomFunctionData[] = { static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "manuallyEdited", 1 ), YAML_SIGNED( "timezoneMinutes", 3 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_CUSTOM("semver",nullptr,w_semver), YAML_CUSTOM("board",nullptr,w_board), YAML_ARRAY("calib", 48, 12, struct_CalibData, NULL), @@ -792,7 +800,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "disableTelemetryWarning", 1 ), YAML_UNSIGNED( "showInstanceIds", 1 ), YAML_UNSIGNED( "checklistInteractive", 1 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_SIGNED( "customThrottleWarningPosition", 8 ), YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_x9lite.cpp b/radio/src/storage/yaml/yaml_datastructs_x9lite.cpp index b251c8042f1..8a15f0fb445 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9lite.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9lite.cpp @@ -4,6 +4,13 @@ // Enums first // +const struct YamlIdStr enum_HatsMode[] = { + { HATSMODE_TRIMS_ONLY, "TRIMS_ONLY" }, + { HATSMODE_KEYS_ONLY, "KEYS_ONLY" }, + { HATSMODE_SWITCHABLE, "SWITCHABLE" }, + { HATSMODE_GLOBAL, "GLOBAL" }, + { 0, NULL } +}; const struct YamlIdStr enum_BacklightMode[] = { { e_backlight_mode_off, "backlight_mode_off" }, { e_backlight_mode_keys, "backlight_mode_keys" }, @@ -267,7 +274,8 @@ static const struct YamlNode struct_CustomFunctionData[] = { static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "manuallyEdited", 1 ), YAML_SIGNED( "timezoneMinutes", 3 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_CUSTOM("semver",nullptr,w_semver), YAML_CUSTOM("board",nullptr,w_board), YAML_ARRAY("calib", 48, 12, struct_CalibData, NULL), @@ -789,7 +797,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "disableTelemetryWarning", 1 ), YAML_UNSIGNED( "showInstanceIds", 1 ), YAML_UNSIGNED( "checklistInteractive", 1 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_SIGNED( "customThrottleWarningPosition", 8 ), YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_xlites.cpp b/radio/src/storage/yaml/yaml_datastructs_xlites.cpp index feda9fec8c5..246d8f399b9 100644 --- a/radio/src/storage/yaml/yaml_datastructs_xlites.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_xlites.cpp @@ -4,6 +4,13 @@ // Enums first // +const struct YamlIdStr enum_HatsMode[] = { + { HATSMODE_TRIMS_ONLY, "TRIMS_ONLY" }, + { HATSMODE_KEYS_ONLY, "KEYS_ONLY" }, + { HATSMODE_SWITCHABLE, "SWITCHABLE" }, + { HATSMODE_GLOBAL, "GLOBAL" }, + { 0, NULL } +}; const struct YamlIdStr enum_BacklightMode[] = { { e_backlight_mode_off, "backlight_mode_off" }, { e_backlight_mode_keys, "backlight_mode_keys" }, @@ -269,7 +276,8 @@ static const struct YamlNode struct_CustomFunctionData[] = { static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "manuallyEdited", 1 ), YAML_SIGNED( "timezoneMinutes", 3 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_CUSTOM("semver",nullptr,w_semver), YAML_CUSTOM("board",nullptr,w_board), YAML_ARRAY("calib", 48, 12, struct_CalibData, NULL), @@ -795,7 +803,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "disableTelemetryWarning", 1 ), YAML_UNSIGNED( "showInstanceIds", 1 ), YAML_UNSIGNED( "checklistInteractive", 1 ), - YAML_PADDING( 4 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), YAML_SIGNED( "customThrottleWarningPosition", 8 ), YAML_UNSIGNED( "beepANACenter", 16 ), YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp index 4e00d657669..2ba72da76fc 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp @@ -106,7 +106,7 @@ void per10ms() keysPollingCycle(); -#if defined(ROTARY_ENCODER_NAVIGATION) +#if defined(ROTARY_ENCODER_NAVIGATION) && !defined(USE_HATS_AS_KEYS) static rotenc_t rePreviousValue; rotenc_t reNewValue = rotaryEncoderGetValue(); @@ -256,7 +256,7 @@ void bootloaderInitApp() pwrOn(); -#if defined(ROTARY_ENCODER_NAVIGATION) +#if defined(ROTARY_ENCODER_NAVIGATION) && !defined(USE_HATS_AS_KEYS) rotaryEncoderInit(); #endif diff --git a/radio/src/targets/nv14/CMakeLists.txt b/radio/src/targets/nv14/CMakeLists.txt index c8814d96b41..6536e180b78 100644 --- a/radio/src/targets/nv14/CMakeLists.txt +++ b/radio/src/targets/nv14/CMakeLists.txt @@ -39,7 +39,7 @@ set(PCB_RF_BAUD 921600 CACHE STRING "INTERNAL_MODULE_BAUDRATE: ${RF_BAUD_RATE}") set_property(CACHE PCB_RF_BAUD PROPERTY STRINGS ${RF_BAUD_RATE}) add_definitions(-DPCBNV14 -DPCBFLYSKY -DAFHDS2_BAUDRATE=${PCB_RF_BAUD}) -add_definitions(-DBATTERY_CHARGE -DUSE_TRIMS_AS_BUTTONS) +add_definitions(-DBATTERY_CHARGE -DUSE_HATS_AS_KEYS) if (PCBREV STREQUAL EL18) set(FLAVOUR el18) diff --git a/radio/src/targets/nv14/bootloader/boot_menu.cpp b/radio/src/targets/nv14/bootloader/boot_menu.cpp index 492538563c5..590b276aea6 100644 --- a/radio/src/targets/nv14/bootloader/boot_menu.cpp +++ b/radio/src/targets/nv14/bootloader/boot_menu.cpp @@ -70,7 +70,7 @@ void bootloaderInitScreen() lcdInitDisplayDriver(); backlightInit(); backlightEnable(100); - setTrimsAsButtons(true); + setHatsAsKeys(true); } static void bootloaderDrawTitle(const char* text) diff --git a/radio/src/targets/nv14/hal.h b/radio/src/targets/nv14/hal.h index 6ee7097b9b2..4953fc2d6a4 100644 --- a/radio/src/targets/nv14/hal.h +++ b/radio/src/targets/nv14/hal.h @@ -517,6 +517,9 @@ #define BLUETOOTH_ON_GPIO GPIOI #define BLUETOOTH_ON_GPIO_PIN GPIO_Pin_8 // PI.8 +//ROTARY emulation for trims as buttons +#define ROTARY_ENCODER_NAVIGATION + // Bluetooth #define BT_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOH) #define BT_RCC_APB1Periph (RCC_APB1Periph_USART3) diff --git a/radio/src/targets/simu/opentxsimulator.cpp b/radio/src/targets/simu/opentxsimulator.cpp index d8e62917f53..5cb3cc8696e 100644 --- a/radio/src/targets/simu/opentxsimulator.cpp +++ b/radio/src/targets/simu/opentxsimulator.cpp @@ -298,7 +298,7 @@ extern volatile uint32_t rotencDt; void OpenTxSimulator::rotaryEncoderEvent(int steps) { -#if defined(ROTARY_ENCODER_NAVIGATION) +#if defined(ROTARY_ENCODER_NAVIGATION) && !defined(USE_HATS_AS_KEYS) static uint32_t last_tick = 0; if (steps != 0) { if (g_eeGeneral.rotEncMode >= ROTARY_ENCODER_MODE_INVERT_BOTH) steps *= -1; diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index 01720aa5145..28af76c634e 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -448,9 +448,9 @@ void SET_POWER_REASON(uint32_t value) {} #if defined(TRIMS_EMULATE_BUTTONS) bool trimsAsButtons = false; -void setTrimsAsButtons(bool val) { trimsAsButtons = val; } +void setHatsAsKeys(bool val) { trimsAsButtons = val; } -bool getTrimsAsButtons() +bool getHatsAsKeys() { bool lua = false; #if defined(LUA) diff --git a/radio/src/thirdparty/libopenui/src/numberedit.cpp b/radio/src/thirdparty/libopenui/src/numberedit.cpp index d688625ecce..960aed636a6 100644 --- a/radio/src/thirdparty/libopenui/src/numberedit.cpp +++ b/radio/src/thirdparty/libopenui/src/numberedit.cpp @@ -66,7 +66,11 @@ void NumberEdit::onEvent(event_t event) auto step = getStep(); step += (rotaryEncoderGetAccel() * getAccelFactor()) / 8; do { +#if defined(USE_HATS_AS_KEYS) + value -= step; +#else value += step; +#endif } while (isValueAvailable && !isValueAvailable(value) && value <= vmax); if (value <= vmax) { setValue(value); @@ -83,7 +87,11 @@ void NumberEdit::onEvent(event_t event) auto step = getStep(); step += (rotaryEncoderGetAccel() * getAccelFactor()) / 8; do { +#if defined(USE_HATS_AS_KEYS) + value += step; +#else value -= step; +#endif } while (isValueAvailable && !isValueAvailable(value) && value >= vmin); if (value >= vmin) { setValue(value); diff --git a/radio/src/thirdparty/libopenui/src/window.h b/radio/src/thirdparty/libopenui/src/window.h index 4f464a81b52..b3439bba9fb 100644 --- a/radio/src/thirdparty/libopenui/src/window.h +++ b/radio/src/thirdparty/libopenui/src/window.h @@ -231,4 +231,3 @@ class Window virtual void invalidate(const rect_t & rect); }; - diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index 0712cda01b8..44c5d44980b 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -537,6 +537,14 @@ const char STR_DATE[] = TR_DATE; const char STR_CHANNELS_MONITOR[] = TR_CHANNELS_MONITOR; const char STR_ROTARY_ENCODER[] = TR_ROTARY_ENCODER; const char STR_ROTARY_ENC_MODE[] = TR_ROTARY_ENC_MODE; + +#if defined(USE_HATS_AS_KEYS) +const char STR_HATSMODE[] = TR_HATSMODE; +ISTR(HATSOPT); +const char STR_HATSMODE_TRIMS[] = TR_HATSMODE_TRIMS; +const char STR_HATSMODE_KEYS[] = TR_HATSMODE_KEYS; +#endif + const char STR_MIXERS_MONITOR[] = TR_MIXERS_MONITOR; const char STR_PATH_TOO_LONG[] = TR_PATH_TOO_LONG; const char STR_VIEW_TEXT[] = TR_VIEW_TEXT; diff --git a/radio/src/translations.h b/radio/src/translations.h index eca21a41dd2..02a310fb1de 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -172,6 +172,13 @@ extern const char* const STR_CYC_VSRCRAW[]; extern const char* const STR_ROTARY_ENC_OPT[]; +#if defined(USE_HATS_AS_KEYS) +extern const char STR_HATSMODE[]; +extern const char* const STR_HATSOPT[]; +extern const char STR_HATSMODE_TRIMS[]; +extern const char STR_HATSMODE_KEYS[]; +#endif + extern const char* const STR_VTMRMODES[]; extern const char* const STR_VPERSISTENT[]; diff --git a/radio/src/translations/cn.h b/radio/src/translations/cn.h index c68902fd48d..f99c28d53a6 100644 --- a/radio/src/translations/cn.h +++ b/radio/src/translations/cn.h @@ -156,6 +156,13 @@ #define TR_ON_ONE_SWITCHES "ON","One" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "按键帽模式" +#define TR_HATSOPT "微调","导航键","可切换","全局" +#define TR_HATSMODE_TRIMS "按键帽: 微调" +#define TR_HATSMODE_KEYS "按键帽: 导航键" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "正常","反向" #else diff --git a/radio/src/translations/cz.h b/radio/src/translations/cz.h index 9cb9271b66c..947ac6ad542 100644 --- a/radio/src/translations/cz.h +++ b/radio/src/translations/cz.h @@ -169,6 +169,13 @@ #define TR_ON_ONE_SWITCHES "ZAP","One" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "Režim kloboučků" +#define TR_HATSOPT "Pouze trimy","Pouze tlačítka","Přepinatelné","Globální" +#define TR_HATSMODE_TRIMS "Režim kloboučků: Trimy" +#define TR_HATSMODE_KEYS "Režim kloboučků: Tlačítka" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "Normal","Invertován" #else diff --git a/radio/src/translations/da.h b/radio/src/translations/da.h index 3a74f7a330e..c46c9bd2b2f 100644 --- a/radio/src/translations/da.h +++ b/radio/src/translations/da.h @@ -164,6 +164,13 @@ #define TR_ON_ONE_SWITCHES "EN","En" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "Joystik indstilling" +#define TR_HATSOPT "Kun trim","Kun knap","Trim / Knap", "Global" +#define TR_HATSMODE_TRIMS "Joystik: Trim" +#define TR_HATSMODE_KEYS "Joystik: Knap" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "Normal","Invers" #else diff --git a/radio/src/translations/de.h b/radio/src/translations/de.h index 96a049eff73..699025d6e73 100644 --- a/radio/src/translations/de.h +++ b/radio/src/translations/de.h @@ -159,6 +159,13 @@ #define TR_ON_ONE_SWITCHES "ON","One" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "Joystick Modus" +#define TR_HATSOPT "Nur Trimmung","Nur Tasten","Umschaltbar","Global" +#define TR_HATSMODE_TRIMS "Joystick Modus: Trimmung" +#define TR_HATSMODE_KEYS "Joystick Modus: Tasten" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "Normal","Inverted" #else diff --git a/radio/src/translations/en.h b/radio/src/translations/en.h index 74c1171e567..ea23ceec8b5 100644 --- a/radio/src/translations/en.h +++ b/radio/src/translations/en.h @@ -161,6 +161,13 @@ #define TR_ON_ONE_SWITCHES "ON","One" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "Hats mode" +#define TR_HATSOPT "Trims only","Keys only","Switchable","Global" +#define TR_HATSMODE_TRIMS "Hats mode: Trims" +#define TR_HATSMODE_KEYS "Hats mode: Keys" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "Normal","Inverted" #else diff --git a/radio/src/translations/es.h b/radio/src/translations/es.h index 47e4230022a..b37455ead4c 100644 --- a/radio/src/translations/es.h +++ b/radio/src/translations/es.h @@ -157,6 +157,13 @@ #define TR_ON_ONE_SWITCHES "ON","One" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "Hats mode" +#define TR_HATSOPT "Trims only","Keys only","Switchable","Global" +#define TR_HATSMODE_TRIMS "Hats mode: Trims" +#define TR_HATSMODE_KEYS "Hats mode: Keys" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "Normal","Inverted" #else diff --git a/radio/src/translations/fi.h b/radio/src/translations/fi.h index 3734d691f11..ec6793cef65 100644 --- a/radio/src/translations/fi.h +++ b/radio/src/translations/fi.h @@ -168,6 +168,13 @@ #define TR_ON_ONE_SWITCHES "ON","One" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "Hats mode" +#define TR_HATSOPT "Trims only","Keys only","Switchable","Global" +#define TR_HATSMODE_TRIMS "Hats mode: Trims" +#define TR_HATSMODE_KEYS "Hats mode: Keys" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "Normal","Inverted" #else diff --git a/radio/src/translations/fr.h b/radio/src/translations/fr.h index e674da12688..0cc1eeb9a86 100644 --- a/radio/src/translations/fr.h +++ b/radio/src/translations/fr.h @@ -169,6 +169,13 @@ #define TR_ON_ONE_SWITCHES "ON","Un" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "Mode joystick" +#define TR_HATSOPT "Trims uniquement","Touches uniquement","Commutable","Global" +#define TR_HATSMODE_TRIMS "Mode joystick: trims" +#define TR_HATSMODE_KEYS "Mode joystick: touches" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "Normal","Inversé" #else diff --git a/radio/src/translations/he.h b/radio/src/translations/he.h index 4f70d7bc41f..e9d2b1a49e1 100644 --- a/radio/src/translations/he.h +++ b/radio/src/translations/he.h @@ -166,6 +166,13 @@ #define TR_ON_ONE_SWITCHES "ON","One" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "מצב כובעונים" +#define TR_HATSOPT "קיזוזים בלבד","ניווט בלבד","משולב","גלובאלי" +#define TR_HATSMODE_TRIMS "מצב כובעונים: קיזוזים" +#define TR_HATSMODE_KEYS "מצב כובעונים: ניווט" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "רגיל","הפוך" #else diff --git a/radio/src/translations/it.h b/radio/src/translations/it.h index 0e0f6415ade..b6813b8cd8a 100644 --- a/radio/src/translations/it.h +++ b/radio/src/translations/it.h @@ -162,6 +162,13 @@ #define TR_ON_ONE_SWITCHES "ON","One" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "Modo joystick" +#define TR_HATSOPT "Solo trims","Solo keys","Commutabile","Globale" +#define TR_HATSMODE_TRIMS "Modo joystick: trims" +#define TR_HATSMODE_KEYS "Modo joystick: keys" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "Normale","Invertito" #else diff --git a/radio/src/translations/jp.h b/radio/src/translations/jp.h index dd3c43893de..66b1aad2c9a 100644 --- a/radio/src/translations/jp.h +++ b/radio/src/translations/jp.h @@ -161,6 +161,13 @@ #define TR_ON_ONE_SWITCHES "ON","One" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "アナログスティック" +#define TR_HATSOPT "トリムのみ","キーのみ","スイッチ","すべて" +#define TR_HATSMODE_TRIMS "アナログスティック: トリム" +#define TR_HATSMODE_KEYS "アナログスティック: キー" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "標準","リバース" #else diff --git a/radio/src/translations/nl.h b/radio/src/translations/nl.h index dd2776d3614..6a24954e99c 100644 --- a/radio/src/translations/nl.h +++ b/radio/src/translations/nl.h @@ -158,6 +158,13 @@ #define TR_ON_ONE_SWITCHES "ON","One" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "Hats mode" +#define TR_HATSOPT "Trims only","Keys only","Switchable","Global" +#define TR_HATSMODE_TRIMS "Hats mode: Trims" +#define TR_HATSMODE_KEYS "Hats mode: Keys" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "Normal","Inverted" #else diff --git a/radio/src/translations/pl.h b/radio/src/translations/pl.h index 5fdd60bbb91..602221b01d1 100644 --- a/radio/src/translations/pl.h +++ b/radio/src/translations/pl.h @@ -157,6 +157,13 @@ #define TR_ON_ONE_SWITCHES "ON","One" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "Tryb grzybków" +#define TR_HATSOPT "Tylko trymy","Tylko przyciski","Przełączane","Globalne" +#define TR_HATSMODE_TRIMS "Tryb grzybków: trymy" +#define TR_HATSMODE_KEYS "Tryb grzybków: przyciski" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "Normal","Inverted" #else diff --git a/radio/src/translations/pt.h b/radio/src/translations/pt.h index b9a9496c67d..2a389987dbb 100644 --- a/radio/src/translations/pt.h +++ b/radio/src/translations/pt.h @@ -164,6 +164,13 @@ #define TR_ON_ONE_SWITCHES "LIG","UM" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "Hats mode" +#define TR_HATSOPT "Trims only","Keys only","Switchable","Global" +#define TR_HATSMODE_TRIMS "Hats mode: Trims" +#define TR_HATSMODE_KEYS "Hats mode: Keys" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "Normal","Invert" #else diff --git a/radio/src/translations/se.h b/radio/src/translations/se.h index 68c19fc201c..4ac407234a1 100644 --- a/radio/src/translations/se.h +++ b/radio/src/translations/se.h @@ -179,6 +179,13 @@ #define TR_ON_ONE_SWITCHES "PÅ","Ett" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "Hattläge" +#define TR_HATSOPT "Endast trimm","Endast knapp","Ändringsbar","Global" +#define TR_HATSMODE_TRIMS "Hattläge: Trimmar" +#define TR_HATSMODE_KEYS "Hattläge: Knappar" +#endif + #if defined(IMU) #define TR_IMU_VSRCRAW "TltX","TltY", #else diff --git a/radio/src/translations/tw.h b/radio/src/translations/tw.h index 1783730289d..3bdab141ab6 100644 --- a/radio/src/translations/tw.h +++ b/radio/src/translations/tw.h @@ -162,6 +162,13 @@ #define TR_ON_ONE_SWITCHES "ON","One" +#if defined(USE_HATS_AS_KEYS) +#define TR_HATSMODE "按鍵帽模式" +#define TR_HATSOPT "微調","導航鍵","可切換","全局" +#define TR_HATSMODE_TRIMS "按鍵帽: 微調" +#define TR_HATSMODE_KEYS "按鍵帽: 導航鍵" +#endif + #if defined(COLORLCD) #define TR_ROTARY_ENC_OPT "正常","反向" #else