diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt index 6914f667c..9c98e519d 100644 --- a/companion/src/CMakeLists.txt +++ b/companion/src/CMakeLists.txt @@ -323,6 +323,8 @@ elseif(PCB STREQUAL X7 AND PCBREV STREQUAL T12) set(FLAVOUR t12) elseif(PCB STREQUAL X7 AND PCBREV STREQUAL TLITE) set(FLAVOUR tlite) +elseif(PCB STREQUAL X7 AND PCBREV STREQUAL TPRO) + set(FLAVOUR tpro) elseif(PCB STREQUAL X7 AND PCBREV STREQUAL TX12) set(FLAVOUR tx12) elseif(PCB STREQUAL X7 AND PCBREV STREQUAL ZORRO) diff --git a/companion/src/companion.qrc b/companion/src/companion.qrc index c34fcd295..9bdbdee8b 100644 --- a/companion/src/companion.qrc +++ b/companion/src/companion.qrc @@ -188,6 +188,10 @@ images/simulator/JumperTLITE/right_top.png images/simulator/JumperTLITE/right_bottom.png images/simulator/JumperTLITE/top.png + images/simulator/JumperTPRO/bottom.png + images/simulator/JumperTPRO/left.png + images/simulator/JumperTPRO/right.png + images/simulator/JumperTPRO/top.png images/simulator/TX12/left.png images/simulator/TX12/left-pageup.png images/simulator/TX12/left-pagedn.png diff --git a/companion/src/constants.h b/companion/src/constants.h index 63ba0a9b1..b06792a91 100644 --- a/companion/src/constants.h +++ b/companion/src/constants.h @@ -43,6 +43,7 @@ #define CPN_MAX_POTS (CPN_MAX_KNOBS + CPN_MAX_SLIDERS) #define CPN_MAX_CYC 3 #define CPN_MAX_SWITCHES 32 +#define CPN_MAX_FUNCTION_SWITCHES 6 #define CPN_MAX_MOUSE_ANALOGS 2 #define CPN_MAX_GYRO_ANALOGS 2 #define CPN_MAX_ANALOGS (CPN_MAX_STICKS + CPN_MAX_POTS + CPN_MAX_MOUSE_ANALOGS + CPN_MAX_GYRO_ANALOGS) diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp index 18605ea10..af164355c 100644 --- a/companion/src/firmwares/boards.cpp +++ b/companion/src/firmwares/boards.cpp @@ -82,6 +82,8 @@ uint32_t Boards::getFourCC(Type board) return 0x3D78746F; case BOARD_JUMPER_TLITE: return 0x4278746F; + case BOARD_JUMPER_TPRO: + return 0x4678746F; case BOARD_JUMPER_T16: return 0x3F78746F; case BOARD_JUMPER_T18: @@ -121,6 +123,7 @@ int Boards::getEEpromSize(Board::Type board) case BOARD_TARANIS_X9E: case BOARD_JUMPER_T12: case BOARD_JUMPER_TLITE: + case BOARD_JUMPER_TPRO: case BOARD_RADIOMASTER_TX12: case BOARD_RADIOMASTER_T8: case BOARD_RADIOMASTER_ZORRO: @@ -160,6 +163,7 @@ int Boards::getFlashSize(Type board) case BOARD_TARANIS_X9E: case BOARD_JUMPER_T12: case BOARD_JUMPER_TLITE: + case BOARD_JUMPER_TPRO: case BOARD_RADIOMASTER_TX12: case BOARD_RADIOMASTER_ZORRO: case BOARD_RADIOMASTER_T8: @@ -196,7 +200,7 @@ SwitchInfo Boards::getSwitchInfo(Board::Type board, int index) if (index < DIM(switches)) return switches[index]; } - else if (IS_TARANIS_XLITE(board) || IS_JUMPER_TLITE(board)) { + else if (IS_TARANIS_XLITE(board) || IS_JUMPER_TLITE(board) || IS_JUMPER_TPRO(board)) { const Board::SwitchInfo switches[] = { {SWITCH_3POS, "SA"}, {SWITCH_3POS, "SB"}, @@ -365,7 +369,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) return 1; else if (IS_JUMPER_TLITE(board)) return 0; - else if (IS_TARANIS_SMALL(board)) + else if (IS_TARANIS_SMALL(board) || IS_JUMPER_TPRO(board)) return 2; else if (IS_TARANIS_X9E(board)) return 4; @@ -427,7 +431,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) return 7; else if (board == BOARD_TARANIS_X7) return 8; - else if (board == BOARD_JUMPER_TLITE) + else if (board == BOARD_JUMPER_TLITE || board == BOARD_JUMPER_TPRO) return 4; else if (board == BOARD_FLYSKY_NV14) return 8; @@ -447,7 +451,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) case FactoryInstalledSwitches: if (IS_TARANIS_X9E(board)) return 8; - else if (IS_JUMPER_TLITE(board)) + else if (IS_JUMPER_TLITE(board) || IS_JUMPER_TPRO(board)) return 4; else if(IS_RADIOMASTER_ZORRO(board)) return 8; @@ -479,6 +483,9 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) case HasColorLcd: return IS_FAMILY_HORUS_OR_T16(board); + case NumFunctionSwitches: + return IS_JUMPER_TPRO(board) ? 6 : 0; + default: return 0; } @@ -645,6 +652,8 @@ QString Boards::getBoardName(Board::Type board) return "Jumper T12"; case BOARD_JUMPER_TLITE: return "Jumper T-Lite"; + case BOARD_JUMPER_TPRO: + return "Jumper T-Pro"; case BOARD_JUMPER_T16: return "Jumper T16"; case BOARD_JUMPER_T18: diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index 2bc37a458..ea0476bda 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -63,6 +63,7 @@ namespace Board { BOARD_JUMPER_TLITE, BOARD_FLYSKY_NV14, BOARD_RADIOMASTER_ZORRO, + BOARD_JUMPER_TPRO, BOARD_TYPE_COUNT, BOARD_TYPE_MAX = BOARD_TYPE_COUNT - 1 }; @@ -143,7 +144,8 @@ namespace Board { NumTrims, NumTrimSwitches, HasRTC, - HasColorLcd + HasColorLcd, + NumFunctionSwitches }; struct SwitchInfo @@ -237,6 +239,11 @@ inline bool IS_JUMPER_TLITE(Board::Type board) return board == Board::BOARD_JUMPER_TLITE; } +inline bool IS_JUMPER_TPRO(Board::Type board) +{ + return board == Board::BOARD_JUMPER_TPRO; +} + inline bool IS_JUMPER_T16(Board::Type board) { return board == Board::BOARD_JUMPER_T16; @@ -335,7 +342,7 @@ inline bool IS_TARANIS_X9E(Board::Type board) inline bool IS_TARANIS_SMALL(Board::Type board) { - return IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board) || IS_FAMILY_T12(board); + return IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board) || IS_FAMILY_T12(board) || IS_JUMPER_TPRO(board); } inline bool IS_TARANIS(Board::Type board) diff --git a/companion/src/firmwares/eepromimportexport.h b/companion/src/firmwares/eepromimportexport.h index 965810731..bcb66ab65 100644 --- a/companion/src/firmwares/eepromimportexport.h +++ b/companion/src/firmwares/eepromimportexport.h @@ -568,7 +568,7 @@ class TransformedField: public DataField { virtual void afterImport() = 0; - int dump(int level, int offset) override + int dump(int level=0, int offset=0) override { beforeExport(); return field.dump(level, offset); diff --git a/companion/src/firmwares/eeprominterface.h b/companion/src/firmwares/eeprominterface.h index 02ab4884d..099501c9d 100644 --- a/companion/src/firmwares/eeprominterface.h +++ b/companion/src/firmwares/eeprominterface.h @@ -162,7 +162,8 @@ enum Capability { HasAntennaChoice, HasADCJitterFilter, HasTelemetryBaudrate, - TopBarZones + TopBarZones, + FunctionSwitches }; class EEPROMInterface diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index e6b12ca5e..a5aa59b10 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -212,6 +212,17 @@ void ModelData::setDefaultMixes(const GeneralSettings & settings) } } +void ModelData::setDefaultFunctionSwitches(int functionSwitchCount) +{ + if (functionSwitchCount == 0) + return; + + for (int i = 0; i < functionSwitchCount; i++) { + functionSwitchConfig |= (Board::SWITCH_2POS << 2 * i); + functionSwitchGroup |= (1 << 2 * i); + } +} + void ModelData::setDefaultValues(unsigned int id, const GeneralSettings & settings) { clear(); @@ -221,6 +232,7 @@ void ModelData::setDefaultValues(unsigned int id, const GeneralSettings & settin moduleData[i].modelId = id + 1; } setDefaultMixes(settings); + setDefaultFunctionSwitches(getCurrentFirmware()->getCapability(FunctionSwitches)); } int ModelData::getTrimValue(int phaseIdx, int trimIdx) diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index fbdd8f9c7..454ab9d2e 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -145,6 +145,7 @@ class ModelData { bool potsWarnEnabled[CPN_MAX_POTS]; int potsWarnPosition[CPN_MAX_POTS]; bool displayChecklist; + GVarData gvarData[CPN_MAX_GVARS]; MavlinkData mavlink; unsigned int telemetryProtocol; @@ -170,10 +171,18 @@ class ModelData { char registrationId[8+1]; + // Function switches + unsigned int functionSwitchConfig; + unsigned int functionSwitchGroup; + unsigned int functionSwitchStartConfig; + unsigned int functionSwitchLogicalState; + char functionSwitchNames[CPN_MAX_FUNCTION_SWITCHES][HARDWARE_NAME_LEN + 1]; + void clear(); bool isEmpty() const; void setDefaultInputs(const GeneralSettings & settings); void setDefaultMixes(const GeneralSettings & settings); + void setDefaultFunctionSwitches(int functionSwitchCount); void setDefaultValues(unsigned int id, const GeneralSettings & settings); int getTrimValue(int phaseIdx, int trimIdx); diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index df8b9263a..421138999 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -51,6 +51,9 @@ inline int MAX_SWITCHES(Board::Type board, int version) if (IS_TARANIS_X7(board)) return 8; + if (IS_JUMPER_TPRO(board)) + return 10; + return Boards::getCapability(board, Board::Switches); } @@ -81,6 +84,13 @@ inline int MAX_POTS(Board::Type board, int version) return Boards::getCapability(board, Board::Pots); } +inline int MAX_FUNCTION_SWITCHES(Board::Type board, int version) +{ + if (IS_JUMPER_TPRO(board)) + return 6; + return 0; +} + inline int MAX_POTS_STORAGE(Board::Type board, int version) { if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board)) @@ -2630,17 +2640,17 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig internalField.Append(new LimitField(this, modelData.limitData[i], board, version)); for (int i=0; i(this, modelData.thrTraceSrc, "Throttle Source")); @@ -2836,6 +2846,16 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig else if (version >= 219) { internalField.Append(new ZCharField<8>(this, modelData.registrationId, "ACCESS Registration ID")); } + + if (IS_JUMPER_TPRO(board)) { + internalField.Append(new UnsignedField<16>(this, modelData.functionSwitchConfig)); + internalField.Append(new UnsignedField<16>(this, modelData.functionSwitchGroup)); + internalField.Append(new UnsignedField<16>(this, modelData.functionSwitchStartConfig)); + internalField.Append(new UnsignedField<8>(this, modelData.functionSwitchLogicalState)); + for (int i=0; i < MAX_FUNCTION_SWITCHES(board, version); ++i) { + internalField.Append(new ZCharField<3>(this, modelData.functionSwitchNames[i], "Function switch name")); + } + } } void OpenTxModelData::beforeExport() diff --git a/companion/src/firmwares/opentx/opentxeeprom.h b/companion/src/firmwares/opentx/opentxeeprom.h index c3f188eea..5ad907871 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.h +++ b/companion/src/firmwares/opentx/opentxeeprom.h @@ -40,6 +40,7 @@ #define JUMPER_TLITE_VARIANT 0x4003 #define RADIOMASTER_T8_VARIANT 0x4004 #define RADIOMASTER_ZORRO_VARIANT 0x4006 +#define JUMPER_TPRO_VARIANT 0x4005 class OpenTxGeneralData: public TransformedField { public: diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 59c6bab33..940d57456 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -62,6 +62,8 @@ const char * OpenTxEepromInterface::getName() return "OpenTX for Jumper T12"; case BOARD_JUMPER_TLITE: return "OpenTX for Jumper T-Lite"; + case BOARD_JUMPER_TPRO: + return "OpenTX for Jumper T-Pro"; case BOARD_JUMPER_T16: return "OpenTX for Jumper T16"; case BOARD_JUMPER_T18: @@ -347,6 +349,9 @@ int OpenTxEepromInterface::save(uint8_t * eeprom, const RadioData & radioData, u else if (IS_JUMPER_TLITE(board)) { variant |= JUMPER_TLITE_VARIANT; } + else if (IS_JUMPER_TPRO(board)) { + variant |= JUMPER_TPRO_VARIANT; + } else if (IS_RADIOMASTER_TX12(board)) { variant |= RADIOMASTER_TX12_VARIANT; } @@ -752,6 +757,9 @@ int OpenTxFirmware::getCapability(::Capability capability) return IS_HORUS_OR_TARANIS(board) ? true : false; case TopBarZones: return getCapability(LcdWidth) > getCapability(LcdHeight) ? 4 : 2; + case FunctionSwitches: + return IS_JUMPER_TPRO(board) ? 6 : 0; + default: return 0; } @@ -1025,6 +1033,11 @@ bool OpenTxEepromInterface::checkVariant(unsigned int version, unsigned int vari variantError = true; } } + else if (IS_JUMPER_TPRO(board)) { + if (variant != JUMPER_TPRO_VARIANT) { + variantError = true; + } + } else if (IS_RADIOMASTER_TX12(board)) { if (variant != RADIOMASTER_TX12_VARIANT) { variantError = true; @@ -1371,6 +1384,16 @@ void registerOpenTxFirmwares() registerOpenTxFirmware(firmware); addOpenTxRfOptions(firmware, FLEX); + /* Jumper T-Pro board */ + firmware = new OpenTxFirmware("opentx-tpro", QCoreApplication::translate("Firmware", "Jumper T-Pro"), BOARD_JUMPER_TPRO); + addOpenTxCommonOptions(firmware); + firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support")); + firmware->addOption("nogvars", Firmware::tr("Disable Global variables")); + firmware->addOption("lua", Firmware::tr("Enable Lua custom scripts screen")); + addOpenTxFontOptions(firmware); + registerOpenTxFirmware(firmware); + addOpenTxRfOptions(firmware, FLEX); + /* Jumper T16 board */ firmware = new OpenTxFirmware("opentx-t16", Firmware::tr("Jumper T16 / T16+ / T16 Pro"), BOARD_JUMPER_T16); addOpenTxFrskyOptions(firmware); diff --git a/companion/src/images/simulator/JumperTPRO/bottom.png b/companion/src/images/simulator/JumperTPRO/bottom.png new file mode 100644 index 000000000..185b5ac36 Binary files /dev/null and b/companion/src/images/simulator/JumperTPRO/bottom.png differ diff --git a/companion/src/images/simulator/JumperTPRO/left.png b/companion/src/images/simulator/JumperTPRO/left.png new file mode 100644 index 000000000..efcfb5e98 Binary files /dev/null and b/companion/src/images/simulator/JumperTPRO/left.png differ diff --git a/companion/src/images/simulator/JumperTPRO/right.png b/companion/src/images/simulator/JumperTPRO/right.png new file mode 100644 index 000000000..e30e90a91 Binary files /dev/null and b/companion/src/images/simulator/JumperTPRO/right.png differ diff --git a/companion/src/images/simulator/JumperTPRO/top.png b/companion/src/images/simulator/JumperTPRO/top.png new file mode 100644 index 000000000..7cf5226ff Binary files /dev/null and b/companion/src/images/simulator/JumperTPRO/top.png differ diff --git a/companion/src/modeledit/CMakeLists.txt b/companion/src/modeledit/CMakeLists.txt index 73f0acf92..7404f821e 100644 --- a/companion/src/modeledit/CMakeLists.txt +++ b/companion/src/modeledit/CMakeLists.txt @@ -45,6 +45,7 @@ set(modeledit_HDRS set(modeledit_UIS setup_timer.ui setup_module.ui + setup_function_switches.ui flightmode.ui telemetry_customscreen.ui telemetry_sensor.ui diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index 9b4222d50..30cf3bbe2 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -22,6 +22,7 @@ #include "ui_setup.h" #include "ui_setup_timer.h" #include "ui_setup_module.h" +#include "ui_setup_function_switches.h" #include "appdata.h" #include "modelprinter.h" #include "multiprotocols.h" @@ -982,6 +983,170 @@ void ModulePanel::onClearAccessRxClicked() } } +/******************************************************************************/ +FunctionSwitchesPanel::FunctionSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): + ModelPanel(parent, model, generalSettings, firmware), + ui(new Ui::FunctionSwitches) +{ + ui->setupUi(this); + + lock = true; + + QRegExp rx(CHAR_FOR_NAMES_REGEX); + + switchcnt = Boards::getCapability(firmware->getBoard(), Board::NumFunctionSwitches); + + for (int i = 0; i < switchcnt; i++) { + QLabel * lblSwitchId = new QLabel(this); + lblSwitchId->setText(tr("SW%1").arg(i + 1)); + + AutoLineEdit * aleName = new AutoLineEdit(this); + aleName->setProperty("index", i); + aleName->setValidator(new QRegExpValidator(rx, this)); + aleName->setField((char *)model.functionSwitchNames[i], 3); + + // TODO itemmodel + QComboBox * cboConfig = new QComboBox(this); + cboConfig->setProperty("index", i); + cboConfig->addItem(tr("NONE")); + cboConfig->addItem(tr("TOGGLE")); + cboConfig->addItem(tr("2POS")); + + // TODO itemmodel + QComboBox * cboStartPosn = new QComboBox(this); + cboStartPosn->setProperty("index", i); + cboStartPosn->addItem(CPN_STR_SW_INDICATOR_UP); + cboStartPosn->addItem(CPN_STR_SW_INDICATOR_DN); + cboStartPosn->addItem("="); + + QSpinBox * sbGroup = new QSpinBox(this); + sbGroup->setProperty("index", i); + sbGroup->setMaximum(3); + + int row = 0; + int coloffset = 1; + ui->gridSwitches->addWidget(lblSwitchId, row++, i + coloffset); + ui->gridSwitches->addWidget(aleName, row++, i + coloffset); + ui->gridSwitches->addWidget(cboConfig, row++, i + coloffset); + ui->gridSwitches->addWidget(cboStartPosn, row++, i + coloffset); + ui->gridSwitches->addWidget(sbGroup, row++, i + coloffset); + + connect(cboConfig, QOverload::of(&QComboBox::currentIndexChanged), this, &FunctionSwitchesPanel::on_configCurrentIndexChanged); + connect(cboStartPosn, QOverload::of(&QComboBox::currentIndexChanged), this, &FunctionSwitchesPanel::on_startPosnCurrentIndexChanged); + connect(sbGroup, QOverload::of(&QSpinBox::valueChanged), this, &FunctionSwitchesPanel::on_groupChanged); + + aleNames << aleName; + cboConfigs << cboConfig; + cboStartupPosns << cboStartPosn; + sbGroups << sbGroup; + } + + update(); + + lock = false; +} + +FunctionSwitchesPanel::~FunctionSwitchesPanel() +{ + delete ui; +} + +void FunctionSwitchesPanel::update() +{ + for (int i = 0; i < switchcnt; i++) { + update(i); + } +} + +void FunctionSwitchesPanel::update(int index) +{ + lock = true; + + for (int i = 0; i < switchcnt; i++) { + aleNames[i]->update(); + cboConfigs[i]->setCurrentIndex((model->functionSwitchConfig >> (2 * i)) & 0x03); + cboStartupPosns[i]->setCurrentIndex((model->functionSwitchStartConfig >> (2 * i)) & 0x03); + sbGroups[i]->setValue((model->functionSwitchGroup >> (2 * i)) & 0x03); + + if (cboConfigs[i]->currentIndex() < 2) + cboStartupPosns[i]->setEnabled(false); + else + cboStartupPosns[i]->setEnabled(true); + + if (cboConfigs[i]->currentIndex() < 1) + sbGroups[i]->setEnabled(false); + else + sbGroups[i]->setEnabled(true); + } + + lock = false; +} + +void FunctionSwitchesPanel::on_configCurrentIndexChanged(int index) +{ + if (!sender()) + return; + + QComboBox * cb = qobject_cast(sender()); + + if (cb && !lock) { + lock = true; + bool ok = false; + int i = sender()->property("index").toInt(&ok); + if (ok && ((model->functionSwitchConfig >> (2 * i)) & 0x03) != (unsigned int)index) { + unsigned int mask = ((unsigned int) 0x03 << (2 * i)); + model->functionSwitchConfig = (model->functionSwitchConfig & ~ mask) | ((unsigned int) index << (2 * i)); + if (index < 2) + model->functionSwitchStartConfig = (model->functionSwitchStartConfig & ~ mask) | ((unsigned int) 0 << (2 * i)); + if (index < 1) + model->functionSwitchGroup = (model->functionSwitchGroup & ~ mask) | ((unsigned int) 0 << (2 * i)); + update(i); + emit modified(); + } + lock = false; + } +} + +void FunctionSwitchesPanel::on_startPosnCurrentIndexChanged(int index) +{ + if (!sender()) + return; + + QComboBox * cb = qobject_cast(sender()); + + if (cb && !lock) { + lock = true; + bool ok = false; + int i = sender()->property("index").toInt(&ok); + if (ok && ((model->functionSwitchStartConfig >> (2 * i)) & 0x03) != (unsigned int)index) { + unsigned int mask = ((unsigned int) 0x03 << (2 * i)); + model->functionSwitchStartConfig = (model->functionSwitchStartConfig & ~ mask) | ((unsigned int) index << (2 * i)); + emit modified(); + } + lock = false; + } +} + +void FunctionSwitchesPanel::on_groupChanged(int value) +{ + if (!sender()) + return; + + QSpinBox * sb = qobject_cast(sender()); + + if (sb && !lock) { + lock = true; + bool ok = false; + int i = sender()->property("index").toInt(&ok); + if (ok && ((model->functionSwitchGroup >> (2 * i)) & 0x03) != (unsigned int)value) { + unsigned int mask = ((unsigned int) 0x03 << (2 * i)); + model->functionSwitchGroup = (model->functionSwitchGroup & ~ mask) | ((unsigned int) value << (2 * i)); + emit modified(); + } + lock = false; + } +} + /******************************************************************************/ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, @@ -1221,6 +1386,11 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge ui->trimsDisplay->setField(model.trimsDisplay, this); + if (Boards::getCapability(firmware->getBoard(), Board::NumFunctionSwitches) > 0) + ui->functionSwitchesLayout->addWidget(new FunctionSwitchesPanel(this, model, generalSettings, firmware)); + //else + // ui->functionSwitchesLayout->hide(); + for (int i = firmware->getCapability(NumFirstUsableModule); i < firmware->getCapability(NumModules); i++) { modules[i] = new ModulePanel(this, model, model.moduleData[i], generalSettings, firmware, i); ui->modulesLayout->addWidget(modules[i]); diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h index 824b28acb..c63932237 100644 --- a/companion/src/modeledit/setup.h +++ b/companion/src/modeledit/setup.h @@ -31,8 +31,11 @@ namespace Ui { class Setup; class Timer; class Module; + class FunctionSwitches; } +class AutoLineEdit; + class TimerPanel : public ModelPanel { Q_OBJECT @@ -128,6 +131,31 @@ class ModulePanel : public ModelPanel void updateFailsafeUI(unsigned channel, quint8 updtSb); }; +class FunctionSwitchesPanel : public ModelPanel +{ + Q_OBJECT + + public: + FunctionSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); + virtual ~FunctionSwitchesPanel(); + + virtual void update(); + void update(int index); + + private slots: + void on_configCurrentIndexChanged(int index); + void on_startPosnCurrentIndexChanged(int index); + void on_groupChanged(int value); + + private: + Ui::FunctionSwitches * ui; + QVector aleNames; + QVector cboConfigs; + QVector cboStartupPosns; + QVector sbGroups; + int switchcnt; +}; + class SetupPanel : public ModelPanel { Q_OBJECT diff --git a/companion/src/modeledit/setup.ui b/companion/src/modeledit/setup.ui index ee0ec28a3..51aae4f1e 100644 --- a/companion/src/modeledit/setup.ui +++ b/companion/src/modeledit/setup.ui @@ -7,7 +7,7 @@ 0 0 1007 - 405 + 435 @@ -630,6 +630,9 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi + + + diff --git a/companion/src/modeledit/setup_function_switches.ui b/companion/src/modeledit/setup_function_switches.ui new file mode 100644 index 000000000..acfd88e5d --- /dev/null +++ b/companion/src/modeledit/setup_function_switches.ui @@ -0,0 +1,121 @@ + + + FunctionSwitches + + + + 0 + 0 + 231 + 140 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + + + + + + + 75 + true + + + + Function Switches + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + QLayout::SetMinimumSize + + + + + Type + + + + + + + + 0 + 0 + + + + Group + + + + + + + Start + + + + + + + Name + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + diff --git a/companion/src/simulation/CMakeLists.txt b/companion/src/simulation/CMakeLists.txt index cc605abbb..091867696 100644 --- a/companion/src/simulation/CMakeLists.txt +++ b/companion/src/simulation/CMakeLists.txt @@ -14,6 +14,7 @@ set(simulation_SRCS simulateduiwidgetX12.cpp simulateduiwidgetJumperT12.cpp simulateduiwidgetJumperTLITE.cpp + simulateduiwidgetJumperTPRO.cpp simulateduiwidgetJumperT16.cpp simulateduiwidgetJumperT18.cpp simulateduiwidgetTX12.cpp @@ -46,6 +47,7 @@ set(simulation_UIS simulateduiwidgetX12.ui simulateduiwidgetJumperT12.ui simulateduiwidgetJumperTLITE.ui + simulateduiwidgetJumperTPRO.ui simulateduiwidgetJumperT16.ui simulateduiwidgetJumperT18.ui simulateduiwidgetTX12.ui diff --git a/companion/src/simulation/simulateduiwidget.h b/companion/src/simulation/simulateduiwidget.h index 579ad567f..187a60660 100644 --- a/companion/src/simulation/simulateduiwidget.h +++ b/companion/src/simulation/simulateduiwidget.h @@ -113,6 +113,7 @@ namespace Ui { class SimulatedUIWidgetX12; class SimulatedUIWidgetJumperT12; class SimulatedUIWidgetJumperTLITE; + class SimulatedUIWidgetJumperTPRO; class SimulatedUIWidgetJumperT16; class SimulatedUIWidgetJumperT18; class SimulatedUIWidgetTX16S; @@ -258,6 +259,18 @@ class SimulatedUIWidgetJumperTLITE: public SimulatedUIWidget Ui::SimulatedUIWidgetJumperTLITE * ui; }; +class SimulatedUIWidgetJumperTPRO: public SimulatedUIWidget +{ + Q_OBJECT + + public: + explicit SimulatedUIWidgetJumperTPRO(SimulatorInterface * simulator, QWidget * parent = NULL); + virtual ~SimulatedUIWidgetJumperTPRO(); + + private: + Ui::SimulatedUIWidgetJumperTPRO * ui; +}; + class SimulatedUIWidgetJumperT16: public SimulatedUIWidget { Q_OBJECT diff --git a/companion/src/simulation/simulateduiwidgetJumperTPRO.cpp b/companion/src/simulation/simulateduiwidgetJumperTPRO.cpp new file mode 100644 index 000000000..e46c7fbad --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetJumperTPRO.cpp @@ -0,0 +1,54 @@ +#include "simulateduiwidget.h" +#include "ui_simulateduiwidgetJumperTPRO.h" + +// NOTE: RadioUiAction(NUMBER,...): NUMBER relates to enum EnumKeys in the specific board.h + +SimulatedUIWidgetJumperTPRO::SimulatedUIWidgetJumperTPRO(SimulatorInterface *simulator, QWidget * parent): + SimulatedUIWidget(simulator, parent), + ui(new Ui::SimulatedUIWidgetJumperTPRO) +{ + RadioUiAction * act; + + ui->setupUi(this); + + act = new RadioUiAction(0, QList() << Qt::Key_PageUp << Qt::Key_Up, SIMU_STR_HLP_KEYS_GO_UP, SIMU_STR_HLP_ACT_MENU_ICN); + addRadioWidget(ui->leftbuttons->addArea(QRect(70, 85, 110, 90), "JumperTPRO/left.png", act)); + + act = new RadioUiAction(3, QList() << Qt::Key_PageDown << Qt::Key_Down, SIMU_STR_HLP_KEYS_GO_DN, SIMU_STR_HLP_ACT_PAGE); + addRadioWidget(ui->leftbuttons->addArea(QRect(53, 174, 110, 90), "JumperTPRO/left.png", act)); + + act = new RadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_EXIT); + addRadioWidget(ui->leftbuttons->addArea(QRect(11, 257, 110, 90), "JumperTPRO/left.png", act)); + + m_mouseMidClickAction = new RadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN); + addRadioWidget(ui->rightbuttons->addArea(QRect(10, 96, 200, 220), "JumperTPRO/right.png", m_mouseMidClickAction)); + + //addRadioWidget(ui->leftbuttons->addArea(QRect(10, 65, 70, 50), "JumperTPRO/left_scrnshot.png", m_screenshotAction)); + + m_backlightColors << QColor(215, 243, 255); // X7 Blue + m_backlightColors << QColor(166,247,159); + m_backlightColors << QColor(247,159,166); + m_backlightColors << QColor(255,195,151); + m_backlightColors << QColor(247,242,159); + + setLcd(ui->lcd); + + QString css = "#radioUiWidget {" + "background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1," + "stop:0 rgba(255, 255, 255, 255)," + "stop:0.757062 rgba(241, 238, 238, 255)," + "stop:1 rgba(247, 245, 245, 255));" + "}"; + + QTimer * tim = new QTimer(this); + tim->setSingleShot(true); + connect(tim, &QTimer::timeout, [this, css]() { + emit customStyleRequest(css); + }); + tim->start(100); +} + +SimulatedUIWidgetJumperTPRO::~SimulatedUIWidgetJumperTPRO() +{ + delete ui; +} diff --git a/companion/src/simulation/simulateduiwidgetJumperTPRO.ui b/companion/src/simulation/simulateduiwidgetJumperTPRO.ui new file mode 100644 index 000000000..5a77f11ff --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetJumperTPRO.ui @@ -0,0 +1,258 @@ + + + SimulatedUIWidgetJumperTPRO + + + + 0 + 0 + 725 + 389 + + + + + 0 + 0 + + + + + 725 + 389 + + + + + 501 + 310 + + + + Jumper T-Pro Simulator + + + background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 255), stop:0.757062 rgba(241, 238, 238, 255), stop:1 rgba(247, 245, 245, 255)); + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 234 + 368 + + + + + 234 + 368 + + + + background:url(:/images/simulator/JumperTPRO/left.png); + + + + + + + + 0 + 0 + + + + + 256 + 231 + + + + + 256 + 231 + + + + background-color: rgb(215, 243, 255); + + + + + + + + 0 + 0 + + + + + 236 + 368 + + + + + 236 + 368 + + + + background:url(:/images/simulator/JumperTPRO/right.png) + + + + + + + + 0 + 0 + + + + + 255 + 85 + + + + + 255 + 85 + + + + background:url(:/images/simulator/JumperTPRO/top.png) + + + + + + + + 0 + 0 + + + + + 255 + 131 + + + + + 255 + 131 + + + + background:url(:/images/simulator/JumperTPRO/bottom.png) + + + + + + + + 0 + 0 + + + + + 0 + 10 + + + + + 16777215 + 12 + + + + + 0 + 12 + + + + background-color: rgb(255, 255, 255); + + + + + + + + + + + 0 + 0 + + + + + 0 + 10 + + + + + 16777215 + 10 + + + + background-color: rgb(247, 245, 245); + + + + + + + + + + + LcdWidget + QWidget +
lcdwidget.h
+ 1 +
+ + ButtonsWidget + QWidget +
buttonswidget.h
+ 1 +
+
+ + +
diff --git a/companion/src/simulation/simulatorwidget.cpp b/companion/src/simulation/simulatorwidget.cpp index b087c7055..8f3ef08c2 100644 --- a/companion/src/simulation/simulatorwidget.cpp +++ b/companion/src/simulation/simulatorwidget.cpp @@ -94,6 +94,9 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato case Board::BOARD_JUMPER_TLITE: radioUiWidget = new SimulatedUIWidgetJumperTLITE(simulator, this); break; + case Board::BOARD_JUMPER_TPRO: + radioUiWidget = new SimulatedUIWidgetJumperTPRO(simulator, this); + break; case Board::BOARD_JUMPER_T16: radioUiWidget = new SimulatedUIWidgetJumperT16(simulator, this); break; diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index fd108bf56..268dcb9a5 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -419,7 +419,12 @@ enum SwitchSources { SWSRC_SD2, #endif -#if defined(STORAGE_SWITCH_E) +#if defined(FUNCTION_SWITCHES) && defined(RADIO_TPRO) + SWSRC_FIRST_FUNCTION_SWITCH, + SWSRC_SE0 = SWSRC_FIRST_FUNCTION_SWITCH, + SWSRC_SE1, + SWSRC_SE2, +#elif defined(STORAGE_SWITCH_E) SWSRC_SE0, SWSRC_SE1, SWSRC_SE2, @@ -569,7 +574,7 @@ enum SwitchSources { SWSRC_INVERT SKIP = SWSRC_COUNT+1, }; -#if NUM_SWITCHES >= 8 +#if NUM_SWITCHES - NUM_FUNCTIONS_SWITCHES >= 8 #define SWSRC_TRAINER SWSRC_SH2 #else #define SWSRC_TRAINER SWSRC_LAST_SWITCH, @@ -786,11 +791,15 @@ enum MixSources { static_assert(MIXSRC_FIRST_LOGICAL_SWITCH == MIXSRC_FIRST_SWITCH + STORAGE_NUM_SWITCHES, "Wrong switches definition in MIXSRC list"); #endif -#define MIXSRC_FIRST (MIXSRC_NONE + 1) -#define MIXSRC_LAST MIXSRC_LAST_CH -#define MIXSRC_LAST_SWITCH (MIXSRC_FIRST_SWITCH + STORAGE_NUM_SWITCHES - 1) -#define INPUTSRC_FIRST MIXSRC_Rud -#define INPUTSRC_LAST MIXSRC_LAST_TELEM +#define MIXSRC_FIRST (MIXSRC_NONE + 1) +#define MIXSRC_LAST MIXSRC_LAST_CH +#define MIXSRC_LAST_SWITCH (MIXSRC_FIRST_SWITCH + STORAGE_NUM_SWITCHES - 1) +#define INPUTSRC_FIRST MIXSRC_Rud +#define INPUTSRC_LAST MIXSRC_LAST_TELEM +#if defined(FUNCTION_SWITCHES) +#define MIXSRC_LAST_REGULAR_SWITCH (MIXSRC_FIRST_SWITCH + NUM_REGULAR_SWITCHES - 1) +#define MIXSRC_FIRST_FS_SWITCH (MIXSRC_LAST_REGULAR_SWITCH + 1) +#endif enum BacklightMode { e_backlight_mode_off = 0, diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index 5cc4c4319..8da911cf5 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -121,6 +121,9 @@ static inline void check_struct() #elif defined(PCBXLITE) CHKSIZE(RadioData, 858); CHKSIZE(ModelData, 6159); +#elif defined(RADIO_TPRO) + CHKSIZE(RadioData, 841); + CHKSIZE(ModelData, 6184); #elif defined(PCBX7) CHKSIZE(RadioData, 864); CHKSIZE(ModelData, 6159); diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index e062e926d..c4453ee69 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -616,6 +616,17 @@ PACK(struct CustomScreenData { #define SCRIPT_DATA #endif +#if defined(FUNCTION_SWITCHES) && NUM_FUNCTIONS_SWITCHES < 8 + #define FUNCTION_SWITCHS_FIELDS \ + uint16_t functionSwitchConfig; \ + uint16_t functionSwitchGroup; \ + uint16_t functionSwitchStartConfig; \ + uint8_t functionSwitchLogicalState; \ + char switchNames[NUM_FUNCTIONS_SWITCHES][LEN_SWITCH_NAME]; +#else + #define FUNCTION_SWITCHS_FIELDS +#endif + PACK(struct PartialModel { ModelHeader header; TimerData timers[MAX_TIMERS]; @@ -683,6 +694,8 @@ PACK(struct ModelData { char modelRegistrationID[PXX2_LEN_REGISTRATION_ID]; + FUNCTION_SWITCHS_FIELDS + bool isTrainerTraineeEnable() const { #if defined(PCBNV14) @@ -794,7 +807,7 @@ PACK(struct TrainerData { uint8_t backlightColor; \ CUST_ARRAY(sticksConfig, struct_sticksConfig, stick_name_valid); \ swconfig_t switchConfig ARRAY(2,struct_switchConfig,nullptr); \ - char switchNames[STORAGE_NUM_SWITCHES][LEN_SWITCH_NAME] SKIP; \ + char switchNames[STORAGE_NUM_SWITCHES - NUM_FUNCTIONS_SWITCHES][LEN_SWITCH_NAME] SKIP; \ char anaNames[NUM_STICKS+STORAGE_NUM_POTS+STORAGE_NUM_SLIDERS][LEN_ANA_NAME] SKIP; \ BLUETOOTH_FIELDS #else diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index f6a6c6160..9460b4a74 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -39,7 +39,7 @@ uint8_t g_moduleIdx; uint8_t getSwitchWarningsCount() { uint8_t count = 0; - for (int i=0; ipersistent = editChoice(MODEL_SETUP_2ND_COLUMN, y, STR_PERSISTENT, STR_VPERSISTENT, timer->persistent, 0, 2, attr, event); break; } +#if defined(FUNCTION_SWITCHES) + case ITEM_MODEL_SETUP_LABEL: + lcdDrawTextAlignedLeft(y, "Function Switches"); + break; + + case ITEM_MODEL_SETUP_SW1: + case ITEM_MODEL_SETUP_SW2: + case ITEM_MODEL_SETUP_SW3: + case ITEM_MODEL_SETUP_SW4: + case ITEM_MODEL_SETUP_SW5: + case ITEM_MODEL_SETUP_SW6: + { + int index = k - ITEM_MODEL_SETUP_SW1; + int config = FSWITCH_CONFIG(index); + lcdDrawTextAtIndex(INDENT_WIDTH, y, STR_VSRCRAW, MIXSRC_FIRST_SWITCH + NUM_REGULAR_SWITCHES - MIXSRC_Rud + index + 1, menuHorizontalPosition < 0 ? attr : 0); + if (ZEXIST(g_model.switchNames[index]) || (attr && s_editMode > 0 && menuHorizontalPosition == 0)) + editName(35, y, g_model.switchNames[index], LEN_SWITCH_NAME, event, true, menuHorizontalPosition == 0 ? attr : 0, old_editMode); + else + lcdDrawMMM(35, y, menuHorizontalPosition == 0 ? attr : 0); + config = editChoice(30 + 5*FW, y, "", STR_SWTYPES, config, SWITCH_NONE, SWITCH_2POS, menuHorizontalPosition == 1 ? attr : 0, event); + if (attr && checkIncDec_Ret) { + swconfig_t mask = (swconfig_t)0x03 << (2*index); + g_model.functionSwitchConfig = (g_model.functionSwitchConfig & ~mask) | ((swconfig_t(config) & 0x03) << (2*index)); + } + + config = FSWITCH_GROUP(index); + config = editChoice(30 + 15*FW, y, "", STR_FSGROUPS, config, 0, 3, menuHorizontalPosition == 2 ? attr : 0, event); + if (attr && checkIncDec_Ret && menuHorizontalPosition == 2) { + swconfig_t mask = (swconfig_t) 0x03 << (2 * index); + g_model.functionSwitchGroup = (g_model.functionSwitchGroup & ~mask) | ((swconfig_t(config) & 0x03) << (2 * index)); + } + break; + } + + case ITEM_MODEL_SETUP_FS_STARTUP: + { + char c; + lcdDrawText(0, y, INDENT "Start", menuHorizontalPosition < 0 ? attr : 0); + for (uint8_t i = 0; i < NUM_FUNCTIONS_SWITCHES; i++) { + uint8_t startPos = (g_model.functionSwitchStartConfig >> 2 * i) & 0x03; + c = "\300\301="[(g_model.functionSwitchStartConfig >> 2 * i) & 0x03]; + lcdDrawNumber(MODEL_SETUP_2ND_COLUMN - (2 + FW) + i * 2 * FW, y, i + 1, 0); + lcdDrawChar(lcdNextPos, y, c, attr && (menuHorizontalPosition == i) ? (s_editMode ? INVERS + BLINK : INVERS) : 0); + if (attr && menuHorizontalPosition == i) { + CHECK_INCDEC_MODELVAR(event, startPos, 0, 2); + } + if (attr && checkIncDec_Ret) { + swconfig_t mask = (swconfig_t)0x03 << (2*i); + g_model.functionSwitchStartConfig = (g_model.functionSwitchStartConfig & ~mask) | ((swconfig_t(startPos) & 0x03) << (2*i)); + storageDirty(EE_MODEL); + } + } + break; + } +#endif case ITEM_MODEL_SETUP_EXTENDED_LIMITS: g_model.extendedLimits = editCheckBox(g_model.extendedLimits, MODEL_SETUP_2ND_COLUMN, y, STR_ELIMITS, attr, event); break; @@ -724,7 +796,7 @@ void menuModelSetup(event_t event) } int current = 0; - for (int i = 0; i < NUM_SWITCHES; i++) { + for (int i = 0; i < NUM_SWITCHES - NUM_FUNCTIONS_SWITCHES; i++) { if (SWITCH_WARNING_ALLOWED(i)) { div_t qr = div(current, MAX_SWITCH_PER_LINE); if (!READ_ONLY() && event == EVT_KEY_BREAK(KEY_ENTER) && attr && diff --git a/radio/src/gui/128x64/radio_diagkeys.cpp b/radio/src/gui/128x64/radio_diagkeys.cpp index 02f9b4b86..2452b900b 100644 --- a/radio/src/gui/128x64/radio_diagkeys.cpp +++ b/radio/src/gui/128x64/radio_diagkeys.cpp @@ -41,7 +41,7 @@ void menuRadioDiagKeys(event_t event) lcdDrawText(14*FW, MENU_HEADER_HEIGHT + 1, STR_VTRIM); - for (uint8_t i=0; i<9; i++) { + for (uint8_t i=0; i<10; i++) { coord_t y; if (i < NUM_TRIMS_KEYS) { @@ -69,10 +69,19 @@ void menuRadioDiagKeys(event_t event) drawSwitch(8*FW, y, i+1, 0); displaySwitchState(11*FW+2, y, i); } +#elif (NUM_SWITCHES > 6) + if (i < NUM_SWITCHES) { + if (SWITCH_EXISTS(i)) { + y = (i > 4) ? FH*(i-4) : MENU_HEADER_HEIGHT + FH*i; + getvalue_t val = getValue(MIXSRC_FIRST_SWITCH+i); + getvalue_t sw = ((val < 0) ? 3*i+1 : ((val == 0) ? 3*i+2 : 3*i+3)); + drawSwitch(i > 4 ? 11*FW-5: 8*FW-9, y, sw, 0, false); + } + } #else if (i < NUM_SWITCHES) { if (SWITCH_EXISTS(i)) { - y = (NUM_SWITCHES > 6 ? 0 : MENU_HEADER_HEIGHT) + FH*i; + y = (NUM_SWITCHES - NUM_FUNCTIONS_SWITCHES > 6 ? 0 : MENU_HEADER_HEIGHT) + FH*i; getvalue_t val = getValue(MIXSRC_FIRST_SWITCH+i); getvalue_t sw = ((val < 0) ? 3*i+1 : ((val == 0) ? 3*i+2 : 3*i+3)); drawSwitch(8*FW+4, y, sw, 0); @@ -81,8 +90,18 @@ void menuRadioDiagKeys(event_t event) #endif } +#if defined(FUNCTION_SWITCHES) && defined(DEBUG) + lcdDrawText(LCD_W / 2 , LCD_H - 2 * FH, "Phys"); + lcdDrawText(LCD_W / 2 , LCD_H - 1 * FH, "Log"); + + for (uint8_t i = 0; i < NUM_FUNCTIONS_SWITCHES; i++) { + lcdDrawNumber(LCD_W / 2 + 20 + (i + 1) * FW , LCD_H - 2 * FH, getFSPhysicalState(i)); + lcdDrawNumber(LCD_W / 2 + 20 + (i + 1) * FW , LCD_H - 1 * FH, getFSLogicalState(i)); + } +#endif + #if defined(ROTARY_ENCODER_NAVIGATION) - coord_t y = MENU_HEADER_HEIGHT + 1 + FH*KEY_COUNT; + coord_t y = LCD_H - FH - 1; lcdDrawText(0, y, STR_ROTARY_ENCODER); lcdDrawNumber(5*FW+FWNUM+2, y, rotencValue / ROTARY_ENCODER_GRANULARITY, RIGHT); #endif diff --git a/radio/src/gui/128x64/view_main.cpp b/radio/src/gui/128x64/view_main.cpp index 471dc7168..35039c4a7 100644 --- a/radio/src/gui/128x64/view_main.cpp +++ b/radio/src/gui/128x64/view_main.cpp @@ -660,7 +660,7 @@ void menuMainView(event_t event) } } #elif defined(PCBTARANIS) - uint8_t switches = min(NUM_SWITCHES, 6); + uint8_t switches = min(NUM_SWITCHES- NUM_FUNCTIONS_SWITCHES, 6); for (int i = 0; i < switches; ++i) { if (SWITCH_EXISTS(i)) { uint8_t x = 2 * FW - 2, y = 4 * FH + i * FH + 1; diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index 48bb47246..67de15c46 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -55,6 +55,7 @@ enum { ITEM_RADIO_HARDWARE_SB, ITEM_RADIO_HARDWARE_SC, ITEM_RADIO_HARDWARE_SD, +#if !defined(RADIO_TPRO) #if defined(HARDWARE_SWITCH_E) ITEM_RADIO_HARDWARE_SE, #endif @@ -73,6 +74,7 @@ enum { #if defined(HARDWARE_SWITCH_J) ITEM_RADIO_HARDWARE_SJ, #endif +#endif #if defined(HARDWARE_SWITCH_K) ITEM_RADIO_HARDWARE_SK, ITEM_RADIO_HARDWARE_SL, @@ -154,6 +156,8 @@ enum { #if defined(PCBX9E) #define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1 +#elif defined(RADIO_TPRO) + #define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1 #elif defined(RADIO_T12) #define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|HIDDEN_ROW, NAVIGATION_LINE_BY_LINE|HIDDEN_ROW #elif NUM_SWITCHES == 9 @@ -432,6 +436,7 @@ void menuRadioHardware(event_t event) case ITEM_RADIO_HARDWARE_SB: case ITEM_RADIO_HARDWARE_SC: case ITEM_RADIO_HARDWARE_SD: +#if !defined(RADIO_TPRO) #if defined(HARDWARE_SWITCH_E) case ITEM_RADIO_HARDWARE_SE: #endif @@ -450,6 +455,7 @@ void menuRadioHardware(event_t event) #if defined(HARDWARE_SWITCH_J) case ITEM_RADIO_HARDWARE_SJ: #endif +#endif #if defined(HARDWARE_SWITCH_K) case ITEM_RADIO_HARDWARE_SK: case ITEM_RADIO_HARDWARE_SL: diff --git a/radio/src/hal/adc_driver.cpp b/radio/src/hal/adc_driver.cpp index a7e5dc6c9..a02c3a78b 100644 --- a/radio/src/hal/adc_driver.cpp +++ b/radio/src/hal/adc_driver.cpp @@ -59,6 +59,8 @@ const etx_hal_adc_driver_t* etx_hal_adc_driver = nullptr; const int8_t adcDirection[NUM_ANALOGS] = {-1,1,-1,1, -1,-1, 1, 1}; #elif defined(RADIO_ZORRO) const int8_t adcDirection[NUM_ANALOGS] = {-1, 1, 1, -1, -1, 1, 1, 1}; +#elif defined(RADIO_TPRO) + const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1, 1, 1}; #elif defined(PCBX7) const int8_t adcDirection[NUM_ANALOGS] = {-1,1,-1,1, 1,1, 1, 1}; #elif defined(PCBX9LITE) diff --git a/radio/src/lua/CMakeLists.txt b/radio/src/lua/CMakeLists.txt index 8a75d379c..685778108 100644 --- a/radio/src/lua/CMakeLists.txt +++ b/radio/src/lua/CMakeLists.txt @@ -30,6 +30,7 @@ if(PYTHONINTERP_FOUND) add_lua_export_target(x12s ${LUA_INCLUDES} -DPCBHORUS -DPCBX12S) add_lua_export_target(t12 ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_T12) add_lua_export_target(tlite ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_TLITE) + add_lua_export_target(tpro ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_TPRO) add_lua_export_target(tx12 ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_TX12) add_lua_export_target(zorro ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_ZORRO) add_lua_export_target(t8 ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_T8) diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 8ac29f153..354cdd1c8 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -50,6 +50,8 @@ #include "lua/lua_exports_t12.inc" #elif defined(RADIO_TLITE) #include "lua/lua_exports_tlite.inc" +#elif defined(RADIO_TPRO) + #include "lua/lua_exports_tpro.inc" #elif defined(RADIO_TX12) #include "lua/lua_exports_tx12.inc" #elif defined(RADIO_ZORRO) diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index 92214f605..cdb90e6df 100644 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -348,6 +348,20 @@ getvalue_t getValue(mixsrc_t i) // TODO : find a better define #if defined(PCBFRSKY) || defined(PCBFLYSKY) +#if defined(FUNCTION_SWITCHES) + else if (i >= MIXSRC_FIRST_SWITCH && i <= MIXSRC_LAST_REGULAR_SWITCH) { + mixsrc_t sw = i - MIXSRC_FIRST_SWITCH; + if (SWITCH_EXISTS(sw)) { + return (switchState(3*sw) ? -1024 : (IS_CONFIG_3POS(sw) && switchState(3*sw+1) ? 0 : 1024)); + } + else { + return 0; + } + } + else if (i >= MIXSRC_FIRST_FS_SWITCH && i <= MIXSRC_LAST_SWITCH) { + return getFSLogicalState(i - MIXSRC_FIRST_SWITCH - NUM_REGULAR_SWITCHES) ? +1024 : -1024; + } +#else else if (i >= MIXSRC_FIRST_SWITCH && i <= MIXSRC_LAST_SWITCH) { mixsrc_t sw = i - MIXSRC_FIRST_SWITCH; if (SWITCH_EXISTS(sw)) { @@ -357,6 +371,7 @@ getvalue_t getValue(mixsrc_t i) return 0; } } +#endif #else else if (i == MIXSRC_3POS) { return (getSwitch(SW_ID0+1) ? -1024 : (getSwitch(SW_ID1+1) ? 0 : 1024)); diff --git a/radio/src/model_init.cpp b/radio/src/model_init.cpp index 492ccb190..ce3b3cf7b 100644 --- a/radio/src/model_init.cpp +++ b/radio/src/model_init.cpp @@ -114,6 +114,13 @@ void applyDefaultTemplate() setDefaultModelRegistrationID(); +#if defined(FUNCTION_SWITCHES) + g_model.functionSwitchConfig = DEFAULT_FS_CONFIG; + g_model.functionSwitchGroup = DEFAULT_FS_GROUPS; + g_model.functionSwitchStartConfig = DEFAULT_FS_STARTUP_CONFIG; + g_model.functionSwitchLogicalState = 0; +#endif + #if defined(COLORLCD) //TODO: not sure yet we need it here loadDefaultLayout(); diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 958e529a3..a8117e792 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -83,9 +83,18 @@ #if defined(PCBFRSKY) || defined(PCBNV14) #define SWITCH_CONFIG(x) (bfGet(g_eeGeneral.switchConfig, 2*(x), 2)) +#if defined(FUNCTION_SWITCHES) + #define FSWITCH_CONFIG(x) (bfGet(g_model.functionSwitchConfig, 2*(x), 2)) + #define FSWITCH_GROUP(x) (bfGet(g_model.functionSwitchGroup, 2*(x), 2)) + #define IS_SWITCH_FS(x) (x >= NUM_REGULAR_SWITCHES) + #define SWITCH_EXISTS(x) (IS_SWITCH_FS(x) ? true : (FSWITCH_CONFIG(x) != SWITCH_NONE)) + #define IS_CONFIG_3POS(x) (IS_SWITCH_FS(x) ? (FSWITCH_CONFIG(x - NUM_REGULAR_SWITCHES) == SWITCH_3POS) : (SWITCH_CONFIG(x) == SWITCH_3POS)) + #define IS_CONFIG_TOGGLE(x) (IS_SWITCH_FS(x) ? (FSWITCH_CONFIG(x - NUM_REGULAR_SWITCHES) == SWITCH_TOGGLE) : (SWITCH_CONFIG(x) == SWITCH_TOGGLE)) +#else #define SWITCH_EXISTS(x) (SWITCH_CONFIG(x) != SWITCH_NONE) #define IS_CONFIG_3POS(x) (SWITCH_CONFIG(x) == SWITCH_3POS) #define IS_CONFIG_TOGGLE(x) (SWITCH_CONFIG(x) == SWITCH_TOGGLE) +#endif #define SWITCH_WARNING_ALLOWED(x) (SWITCH_EXISTS(x) && !IS_CONFIG_TOGGLE(x)) #else #define IS_CONFIG_3POS(x) IS_3POS(x) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index f358af4a4..16895d2c6 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -171,6 +171,10 @@ void per10ms() readKeysAndTrims(); +#if defined(FUNCTION_SWITCHES) + evalFunctionSwitches(); +#endif + #if defined(ROTARY_ENCODER_NAVIGATION) if (IS_ROTARY_ENCODER_NAVIGATION_ENABLE()) { static rotenc_t rePreviousValue; @@ -372,7 +376,6 @@ uint16_t evalChkSum() return sum; } - bool isInputRecursive(int index) { ExpoData * line = expoAddress(0); @@ -1414,6 +1417,12 @@ void opentxStart(const uint8_t startOptions = OPENTX_START_DEFAULT_ARGS) ALERT(STR_TEST_WARNING, TR_TEST_NOTSAFE, AU_ERROR); #endif +#if defined(FUNCTION_SWITCHES) + if (!UNEXPECTED_SHUTDOWN()) { + setFSStartupPosition(); + } +#endif + #if defined(GUI) if (calibration_needed) { #if defined(LIBOPENUI) diff --git a/radio/src/opentx_constants.h b/radio/src/opentx_constants.h index 4b6559a65..bcb934df5 100644 --- a/radio/src/opentx_constants.h +++ b/radio/src/opentx_constants.h @@ -41,6 +41,12 @@ enum SliderConfig { SLIDER_WITH_DETENT, }; +enum fsStartPositionType { + FS_START_UP, + FS_START_DOWN, + FS_START_PREVIOUS +}; + enum CalibrationState { CALIB_START, CALIB_SET_MIDPOINT, diff --git a/radio/src/sdcard.h b/radio/src/sdcard.h index 2ac4f5dc6..43896b690 100644 --- a/radio/src/sdcard.h +++ b/radio/src/sdcard.h @@ -152,6 +152,8 @@ const char * getBasename(const char * path); #define OTX_FOURCC 0x3D78746F // otx for Jumper T12 #elif defined(RADIO_TLITE) #define OTX_FOURCC 0x4278746F // otx for Jumper TLite +#elif defined(RADIO_TPRO) + #define OTX_FOURCC 0x4678746F // otx for Jumper TPro #elif defined(RADIO_TX12) #define OTX_FOURCC 0x4178746F // otx for Radiomaster TX12 #elif defined(RADIO_ZORRO) diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index 53410cb2e..e88309434 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -445,7 +445,14 @@ void OpenTxSim::updateKeysAndSwitches(bool start) SWITCH_KEY(C, 2, 3); SWITCH_KEY(D, 3, 3); - #if defined(HARDWARE_SWITCH_G) && defined(HARDWARE_SWITCH_H) + #if defined(RADIO_TPRO) + SWITCH_KEY(1, 4, 2); + SWITCH_KEY(2, 5, 2); + SWITCH_KEY(3, 6, 2); + SWITCH_KEY(4, 7, 2); + SWITCH_KEY(5, 8, 2); + SWITCH_KEY(6, 9, 2); + #elif defined(HARDWARE_SWITCH_G) && defined(HARDWARE_SWITCH_H) SWITCH_KEY(E, 4, 3); SWITCH_KEY(F, 5, 2); SWITCH_KEY(G, 6, 3); diff --git a/radio/src/storage/conversions/CMakeLists.txt b/radio/src/storage/conversions/CMakeLists.txt index 601482530..75ec49ad2 100644 --- a/radio/src/storage/conversions/CMakeLists.txt +++ b/radio/src/storage/conversions/CMakeLists.txt @@ -1,8 +1,11 @@ set(STORAGE_CONVERSIONS 219) -if(PCB STREQUAL X7 AND PCBREV STREQUAL ZORRO) - set(STORAGE_CONVERSIONS 221) +if(PCB STREQUAL X7) + if(PCBREV STREQUAL ZORRO OR PCBREV STREQUAL TPRO) + set(STORAGE_CONVERSIONS 221) + endif() endif() +message("Storage conversion: ${STORAGE_CONVERSIONS}") if(STORAGE_CONVERSIONS) add_definitions(-DSTORAGE_CONVERSIONS=${STORAGE_CONVERSIONS}) diff --git a/radio/src/storage/conversions/conversions_219_220.cpp b/radio/src/storage/conversions/conversions_219_220.cpp index d65d528af..efbaaa7c7 100644 --- a/radio/src/storage/conversions/conversions_219_220.cpp +++ b/radio/src/storage/conversions/conversions_219_220.cpp @@ -35,6 +35,8 @@ #include #endif +#if STORAGE_CONVERSIONS < 220 + // // Summary of all changes between 219 & 220 // @@ -349,3 +351,5 @@ const char* convertRadioData_219_to_220() return nullptr; } #endif + +#endif diff --git a/radio/src/storage/conversions/conversions_220_221.cpp b/radio/src/storage/conversions/conversions_220_221.cpp index 634f8b960..7a1981c82 100644 --- a/radio/src/storage/conversions/conversions_220_221.cpp +++ b/radio/src/storage/conversions/conversions_220_221.cpp @@ -44,6 +44,8 @@ namespace yaml_conv_220 { const YamlNode* get_partialmodel_nodes(); }; +#if STORAGE_CONVERSIONS < 221 + #if defined(STORAGE_MODELSLIST) void patchFilenameToYaml(char* str); @@ -184,3 +186,5 @@ const char* convertRadioData_220_to_221() } #endif + +#endif diff --git a/radio/src/storage/conversions/yaml/dataconstants_220.h b/radio/src/storage/conversions/yaml/dataconstants_220.h index aefde174c..a520dd2d2 100644 --- a/radio/src/storage/conversions/yaml/dataconstants_220.h +++ b/radio/src/storage/conversions/yaml/dataconstants_220.h @@ -92,6 +92,8 @@ #if defined(PCBXLITES) || defined(PCBXLITE) #define STORAGE_NUM_SWITCHES 6 +#elif defined(RADIO_TPRO) +#define STORAGE_NUM_SWITCHES 10 #elif defined(RADIO_TLITE) || defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_TX12) || defined(RADIO_T8) || defined(PCBX7ACCESS) || defined(PCBX7) #define STORAGE_NUM_SWITCHES 8 #elif defined(PCBX9LITES) diff --git a/radio/src/storage/conversions/yaml/datastructs_220.h b/radio/src/storage/conversions/yaml/datastructs_220.h index 2e5392317..b99edaf6e 100644 --- a/radio/src/storage/conversions/yaml/datastructs_220.h +++ b/radio/src/storage/conversions/yaml/datastructs_220.h @@ -999,6 +999,9 @@ static inline void check_struct() #elif defined(PCBXLITE) CHKSIZE(RadioData, 859); CHKSIZE(ModelData, 6157); +#elif defined(RADIO_TPRO) + CHKSIZE(RadioData, 860); + CHKSIZE(ModelData, 6157); #elif defined(PCBX7) CHKSIZE(RadioData, 865); CHKSIZE(ModelData, 6157); diff --git a/radio/src/strhelpers.cpp b/radio/src/strhelpers.cpp index 291e109ae..885201f86 100644 --- a/radio/src/strhelpers.cpp +++ b/radio/src/strhelpers.cpp @@ -444,20 +444,20 @@ int getRawSwitchIdx(char sw) char getRawSwitchFromIdx(int idx) { -#if defined(PCBX7) && !defined(RADIO_TX12) && !defined(RADIO_ZORRO) +#if defined(PCBX7) && !defined(RADIO_TX12) && !defined(RADIO_ZORRO) && !defined(RADIO_TPRO) if (idx >= 5) return 'H' + idx - 5; else if (idx == 4) -#if defined(RADIO_T12) + #if defined(RADIO_T12) return 'G'; -#else + #else return 'F'; -#endif + #endif else return 'A' + idx; #else return 'A' + idx; -#endif +#endif } char *getSwitchName(char *dest, swsrc_t idx) @@ -467,6 +467,13 @@ char *getSwitchName(char *dest, swsrc_t idx) dest = strAppend(dest, g_eeGeneral.switchNames[swinfo.quot], LEN_SWITCH_NAME); } else { +#if defined(FUNCTIONS_SWITCHES) + if (swinfo.quot >= NUM_REGULAR_SWITCHES) { + *dest++ = 'W'; + *dest++ = '1' + swinfo.quot - 4; + return dest; + } +#endif *dest++ = 'S'; *dest++ = getRawSwitchFromIdx(swinfo.quot); } diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp index 5d77bb168..3d9ccad3f 100644 --- a/radio/src/switches.cpp +++ b/radio/src/switches.cpp @@ -70,6 +70,85 @@ uint8_t potsPos[NUM_XPOTS]; #define SWITCH_POSITION(sw) (switchesPos & ((MASK_CFN_TYPE)1<<(sw))) #define POT_POSITION(sw) ((potsPos[(sw)/XPOTS_MULTIPOS_COUNT] & 0x0f) == ((sw) % XPOTS_MULTIPOS_COUNT)) +#if defined(FUNCTION_SWITCHES) +// Non pushed : SWSRC_Sx0 = -1024 = Sx(up) = state 0 +// Pushed : SWSRC_Sx2 = +1024 = Sx(down) = state 1 + +uint8_t fsPreviousState = 0; + +void setFSStartupPosition() +{ + for (uint8_t i = 0; i < NUM_FUNCTIONS_SWITCHES; i++) { + uint8_t startPos = (g_model.functionSwitchStartConfig >> 2 * i) & 0x03; + switch(startPos) { + case FS_START_DOWN: + g_model.functionSwitchLogicalState &= ~(1 << i); // clear state + break; + + case FS_START_UP: + g_model.functionSwitchLogicalState |= 1 << i; + break; + + case FS_START_PREVIOUS: + default: + // Do nothing, use existing g_model.functionSwitchLogicalState value + break; + } + } +} + +uint8_t getFSLogicalState(uint8_t index) +{ + return (uint8_t )(bfSingleBitGet(g_model.functionSwitchLogicalState, index) >> (index)); +} + +uint8_t getFSPhysicalState(uint8_t index) +{ + return switchState(((index + NUM_REGULAR_SWITCHES) * 3) + 2) ? 1 : 0; +} + +uint8_t getFSPreviousPhysicalState(uint8_t index) +{ + return (uint8_t )(bfSingleBitGet(fsPreviousState, index) >> (index)); +} + +void evalFunctionSwitches() +{ + for (uint8_t i = 0; i < NUM_FUNCTIONS_SWITCHES; i++) { + if (FSWITCH_CONFIG(i) == SWITCH_NONE) { + fsLedOff(i); + continue; + } + + uint8_t physicalState = getFSPhysicalState(i); + if (physicalState != getFSPreviousPhysicalState(i)) { // FS was moved + if (FSWITCH_CONFIG(i) == SWITCH_2POS && physicalState == 1) { + g_model.functionSwitchLogicalState ^= 1 << i; // Toggle bit + } + else if (FSWITCH_CONFIG(i) == SWITCH_TOGGLE) { + g_model.functionSwitchLogicalState ^= (physicalState ^ g_model.functionSwitchLogicalState) & (1 << i); // Set bit to switch value + } + if (FSWITCH_GROUP(i) && physicalState == 1) { // switch is in a group, other in group need to be turned off + for (uint8_t j = 0; j < NUM_FUNCTIONS_SWITCHES; j++) { + if (i == j) + continue; + if (FSWITCH_GROUP(j) == FSWITCH_GROUP(i)) { + g_model.functionSwitchLogicalState &= ~(1 << j); // clear state + } + } + } + fsPreviousState ^= 1 << i; // Toggle state + storageDirty(EE_MODEL); + } + + if (getFSLogicalState(i)) + fsLedOn(i); + else + fsLedOff(i); + } +} +#endif + div_t switchInfo(int switchPosition) { return div(switchPosition-SWSRC_FIRST_SWITCH, 3); @@ -133,6 +212,11 @@ void getSwitchesPosition(bool startup) CHECK_2POS(SW_SA); CHECK_3POS(0, SW_SB); CHECK_3POS(1, SW_SC); +#elif defined(RADIO_TPRO) + CHECK_3POS(0, SW_SA); + CHECK_3POS(1, SW_SB); + CHECK_2POS(SW_SC); + CHECK_2POS(SW_SD); #else CHECK_3POS(0, SW_SA); CHECK_3POS(1, SW_SB); @@ -165,6 +249,13 @@ void getSwitchesPosition(bool startup) CHECK_2POS(SW_SD); CHECK_3POS(2, SW_SE); CHECK_3POS(3, SW_SF); +#elif defined(RADIO_TPRO) + CHECK_2POS(SW_SE); + CHECK_2POS(SW_SF); + CHECK_2POS(SW_SG); + CHECK_2POS(SW_SH); + CHECK_2POS(SW_SI); + CHECK_2POS(SW_SJ); #elif defined(PCBX7) CHECK_3POS(3, SW_SD); #if defined(RADIO_T12) @@ -456,8 +547,8 @@ bool getSwitch(swsrc_t swtch, uint8_t flags) result = latencyToggleSwitch; } #endif - else if (cs_idx <= SWSRC_LAST_SWITCH) { -#if defined(PCBFRSKY) + else if (cs_idx <= (SWSRC_LAST_SWITCH - 3 * NUM_FUNCTIONS_SWITCHES)) { +#if defined(PCBFRSKY) || defined(PCBFLYSKY) if (flags & GETSWITCH_MIDPOS_DELAY) result = SWITCH_POSITION(cs_idx-SWSRC_FIRST_SWITCH); else @@ -465,8 +556,14 @@ bool getSwitch(swsrc_t swtch, uint8_t flags) #else result = switchState(cs_idx-SWSRC_FIRST_SWITCH); #endif - } +#if defined(FUNCTION_SWITCHES) + else if (cs_idx <= SWSRC_LAST_SWITCH) { + div_t qr = div(cs_idx - 3 * NUM_FUNCTIONS_SWITCHES, 3); + auto value = getFSLogicalState(qr.quot + 1); + result = qr.rem == -2 ? 1 - value : value; + } +#endif #if NUM_XPOTS > 0 else if (cs_idx <= SWSRC_LAST_MULTIPOS_SWITCH) { result = POT_POSITION(cs_idx-SWSRC_FIRST_MULTIPOS_SWITCH); @@ -526,13 +623,14 @@ void evalLogicalSwitches(bool isCurrentFlightmode) } swarnstate_t switches_states = 0; +uint8_t fsswitches_states = 0; swsrc_t getMovedSwitch() { static tmr10ms_t s_move_last_time = 0; swsrc_t result = 0; // Switches - for (int i = 0; i < NUM_SWITCHES; i++) { + for (int i = 0; i < NUM_SWITCHES - NUM_FUNCTIONS_SWITCHES; i++) { if (SWITCH_EXISTS(i)) { swarnstate_t mask = ((swarnstate_t) 0x07 << (i * 3)); uint8_t prev = (switches_states & mask) >> (i * 3); @@ -544,6 +642,20 @@ swsrc_t getMovedSwitch() } } } + +#if defined(FUNCTION_SWITCHES) + for (int i = 0; i < NUM_FUNCTIONS_SWITCHES; i++) { + if (FSWITCH_CONFIG(i) != SWITCH_NONE) { + auto prev = (uint8_t )(bfSingleBitGet(fsswitches_states, i) >> (i)); + uint8_t next = getFSLogicalState(i); + if (prev != next) { + switches_states ^= (-next ^ switches_states) & (1 << i); + result = 2 + (3 * (i + NUM_REGULAR_SWITCHES)) + next; + } + } + } +#endif + // Multipos for (int i = 0; i < NUM_XPOTS; i++) { if (IS_POT_MULTIPOS(POT1 + i)) { diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index f9e1873f3..7450b124a 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -304,6 +304,10 @@ enum EnumSwitchesPositions #define STORAGE_NUM_SWITCHES_POSITIONS (STORAGE_NUM_SWITCHES * 3) +#if !defined(NUM_FUNCTIONS_SWITCHES) +#define NUM_FUNCTIONS_SWITCHES 0 +#endif + void keysInit(); uint32_t switchState(uint8_t index); uint32_t readKeys(); diff --git a/radio/src/targets/nv14/board.h b/radio/src/targets/nv14/board.h index c70100315..0677593b3 100644 --- a/radio/src/targets/nv14/board.h +++ b/radio/src/targets/nv14/board.h @@ -235,6 +235,10 @@ enum EnumSwitchesPositions #define STORAGE_NUM_SWITCHES_POSITIONS (STORAGE_NUM_SWITCHES * 3) +#if !defined(NUM_FUNCTIONS_SWITCHES) +#define NUM_FUNCTIONS_SWITCHES 0 +#endif + void monitorInit(); void keysInit(); uint8_t keyState(uint8_t index); diff --git a/radio/src/targets/sky9x/board.h b/radio/src/targets/sky9x/board.h index e12be5f6d..7ac83b00b 100644 --- a/radio/src/targets/sky9x/board.h +++ b/radio/src/targets/sky9x/board.h @@ -57,6 +57,10 @@ void rotaryEncoderEnd(); #define STORAGE_NUM_SWITCHES NUM_SWITCHES #define NUM_SWITCHES_POSITIONS 9 +#if !defined(NUM_FUNCTIONS_SWITCHES) +#define NUM_FUNCTIONS_SWITCHES 0 +#endif + enum EnumKeys { KEY_MENU, diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt index 15ff14c05..599d77188 100644 --- a/radio/src/targets/taranis/CMakeLists.txt +++ b/radio/src/targets/taranis/CMakeLists.txt @@ -138,6 +138,20 @@ elseif(PCB STREQUAL X7) add_definitions(-DRADIO_FAMILY_JUMPER_T12) add_definitions(-DEEPROM_VARIANT=0x4001) add_definitions(-DMANUFACTURER_JUMPER) + elseif(PCBREV STREQUAL TPRO) + set(DEFAULT_INTERNAL_MODULE MULTIMODULE CACHE STRING "Default internal module") + set(INTERNAL_MODULE_SERIAL YES) + set(FLAVOUR tpro) + set(NAVIGATION_TYPE x7) + set(CPU_TYPE STM32F2) + set(ROTARY_ENCODER YES) + set(CPU_TYPE_FULL STM32F205xE) # for size report + set(LINKER_SCRIPT targets/taranis/stm32f2_flash.ld) + set(LUA_EXPORT lua_export_tpro) + add_definitions(-DFUNCTION_SWITCHES) + add_definitions(-DRADIO_TPRO) + add_definitions(-DEEPROM_VARIANT=0x4005) + add_definitions(-DMANUFACTURER_JUMPER) elseif(PCBREV STREQUAL TLITE) set(DEFAULT_INTERNAL_MODULE MULTIMODULE CACHE STRING "Default internal module") set(INTERNAL_MODULE_SERIAL YES) diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 01df37927..2b7c918f8 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -38,7 +38,7 @@ void rotaryEncoderInit(); void rotaryEncoderCheck(); #endif -#if defined(RADIO_ZORRO) +#if defined(RADIO_ZORRO) || defined(RADIO_TPRO) #define ROTARY_ENCODER_INVERT #endif @@ -330,7 +330,16 @@ enum EnumSwitches SW_SE, SW_SF, SW_SG, - SW_SH + SW_SH, + SW_SI, + SW_SJ, + SW_SK, + SW_SL, + SW_SM, + SW_SO, + SW_SP, + SW_SQ, + SW_SR, }; #if defined(RADIO_TX12) #define IS_3POS(x) ((x) != SW_SA && (x) != SW_SD) @@ -353,22 +362,22 @@ enum EnumSwitchesPositions SW_SD0, SW_SD1, SW_SD2, -#if defined(PCBX9) || defined(PCBXLITES) || defined(PCBX9LITES) || defined(RADIO_TX12) || defined(RADIO_ZORRO) +#if defined(HARDWARE_SWITCH_E) SW_SE0, SW_SE1, SW_SE2, #endif -#if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E) || (defined(PCBX7) && !defined(RADIO_T12)) || defined(PCBXLITES) || defined(PCBX9LITES) || defined(RADIO_T8) || defined(RADIO_ZORRO) +#if defined(HARDWARE_SWITCH_F) SW_SF0, SW_SF1, SW_SF2, #endif -#if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E) || defined(PCBX9LITES) || defined(RADIO_T12) || defined(RADIO_ZORRO) +#if defined(HARDWARE_SWITCH_G) SW_SG0, SW_SG1, SW_SG2, #endif -#if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E) || (defined(PCBX7) && !defined(RADIO_TX12)) || defined(RADIO_T8) || defined(RADIO_ZORRO) +#if defined(HARDWARE_SWITCH_H) SW_SH0, SW_SH1, SW_SH2, @@ -440,6 +449,16 @@ enum EnumSwitchesPositions #define STORAGE_NUM_SWITCHES 8 #define DEFAULT_SWITCH_CONFIG (SWITCH_2POS << 6) + (SWITCH_2POS << 4) + (SWITCH_3POS << 2) + (SWITCH_3POS << 0); #define DEFAULT_POTS_CONFIG (0) +#elif defined(RADIO_TPRO) + #define NUM_SWITCHES 10 + #define NUM_FUNCTIONS_SWITCHES 6 + #define NUM_REGULAR_SWITCHES (NUM_SWITCHES - NUM_FUNCTIONS_SWITCHES) + #define STORAGE_NUM_SWITCHES 10 + #define DEFAULT_SWITCH_CONFIG (SWITCH_TOGGLE << 6) + (SWITCH_TOGGLE << 4) + (SWITCH_3POS << 2) + (SWITCH_3POS << 0); + #define DEFAULT_FS_CONFIG (SWITCH_2POS << 10) + (SWITCH_2POS << 8) + (SWITCH_2POS << 6) + (SWITCH_2POS << 4) + (SWITCH_2POS << 2) + (SWITCH_2POS << 0) + #define DEFAULT_FS_GROUPS (1 << 10) + (1 << 8) + (1 << 6) + (1 << 4) + (1 << 2) + (1 << 0) // Set all FS to group 1 to act like a 6pos + #define DEFAULT_FS_STARTUP_CONFIG ((FS_START_PREVIOUS << 10) + (FS_START_PREVIOUS << 8) + (FS_START_PREVIOUS << 6) + (FS_START_PREVIOUS << 4) + (FS_START_PREVIOUS << 2) + (FS_START_PREVIOUS << 0)) // keep last state by default + #define DEFAULT_POTS_CONFIG (POT_WITHOUT_DETENT << 0) + (POT_WITH_DETENT << 2); // S1 = pot without detent, S2 = pot with detent #elif defined(RADIO_FAMILY_JUMPER_T12) #define NUM_SWITCHES 8 #define STORAGE_NUM_SWITCHES NUM_SWITCHES @@ -500,17 +519,24 @@ enum EnumSwitchesPositions #define DEFAULT_SLIDERS_CONFIG (SLIDER_WITH_DETENT << 1) + (SLIDER_WITH_DETENT << 0) #endif +#if !defined(NUM_FUNCTIONS_SWITCHES) + #define NUM_FUNCTIONS_SWITCHES 0 +#endif + #define STORAGE_NUM_SWITCHES_POSITIONS (STORAGE_NUM_SWITCHES * 3) void keysInit(); uint32_t switchState(uint8_t index); -#if defined(RADIO_ZORRO) -static const uint8_t switchReOrder[] = {1, 0, 4, 2, 3, 5}; -#else -static const uint8_t switchReOrder[] = {0, 1, 2, 3, 4, 5}; -#endif uint32_t readKeys(); uint32_t readTrims(); +#if defined(FUNCTION_SWITCHES) +extern uint8_t fsPreviousState; +void evalFunctionSwitches(); +void setFSStartupPosition(); +uint8_t getFSLogicalState(uint8_t index); +uint8_t getFSPhysicalState(uint8_t index); +#endif + #define TRIMS_PRESSED() (readTrims()) #define KEYS_PRESSED() (readKeys()) @@ -926,6 +952,10 @@ void ledOff(); void ledRed(); void ledGreen(); void ledBlue(); +#if defined(FUNCTION_SWITCHES) +void fsLedOff(uint8_t); +void fsLedOn(uint8_t); +#endif // LCD driver #if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E) @@ -942,7 +972,7 @@ void ledBlue(); #define IS_LCD_RESET_NEEDED() true #define LCD_CONTRAST_MIN 10 #define LCD_CONTRAST_MAX 30 -#if defined(RADIO_TX12) || defined(RADIO_FAMILY_JUMPER_T12) +#if defined(RADIO_TX12) || defined(RADIO_TPRO) || defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_TPRO) #define LCD_CONTRAST_DEFAULT 25 #else #define LCD_CONTRAST_DEFAULT 15 diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 4db84712d..ea2bec79b 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -53,7 +53,7 @@ #define KEYS_GPIO_PIN_LEFT GPIO_Pin_12 // PE.12 #define KEYS_GPIO_REG_RIGHT GPIOE->IDR #define KEYS_GPIO_PIN_RIGHT GPIO_Pin_13 // PE.13 -#elif defined(RADIO_FAMILY_JUMPER_T12) +#elif defined(RADIO_FAMILY_JUMPER_T12) && !defined(RADIO_TPRO) #define KEYS_GPIO_REG_EXIT GPIOD->IDR #define KEYS_GPIO_PIN_EXIT GPIO_Pin_2 // PD.02 #define KEYS_GPIO_REG_ENTER GPIOE->IDR @@ -174,7 +174,7 @@ #define ROTARY_ENCODER_EXTI_PortSource EXTI_PortSourceGPIOE #define ROTARY_ENCODER_EXTI_PinSource1 EXTI_PinSource10 #define ROTARY_ENCODER_EXTI_PinSource2 EXTI_PinSource11 -#elif defined(RADIO_X7) || defined(RADIO_X7ACCESS) +#elif defined(RADIO_X7) || defined(RADIO_X7ACCESS) || defined(RADIO_TPRO) #define ROTARY_ENCODER_NAVIGATION #define ROTARY_ENCODER_GPIO GPIOE #define ROTARY_ENCODER_GPIO_PIN_A GPIO_Pin_9 // PE.09 @@ -368,6 +368,13 @@ #define HARDWARE_SWITCH_A #define SWITCHES_GPIO_REG_A GPIOE->IDR #define SWITCHES_GPIO_PIN_A GPIO_Pin_14 // PE.14 +#elif defined(RADIO_TPRO) + #define STORAGE_SWITCH_A + #define HARDWARE_SWITCH_A + #define SWITCHES_GPIO_REG_A_L GPIOE->IDR + #define SWITCHES_GPIO_PIN_A_L GPIO_Pin_13 // PE.13 + #define SWITCHES_GPIO_REG_A_H GPIOE->IDR + #define SWITCHES_GPIO_PIN_A_H GPIO_Pin_7 // PE.07 #elif defined(PCBX7) #define STORAGE_SWITCH_A #define HARDWARE_SWITCH_A @@ -405,7 +412,7 @@ #define SWITCHES_GPIO_PIN_B_L GPIO_Pin_7 // PE.07 #define SWITCHES_GPIO_REG_B_H GPIOE->IDR #define SWITCHES_GPIO_PIN_B_H GPIO_Pin_13 // PE.13 -#elif defined(RADIO_TLITE) +#elif defined(RADIO_TLITE) || defined(RADIO_TPRO) #define STORAGE_SWITCH_B #define HARDWARE_SWITCH_B #define SWITCHES_GPIO_REG_B_L GPIOE->IDR @@ -470,7 +477,7 @@ #define SWITCHES_GPIO_PIN_C_L GPIO_Pin_2 // PE.02 #define SWITCHES_GPIO_REG_C_H GPIOE->IDR #define SWITCHES_GPIO_PIN_C_H GPIO_Pin_1 // PE.01 -#elif defined(RADIO_TLITE) +#elif defined(RADIO_TLITE) || defined(RADIO_TPRO) #define STORAGE_SWITCH_C #define HARDWARE_SWITCH_C #define SWITCHES_GPIO_REG_C GPIOE->IDR @@ -527,7 +534,7 @@ #define HARDWARE_SWITCH_D #define SWITCHES_GPIO_REG_D GPIOE->IDR #define SWITCHES_GPIO_PIN_D GPIO_Pin_8 // PE.08 -#elif defined(RADIO_TLITE) +#elif defined(RADIO_TLITE) || defined(RADIO_TPRO) #define STORAGE_SWITCH_D #define HARDWARE_SWITCH_D #define SWITCHES_GPIO_REG_D GPIOD->IDR @@ -585,6 +592,12 @@ #define SWITCHES_GPIO_PIN_E_H GPIO_Pin_13 // PE.13 #define SWITCHES_GPIO_REG_E_L GPIOE->IDR #define SWITCHES_GPIO_PIN_E_L GPIO_Pin_7 // PE.07 +#elif defined(RADIO_TPRO) + // SW1 + #define STORAGE_SWITCH_E + #define HARDWARE_SWITCH_E + #define SWITCHES_GPIO_REG_E GPIOG->IDR + #define SWITCHES_GPIO_PIN_E GPIO_Pin_7 // PG.07 #elif defined(PCBX7) // no SWE #else @@ -628,7 +641,13 @@ #define SWITCHES_GPIO_PIN_F_L GPIO_Pin_1 // PE.01 #define SWITCHES_GPIO_REG_F_H GPIOE->IDR #define SWITCHES_GPIO_PIN_F_H GPIO_Pin_2 // PE.02 -#elif defined(RADIO_T8) || defined(RADIO_TLITE) +#elif defined(RADIO_TPRO) + // SW2 + #define STORAGE_SWITCH_F + #define HARDWARE_SWITCH_F + #define SWITCHES_GPIO_REG_F GPIOG->IDR + #define SWITCHES_GPIO_PIN_F GPIO_Pin_6 // PG.06 +#elif defined(RADIO_T8) || defined(RADIO_TLITE) || defined(RADIO_TPRO) // no SWF #define STORAGE_SWITCH_F #elif defined(RADIO_T12) @@ -662,6 +681,12 @@ #define HARDWARE_SWITCH_G #define SWITCHES_GPIO_REG_G GPIOE->IDR #define SWITCHES_GPIO_PIN_G GPIO_Pin_14 // PE.14 +#elif defined(RADIO_TPRO) + // SW3 + #define STORAGE_SWITCH_G + #define HARDWARE_SWITCH_G + #define SWITCHES_GPIO_REG_G GPIOG->IDR + #define SWITCHES_GPIO_PIN_G GPIO_Pin_5 // PG.05 #elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_T8) // no SWG #else @@ -689,7 +714,13 @@ #define STORAGE_SWITCH_H // no SWH #elif defined(RADIO_TX12) -#elif defined(RADIO_TLITE) +#elif defined(RADIO_TPRO) + // SW4 + #define STORAGE_SWITCH_H + #define HARDWARE_SWITCH_H + #define SWITCHES_GPIO_REG_H GPIOG->IDR + #define SWITCHES_GPIO_PIN_H GPIO_Pin_4 // PG.04 +#elif defined(RADIO_TLITE) || defined(RADIO_TPRO) // no SWH #define STORAGE_SWITCH_H #elif defined(PCBX7) @@ -740,6 +771,17 @@ #define STORAGE_SWITCH_J #elif defined(RADIO_ZORRO) // No I/J +#elif defined(RADIO_TPRO) + // SW5 + #define STORAGE_SWITCH_I + #define HARDWARE_SWITCH_I + #define SWITCHES_GPIO_REG_I GPIOG->IDR + #define SWITCHES_GPIO_PIN_I GPIO_Pin_3 // PG.03 + // SW6 + #define STORAGE_SWITCH_J + #define HARDWARE_SWITCH_J + #define SWITCHES_GPIO_REG_J GPIOG->IDR + #define SWITCHES_GPIO_PIN_J GPIO_Pin_2 // PG.02 #elif defined(PCBX7) #define STORAGE_SWITCH_I #define HARDWARE_SWITCH_I @@ -849,6 +891,13 @@ #define KEYS_GPIOB_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5) #define KEYS_GPIOC_PINS (GPIO_Pin_4 | GPIO_Pin_5) #define KEYS_GPIOE_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14) +#elif defined(RADIO_TPRO) + #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOG) + #define KEYS_GPIOA_PINS (GPIO_Pin_5) + #define KEYS_GPIOC_PINS (GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3) + #define KEYS_GPIOD_PINS (GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15) + #define KEYS_GPIOE_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15) + #define KEYS_GPIOG_PINS (GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7) #elif defined(RADIO_FAMILY_JUMPER_T12) #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE) #define KEYS_GPIOA_PINS GPIO_Pin_5 @@ -1067,6 +1116,30 @@ #define ADC_GPIOC_PINS ADC_GPIO_PIN_BATT #define ADC_CHANNEL_BATT ADC_Channel_10 #define ADC_VREF_PREC2 330 +#elif defined(RADIO_TPRO) + #define HARDWARE_POT1 + #define HARDWARE_POT2 + #define ADC_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA2) + #define ADC_RCC_APB1Periph 0 + #define ADC_RCC_APB2Periph RCC_APB2Periph_ADC1 + #define ADC_GPIO_PIN_STICK_RV GPIO_Pin_0 // PA.00 + #define ADC_GPIO_PIN_STICK_RH GPIO_Pin_1 // PA.01 + #define ADC_GPIO_PIN_STICK_LV GPIO_Pin_2 // PA.02 + #define ADC_GPIO_PIN_STICK_LH GPIO_Pin_3 // PA.03 + #define ADC_CHANNEL_STICK_RV ADC_Channel_0 // ADC1_IN0 + #define ADC_CHANNEL_STICK_RH ADC_Channel_1 // ADC1_IN1 + #define ADC_CHANNEL_STICK_LV ADC_Channel_2 // ADC1_IN2 + #define ADC_CHANNEL_STICK_LH ADC_Channel_3 // ADC1_IN3 + #define ADC_GPIO_PIN_POT1 GPIO_Pin_0 // PB.00 + #define ADC_GPIO_PIN_POT2 GPIO_Pin_6 // PA.06 + #define ADC_GPIO_PIN_BATT GPIO_Pin_0 // PC.00 + #define ADC_GPIOA_PINS (ADC_GPIO_PIN_STICK_RV | ADC_GPIO_PIN_STICK_RH | ADC_GPIO_PIN_STICK_LH | ADC_GPIO_PIN_STICK_LV | ADC_GPIO_PIN_POT2) + #define ADC_GPIOB_PINS ADC_GPIO_PIN_POT1 + #define ADC_GPIOC_PINS ADC_GPIO_PIN_BATT + #define ADC_CHANNEL_POT1 ADC_Channel_6 + #define ADC_CHANNEL_POT2 ADC_Channel_8 + #define ADC_CHANNEL_BATT ADC_Channel_10 + #define ADC_VREF_PREC2 330 #elif defined(PCBX7) #define HARDWARE_POT1 #define HARDWARE_POT2 @@ -1244,6 +1317,19 @@ #define LED_BLUE_GPIO_PIN GPIO_Pin_6 // PE.06 #endif +#if defined(FUNCTION_SWITCHES) + #define FS_RCC_AHB1Periph RCC_AHB1Periph_GPIOF + #define GPIO_FSLED_GPIO_ON GPIO_SetBits + #define GPIO_FSLED_GPIO_OFF GPIO_ResetBits + #define FSLED_GPIO GPIOF + #define FSLED_GPIO_PIN_1 GPIO_Pin_5 + #define FSLED_GPIO_PIN_2 GPIO_Pin_4 + #define FSLED_GPIO_PIN_3 GPIO_Pin_3 + #define FSLED_GPIO_PIN_4 GPIO_Pin_2 + #define FSLED_GPIO_PIN_5 GPIO_Pin_1 + #define FSLED_GPIO_PIN_6 GPIO_Pin_0 +#endif + // Internal Module #if defined(PCBXLITE) #define EXTERNAL_ANTENNA @@ -1362,7 +1448,7 @@ #define INTMODULE_DMA_STREAM_IRQHandler DMA2_Stream5_IRQHandler #define INTMODULE_DMA_FLAG_TC DMA_IT_TCIF5 #define INTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2) -#elif (defined(RADIO_FAMILY_JUMPER_T12) && defined(HARDWARE_INTERNAL_MODULE)) || defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_T8) +#elif (defined(RADIO_FAMILY_JUMPER_T12) && defined(HARDWARE_INTERNAL_MODULE)) || defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_T8) || defined(RADIO_TPRO) #define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA1) #define INTMODULE_RCC_APB1Periph (RCC_APB1Periph_USART3 | RCC_APB1Periph_TIM2) #define INTMODULE_RCC_APB2Periph 0 @@ -1612,7 +1698,7 @@ #define TELEMETRY_EXTI_IRQn EXTI9_5_IRQn #define TELEMETRY_EXTI_TRIGGER EXTI_Trigger_Rising -#if defined(RADIO_X7) || defined(RADIO_X7ACCESS) || defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_T8) +#if defined(RADIO_X7) || defined(RADIO_X7ACCESS) || defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_T8) || defined(RADIO_TPRO) #define TELEMETRY_EXTI_REUSE_INTERRUPT_ROTARY_ENCODER #elif defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_X9DP2019) #define TELEMETRY_EXTI_IRQHandler EXTI9_5_IRQHandler @@ -1724,7 +1810,7 @@ #define INTMODULE_HEARTBEAT_EXTI_IRQHandler EXTI1_IRQHandler #elif defined(RADIO_ZORRO) #define INTMODULE_HEARTBEAT_RCC_AHB1Periph 0 -#elif defined(RADIO_X7) || defined(RADIO_TX12) +#elif defined(RADIO_X7) || defined(RADIO_TX12) || defined(RADIO_TPRO) #define INTMODULE_HEARTBEAT #define INTMODULE_HEARTBEAT_REUSE_INTERRUPT_ROTARY_ENCODER #define INTMODULE_HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOC @@ -1912,7 +1998,7 @@ #define KEYS_BACKLIGHT_RCC_AHB1Periph 0 // LCD driver -#if defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_T8) +#if defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_T8) || defined(RADIO_TPRO) #define LCD_VERTICAL_INVERT #endif #if defined(PCBX9E) @@ -2116,12 +2202,12 @@ #define AUDIO_SPEAKER_ENABLE_GPIO_PIN GPIO_Pin_14 // PD.14 #define HEADPHONE_TRAINER_SWITCH_GPIO GPIOD #define HEADPHONE_TRAINER_SWITCH_GPIO_PIN GPIO_Pin_9 // PD.09 -#elif defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_T8) || defined(RADIO_TLITE) +#elif defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_T8) || defined(RADIO_TLITE) || defined(RADIO_TPRO) #define AUDIO_RCC_AHB1Periph (RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_DMA1) #define AUDIO_MUTE_GPIO GPIOE #define AUDIO_MUTE_GPIO_PIN GPIO_Pin_12 // PE.12 #define AUDIO_MUTE_DELAY 500 // ms -#if defined(RADIO_TLITE) +#if defined(RADIO_TLITE) || defined(RADIO_TPRO) #define AUDIO_UNMUTE_DELAY 250 // ms #else #define AUDIO_UNMUTE_DELAY 150 // ms diff --git a/radio/src/targets/taranis/keys_driver.cpp b/radio/src/targets/taranis/keys_driver.cpp index 3dc4260eb..1d5d3fccf 100644 --- a/radio/src/targets/taranis/keys_driver.cpp +++ b/radio/src/targets/taranis/keys_driver.cpp @@ -210,7 +210,7 @@ uint32_t switchState(uint8_t index) ADD_2POS_CASE(A); ADD_3POS_CASE(B, 1); ADD_3POS_CASE(C, 2); -#elif defined(RADIO_TLITE) +#elif defined(RADIO_TLITE) || defined(RADIO_TPRO) ADD_3POS_CASE(A, 0); ADD_3POS_CASE(B, 1); ADD_2POS_CASE(C); @@ -256,6 +256,13 @@ uint32_t switchState(uint8_t index) ADD_2POS_CASE(D); #elif defined(RADIO_TLITE) // Only 4 switches +#elif defined(RADIO_TPRO) + ADD_2POS_CASE(E); + ADD_2POS_CASE(F); + ADD_2POS_CASE(G); + ADD_2POS_CASE(H); + ADD_2POS_CASE(I); + ADD_2POS_CASE(J); #elif defined(PCBX7) ADD_3POS_CASE(D, 3); #if defined(RADIO_T12) diff --git a/radio/src/targets/taranis/lcd_driver_spi.cpp b/radio/src/targets/taranis/lcd_driver_spi.cpp index 53ac9ac25..e3f9069c8 100644 --- a/radio/src/targets/taranis/lcd_driver_spi.cpp +++ b/radio/src/targets/taranis/lcd_driver_spi.cpp @@ -21,7 +21,7 @@ #include "opentx.h" -#if defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_T8) +#if defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_T8) || defined(RADIO_TPRO) #define LCD_CONTRAST_OFFSET -10 #else #define LCD_CONTRAST_OFFSET 160 diff --git a/radio/src/targets/taranis/led_driver.cpp b/radio/src/targets/taranis/led_driver.cpp index 04033c655..0b6824cf0 100644 --- a/radio/src/targets/taranis/led_driver.cpp +++ b/radio/src/targets/taranis/led_driver.cpp @@ -43,8 +43,32 @@ void ledInit() GPIO_InitStructure.GPIO_Pin = LED_BLUE_GPIO_PIN; GPIO_Init(LED_BLUE_GPIO, &GPIO_InitStructure); #endif + +#if defined(FUNCTION_SWITCHES) + RCC_AHB1PeriphClockCmd(FS_RCC_AHB1Periph, ENABLE); + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Pin = FSLED_GPIO_PIN_1 | FSLED_GPIO_PIN_2 | FSLED_GPIO_PIN_3 | FSLED_GPIO_PIN_4 | FSLED_GPIO_PIN_5 | FSLED_GPIO_PIN_6; + GPIO_Init(FSLED_GPIO, &GPIO_InitStructure); +#endif } +#if defined(FUNCTION_SWITCHES) +constexpr uint32_t fsLeds[] = {FSLED_GPIO_PIN_1, FSLED_GPIO_PIN_2, FSLED_GPIO_PIN_3, FSLED_GPIO_PIN_4, FSLED_GPIO_PIN_5, FSLED_GPIO_PIN_6}; + +void fsLedOff(uint8_t index) +{ + GPIO_FSLED_GPIO_OFF(FSLED_GPIO, fsLeds[index]); +} + +void fsLedOn(uint8_t index) +{ + GPIO_FSLED_GPIO_ON(FSLED_GPIO, fsLeds[index]); +} +#endif + void ledOff() { #if defined(LED_RED_GPIO) diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index 418d4b639..d54529847 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -94,6 +94,7 @@ ISTR(CRSF_BAUDRATE); ISTR(PPM_POL); ISTR(SBUS_INVERSION_VALUES); ISTR(SPORT_MODES); +ISTR(FSGROUPS); #if defined(PCBSKY9X) && defined(REVX) ISTR(VOUTPUT_TYPE); diff --git a/radio/src/translations.h b/radio/src/translations.h index f1c16e9a2..e37110dbb 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -178,6 +178,7 @@ extern const char STR_MULTI_POWER[]; extern const char STR_MULTI_TELEMETRY_MODE[]; extern const char STR_MULTI_WBUS_MODE[]; extern const char STR_SPORT_MODES[]; +extern const char STR_FSGROUPS[]; extern const char STR_AFHDS3_ONE_TO_ONE_TELEMETRY[]; extern const char STR_AFHDS3_ONE_TO_MANY[]; diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h index fca9c7ecd..2d3936df5 100644 --- a/radio/src/translations/untranslated.h +++ b/radio/src/translations/untranslated.h @@ -40,9 +40,20 @@ #elif defined(PCBXLITE) #define TR_POTS_VSRCRAW STR_CHAR_POT"S1\0" STR_CHAR_POT"S2\0" #define TR_SW_VSRCRAW STR_CHAR_SWITCH"SA\0" STR_CHAR_SWITCH"SB\0" STR_CHAR_SWITCH"SC\0" STR_CHAR_SWITCH"SD\0" STR_CHAR_SWITCH"SE\0" STR_CHAR_SWITCH"SF\0" -#elif defined(RADIO_FAMILY_JUMPER_T12) +#elif defined(RADIO_TPRO) #define TR_POTS_VSRCRAW STR_CHAR_POT"S1\0" STR_CHAR_POT"S2\0" - #define TR_SW_VSRCRAW STR_CHAR_SWITCH"SA\0" STR_CHAR_SWITCH"SB\0" STR_CHAR_SWITCH"SC\0" STR_CHAR_SWITCH"SD\0" STR_CHAR_SWITCH"SG\0" STR_CHAR_SWITCH"SH\0" STR_CHAR_SWITCH"SI\0" STR_CHAR_SWITCH"SJ\0" +#define TR_SW_VSRCRAW \ + STR_CHAR_SWITCH \ + "SA\0" STR_CHAR_SWITCH "SB\0" STR_CHAR_SWITCH "SC\0" STR_CHAR_SWITCH \ + "SD\0" STR_CHAR_SWITCH "SW1" STR_CHAR_SWITCH "SW2" STR_CHAR_SWITCH \ + "SW3" STR_CHAR_SWITCH "SW4" STR_CHAR_SWITCH "SW5" STR_CHAR_SWITCH "SW6" +#elif defined(RADIO_FAMILY_JUMPER_T12) +#define TR_POTS_VSRCRAW STR_CHAR_POT "S1\0" STR_CHAR_POT "S2\0" +#define TR_SW_VSRCRAW \ + STR_CHAR_SWITCH "SA\0" STR_CHAR_SWITCH "SB\0" STR_CHAR_SWITCH \ + "SC\0" STR_CHAR_SWITCH "SD\0" STR_CHAR_SWITCH \ + "SG\0" STR_CHAR_SWITCH "SH\0" STR_CHAR_SWITCH \ + "SI\0" STR_CHAR_SWITCH "SJ\0" #elif defined(RADIO_TX12) #define TR_POTS_VSRCRAW STR_CHAR_POT "S1\0" STR_CHAR_POT "S2\0" #define TR_SW_VSRCRAW STR_CHAR_SWITCH "SA\0" STR_CHAR_SWITCH "SB\0" STR_CHAR_SWITCH "SC\0" STR_CHAR_SWITCH "SD\0" STR_CHAR_SWITCH "SE\0" STR_CHAR_SWITCH "SF\0" STR_CHAR_SWITCH "SI\0" STR_CHAR_SWITCH "SJ\0" @@ -372,3 +383,7 @@ #define TR_EDIT_THEME "EDIT THEME" #define TR_DETAILS "Details" #define TR_THEME_EDITOR "THEMES" + +#define LEN_FSGROUPS "\001" +#define TR_FSGROUPS "-""1""2""3" + diff --git a/tools/build-jumper.py b/tools/build-jumper.py index cfce0920c..8e7d9e171 100755 --- a/tools/build-jumper.py +++ b/tools/build-jumper.py @@ -14,6 +14,11 @@ boards = { "PCBREV": "TLITE", "DEFAULT_MODE": "2", }, + "TPRO": { + "PCB": "X7", + "PCBREV": "TPRO", + "DEFAULT_MODE": "2", + }, "T12": { "PCB": "X7", "PCBREV": "T12",