diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index d67d27b8e4b..b3d32a569c0 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -49,6 +49,7 @@ jobs: - pl18 - pl18ev - t12 + - t15 - t16 - t18 - t8 @@ -97,7 +98,7 @@ jobs: - nv14;el18 - pl18;pl18ev - t12 - - t16;t18 + - t15;t16;t18 - t8;zorro;pocket;mt12;commando8 - tlite;tpro;tprov2;lr3pro - t20;t20v2;t14 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index ce10f1135f0..e9b3ed90974 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -19,7 +19,7 @@ jobs: - nv14;el18 - pl18;pl18ev - t12 - - t16;t18 + - t15;t16;t18 - t8;zorro;pocket;mt12;commando8 - tlite;tpro;tprov2;lr3pro - t20;t20v2;t14 diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt index 2b720dd7589..f41b0873baf 100644 --- a/companion/src/CMakeLists.txt +++ b/companion/src/CMakeLists.txt @@ -336,6 +336,8 @@ elseif(PCB STREQUAL X10 AND PCBREV STREQUAL TX16S) set(FLAVOUR tx16s) elseif(PCB STREQUAL X7 AND PCBREV STREQUAL T14) set(FLAVOUR t14) +elseif(PCB STREQUAL X10 AND PCBREV STREQUAL T15) + set(FLAVOUR t15) elseif(PCB STREQUAL X10 AND PCBREV STREQUAL T16) set(FLAVOUR t16) elseif(PCB STREQUAL X10 AND PCBREV STREQUAL T18) diff --git a/companion/src/companion.qrc b/companion/src/companion.qrc index fde60acfd9e..6c4d972a288 100644 --- a/companion/src/companion.qrc +++ b/companion/src/companion.qrc @@ -261,6 +261,13 @@ images/simulator/JumperT14/left.png images/simulator/JumperT14/right.png images/simulator/JumperT14/top.png + images/simulator/JumperT15/left.png + images/simulator/JumperT15/right.png + images/simulator/JumperT15/top.png + images/simulator/JumperT15/bottom.png + images/simulator/JumperT15/model.png + images/simulator/JumperT15/exit.png + images/simulator/JumperT15/page.png images/simulator/JumperT16/left.png images/simulator/JumperT16/right.png images/simulator/JumperT16/top.png diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp index 93db2e4a8a5..0bfde994f8a 100644 --- a/companion/src/firmwares/boards.cpp +++ b/companion/src/firmwares/boards.cpp @@ -202,6 +202,7 @@ int Boards::getEEpromSize(Board::Type board) case BOARD_HORUS_X12S: case BOARD_X10: case BOARD_X10_EXPRESS: + case BOARD_JUMPER_T15: case BOARD_JUMPER_T16: case BOARD_JUMPER_T18: case BOARD_RADIOMASTER_TX16S: @@ -252,6 +253,7 @@ int Boards::getFlashSize(Type board) case BOARD_HORUS_X12S: case BOARD_X10: case BOARD_X10_EXPRESS: + case BOARD_JUMPER_T15: case BOARD_JUMPER_T16: case BOARD_JUMPER_T18: case BOARD_RADIOMASTER_TX16S: @@ -532,6 +534,8 @@ QString Boards::getBoardName(Board::Type board) return "Jumper T-Pro V2"; case BOARD_JUMPER_T14: return "Jumper T14"; + case BOARD_JUMPER_T15: + return "Jumper T15"; case BOARD_JUMPER_T16: return "Jumper T16"; case BOARD_JUMPER_T18: @@ -668,6 +672,7 @@ int Boards::getDefaultInternalModules(Board::Type board) case BOARD_RADIOMASTER_TX12_MK2: case BOARD_IFLIGHT_COMMANDO8: case BOARD_JUMPER_T14: + case BOARD_JUMPER_T15: case BOARD_JUMPER_T20: case BOARD_JUMPER_T20V2: return (int)MODULE_TYPE_CROSSFIRE; diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index 5396526f008..6859053f5f1 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -62,6 +62,7 @@ namespace Board { BOARD_TARANIS_X9LITES, BOARD_JUMPER_T12, BOARD_JUMPER_T14, + BOARD_JUMPER_T15, BOARD_JUMPER_T16, BOARD_RADIOMASTER_TX16S, BOARD_JUMPER_T18, @@ -434,6 +435,11 @@ inline bool IS_JUMPER_TPROV2(Board::Type board) return board == Board::BOARD_JUMPER_TPROV2; } +inline bool IS_JUMPER_T15(Board::Type board) +{ + return board == Board::BOARD_JUMPER_T15; +} + inline bool IS_JUMPER_T16(Board::Type board) { return board == Board::BOARD_JUMPER_T16; @@ -492,7 +498,7 @@ inline bool IS_RADIOMASTER_T8(Board::Type board) inline bool IS_FAMILY_T16(Board::Type board) { - return board == Board::BOARD_JUMPER_T16 || board == Board::BOARD_RADIOMASTER_TX16S || board == Board::BOARD_JUMPER_T18; + return board == Board::BOARD_JUMPER_T15 || board == Board::BOARD_JUMPER_T16 || board == Board::BOARD_RADIOMASTER_TX16S || board == Board::BOARD_JUMPER_T18; } inline bool IS_FAMILY_T12(Board::Type board) diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index f56fcac4e1a..e8d9d176fd3 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -70,6 +70,8 @@ const char * OpenTxEepromInterface::getName() return "EdgeTX for Jumper T-Pro V2"; case BOARD_JUMPER_T14: return "EdgeTX for Jumper T14"; + case BOARD_JUMPER_T15: + return "EdgeTX for Jumper T15"; case BOARD_JUMPER_T16: return "EdgeTX for Jumper T16"; case BOARD_JUMPER_T18: @@ -710,7 +712,7 @@ int OpenTxFirmware::getCapability(::Capability capability) case LcdHeight: if (IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board)) return 480; - else if (IS_FLYSKY_PL18(board)) + else if (IS_FLYSKY_PL18(board) || IS_JUMPER_T15(board)) return 320; else if (IS_FAMILY_HORUS_OR_T16(board)) return 272; @@ -1440,6 +1442,12 @@ void registerOpenTxFirmwares() addOpenTxRfOptions(firmware, NONE); registerOpenTxFirmware(firmware); + /* Jumper T15 board */ + firmware = new OpenTxFirmware(FIRMWAREID("t15"), Firmware::tr("Jumper T15"), BOARD_JUMPER_T15); + addOpenTxFrskyOptions(firmware); + addOpenTxRfOptions(firmware, FLEX); + registerOpenTxFirmware(firmware); + /* Jumper T16 board */ firmware = new OpenTxFirmware(FIRMWAREID("t16"), Firmware::tr("Jumper T16 / T16+ / T16 Pro"), BOARD_JUMPER_T16); addOpenTxFrskyOptions(firmware); diff --git a/companion/src/images/simulator/JumperT15/bottom.png b/companion/src/images/simulator/JumperT15/bottom.png new file mode 100644 index 00000000000..8ca5f5a2c12 Binary files /dev/null and b/companion/src/images/simulator/JumperT15/bottom.png differ diff --git a/companion/src/images/simulator/JumperT15/exit.png b/companion/src/images/simulator/JumperT15/exit.png new file mode 100644 index 00000000000..8e58c797905 Binary files /dev/null and b/companion/src/images/simulator/JumperT15/exit.png differ diff --git a/companion/src/images/simulator/JumperT15/left.png b/companion/src/images/simulator/JumperT15/left.png new file mode 100644 index 00000000000..64d145d4c1c Binary files /dev/null and b/companion/src/images/simulator/JumperT15/left.png differ diff --git a/companion/src/images/simulator/JumperT15/model.png b/companion/src/images/simulator/JumperT15/model.png new file mode 100644 index 00000000000..c97c3ec47ae Binary files /dev/null and b/companion/src/images/simulator/JumperT15/model.png differ diff --git a/companion/src/images/simulator/JumperT15/page.png b/companion/src/images/simulator/JumperT15/page.png new file mode 100644 index 00000000000..f0d48656dd3 Binary files /dev/null and b/companion/src/images/simulator/JumperT15/page.png differ diff --git a/companion/src/images/simulator/JumperT15/right.png b/companion/src/images/simulator/JumperT15/right.png new file mode 100644 index 00000000000..4518e620e83 Binary files /dev/null and b/companion/src/images/simulator/JumperT15/right.png differ diff --git a/companion/src/images/simulator/JumperT15/top.png b/companion/src/images/simulator/JumperT15/top.png new file mode 100644 index 00000000000..27d67c85ced Binary files /dev/null and b/companion/src/images/simulator/JumperT15/top.png differ diff --git a/companion/src/simulation/CMakeLists.txt b/companion/src/simulation/CMakeLists.txt index 4ecdc64182f..3d3fee2a863 100644 --- a/companion/src/simulation/CMakeLists.txt +++ b/companion/src/simulation/CMakeLists.txt @@ -35,6 +35,7 @@ set(${PROJECT_NAME}_SRCS simulateduiwidgetEL18.cpp simulateduiwidgetJumperT12.cpp simulateduiwidgetJumperT14.cpp + simulateduiwidgetJumperT15.cpp simulateduiwidgetJumperT16.cpp simulateduiwidgetJumperT18.cpp simulateduiwidgetJumperT20.cpp diff --git a/companion/src/simulation/simulateduiwidget.h b/companion/src/simulation/simulateduiwidget.h index 7a31258cde1..87a681bc0fc 100644 --- a/companion/src/simulation/simulateduiwidget.h +++ b/companion/src/simulation/simulateduiwidget.h @@ -145,6 +145,7 @@ namespace Ui { class SimulatedUIWidgetJumperTLITE; class SimulatedUIWidgetJumperTPRO; class SimulatedUIWidgetJumperT14; + class SimulatedUIWidgetJumperT15; class SimulatedUIWidgetJumperT16; class SimulatedUIWidgetJumperT18; class SimulatedUIWidgetJumperT20; @@ -331,6 +332,18 @@ class SimulatedUIWidgetJumperTPRO: public SimulatedUIWidget Ui::SimulatedUIWidgetJumperTPRO * ui; }; +class SimulatedUIWidgetJumperT15: public SimulatedUIWidget +{ + Q_OBJECT + +public: + explicit SimulatedUIWidgetJumperT15(SimulatorInterface * simulator, QWidget * parent = nullptr); + virtual ~SimulatedUIWidgetJumperT15(); + +private: + Ui::SimulatedUIWidgetJumperT15 * ui; +}; + class SimulatedUIWidgetJumperT16: public SimulatedUIWidget { Q_OBJECT diff --git a/companion/src/simulation/simulateduiwidgetJumperT15.cpp b/companion/src/simulation/simulateduiwidgetJumperT15.cpp new file mode 100644 index 00000000000..e172b54b7e3 --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetJumperT15.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +// NOTE: RadioUiAction(NUMBER,...): NUMBER relates to enum EnumKeys in the specific board.h + +#include "simulateduiwidget.h" +#include "ui_simulateduiwidgetJumperT15.h" + +SimulatedUIWidgetJumperT15::SimulatedUIWidgetJumperT15(SimulatorInterface *simulator, QWidget * parent): + SimulatedUIWidget(simulator, parent), + ui(new Ui::SimulatedUIWidgetJumperT15) +{ + RadioUiAction * act; + + ui->setupUi(this); + + // add actions in order of appearance on the help menu + + act = new RadioUiAction(KEY_MODEL, QList() << Qt::Key_Up, SIMU_STR_HLP_KEY_UP, SIMU_STR_HLP_ACT_MDL); + addRadioWidget(ui->leftbuttons->addArea(QRect(80, 120, 100, 60), "JumperT15/model.png", act)); + + act = new RadioUiAction(KEY_SYS, QList() << Qt::Key_Left, SIMU_STR_HLP_KEY_LFT, SIMU_STR_HLP_ACT_SYS); + addRadioWidget(ui->leftbuttons->addArea(QRect(40, 55, 140, 40), "JumperT15/left.png", act)); + + act = new RadioUiAction(KEY_TELE, QList() << Qt::Key_Right, SIMU_STR_HLP_KEY_RGT, SIMU_STR_HLP_ACT_TELE); + addRadioWidget(ui->rightbuttons->addArea(QRect(75, 55, 140, 40), "JumperT15/right.png", act)); + + act = new RadioUiAction(KEY_EXIT, QList() << Qt::Key_Down << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, + SIMU_STR_HLP_KEY_DN % "
" % SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_RTN); + addRadioWidget(ui->leftbuttons->addArea(QRect(80, 310, 100, 60), "JumperT15/exit.png", act)); + + act = new RadioUiAction(KEY_PAGEDN, QList() << Qt::Key_PageDown, SIMU_STR_HLP_KEY_PGDN, SIMU_STR_HLP_ACT_PGDN); + addRadioWidget(ui->leftbuttons->addArea(QRect(50, 210, 100, 60), "JumperT15/page.png", act)); + + m_scrollUpAction = new RadioUiAction(-1, QList() << Qt::Key_Minus, SIMU_STR_HLP_KEY_MIN % "|" % SIMU_STR_HLP_MOUSE_UP, SIMU_STR_HLP_ACT_ROT_LFT); + m_scrollDnAction = new RadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Equal, SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_DN, SIMU_STR_HLP_ACT_ROT_RGT); + connectScrollActions(); + + m_mouseMidClickAction = new RadioUiAction(KEY_ENTER, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN); + addRadioWidget(ui->rightbuttons->addArea(QRect(80, 160, 100, 170), "JumperT15/right.png", m_mouseMidClickAction)); + + //addRadioWidget(ui->leftbuttons->addArea(QRect(10, 252, 30, 30), "JumperT15/left_scrnsht.png", m_screenshotAction)); + + m_backlightColors << QColor(47, 123, 227); + + setLcd(ui->lcd); +} + +SimulatedUIWidgetJumperT15::~SimulatedUIWidgetJumperT15() +{ + delete ui; +} diff --git a/companion/src/simulation/simulateduiwidgetJumperT15.ui b/companion/src/simulation/simulateduiwidgetJumperT15.ui new file mode 100644 index 00000000000..01aa6f97c6a --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetJumperT15.ui @@ -0,0 +1,206 @@ + + + SimulatedUIWidgetJumperT15 + + + + 0 + 0 + 1000 + 520 + + + + + 0 + 0 + + + + + 1000 + 520 + + + + + 1000 + 520 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 260 + 520 + + + + + 260 + 520 + + + + background:url(:/images/simulator/JumperT15/right.png) + + + + + + + + 0 + 0 + + + + + 480 + 320 + + + + + 480 + 320 + + + + + 5 + + + + + + + + + 0 + 0 + + + + + 260 + 520 + + + + + 260 + 520 + + + + true + + + background:url(:/images/simulator/JumperT15/left.png); + + + + + + + + 0 + 0 + + + + + 480 + 100 + + + + + 480 + 100 + + + + + 5 + + + + background:url(:/images/simulator/JumperT15/top.png) + + + + + + + + 0 + 0 + + + + + 480 + 100 + + + + + 480 + 100 + + + + + 5 + false + + + + background:url(:/images/simulator/JumperT15/bottom.png) + + + + + + + + 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 a708c013e8d..12571326cf6 100644 --- a/companion/src/simulation/simulatorwidget.cpp +++ b/companion/src/simulation/simulatorwidget.cpp @@ -108,6 +108,9 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato case Board::BOARD_JUMPER_T14: radioUiWidget = new SimulatedUIWidgetJumperT14(simulator, this); break; + case Board::BOARD_JUMPER_T15: + radioUiWidget = new SimulatedUIWidgetJumperT15(simulator, this); + break; case Board::BOARD_JUMPER_T16: radioUiWidget = new SimulatedUIWidgetJumperT16(simulator, this); break; diff --git a/fw.json b/fw.json index 8268c3cdc36..9bdf222b883 100644 --- a/fw.json +++ b/fw.json @@ -22,6 +22,7 @@ ["iFlight Commando 8", "commando8-"], ["Jumper T12", "t12-"], ["Jumper T14", "t14-"], + ["Jumper T15", "t15-"], ["Jumper T16", "t16-"], ["Jumper T18", "t18-"], ["Jumper T20", "t20-"], diff --git a/radio/src/cli.cpp b/radio/src/cli.cpp index fdfc6372b6d..bbead1cc613 100644 --- a/radio/src/cli.cpp +++ b/radio/src/cli.cpp @@ -1583,8 +1583,7 @@ int cliCrypt(const char ** argv) } #endif -#if defined(HARDWARE_TOUCH) && !defined(PCBNV14) && !defined(PCBPL18) - +#if defined(TP_GT911) // from tp_gt911.cpp extern uint8_t tp_gt911_cfgVer; @@ -1655,7 +1654,7 @@ const CliCommand cliCommands[] = { #if defined(ACCESS_DENIED) && defined(DEBUG_CRYPT) { "crypt", cliCrypt, "" }, #endif -#if defined(HARDWARE_TOUCH) && !defined(PCBNV14) && !defined(PCBPL18) +#if defined(TP_GT911) { "reset_gt911", cliResetGT911, ""}, #endif { nullptr, nullptr, nullptr } /* sentinel */ diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index f3bb0f41ff2..223a4221232 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -153,7 +153,10 @@ static inline void check_struct() CHKSIZE(RadioData, 869); CHKSIZE(ModelData, 6706); #elif defined(PCBHORUS) - #if defined(PCBX10) + #if defined(RADIO_T15) + CHKSIZE(RadioData, 965); + CHKSIZE(ModelData, 15760); + #elif defined(PCBX10) CHKSIZE(RadioData, 965); CHKSIZE(ModelData, 15735); #else diff --git a/radio/src/gui/colorlcd/CMakeLists.txt b/radio/src/gui/colorlcd/CMakeLists.txt index 23f8cde4606..7fb1a4e74c4 100644 --- a/radio/src/gui/colorlcd/CMakeLists.txt +++ b/radio/src/gui/colorlcd/CMakeLists.txt @@ -114,6 +114,13 @@ set(GUI_SRC radio_version.cpp ) +if(FUNCTION_SWITCHES) + set(GUI_SRC ${GUI_SRC} + function_switches.cpp + radio_diagcustswitches.cpp + ) +endif() + macro(add_gui_src src) set(GUI_SRC ${GUI_SRC} diff --git a/radio/src/gui/colorlcd/function_switches.cpp b/radio/src/gui/colorlcd/function_switches.cpp new file mode 100644 index 00000000000..ec3931bdfa4 --- /dev/null +++ b/radio/src/gui/colorlcd/function_switches.cpp @@ -0,0 +1,280 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#if defined(FUNCTION_SWITCHES) + +#include "function_switches.h" + +#include "opentx.h" +#include "strhelpers.h" +#include "switches.h" + +#define SET_DIRTY() storageDirty(EE_MODEL) + +static const lv_coord_t line_col_dsc1[] = {LV_GRID_CONTENT, + LV_GRID_TEMPLATE_LAST}; + +static const lv_coord_t line_col_dsc2[] = { + LV_GRID_FR(10), LV_GRID_FR(10), LV_GRID_FR(10), + LV_GRID_FR(12), LV_GRID_FR(8), LV_GRID_TEMPLATE_LAST}; + +static const lv_coord_t line_row_dsc[] = {LV_GRID_CONTENT, + LV_GRID_TEMPLATE_LAST}; + +static const char* _fct_sw_start[] = {STR_CHAR_DOWN, STR_CHAR_UP, STR_LAST}; + +const std::string edgetx_fs_manual_url = + "https://edgetx.gitbook.io/edgetx-user-manual/b-and-w-radios/model-select/" + "setup#function-switches"; + +class FunctionSwitch : public Window +{ + public: + FunctionSwitch(Window* parent, uint8_t sw) : + Window(parent, {0, 0, LCD_W - PAD_SMALL * 2, 36}), switchIndex(sw) + { + padAll(PAD_TINY); + + std::string s(STR_CHAR_SWITCH); + s += switchGetName(switchIndex + switchGetMaxSwitches()); + + new StaticText(this, {8, 6, SW_W, EdgeTxStyles::PAGE_LINE_HEIGHT}, s, + COLOR_THEME_PRIMARY1); + + new ModelTextEdit(this, {NM_X, 0, NM_W, 32}, + g_model.switchNames[switchIndex], LEN_SWITCH_NAME); + + auto choice = new Choice( + this, {TP_X, 0, TP_W, 32}, STR_SWTYPES, SWITCH_NONE, SWITCH_2POS, + [=]() { return FSWITCH_CONFIG(switchIndex); }, + [=](int val) { + FSWITCH_SET_CONFIG(switchIndex, val); + if (val == SWITCH_TOGGLE) { + FSWITCH_SET_STARTUP(switchIndex, FS_START_PREVIOUS); + startChoice->setValue(startChoice->getIntValue()); + } + SET_DIRTY(); + }); + choice->setAvailableHandler([=](int typ) -> bool { + int group = FSWITCH_GROUP(switchIndex); + if (group > 0 && IS_FSWITCH_GROUP_ON(group) && typ == SWITCH_TOGGLE) + return false; + return true; + }); + + groupChoice = new Choice( + this, {GR_X, 0, GR_W, 32}, STR_FUNCTION_SWITCH_GROUPS, 0, 3, + [=]() { return FSWITCH_GROUP(switchIndex); }, + [=](int group) { + int oldGroup = FSWITCH_GROUP(switchIndex); + if (groupHasSwitchOn(group)) setFSLogicalState(switchIndex, 0); + FSWITCH_SET_GROUP(switchIndex, group); + if (group > 0) { + FSWITCH_SET_STARTUP(switchIndex, groupDefaultSwitch(group) == -1 + ? FS_START_PREVIOUS + : FS_START_OFF); + if (FSWITCH_CONFIG(switchIndex) == SWITCH_TOGGLE && + IS_FSWITCH_GROUP_ON(group)) + FSWITCH_SET_CONFIG(switchIndex, SWITCH_2POS); + setGroupSwitchState(group, switchIndex); + } else { + FSWITCH_SET_STARTUP(switchIndex, FS_START_PREVIOUS); + } + setGroupSwitchState(oldGroup); + SET_DIRTY(); + }); + groupChoice->setAvailableHandler([=](int group) -> bool { + if (FSWITCH_CONFIG(switchIndex) == SWITCH_TOGGLE && group && + IS_FSWITCH_GROUP_ON(group)) + return false; + return true; + }); + + startChoice = new Choice( + this, {ST_X, 0, ST_W, 32}, _fct_sw_start, 0, 2, + [=]() { return FSWITCH_STARTUP(switchIndex); }, + [=](int val) { + FSWITCH_SET_STARTUP(switchIndex, val); + SET_DIRTY(); + }); + + setState(); + } + + static constexpr coord_t SW_W = (LCD_W - 4 * 2 - 2 * 4) / 5; + static constexpr coord_t NM_X = SW_W + 2; + static constexpr coord_t NM_W = 80; + static constexpr coord_t TP_X = NM_X + SW_W + 2; + static constexpr coord_t TP_W = 86; + static constexpr coord_t GR_X = TP_X + SW_W + 2; + static constexpr coord_t GR_W = 94; + static constexpr coord_t ST_X = GR_X + SW_W + 20; + static constexpr coord_t ST_W = 70; + + protected: + uint8_t switchIndex; + Choice* groupChoice = nullptr; + Choice* startChoice = nullptr; + + void setState() + { + if (FSWITCH_CONFIG(switchIndex) != SWITCH_2POS || + FSWITCH_GROUP(switchIndex) > 0) { + lv_obj_add_flag(startChoice->getLvObj(), LV_OBJ_FLAG_HIDDEN); + } else { + lv_obj_clear_flag(startChoice->getLvObj(), LV_OBJ_FLAG_HIDDEN); + } + if (FSWITCH_CONFIG(switchIndex) == SWITCH_NONE) { + lv_obj_add_flag(groupChoice->getLvObj(), LV_OBJ_FLAG_HIDDEN); + } else { + lv_obj_clear_flag(groupChoice->getLvObj(), LV_OBJ_FLAG_HIDDEN); + } + } + + void checkEvents() override + { + setState(); + Window::checkEvents(); + } +}; + +class SwitchGroup : public Window +{ + public: + SwitchGroup(Window* parent, uint8_t group) : + Window(parent, {0, 0, LCD_W - PAD_SMALL * 2, 36}), groupIndex(group) + { + padAll(PAD_TINY); + + new StaticText(this, {0, 6, NM_W, EdgeTxStyles::PAGE_LINE_HEIGHT}, + STR_FUNCTION_SWITCH_GROUPS[groupIndex], + COLOR_THEME_PRIMARY1); + + auto btn = new TextButton( + this, {AO_X, 0, AO_W, 32}, STR_GROUP_ALWAYS_ON, [=]() -> int8_t { + int groupAlwaysOn = IS_FSWITCH_GROUP_ON(groupIndex); + groupAlwaysOn ^= 1; + SET_FSWITCH_GROUP_ON(groupIndex, groupAlwaysOn); + setGroupSwitchState(groupIndex); + startChoice->setValue(startChoice->getIntValue()); + SET_DIRTY(); + return groupAlwaysOn; + }); + btn->check(IS_FSWITCH_GROUP_ON(groupIndex)); + + new StaticText(this, {SL_X, 6, SL_W, EdgeTxStyles::PAGE_LINE_HEIGHT}, STR_SWITCH_STARTUP, + COLOR_THEME_PRIMARY1); + + startChoice = new Choice( + this, {ST_X, 0, ST_W, 32}, STR_FSSWITCHES, 0, + NUM_FUNCTIONS_SWITCHES + 1, + [=]() { return groupDefaultSwitch(groupIndex) + 1; }, + [=](int sw) { + for (int i = 0; i < NUM_FUNCTIONS_SWITCHES; i += 1) { + if (FSWITCH_GROUP(i) == groupIndex) { + FSWITCH_SET_STARTUP(i, sw ? FS_START_OFF : FS_START_PREVIOUS); + } + } + if (sw > 0 && sw <= NUM_FUNCTIONS_SWITCHES) { + FSWITCH_SET_STARTUP(sw - 1, FS_START_ON); + } + SET_DIRTY(); + }); + startChoice->setAvailableHandler([=](int sw) -> bool { + return (sw == 0) || + (sw == NUM_FUNCTIONS_SWITCHES + 1 && + !IS_FSWITCH_GROUP_ON(groupIndex)) || + (FSWITCH_GROUP(sw - 1) == groupIndex); + }); + } + + static constexpr coord_t NM_W = 100; + static constexpr coord_t AO_X = NM_W + 2; + static constexpr coord_t AO_W = 100; + static constexpr coord_t SL_X = AO_X + AO_W + 30; + static constexpr coord_t SL_W = 100; + static constexpr coord_t ST_X = SL_X + SL_W + 2; + static constexpr coord_t ST_W = 80; + + protected: + uint8_t groupIndex; + Choice* startChoice; +}; + +ModelFunctionSwitches::ModelFunctionSwitches() : Page(ICON_MODEL_SETUP) +{ + header->setTitle(STR_MENU_MODEL_SETUP); + header->setTitle2(STR_MENU_FSWITCH); + + body->padAll(PAD_TINY); + body->setFlexLayout(LV_FLEX_FLOW_COLUMN, PAD_ZERO); + + FlexGridLayout grid1(line_col_dsc1, line_row_dsc, PAD_TINY); + FlexGridLayout grid2(line_col_dsc2, line_row_dsc, PAD_TINY); + + auto line = body->newLine(grid2); + new StaticText(line, rect_t{}, STR_SWITCHES, COLOR_THEME_PRIMARY1); + new StaticText(line, rect_t{}, STR_NAME, COLOR_THEME_PRIMARY1 | FONT(XS)); + new StaticText(line, rect_t{}, STR_SWITCH_TYPE, + COLOR_THEME_PRIMARY1 | FONT(XS)); + new StaticText(line, rect_t{}, STR_GROUP, COLOR_THEME_PRIMARY1 | FONT(XS)); + new StaticText(line, rect_t{}, STR_SWITCH_STARTUP, + COLOR_THEME_PRIMARY1 | FONT(XS)); + + for (uint8_t i = 0; i < NUM_FUNCTIONS_SWITCHES; i += 1) { + new FunctionSwitch(body, i); + } + + for (uint8_t i = 1; i <= 3; i += 1) { + groupLines[i - 1] = new SwitchGroup(body, i); + } + + line = body->newLine(grid1); + + new StaticText(line, rect_t{}, STR_MORE_INFO, COLOR_THEME_PRIMARY1); + + line = body->newLine(grid1); + line->padBottom(10); + line->padLeft((width() - 150) / 2); + + auto qr = lv_qrcode_create(line->getLvObj(), 150, + makeLvColor(COLOR_THEME_SECONDARY1), + makeLvColor(COLOR_THEME_SECONDARY3)); + lv_qrcode_update(qr, edgetx_fs_manual_url.c_str(), + edgetx_fs_manual_url.length()); +} + +void ModelFunctionSwitches::setState() +{ + for (int i = 0; i < 3; i += 1) + if (firstSwitchInGroup(i + 1) < 0) + lv_obj_add_flag(groupLines[i]->getLvObj(), LV_OBJ_FLAG_HIDDEN); + else + lv_obj_clear_flag(groupLines[i]->getLvObj(), LV_OBJ_FLAG_HIDDEN); +} + +void ModelFunctionSwitches::checkEvents() +{ + setState(); + Page::checkEvents(); +} + +#endif diff --git a/radio/src/gui/colorlcd/function_switches.h b/radio/src/gui/colorlcd/function_switches.h new file mode 100644 index 00000000000..768ef684f9e --- /dev/null +++ b/radio/src/gui/colorlcd/function_switches.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#if defined(FUNCTION_SWITCHES) + +#include "page.h" + +class ModelFunctionSwitches : public Page +{ + public: + ModelFunctionSwitches(); + + protected: + Window* groupLines[3] = {nullptr}; + BitmapBuffer* qrcode = nullptr; + + void setState(); + void checkEvents() override; +}; + +#endif diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp index c7ee0830706..82fc28c45fb 100644 --- a/radio/src/gui/colorlcd/model_setup.cpp +++ b/radio/src/gui/colorlcd/model_setup.cpp @@ -33,6 +33,9 @@ #include "trims_setup.h" #include "throttle_params.h" #include "preflight_checks.h" +#if defined(FUNCTION_SWITCHES) +#include "function_switches.h" +#endif #include "throttle_params.h" #include "timer_setup.h" #include "trainer_setup.h" @@ -387,6 +390,9 @@ void ModelSetupPage::build(Window * window) {STR_ENABLED_FEATURES, []() { new SubPage(ICON_MODEL_SETUP, STR_MENU_MODEL_SETUP, STR_ENABLED_FEATURES, viewOptionsPageSetupLines, DIM(viewOptionsPageSetupLines)); }}, #if defined(USBJ_EX) {STR_USBJOYSTICK_LABEL, []() { new ModelUSBJoystickPage(); }}, +#endif +#if defined(FUNCTION_SWITCHES) + {STR_FUNCTION_SWITCHES, []() { new ModelFunctionSwitches(); }}, #endif {STR_MENU_OTHER, []() { new SubPage(ICON_MODEL_SETUP, STR_MENU_MODEL_SETUP, STR_MENU_OTHER, otherPageSetupLines, DIM(otherPageSetupLines)); }}, }, BTN_H); diff --git a/radio/src/gui/colorlcd/radio_diaganas.cpp b/radio/src/gui/colorlcd/radio_diaganas.cpp index 5cf63920c32..2e4f6c9c38d 100644 --- a/radio/src/gui/colorlcd/radio_diaganas.cpp +++ b/radio/src/gui/colorlcd/radio_diaganas.cpp @@ -193,7 +193,7 @@ class AnaCalibratedViewWindow : public AnaViewWindow lv_obj_set_grid_cell(lbl->getLvObj(), LV_GRID_ALIGN_STRETCH, 0, 5, LV_GRID_ALIGN_CENTER, 0, 1); -#if !defined(SIMU) && !defined(PCBNV14) && !defined(PCBPL18) +#if !defined(SIMU) && defined(TP_GT911) line = newLine(grid); auto lbl2 = new StaticText( line, rect_t{}, diff --git a/radio/src/gui/colorlcd/radio_diagcustswitches.cpp b/radio/src/gui/colorlcd/radio_diagcustswitches.cpp new file mode 100644 index 00000000000..598322b5c65 --- /dev/null +++ b/radio/src/gui/colorlcd/radio_diagcustswitches.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#if defined(FUNCTION_SWITCHES) + +#include "radio_diagcustswitches.h" + +#include "board.h" +#include "libopenui.h" +#include "opentx.h" + +class RadioCustSwitchesDiagsWindow : public Window +{ + static constexpr coord_t FS_1ST_COLUMN = 95; + static constexpr coord_t FS_2ND_COLUMN = 160; + static constexpr coord_t FS_3RD_COLUMN = 260; + + public: + RadioCustSwitchesDiagsWindow(Window *parent, const rect_t &rect) : + Window(parent, rect) + { + new StaticText(this, {FS_1ST_COLUMN, PAD_SMALL, 60, LV_SIZE_CONTENT}, + "Phys"); + new StaticText(this, {FS_2ND_COLUMN, PAD_SMALL, 60, LV_SIZE_CONTENT}, + "Log"); + new StaticText(this, {FS_3RD_COLUMN, PAD_SMALL, 60, LV_SIZE_CONTENT}, + "Led"); + for (uint8_t i = 0; i < NUM_FUNCTIONS_SWITCHES; i += 1) { + coord_t y = 2 * EdgeTxStyles::PAGE_LINE_HEIGHT + + i * EdgeTxStyles::PAGE_LINE_HEIGHT; + new StaticText(this, {10, y, LV_SIZE_CONTENT, LV_SIZE_CONTENT}, + STR_CHAR_SWITCH); + new StaticText(this, {25, y, LV_SIZE_CONTENT, LV_SIZE_CONTENT}, + switchGetName(i + switchGetMaxSwitches())); + new DynamicText( + this, {FS_1ST_COLUMN + 10, y, LV_SIZE_CONTENT, LV_SIZE_CONTENT}, + [=]() { + return getFSPhysicalState(i) ? STR_CHAR_DOWN : STR_CHAR_UP; + }); + new DynamicText( + this, {FS_2ND_COLUMN + 10, y, LV_SIZE_CONTENT, LV_SIZE_CONTENT}, + [=]() { return getFSLogicalState(i) ? STR_CHAR_DOWN : STR_CHAR_UP; }); + new DynamicText(this, + {FS_3RD_COLUMN + 5, y, LV_SIZE_CONTENT, LV_SIZE_CONTENT}, + [=]() { return STR_OFFON[getFSLedState(i)]; }); + } + } + + protected: +}; + +void RadioCustSwitchesDiagsPage::buildHeader(Window *window) +{ + header->setTitle(STR_RADIO_SETUP); + header->setTitle2(STR_MENU_FSWITCH); +} + +void RadioCustSwitchesDiagsPage::buildBody(Window *window) +{ + body->padAll(PAD_ZERO); + new RadioCustSwitchesDiagsWindow(window, + {0, 0, window->width(), window->height()}); +} + +RadioCustSwitchesDiagsPage::RadioCustSwitchesDiagsPage() : + Page(ICON_MODEL_SETUP) +{ + buildHeader(header); + buildBody(body); +} + +#endif diff --git a/radio/src/gui/colorlcd/radio_diagcustswitches.h b/radio/src/gui/colorlcd/radio_diagcustswitches.h new file mode 100644 index 00000000000..6f3ed471163 --- /dev/null +++ b/radio/src/gui/colorlcd/radio_diagcustswitches.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "page.h" + +class RadioCustSwitchesDiagsPage : public Page +{ + public: + explicit RadioCustSwitchesDiagsPage(); + + protected: + void buildHeader(Window* window); + void buildBody(Window* window); +}; diff --git a/radio/src/gui/colorlcd/radio_hardware.cpp b/radio/src/gui/colorlcd/radio_hardware.cpp index c825187adbd..2ed8081e1c5 100644 --- a/radio/src/gui/colorlcd/radio_hardware.cpp +++ b/radio/src/gui/colorlcd/radio_hardware.cpp @@ -33,6 +33,10 @@ #include "radio_diagkeys.h" #include "radio_setup.h" +#if defined(FUNCTION_SWITCHES) +#include "radio_diagcustswitches.h" +#endif + #if defined(BLUETOOTH) #include "hw_bluetooth.h" #endif @@ -199,8 +203,11 @@ void RadioHardwarePage::build(Window* window) }); // Debugs - new SetupButtonGroup(window, {0, 0, LCD_W - padding * 2, 0}, STR_DEBUG, BTN_COLS, PAD_ZERO, { + new SetupButtonGroup(window, {0, 0, LCD_W - padding * 2, 0}, STR_DEBUG, FS_BTN_COLS, PAD_ZERO, { {STR_ANALOGS_BTN, []() { new RadioAnalogsDiagsViewPageGroup(); }}, {STR_KEYS_BTN, []() { new RadioKeyDiagsPage(); }}, +#if defined(FUNCTION_SWITCHES) + {STR_FS_BTN, []() { new RadioCustSwitchesDiagsPage(); }}, +#endif }); } diff --git a/radio/src/gui/colorlcd/radio_hardware.h b/radio/src/gui/colorlcd/radio_hardware.h index a56414a8267..11940ffdd52 100644 --- a/radio/src/gui/colorlcd/radio_hardware.h +++ b/radio/src/gui/colorlcd/radio_hardware.h @@ -32,6 +32,7 @@ class RadioHardwarePage : public PageTab static LAYOUT_VAL(NUM_EDIT_W, 80, 80) static LAYOUT_VAL(BTN_COLS, 4, 3) + static LAYOUT_VAL(FS_BTN_COLS, 2, 2) protected: void cleanup() override; diff --git a/radio/src/gui/colorlcd/radio_version.cpp b/radio/src/gui/colorlcd/radio_version.cpp index 93c2a38d5d9..7f542748760 100644 --- a/radio/src/gui/colorlcd/radio_version.cpp +++ b/radio/src/gui/colorlcd/radio_version.cpp @@ -360,6 +360,12 @@ void RadioVersionPage::build(Window* window) version += options[i]; } +#if defined(RADIO_T15) + version += nl; + version += "PCBREV: "; + version += '0' + hardwareOptions.pcbrev; +#endif + #if (defined(PCBNV14) || defined(PCBPL18)) && !defined(SIMU) version += nl; version += "LCD: "; diff --git a/radio/src/hal/adc_driver.cpp b/radio/src/hal/adc_driver.cpp index d3aeecca414..20d01d9d59e 100644 --- a/radio/src/hal/adc_driver.cpp +++ b/radio/src/hal/adc_driver.cpp @@ -310,6 +310,13 @@ uint16_t getBatteryVoltage() // removal will break existing calibrations! instant_vbat += VOLTAGE_DROP; return (uint16_t)instant_vbat; +#elif defined(VOLTAGE_DROP) + instant_vbat = ((instant_vbat * (1000 + g_eeGeneral.txVoltageCalibration)) / + BATTERY_DIVIDER); + // add voltage drop because of the diode + // removal will break existing calibrations! + instant_vbat += VOLTAGE_DROP; + return (uint16_t)instant_vbat; #else return (uint16_t)((instant_vbat * (1000 + g_eeGeneral.txVoltageCalibration)) / BATTERY_DIVIDER); diff --git a/radio/src/hal/rotary_encoder.h b/radio/src/hal/rotary_encoder.h index d1fc7456b39..510c6d598d1 100644 --- a/radio/src/hal/rotary_encoder.h +++ b/radio/src/hal/rotary_encoder.h @@ -27,7 +27,7 @@ #define ROTENC_MIDSPEED 5 #define ROTENC_HIGHSPEED 50 -#if defined(RADIO_FAMILY_T20) || defined(RADIO_T14) +#if defined(RADIO_FAMILY_T20) || defined(RADIO_T14) || defined(RADIO_T15) #define ROTARY_ENCODER_GRANULARITY 4 #else #define ROTARY_ENCODER_GRANULARITY 2 diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 75f9c7567d6..6860607f502 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -26,6 +26,7 @@ #include "opentx_types.h" #include "opentx_helpers.h" #include "touch.h" +#include "switches.h" #if defined(SIMU) #include "targets/simu/simpgmspace.h" diff --git a/radio/src/storage/yaml/CMakeLists.txt b/radio/src/storage/yaml/CMakeLists.txt index 6803ba88e7b..fd2756c2e72 100644 --- a/radio/src/storage/yaml/CMakeLists.txt +++ b/radio/src/storage/yaml/CMakeLists.txt @@ -17,7 +17,11 @@ endif() if(PCB STREQUAL X12S) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_x12s.cpp) elseif(PCB STREQUAL X10) - set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_x10.cpp) + if(PCBREV STREQUAL T15) + set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_t15.cpp) + else() + set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_x10.cpp) + endif() elseif(PCB STREQUAL NV14) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_nv14.cpp) elseif(PCB STREQUAL PL18) diff --git a/radio/src/storage/yaml/yaml_datastructs.cpp b/radio/src/storage/yaml/yaml_datastructs.cpp index dcc6ceabe92..e533c98065c 100644 --- a/radio/src/storage/yaml/yaml_datastructs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs.cpp @@ -31,7 +31,11 @@ #if defined(PCBX12S) #include "yaml_datastructs_x12s.cpp" #elif defined(PCBX10) - #include "yaml_datastructs_x10.cpp" +#if defined(RADIO_T15) + #include "yaml_datastructs_t15.cpp" + #else + #include "yaml_datastructs_x10.cpp" + #endif #elif defined(PCBNV14) #include "yaml_datastructs_nv14.cpp" #elif defined(PCBPL18) diff --git a/radio/src/storage/yaml/yaml_datastructs_t15.cpp b/radio/src/storage/yaml/yaml_datastructs_t15.cpp new file mode 100644 index 00000000000..2925365a6ff --- /dev/null +++ b/radio/src/storage/yaml/yaml_datastructs_t15.cpp @@ -0,0 +1,919 @@ +// generated by generate_yaml.py + +// +// Enums first +// + +const struct YamlIdStr enum_BacklightMode[] = { + { e_backlight_mode_off, "backlight_mode_off" }, + { e_backlight_mode_keys, "backlight_mode_keys" }, + { e_backlight_mode_sticks, "backlight_mode_sticks" }, + { e_backlight_mode_all, "backlight_mode_all" }, + { e_backlight_mode_on, "backlight_mode_on" }, + { 0, NULL } +}; +const struct YamlIdStr enum_AntennaModes[] = { + { ANTENNA_MODE_INTERNAL, "MODE_INTERNAL" }, + { ANTENNA_MODE_ASK, "MODE_ASK" }, + { ANTENNA_MODE_PER_MODEL, "MODE_PER_MODEL" }, + { ANTENNA_MODE_EXTERNAL, "MODE_EXTERNAL" }, + { 0, NULL } +}; +const struct YamlIdStr enum_ModuleType[] = { + { MODULE_TYPE_NONE, "TYPE_NONE" }, + { MODULE_TYPE_PPM, "TYPE_PPM" }, + { MODULE_TYPE_XJT_PXX1, "TYPE_XJT_PXX1" }, + { MODULE_TYPE_ISRM_PXX2, "TYPE_ISRM_PXX2" }, + { MODULE_TYPE_DSM2, "TYPE_DSM2" }, + { MODULE_TYPE_CROSSFIRE, "TYPE_CROSSFIRE" }, + { MODULE_TYPE_MULTIMODULE, "TYPE_MULTIMODULE" }, + { MODULE_TYPE_R9M_PXX1, "TYPE_R9M_PXX1" }, + { MODULE_TYPE_R9M_PXX2, "TYPE_R9M_PXX2" }, + { MODULE_TYPE_R9M_LITE_PXX1, "TYPE_R9M_LITE_PXX1" }, + { MODULE_TYPE_R9M_LITE_PXX2, "TYPE_R9M_LITE_PXX2" }, + { MODULE_TYPE_GHOST, "TYPE_GHOST" }, + { MODULE_TYPE_R9M_LITE_PRO_PXX2, "TYPE_R9M_LITE_PRO_PXX2" }, + { MODULE_TYPE_SBUS, "TYPE_SBUS" }, + { MODULE_TYPE_XJT_LITE_PXX2, "TYPE_XJT_LITE_PXX2" }, + { MODULE_TYPE_FLYSKY_AFHDS2A, "TYPE_FLYSKY_AFHDS2A" }, + { MODULE_TYPE_FLYSKY_AFHDS3, "TYPE_FLYSKY_AFHDS3" }, + { MODULE_TYPE_LEMON_DSMP, "TYPE_LEMON_DSMP" }, + { 0, NULL } +}; +const struct YamlIdStr enum_TrainerMultiplex[] = { + { TRAINER_OFF, "OFF" }, + { TRAINER_ADD, "ADD" }, + { TRAINER_REPL, "REPL" }, + { 0, NULL } +}; +const struct YamlIdStr enum_BeeperMode[] = { + { e_mode_quiet, "mode_quiet" }, + { e_mode_alarms, "mode_alarms" }, + { e_mode_nokeys, "mode_nokeys" }, + { e_mode_all, "mode_all" }, + { 0, NULL } +}; +const struct YamlIdStr enum_BluetoothModes[] = { + { BLUETOOTH_OFF, "OFF" }, + { BLUETOOTH_TELEMETRY, "TELEMETRY" }, + { BLUETOOTH_TRAINER, "TRAINER" }, + { 0, NULL } +}; +const struct YamlIdStr enum_Functions[] = { + { FUNC_OVERRIDE_CHANNEL, "OVERRIDE_CHANNEL" }, + { FUNC_TRAINER, "TRAINER" }, + { FUNC_INSTANT_TRIM, "INSTANT_TRIM" }, + { FUNC_RESET, "RESET" }, + { FUNC_SET_TIMER, "SET_TIMER" }, + { FUNC_ADJUST_GVAR, "ADJUST_GVAR" }, + { FUNC_VOLUME, "VOLUME" }, + { FUNC_SET_FAILSAFE, "SET_FAILSAFE" }, + { FUNC_RANGECHECK, "RANGECHECK" }, + { FUNC_BIND, "BIND" }, + { FUNC_PLAY_SOUND, "PLAY_SOUND" }, + { FUNC_PLAY_TRACK, "PLAY_TRACK" }, + { FUNC_PLAY_VALUE, "PLAY_VALUE" }, + { FUNC_PLAY_SCRIPT, "PLAY_SCRIPT" }, + { FUNC_BACKGND_MUSIC, "BACKGND_MUSIC" }, + { FUNC_BACKGND_MUSIC_PAUSE, "BACKGND_MUSIC_PAUSE" }, + { FUNC_VARIO, "VARIO" }, + { FUNC_HAPTIC, "HAPTIC" }, + { FUNC_LOGS, "LOGS" }, + { FUNC_BACKLIGHT, "BACKLIGHT" }, + { FUNC_SCREENSHOT, "SCREENSHOT" }, + { FUNC_RACING_MODE, "RACING_MODE" }, + { FUNC_DISABLE_TOUCH, "DISABLE_TOUCH" }, + { FUNC_SET_SCREEN, "SET_SCREEN" }, + { FUNC_DISABLE_AUDIO_AMP, "DISABLE_AUDIO_AMP" }, + { FUNC_RGB_LED, "RGB_LED" }, + { FUNC_TEST, "TEST" }, + { 0, NULL } +}; +const struct YamlIdStr enum_TimerModes[] = { + { TMRMODE_OFF, "OFF" }, + { TMRMODE_ON, "ON" }, + { TMRMODE_START, "START" }, + { TMRMODE_THR, "THR" }, + { TMRMODE_THR_REL, "THR_REL" }, + { TMRMODE_THR_START, "THR_START" }, + { 0, NULL } +}; +const struct YamlIdStr enum_MixerMultiplex[] = { + { MLTPX_ADD, "ADD" }, + { MLTPX_MUL, "MUL" }, + { MLTPX_REPL, "REPL" }, + { 0, NULL } +}; +const struct YamlIdStr enum_MixSources[] = { + { MIXSRC_NONE, "NONE" }, + { MIXSRC_TILT_X, "TILT_X" }, + { MIXSRC_TILT_Y, "TILT_Y" }, + { MIXSRC_SPACEMOUSE_A, "SPACEMOUSE_A" }, + { MIXSRC_SPACEMOUSE_B, "SPACEMOUSE_B" }, + { MIXSRC_SPACEMOUSE_C, "SPACEMOUSE_C" }, + { MIXSRC_SPACEMOUSE_D, "SPACEMOUSE_D" }, + { MIXSRC_SPACEMOUSE_E, "SPACEMOUSE_E" }, + { MIXSRC_SPACEMOUSE_F, "SPACEMOUSE_F" }, + { MIXSRC_MIN, "MIN" }, + { MIXSRC_MAX, "MAX" }, + { MIXSRC_TX_VOLTAGE, "TX_VOLTAGE" }, + { MIXSRC_TX_TIME, "TX_TIME" }, + { MIXSRC_TX_GPS, "TX_GPS" }, + { 0, NULL } +}; +const struct YamlIdStr enum_LogicalSwitchesFunctions[] = { + { LS_FUNC_NONE, "FUNC_NONE" }, + { LS_FUNC_VEQUAL, "FUNC_VEQUAL" }, + { LS_FUNC_VALMOSTEQUAL, "FUNC_VALMOSTEQUAL" }, + { LS_FUNC_VPOS, "FUNC_VPOS" }, + { LS_FUNC_VNEG, "FUNC_VNEG" }, + { LS_FUNC_APOS, "FUNC_APOS" }, + { LS_FUNC_ANEG, "FUNC_ANEG" }, + { LS_FUNC_AND, "FUNC_AND" }, + { LS_FUNC_OR, "FUNC_OR" }, + { LS_FUNC_XOR, "FUNC_XOR" }, + { LS_FUNC_EDGE, "FUNC_EDGE" }, + { LS_FUNC_EQUAL, "FUNC_EQUAL" }, + { LS_FUNC_GREATER, "FUNC_GREATER" }, + { LS_FUNC_LESS, "FUNC_LESS" }, + { LS_FUNC_DIFFEGREATER, "FUNC_DIFFEGREATER" }, + { LS_FUNC_ADIFFEGREATER, "FUNC_ADIFFEGREATER" }, + { LS_FUNC_TIMER, "FUNC_TIMER" }, + { LS_FUNC_STICKY, "FUNC_STICKY" }, + { 0, NULL } +}; +const struct YamlIdStr enum_SwashType[] = { + { SWASH_TYPE_NONE, "TYPE_NONE" }, + { SWASH_TYPE_120, "TYPE_120" }, + { SWASH_TYPE_120X, "TYPE_120X" }, + { SWASH_TYPE_140, "TYPE_140" }, + { SWASH_TYPE_90, "TYPE_90" }, + { 0, NULL } +}; +const struct YamlIdStr enum_SwitchSources[] = { + { SWSRC_NONE, "NONE" }, + { SWSRC_ON, "ON" }, + { SWSRC_ONE, "ONE" }, + { SWSRC_TELEMETRY_STREAMING, "TELEMETRY_STREAMING" }, + { SWSRC_RADIO_ACTIVITY, "RADIO_ACTIVITY" }, + { SWSRC_TRAINER_CONNECTED, "TRAINER_CONNECTED" }, + { SWSRC_OFF, "OFF" }, + { 0, NULL } +}; +const struct YamlIdStr enum_PotsWarnMode[] = { + { POTS_WARN_OFF, "WARN_OFF" }, + { POTS_WARN_MANUAL, "WARN_MANUAL" }, + { POTS_WARN_AUTO, "WARN_AUTO" }, + { 0, NULL } +}; +const struct YamlIdStr enum_ModelOverridableEnable[] = { + { OVERRIDE_GLOBAL, "GLOBAL" }, + { OVERRIDE_OFF, "OFF" }, + { OVERRIDE_ON, "ON" }, + { 0, NULL } +}; +const struct YamlIdStr enum_FailsafeModes[] = { + { FAILSAFE_NOT_SET, "NOT_SET" }, + { FAILSAFE_HOLD, "HOLD" }, + { FAILSAFE_CUSTOM, "CUSTOM" }, + { FAILSAFE_NOPULSES, "NOPULSES" }, + { FAILSAFE_RECEIVER, "RECEIVER" }, + { 0, NULL } +}; +const struct YamlIdStr enum_TelemetrySensorFormula[] = { + { TELEM_FORMULA_ADD, "FORMULA_ADD" }, + { TELEM_FORMULA_AVERAGE, "FORMULA_AVERAGE" }, + { TELEM_FORMULA_MIN, "FORMULA_MIN" }, + { TELEM_FORMULA_MAX, "FORMULA_MAX" }, + { TELEM_FORMULA_MULTIPLY, "FORMULA_MULTIPLY" }, + { TELEM_FORMULA_TOTALIZE, "FORMULA_TOTALIZE" }, + { TELEM_FORMULA_CELL, "FORMULA_CELL" }, + { TELEM_FORMULA_CONSUMPTION, "FORMULA_CONSUMPTION" }, + { TELEM_FORMULA_DIST, "FORMULA_DIST" }, + { 0, NULL } +}; +const struct YamlIdStr enum_TelemetrySensorType[] = { + { TELEM_TYPE_CUSTOM, "TYPE_CUSTOM" }, + { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" }, + { 0, NULL } +}; +const struct YamlIdStr enum_ZoneOptionValueEnum[] = { + { ZOV_Unsigned, "Unsigned" }, + { ZOV_Signed, "Signed" }, + { ZOV_Bool, "Bool" }, + { ZOV_String, "String" }, + { ZOV_Source, "Source" }, + { ZOV_Color, "Color" }, + { 0, NULL } +}; +const struct YamlIdStr enum_USBJoystickIfMode[] = { + { USBJOYS_JOYSTICK, "JOYSTICK" }, + { USBJOYS_GAMEPAD, "GAMEPAD" }, + { USBJOYS_MULTIAXIS, "MULTIAXIS" }, + { 0, NULL } +}; +const struct YamlIdStr enum_USBJoystickCh[] = { + { USBJOYS_CH_NONE, "CH_NONE" }, + { USBJOYS_CH_BUTTON, "CH_BUTTON" }, + { USBJOYS_CH_AXIS, "CH_AXIS" }, + { USBJOYS_CH_SIM, "CH_SIM" }, + { 0, NULL } +}; + +// +// Structs last +// + +static const struct YamlNode struct_CalibData[] = { + YAML_IDX_CUST("calib",r_calib,w_calib), + YAML_SIGNED( "mid", 16 ), + YAML_SIGNED( "spanNeg", 16 ), + YAML_SIGNED( "spanPos", 16 ), + YAML_END +}; +static const struct YamlNode struct_signed_16[] = { + YAML_IDX, + YAML_SIGNED( "val", 16 ), + YAML_END +}; +static const struct YamlNode struct_TrainerMix[] = { + YAML_IDX, + YAML_UNSIGNED( "srcChn", 6 ), + YAML_ENUM("mode", 2, enum_TrainerMultiplex), + YAML_SIGNED( "studWeight", 8 ), + YAML_END +}; +static const struct YamlNode struct_TrainerData[] = { + YAML_ARRAY("calib", 16, 4, struct_signed_16, NULL), + YAML_ARRAY("mix", 16, 4, struct_TrainerMix, NULL), + YAML_END +}; +static const struct YamlNode struct_anonymous_1[] = { + YAML_STRING("name", 8), + YAML_END +}; +static const struct YamlNode struct_anonymous_2[] = { + YAML_SIGNED( "val", 16 ), + YAML_UNSIGNED( "mode", 8 ), + YAML_UNSIGNED( "param", 8 ), + YAML_SIGNED( "spare", 32 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_3[] = { + YAML_SIGNED( "val1", 32 ), + YAML_SIGNED( "val2", 32 ), + YAML_END +}; +static const struct YamlNode union_anonymous_0_elmts[] = { + YAML_STRUCT("play", 64, struct_anonymous_1, NULL), + YAML_STRUCT("all", 64, struct_anonymous_2, NULL), + YAML_STRUCT("clear", 64, struct_anonymous_3, NULL), + YAML_END +}; +static const struct YamlNode struct_CustomFunctionData[] = { + YAML_IDX, + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), + YAML_ENUM("func", 6, enum_Functions), + YAML_CUSTOM("def",r_customFn,w_customFn), + YAML_PADDING( 64 ), + YAML_PADDING( 1 ), + YAML_PADDING( 7 ), + YAML_END +}; +static const struct YamlNode struct_RadioData[] = { + YAML_UNSIGNED( "manuallyEdited", 1 ), + YAML_SIGNED( "timezoneMinutes", 3 ), + YAML_UNSIGNED( "ppmunit", 2 ), + YAML_PADDING( 2 ), + YAML_CUSTOM("semver",nullptr,w_semver), + YAML_CUSTOM("board",nullptr,w_board), + YAML_ARRAY("calib", 48, 20, struct_CalibData, NULL), + YAML_PADDING( 16 ), + YAML_UNSIGNED( "vBatWarn", 8 ), + YAML_SIGNED( "txVoltageCalibration", 8 ), + YAML_ENUM("backlightMode", 3, enum_BacklightMode), + YAML_ENUM("antennaMode", 2, enum_AntennaModes), + YAML_UNSIGNED( "disableRtcWarning", 1 ), + YAML_UNSIGNED( "keysBacklight", 1 ), + YAML_UNSIGNED( "dontPlayHello", 1 ), + YAML_ENUM("internalModule", 8, enum_ModuleType), + YAML_STRUCT("trainer", 128, struct_TrainerData, NULL), + YAML_UNSIGNED( "view", 8 ), + YAML_PADDING( 2 ), + YAML_UNSIGNED( "fai", 1 ), + YAML_SIGNED_CUST( "beepMode", 2, r_beeperMode, w_beeperMode ), + YAML_UNSIGNED( "alarmsFlash", 1 ), + YAML_UNSIGNED( "disableMemoryWarning", 1 ), + YAML_UNSIGNED( "disableAlarmWarning", 1 ), + YAML_UNSIGNED( "stickMode", 2 ), + YAML_SIGNED( "timezone", 5 ), + YAML_UNSIGNED( "adjustRTC", 1 ), + YAML_UNSIGNED( "inactivityTimer", 8 ), + YAML_CUSTOM("telemetryBaudrate",r_telemetryBaudrate,nullptr), + YAML_UNSIGNED( "internalModuleBaudrate", 3 ), + YAML_SIGNED( "splashMode", 3 ), + YAML_SIGNED_CUST( "hapticMode", 2, r_beeperMode, w_beeperMode ), + YAML_SIGNED( "switchesDelay", 8 ), + YAML_UNSIGNED( "lightAutoOff", 8 ), + YAML_UNSIGNED( "templateSetup", 8 ), + YAML_SIGNED( "PPM_Multiplier", 8 ), + YAML_SIGNED_CUST( "hapticLength", 8, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "beepLength", 3, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "hapticStrength", 3, r_5pos, w_5pos ), + YAML_UNSIGNED( "gpsFormat", 1 ), + YAML_UNSIGNED( "audioMuteEnable", 1 ), + YAML_UNSIGNED_CUST( "speakerPitch", 8, r_spPitch, w_spPitch ), + YAML_SIGNED_CUST( "speakerVolume", 8, r_vol, w_vol ), + YAML_SIGNED_CUST( "vBatMin", 8, r_vbat_min, w_vbat_min ), + YAML_SIGNED_CUST( "vBatMax", 8, r_vbat_max, w_vbat_max ), + YAML_UNSIGNED( "backlightBright", 8 ), + YAML_UNSIGNED( "globalTimer", 32 ), + YAML_UNSIGNED( "bluetoothBaudrate", 4 ), + YAML_ENUM("bluetoothMode", 4, enum_BluetoothModes), + YAML_UNSIGNED( "countryCode", 2 ), + YAML_SIGNED( "pwrOnSpeed", 3 ), + YAML_SIGNED( "pwrOffSpeed", 3 ), + YAML_CUSTOM("jitterFilter",r_jitterFilter,nullptr), + YAML_UNSIGNED( "noJitterFilter", 1 ), + YAML_UNSIGNED( "imperial", 1 ), + YAML_UNSIGNED( "disableRssiPoweroffAlarm", 1 ), + YAML_UNSIGNED( "USBMode", 2 ), + YAML_UNSIGNED( "jackMode", 2 ), + YAML_PADDING( 1 ), + YAML_STRING("ttsLanguage", 2), + YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "backgroundVolume", 4, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "varioPitch", 8, r_vPitch, w_vPitch ), + YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ), + YAML_SIGNED( "varioRepeat", 8 ), + YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active), + YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr), + YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr), + YAML_ARRAY("serialPort", 8, 4, struct_serialConfig, nullptr), + YAML_ARRAY("sticksConfig", 0, MAX_STICKS, struct_stickConfig, stick_name_valid), + YAML_ARRAY("slidersConfig", 0, MAX_POTS, struct_sliderConfig, nullptr), + YAML_ARRAY("potsConfig", 4, 16, struct_potConfig, nullptr), + YAML_ARRAY("switchConfig", 2, 32, struct_switchConfig, nullptr), + YAML_ARRAY("flexSwitches", 0, MAX_FLEX_SWITCHES, struct_flexSwitch, flex_sw_valid), + YAML_STRING("currModelFilename", 17), + YAML_UNSIGNED( "modelQuickSelect", 1 ), + YAML_UNSIGNED( "blOffBright", 7 ), + YAML_STRING("bluetoothName", 10), + YAML_STRING("ownerRegistrationID", 8), + YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr), + YAML_UNSIGNED( "rotEncMode", 3 ), + YAML_SIGNED( "uartSampleMode", 2 ), + YAML_PADDING( 3 ), + YAML_SIGNED( "imuMax", 8 ), + YAML_SIGNED( "imuOffset", 8 ), + YAML_STRING("selectedTheme", 26), + YAML_UNSIGNED( "labelSingleSelect", 1 ), + YAML_UNSIGNED( "labelMultiMode", 1 ), + YAML_UNSIGNED( "favMultiMode", 1 ), + YAML_UNSIGNED( "modelSelectLayout", 2 ), + YAML_UNSIGNED( "radioThemesDisabled", 1 ), + YAML_UNSIGNED( "radioGFDisabled", 1 ), + YAML_UNSIGNED( "radioTrainerDisabled", 1 ), + YAML_UNSIGNED( "modelHeliDisabled", 1 ), + YAML_UNSIGNED( "modelFMDisabled", 1 ), + YAML_UNSIGNED( "modelCurvesDisabled", 1 ), + YAML_UNSIGNED( "modelGVDisabled", 1 ), + YAML_UNSIGNED( "modelLSDisabled", 1 ), + YAML_UNSIGNED( "modelSFDisabled", 1 ), + YAML_UNSIGNED( "modelCustomScriptsDisabled", 1 ), + YAML_UNSIGNED( "modelTelemetryDisabled", 1 ), + YAML_UNSIGNED( "disableTrainerPoweroffAlarm", 1 ), + YAML_PADDING( 7 ), + YAML_END +}; +static const struct YamlNode struct_unsigned_8[] = { + YAML_IDX, + YAML_UNSIGNED( "val", 8 ), + YAML_END +}; +static const struct YamlNode struct_ModelHeader[] = { + YAML_STRING("name", 15), + YAML_ARRAY("modelId", 8, 2, struct_unsigned_8, NULL), + YAML_STRING("bitmap", 14), + YAML_STRING("labels", 100), + YAML_END +}; +static const struct YamlNode struct_TimerData[] = { + YAML_IDX, + YAML_UNSIGNED( "start", 22 ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), + YAML_SIGNED( "value", 22 ), + YAML_ENUM("mode", 3, enum_TimerModes), + YAML_UNSIGNED( "countdownBeep", 2 ), + YAML_UNSIGNED( "minuteBeep", 1 ), + YAML_UNSIGNED( "persistent", 2 ), + YAML_SIGNED( "countdownStart", 2 ), + YAML_UNSIGNED( "showElapsed", 1 ), + YAML_UNSIGNED( "extraHaptic", 1 ), + YAML_PADDING( 6 ), + YAML_STRING("name", 8), + YAML_END +}; +static const struct YamlNode struct_CurveRef[] = { + YAML_UNSIGNED( "type", 8 ), + YAML_SIGNED_CUST( "value", 8, in_read_weight, in_write_weight ), + YAML_END +}; +static const struct YamlNode struct_MixData[] = { + YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "destCh", 5 ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), + YAML_UNSIGNED( "carryTrim", 1 ), + YAML_UNSIGNED( "mixWarn", 2 ), + YAML_ENUM("mltpx", 2, enum_MixerMultiplex), + YAML_UNSIGNED( "speedPrec", 1 ), + YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "delayUp", 8 ), + YAML_UNSIGNED( "delayDown", 8 ), + YAML_UNSIGNED( "speedUp", 8 ), + YAML_UNSIGNED( "speedDown", 8 ), + YAML_STRING("name", 6), + YAML_END +}; +static const struct YamlNode struct_LimitData[] = { + YAML_IDX, + YAML_SIGNED_CUST( "min", 11, in_read_weight, in_write_weight ), + YAML_SIGNED_CUST( "max", 11, in_read_weight, in_write_weight ), + YAML_SIGNED( "ppmCenter", 10 ), + YAML_SIGNED_CUST( "offset", 11, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "symetrical", 1 ), + YAML_UNSIGNED( "revert", 1 ), + YAML_PADDING( 3 ), + YAML_SIGNED( "curve", 8 ), + YAML_STRING("name", 6), + YAML_END +}; +static const struct YamlNode struct_ExpoData[] = { + YAML_UNSIGNED( "mode", 2 ), + YAML_UNSIGNED( "scale", 14 ), + YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), + YAML_SIGNED( "trimSource", 6 ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), + YAML_UNSIGNED( "chn", 5 ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ), + YAML_STRING("name", 6), + YAML_SIGNED_CUST( "offset", 8, in_read_weight, in_write_weight ), + YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_END +}; +static const struct YamlNode struct_CurveHeader[] = { + YAML_IDX, + YAML_UNSIGNED( "type", 1 ), + YAML_UNSIGNED( "smooth", 1 ), + YAML_SIGNED( "points", 6 ), + YAML_STRING("name", 3), + YAML_END +}; +static const struct YamlNode struct_signed_8[] = { + YAML_IDX, + YAML_SIGNED( "val", 8 ), + YAML_END +}; +static const struct YamlNode struct_LogicalSwitchData[] = { + YAML_IDX, + YAML_ENUM("func", 8, enum_LogicalSwitchesFunctions), + YAML_CUSTOM("def",r_logicSw,w_logicSw), + YAML_PADDING( 10 ), + YAML_PADDING( 10 ), + YAML_SIGNED_CUST( "andsw", 10, r_swtchSrc, w_swtchSrc ), + YAML_UNSIGNED( "lsPersist", 1 ), + YAML_UNSIGNED( "lsState", 1 ), + YAML_PADDING( 16 ), + YAML_UNSIGNED( "delay", 8 ), + YAML_UNSIGNED( "duration", 8 ), + YAML_END +}; +static const struct YamlNode struct_SwashRingData[] = { + YAML_ENUM("type", 8, enum_SwashType), + YAML_UNSIGNED( "value", 8 ), + YAML_UNSIGNED_CUST( "collectiveSource", 8, r_mixSrcRaw, w_mixSrcRaw ), + YAML_UNSIGNED_CUST( "aileronSource", 8, r_mixSrcRaw, w_mixSrcRaw ), + YAML_UNSIGNED_CUST( "elevatorSource", 8, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED( "collectiveWeight", 8 ), + YAML_SIGNED( "aileronWeight", 8 ), + YAML_SIGNED( "elevatorWeight", 8 ), + YAML_END +}; +static const struct YamlNode struct_trim_t[] = { + YAML_IDX, + YAML_SIGNED( "value", 11 ), + YAML_UNSIGNED( "mode", 5 ), + YAML_END +}; +static const struct YamlNode struct_FlightModeData[] = { + YAML_IDX, + YAML_ARRAY("trim", 16, 6, struct_trim_t, NULL), + YAML_STRING("name", 10), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), + YAML_PADDING( 6 ), + YAML_UNSIGNED( "fadeIn", 8 ), + YAML_UNSIGNED( "fadeOut", 8 ), + YAML_ARRAY("gvars", 16, 9, struct_signed_16, gvar_is_active), + YAML_END +}; +static const struct YamlNode struct_GVarData[] = { + YAML_IDX, + YAML_STRING("name", 3), + YAML_UNSIGNED( "min", 12 ), + YAML_UNSIGNED( "max", 12 ), + YAML_UNSIGNED( "popup", 1 ), + YAML_UNSIGNED( "prec", 1 ), + YAML_UNSIGNED( "unit", 2 ), + YAML_PADDING( 4 ), + YAML_END +}; +static const struct YamlNode struct_VarioData[] = { + YAML_UNSIGNED_CUST( "source", 7, r_tele_sensor, w_tele_sensor ), + YAML_UNSIGNED( "centerSilent", 1 ), + YAML_SIGNED( "centerMax", 8 ), + YAML_SIGNED( "centerMin", 8 ), + YAML_SIGNED( "min", 8 ), + YAML_SIGNED( "max", 8 ), + YAML_END +}; +static const struct YamlNode struct_RssiAlarmData[] = { + YAML_CUSTOM("disabled",r_rssiDisabled,nullptr), + YAML_CUSTOM("warning",r_rssiWarning,nullptr), + YAML_CUSTOM("critical",r_rssiCritical,nullptr), + YAML_END +}; +static const struct YamlNode struct_RFAlarmData[] = { + YAML_SIGNED( "warning", 8 ), + YAML_SIGNED( "critical", 8 ), + YAML_END +}; +static const struct YamlNode struct_PpmModule[] = { + YAML_SIGNED( "delay", 6 ), + YAML_UNSIGNED( "pulsePol", 1 ), + YAML_UNSIGNED( "outputType", 1 ), + YAML_SIGNED( "frameLength", 8 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_5[] = { + YAML_PADDING( 8 ), + YAML_UNSIGNED( "disableTelemetry", 1 ), + YAML_UNSIGNED( "disableMapping", 1 ), + YAML_UNSIGNED( "autoBindMode", 1 ), + YAML_UNSIGNED( "lowPowerMode", 1 ), + YAML_UNSIGNED( "receiverTelemetryOff", 1 ), + YAML_UNSIGNED( "receiverHigherChannels", 1 ), + YAML_PADDING( 2 ), + YAML_SIGNED( "optionValue", 8 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_6[] = { + YAML_UNSIGNED( "power", 2 ), + YAML_PADDING( 2 ), + YAML_UNSIGNED( "receiverTelemetryOff", 1 ), + YAML_UNSIGNED( "receiverHigherChannels", 1 ), + YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 8 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_7[] = { + YAML_PADDING( 6 ), + YAML_UNSIGNED( "noninverted", 1 ), + YAML_PADDING( 1 ), + YAML_SIGNED( "refreshRate", 8 ), + YAML_END +}; +static const struct YamlNode struct_string_64[] = { + YAML_IDX, + YAML_STRING("val", 8), + YAML_END +}; +static const struct YamlNode struct_anonymous_8[] = { + YAML_UNSIGNED( "receivers", 7 ), + YAML_UNSIGNED( "racingMode", 1 ), + YAML_ARRAY("receiverName", 64, 3, struct_string_64, NULL), + YAML_END +}; +static const struct YamlNode struct_anonymous_9[] = { + YAML_ARRAY("rx_id", 8, 4, struct_unsigned_8, NULL), + YAML_UNSIGNED( "mode", 3 ), + YAML_UNSIGNED( "rfPower", 1 ), + YAML_UNSIGNED( "reserved", 4 ), + YAML_ARRAY("rx_freq", 8, 2, struct_unsigned_8, NULL), + YAML_END +}; +static const struct YamlNode struct_anonymous_10[] = { + YAML_UNSIGNED( "emi", 2 ), + YAML_UNSIGNED( "telemetry", 1 ), + YAML_UNSIGNED( "phyMode", 3 ), + YAML_UNSIGNED( "reserved", 2 ), + YAML_UNSIGNED( "rfPower", 8 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_11[] = { + YAML_UNSIGNED( "raw12bits", 1 ), + YAML_UNSIGNED( "telemetryBaudrate", 3 ), + YAML_PADDING( 4 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_12[] = { + YAML_UNSIGNED( "telemetryBaudrate", 3 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_13[] = { + YAML_UNSIGNED( "flags", 8 ), + YAML_END +}; +static const struct YamlNode union_anonymous_4_elmts[] = { + YAML_ARRAY("raw", 8, 25, struct_unsigned_8, NULL), + YAML_STRUCT("ppm", 16, struct_PpmModule, NULL), + YAML_STRUCT("multi", 24, struct_anonymous_5, NULL), + YAML_STRUCT("pxx", 16, struct_anonymous_6, NULL), + YAML_STRUCT("sbus", 16, struct_anonymous_7, NULL), + YAML_STRUCT("pxx2", 200, struct_anonymous_8, NULL), + YAML_STRUCT("flysky", 56, struct_anonymous_9, NULL), + YAML_STRUCT("afhds3", 16, struct_anonymous_10, NULL), + YAML_STRUCT("ghost", 8, struct_anonymous_11, NULL), + YAML_STRUCT("crsf", 8, struct_anonymous_12, NULL), + YAML_STRUCT("dsmp", 8, struct_anonymous_13, NULL), + YAML_END +}; +static const struct YamlNode struct_ModuleData[] = { + YAML_IDX, + YAML_UNSIGNED_CUST( "type", 8, r_moduleType, w_moduleType ), + YAML_CUSTOM("subType",r_modSubtype,w_modSubtype), + YAML_UNSIGNED( "channelsStart", 8 ), + YAML_SIGNED_CUST( "channelsCount", 8, r_channelsCount, w_channelsCount ), + YAML_ENUM("failsafeMode", 4, enum_FailsafeModes), + YAML_PADDING( 4 ), + YAML_UNION("mod", 200, union_anonymous_4_elmts, select_mod_type), + YAML_END +}; +static const struct YamlNode struct_TrainerModuleData[] = { + YAML_UNSIGNED_CUST( "mode", 8, r_trainerMode, w_trainerMode ), + YAML_UNSIGNED( "channelsStart", 8 ), + YAML_SIGNED( "channelsCount", 8 ), + YAML_SIGNED( "frameLength", 8 ), + YAML_SIGNED( "delay", 6 ), + YAML_UNSIGNED( "pulsePol", 1 ), + YAML_PADDING( 1 ), + YAML_END +}; +static const struct YamlNode union_ScriptDataInput_elmts[] = { + YAML_SIGNED( "value", 16 ), + YAML_UNSIGNED_CUST( "source", 16, r_mixSrcRaw, w_mixSrcRaw ), + YAML_END +}; +static const struct YamlNode union_ScriptDataInput[] = { + YAML_IDX, + YAML_UNION("u", 16, union_ScriptDataInput_elmts, select_script_input), + YAML_END +}; +static const struct YamlNode struct_ScriptData[] = { + YAML_IDX, + YAML_STRING("file", 6), + YAML_STRING("name", 6), + YAML_ARRAY("inputs", 16, 6, union_ScriptDataInput, NULL), + YAML_END +}; +static const struct YamlNode struct_string_32[] = { + YAML_IDX, + YAML_STRING("val", 4), + YAML_END +}; +static const struct YamlNode union_anonymous_14_elmts[] = { + YAML_UNSIGNED( "id", 16 ), + YAML_UNSIGNED( "persistentValue", 16 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_16[] = { + YAML_UNSIGNED( "physID", 5 ), + YAML_UNSIGNED( "rxIndex", 3 ), + YAML_END +}; +static const struct YamlNode union_anonymous_15_elmts[] = { + YAML_STRUCT("frskyInstance", 8, struct_anonymous_16, NULL), + YAML_UNSIGNED( "instance", 8 ), + YAML_ENUM("formula", 8, enum_TelemetrySensorFormula), + YAML_END +}; +static const struct YamlNode struct_anonymous_18[] = { + YAML_UNSIGNED( "ratio", 16 ), + YAML_SIGNED( "offset", 16 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_19[] = { + YAML_UNSIGNED( "source", 8 ), + YAML_UNSIGNED( "index", 8 ), + YAML_PADDING( 16 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_20[] = { + YAML_ARRAY("sources", 8, 4, struct_signed_8, NULL), + YAML_END +}; +static const struct YamlNode struct_anonymous_21[] = { + YAML_UNSIGNED( "source", 8 ), + YAML_PADDING( 24 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_22[] = { + YAML_UNSIGNED( "gps", 8 ), + YAML_UNSIGNED( "alt", 8 ), + YAML_PADDING( 16 ), + YAML_END +}; +static const struct YamlNode union_anonymous_17_elmts[] = { + YAML_STRUCT("custom", 32, struct_anonymous_18, NULL), + YAML_STRUCT("cell", 32, struct_anonymous_19, NULL), + YAML_STRUCT("calc", 32, struct_anonymous_20, NULL), + YAML_STRUCT("consumption", 32, struct_anonymous_21, NULL), + YAML_STRUCT("dist", 32, struct_anonymous_22, NULL), + YAML_UNSIGNED( "param", 32 ), + YAML_END +}; +static const struct YamlNode struct_TelemetrySensor[] = { + YAML_IDX, + YAML_UNION("id1", 16, union_anonymous_14_elmts, select_id1), + YAML_UNION("id2", 8, union_anonymous_15_elmts, select_id2), + YAML_STRING("label", 4), + YAML_UNSIGNED( "subId", 8 ), + YAML_ENUM("type", 1, enum_TelemetrySensorType), + YAML_PADDING( 1 ), + YAML_UNSIGNED( "unit", 6 ), + YAML_UNSIGNED( "prec", 2 ), + YAML_UNSIGNED( "autoOffset", 1 ), + YAML_UNSIGNED( "filter", 1 ), + YAML_UNSIGNED( "logs", 1 ), + YAML_UNSIGNED( "persistent", 1 ), + YAML_UNSIGNED( "onlyPositive", 1 ), + YAML_PADDING( 1 ), + YAML_UNION("cfg", 32, union_anonymous_17_elmts, select_sensor_cfg), + YAML_END +}; +static const struct YamlNode union_ZoneOptionValue_elmts[] = { + YAML_UNSIGNED( "unsignedValue", 32 ), + YAML_SIGNED( "signedValue", 32 ), + YAML_UNSIGNED( "boolValue", 32 ), + YAML_STRING("stringValue", 8), + YAML_CUSTOM("source",r_zov_source,w_zov_source), + YAML_CUSTOM("color",r_zov_color,w_zov_color), + YAML_END +}; +static const struct YamlNode struct_ZoneOptionValueTyped[] = { + YAML_IDX, + YAML_ENUM("type", 32, enum_ZoneOptionValueEnum), + YAML_UNION("value", 64, union_ZoneOptionValue_elmts, select_zov), + YAML_END +}; +static const struct YamlNode struct_WidgetPersistentData[] = { + YAML_ARRAY("options", 96, 5, struct_ZoneOptionValueTyped, NULL), + YAML_END +}; +static const struct YamlNode struct_ZonePersistentData[] = { + YAML_IDX, + YAML_STRING("widgetName", 12), + YAML_STRUCT("widgetData", 480, struct_WidgetPersistentData, NULL), + YAML_END +}; +static const struct YamlNode struct_LayoutPersistentData[] = { + YAML_ARRAY("zones", 576, 10, struct_ZonePersistentData, NULL), + YAML_ARRAY("options", 96, 10, struct_ZoneOptionValueTyped, NULL), + YAML_END +}; +static const struct YamlNode struct_CustomScreenData[] = { + YAML_IDX, + YAML_STRING("LayoutId", 12), + YAML_STRUCT("layoutData", 6720, struct_LayoutPersistentData, NULL), + YAML_END +}; +static const struct YamlNode struct_TopBarPersistentData[] = { + YAML_ARRAY("zones", 576, 6, struct_ZonePersistentData, NULL), + YAML_ARRAY("options", 96, 1, struct_ZoneOptionValueTyped, NULL), + YAML_END +}; +static const struct YamlNode struct_string_24[] = { + YAML_IDX, + YAML_STRING("val", 3), + YAML_END +}; +static const struct YamlNode struct_USBJoystickChData[] = { + YAML_IDX, + YAML_ENUM("mode", 3, enum_USBJoystickCh), + YAML_UNSIGNED( "inversion", 1 ), + YAML_UNSIGNED( "param", 4 ), + YAML_UNSIGNED( "btn_num", 5 ), + YAML_UNSIGNED( "switch_npos", 3 ), + YAML_END +}; +static const struct YamlNode struct_ModelData[] = { + YAML_CUSTOM("semver",nullptr,w_semver), + YAML_STRUCT("header", 1048, struct_ModelHeader, NULL), + YAML_ARRAY("timers", 136, 3, struct_TimerData, NULL), + YAML_UNSIGNED( "telemetryProtocol", 3 ), + YAML_UNSIGNED( "thrTrim", 1 ), + YAML_UNSIGNED( "noGlobalFunctions", 1 ), + YAML_UNSIGNED( "displayTrims", 2 ), + YAML_UNSIGNED( "ignoreSensorIds", 1 ), + YAML_SIGNED( "trimInc", 3 ), + YAML_UNSIGNED( "disableThrottleWarning", 1 ), + YAML_UNSIGNED( "displayChecklist", 1 ), + YAML_UNSIGNED( "extendedLimits", 1 ), + YAML_UNSIGNED( "extendedTrims", 1 ), + YAML_UNSIGNED( "throttleReversed", 1 ), + YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ), + YAML_UNSIGNED( "disableTelemetryWarning", 1 ), + YAML_UNSIGNED( "showInstanceIds", 1 ), + YAML_UNSIGNED( "checklistInteractive", 1 ), + YAML_PADDING( 4 ), + YAML_SIGNED( "customThrottleWarningPosition", 8 ), + YAML_UNSIGNED( "beepANACenter", 16 ), + YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), + YAML_ARRAY("limitData", 104, 32, struct_LimitData, NULL), + YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL), + YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL), + YAML_ARRAY("points", 8, 512, struct_signed_8, NULL), + YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL), + YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active), + YAML_STRUCT("swashR", 64, struct_SwashRingData, swash_is_active), + YAML_ARRAY("flightModeData", 352, 9, struct_FlightModeData, fmd_is_active), + YAML_UNSIGNED_CUST( "thrTraceSrc", 8, r_thrSrc, w_thrSrc ), + YAML_CUSTOM("switchWarningState",r_swtchWarn,nullptr), + YAML_ARRAY("switchWarning", 3, 21, struct_swtchWarn, nullptr), + YAML_PADDING(1), + YAML_ARRAY("gvars", 56, 9, struct_GVarData, NULL), + YAML_STRUCT("varioData", 40, struct_VarioData, NULL), + YAML_UNSIGNED_CUST( "rssiSource", 8, r_tele_sensor, w_tele_sensor ), + YAML_STRUCT("rssiAlarms", 0, struct_RssiAlarmData, NULL), + YAML_STRUCT("rfAlarms", 16, struct_RFAlarmData, NULL), + YAML_UNSIGNED( "thrTrimSw", 3 ), + YAML_ENUM("potsWarnMode", 2, enum_PotsWarnMode), + YAML_ENUM("jitterFilter", 2, enum_ModelOverridableEnable), + YAML_PADDING( 1 ), + YAML_ARRAY("moduleData", 232, 2, struct_ModuleData, NULL), + YAML_ARRAY("failsafeChannels", 16, 32, struct_signed_16, NULL), + YAML_STRUCT("trainerData", 40, struct_TrainerModuleData, NULL), + YAML_ARRAY("scriptsData", 192, 9, struct_ScriptData, NULL), + YAML_ARRAY("inputNames", 32, 32, struct_string_32, NULL), + YAML_UNSIGNED( "potsWarnEnabled", 16 ), + YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL), + YAML_ARRAY("telemetrySensors", 112, 60, struct_TelemetrySensor, NULL), + YAML_ARRAY("screenData", 6816, 10, struct_CustomScreenData, NULL), + YAML_STRUCT("topbarData", 3552, struct_TopBarPersistentData, NULL), + YAML_UNSIGNED( "view", 8 ), + YAML_STRING("modelRegistrationID", 8), + YAML_UNSIGNED( "functionSwitchConfig", 16 ), + YAML_UNSIGNED( "functionSwitchGroup", 16 ), + YAML_UNSIGNED( "functionSwitchStartConfig", 16 ), + YAML_UNSIGNED( "functionSwitchLogicalState", 8 ), + YAML_ARRAY("switchNames", 24, 6, struct_string_24, NULL), + YAML_UNSIGNED( "usbJoystickExtMode", 1 ), + YAML_ENUM("usbJoystickIfMode", 3, enum_USBJoystickIfMode), + YAML_UNSIGNED( "usbJoystickCircularCut", 4 ), + YAML_ARRAY("usbJoystickCh", 16, 26, struct_USBJoystickChData, NULL), + YAML_ENUM("radioThemesDisabled", 2, enum_ModelOverridableEnable), + YAML_ENUM("radioGFDisabled", 2, enum_ModelOverridableEnable), + YAML_ENUM("radioTrainerDisabled", 2, enum_ModelOverridableEnable), + YAML_ENUM("modelHeliDisabled", 2, enum_ModelOverridableEnable), + YAML_ENUM("modelFMDisabled", 2, enum_ModelOverridableEnable), + YAML_ENUM("modelCurvesDisabled", 2, enum_ModelOverridableEnable), + YAML_ENUM("modelGVDisabled", 2, enum_ModelOverridableEnable), + YAML_ENUM("modelLSDisabled", 2, enum_ModelOverridableEnable), + YAML_ENUM("modelSFDisabled", 2, enum_ModelOverridableEnable), + YAML_ENUM("modelCustomScriptsDisabled", 2, enum_ModelOverridableEnable), + YAML_ENUM("modelTelemetryDisabled", 2, enum_ModelOverridableEnable), + YAML_END +}; +static const struct YamlNode struct_PartialModel[] = { + YAML_STRUCT("header", 1048, struct_ModelHeader, NULL), + YAML_ARRAY("timers", 136, 3, struct_TimerData, NULL), + YAML_END +}; + +#define MAX_RADIODATA_MODELDATA_PARTIALMODEL_STR_LEN 29 + +static const struct YamlNode __RadioData_root_node = YAML_ROOT( struct_RadioData ); + +const YamlNode* get_radiodata_nodes() +{ + return &__RadioData_root_node; +} +static const struct YamlNode __ModelData_root_node = YAML_ROOT( struct_ModelData ); + +const YamlNode* get_modeldata_nodes() +{ + return &__ModelData_root_node; +} +static const struct YamlNode __PartialModel_root_node = YAML_ROOT( struct_PartialModel ); + +const YamlNode* get_partialmodel_nodes() +{ + return &__PartialModel_root_node; +} + diff --git a/radio/src/switches.h b/radio/src/switches.h index f04ddd9daa3..a4e4a86b017 100644 --- a/radio/src/switches.h +++ b/radio/src/switches.h @@ -89,10 +89,18 @@ SwitchConfig switchGetMaxType(uint8_t idx); void logicalSwitchesInit(bool force); #if defined(FUNCTION_SWITCHES) +void setFSStartupPosition(); +void evalFunctionSwitches(); uint8_t getFSLogicalState(uint8_t index); void setFSLogicalState(uint8_t index, uint8_t value); bool groupHasSwitchOn(uint8_t group); int firstSwitchInGroup(uint8_t group); int groupDefaultSwitch(uint8_t group); void setGroupSwitchState(uint8_t group, int defaultSwitch = -1); +uint8_t getFSPhysicalState(uint8_t index); + +//led_driver.cpp +void fsLedOff(uint8_t); +void fsLedOn(uint8_t); +bool getFSLedState(uint8_t index); #endif diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 798b25bd421..c753f623d07 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -54,7 +54,7 @@ if (PCB STREQUAL X10) ${FIRMWARE_SRC} targets/common/arm/stm32/audio_dac_driver.cpp ) - if (NOT PCBREV STREQUAL TX16S) + if (NOT (PCBREV STREQUAL TX16S OR PCBREV STREQUAL T15)) set(FIRMWARE_SRC ${FIRMWARE_SRC} targets/common/arm/stm32/sticks_pwm_driver.cpp @@ -71,6 +71,18 @@ if (PCB STREQUAL X10) add_definitions(-DHARDWARE_POWER_MANAGEMENT_UNIT) add_definitions(-DRADIO_X10E) add_definitions(-DMANUFACTURER_FRSKY) + elseif (PCBREV STREQUAL T15) + set(FLAVOUR t15) + add_definitions(-DRADIO_T15) + add_definitions(-DRADIO_FAMILY_T16) + set(FUNCTION_SWITCHES ON) + set(DEFAULT_INTERNAL_MODULE CROSSFIRE CACHE STRING "Default internal module") + option(BLUETOOTH "Support for bluetooth module" OFF) + option(INTERNAL_GPS "Support for internal NMEA GPS" OFF) + set(AUX_SERIAL ON) + set(AUX2_SERIAL OFF) + add_definitions(-DMANUFACTURER_JUMPER) + set(LCD_DRIVER lcd_st7796s_driver.cpp) elseif (PCBREV STREQUAL T16) set(FLAVOUR t16) add_definitions(-DRADIO_T16) @@ -158,6 +170,10 @@ add_definitions(-DSTM32_SUPPORT_32BIT_TIMERS) set(SDRAM ON) +if(FUNCTION_SWITCHES) +add_definitions(-DFUNCTION_SWITCHES) +endif() + if(NOT UNEXPECTED_SHUTDOWN) add_definitions(-DNO_UNEXPECTED_SHUTDOWN) endif() @@ -206,7 +222,12 @@ endif() set(GVAR_SCREEN model_gvars.cpp) if(HARDWARE_TOUCH) - set(TOUCH_DRIVER tp_gt911.cpp) + if(FLAVOUR STREQUAL t15) + set(TOUCH_DRIVER cst8xx_driver.cpp) + else() + set(TOUCH_DRIVER tp_gt911.cpp) + add_definitions(-DTP_GT911) + endif() add_definitions(-DHARDWARE_TOUCH) endif() diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp index 51b837db5d6..3a18498f484 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -65,6 +65,52 @@ void boardInit() #endif pwrInit(); + +#if defined(FUNCTION_SWITCHES) && !defined(DEBUG_SEGGER_RTT) +#if defined(RADIO_T15) +#define LEDCHARGEON(x) fsLedOff(x) +#define LEDCHARGEOFF(x) fsLedOn(x) +#else +#define LEDCHARGEON(x) fsLedOn(x) +#define LEDCHARGEOFF(x) fsLedOff(x) +#endif + // This is needed to prevent radio from starting when usb is plugged to charge + usbInit(); + ledInit(); + // prime debounce state... + usbPlugged(); + if (usbPlugged()) { + delaysInit(); + adcInit(&_adc_driver); + getADC(); + pwrOn(); // required to get bat adc reads + INTERNAL_MODULE_OFF(); + EXTERNAL_MODULE_OFF(); + for (uint8_t i=0; i < NUM_FUNCTIONS_SWITCHES; i++) + LEDCHARGEOFF(i); + while (usbPlugged()) { + // Let it charge ... + getADC(); // Warning: the value read does not include VBAT calibration + // Also, MCU is running which create a drop vs off + if (getBatteryVoltage() >= 660) + LEDCHARGEON(0); + if (getBatteryVoltage() >= 700) + LEDCHARGEON(1); + if (getBatteryVoltage() >= 740) + LEDCHARGEON(2); + if (getBatteryVoltage() >= 780) + LEDCHARGEON(3); + if (getBatteryVoltage() >= 810) + LEDCHARGEON(4); + if (getBatteryVoltage() >= 820) + LEDCHARGEON(5); + delay_ms(1000); + } + while(1) // Wait power to drain + pwrOff(); + } +#endif + boardInitModulePorts(); #if defined(INTMODULE_HEARTBEAT) && \ diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index c3fa6ef13cd..c4264f2c66e 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -74,6 +74,10 @@ enum { // X10 PCBREV_X10_STD = 0, PCBREV_X10_EXPRESS = 3, + + //T15 + PCBREV_T15_STD = 0, + PCBREV_T15_IPS = 1, }; #if defined(SIMU) @@ -145,10 +149,6 @@ uint32_t isBootloaderStart(const uint8_t * buffer); #define IS_PXX1_INTERNAL_ENABLED() (true) #endif -#if !defined(NUM_FUNCTIONS_SWITCHES) -#define NUM_FUNCTIONS_SWITCHES 0 -#endif - // POTS and SLIDERS default configuration #if defined(RADIO_TX16S) #define XPOS_CALIB_DEFAULT {0x3, 0xc, 0x15, 0x1e, 0x26} @@ -159,6 +159,10 @@ uint32_t isBootloaderStart(const uint8_t * buffer); #define NUM_TRIMS_KEYS (NUM_TRIMS * 2) // Battery driver +#if defined(RADIO_T15) +#define VOLTAGE_DROP 65 +#endif + #if defined(PCBX10) // Lipo 2S #define BATTERY_WARN 66 // 6.6V @@ -320,6 +324,26 @@ void bluetoothDisable(); #define BATTERY_DIVIDER 1495 #else #define BATTERY_DIVIDER 1629 -#endif +#endif + +#if defined(FUNCTION_SWITCHES) +#define NUM_FUNCTIONS_SWITCHES 6 +#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 + +#else +#define NUM_FUNCTIONS_SWITCHES 0 +#endif #endif // _BOARD_H_ diff --git a/radio/src/targets/horus/bootloader/boot_menu.cpp b/radio/src/targets/horus/bootloader/boot_menu.cpp index 9536a762ff1..32530d65c15 100644 --- a/radio/src/targets/horus/bootloader/boot_menu.cpp +++ b/radio/src/targets/horus/bootloader/boot_menu.cpp @@ -61,7 +61,7 @@ static void bootloaderDrawTitle(unsigned int x, const char* text) static void bootloaderDrawFooter() { - lcd->drawSolidFilledRect(28, 234, 422, 2, BL_FOREGROUND); + lcd->drawSolidFilledRect(28, LCD_H - 38, 422, 2, BL_FOREGROUND); } static void bootloaderDrawBackground() @@ -94,17 +94,17 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str) pos -= 92; lcd->drawSolidRect(92, (opt == 0) ? 72 : 107, pos, 26, 2, BL_SELECTED); - lcd->drawBitmap(60, 166, (const BitmapBuffer*)&BMP_PLUG_USB); - lcd->drawText(195, 175, TR_BL_USB_PLUGIN, BL_FOREGROUND); - lcd->drawText(195, 200, TR_BL_USB_MASS_STORE, BL_FOREGROUND); + lcd->drawBitmap(60, LCD_H - 106, (const BitmapBuffer*)&BMP_PLUG_USB); + lcd->drawText(195, LCD_H - 97, TR_BL_USB_PLUGIN, BL_FOREGROUND); + lcd->drawText(195, LCD_H - 72, TR_BL_USB_MASS_STORE, BL_FOREGROUND); bootloaderDrawFooter(); - lcd->drawText(LCD_W / 2, 242, getFirmwareVersion(), CENTERED | BL_FOREGROUND); + lcd->drawText(LCD_W / 2, LCD_H - 30, getFirmwareVersion(), CENTERED | BL_FOREGROUND); } else if (st == ST_USB) { - - lcd->drawBitmap(136, 98, (const BitmapBuffer*)&BMP_USB_PLUGGED); - lcd->drawText(195, 128, TR_BL_USB_CONNECTED, BL_FOREGROUND); + coord_t y = (LCD_H - BMP_USB_PLUGGED.height()) / 2; + lcd->drawBitmap(136, y, (const BitmapBuffer*)&BMP_USB_PLUGGED); + lcd->drawText(195, y + 30, TR_BL_USB_CONNECTED, BL_FOREGROUND); } else if (st == ST_FILE_LIST || st == ST_DIR_CHECK || st == ST_FLASH_CHECK || st == ST_FLASHING || st == ST_FLASH_DONE) { @@ -119,8 +119,8 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str) opt = 100; // Completed > 100% } - lcd->drawRect(70, 120, 340, 31, 2, SOLID, BL_SELECTED); - lcd->drawSolidFilledRect(74, 124, (332 * opt) / 100, 23, color); + lcd->drawRect(70, (LCD_H - 31) / 2, 340, 31, 2, SOLID, BL_SELECTED); + lcd->drawSolidFilledRect(74, (LCD_H - 31) / 2 + 4, (332 * opt) / 100, 23, color); } else if (st == ST_DIR_CHECK) { if (opt == FR_NO_PATH) { lcd->drawText(90, 168, LV_SYMBOL_CLOSE TR_BL_DIR_MISSING, @@ -162,25 +162,25 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str) if ( st != ST_DIR_CHECK && (st != ST_FLASH_CHECK || opt == FC_OK)) { - lcd->drawText(28, 242, LV_SYMBOL_CHARGE, BL_FOREGROUND); + lcd->drawText(28, LCD_H - 30, LV_SYMBOL_CHARGE, BL_FOREGROUND); if (st == ST_FILE_LIST) { - lcd->drawText(56, 244, TR_BL_SELECT_KEY, BL_FOREGROUND); + lcd->drawText(56, LCD_H - 28, TR_BL_SELECT_KEY, BL_FOREGROUND); } else if (st == ST_FLASH_CHECK && opt == FC_OK) { - lcd->drawText(56, 244, TR_BL_FLASH_KEY, BL_FOREGROUND); + lcd->drawText(56, LCD_H - 28, TR_BL_FLASH_KEY, BL_FOREGROUND); } else if (st == ST_FLASHING) { - lcd->drawText(56, 244, TR_BL_WRITING_FW, BL_FOREGROUND); + lcd->drawText(56, LCD_H - 28, TR_BL_WRITING_FW, BL_FOREGROUND); } else if (st == ST_FLASH_DONE) { - lcd->drawText(56, 244, TR_BL_WRITING_COMPL, BL_FOREGROUND); + lcd->drawText(56, LCD_H - 28, TR_BL_WRITING_COMPL, BL_FOREGROUND); } } if (st != ST_FLASHING) { - lcd->drawText(305, 244, LV_SYMBOL_NEW_LINE, BL_FOREGROUND); - lcd->drawText(335, 244, TR_BL_EXIT_KEY, BL_FOREGROUND); + lcd->drawText(305, LCD_H - 28, LV_SYMBOL_NEW_LINE, BL_FOREGROUND); + lcd->drawText(335, LCD_H - 28, TR_BL_EXIT_KEY, BL_FOREGROUND); } } diff --git a/radio/src/targets/horus/cst8xx_driver.cpp b/radio/src/targets/horus/cst8xx_driver.cpp new file mode 100644 index 00000000000..f0745d42825 --- /dev/null +++ b/radio/src/targets/horus/cst8xx_driver.cpp @@ -0,0 +1,290 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "cst8xx_driver.h" + +#include "debug.h" +#include "delays_driver.h" +#include "hal.h" +#include "hal/gpio.h" +#include "rtos.h" +#include "stm32_exti_driver.h" +#include "stm32_gpio.h" +#include "stm32_gpio_driver.h" +#include "stm32_hal.h" +#include "stm32_hal_ll.h" +#include "stm32_i2c_driver.h" +#include "timers_driver.h" + +volatile static bool touchEventOccured; + +#define TOUCH_CST836U_I2C_ADDRESS (0x15) + +static tc_handle_TypeDef tc_handle = {0, 0}; + +tmr10ms_t downTime = 0; +tmr10ms_t tapTime = 0; +short tapCount = 0; +#define TAP_TIME 250 // ms + +static TouchState internalTouchState = {}; + +static void _cst836u_exti_isr(void) { touchEventOccured = true; } + +static void TouchAFExtiConfig(void) +{ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + LL_SYSCFG_SetEXTISource(TOUCH_INT_EXTI_Port, TOUCH_INT_EXTI_SysCfgLine); + + stm32_exti_enable(TOUCH_INT_EXTI_Line, LL_EXTI_TRIGGER_FALLING, + _cst836u_exti_isr); +} + +void initTouchI2C(void) +{ + TRACE("CST836U I2C Init"); + + if (stm32_i2c_init(TOUCH_I2C_BUS, TOUCH_I2C_CLK_RATE) < 0) { + TRACE("CST836U ERROR: stm32_i2c_init failed"); + return; + } +} + +#define I2C_TIMEOUT_MAX 5 // 5 ms + +bool touch_i2c_read(uint8_t addr, uint8_t reg, uint8_t* data, uint8_t len) +{ + if (stm32_i2c_master_tx(TOUCH_I2C_BUS, addr, ®, 1, 3) < 0) return false; + delay_us(5); + if (stm32_i2c_master_rx(TOUCH_I2C_BUS, addr, data, len, I2C_TIMEOUT_MAX) < 0) + return false; + + return true; +} + +static uint8_t TS_IO_Read(uint8_t addr, uint8_t reg) +{ + uint8_t result; + uint8_t tryCount = 3; + while (!touch_i2c_read(addr, reg, &result, 1)) { + if (--tryCount == 0) break; + initTouchI2C(); + } + return result; +} + +static uint16_t TS_IO_ReadMultiple(uint8_t addr, uint8_t reg, uint8_t* buffer, + uint16_t length) +{ + uint8_t tryCount = 3; + while (!touch_i2c_read(addr, reg, buffer, length)) { + if (--tryCount == 0) break; + initTouchI2C(); + } + return 1; +} + +static void touch_cst836u_debug_info(void) +{ +#if defined(DEBUG) + TRACE("cst836u: fw ver 0x%02X %02X", + TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_FW_VERSION_H_REG), + TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_FW_VERSION_L_REG)); + TRACE("cst836u: module version 0x%02X", + TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_MODULE_VERSION_REG)); + TRACE("cst836u: project name 0x%02X", + TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_PROJECT_NAME_REG)); + TRACE("cst836u: chip type 0x%02X 0x%02X", + TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_CHIP_TYPE_H_REG), + TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_CHIP_TYPE_L_REG)); +#endif +} + +/** + * @brief Get the touch screen X and Y positions values + * Manage multi touch thanks to touch Index global + * variable 'tc_handle.currActiveTouchIdx'. + * @param DeviceAddr: Device address on communication Bus. + * @param X: Pointer to X position value + * @param Y: Pointer to Y position value + * @retval None. + */ +static void cst836u_TS_GetXY(uint16_t* X, uint16_t* Y, uint32_t* event) +{ + uint8_t regAddress = 0; + uint8_t dataxy[4]; + + if (tc_handle.currActiveTouchIdx < tc_handle.currActiveTouchNb) { + switch (tc_handle.currActiveTouchIdx) { + case 0: + regAddress = CST836U_TOUCH1_XH_REG; + break; + case 1: + regAddress = CST836U_TOUCH2_XH_REG; + break; + default: + break; + } + + /* Read X and Y positions */ + TS_IO_ReadMultiple(TOUCH_CST836U_I2C_ADDRESS, regAddress, dataxy, + sizeof(dataxy)); + /* Send back ready X position to caller */ + *X = ((dataxy[0] & CST836U_MSB_MASK) << 8) | dataxy[1]; + /* Send back ready Y position to caller */ + *Y = ((dataxy[2] & CST836U_MSB_MASK) << 8) | dataxy[3]; + + *event = (dataxy[0] & CST836U_TOUCH_EVT_FLAG_MASK) >> + CST836U_TOUCH_EVT_FLAG_SHIFT; + /* + uint32_t weight; + uint32_t area; + */ + tc_handle.currActiveTouchIdx++; + } +} + +/** + * @brief Return if there is touches detected or not. + * Try to detect new touches and forget the old ones (reset internal + * global variables). + * @param DeviceAddr: Device address on communication Bus. + * @retval : Number of active touches detected (can be 0, 1 or 2). + */ +static uint8_t cst836u_TS_DetectTouch() +{ + volatile uint8_t nbTouch = 0; + + /* Read register CST836U_TOUCH_NUM_REG to check number of touches detection */ + nbTouch = TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_TOUCH_NUM_REG); + if (nbTouch > CST836U_MAX_DETECTABLE_TOUCH) { + /* If invalid number of touch detected, set it to zero */ + nbTouch = 0; + } + tc_handle.currActiveTouchNb = nbTouch; + + tc_handle.currActiveTouchIdx = 0; + return (nbTouch); +} + +void TouchReset() +{ + gpio_clear(TOUCH_RST_GPIO); + delay_ms(10); + gpio_set(TOUCH_RST_GPIO); + delay_ms(300); +} + +void touchPanelInit(void) +{ + gpio_init(TOUCH_RST_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW); + initTouchI2C(); + TouchReset(); + TouchAFExtiConfig(); + touch_cst836u_debug_info(); +} + +void handleTouch() +{ + unsigned short touchX; + unsigned short touchY; + uint32_t tEvent = 0; + cst836u_TS_GetXY(&touchX, &touchY, &tEvent); + + if (tEvent == CST836U_TOUCH_EVT_FLAG_CONTACT) { + int dx = touchX - internalTouchState.x; + int dy = touchY - internalTouchState.y; + + internalTouchState.x = touchX; + internalTouchState.y = touchY; + + if (internalTouchState.event == TE_NONE || + internalTouchState.event == TE_UP || + internalTouchState.event == TE_SLIDE_END) { + internalTouchState.startX = internalTouchState.x; + internalTouchState.startY = internalTouchState.y; + internalTouchState.event = TE_DOWN; + } else if (internalTouchState.event == TE_DOWN) { + if (dx >= SLIDE_RANGE || dx <= -SLIDE_RANGE || dy >= SLIDE_RANGE || + dy <= -SLIDE_RANGE) { + internalTouchState.event = TE_SLIDE; + internalTouchState.deltaX = (short)dx; + internalTouchState.deltaY = (short)dy; + } else { + internalTouchState.event = TE_DOWN; + internalTouchState.deltaX = 0; + internalTouchState.deltaY = 0; + } + } else if (internalTouchState.event == TE_SLIDE) { + internalTouchState.event = TE_SLIDE; // no change + internalTouchState.deltaX = (short)dx; + internalTouchState.deltaY = (short)dy; + } + } +} + +bool touchPanelEventOccured() { return touchEventOccured; } + +TouchState touchPanelRead() +{ + if (!touchEventOccured) return internalTouchState; + + touchEventOccured = false; + + tmr10ms_t now = RTOS_GET_MS(); + internalTouchState.tapCount = 0; + + if (cst836u_TS_DetectTouch()) { + handleTouch(); + if (internalTouchState.event == TE_DOWN && downTime == 0) { + downTime = now; + } + } else { + if (internalTouchState.event == TE_DOWN) { + internalTouchState.event = TE_UP; + if (now - downTime <= TAP_TIME) { + if (now - tapTime > TAP_TIME) { + tapCount = 1; + } else { + tapCount++; + } + internalTouchState.tapCount = tapCount; + tapTime = now; + } else { + internalTouchState.tapCount = 0; // not a tap + } + downTime = 0; + } else { + tapCount = 0; + internalTouchState.tapCount = 0; + internalTouchState.event = TE_SLIDE_END; + } + } + TouchState ret = internalTouchState; + internalTouchState.deltaX = 0; + internalTouchState.deltaY = 0; + if (internalTouchState.event == TE_UP || + internalTouchState.event == TE_SLIDE_END) + internalTouchState.event = TE_NONE; + return ret; +} + +TouchState getInternalTouchState() { return internalTouchState; } diff --git a/radio/src/targets/horus/cst8xx_driver.h b/radio/src/targets/horus/cst8xx_driver.h new file mode 100644 index 00000000000..086d73d00c2 --- /dev/null +++ b/radio/src/targets/horus/cst8xx_driver.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + Copyright 2016 fishpepper gmail.com + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + author: fishpepper gmail.com +*/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* Set Multi-touch as non supported */ +#ifndef TS_MULTI_TOUCH_SUPPORTED +#define TS_MULTI_TOUCH_SUPPORTED 0 +#endif + +/* Set Auto-calibration as non supported */ +#ifndef TS_AUTO_CALIBRATION_SUPPORTED +#define TS_AUTO_CALIBRATION_SUPPORTED 0 +#endif + +/* Macros --------------------------------------------------------------------*/ + +/** @typedef ft6x06_handle_TypeDef + * ft6x06 Handle definition. + */ +typedef struct { + /* field holding the current number of simultaneous active touches */ + uint8_t currActiveTouchNb; + + /* field holding the touch index currently managed */ + uint8_t currActiveTouchIdx; + +} tc_handle_TypeDef; +/* clang-format off */ +#define CST836U_WORK_MODE_REG 0x00 +#define CST836U_PROXIMITY_ID_REG 0x01 +#define CST836U_TOUCH_NUM_REG 0x02 +#define CST836U_TOUCH1_XH_REG 0x03 +#define CST836U_TOUCH1_XL_REG 0x04 +#define CST836U_TOUCH1_YH_REG 0x05 +#define CST836U_TOUCH1_YL_REG 0x06 + +#define CST836U_TOUCH2_XH_REG 0x09 +#define CST836U_TOUCH2_XL_REG 0x0A +#define CST836U_TOUCH2_YH_REG 0x0B +#define CST836U_TOUCH2_YL_REG 0x0C + +#define CST836U_FW_VERSION_L_REG 0xA6 +#define CST836U_FW_VERSION_H_REG 0xA7 +#define CST836U_MODULE_VERSION_REG 0xA8 +#define CST836U_PROJECT_NAME_REG 0xA9 +#define CST836U_CHIP_TYPE_L_REG 0xAA +#define CST836U_CHIP_TYPE_H_REG 0xAB +#define CST836U_CHECKSUM_L_REG 0xAC +#define CST836U_CHECKSUM_H_REG 0xAD + +#define CST836U_PROX_STATE_REG 0xB0 +#define CST836U_GES_STATE_REG 0xD0 +#define CST836U_GES_ID_REG_REG 0xD3 + +#define CST836U_MAX_DETECTABLE_TOUCH 2 + +#define CST836U_MSB_MASK 0x0F + +#define CST836U_TOUCH_EVT_FLAG_SHIFT 6 +#define CST836U_TOUCH_EVT_FLAG_MASK (3 << CST836U_TOUCH_EVT_FLAG_SHIFT) +#define CST836U_TOUCH_EVT_FLAG_CONTACT 0x02 +/* clang-format on */ + +extern void TouchInit(void); +extern void TouchDriver(void); + +#ifdef __cplusplus +} +#endif diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index ee1aa9b38f3..421a9fe69e4 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -61,6 +61,19 @@ #define KEYS_GPIO_PIN_SYS LL_GPIO_PIN_7 // PI.07 #define KEYS_GPIO_REG_TELE GPIOI #define KEYS_GPIO_PIN_TELE LL_GPIO_PIN_5 // PI.05 +#elif defined(RADIO_T15) + #define KEYS_GPIO_REG_ENTER GPIOI + #define KEYS_GPIO_PIN_ENTER LL_GPIO_PIN_8 // PI.08 + #define KEYS_GPIO_REG_PAGEDN GPIOI + #define KEYS_GPIO_PIN_PAGEDN LL_GPIO_PIN_11 // PI.11 + #define KEYS_GPIO_REG_MDL GPIOI + #define KEYS_GPIO_PIN_MDL LL_GPIO_PIN_6 // PI.06 + #define KEYS_GPIO_REG_EXIT GPIOI + #define KEYS_GPIO_PIN_EXIT LL_GPIO_PIN_5 // PI.05 + #define KEYS_GPIO_REG_SYS GPIOI + #define KEYS_GPIO_PIN_SYS LL_GPIO_PIN_7 // PI.07 + #define KEYS_GPIO_REG_TELE GPIOI + #define KEYS_GPIO_PIN_TELE LL_GPIO_PIN_4 // PI.04 #elif defined(PCBX10) #define KEYS_GPIO_REG_ENTER GPIOI #define KEYS_GPIO_PIN_ENTER LL_GPIO_PIN_8 // PI.08 @@ -94,90 +107,188 @@ #define ROTARY_ENCODER_TIMER_IRQn TIM8_BRK_TIM12_IRQn #define ROTARY_ENCODER_TIMER_IRQHandler TIM8_BRK_TIM12_IRQHandler -#if defined(RADIO_FAMILY_T16) && !defined(RADIO_T18) +#if defined(RADIO_T15) + #define ROTARY_ENCODER_INVERTED +#endif + +#if defined(RADIO_FAMILY_T16) && !defined(RADIO_T18) && !defined(RADIO_T15) #define ROTARY_ENCODER_SUPPORT_BUGGY_WIRING #endif // Switches -#define STORAGE_SWITCH_A -#define HARDWARE_SWITCH_A -#define SWITCHES_GPIO_REG_A_H GPIOH -#define SWITCHES_GPIO_PIN_A_H LL_GPIO_PIN_9 // PH.09 -#define SWITCHES_GPIO_REG_A_L GPIOI -#define SWITCHES_GPIO_PIN_A_L LL_GPIO_PIN_15 // PI.15 -#define STORAGE_SWITCH_B -#define HARDWARE_SWITCH_B -#define SWITCHES_GPIO_REG_B_H GPIOH -#define SWITCHES_GPIO_PIN_B_H LL_GPIO_PIN_12 // PH.12 -#define SWITCHES_GPIO_REG_B_L GPIOB -#define SWITCHES_GPIO_PIN_B_L LL_GPIO_PIN_12 // PB.12 -#define STORAGE_SWITCH_C -#define HARDWARE_SWITCH_C -#define SWITCHES_GPIO_REG_C_H GPIOD -#define SWITCHES_GPIO_PIN_C_H LL_GPIO_PIN_11 // PD.11 -#define SWITCHES_GPIO_REG_C_L GPIOB -#define SWITCHES_GPIO_PIN_C_L LL_GPIO_PIN_15 // PB.15 -#define STORAGE_SWITCH_D -#define HARDWARE_SWITCH_D -#define SWITCHES_GPIO_REG_D_H GPIOJ -#define SWITCHES_GPIO_PIN_D_H LL_GPIO_PIN_7 // PJ.07 -#define SWITCHES_GPIO_REG_D_L GPIOG -#define SWITCHES_GPIO_PIN_D_L LL_GPIO_PIN_2 // PG.02 -#define STORAGE_SWITCH_E -#define HARDWARE_SWITCH_E -#define SWITCHES_GPIO_REG_E_H GPIOH -#define SWITCHES_GPIO_PIN_E_H LL_GPIO_PIN_4 // PH.04 -#define SWITCHES_GPIO_REG_E_L GPIOE -#define SWITCHES_GPIO_PIN_E_L LL_GPIO_PIN_3 // PE.03 -#define STORAGE_SWITCH_F -#define HARDWARE_SWITCH_F -#define SWITCHES_GPIO_REG_F GPIOH -#define SWITCHES_GPIO_PIN_F LL_GPIO_PIN_3 // PH.03 -#define STORAGE_SWITCH_G -#define HARDWARE_SWITCH_G -#define SWITCHES_GPIO_REG_G_H GPIOG -#define SWITCHES_GPIO_PIN_G_H LL_GPIO_PIN_6 // PG.06 -#define SWITCHES_GPIO_REG_G_L GPIOG -#define SWITCHES_GPIO_PIN_G_L LL_GPIO_PIN_3 // PG.03 -#define STORAGE_SWITCH_H -#define HARDWARE_SWITCH_H -#define SWITCHES_GPIO_REG_H GPIOG -#define SWITCHES_GPIO_PIN_H LL_GPIO_PIN_7 // PG.07 +#if defined(RADIO_T15) + #define STORAGE_SWITCH_A + #define HARDWARE_SWITCH_A + #define SWITCHES_GPIO_REG_A_H GPIOG + #define SWITCHES_GPIO_PIN_A_H LL_GPIO_PIN_3 // PG.03 + #define SWITCHES_GPIO_REG_A_L GPIOD + #define SWITCHES_GPIO_PIN_A_L LL_GPIO_PIN_11 // PD.11 + #define SWITCHES_A_INVERTED -#if defined(PCBX12S) - #define SWITCHES_F_INVERTED -#elif defined(PCBX10) - #define SWITCHES_B_INVERTED - #define SWITCHES_D_INVERTED - #define SWITCHES_E_INVERTED -#endif + #define STORAGE_SWITCH_B + #define HARDWARE_SWITCH_B + #define SWITCHES_GPIO_REG_B_H GPIOB + #define SWITCHES_GPIO_PIN_B_H LL_GPIO_PIN_12 // PB.12 + #define SWITCHES_GPIO_REG_B_L GPIOH + #define SWITCHES_GPIO_PIN_B_L LL_GPIO_PIN_9 // PH.09 -#if defined(PCBX10) - // Gimbal switch left + #define STORAGE_SWITCH_C + #define HARDWARE_SWITCH_C + #define SWITCHES_GPIO_REG_C_H GPIOG + #define SWITCHES_GPIO_PIN_C_H LL_GPIO_PIN_2 // PG.02 + #define SWITCHES_GPIO_REG_C_L GPIOH + #define SWITCHES_GPIO_PIN_C_L LL_GPIO_PIN_14 // PH.14 + #define SWITCHES_C_INVERTED + + #define STORAGE_SWITCH_D + #define HARDWARE_SWITCH_D + #define SWITCHES_GPIO_REG_D_H GPIOI + #define SWITCHES_GPIO_PIN_D_H LL_GPIO_PIN_15 // PI.15 + #define SWITCHES_GPIO_REG_D_L GPIOH + #define SWITCHES_GPIO_PIN_D_L LL_GPIO_PIN_15 // PH.15 + + #define STORAGE_SWITCH_E + #define HARDWARE_SWITCH_E + #define SWITCHES_GPIO_REG_E GPIOB + #define SWITCHES_GPIO_PIN_E LL_GPIO_PIN_15 // PB.15 + #define STORAGE_SWITCH_F + #define HARDWARE_SWITCH_F + #define SWITCHES_GPIO_REG_F GPIOH + #define SWITCHES_GPIO_PIN_F LL_GPIO_PIN_12 // PH.12 + //SW1 + #define FUNCTION_SWITCH_1 SG + #define STORAGE_SWITCH_G + #define HARDWARE_SWITCH_G + #define SWITCHES_GPIO_REG_G GPIOB + #define SWITCHES_GPIO_PIN_G LL_GPIO_PIN_14 // PB.14 + //SW2 + #define FUNCTION_SWITCH_2 SH + #define STORAGE_SWITCH_H + #define HARDWARE_SWITCH_H + #define SWITCHES_GPIO_REG_H GPIOD + #define SWITCHES_GPIO_PIN_H LL_GPIO_PIN_13 // PD.13 + //SW3 + #define FUNCTION_SWITCH_3 SI #define STORAGE_SWITCH_I #define HARDWARE_SWITCH_I - #define SWITCHES_GPIO_REG_I GPIOH - #define SWITCHES_GPIO_PIN_I LL_GPIO_PIN_14 // PH.14 - // Gimbal switch right + #define SWITCHES_GPIO_REG_I GPIOJ + #define SWITCHES_GPIO_PIN_I LL_GPIO_PIN_7 // PJ.07 + //SW4 + #define FUNCTION_SWITCH_4 SJ #define STORAGE_SWITCH_J #define HARDWARE_SWITCH_J - #define SWITCHES_GPIO_REG_J GPIOH - #define SWITCHES_GPIO_PIN_J LL_GPIO_PIN_15 // PH.15 -#elif defined(PCBX12S) + #define SWITCHES_GPIO_REG_J GPIOG + #define SWITCHES_GPIO_PIN_J LL_GPIO_PIN_13 // PG.13 + //SW5 + #define FUNCTION_SWITCH_5 SK + #define STORAGE_SWITCH_K + #define HARDWARE_SWITCH_K + #define SWITCHES_GPIO_REG_K GPIOJ + #define SWITCHES_GPIO_PIN_K LL_GPIO_PIN_8 // PJ.08 + //SW6 + #define FUNCTION_SWITCH_6 SL + #define STORAGE_SWITCH_L + #define HARDWARE_SWITCH_L + #define SWITCHES_GPIO_REG_L GPIOB + #define SWITCHES_GPIO_PIN_L LL_GPIO_PIN_13 // PB.13 +#else + #define STORAGE_SWITCH_A + #define HARDWARE_SWITCH_A + #define SWITCHES_GPIO_REG_A_H GPIOH + #define SWITCHES_GPIO_PIN_A_H LL_GPIO_PIN_9 // PH.09 + #define SWITCHES_GPIO_REG_A_L GPIOI + #define SWITCHES_GPIO_PIN_A_L LL_GPIO_PIN_15 // PI.15 + #define STORAGE_SWITCH_B + #define HARDWARE_SWITCH_B + #define SWITCHES_GPIO_REG_B_H GPIOH + #define SWITCHES_GPIO_PIN_B_H LL_GPIO_PIN_12 // PH.12 + #define SWITCHES_GPIO_REG_B_L GPIOB + #define SWITCHES_GPIO_PIN_B_L LL_GPIO_PIN_12 // PB.12 + #define STORAGE_SWITCH_C + #define HARDWARE_SWITCH_C + #define SWITCHES_GPIO_REG_C_H GPIOD + #define SWITCHES_GPIO_PIN_C_H LL_GPIO_PIN_11 // PD.11 + #define SWITCHES_GPIO_REG_C_L GPIOB + #define SWITCHES_GPIO_PIN_C_L LL_GPIO_PIN_15 // PB.15 + #define STORAGE_SWITCH_D + #define HARDWARE_SWITCH_D + #define SWITCHES_GPIO_REG_D_H GPIOJ + #define SWITCHES_GPIO_PIN_D_H LL_GPIO_PIN_7 // PJ.07 + #define SWITCHES_GPIO_REG_D_L GPIOG + #define SWITCHES_GPIO_PIN_D_L LL_GPIO_PIN_2 // PG.02 + #define STORAGE_SWITCH_E + #define HARDWARE_SWITCH_E + #define SWITCHES_GPIO_REG_E_H GPIOH + #define SWITCHES_GPIO_PIN_E_H LL_GPIO_PIN_4 // PH.04 + #define SWITCHES_GPIO_REG_E_L GPIOE + #define SWITCHES_GPIO_PIN_E_L LL_GPIO_PIN_3 // PE.03 + #define STORAGE_SWITCH_F + #define HARDWARE_SWITCH_F + #define SWITCHES_GPIO_REG_F GPIOH + #define SWITCHES_GPIO_PIN_F LL_GPIO_PIN_3 // PH.03 + #define STORAGE_SWITCH_G + #define HARDWARE_SWITCH_G + #define SWITCHES_GPIO_REG_G_H GPIOG + #define SWITCHES_GPIO_PIN_G_H LL_GPIO_PIN_6 // PG.06 + #define SWITCHES_GPIO_REG_G_L GPIOG + #define SWITCHES_GPIO_PIN_G_L LL_GPIO_PIN_3 // PG.03 + #define STORAGE_SWITCH_H + #define HARDWARE_SWITCH_H + #define SWITCHES_GPIO_REG_H GPIOG + #define SWITCHES_GPIO_PIN_H LL_GPIO_PIN_7 // PG.07 + + #if defined(PCBX12S) + #define SWITCHES_F_INVERTED + #elif defined(PCBX10) + #define SWITCHES_B_INVERTED + #define SWITCHES_D_INVERTED + #define SWITCHES_E_INVERTED + #endif + + #if defined(PCBX10) // Gimbal switch left - #define STORAGE_SWITCH_I - #define HARDWARE_SWITCH_I - #define SWITCHES_GPIO_REG_I GPIOB - #define SWITCHES_GPIO_PIN_I LL_GPIO_PIN_1 // PB.01 - // Gimbal switch right - #define STORAGE_SWITCH_J - #define HARDWARE_SWITCH_J - #define SWITCHES_GPIO_REG_J GPIOB - #define SWITCHES_GPIO_PIN_J LL_GPIO_PIN_0 // PB.00 + #define STORAGE_SWITCH_I + #define HARDWARE_SWITCH_I + #define SWITCHES_GPIO_REG_I GPIOH + #define SWITCHES_GPIO_PIN_I LL_GPIO_PIN_14 // PH.14 + // Gimbal switch right + #define STORAGE_SWITCH_J + #define HARDWARE_SWITCH_J + #define SWITCHES_GPIO_REG_J GPIOH + #define SWITCHES_GPIO_PIN_J LL_GPIO_PIN_15 // PH.15 + #elif defined(PCBX12S) + // Gimbal switch left + #define STORAGE_SWITCH_I + #define HARDWARE_SWITCH_I + #define SWITCHES_GPIO_REG_I GPIOB + #define SWITCHES_GPIO_PIN_I LL_GPIO_PIN_1 // PB.01 + // Gimbal switch right + #define STORAGE_SWITCH_J + #define HARDWARE_SWITCH_J + #define SWITCHES_GPIO_REG_J GPIOB + #define SWITCHES_GPIO_PIN_J LL_GPIO_PIN_0 // PB.00 + #endif #endif // Trims -#if defined(PCBX12S) +#if defined(RADIO_T15) + #define TRIMS_GPIO_REG_LHL GPIOD + #define TRIMS_GPIO_PIN_LHL LL_GPIO_PIN_3 // PD.03 + #define TRIMS_GPIO_REG_LHR GPIOD + #define TRIMS_GPIO_PIN_LHR LL_GPIO_PIN_7 // PD.07 + #define TRIMS_GPIO_REG_LVU GPIOJ + #define TRIMS_GPIO_PIN_LVU LL_GPIO_PIN_12 // PJ.12 + #define TRIMS_GPIO_REG_LVD GPIOJ + #define TRIMS_GPIO_PIN_LVD LL_GPIO_PIN_13 // PJ.13 + #define TRIMS_GPIO_REG_RVD GPIOG + #define TRIMS_GPIO_PIN_RVD LL_GPIO_PIN_12 // PG.12 + #define TRIMS_GPIO_REG_RHL GPIOA + #define TRIMS_GPIO_PIN_RHL LL_GPIO_PIN_6 // PA.06 + #define TRIMS_GPIO_REG_RVU GPIOJ + #define TRIMS_GPIO_PIN_RVU LL_GPIO_PIN_14 // PJ.14 + #define TRIMS_GPIO_REG_RHR GPIOC + #define TRIMS_GPIO_PIN_RHR LL_GPIO_PIN_4 // PC.04 +#elif defined(PCBX12S) #define TRIMS_GPIO_REG_RHL GPIOC #define TRIMS_GPIO_PIN_RHL LL_GPIO_PIN_0 // PC.00 #define TRIMS_GPIO_REG_RHR GPIOI @@ -287,21 +398,36 @@ #define ADC_SAMPTIME LL_ADC_SAMPLINGTIME_56CYCLES #define ADC_VREF_PREC2 600 #elif defined(PCBX10) +#if defined(RADIO_T15) + #define ADC_GPIO_PIN_STICK_LH LL_GPIO_PIN_1 // PA.01 + #define ADC_GPIO_PIN_STICK_LV LL_GPIO_PIN_0 // PA.00 + #define ADC_GPIO_PIN_STICK_RV LL_GPIO_PIN_2 // PA.02 + #define ADC_GPIO_PIN_STICK_RH LL_GPIO_PIN_3 // PA.03 + #define ADC_GPIO_PIN_POT1 LL_GPIO_PIN_2 // PC.02 + #define ADC_GPIO_PIN_POT2 LL_GPIO_PIN_0 // PC.00 + #define ADC_CHANNEL_POT1 LL_ADC_CHANNEL_12 // ADC3_IN12 + #define ADC_CHANNEL_POT2 LL_ADC_CHANNEL_10 // ADC3_IN10 +#else #define ADC_GPIO_PIN_STICK_LH LL_GPIO_PIN_0 // PA.00 #define ADC_GPIO_PIN_STICK_LV LL_GPIO_PIN_1 // PA.01 #define ADC_GPIO_PIN_STICK_RV LL_GPIO_PIN_3 // PA.03 #define ADC_GPIO_PIN_STICK_RH LL_GPIO_PIN_2 // PA.02 #define ADC_GPIO_PIN_POT1 LL_GPIO_PIN_0 // PC.00 #define ADC_GPIO_PIN_POT2 LL_GPIO_PIN_1 // PC.01 + #define ADC_CHANNEL_POT1 LL_ADC_CHANNEL_10 // ADC3_IN10 + #define ADC_CHANNEL_POT2 LL_ADC_CHANNEL_11 // ADC3_IN11 +#endif + #define ADC_GPIO_PIN_BATT LL_GPIO_PIN_7 // PF.07 +#if !defined(RADIO_T15) #define ADC_GPIO_PIN_POT3 LL_GPIO_PIN_2 // PC.02 // #define ADC_GPIO_PIN_SLIDER1 LL_GPIO_PIN_6 // PF.06 #define ADC_GPIO_PIN_SLIDER2 LL_GPIO_PIN_3 // PC.03 // - #define ADC_GPIO_PIN_BATT LL_GPIO_PIN_7 // PF.07 #define ADC_GPIO_PIN_EXT1 LL_GPIO_PIN_8 // PF.08 #define ADC_GPIO_PIN_EXT2 LL_GPIO_PIN_9 // PF.09 #define ADC_GPIO_PIN_EXT3 ADC_GPIO_PIN_STICK_RH #define ADC_GPIO_PIN_EXT4 ADC_GPIO_PIN_STICK_RV - #if !defined(RADIO_TX16S) +#endif + #if !defined(RADIO_TX16S) && !defined(RADIO_T15) #define PWM_STICKS #define PWM_TIMER TIM5 #define PWM_GPIO GPIOA @@ -314,24 +440,38 @@ #define STICK_PWM_CHANNEL_RV 3 #define STICK_PWM_CHANNEL_RH 2 #endif - #define ADC_GPIOA_PINS_FS (LL_GPIO_PIN_2 | LL_GPIO_PIN_3) - #define ADC_GPIOA_PINS (ADC_GPIO_PIN_STICK_LH | ADC_GPIO_PIN_STICK_LV | ADC_GPIO_PIN_STICK_RH | ADC_GPIO_PIN_STICK_RV) - #define ADC_GPIOC_PINS (ADC_GPIO_PIN_POT1 | ADC_GPIO_PIN_POT2 | ADC_GPIO_PIN_POT3 | ADC_GPIO_PIN_SLIDER2) - #define ADC_GPIOF_PINS (ADC_GPIO_PIN_SLIDER1 | ADC_GPIO_PIN_BATT | ADC_GPIO_PIN_EXT1 | ADC_GPIO_PIN_EXT2) +#if defined(RADIO_T15) + #define ADC_CHANNEL_STICK_LH LL_ADC_CHANNEL_1 // ADC3_IN1 + #define ADC_CHANNEL_STICK_LV LL_ADC_CHANNEL_0 // ADC3_IN0 + #define ADC_CHANNEL_STICK_RH LL_ADC_CHANNEL_3 // ADC3_IN3 + #define ADC_CHANNEL_STICK_RV LL_ADC_CHANNEL_2 // ADC3_IN2 + #define ADC_CHANNEL_BATT LL_ADC_CHANNEL_5 // ADC3_IN5 +#else #define ADC_CHANNEL_STICK_LH LL_ADC_CHANNEL_0 // ADC3_IN0 #define ADC_CHANNEL_STICK_LV LL_ADC_CHANNEL_1 // ADC3_IN1 #define ADC_CHANNEL_STICK_RH LL_ADC_CHANNEL_2 // ADC3_IN2 #define ADC_CHANNEL_STICK_RV LL_ADC_CHANNEL_3 // ADC3_IN3 - #define ADC_CHANNEL_POT1 LL_ADC_CHANNEL_10 // ADC3_IN10 - #define ADC_CHANNEL_POT2 LL_ADC_CHANNEL_11 // ADC3_IN11 + #define ADC_CHANNEL_BATT LL_ADC_CHANNEL_5 // ADC3_IN5 +#endif +#if !defined(RADIO_T15) #define ADC_CHANNEL_POT3 LL_ADC_CHANNEL_12 // ADC3_IN12 #define ADC_CHANNEL_SLIDER1 LL_ADC_CHANNEL_4 // ADC3_IN4 #define ADC_CHANNEL_SLIDER2 LL_ADC_CHANNEL_13 // ADC3_IN13 - #define ADC_CHANNEL_BATT LL_ADC_CHANNEL_5 // ADC3_IN5 #define ADC_CHANNEL_EXT1 LL_ADC_CHANNEL_6 // ADC3_IN6 #define ADC_CHANNEL_EXT2 LL_ADC_CHANNEL_7 // ADC3_IN7 #define ADC_CHANNEL_EXT3 LL_ADC_CHANNEL_2 // ADC3_IN2: same as RH #define ADC_CHANNEL_EXT4 LL_ADC_CHANNEL_3 // ADC3_IN3: same as RV +#endif +#if defined(RADIO_T15) + #define ADC_GPIOA_PINS (ADC_GPIO_PIN_STICK_LH | ADC_GPIO_PIN_STICK_LV | ADC_GPIO_PIN_STICK_RH | ADC_GPIO_PIN_STICK_RV) + #define ADC_GPIOC_PINS (ADC_GPIO_PIN_POT1 | ADC_GPIO_PIN_POT2) + #define ADC_GPIOF_PINS (ADC_GPIO_PIN_BATT) +#else + #define ADC_GPIOA_PINS_FS (LL_GPIO_PIN_2 | LL_GPIO_PIN_3) + #define ADC_GPIOA_PINS (ADC_GPIO_PIN_STICK_LH | ADC_GPIO_PIN_STICK_LV | ADC_GPIO_PIN_STICK_RH | ADC_GPIO_PIN_STICK_RV) + #define ADC_GPIOC_PINS (ADC_GPIO_PIN_POT1 | ADC_GPIO_PIN_POT2 | ADC_GPIO_PIN_POT3 | ADC_GPIO_PIN_SLIDER2) + #define ADC_GPIOF_PINS (ADC_GPIO_PIN_SLIDER1 | ADC_GPIO_PIN_BATT | ADC_GPIO_PIN_EXT1 | ADC_GPIO_PIN_EXT2) +#endif #define ADC_CHANNEL_RTC_BAT LL_ADC_CHANNEL_VBAT // ADC1_IN18 #define ADC_MAIN ADC3 #define ADC_EXT ADC1 @@ -345,7 +485,7 @@ #define ADC_DMA_STREAM_IRQHandler DMA2_Stream0_IRQHandler // VBat divider is /4 on F42x and F43x devices - #if defined(RADIO_TX16S) + #if defined(RADIO_TX16S) || defined(RADIO_T15) #define ADC_VREF_PREC2 660 #elif defined(RADIO_T16) || defined(RADIO_T18) #define ADC_VREF_PREC2 600 @@ -354,7 +494,9 @@ #endif #endif -#if defined(RADIO_T16) +#if defined(RADIO_T15) + #define ADC_DIRECTION {1,-1,1,-1, 1,1} +#elif defined(RADIO_T16) #define ADC_DIRECTION {1,-1,1,-1, 1,1,1, -1,1,1,1, -1,1 } #elif defined(RADIO_T18) #define ADC_DIRECTION {1,-1,1,-1, -1,1,-1, -1,1,1,1, -1,1 } @@ -392,12 +534,16 @@ #define SPORT_MAX_BAUDRATE 250000 // < 400000 #endif -#if defined(PCBX10) && !defined(RADIO_FAMILY_T16) +#if defined(PCBX10) && !defined(RADIO_FAMILY_T16) && !defined(RADIO_T15) #define SPORT_UPDATE_PWR_GPIO GPIO_PIN(GPIOH, 13) // PH.13 #endif // PCBREV -#if defined(PCBX10) +#if defined(RADIO_T15) + #define PCBREV_GPIO_1 GPIO_PIN(GPIOH, 7) // PH.07 + #define PCBREV_GPIO_2 GPIO_PIN(GPIOH, 8) // PH.08 + #define PCBREV_VALUE() ((gpio_read(PCBREV_GPIO_1) | gpio_read(PCBREV_GPIO_2)) >> 7) +#elif defined(PCBX10) #define PCBREV_GPIO_1 GPIO_PIN(GPIOH, 7) // PH.07 #define PCBREV_GPIO_2 GPIO_PIN(GPIOH, 8) // PH.08 #define PCBREV_TOUCH_GPIO GPIO_PIN(GPIOA, 6) // PA.06 @@ -412,12 +558,26 @@ #define STATUS_LEDS #if defined(PCBX12S) #define LED_GPIO GPIO_PIN(GPIOI, 5) // PI.05 +#elif defined(RADIO_T15) + #define LED_RED_GPIO GPIO_PIN(GPIOI, 14) //PI.14 + #define LED_GREEN_GPIO GPIO_PIN(GPIOC, 13) //PC.13 + #define LED_BLUE_GPIO GPIO_PIN(GPIOE, 3) //PE.03 #elif defined(PCBX10) #define LED_RED_GPIO GPIO_PIN(GPIOE, 2) // PE.02 #define LED_GREEN_GPIO GPIO_PIN(GPIOE, 4) // PE.04 #define LED_BLUE_GPIO GPIO_PIN(GPIOE, 5) // PE.05 #endif +// Customisable switches leds +#if defined(RADIO_T15) +#define FSLED_GPIO_1 GPIO_PIN(GPIOA, 15) //PA.15 +#define FSLED_GPIO_2 GPIO_PIN(GPIOC, 5) //PC.05 +#define FSLED_GPIO_3 GPIO_PIN(GPIOH, 13) //PH.13 +#define FSLED_GPIO_4 GPIO_PIN(GPIOG, 11) //PG.11 +#define FSLED_GPIO_5 GPIO_PIN(GPIOC, 3) //PC.03 +#define FSLED_GPIO_6 GPIO_PIN(GPIOC, 1) //PC.01 +#endif + // Serial Port (DEBUG) #if defined(AUX_SERIAL) #define AUX_SERIAL_TX_GPIO GPIO_PIN(GPIOB, 10) // PB.10 @@ -507,6 +667,20 @@ #define USB_GPIO_AF GPIO_AF10 // LCD +#if defined(RADIO_T15) + #define LCD_RCC_AHB1Periph (LL_AHB1_GRP1_PERIPH_GPIOE | LL_AHB1_GRP1_PERIPH_GPIOG | LL_AHB1_GRP1_PERIPH_GPIOI | LL_AHB1_GRP1_PERIPH_GPIOJ | LL_AHB1_GRP1_PERIPH_GPIOK | LL_AHB1_GRP1_PERIPH_DMA2D) + #define LCD_RCC_APB1Periph 0 + #define LCD_RCC_APB2Periph LL_APB2_GRP1_PERIPH_LTDC + #define LCD_NRST_GPIO GPIOG + #define LCD_NRST_GPIO_PIN LL_GPIO_PIN_10 // PG.10 + #define LCD_SPI_GPIO GPIOE + #define LCD_SPI_CS_GPIO_PIN LL_GPIO_PIN_4 // PE.04 + #define LCD_SPI_SCK_GPIO_PIN LL_GPIO_PIN_2 // PE.02 + #define LCD_SPI_MISO_GPIO_PIN LL_GPIO_PIN_5 // PE.05 + #define LCD_SPI_MOSI_GPIO_PIN LL_GPIO_PIN_6 // PE.06 + #define LTDC_IRQ_PRIO 4 + #define DMA_SCREEN_IRQ_PRIO 6 +#else #define LCD_RCC_AHB1Periph LL_AHB1_GRP1_PERIPH_DMA2D #define LCD_RCC_APB2Periph LL_APB2_GRP1_PERIPH_LTDC #if defined(PCBX12S) @@ -519,6 +693,7 @@ #endif #define LTDC_IRQ_PRIO 4 #define DMA_SCREEN_IRQ_PRIO 6 +#endif // Backlight #if defined(PCBX12S) @@ -545,7 +720,9 @@ #endif // SD +#if !defined(RADIO_T15) #define SD_PRESENT_GPIO GPIO_PIN(GPIOC, 5) // PC.05 +#endif #define SD_SDIO_DMA DMA2 #define SD_SDIO_DMA_STREAM DMA2_Stream3 // or Stream6 #define SD_SDIO_DMA_CHANNEL LL_DMA_CHANNEL_4 @@ -675,7 +852,7 @@ #endif // HARDWARE_TOUCH // First I2C Bus -#if defined(RADIO_TX16S) || defined(PCBX12S) +#if defined(RADIO_TX16S) || defined(PCBX12S) || defined(RADIO_T15) #define I2C_B1 I2C1 #define I2C_B1_GPIO GPIOB #define I2C_B1_SCL_GPIO_PIN LL_GPIO_PIN_8 // PB.08 @@ -722,6 +899,13 @@ #define HAPTIC_TIMER_OUTPUT_ENABLE TIM_CCER_CC1E #define HAPTIC_TIMER_MODE TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 #define HAPTIC_TIMER_COMPARE_VALUE HAPTIC_GPIO_TIMER->CCR1 +#elif defined(RADIO_T15) // TIM2_CH1 + #define HAPTIC_GPIO GPIO_PIN(GPIOA, 5) // PA.05 + #define HAPTIC_GPIO_TIMER TIM2 + #define HAPTIC_GPIO_AF GPIO_AF1 + #define HAPTIC_TIMER_OUTPUT_ENABLE TIM_CCER_CC1E | TIM_CCER_CC1NE; + #define HAPTIC_TIMER_MODE TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1PE + #define HAPTIC_TIMER_COMPARE_VALUE HAPTIC_GPIO_TIMER->CCR1 #elif defined(PCBX10) #define HAPTIC_GPIO GPIO_PIN(GPIOE, 6) // PE.06 #define HAPTIC_GPIO_TIMER TIM9 @@ -904,10 +1088,18 @@ #define PORTRAIT_LCD false #define LANDSCAPE_LCD true +#if defined(RADIO_T15) +#define LCD_W 480 +#define LCD_H 320 +#define LCD_PHYS_H LCD_H +#define LCD_PHYS_W LCD_W +#define LCD_DEPTH 16 +#else #define LCD_W 480 #define LCD_H 272 #define LCD_PHYS_H LCD_H #define LCD_PHYS_W LCD_W #define LCD_DEPTH 16 +#endif #endif // _HAL_H_ diff --git a/radio/src/targets/horus/lcd_st7796s_driver.cpp b/radio/src/targets/horus/lcd_st7796s_driver.cpp new file mode 100644 index 00000000000..3d9b12af083 --- /dev/null +++ b/radio/src/targets/horus/lcd_st7796s_driver.cpp @@ -0,0 +1,460 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "lcd_st7796s_driver.h" + +#include "board.h" +#include "debug.h" +#include "delays_driver.h" +#include "dma2d.h" +#include "hal.h" +#include "lcd.h" +#include "opentx_types.h" +#include "stm32_hal.h" +#include "stm32_hal_ll.h" + +static LTDC_HandleTypeDef hltdc; +static void* initialFrameBuffer = nullptr; + +static volatile uint8_t _frame_addr_reloaded = 0; + +static void startLcdRefresh(lv_disp_drv_t* disp_drv, uint16_t* buffer, + const rect_t& copy_area) +{ + (void)disp_drv; + (void)copy_area; + + LTDC_Layer1->CFBAR &= ~(LTDC_LxCFBAR_CFBADD); + LTDC_Layer1->CFBAR = (uint32_t)buffer; + // reload shadow registers on vertical blank + _frame_addr_reloaded = 0; + LTDC->SRCR = LTDC_SRCR_VBR; + __HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI); + + // wait for reload + // TODO: replace through some smarter mechanism without busy wait + while (_frame_addr_reloaded == 0); +} + +uint32_t lcdPixelClock; + +static void LCD_AF_GPIOConfig(void) +{ + /* + ----------------------------------------------------------------------------- + LCD_CLK <-> PG.07 | LCD_HSYNC <-> PI.12 | LCD_R3 <-> PJ.02 | LCD_G5 <-> PK.00 + | LCD VSYNC <-> PI.13 | LCD_R4 <-> PJ.03 | LCD_G6 <-> PK.01 + | | LCD_R5 <-> PJ.04 | LCD_G7 <-> PK.02 + | | LCD_R6 <-> PJ.05 | LCD_B4 <-> PK.03 + | | LCD_R7 <-> PJ.06 | LCD_B5 <-> PK.04 + | | LCD_G2 <-> PJ.09 | LCD_B6 <-> PK.05 + | | LCD_G3 <-> PJ.10 | LCD_B7 <-> PK.06 + | | LCD_G4 <-> PJ.11 | LCD_DE <-> PK.07 + | | LCD_B3 <-> PJ.15 | + */ + + LL_GPIO_InitTypeDef GPIO_InitStructure; + LL_GPIO_StructInit(&GPIO_InitStructure); + + // GPIOG configuration + GPIO_InitStructure.Pin = LL_GPIO_PIN_7; + GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStructure.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStructure.Pull = LL_GPIO_PULL_NO; + GPIO_InitStructure.Alternate = LL_GPIO_AF_14; // AF LTDC + LL_GPIO_Init(GPIOG, &GPIO_InitStructure); + + // GPIOI configuration + GPIO_InitStructure.Pin = LL_GPIO_PIN_12 | LL_GPIO_PIN_13; + LL_GPIO_Init(GPIOI, &GPIO_InitStructure); + + // GPIOJ configuration + GPIO_InitStructure.Pin = LL_GPIO_PIN_2 | LL_GPIO_PIN_3 | LL_GPIO_PIN_4 | + LL_GPIO_PIN_5 | LL_GPIO_PIN_6 | LL_GPIO_PIN_9 | + LL_GPIO_PIN_10 | LL_GPIO_PIN_11 | LL_GPIO_PIN_15; + LL_GPIO_Init(GPIOJ, &GPIO_InitStructure); + + // GPIOK configuration + GPIO_InitStructure.Pin = LL_GPIO_PIN_0 | LL_GPIO_PIN_1 | LL_GPIO_PIN_2 | + LL_GPIO_PIN_3 | LL_GPIO_PIN_4 | LL_GPIO_PIN_5 | + LL_GPIO_PIN_6 | LL_GPIO_PIN_7; + LL_GPIO_Init(GPIOK, &GPIO_InitStructure); +} + +static void lcdSpiConfig(void) +{ + LL_GPIO_InitTypeDef GPIO_InitStructure; + LL_GPIO_StructInit(&GPIO_InitStructure); + + GPIO_InitStructure.Pin = LCD_SPI_SCK_GPIO_PIN | LCD_SPI_MOSI_GPIO_PIN; + GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStructure.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStructure.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(LCD_SPI_GPIO, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = LCD_SPI_CS_GPIO_PIN; + GPIO_InitStructure.Pull = LL_GPIO_PULL_UP; + LL_GPIO_Init(LCD_SPI_GPIO, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = LCD_NRST_GPIO_PIN; + LL_GPIO_Init(LCD_NRST_GPIO, &GPIO_InitStructure); + + /* Set the chip select pin always low */ + LCD_CS_LOW(); +} + +void lcdDelay() { delay_01us(1); } + +static void lcdReset() +{ + LCD_NRST_HIGH(); + delay_ms(1); + + LCD_NRST_LOW(); // RESET(); + delay_ms(100); + + LCD_NRST_HIGH(); + delay_ms(100); +} + +static void lcdWriteByte(uint8_t data_enable, uint8_t byte) +{ + LCD_SCK_LOW(); + + if (data_enable) { + LCD_MOSI_HIGH(); + } else { + LCD_MOSI_LOW(); + } + + lcdDelay(); + LCD_SCK_HIGH(); + + for (int i = 0; i < 8; i++) { + lcdDelay(); + LCD_SCK_LOW(); + + if (byte & 0x80) { + LCD_MOSI_HIGH(); + } else { + LCD_MOSI_LOW(); + } + + lcdDelay(); + LCD_SCK_HIGH(); + byte <<= 1; + } + + lcdDelay(); + LCD_SCK_LOW(); +} + +void lcdWriteCommand(uint8_t command) +{ + LCD_CS_LOW(); + lcdWriteByte(0, command); + LCD_CS_HIGH(); + lcdDelay(); +} + +void lcdWriteData(uint8_t data) +{ + LCD_CS_LOW(); + lcdWriteByte(1, data); + LCD_CS_HIGH(); + lcdDelay(); +} + +void LCD_ST7796S_On(void) { lcdWriteCommand(0x29); } + +void LCD_ST7796S_Init(void) +{ + delay_ms(120); + + lcdWriteCommand(0x11); + delay_ms(120); + + lcdWriteCommand(0xF0); + lcdWriteData(0xC3); + + lcdWriteCommand(0xF0); + lcdWriteData(0x96); + + lcdWriteCommand(0x36); + lcdWriteData(0x28); + + lcdWriteCommand(0x2A); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x01); + lcdWriteData(0xDF); + lcdWriteCommand(0x2B); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x01); + lcdWriteData(0x3F); + + lcdWriteCommand(0x3A); +#if defined(RADIO_T15) + lcdWriteData(0x55); +#else + lcdWriteData(0x66); +#endif + + lcdWriteCommand(0x34); + + // SET RGB STRAT + lcdWriteCommand(0xB0); // SET HS VS DE CLK 上升还是下降有效 + lcdWriteData(0x80); + + lcdWriteCommand(0xB4); + lcdWriteData(0x01); + + lcdWriteCommand(0xB6); + // lcdWriteData( 0x20 ); + // lcdWriteData( 0x02 ); + // lcdWriteData( 0x3B ); + lcdWriteData(0x20); + lcdWriteData(0x02); + lcdWriteData(0x3B); + // SET RGB END + + lcdWriteCommand(0xB7); + lcdWriteData(0xC6); + + lcdWriteCommand(0xB9); + lcdWriteData(0x02); + lcdWriteData(0xE0); + + lcdWriteCommand(0xC0); + lcdWriteData(0x80); + lcdWriteData(0x65); + + lcdWriteCommand(0xC1); + lcdWriteData(0x0D); + + lcdWriteCommand(0xC2); + lcdWriteData(0xA7); + + lcdWriteCommand(0xC5); + lcdWriteData(0x14); + + lcdWriteCommand(0xE8); + lcdWriteData(0x40); + lcdWriteData(0x8A); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x29); + lcdWriteData(0x19); + lcdWriteData(0xA5); + lcdWriteData(0x33); + + lcdWriteCommand(0xE0); + lcdWriteData(0xD0); + lcdWriteData(0x00); + lcdWriteData(0x04); + lcdWriteData(0x05); + lcdWriteData(0x04); + lcdWriteData(0x21); + lcdWriteData(0x25); + lcdWriteData(0x43); + lcdWriteData(0x3F); + lcdWriteData(0x37); + lcdWriteData(0x13); + lcdWriteData(0x13); + lcdWriteData(0x29); + lcdWriteData(0x32); + + lcdWriteCommand(0xE1); + lcdWriteData(0xD0); + lcdWriteData(0x04); + lcdWriteData(0x06); + lcdWriteData(0x09); + lcdWriteData(0x06); + lcdWriteData(0x03); + lcdWriteData(0x25); + lcdWriteData(0x32); + lcdWriteData(0x3E); + lcdWriteData(0x18); + lcdWriteData(0x15); + lcdWriteData(0x15); + lcdWriteData(0x2B); + lcdWriteData(0x30); + + lcdWriteCommand(0xF0); + lcdWriteData(0x3C); + + lcdWriteCommand(0xF0); + lcdWriteData(0x69); + + delay_ms(120); + +#if defined(RADIO_T15) + if (hardwareOptions.pcbrev == PCBREV_T15_IPS) lcdWriteCommand(0x21); +#endif + + LCD_ST7796S_On(); +} + +void LCD_ST7796S_Off(void) { lcdWriteCommand(0x28); } + +void LCD_Init_LTDC() +{ + hltdc.Instance = LTDC; + + /* Configure PLLSAI prescalers for LCD */ + /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */ + /* PLLSAI_VCO Output = PLLSAI_VCO Input * lcdPixelclock * 16 = XX Mhz */ + /* PLLLCDCLK = PLLSAI_VCO Output/PLL_LTDC = PLLSAI_VCO/4 = YY Mhz */ + /* LTDC clock frequency = PLLLCDCLK / RCC_PLLSAIDivR = YY/4 = lcdPixelClock + * Mhz */ + uint32_t clock = (lcdPixelClock * 16) / 1000000; // clock*16 in MHz + RCC_PeriphCLKInitTypeDef clkConfig; + clkConfig.PeriphClockSelection = RCC_PERIPHCLK_LTDC; + clkConfig.PLLSAI.PLLSAIN = clock; + clkConfig.PLLSAI.PLLSAIR = 4; + clkConfig.PLLSAIDivQ = 6; + clkConfig.PLLSAIDivR = RCC_PLLSAIDIVR_4; + HAL_RCCEx_PeriphCLKConfig(&clkConfig); + + /* LTDC Configuration + * *********************************************************/ + /* Polarity configuration */ + /* Initialize the horizontal synchronization polarity as active low */ + hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL; + /* Initialize the vertical synchronization polarity as active low */ + hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL; + /* Initialize the data enable polarity as active low */ + hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL; + /* Initialize the pixel clock polarity as input pixel clock */ + hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IIPC; + + /* Configure R,G,B component values for LCD background color */ + hltdc.Init.Backcolor.Red = 0; + hltdc.Init.Backcolor.Green = 0; + hltdc.Init.Backcolor.Blue = 0; + + /* Configure horizontal synchronization width */ + hltdc.Init.HorizontalSync = HSW; + /* Configure vertical synchronization height */ + hltdc.Init.VerticalSync = VSH; + /* Configure accumulated horizontal back porch */ + hltdc.Init.AccumulatedHBP = HBP; + /* Configure accumulated vertical back porch */ + hltdc.Init.AccumulatedVBP = VBP; + /* Configure accumulated active width */ + hltdc.Init.AccumulatedActiveW = LCD_H + HBP; + /* Configure accumulated active height */ + hltdc.Init.AccumulatedActiveH = LCD_W + VBP; + /* Configure total width */ + hltdc.Init.TotalWidth = LCD_H + HBP + HFP; + /* Configure total height */ + hltdc.Init.TotalHeigh = LCD_W + VBP + VFP; + + HAL_LTDC_Init(&hltdc); + + // Configure IRQ (line) + NVIC_SetPriority(LTDC_IRQn, LTDC_IRQ_PRIO); + NVIC_EnableIRQ(LTDC_IRQn); + + // Trigger on last line + HAL_LTDC_ProgramLineEvent(&hltdc, LCD_W); + __HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI); +} + +void LCD_LayerInit() +{ + auto& layer = hltdc.LayerCfg[0]; + + /* Windowing configuration */ + layer.WindowX0 = 0; + layer.WindowX1 = LCD_H; + layer.WindowY0 = 0; + layer.WindowY1 = LCD_W; + + /* Pixel Format configuration*/ + layer.PixelFormat = LTDC_PIXEL_FORMAT_RGB565; + + /* Alpha constant (255 totally opaque) */ + layer.Alpha = 255; + + /* Default Color configuration (configure A,R,G,B component values) */ + layer.Backcolor.Blue = 0; + layer.Backcolor.Green = 0; + layer.Backcolor.Red = 0; + layer.Alpha0 = 0; + + /* Configure blending factors */ + layer.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA; + layer.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA; + + layer.ImageWidth = LCD_H; + layer.ImageHeight = LCD_W; + + /* Start Address configuration : the LCD Frame buffer is defined on SDRAM w/ + * Offset */ + layer.FBStartAdress = (intptr_t)initialFrameBuffer; + + /* Initialize LTDC layer 1 */ + HAL_LTDC_ConfigLayer(&hltdc, &hltdc.LayerCfg[0], 0); + + /* dithering activation */ + HAL_LTDC_EnableDither(&hltdc); +} + +extern "C" void lcdSetInitalFrameBuffer(void* fbAddress) +{ + initialFrameBuffer = fbAddress; +} + +extern "C" void lcdInit(void) +{ + /* Configure the LCD SPI+RESET pins */ + lcdSpiConfig(); + + /* Reset the LCD --------------------------------------------------------*/ + lcdReset(); + + /* Configure the LCD Control pins */ + LCD_AF_GPIOConfig(); + + /* Send LCD initialization commands */ + lcdPixelClock = 12000000; + + LCD_ST7796S_Init(); + + LCD_Init_LTDC(); + LCD_LayerInit(); + + // Enable LCD display + __HAL_LTDC_ENABLE(&hltdc); + + lcdSetFlushCb(startLcdRefresh); +} + +extern "C" void LTDC_IRQHandler(void) +{ + __HAL_LTDC_CLEAR_FLAG(&hltdc, LTDC_FLAG_LI); + __HAL_LTDC_DISABLE_IT(&hltdc, LTDC_IT_LI); + _frame_addr_reloaded = 1; +} diff --git a/radio/src/targets/horus/lcd_st7796s_driver.h b/radio/src/targets/horus/lcd_st7796s_driver.h new file mode 100644 index 00000000000..678b0ca6d0e --- /dev/null +++ b/radio/src/targets/horus/lcd_st7796s_driver.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#define HBP (24) +#define VBP (10) + +#define HSW (4) +#define VSH (2) + +#define HFP (140 - HBP) +#define VFP (22 - VBP) + +#define SET_IO_INPUT(PORT, PIN) \ + LL_GPIO_SetPinMode(PORT, PIN, LL_GPIO_MODE_INPUT) +#define SET_IO_OUTPUT(PORT, PIN) \ + LL_GPIO_SetPinMode(PORT, PIN, LL_GPIO_MODE_OUTPUT) + +#define LCD_NRST_HIGH() LL_GPIO_SetOutputPin(LCD_NRST_GPIO, LCD_NRST_GPIO_PIN) +#define LCD_NRST_LOW() LL_GPIO_ResetOutputPin(LCD_NRST_GPIO, LCD_NRST_GPIO_PIN) + +#define LCD_CS_HIGH() LL_GPIO_SetOutputPin(LCD_SPI_GPIO, LCD_SPI_CS_GPIO_PIN) +#define LCD_CS_LOW() LL_GPIO_ResetOutputPin(LCD_SPI_GPIO, LCD_SPI_CS_GPIO_PIN) + +#define LCD_SCK_HIGH() LL_GPIO_SetOutputPin(LCD_SPI_GPIO, LCD_SPI_SCK_GPIO_PIN) +#define LCD_SCK_LOW() LL_GPIO_ResetOutputPin(LCD_SPI_GPIO, LCD_SPI_SCK_GPIO_PIN) + +#define LCD_MOSI_HIGH() \ + LL_GPIO_SetOutputPin(LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN) +#define LCD_MOSI_LOW() \ + LL_GPIO_ResetOutputPin(LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN) + +#define LCD_MOSI_AS_INPUT() SET_IO_INPUT(LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN) +#define LCD_MOSI_AS_OUTPUT() SET_IO_OUTPUT(LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN) + +#define LCD_READ_DATA_PIN() \ + LL_GPIO_IsInputPinSet(LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN) + +#define HORIZONTAL_SYNC_WIDTH (4) +#define HORIZONTAL_BACK_PORCH (24) +#define HORIZONTAL_FRONT_PORCH (140 - HORIZONTAL_BACK_PORCH) +#define VERTICAL_SYNC_HEIGHT (2) +#define VERTICAL_BACK_PORCH (10) +#define VERTICAL_FRONT_PORCH (22 - VERTICAL_BACK_PORCH) diff --git a/radio/src/targets/horus/led_driver.cpp b/radio/src/targets/horus/led_driver.cpp index c74297cdff2..53eca1ba531 100644 --- a/radio/src/targets/horus/led_driver.cpp +++ b/radio/src/targets/horus/led_driver.cpp @@ -38,8 +38,39 @@ void ledInit() #if defined(LED_BLUE_GPIO) gpio_init(LED_BLUE_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW); #endif + +#if defined(FUNCTION_SWITCHES) + gpio_init(FSLED_GPIO_1, GPIO_OUT, GPIO_PIN_SPEED_LOW); + gpio_init(FSLED_GPIO_2, GPIO_OUT, GPIO_PIN_SPEED_LOW); + gpio_init(FSLED_GPIO_3, GPIO_OUT, GPIO_PIN_SPEED_LOW); + gpio_init(FSLED_GPIO_4, GPIO_OUT, GPIO_PIN_SPEED_LOW); + gpio_init(FSLED_GPIO_5, GPIO_OUT, GPIO_PIN_SPEED_LOW); + gpio_init(FSLED_GPIO_6, GPIO_OUT, GPIO_PIN_SPEED_LOW); +#endif + +} + +#if defined(FUNCTION_SWITCHES) +gpio_t fsLeds[] = {FSLED_GPIO_1, FSLED_GPIO_2, + FSLED_GPIO_3, FSLED_GPIO_4, + FSLED_GPIO_5, FSLED_GPIO_6}; + +void fsLedOff(uint8_t index) +{ + gpio_clear(fsLeds[index]); } +void fsLedOn(uint8_t index) +{ + gpio_set(fsLeds[index]); +} + +bool getFSLedState(uint8_t index) +{ + return (gpio_read(fsLeds[index])); +} +#endif + #if defined(LED_GPIO) // Single GPIO for dual color LED diff --git a/radio/src/targets/horus/usb_descriptor.h b/radio/src/targets/horus/usb_descriptor.h index 70cac72bf4a..397adf9d3b9 100644 --- a/radio/src/targets/horus/usb_descriptor.h +++ b/radio/src/targets/horus/usb_descriptor.h @@ -26,6 +26,10 @@ #define USB_NAME "FrSky Horus" #define USB_MANUFACTURER 'F', 'r', 'S', 'k', 'y', ' ', ' ', ' ' /* 8 bytes */ #define USB_PRODUCT 'H', 'o', 'r', 'u', 's', ' ', ' ', ' ' /* 8 Bytes */ +#elif defined(RADIO_T15) + #define USB_NAME "Jumper T15" + #define USB_MANUFACTURER 'J', 'u', 'm', 'p', 'e', 'r', ' ', ' ' /* 8 bytes */ + #define USB_PRODUCT 'T', '1', '5', ' ', ' ', ' ', ' ', ' ' /* 8 Bytes */ #elif defined(RADIO_T16) #define USB_NAME "Jumper T16" #define USB_MANUFACTURER 'J', 'u', 'm', 'p', 'e', 'r', ' ', ' ' /* 8 bytes */ diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 0be92e2bc4b..239877dd6da 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -131,17 +131,6 @@ uint32_t isBootloaderStart(const uint8_t * buffer); #endif -#if defined(FUNCTION_SWITCHES) -extern uint8_t fsPreviousState; -void evalFunctionSwitches(); -void setFSStartupPosition(); -void fsLedOff(uint8_t); -void fsLedOn(uint8_t); -uint8_t getFSLogicalState(uint8_t index); -uint8_t getFSPhysicalState(uint8_t index); -bool getFSLedState(uint8_t index); -#endif - #if defined(ADC_GPIO_PIN_STICK_TH) #define SURFACE_RADIO true #endif diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index cd9961d053e..5619fd383eb 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -100,6 +100,9 @@ ISTR(ADCFILTERVALUES); ISTR(TIMER_DIR); ISTR(PREFLIGHT_POTSLIDER_CHECK); ISTR(PPMUNIT); +#if defined(FUNCTION_SWITCHES) +ISTR(FUNCTION_SWITCH_GROUPS); +#endif #if defined(HELI) ISTR(VSWASHTYPE); @@ -162,6 +165,12 @@ const char STR_REFRESHRATE[] = TR_REFRESHRATE; const char STR_MS[] = TR_MS; const char STR_SWITCH[] = TR_SWITCH; #if defined(FUNCTION_SWITCHES) +const char STR_GROUPS[] = TR_GROUPS; +const char STR_LAST[] = TR_LAST; +const char STR_MORE_INFO[] = TR_MORE_INFO; +const char STR_SWITCH_TYPE[] = TR_SWITCH_TYPE; +const char STR_SWITCH_GROUP[] = TR_SWITCH_GROUP; +const char STR_SWITCH_STARTUP[] = TR_SWITCH_STARTUP; const char STR_FUNCTION_SWITCHES[] = TR_FUNCTION_SWITCHES; const char STR_GROUP[] = TR_GROUP; const char STR_GROUP_ALWAYS_ON[] = TR_GROUP_ALWAYS_ON; diff --git a/radio/src/translations.h b/radio/src/translations.h index 454f824fc09..75694f3c8ad 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -290,6 +290,13 @@ extern const char STR_SWITCH[]; extern const char STR_FUNCTION_SWITCHES[]; extern const char STR_GROUP[]; extern const char STR_GROUP_ALWAYS_ON[]; +extern const char STR_GROUPS[]; +extern const char STR_LAST[]; +extern const char STR_MORE_INFO[]; +extern const char STR_SWITCH_TYPE[]; +extern const char STR_SWITCH_GROUP[]; +extern const char STR_SWITCH_STARTUP[]; +extern const char* const STR_FUNCTION_SWITCH_GROUPS[]; extern const char STR_ADJUST_GVAR[]; extern const char STR_PLAY_TRACK[]; extern const char STR_PLAY_VALUE[]; diff --git a/radio/src/translations/cn.h b/radio/src/translations/cn.h index 4ce872b6194..358bf84ac07 100644 --- a/radio/src/translations/cn.h +++ b/radio/src/translations/cn.h @@ -282,6 +282,15 @@ #define TR_FUNCTION_SWITCHES "可自定义开关" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Trigger" #define TR_TRIMS "微调" #define TR_FADEIN "渐入" diff --git a/radio/src/translations/cz.h b/radio/src/translations/cz.h index 23bf0207416..ee375b23974 100644 --- a/radio/src/translations/cz.h +++ b/radio/src/translations/cz.h @@ -297,6 +297,15 @@ #define TR_FUNCTION_SWITCHES "Nastavitelné přepínače" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Trigger" #define TR_TRIMS "Trimy" #define TR_FADEIN "Přechod Zap" diff --git a/radio/src/translations/da.h b/radio/src/translations/da.h index 2e0ced91652..8a662608c12 100644 --- a/radio/src/translations/da.h +++ b/radio/src/translations/da.h @@ -290,6 +290,15 @@ #define TR_FUNCTION_SWITCHES "Kontakter der kan tilpasses" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Udløser" #define TR_TRIMS "Trim" #define TR_FADEIN "Tone ind" diff --git a/radio/src/translations/de.h b/radio/src/translations/de.h index 02c2170fd06..1d1f3692182 100644 --- a/radio/src/translations/de.h +++ b/radio/src/translations/de.h @@ -288,6 +288,15 @@ #define TR_FUNCTION_SWITCHES "Anpassbare Schalter" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Trigger" #define TR_TRIMS "Trimmer" #define TR_FADEIN "Langs. Ein" diff --git a/radio/src/translations/en.h b/radio/src/translations/en.h index 0025bb6a582..6bc77a9f4e4 100644 --- a/radio/src/translations/en.h +++ b/radio/src/translations/en.h @@ -287,6 +287,13 @@ #define TR_FUNCTION_SWITCHES "Customizable Switches" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Trigger" #define TR_TRIMS "Trims" #define TR_FADEIN "Fade in" diff --git a/radio/src/translations/es.h b/radio/src/translations/es.h index 80e86f319e4..f7babb5357a 100644 --- a/radio/src/translations/es.h +++ b/radio/src/translations/es.h @@ -285,6 +285,15 @@ #define TR_FUNCTION_SWITCHES "Customizable switches" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Trigger" #define TR_TRIMS "Trims" #define TR_FADEIN "Inicio" diff --git a/radio/src/translations/fi.h b/radio/src/translations/fi.h index 5d55421a863..8f39c471611 100644 --- a/radio/src/translations/fi.h +++ b/radio/src/translations/fi.h @@ -299,6 +299,15 @@ #define TR_FUNCTION_SWITCHES "Customizable switches" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Trigger" #define TR_TRIMS "Trims" #define TR_FADEIN "Fade In" diff --git a/radio/src/translations/fr.h b/radio/src/translations/fr.h index 875fee0ef6c..fe449051be8 100644 --- a/radio/src/translations/fr.h +++ b/radio/src/translations/fr.h @@ -292,6 +292,15 @@ #define TR_MS "ms" #define TR_SWITCH TR("Inter", "Interrupteur") #define TR_FUNCTION_SWITCHES "Inters paramétrables" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Interrupteur" #define TR_TRIMS "Trims" #define TR_FADEIN "Fondu ON" diff --git a/radio/src/translations/he.h b/radio/src/translations/he.h index 415cee6052c..cbc197f1b69 100644 --- a/radio/src/translations/he.h +++ b/radio/src/translations/he.h @@ -291,6 +291,15 @@ #define TR_FUNCTION_SWITCHES "מפסקים בהתאמה אישית" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "הדק" #define TR_TRIMS "קיזוזים" #define TR_FADEIN "Fade in" diff --git a/radio/src/translations/it.h b/radio/src/translations/it.h index 15f6531199f..451417e5b64 100644 --- a/radio/src/translations/it.h +++ b/radio/src/translations/it.h @@ -287,6 +287,15 @@ #define TR_FUNCTION_SWITCHES "Interruttori personalizzabili" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Trigger" #define TR_TRIMS "Trims" #define TR_FADEIN "Diss.In" diff --git a/radio/src/translations/jp.h b/radio/src/translations/jp.h index 44658bbe39c..5a120e297e5 100644 --- a/radio/src/translations/jp.h +++ b/radio/src/translations/jp.h @@ -286,6 +286,15 @@ #define TR_FUNCTION_SWITCHES "カスタマイズ スイッチ" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "トリガー" #define TR_TRIMS "トリム" #define TR_FADEIN "フェードイン" diff --git a/radio/src/translations/nl.h b/radio/src/translations/nl.h index 8073dfdf429..84ec3b776e0 100644 --- a/radio/src/translations/nl.h +++ b/radio/src/translations/nl.h @@ -284,6 +284,15 @@ #define TR_FUNCTION_SWITCHES "Customizable switches" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Trigger" #define TR_TRIMS "Trims" #define TR_FADEIN "Fade in" diff --git a/radio/src/translations/pl.h b/radio/src/translations/pl.h index 15d20050a8a..ea21dd4ee86 100644 --- a/radio/src/translations/pl.h +++ b/radio/src/translations/pl.h @@ -284,6 +284,15 @@ #define TR_FUNCTION_SWITCHES "Ustawiane przełączniki" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Trigger" #define TR_TRIMS "Trymy" #define TR_FADEIN "Pojawia" diff --git a/radio/src/translations/pt.h b/radio/src/translations/pt.h index 7405a774678..86117633b23 100644 --- a/radio/src/translations/pt.h +++ b/radio/src/translations/pt.h @@ -290,6 +290,15 @@ #define TR_FUNCTION_SWITCHES "Chaves customizáveis" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Disparo" #define TR_TRIMS "Trims" #define TR_FADEIN "Aparecer" diff --git a/radio/src/translations/ru.h b/radio/src/translations/ru.h index 50e8e64b51a..498788ee96f 100644 --- a/radio/src/translations/ru.h +++ b/radio/src/translations/ru.h @@ -289,6 +289,15 @@ #define TR_FUNCTION_SWITCHES "Настр тумблеры" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Триггер" #define TR_TRIMS "тримы" #define TR_FADEIN "Затух входа" diff --git a/radio/src/translations/se.h b/radio/src/translations/se.h index 6d93ef40669..8d65f3964a8 100644 --- a/radio/src/translations/se.h +++ b/radio/src/translations/se.h @@ -300,6 +300,15 @@ #define TR_FUNCTION_SWITCHES "Anpassningsbara brytare" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Trigger" #define TR_TRIMS "Trimmar" #define TR_FADEIN "Tona in" diff --git a/radio/src/translations/tw.h b/radio/src/translations/tw.h index e7cae879e24..ef3c7d5c609 100644 --- a/radio/src/translations/tw.h +++ b/radio/src/translations/tw.h @@ -287,6 +287,15 @@ #define TR_FUNCTION_SWITCHES "可自定義開關" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Trigger" #define TR_TRIMS "微調" #define TR_FADEIN "漸入" diff --git a/radio/src/translations/ua.h b/radio/src/translations/ua.h index 5aa03e0faee..6a2c5f66132 100644 --- a/radio/src/translations/ua.h +++ b/radio/src/translations/ua.h @@ -289,6 +289,15 @@ #define TR_FUNCTION_SWITCHES "Користувацькі перемикачі" #define TR_GROUP "Group" #define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUP "Group" +#define TR_GROUP_ALWAYS_ON "Always on" +#define TR_GROUPS "Always on groups" +#define TR_LAST "Last" +#define TR_MORE_INFO "More info" +#define TR_SWITCH_TYPE "Type" +#define TR_SWITCH_STARTUP "Startup" +#define TR_SWITCH_GROUP "Group" +#define TR_FUNCTION_SWITCH_GROUPS "---", TR_SWITCH_GROUP" 1", TR_SWITCH_GROUP" 2", TR_SWITCH_GROUP" 3" #define TR_SF_SWITCH "Тригери" #define TR_TRIMS "Трим." #define TR_FADEIN "Вх.Згасання" diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h index aeada9515e4..b911eb0d11c 100644 --- a/radio/src/translations/untranslated.h +++ b/radio/src/translations/untranslated.h @@ -314,7 +314,11 @@ #define STR_CHAR_BW_DEGREE '@' #define TR_FSGROUPS "-","1","2","3" +#if defined(COLORLCD) +#define TR_FSSWITCHES TR_LAST, "SW1", "SW2", "SW3", "SW4", "SW5", "SW6", TR_OFF +#else #define TR_FSSWITCHES "=", "SW1", "SW2", "SW3", "SW4", "SW5", "SW6", TR_OFF +#endif // // HoTT Telemetry sensor names by Hott device diff --git a/radio/util/build-firmware.py b/radio/util/build-firmware.py index 3f524e01a4c..f6113764d56 100755 --- a/radio/util/build-firmware.py +++ b/radio/util/build-firmware.py @@ -169,6 +169,11 @@ def main(): cmake_options["PCBREV"] = "T8" firmware_options = options_radiomaster_t8 maxsize = 65536 * 8 + elif board_name == "t15": + cmake_options["PCB"] = "X10" + cmake_options["PCBREV"] = "T15" + firmware_options = options_jumper_t16 + maxsize = 2 * 1024 * 1024 elif board_name == "t16": cmake_options["PCB"] = "X10" cmake_options["PCBREV"] = "T16" diff --git a/radio/util/hw_defs/legacy_names.py b/radio/util/hw_defs/legacy_names.py index 3a07943ea4d..4504d78816a 100644 --- a/radio/util/hw_defs/legacy_names.py +++ b/radio/util/hw_defs/legacy_names.py @@ -89,6 +89,37 @@ } } }, + { + "targets": {"t15"}, + "inputs": { + "LH": { + "yaml": "Rud" + }, + "LV": { + "yaml": "Ele" + }, + "RV": { + "yaml": "Thr" + }, + "RH": { + "yaml": "Ail" + }, + "P1": { + "yaml": "S1", + "lua": "s1", + "label": "S1", + "short_label": "1", + "description": "Potentiometer S1" + }, + "P2": { + "yaml": "S2", + "lua": "s2", + "label": "S2", + "short_label": "2", + "description": "Potentiometer S2" + } + } + }, { "targets": {"x12s"}, "inputs": { diff --git a/radio/util/hw_defs/pot_config.py b/radio/util/hw_defs/pot_config.py index afb60dbdb67..bd7abbf4702 100644 --- a/radio/util/hw_defs/pot_config.py +++ b/radio/util/hw_defs/pot_config.py @@ -78,6 +78,10 @@ "P1": {"default": "POT_CENTER"}, "P2": {"default": "POT_CENTER"} }, + "t15": { + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "POT_CENTER"}, + }, "t16": { "P1": {"default": "POT_CENTER"}, "P2": {"default": "MULTIPOS"}, diff --git a/radio/util/hw_defs/switch_config.py b/radio/util/hw_defs/switch_config.py index 22bc907c9ef..589495026a9 100644 --- a/radio/util/hw_defs/switch_config.py +++ b/radio/util/hw_defs/switch_config.py @@ -105,6 +105,14 @@ "SD": {"default": "3POS", "display": [1, 1]}, "SF": {"default": "TOGGLE", "display": [1, 2]} }, + "t15": { + "SA": {"default": "3POS"}, + "SB": {"default": "3POS"}, + "SC": {"default": "3POS"}, + "SD": {"default": "3POS"}, + "SE": {"default": "2POS"}, + "SF": {"default": "2POS"}, + }, "t16": { "SA": {"default": "3POS"}, "SB": {"default": "3POS"}, diff --git a/tools/boards.py b/tools/boards.py index 34368651afb..018bf0b8059 100755 --- a/tools/boards.py +++ b/tools/boards.py @@ -43,6 +43,11 @@ "X12S": { "PCB": "X12S", }, + "T15": { + "PCB": "X10", + "PCBREV": "T15", + "INTERNAL_MODULE_CRSF": "YES" + }, "T16": { "PCB": "X10", "PCBREV": "T16", diff --git a/tools/build-companion.sh b/tools/build-companion.sh index 9d7557a932c..6be81ebb26e 100755 --- a/tools/build-companion.sh +++ b/tools/build-companion.sh @@ -72,7 +72,7 @@ declare -a simulator_plugins=(x9lite x9lites xlite xlites nv14 el18 pl18 pl18ev x10 x10-access x12s - t16 t18 t20 t20v2 tx16s) + t15 t16 t18 t20 t20v2 tx16s) for plugin in "${simulator_plugins[@]}" do @@ -164,6 +164,9 @@ do x12s) BUILD_OPTIONS+="-DPCB=X12S" ;; + t15) + BUILD_OPTIONS+="-DPCB=X10 -DPCBREV=T15 -DINTERNAL_MODULE_CRSF=ON" + ;; t16) BUILD_OPTIONS+="-DPCB=X10 -DPCBREV=T16 -DINTERNAL_MODULE_MULTI=ON" ;; diff --git a/tools/build-gh.sh b/tools/build-gh.sh index 5a90a49d6f4..f6a46aa84f4 100755 --- a/tools/build-gh.sh +++ b/tools/build-gh.sh @@ -182,6 +182,9 @@ do x12s) BUILD_OPTIONS+="-DPCB=X12S" ;; + t15) + BUILD_OPTIONS+="-DPCB=X10 -DPCBREV=T15 -DINTERNAL_MODULE_CRSF=ON" + ;; t16) BUILD_OPTIONS+="-DPCB=X10 -DPCBREV=T16 -DINTERNAL_MODULE_MULTI=ON" ;; diff --git a/tools/commit-tests.sh b/tools/commit-tests.sh index c87c0adb4e7..e4b40856222 100755 --- a/tools/commit-tests.sh +++ b/tools/commit-tests.sh @@ -142,6 +142,9 @@ do x12s) BUILD_OPTIONS+="-DPCB=X12S" ;; + t15) + BUILD_OPTIONS+="-DPCB=X10 -DPCBREV=T15 -DINTERNAL_MODULE_CRSF=ON" + ;; t16) BUILD_OPTIONS+="-DPCB=X10 -DPCBREV=T16 -DINTERNAL_MODULE_MULTI=ON" ;; diff --git a/tools/generate-hw-defs.sh b/tools/generate-hw-defs.sh index 44b59550769..48aeaa63fe0 100755 --- a/tools/generate-hw-defs.sh +++ b/tools/generate-hw-defs.sh @@ -6,7 +6,7 @@ set -e : "${SRCDIR:=$(dirname "$(pwd)/$0")/..}" -: ${FLAVOR:="nv14;t12;t16;t18;t8;zorro;pocket;commando8;tlite;tpro;tprov2;t20;t20v2;t14;lr3pro;mt12;tx12;tx12mk2;boxer;tx16s;x10;x10-access;x12s;x7;x7-access;x9d;x9dp;x9dp2019;x9e;x9lite;x9lites;xlite;xlites"} +: ${FLAVOR:="nv14;t12;t15;t16;t18;t8;zorro;pocket;commando8;tlite;tpro;tprov2;t20;t20v2;t14;lr3pro;mt12;tx12;tx12mk2;boxer;tx16s;x10;x10-access;x12s;x7;x7-access;x9d;x9dp;x9dp2019;x9e;x9lite;x9lites;xlite;xlites"} : ${COMMON_OPTIONS:="-DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_RULE_MESSAGES=OFF -Wno-dev -DCMAKE_MESSAGE_LOG_LEVEL=WARNING"} # wipe build directory clean @@ -108,6 +108,9 @@ do x12s) BUILD_OPTIONS+="-DPCB=X12S" ;; + t15) + BUILD_OPTIONS+="-DPCB=X10 -DPCBREV=T15 -DINTERNAL_MODULE_CRSF=ON" + ;; t16) BUILD_OPTIONS+="-DPCB=X10 -DPCBREV=T16 -DINTERNAL_MODULE_MULTI=ON" ;; diff --git a/tools/generate-yaml.sh b/tools/generate-yaml.sh index 47702b113e5..42b114fe60f 100755 --- a/tools/generate-yaml.sh +++ b/tools/generate-yaml.sh @@ -8,7 +8,7 @@ if [[ -n ${GCC_ARM} ]] ; then export PATH=${GCC_ARM}:$PATH fi -: ${FLAVOR:="tx16s;x12s;nv14;pl18;x9d;x9dp;x9e;xlites;x7;tpro;t20"} +: ${FLAVOR:="t15;tx16s;x12s;nv14;pl18;x9d;x9dp;x9e;xlites;x7;tpro;t20"} : ${SRCDIR:=$(dirname "$(pwd)/$0")/..} : ${COMMON_OPTIONS:="-DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_RULE_MESSAGES=OFF -Wno-dev -DDISABLE_COMPANION=YES -DCMAKE_MESSAGE_LOG_LEVEL=WARNING"} @@ -107,6 +107,9 @@ do x12s) BUILD_OPTIONS+="-DPCB=X12S" ;; + t15) + BUILD_OPTIONS+="-DPCB=X10 -DPCBREV=T15 -DINTERNAL_MODULE_CRSF=ON" + ;; t16) BUILD_OPTIONS+="-DPCB=X10 -DPCBREV=T16 -DINTERNAL_MODULE_MULTI=ON" ;; diff --git a/tools/msys2_fetch_and_build_all.sh b/tools/msys2_fetch_and_build_all.sh index 6e5bf7e1bcf..b444a245eb3 100644 --- a/tools/msys2_fetch_and_build_all.sh +++ b/tools/msys2_fetch_and_build_all.sh @@ -9,7 +9,7 @@ # ----------------------------------------------------------------------------- export BRANCH_NAME="main" # main|2.9|... -export RADIO_TYPE="tx16s" # tx16s|x10|x10-access|x12s|x9d|x9dp|x9lite|x9lites|x7|x7-access|t12|tx12|tx12mk2|mt12|boxer|t8|zorro|pocket|tlite|tpro|t20|t20v2|t14|lr3pro|xlite|xlites|x9dp2019|x9e|x9e-hall|t16|t18|nv14|commando8 +export RADIO_TYPE="tx16s" # tx16s|x10|x10-access|x12s|x9d|x9dp|x9lite|x9lites|x7|x7-access|t12|tx12|tx12mk2|mt12|boxer|t8|zorro|pocket|tlite|tpro|t20|t20v2|t14|lr3pro|xlite|xlites|x9dp2019|x9e|x9e-hall|t15|t16|t18|nv14|commando8 export BUILD_OPTIONS="-DDEFAULT_MODE=2 -DGVARS=YES" @@ -99,6 +99,9 @@ case $RADIO_TYPE in x12s) BUILD_OPTIONS+=" -DPCB=X12S" ;; + t15) + BUILD_OPTIONS+=" -DPCB=X10 -DPCBREV=T15 -DINTERNAL_MODULE_CRSF=ON" + ;; t16) BUILD_OPTIONS+=" -DPCB=X10 -DPCBREV=T16 -DINTERNAL_MODULE_MULTI=ON" ;;