diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index 4fcb62a870f..91807761949 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -46,6 +46,8 @@ jobs: - tx16s - nv14 - el18 + - pl18 + - pl18ev - t12 - t16 - t18 @@ -90,9 +92,9 @@ jobs: matrix: target: - nv14;el18 + - pl18;pl18ev - t12 - - t16 - - t18 + - t16;t18 - t8;zorro;pocket;mt12;commando8 - tlite;tpro;tprov2;lr3pro - t20 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 009f2147320..4406634ecd4 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -16,6 +16,7 @@ jobs: matrix: target: - nv14;el18 + - pl18;pl18ev - t12 - t16 - t18 diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt index c623a69a268..7cb6f9242a8 100644 --- a/companion/src/CMakeLists.txt +++ b/companion/src/CMakeLists.txt @@ -318,6 +318,8 @@ elseif(PCB STREQUAL X10 AND PCBREV STREQUAL T18) set(FLAVOUR t18) elseif(PCB STREQUAL NV14 AND PCBREV STREQUAL EL18) set(FLAVOUR el18) +elseif(PCB STREQUAL PL18) + set(FLAVOUR pl18) else() string(TOLOWER ${PCB} FLAVOUR) endif() diff --git a/companion/src/companion.qrc b/companion/src/companion.qrc index 792e2f494b9..c28331e9a68 100644 --- a/companion/src/companion.qrc +++ b/companion/src/companion.qrc @@ -293,6 +293,10 @@ images/simulator/NV14/right.png images/simulator/NV14/top.png images/simulator/NV14/bottom.png + images/simulator/PL18/left.png + images/simulator/PL18/right.png + images/simulator/PL18/top.png + images/simulator/PL18/bottom.png images/wizard/ailerons.png images/wizard/airbrakes.png images/wizard/elevons.png diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp index 08e058ac863..f7f2be15615 100644 --- a/companion/src/firmwares/boards.cpp +++ b/companion/src/firmwares/boards.cpp @@ -110,7 +110,9 @@ uint32_t Boards::getFourCC(Type board) case BOARD_FLYSKY_NV14: return 0x3A78746F; case BOARD_FLYSKY_EL18: - return 0x3A78746F; // TODO: check this + return 0x3A78746F; + case BOARD_FLYSKY_PL18: + return 0x4878746F; default: return 0; } @@ -159,6 +161,7 @@ int Boards::getEEpromSize(Board::Type board) case BOARD_RADIOMASTER_TX16S: case BOARD_FLYSKY_NV14: case BOARD_FLYSKY_EL18: + case BOARD_FLYSKY_PL18: return 0; default: return 0; @@ -206,6 +209,7 @@ int Boards::getFlashSize(Type board) case BOARD_RADIOMASTER_TX16S: case BOARD_FLYSKY_NV14: case BOARD_FLYSKY_EL18: + case BOARD_FLYSKY_PL18: return FSIZE_HORUS; case BOARD_UNKNOWN: return FSIZE_MAX; @@ -419,6 +423,20 @@ SwitchInfo Boards::getSwitchInfo(Board::Type board, int index) if (index < DIM(switches)) return switches[index]; } + else if (IS_FLYSKY_PL18(board)) { + const Board::SwitchInfo switches[] = { + {SWITCH_2POS, "SA"}, + {SWITCH_3POS, "SB"}, + {SWITCH_2POS, "SC"}, + {SWITCH_3POS, "SD"}, + {SWITCH_3POS, "SE"}, + {SWITCH_2POS, "SF"}, + {SWITCH_3POS, "SG"}, + {SWITCH_3POS, "SH"} + }; + if (index < DIM(switches)) + return switches[index]; + } else if (IS_FAMILY_HORUS_OR_T16(board)) { const Board::SwitchInfo switches[] = { {SWITCH_3POS, "SA"}, @@ -497,6 +515,8 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) return 7; else if (IS_HORUS_X12S(board)) return 3; + else if (IS_FLYSKY_PL18(board)) + return 3; else return 3; @@ -509,7 +529,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) case Sliders: if (IS_HORUS_X12S(board) || IS_TARANIS_X9E(board) || IS_JUMPER_T20(board)) return 4; - else if (IS_TARANIS_X9D(board) || IS_HORUS_X10(board) || IS_FAMILY_T16(board)) + else if (IS_TARANIS_X9D(board) || IS_HORUS_X10(board) || IS_FAMILY_T16(board) || IS_FLYSKY_PL18(board)) return 2; else return 0; @@ -531,7 +551,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) getCapability(board, Board::MouseAnalogs) + getCapability(board, Board::GyroAnalogs); case MultiposPots: - if (IS_HORUS_OR_TARANIS(board) && !(IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board))) + if (IS_HORUS_OR_TARANIS(board) && !(IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_FLYSKY_PL18(board))) return getCapability(board, Board::Pots); else return 0; @@ -558,6 +578,8 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) return 6; else if (board == BOARD_FLYSKY_NV14 || board == BOARD_FLYSKY_EL18) return 8; + else if (board == BOARD_FLYSKY_PL18) + return 8; else if (board == BOARD_RADIOMASTER_TX12_MK2 || board == BOARD_RADIOMASTER_BOXER || board == BOARD_JUMPER_TPRO) return 6; else if (board == BOARD_RADIOMASTER_POCKET) @@ -600,7 +622,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) return getCapability(board, Board::Switches); case SwitchPositions: - if (IS_HORUS_OR_TARANIS(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board)) + if (IS_HORUS_OR_TARANIS(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_FLYSKY_PL18(board)) return getCapability(board, Board::Switches) * 3; else return 9; @@ -610,7 +632,9 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) case NumTrims: - if (IS_FAMILY_HORUS_OR_T16(board) && !(IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board))) + if (IS_FLYSKY_PL18(board)) + return 8; + else if (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board)) return 6; else if (IS_IFLIGHT_COMMANDO8(board)) return 0; @@ -626,7 +650,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) return IS_STM32(board) ? true : false; case HasColorLcd: - return IS_FAMILY_HORUS_OR_T16(board); + return IS_FAMILY_HORUS_OR_T16(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board); case HasSDCard: return IS_STM32(board); @@ -647,7 +671,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) return false; case SportMaxBaudRate: - if (IS_FAMILY_T16(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_TARANIS_X7_ACCESS(board) || + if (IS_FAMILY_T16(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_FLYSKY_PL18(board) ||IS_TARANIS_X7_ACCESS(board) || (IS_TARANIS(board) && !IS_TARANIS_XLITE(board) && !IS_TARANIS_X7(board) && !IS_TARANIS_X9LITE(board))) return 400000; // 400K and higher else @@ -833,6 +857,14 @@ StringTagMappingTable Boards::getAnalogNamesLookupTable(Board::Type board, const {tr("TltY").toStdString(), "TILT_Y", 14}, }); } + } else if (IS_FLYSKY_PL18(board)) { + tbl.insert(tbl.end(), { + {tr("VRA").toStdString(), "POT1"}, + {tr("VRB").toStdString(), "POT2"}, + {tr("VRC").toStdString(), "POT3"}, + {tr("LS").toStdString(), "LS"}, + {tr("RS").toStdString(), "RS"}, + }); } else if (IS_HORUS_X10(board) || IS_FAMILY_T16(board)) { if (version < adcVersion) { tbl.insert(tbl.end(), { @@ -964,6 +996,8 @@ QString Boards::getBoardName(Board::Type board) return "FlySky NV14"; case BOARD_FLYSKY_EL18: return "FlySky EL18"; + case BOARD_FLYSKY_PL18: + return "FlySky PL18"; case BOARD_BETAFPV_LR3PRO: return "BETAFPV LR3PRO"; case BOARD_IFLIGHT_COMMANDO8: @@ -1198,6 +1232,7 @@ int Boards::getDefaultInternalModules(Board::Type board) case BOARD_JUMPER_TLITE_F4: case BOARD_JUMPER_TPRO: case BOARD_JUMPER_TPROV2: + case BOARD_FLYSKY_PL18: return (int)MODULE_TYPE_MULTIMODULE; case BOARD_BETAFPV_LR3PRO: diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index 75c6473c918..b853436bdfe 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -69,6 +69,7 @@ namespace Board { BOARD_JUMPER_TLITE, BOARD_JUMPER_TLITE_F4, BOARD_FLYSKY_NV14, + BOARD_FLYSKY_PL18, BOARD_RADIOMASTER_ZORRO, BOARD_JUMPER_TPRO, BOARD_BETAFPV_LR3PRO, @@ -398,6 +399,11 @@ inline bool IS_FLYSKY_EL18(Board::Type board) return (board == Board::BOARD_FLYSKY_EL18); } +inline bool IS_FLYSKY_PL18(Board::Type board) +{ + return (board == Board::BOARD_FLYSKY_PL18); +} + inline bool IS_TARANIS_XLITE(Board::Type board) { return board == Board::BOARD_TARANIS_XLITE || board == Board::BOARD_TARANIS_XLITES; @@ -475,7 +481,9 @@ inline bool IS_FAMILY_HORUS(Board::Type board) inline bool IS_FAMILY_HORUS_OR_T16(Board::Type board) { - return IS_FAMILY_HORUS(board) || IS_FAMILY_T16(board) || IS_FLYSKY_NV14(board)/*generally*/ || IS_FLYSKY_EL18(board)/*generally*/; + return IS_FAMILY_HORUS(board) || IS_FAMILY_T16(board) || + IS_FLYSKY_NV14(board)/*generally*/ || IS_FLYSKY_EL18(board)/*generally*/ + || IS_FLYSKY_PL18(board); } inline bool IS_HORUS_OR_TARANIS(Board::Type board) @@ -485,7 +493,8 @@ inline bool IS_HORUS_OR_TARANIS(Board::Type board) inline bool IS_STM32(Board::Type board) { - return IS_TARANIS(board) || IS_FAMILY_HORUS_OR_T16(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board); + return IS_TARANIS(board) || IS_FAMILY_HORUS_OR_T16(board) || + IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_FLYSKY_PL18(board); } inline bool IS_ARM(Board::Type board) diff --git a/companion/src/firmwares/generalsettings.cpp b/companion/src/firmwares/generalsettings.cpp index b4cc9e80b55..9e7688c99ca 100644 --- a/companion/src/firmwares/generalsettings.cpp +++ b/companion/src/firmwares/generalsettings.cpp @@ -154,6 +154,8 @@ void GeneralSettings::init() strcpy(bluetoothName, "t16"); else if (IS_FLYSKY_NV14(board)) strcpy(bluetoothName, "nv14"); + else if (IS_FLYSKY_PL18(board)) + strcpy(bluetoothName, "pl18"); else if (IS_FAMILY_HORUS_OR_T16(board)) strcpy(bluetoothName, "horus"); else if (IS_TARANIS_X9E(board) || IS_TARANIS_SMALL(board)) @@ -269,7 +271,7 @@ void GeneralSettings::init() internalModule = g.profile[g.sessionId()].defaultInternalModule(); - if (IS_FLYSKY_NV14(board)) + if (IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) stickDeadZone = 2; } @@ -285,7 +287,7 @@ void GeneralSettings::setDefaultControlTypes(Board::Type board) return; // TODO: move to Boards, like with switches - if (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board)) { + if (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board)) { potConfig[0] = Board::POT_WITH_DETENT; potConfig[1] = Board::POT_MULTIPOS_SWITCH; potConfig[2] = Board::POT_WITH_DETENT; @@ -294,6 +296,11 @@ void GeneralSettings::setDefaultControlTypes(Board::Type board) potConfig[0] = Board::POT_WITHOUT_DETENT; potConfig[1] = Board::POT_WITHOUT_DETENT; } + else if (IS_FLYSKY_PL18(board)) { + potConfig[0] = Board::POT_WITHOUT_DETENT; + potConfig[1] = Board::POT_WITHOUT_DETENT; + potConfig[2] = Board::POT_WITHOUT_DETENT; + } else if (IS_TARANIS_XLITE(board)) { potConfig[0] = Board::POT_WITHOUT_DETENT; potConfig[1] = Board::POT_WITHOUT_DETENT; diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index d5339d9982b..b7c44f0988e 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -116,7 +116,7 @@ inline int MAX_POTS_STORAGE(Board::Type board, int version) { if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board)) return 3; - if (version <= 220 && IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board)) + if (version <= 220 && IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board)) return 5; if (IS_FAMILY_T12(board)) return 2; @@ -147,7 +147,7 @@ inline int MAX_XPOTS(Board::Type board, int version) inline int MAX_SLIDERS_STORAGE(Board::Type board, int version) { - if (version >= 219 && (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board))) + if (version >= 219 && (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board))) return 4; return Boards::getCapability(board, Board::Sliders); } @@ -183,7 +183,7 @@ inline int SWITCHES_CONFIG_SIZE(Board::Type board, int version) inline int MAX_MOUSE_ANALOG_SOURCES(Board::Type board, int version) { - if (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board)) + if (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board)) return 2; else return 0; @@ -211,10 +211,10 @@ inline int MAX_GYRO_ANALOGS(Board::Type board, int version) #define MAX_CURVES(board, version) ((version >= 219 || HAS_LARGE_LCD(board)) ? 32 : 16) #define MAX_GVARS(board, version) 9 #define MAX_SCRIPTS(board) (IS_FAMILY_HORUS_OR_T16(board) ? 9 : 7) -#define MAX_TELEMETRY_SENSORS(board, version) (version <= 218 ? 32 : ((IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS_X9(board) || IS_FLYSKY_NV14(board)) ? 60 : 40)) +#define MAX_TELEMETRY_SENSORS(board, version) (version <= 218 ? 32 : ((IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS_X9(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) ? 60 : 40)) #define NUM_PPM_INPUTS(board, version) 16 #define ROTENC_COUNT(board, version) ((IS_STM32(board) && version >= 218) ? 0 : 1) -#define MAX_AUX_TRIMS(board) ((IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board)) ? 2 : 0) +#define MAX_AUX_TRIMS(board) ((IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board)) ? 2 : 0) #define MAX_SOURCE_TYPE_SPECIAL(board, version) SOURCE_TYPE_SPECIAL_COUNT inline int switchIndex(int i, Board::Type board, unsigned int version) @@ -2910,7 +2910,7 @@ void OpenTxModelData::beforeExport() // TODO remove when enum not radio specific requires eeprom change and conversion // Note: this must mirror reverse afterImport - if (!IS_FLYSKY_NV14(board)) + if (!IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board)) modelData.trainerMode -= 1; if (modelData.trainerMode > TRAINER_MODE_SLAVE_JACK) { @@ -2957,7 +2957,7 @@ void OpenTxModelData::afterImport() // TODO remove when enum not radio specific requires eeprom change and conversion // Note: this must mirror reverse beforeExport - if (!IS_FLYSKY_NV14(board)) + if (!IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board)) modelData.trainerMode += 1; if (modelData.trainerMode > TRAINER_MODE_SLAVE_JACK) { @@ -3003,7 +3003,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type internalField.Append(new UnsignedField<16>(this, chkSum)); - if (!IS_FAMILY_HORUS_OR_T16(board) || (IS_FLYSKY_NV14(board))) { + if (!IS_FAMILY_HORUS_OR_T16(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) { internalField.Append(new UnsignedField<8>(this, generalData.currModelIndex)); internalField.Append(new UnsignedField<8>(this, generalData.contrast)); } @@ -3067,11 +3067,11 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type internalField.Append(new SignedField<8>(this, generalData.PPM_Multiplier)); internalField.Append(new SignedField<8>(this, generalData.hapticLength)); - if (version < 218 || (!IS_TARANIS(board) && !IS_FAMILY_HORUS_OR_T16(board)) || IS_FLYSKY_NV14(board)) { + if (version < 218 || (!IS_TARANIS(board) && !IS_FAMILY_HORUS_OR_T16(board)) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) { internalField.Append(new UnsignedField<8>(this, generalData.reNavigation)); } - if ((!IS_TARANIS(board) && !IS_FAMILY_HORUS_OR_T16(board)) || IS_FLYSKY_NV14(board)) { + if ((!IS_TARANIS(board) && !IS_FAMILY_HORUS_OR_T16(board)) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) { internalField.Append(new UnsignedField<8>(this, generalData.stickReverse)); } diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 34d441279c0..192fb4c32b7 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -124,6 +124,8 @@ const char * OpenTxEepromInterface::getName() return "EdgeTX for FlySky NV14"; case BOARD_FLYSKY_EL18: return "EdgeTX for FlySky EL18"; + case BOARD_FLYSKY_PL18: + return "EdgeTX for FlySky PL18"; case BOARD_BETAFPV_LR3PRO: return "EdgeTx for BETAFPV LR3PRO"; case BOARD_IFLIGHT_COMMANDO8: @@ -664,6 +666,8 @@ int OpenTxFirmware::getCapability(::Capability capability) case LcdWidth: if (IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board)) return 320; + else if (IS_FLYSKY_PL18(board)) + return 480; else if (IS_FAMILY_HORUS_OR_T16(board)) return 480; else if (IS_TARANIS_SMALL(board)) @@ -675,6 +679,8 @@ int OpenTxFirmware::getCapability(::Capability capability) case LcdHeight: if (IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board)) return 480; + else if (IS_FLYSKY_PL18(board)) + return 320; else if (IS_FAMILY_HORUS_OR_T16(board)) return 272; else @@ -777,7 +783,7 @@ int OpenTxFirmware::getCapability(::Capability capability) IS_JUMPER_TPRO(board) || IS_RADIOMASTER_TX12_MK2(board) || IS_RADIOMASTER_BOXER(board) || IS_RADIOMASTER_POCKET(board); case HasBluetooth: return (IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board)|| IS_TARANIS_X9E(board) || - IS_TARANIS_X9DP_2019(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board)) ? true : false; + IS_TARANIS_X9DP_2019(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_FLYSKY_PL18(board)) ? true : false; case HasADCJitterFilter: return IS_HORUS_OR_TARANIS(board); case HasTelemetryBaudrate: @@ -1244,6 +1250,13 @@ void registerOpenTxFirmwares() addOpenTxRfOptions(firmware, FLEX + AFHDS2A + AFHDS3); registerOpenTxFirmware(firmware); + /* FlySky PL18 board */ + firmware = new OpenTxFirmware(FIRMWAREID("pl18"), Firmware::tr("FlySky PL18"), BOARD_FLYSKY_PL18); + addOpenTxFrskyOptions(firmware); + firmware->addOption("bluetooth", Firmware::tr("Support for bluetooth module")); + addOpenTxRfOptions(firmware, FLEX + AFHDS3); + registerOpenTxFirmware(firmware); + /* FrSky Horus X10 board */ firmware = new OpenTxFirmware(FIRMWAREID("x10"), Firmware::tr("FrSky Horus X10 / X10S"), BOARD_X10); addOpenTxFrskyOptions(firmware); diff --git a/companion/src/generaledit/generalsetup.cpp b/companion/src/generaledit/generalsetup.cpp index 75d3b2dabc7..265aad75ac1 100644 --- a/companion/src/generaledit/generalsetup.cpp +++ b/companion/src/generaledit/generalsetup.cpp @@ -175,7 +175,7 @@ ui(new Ui::GeneralSetup) ui->usbModeCB->hide(); } - if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board)) { + if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) { ui->hatsModeCB->setModel(new FilteredItemModel(GeneralSettings::hatsModeItemModel())); ui->hatsModeCB->setField(generalSettings.hatsMode, this); } diff --git a/companion/src/images/simulator/PL18/bottom.png b/companion/src/images/simulator/PL18/bottom.png new file mode 100644 index 00000000000..5fc10a49d42 Binary files /dev/null and b/companion/src/images/simulator/PL18/bottom.png differ diff --git a/companion/src/images/simulator/PL18/left.png b/companion/src/images/simulator/PL18/left.png new file mode 100644 index 00000000000..6294e9922da Binary files /dev/null and b/companion/src/images/simulator/PL18/left.png differ diff --git a/companion/src/images/simulator/PL18/right.png b/companion/src/images/simulator/PL18/right.png new file mode 100644 index 00000000000..6294e9922da Binary files /dev/null and b/companion/src/images/simulator/PL18/right.png differ diff --git a/companion/src/images/simulator/PL18/top.png b/companion/src/images/simulator/PL18/top.png new file mode 100644 index 00000000000..5fc10a49d42 Binary files /dev/null and b/companion/src/images/simulator/PL18/top.png differ diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index 345e6aed9e1..d0911ccf99f 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -1696,7 +1696,7 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge ui->trimsDisplay->setField(model.trimsDisplay, this); - if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board)) { + if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) { ui->cboHatsMode->setModel(panelFilteredModels->getItemModel(FIM_HATSMODE)); ui->cboHatsMode->setField(model.hatsMode, this); } diff --git a/companion/src/modelprinter.cpp b/companion/src/modelprinter.cpp index 5501340990f..e524454aaa3 100644 --- a/companion/src/modelprinter.cpp +++ b/companion/src/modelprinter.cpp @@ -841,7 +841,7 @@ QString ModelPrinter::printSettingsTrim() str << printLabelValue(tr("Display"), printTrimsDisplayMode()); str << printLabelValue(tr("Extended"), printBoolean(model.extendedTrims, BOOLEAN_YESNO)); Board::Type board = firmware->getBoard(); - if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board)) { + if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) { str << printLabelValue(tr("Hats Mode"), printHatsMode()); } return str.join(" "); diff --git a/companion/src/simulation/CMakeLists.txt b/companion/src/simulation/CMakeLists.txt index 54a994dcf4b..f700a917d5d 100644 --- a/companion/src/simulation/CMakeLists.txt +++ b/companion/src/simulation/CMakeLists.txt @@ -40,6 +40,7 @@ set(${PROJECT_NAME}_SRCS simulateduiwidgetJumperTPRO.cpp simulateduiwidgetLR3PRO.cpp simulateduiwidgetNV14.cpp + simulateduiwidgetPL18.cpp simulateduiwidgetT8.cpp simulateduiwidgetTX12.cpp simulateduiwidgetTX16S.cpp diff --git a/companion/src/simulation/simulateduiwidget.h b/companion/src/simulation/simulateduiwidget.h index a3856aa86a1..11f99a33743 100644 --- a/companion/src/simulation/simulateduiwidget.h +++ b/companion/src/simulation/simulateduiwidget.h @@ -125,6 +125,7 @@ namespace Ui { class SimulatedUIWidgetT8; class SimulatedUIWidgetNV14; class SimulatedUIWidgetEL18; + class SimulatedUIWidgetPL18; } class SimulatedUIWidget9X: public SimulatedUIWidget @@ -407,4 +408,16 @@ class SimulatedUIWidgetEL18: public SimulatedUIWidget Ui::SimulatedUIWidgetEL18 * ui; }; +class SimulatedUIWidgetPL18: public SimulatedUIWidget +{ + Q_OBJECT + + public: + explicit SimulatedUIWidgetPL18(SimulatorInterface * simulator, QWidget * parent = nullptr); + virtual ~SimulatedUIWidgetPL18(); + + private: + Ui::SimulatedUIWidgetPL18 * ui; +}; + #endif // SIMULATEDUIWIDGET_H diff --git a/companion/src/simulation/simulateduiwidgetPL18.cpp b/companion/src/simulation/simulateduiwidgetPL18.cpp new file mode 100644 index 00000000000..5e3554245cc --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetPL18.cpp @@ -0,0 +1,76 @@ +/* + * 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_simulateduiwidgetPL18.h" + +SimulatedUIWidgetPL18::SimulatedUIWidgetPL18(SimulatorInterface *simulator, QWidget * parent): + SimulatedUIWidget(simulator, parent), + ui(new Ui::SimulatedUIWidgetPL18) +{ + RadioUiAction * act; + + ui->setupUi(this); + + // add actions in order of appearance on the help menu + + // Note: the PL18 has no physical buttons though at some point the trim joystick is repurposed + // allow for colorlcd key events and see what works + // the mouse click areas do not map to visual buttons on the background images + + act = new RadioUiAction(3, QList() << Qt::Key_Up, SIMU_STR_HLP_KEY_UP, SIMU_STR_HLP_ACT_MDL); + addRadioWidget(ui->rightbuttons->addArea(QRect(10, 1, 80, 35), "PL18/left.png", act)); + + m_mouseMidClickAction = new RadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN); + addRadioWidget(ui->rightbuttons->addArea(QRect(10, 40, 80, 35), "PL18/left.png", m_mouseMidClickAction)); + + act = new RadioUiAction(6, QList() << Qt::Key_Left, SIMU_STR_HLP_KEY_LFT, SIMU_STR_HLP_ACT_SYS); + addRadioWidget(ui->leftbuttons->addArea(QRect(10, 80, 80, 35), "PL18/left.png", act)); + + act = new RadioUiAction(5, QList() << Qt::Key_Right, SIMU_STR_HLP_KEY_RGT, SIMU_STR_HLP_ACT_TELE); + addRadioWidget(ui->leftbuttons->addArea(QRect(10, 120, 80, 35), "PL18/left.png", act)); + + act = new RadioUiAction(1, QList() << Qt::Key_PageDown, SIMU_STR_HLP_KEY_PGDN, SIMU_STR_HLP_ACT_PGDN); + addRadioWidget(ui->leftbuttons->addArea(QRect(10, 160, 80, 35), "PL18/left.png", act)); + + act = new RadioUiAction(0, QList() << Qt::Key_PageUp, SIMU_STR_HLP_KEY_PGUP, SIMU_STR_HLP_ACT_PGUP); + addRadioWidget(ui->leftbuttons->addArea(QRect(10, 200, 80, 35), "PL18/left.png", act)); + + act = new RadioUiAction(4, 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(10, 240, 80, 35), "PL18/left.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(); + + addRadioWidget(ui->leftbuttons->addArea(QRect(10, 280, 30, 30), "PL18/left.png", m_screenshotAction)); + + m_backlightColors << QColor(47, 123, 227); + + setLcd(ui->lcd); +} + +SimulatedUIWidgetPL18::~SimulatedUIWidgetPL18() +{ + delete ui; +} diff --git a/companion/src/simulation/simulateduiwidgetPL18.ui b/companion/src/simulation/simulateduiwidgetPL18.ui new file mode 100644 index 00000000000..c1bbcaedaf4 --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetPL18.ui @@ -0,0 +1,206 @@ + + + SimulatedUIWidgetPL18 + + + + 0 + 0 + 520 + 500 + + + + + 0 + 0 + + + + + 520 + 500 + + + + + 520 + 500 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 100 + 500 + + + + + 100 + 500 + + + + background:url(:/images/simulator/PL18/right.png) + + + + + + + + 0 + 0 + + + + + 480 + 320 + + + + + 480 + 320 + + + + + 5 + + + + + + + + + 0 + 0 + + + + + 100 + 500 + + + + + 100 + 500 + + + + true + + + background:url(:/images/simulator/PL18/left.png); + + + + + + + + 0 + 0 + + + + + 320 + 10 + + + + + 320 + 10 + + + + + 5 + + + + background:url(:/images/simulator/PL18/top.png) + + + + + + + + 0 + 0 + + + + + 320 + 10 + + + + + 320 + 10 + + + + + 5 + false + + + + background:url(:/images/simulator/PL18/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 dc0d34acc26..36f30b2586c 100644 --- a/companion/src/simulation/simulatorwidget.cpp +++ b/companion/src/simulation/simulatorwidget.cpp @@ -133,6 +133,9 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato case Board::BOARD_FLYSKY_EL18: radioUiWidget = new SimulatedUIWidgetEL18(simulator, this); break; + case Board::BOARD_FLYSKY_PL18: + radioUiWidget = new SimulatedUIWidgetPL18(simulator, this); + break; default: radioUiWidget = new SimulatedUIWidget9X(simulator, this); break; diff --git a/fw.json b/fw.json index 728a2188278..b92436535d2 100644 --- a/fw.json +++ b/fw.json @@ -3,6 +3,8 @@ ["BETAFPV LiteRadio 3 Pro", "lr3pro-"], ["Flysky EL18", "el18-"], ["Flysky NV14", "nv14-"], + ["Flysky PL18", "pl18-"], + ["Flysky PL18EV", "pl18ev-"], ["FrSky Horus X10", "x10-"], ["FrSky Horus X10 Access", "x10-access-"], ["FrSky Horus X12s", "x12s-"], diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 577889d7d4a..e72fe13f0fd 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -1,7 +1,7 @@ include(CMakeForceCompiler) include(Bitmaps) -set(PCB_TYPES X9LITE X9LITES X7 XLITE XLITES X9D X9D+ X9E X10 X12S NV14) +set(PCB_TYPES X9LITE X9LITES X7 XLITE XLITES X9D X9D+ X9E X10 X12S NV14 PL18) set(RADIO_LANGUAGES CN CZ DA DE EN ES FI FR HE IT JP PT RU SK SE PL HU NL TW) set(TTS_LANGUAGES CN CZ DA DE EN ES FR HE IT JP PT RU SK SE PL HU NL) @@ -85,6 +85,8 @@ if(PCB STREQUAL X12S OR PCB STREQUAL X10) include(targets/horus/CMakeLists.txt) elseif(PCB STREQUAL NV14) include(targets/nv14/CMakeLists.txt) +elseif(PCB STREQUAL PL18) + include(targets/pl18/CMakeLists.txt) elseif(PCB STREQUAL X9E OR PCB STREQUAL X9D+ OR PCB STREQUAL X9D OR PCB STREQUAL X7 OR PCB STREQUAL X9LITE OR PCB STREQUAL X9LITES OR PCB STREQUAL XLITE OR PCB STREQUAL XLITES) include(targets/taranis/CMakeLists.txt) else() diff --git a/radio/src/bitmaps/480x272/CMakeLists.txt b/radio/src/bitmaps/480x272/CMakeLists.txt index a1458053abd..6c0f81f6b0a 100644 --- a/radio/src/bitmaps/480x272/CMakeLists.txt +++ b/radio/src/bitmaps/480x272/CMakeLists.txt @@ -4,6 +4,8 @@ set(MASK_ARGS ${BITMAP_SIZE_ARGS}) if(PCB STREQUAL NV14) set(BITMAP_TARGET_PREFIX nv14) +elseif(PCB STREQUAL PL18) + set(BITMAP_TARGET_PREFIX pl18) elseif(PCB STREQUAL X12S) set(BITMAP_TARGET_PREFIX x12s) else() diff --git a/radio/src/boards/generic_stm32/analog_inputs.cpp b/radio/src/boards/generic_stm32/analog_inputs.cpp index 19036a17973..bbcbc7edaab 100644 --- a/radio/src/boards/generic_stm32/analog_inputs.cpp +++ b/radio/src/boards/generic_stm32/analog_inputs.cpp @@ -47,6 +47,9 @@ constexpr uint8_t n_ADC_spi = DIM(_ADC_spi); constexpr uint8_t n_GPIO = DIM(_ADC_GPIOs); constexpr uint8_t n_inputs = DIM(_ADC_inputs); +static_assert(n_inputs <= MAX_ADC_INPUTS, "Too many ADC inputs"); +static_assert(n_inputs <= MAX_ANALOG_INPUTS, "Too many analog inputs"); + static bool adc_init() { bool success = stm32_hal_adc_init(_ADC_adc, n_ADC, _ADC_inputs, _ADC_GPIOs, n_GPIO); diff --git a/radio/src/boards/generic_stm32/inputs.cpp b/radio/src/boards/generic_stm32/inputs.cpp index 385400e03f0..c1c3341c049 100644 --- a/radio/src/boards/generic_stm32/inputs.cpp +++ b/radio/src/boards/generic_stm32/inputs.cpp @@ -26,23 +26,27 @@ #include "stm32_keys.inc" -void keysInit() +#define __weak __attribute__((weak)) + +__weak void keysInit() { _init_keys(); _init_trims(); } -uint32_t readKeys() +__weak uint32_t readKeys() { return _read_keys(); } -uint32_t readTrims() +__weak uint32_t readTrims() { uint32_t trims = _read_trims(); + #if defined(PCBXLITE) if (_read_keys() & (1 << KEY_SHIFT)) return ((trims & 0x03) << 6) | ((trims & 0x0c) << 2); #endif + return trims; } diff --git a/radio/src/boards/generic_stm32/module_ports.cpp b/radio/src/boards/generic_stm32/module_ports.cpp index e4d37be48d7..e7e07fd3d74 100644 --- a/radio/src/boards/generic_stm32/module_ports.cpp +++ b/radio/src/boards/generic_stm32/module_ports.cpp @@ -28,6 +28,7 @@ #include "board.h" #include "dataconstants.h" +#if defined (HARDWARE_INTERNAL_MODULE) #if defined(INTMODULE_USART) #define INTMODULE_USART_IRQ_PRIORITY 5 @@ -110,7 +111,8 @@ extern "C" void INTMODULE_TIMER_IRQHandler() DEFINE_STM32_SOFTSERIAL_PORT(InternalModule, intmoduleTimer); -#endif +#endif // INTMODULE_USART +#endif // HARDWARE_INTERNAL_MODULE #include "module_timer_driver.h" diff --git a/radio/src/cli.cpp b/radio/src/cli.cpp index 8a06aaa9269..f21ca87806d 100644 --- a/radio/src/cli.cpp +++ b/radio/src/cli.cpp @@ -1040,6 +1040,7 @@ int cliSet(const char **argv) } #if defined(ENABLE_SERIAL_PASSTHROUGH) +#if defined(HARDWARE_INTERNAL_MODULE) static etx_module_state_t *spInternalModuleState = nullptr; static void spInternalModuleTx(uint8_t* buf, uint32_t len) @@ -1060,6 +1061,7 @@ static const etx_serial_init spIntmoduleSerialInitParams = { .polarity = ETX_Pol_Normal, }; +#endif // HARDWARE_INTERNAL_MODULE // TODO: use proper method instead extern bool cdcConnected; extern uint32_t usbSerialBaudRate(void*); @@ -1576,7 +1578,7 @@ int cliCrypt(const char ** argv) } #endif -#if defined(HARDWARE_TOUCH) && !defined(PCBNV14) +#if defined(HARDWARE_TOUCH) && !defined(PCBNV14) && !defined(PCBPL18) // from tp_gt911.cpp extern uint8_t tp_gt911_cfgVer; @@ -1648,7 +1650,7 @@ const CliCommand cliCommands[] = { #if defined(ACCESS_DENIED) && defined(DEBUG_CRYPT) { "crypt", cliCrypt, "" }, #endif -#if defined(HARDWARE_TOUCH) && !defined(PCBNV14) +#if defined(HARDWARE_TOUCH) && !defined(PCBNV14) && !defined(PCBPL18) { "reset_gt911", cliResetGT911, ""}, #endif { nullptr, nullptr, nullptr } /* sentinel */ diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index 2459207fdb2..c69b8071d12 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -39,7 +39,7 @@ #define LABELS_LENGTH 100 // Maximum length of the label string #define LABEL_LENGTH 16 -#if defined(PCBHORUS) || defined(PCBNV14) +#if defined(PCBHORUS) || defined(PCBNV14) || defined(PCBPL18) #define MAX_MODELS 60 #define MAX_OUTPUT_CHANNELS 32 // number of real output channels CH1-CH32 #define MAX_FLIGHT_MODES 9 @@ -98,7 +98,7 @@ enum CurveType { #define MIN_POINTS_PER_CURVE 3 #define MAX_POINTS_PER_CURVE 17 -#if defined(PCBHORUS) || defined(PCBNV14) +#if defined(PCBHORUS) || defined(PCBNV14) || defined(PCBPL18) #define LEN_MODEL_NAME 15 #define LEN_TIMER_NAME 8 #define LEN_FLIGHT_MODE_NAME 10 @@ -408,10 +408,10 @@ enum PotsWarnMode { #define MAX_FLEX_SWITCHES 0 #endif -#if defined(RADIO_T20) -#define MAX_TRIMS 8 +#if NUM_TRIMS > 6 +#define MAX_TRIMS 8 #else -#define MAX_TRIMS 6 +#define MAX_TRIMS 6 #endif #define MAX_XPOTS_POSITIONS (MAX_POTS * XPOTS_MULTIPOS_COUNT) @@ -428,6 +428,13 @@ enum SwitchSources { SWSRC_FIRST_TRIM SKIP, SWSRC_LAST_TRIM SKIP = SWSRC_FIRST_TRIM + 2 * MAX_TRIMS - 1, +#if NUM_TRIMS > 6 + SWSRC_TrimT7Down, + SWSRC_TrimT7Up, + SWSRC_TrimT8Down, + SWSRC_TrimT8Up, +#endif + SWSRC_FIRST_LOGICAL_SWITCH SKIP, SWSRC_LAST_LOGICAL_SWITCH SKIP = SWSRC_FIRST_LOGICAL_SWITCH + MAX_LOGICAL_SWITCHES - 1, @@ -605,7 +612,7 @@ enum Functions { #if defined(DEBUG) FUNC_MAX SKIP #else - FUNC_MAX SKIP = FUNC_TEST - 1 + FUNC_MAX SKIP = FUNC_TEST #endif }; diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index 392aefe8fba..fba828f073a 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -87,7 +87,7 @@ static inline void check_struct() CHKSIZE(CurveHeader, 4); CHKSIZE(CustomScreenData, 852); CHKTYPE(TopBarPersistentData, 444); -#elif defined(PCBNV14) +#elif defined(PCBNV14) || defined(PCBPL18) // TODO #else // Common for all variants diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index b149e4e12c0..3c8ec69cde9 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -602,7 +602,7 @@ PACK(struct CustomScreenData { #define TOPBAR_DATA #endif -#if defined(PCBHORUS) || defined(PCBTARANIS) || defined(PCBNV14) +#if defined(PCBHORUS) || defined(PCBTARANIS) || defined(PCBNV14) || defined(PCBPL18) #define SCRIPT_DATA \ NOBACKUP(ScriptData scriptsData[MAX_SCRIPTS]); #else diff --git a/radio/src/debug.h b/radio/src/debug.h index aa31b77cf1d..a5f84ddbec1 100644 --- a/radio/src/debug.h +++ b/radio/src/debug.h @@ -46,8 +46,8 @@ EXTERN_C(extern volatile uint32_t g_tmr10ms); #define debugPrintf(...) #endif -#define TRACE_TIME_FORMAT "%0.2fs: " -#define TRACE_TIME_VALUE ((float)g_tmr10ms / 100.0) +#define TRACE_TIME_FORMAT "%dms: " +#define TRACE_TIME_VALUE (g_tmr10ms * 10) #define TRACE_NOCRLF(...) debugPrintf(__VA_ARGS__) #define TRACE(f_, ...) debugPrintf((TRACE_TIME_FORMAT f_ CRLF), TRACE_TIME_VALUE, ##__VA_ARGS__) diff --git a/radio/src/gui/colorlcd/radio_calibration.cpp b/radio/src/gui/colorlcd/radio_calibration.cpp index 9c54cbea837..8ddba702d29 100644 --- a/radio/src/gui/colorlcd/radio_calibration.cpp +++ b/radio/src/gui/colorlcd/radio_calibration.cpp @@ -93,7 +93,7 @@ void RadioCalibrationPage::buildBody(FormWindow * window) deco->setSlidersVisible(true); deco->setFlightModeVisible(false); -#if defined(PCBNV14) +#if defined(PCBNV14) || defined(PCBPL18) new TextButton(window, {LCD_W - 120, LCD_H - 140, 90, 40}, "Next", [=]() -> uint8_t { nextStep(); diff --git a/radio/src/gui/colorlcd/radio_diaganas.cpp b/radio/src/gui/colorlcd/radio_diaganas.cpp index 903c32c8161..18ef7709ba9 100644 --- a/radio/src/gui/colorlcd/radio_diaganas.cpp +++ b/radio/src/gui/colorlcd/radio_diaganas.cpp @@ -177,7 +177,7 @@ class AnaCalibratedViewWindow: public AnaViewWindow { }, COLOR_THEME_PRIMARY1); lv_obj_set_grid_cell(lbl->getLvObj(), LV_GRID_ALIGN_STRETCH, 0, 5, LV_GRID_ALIGN_CENTER, 0, 1); -#if !defined(SIMU) && !defined(PCBNV14) +#if !defined(SIMU) && !defined(PCBNV14) && !defined(PCBPL18) line = newLine(grid); auto lbl2 = new StaticText(line, rect_t{}, std::string("Touch GT911 FW ver: ") + std::to_string(touchGT911fwver), COLOR_THEME_PRIMARY1); lv_obj_set_grid_cell(lbl2->getLvObj(), LV_GRID_ALIGN_STRETCH, 0, 5, LV_GRID_ALIGN_CENTER, 0, 1); diff --git a/radio/src/gui/colorlcd/radio_diagkeys.cpp b/radio/src/gui/colorlcd/radio_diagkeys.cpp index a12c102e85c..d8dee02bb92 100644 --- a/radio/src/gui/colorlcd/radio_diagkeys.cpp +++ b/radio/src/gui/colorlcd/radio_diagkeys.cpp @@ -25,7 +25,11 @@ #include "hal/rotary_encoder.h" +#if defined(PCBPL18) +static const uint8_t _trimMap[MAX_TRIMS * 2] = {8, 9, 10, 11, 12, 13, 14, 15, 2, 3, 4, 5, 0, 1, 6, 7}; +#else static const uint8_t _trimMap[MAX_TRIMS * 2] = {6, 7, 4, 5, 2, 3, 0, 1, 8, 9, 10, 11}; +#endif static EnumKeys get_ith_key(uint8_t i) { @@ -122,8 +126,13 @@ class RadioKeyDiagsWindow : public Window for (uint8_t i = 0; i < keysGetMaxTrims() * 2; i++) { coord_t y = 1 + FH + FH * (i / 2); if (i & 1) { +#if defined(PCBPL18) + dc->drawText(TRIM_COLUMN, y, "TR", COLOR_THEME_PRIMARY1); + dc->drawNumber(TRIM_COLUMN + 20, y, i / 2 + 1, COLOR_THEME_PRIMARY1); +#else dc->drawText(TRIM_COLUMN, y, "T", COLOR_THEME_PRIMARY1); dc->drawNumber(TRIM_COLUMN + 10, y, i / 2 + 1, COLOR_THEME_PRIMARY1); +#endif } displayTrimState(dc, i & 1 ? TRIM_PLUS_COLUMN : TRIM_MINUS_COLUMN, y, _trimMap[i]); } diff --git a/radio/src/gui/colorlcd/radio_ghost_module_config.cpp b/radio/src/gui/colorlcd/radio_ghost_module_config.cpp index f5976861f1c..0120f1775ff 100644 --- a/radio/src/gui/colorlcd/radio_ghost_module_config.cpp +++ b/radio/src/gui/colorlcd/radio_ghost_module_config.cpp @@ -110,12 +110,14 @@ static void ghostmoduleconfig_cb(lv_event_t* e) } } +#if defined(HARDWARE_KEYS) && !defined(PCBPL18) void RadioGhostModuleConfig::onCancel() { reusableBuffer.ghostMenu.buttonAction = GHST_BTN_JOYLEFT; reusableBuffer.ghostMenu.menuAction = GHST_MENU_CTRL_NONE; moduleState[EXTERNAL_MODULE].counter = GHST_MENU_CONTROL; } +#endif RadioGhostModuleConfig::RadioGhostModuleConfig(uint8_t moduleIdx) : Page(ICON_RADIO_TOOLS), @@ -144,7 +146,7 @@ void RadioGhostModuleConfig::buildBody(FormWindow * window) new GhostModuleConfigWindow(window, {0, 0, LCD_W, LCD_H - MENU_HEADER_HEIGHT - 5}); } -#if defined(HARDWARE_KEYS) +#if defined(HARDWARE_KEYS) && !defined(PCBPL18) void RadioGhostModuleConfig::onEvent(event_t event) { switch (event) { diff --git a/radio/src/gui/colorlcd/radio_ghost_module_config.h b/radio/src/gui/colorlcd/radio_ghost_module_config.h index d80a6991559..3d758ff37ea 100644 --- a/radio/src/gui/colorlcd/radio_ghost_module_config.h +++ b/radio/src/gui/colorlcd/radio_ghost_module_config.h @@ -28,7 +28,7 @@ class RadioGhostModuleConfig: public Page public: explicit RadioGhostModuleConfig(uint8_t moduleIdx); -#if defined(HARDWARE_KEYS) +#if defined(HARDWARE_KEYS) && !defined(PCBPL18) void onEvent(event_t event) override; void checkEvents() override; void onCancel() override; diff --git a/radio/src/gui/colorlcd/radio_version.cpp b/radio/src/gui/colorlcd/radio_version.cpp index ce97935bd25..7d38e02b685 100644 --- a/radio/src/gui/colorlcd/radio_version.cpp +++ b/radio/src/gui/colorlcd/radio_version.cpp @@ -77,13 +77,14 @@ class VersionDialog : public Dialog memclear(&reusableBuffer.hardwareAndSettings.modules, sizeof(reusableBuffer.hardwareAndSettings.modules)); reusableBuffer.hardwareAndSettings.updateTime = get_tmr10ms(); - +#if defined(HARDWARE_INTERNAL_MODULE) // Query modules if (isModulePXX2(INTERNAL_MODULE) && modulePortPowered(INTERNAL_MODULE)) { moduleState[INTERNAL_MODULE].readModuleInformation( &reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE], PXX2_HW_INFO_TX_ID, PXX2_MAX_RECEIVERS_PER_MODULE - 1); } +#endif if (isModulePXX2(EXTERNAL_MODULE) && modulePortPowered(EXTERNAL_MODULE)) { moduleState[EXTERNAL_MODULE].readModuleInformation( @@ -165,11 +166,13 @@ class VersionDialog : public Dialog void update() { +#if defined(HARDWARE_INTERNAL_MODULE) updateModule(INTERNAL_MODULE, int_name, int_module_status_w, int_status, int_rx_name_w, int_rx_name, int_rx_status_w, int_rx_status); +#endif updateModule(EXTERNAL_MODULE, ext_name, ext_module_status_w, ext_status, @@ -309,11 +312,13 @@ class VersionDialog : public Dialog { if (get_tmr10ms() >= reusableBuffer.hardwareAndSettings.updateTime) { // Query modules +#if defined(HARDWARE_INTERNAL_MODULE) if (isModulePXX2(INTERNAL_MODULE) && modulePortPowered(INTERNAL_MODULE)) { moduleState[INTERNAL_MODULE].readModuleInformation( &reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE], PXX2_HW_INFO_TX_ID, PXX2_MAX_RECEIVERS_PER_MODULE - 1); } +#endif if (isModulePXX2(EXTERNAL_MODULE) && modulePortPowered(EXTERNAL_MODULE)) { moduleState[EXTERNAL_MODULE].readModuleInformation( &reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE], @@ -332,7 +337,7 @@ RadioVersionPage::RadioVersionPage(): { } -#if defined(PCBNV14) +#if defined(PCBNV14) || defined(PCBPL18) extern const char* boardLcdType; #endif @@ -355,7 +360,7 @@ void RadioVersionPage::build(FormWindow * window) version += options[i]; } -#if defined(PCBNV14) && !defined(SIMU) +#if (defined(PCBNV14) || defined(PCBPL18)) && !defined(SIMU) version += nl; version += "LCD: "; version += boardLcdType; diff --git a/radio/src/gui/colorlcd/special_functions.cpp b/radio/src/gui/colorlcd/special_functions.cpp index 20b2056ce45..1d35d1b0a43 100644 --- a/radio/src/gui/colorlcd/special_functions.cpp +++ b/radio/src/gui/colorlcd/special_functions.cpp @@ -180,20 +180,21 @@ class SpecialFunctionEditPage : public Page case FUNC_PLAY_TRACK: case FUNC_BACKGND_MUSIC: case FUNC_PLAY_SCRIPT: + case FUNC_RGB_LED: new StaticText(line, rect_t{}, STR_VALUE, 0, COLOR_THEME_PRIMARY1); new FileChoice( line, rect_t{}, - func == FUNC_PLAY_SCRIPT - ? SCRIPTS_FUNCS_PATH + func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED + ? (func == FUNC_PLAY_SCRIPT ? SCRIPTS_FUNCS_PATH : SCRIPTS_RGB_PATH) : std::string(SOUNDS_PATH, SOUNDS_PATH_LNG_OFS) + std::string(currentLanguagePack->id, 2), - func == FUNC_PLAY_SCRIPT ? SCRIPTS_EXT : SOUNDS_EXT, + (func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED) ? SCRIPTS_EXT : SOUNDS_EXT, sizeof(cfn->play.name), [=]() { return std::string(cfn->play.name, ZLEN(cfn->play.name)); }, [=](std::string newValue) { strncpy(cfn->play.name, newValue.c_str(), sizeof(cfn->play.name)); SET_DIRTY(); - if (func == FUNC_PLAY_SCRIPT) + if (func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED) LUA_LOAD_MODEL_SCRIPTS(); }, true); // strip extension diff --git a/radio/src/hal/key_driver.cpp b/radio/src/hal/key_driver.cpp index 6529bc04d70..dc500167f8e 100644 --- a/radio/src/hal/key_driver.cpp +++ b/radio/src/hal/key_driver.cpp @@ -22,6 +22,8 @@ #include "key_driver.h" #include "definitions.h" +#include "dataconstants.h" + #include "hal_keys.inc" uint32_t keysGetSupported() diff --git a/radio/src/hal/key_driver.h b/radio/src/hal/key_driver.h index f0d20baa5f5..1701071a621 100644 --- a/radio/src/hal/key_driver.h +++ b/radio/src/hal/key_driver.h @@ -50,11 +50,7 @@ enum EnumKeys { MAX_KEYS }; -#if defined(RADIO_T20) -#define MAX_TRIMS 8 -#else -#define MAX_TRIMS 6 -#endif + // returns a bit field with each key set as (1 << KEY_xxx) uint32_t readKeys(); diff --git a/radio/src/keys.cpp b/radio/src/keys.cpp index e9cd936dfa0..54e3f3a238c 100644 --- a/radio/src/keys.cpp +++ b/radio/src/keys.cpp @@ -30,11 +30,7 @@ #include "timers_driver.h" #include "hal/watchdog_driver.h" #include "hal/rotary_encoder.h" - -// required by watchdog macro.. -#if !defined(SIMU) -#include "stm32_cmsis.h" -#endif +#include "dataconstants.h" // long key press minimum duration (x10ms), // must be less than KEY_REPEAT_DELAY diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index a1ca3c55395..69eafc19f2a 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -169,7 +169,13 @@ enum CurveRefType { #define TRIM_ELE (-2) #define TRIM_THR (-3) #define TRIM_AIL (-4) -#if defined(PCBHORUS) +#if defined(PCBPL18) + #define TRIM_T5 (-5) + #define TRIM_T6 (-6) + #define TRIM_T7 (-7) + #define TRIM_T8 (-8) + #define TRIM_LAST TRIM_T8 +#elif defined(PCBHORUS) #define TRIM_T5 (-5) #define TRIM_T6 (-6) #define TRIM_LAST TRIM_T6 diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 101d417d255..ffb7cc60477 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -203,10 +203,6 @@ extern uint8_t heartbeat; #include "keys.h" #include "pwr.h" -// #if defined(PCBFRSKY) || defined(PCBNV14) -// extern uint8_t potsPos[NUM_XPOTS]; -// #endif - bool trimDown(uint8_t idx); #if defined(KEYS_GPIO_REG_BIND) diff --git a/radio/src/opentx_types.h b/radio/src/opentx_types.h index 4f556d12c04..07bcd68b809 100644 --- a/radio/src/opentx_types.h +++ b/radio/src/opentx_types.h @@ -83,6 +83,7 @@ typedef uint32_t LcdFlags; typedef uint16_t event_t; typedef uint32_t tmr10ms_t; +typedef int32_t rotenc_t; typedef int32_t getvalue_t; typedef uint32_t mixsrc_t; typedef int32_t swsrc_t; diff --git a/radio/src/pulses/multi.cpp b/radio/src/pulses/multi.cpp index 27ddaf56cd2..e2fbd4bd6c7 100644 --- a/radio/src/pulses/multi.cpp +++ b/radio/src/pulses/multi.cpp @@ -116,12 +116,9 @@ static void sendFailsafeChannels(uint8_t*& p_buf, uint8_t module) static void setupPulsesMulti(uint8_t*& p_buf, uint8_t module) { static int counter[2] = {0,0}; //TODO - static uint8_t invert[2] = {0x00, //internal -#if defined(PCBTARANIS) || defined(PCBHORUS) || defined(PCBNV14) + static uint8_t invert[2] = { + 0x00, //internal 0x08 //external -#else - 0x00 //external -#endif }; uint8_t type=MULTI_NORMAL; diff --git a/radio/src/sdcard.cpp b/radio/src/sdcard.cpp index 9555ebb60ca..7b45c20d9f7 100644 --- a/radio/src/sdcard.cpp +++ b/radio/src/sdcard.cpp @@ -545,7 +545,7 @@ void sdMount() void sdDone() { TRACE("sdDone"); - + if (sdMounted()) { audioQueue.stopSD(); @@ -557,8 +557,10 @@ void sdDone() f_close(&g_bluetoothFile); #endif - f_mount(nullptr, "", 0); // unmount SD + f_mount(nullptr, "", 0); // unmount SD } + + storageDeInit(); } uint32_t sdMounted() diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index 9523affbbbc..e06ab5936ed 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -348,7 +348,7 @@ long OpenTxSim::onMouseMove(FXObject*,FXSelector,void*v) void OpenTxSim::updateKeysAndSwitches(bool start) { static int keys[] = { -#if defined(PCBNV14) +#if defined(PCBFLYSKY) // no keys #elif defined(PCBHORUS) KEY_Page_Up, KEY_PAGEUP, diff --git a/radio/src/storage/yaml/CMakeLists.txt b/radio/src/storage/yaml/CMakeLists.txt index b320ff016a9..6a7e537bbe6 100644 --- a/radio/src/storage/yaml/CMakeLists.txt +++ b/radio/src/storage/yaml/CMakeLists.txt @@ -20,6 +20,8 @@ elseif(PCB STREQUAL X10) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_x10.cpp) elseif(PCB STREQUAL NV14) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_nv14.cpp) +elseif(PCB STREQUAL PL18) + set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_pl18.cpp) elseif(PCB STREQUAL X7) if(PCBREV STREQUAL TPRO) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_tpro.cpp) diff --git a/radio/src/storage/yaml/yaml_datastructs.cpp b/radio/src/storage/yaml/yaml_datastructs.cpp index fe77e7c5220..3b1a2254cf1 100644 --- a/radio/src/storage/yaml/yaml_datastructs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs.cpp @@ -34,6 +34,8 @@ #include "yaml_datastructs_x10.cpp" #elif defined(PCBNV14) #include "yaml_datastructs_nv14.cpp" +#elif defined(PCBPL18) + #include "yaml_datastructs_pl18.cpp" #elif defined(PCBX7) #if defined(RADIO_TPRO) || defined(RADIO_TPROV2) #include "yaml_datastructs_tpro.cpp" diff --git a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp index 85cec0b2301..0745654ef8f 100644 --- a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp @@ -38,7 +38,7 @@ // ======== // // If any of these static_assert() fails, you need to check that -// the functions bellow are still applicable. +// the functions below are still applicable. // // Please note that the sizes used here are those from the v220 format // (see storage/conversions/yaml/datastructs_220.h) diff --git a/radio/src/storage/yaml/yaml_datastructs_pl18.cpp b/radio/src/storage/yaml/yaml_datastructs_pl18.cpp new file mode 100644 index 00000000000..283256262bd --- /dev/null +++ b/radio/src/storage/yaml/yaml_datastructs_pl18.cpp @@ -0,0 +1,915 @@ +// generated by generate_yaml.py + +// +// Enums first +// + +const struct YamlIdStr enum_HatsMode[] = { + { HATSMODE_TRIMS_ONLY, "TRIMS_ONLY" }, + { HATSMODE_KEYS_ONLY, "KEYS_ONLY" }, + { HATSMODE_SWITCHABLE, "SWITCHABLE" }, + { HATSMODE_GLOBAL, "GLOBAL" }, + { 0, NULL } +}; +const struct YamlIdStr enum_BacklightMode[] = { + { e_backlight_mode_off, "backlight_mode_off" }, + { e_backlight_mode_keys, "backlight_mode_keys" }, + { 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_MIN, "MIN" }, + { MIXSRC_MAX, "MAX" }, + { MIXSRC_TrimRud, "TrimRud" }, + { MIXSRC_TrimEle, "TrimEle" }, + { MIXSRC_TrimThr, "TrimThr" }, + { MIXSRC_TrimAil, "TrimAil" }, + { MIXSRC_TrimT5, "TrimT5" }, + { MIXSRC_TrimT6, "TrimT6" }, + { MIXSRC_TrimT7, "TrimT7" }, + { MIXSRC_TrimT8, "TrimT8" }, + { 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_TrimT7Down, "TrimT7Down" }, + { SWSRC_TrimT7Up, "TrimT7Up" }, + { SWSRC_TrimT8Down, "TrimT8Down" }, + { SWSRC_TrimT8Up, "TrimT8Up" }, + { 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", 6), + YAML_END +}; +static const struct YamlNode struct_anonymous_2[] = { + YAML_SIGNED( "val", 16 ), + YAML_UNSIGNED( "mode", 8 ), + YAML_UNSIGNED( "param", 8 ), + YAML_SIGNED( "spare", 16 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_3[] = { + YAML_SIGNED( "val1", 32 ), + YAML_SIGNED( "val2", 16 ), + YAML_END +}; +static const struct YamlNode union_anonymous_0_elmts[] = { + YAML_STRUCT("play", 48, struct_anonymous_1, NULL), + YAML_STRUCT("all", 48, struct_anonymous_2, NULL), + YAML_STRUCT("clear", 48, 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( 48 ), + YAML_PADDING( 1 ), + YAML_PADDING( 7 ), + YAML_END +}; +static const struct YamlNode struct_RadioData[] = { + YAML_UNSIGNED( "manuallyEdited", 1 ), + YAML_SIGNED( "timezoneMinutes", 3 ), + YAML_ENUM("hatsMode", 2, enum_HatsMode), + YAML_UNSIGNED( "ppmunit", 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_SIGNED( "currModel", 8 ), + YAML_UNSIGNED( "contrast", 8 ), + 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_PADDING( 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", 72, 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", 2 ), + YAML_SIGNED( "uartSampleMode", 2 ), + YAML_PADDING( 3 ), + YAML_UNSIGNED( "audioMuteEnable", 1 ), + YAML_STRING("selectedTheme", 26), + 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_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_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + YAML_UNSIGNED( "carryTrim", 1 ), + YAML_UNSIGNED( "mixWarn", 2 ), + YAML_ENUM("mltpx", 2, enum_MixerMultiplex), + YAML_PADDING( 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_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ), + 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_PADDING( 1 ), + YAML_PADDING( 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, 8, 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_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_ENUM("hatsMode", 2, enum_HatsMode), + YAML_PADDING( 2 ), + 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", 72, 64, struct_CustomFunctionData, cfn_is_active), + YAML_STRUCT("swashR", 64, struct_SwashRingData, swash_is_active), + YAML_ARRAY("flightModeData", 384, 9, struct_FlightModeData, fmd_is_active), + YAML_UNSIGNED_CUST( "thrTraceSrc", 8, r_thrSrc, w_thrSrc ), + YAML_CUSTOM("switchWarningState",r_swtchWarn,w_swtchWarn), + YAML_PADDING( 64 ), + 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( "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/targets/common/arm/CMakeLists.txt b/radio/src/targets/common/arm/CMakeLists.txt index a24ee4e8242..e7e353b02e2 100644 --- a/radio/src/targets/common/arm/CMakeLists.txt +++ b/radio/src/targets/common/arm/CMakeLists.txt @@ -22,17 +22,19 @@ option(DEBUG_USB_INTERRUPTS "Count individual USB interrupts" OFF) option(DEBUG_TIMERS "Time critical parts of the code" OFF) option(DEBUG_BLUETOOTH "Debug Bluetooth" OFF) -# option to select the default internal module -#set(DEFAULT_INTERNAL_MODULE NONE CACHE STRING "Default internal module") -set_property(CACHE DEFAULT_INTERNAL_MODULE PROPERTY STRINGS ${INTERNAL_MODULES}) - -# define variables for internal modules -foreach(module ${INTERNAL_MODULES}) - set(INTERNAL_MODULE_${module} ON CACHE BOOL "Support for ${module} internal module") - if (INTERNAL_MODULE_${module}) - message("-- Adding support for ${module} as internal module") - endif() -endforeach() +if(INTERNAL_MODULES) + # option to select the default internal module + #set(DEFAULT_INTERNAL_MODULE NONE CACHE STRING "Default internal module") + set_property(CACHE DEFAULT_INTERNAL_MODULE PROPERTY STRINGS ${INTERNAL_MODULES}) + + # define variables for internal modules + foreach(module ${INTERNAL_MODULES}) + set(INTERNAL_MODULE_${module} ON CACHE BOOL "Support for ${module} internal module") + if (INTERNAL_MODULE_${module}) + message("-- Adding support for ${module} as internal module") + endif() + endforeach() +endif() if(INTERNAL_MODULE_PXX1) add_definitions(-DHARDWARE_INTERNAL_MODULE) diff --git a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt index 117e1c6431c..85e66458cf2 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt +++ b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt @@ -69,8 +69,7 @@ if(DEBUG_SEGGER_RTT) ) endif() - -if(PCB STREQUAL X10 OR PCB STREQUAL X12S OR PCB STREQUAL NV14) +if(PCB STREQUAL X10 OR PCB STREQUAL X12S OR PCB STREQUAL NV14 OR PCB STREQUAL PL18) set(BOOTLOADER_SRC ${BOOTLOADER_SRC} ../../../../../gui/colorlcd/fonts.cpp @@ -79,7 +78,6 @@ if(PCB STREQUAL X10 OR PCB STREQUAL X12S OR PCB STREQUAL NV14) ../../../../../thirdparty/libopenui/src/bitmapbuffer.cpp ../../../../../thirdparty/libopenui/thirdparty/lz4/lz4.c ../../../../../targets/common/arm/stm32/dma2d.cpp - ../../../../../targets/common/arm/stm32/diskio_sdio.cpp ../../../../../targets/common/arm/stm32/rtc_driver.cpp ../../../../../targets/common/arm/stm32/diskio_spi_flash.cpp ../../../../../targets/common/arm/stm32/spi_flash.cpp @@ -90,12 +88,22 @@ if(PCB STREQUAL X10 OR PCB STREQUAL X12S OR PCB STREQUAL NV14) ../../../../../targets/${TARGET_DIR}/haptic_driver.cpp ) + if(NOT PCB STREQUAL PL18) + set(BOOTLOADER_SRC ${BOOTLOADER_SRC} + ../../../../../targets/common/arm/stm32/diskio_sdio.cpp + ) + else() + set(BOOTLOADER_SRC ${BOOTLOADER_SRC} + ../../../../../targets/pl18/key_driver.cpp + ) + endif() + # Add LVGL sources foreach(LVGL_FILE ${LVGL_SRC_FILES_MINIMAL}) set(BOOTLOADER_SRC ${BOOTLOADER_SRC} ../../../../../${LVGL_FILE}) endforeach() - if(NOT PCB STREQUAL NV14) + if(NOT (PCB STREQUAL NV14 OR PCB STREQUAL PL18)) set(BOOTLOADER_SRC ${BOOTLOADER_SRC} ../../../../../targets/${TARGET_DIR}/led_driver.cpp diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp index a83ab59afd2..32a1bdce27f 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp @@ -56,12 +56,17 @@ #define APP_START_ADDRESS (uint32_t)(FIRMWARE_ADDRESS + BOOTLOADER_SIZE) -#if defined(EEPROM) +#if defined(EEPROM) || defined(SPI_FLASH) #define MAIN_MENU_LEN 3 #else #define MAIN_MENU_LEN 2 #endif +#if defined(SPI_FLASH) + #include "spi_flash.h" + #define SEL_CLEAR_FLASH_STORAGE_MENU_LEN 2 +#endif + typedef void (*voidFunction)(void); #define jumpTo(addr) do { \ @@ -369,6 +374,10 @@ int bootloaderMain() memoryType = MEM_EEPROM; state = ST_DIR_CHECK; break; +#elif defined(SPI_FLASH) + case 1: + state = ST_CLEAR_FLASH_CHECK; + break; #endif default: if(vpos < bootloaderGetMenuItemCount(MAIN_MENU_LEN-1)) @@ -511,6 +520,35 @@ int bootloaderMain() else if (memoryType == MEM_EEPROM && eepromWritten >= EEPROM_SIZE) { state = ST_FLASH_DONE; // Backstop } +#endif +#if defined(SPI_FLASH) + } else if (state == ST_CLEAR_FLASH_CHECK) { + bootloaderDrawScreen(state, vpos); + if (event == EVT_KEY_REPT(KEY_DOWN) || event == EVT_KEY_FIRST(KEY_DOWN)) { + if (vpos < SEL_CLEAR_FLASH_STORAGE_MENU_LEN - 1) { vpos++; } + continue; + } + if (event == EVT_KEY_REPT(KEY_UP) || event == EVT_KEY_FIRST(KEY_UP)) { + if (vpos > 0) { vpos--; } + continue; + } + if (event == EVT_KEY_LONG(KEY_ENTER) && vpos == 0) + { + state = ST_CLEAR_FLASH; + } else if (event == EVT_KEY_BREAK(KEY_EXIT) || + (event == EVT_KEY_BREAK(KEY_ENTER) && vpos == 1) ) { + vpos = 0; + state = ST_START; + continue; + } + } else if (state == ST_CLEAR_FLASH) { + bootloaderDrawScreen(state, 0); + lcdRefresh(); + if(event != EVT_KEY_BREAK(KEY_ENTER)) + continue; + flashSpiEraseAll(); + vpos = 0; + state = ST_START; #endif } else if (state == ST_RADIO_MENU) { if(bootloaderRadioMenu(radioMenuItem, event)) @@ -565,6 +603,6 @@ int bootloaderMain() return 0; } -#if !defined(SIMU) && (defined(PCBHORUS) || defined(PCBNV14)) +#if !defined(SIMU) && (defined(PCBHORUS) || defined(PCBFLYSKY)) void *__dso_handle = nullptr; #endif diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.h b/radio/src/targets/common/arm/stm32/bootloader/boot.h index fd93b3ef567..5f747239fef 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/boot.h +++ b/radio/src/targets/common/arm/stm32/bootloader/boot.h @@ -54,6 +54,10 @@ enum BootloaderState { ST_FLASH_DONE, ST_RESTORE_MENU, ST_USB, +#if defined(SPI_FLASH) + ST_CLEAR_FLASH_CHECK, + ST_CLEAR_FLASH, +#endif ST_RADIO_MENU, ST_REBOOT, }; diff --git a/radio/src/targets/common/arm/stm32/diskio_spi_flash.cpp b/radio/src/targets/common/arm/stm32/diskio_spi_flash.cpp index bdd7db86785..3f8dc014b6f 100644 --- a/radio/src/targets/common/arm/stm32/diskio_spi_flash.cpp +++ b/radio/src/targets/common/arm/stm32/diskio_spi_flash.cpp @@ -30,6 +30,7 @@ #include "drivers/frftl.h" static FrFTL _frftl; +static bool frftlInitDone = false; static bool flashRead(uint32_t addr, uint8_t* buf, uint32_t len) { @@ -89,6 +90,7 @@ static DSTATUS spi_flash_initialize(BYTE lun) if (!ftlInit(&_frftl, &_frftl_cb, flashSizeMB)) { return STA_NOINIT; } + frftlInitDone = true; #endif return 0; @@ -102,7 +104,7 @@ static DSTATUS spi_flash_status (BYTE lun) static DRESULT spi_flash_read(BYTE lun, BYTE * buff, DWORD sector, UINT count) { #if defined(USE_FLASH_FTL) - while(count) { + while(frftlInitDone && count) { if(!ftlRead(&_frftl, sector, (uint8_t*)buff)) { return RES_ERROR; @@ -122,7 +124,7 @@ static DRESULT spi_flash_read(BYTE lun, BYTE * buff, DWORD sector, UINT count) static DRESULT spi_flash_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count) { #if defined(USE_FLASH_FTL) - if (!ftlWrite(&_frftl, sector, count, (uint8_t*)buff)) { + if (frftlInitDone && !ftlWrite(&_frftl, sector, count, (uint8_t*)buff)) { return RES_ERROR; } #else @@ -166,7 +168,7 @@ static DRESULT spi_flash_ioctl(BYTE lun, BYTE ctrl, void *buff) case CTRL_SYNC: #if defined(USE_FLASH_FTL) - if (!ftlSync(&_frftl)) { + if (frftlInitDone && !ftlSync(&_frftl)) { res = RES_ERROR; } #else @@ -176,7 +178,7 @@ static DRESULT spi_flash_ioctl(BYTE lun, BYTE ctrl, void *buff) case CTRL_TRIM: #if defined(USE_FLASH_FTL) - if (!ftlTrim(&_frftl, *(DWORD*)buff, 1 + *((DWORD*)buff + 1) - *(DWORD*)buff)) { + if (frftlInitDone && !ftlTrim(&_frftl, *(DWORD*)buff, 1 + *((DWORD*)buff + 1) - *(DWORD*)buff)) { res = RES_ERROR; } #endif diff --git a/radio/src/targets/common/arm/stm32/pwr_driver.cpp b/radio/src/targets/common/arm/stm32/pwr_driver.cpp index 46a50b36e72..fb5b7e49e96 100644 --- a/radio/src/targets/common/arm/stm32/pwr_driver.cpp +++ b/radio/src/targets/common/arm/stm32/pwr_driver.cpp @@ -38,9 +38,11 @@ void pwrInit() #endif // Internal module power +#if defined(HARDWARE_INTERNAL_MODULE) INTERNAL_MODULE_OFF(); GPIO_InitStructure.GPIO_Pin = INTMODULE_PWR_GPIO_PIN; GPIO_Init(INTMODULE_PWR_GPIO, &GPIO_InitStructure); +#endif // External module power EXTERNAL_MODULE_PWR_OFF(); diff --git a/radio/src/targets/common/arm/stm32/spi_flash.cpp b/radio/src/targets/common/arm/stm32/spi_flash.cpp index 100ce9559ec..c9e25567837 100644 --- a/radio/src/targets/common/arm/stm32/spi_flash.cpp +++ b/radio/src/targets/common/arm/stm32/spi_flash.cpp @@ -223,10 +223,19 @@ static bool flash_read_sfdp(SpiFlashDescriptor* desc) return true; } +void flashSpiSync() +{ + uint8_t status; + do { + flash_do_cmd(FLASH_CMD_STATUS, 0, &status, 1); + } while (status & 0x01); +} + bool flashSpiInit(void) { stm32_spi_init(&_flash_spi); delay_ms(1); + flashSpiSync(); if (!flash_read_id(&_flashDescriptor)) { return false; @@ -239,14 +248,6 @@ bool flashSpiInit(void) return true; } -void flashSpiSync() -{ - uint8_t status; - do { - flash_do_cmd(FLASH_CMD_STATUS, 0, &status, 1); - } while (status & 0x01); -} - uint32_t flashSpiGetSize() { return (1UL << _flashDescriptor.log2Size); diff --git a/radio/src/targets/common/arm/stm32/stm32_adc.cpp b/radio/src/targets/common/arm/stm32/stm32_adc.cpp index 4244a5d96a9..48c98278ee9 100644 --- a/radio/src/targets/common/arm/stm32/stm32_adc.cpp +++ b/radio/src/targets/common/arm/stm32/stm32_adc.cpp @@ -26,9 +26,10 @@ #include "opentx.h" -#define ADC_COMMON ((ADC_Common_TypeDef *) ADC_BASE) -#define MAX_ADC_INPUTS 32 -#define OVERSAMPLING 4 +#define ADC_COMMON ((ADC_Common_TypeDef *)ADC_BASE) +#define OVERSAMPLING 4 + +#define SAMPLING_TIMEOUT_US 500 // Please note that we use the same prio for DMA TC and ADC IRQs // to avoid issues with preemption between these 2 @@ -43,7 +44,7 @@ static volatile uint32_t _adc_inhibit_mask; static uint16_t _adc_dma_buffer[MAX_ADC_INPUTS] __DMA; // ADCs started -static uint8_t _adc_started_mask; +static volatile uint8_t _adc_started_mask; static volatile uint8_t _adc_completed; static const stm32_adc_t* _adc_ADCs; @@ -532,8 +533,14 @@ void stm32_hal_adc_wait_completion(const stm32_adc_t* ADCs, uint8_t n_ADC, (void)inputs; (void)n_inputs; + auto timeout = timersGetUsTick(); while(!_adc_completed) { // busy wait + if ((uint32_t)(timersGetUsTick() - timeout) >= SAMPLING_TIMEOUT_US) { + TRACE("ADC timeout"); + _adc_started_mask = 0; + return; + } } } @@ -572,8 +579,7 @@ static void _adc_chain_conversions(const stm32_adc_t* adc) void stm32_hal_adc_dma_isr(const stm32_adc_t* adc) { // Disable IRQ - auto dma_stream = _dma_get_stream(adc->DMAx, adc->DMA_Stream); - CLEAR_BIT(dma_stream->CR, DMA_SxCR_TCIE | DMA_SxCR_TEIE | DMA_SxCR_DMEIE); + adc_dma_clear_flags(adc->DMAx, adc->DMA_Stream); uint16_t* dma_buffer = _adc_dma_buffer + adc->offset; copy_adc_values(dma_buffer, adc, _adc_inputs); diff --git a/radio/src/targets/common/arm/stm32/stm32_adc.h b/radio/src/targets/common/arm/stm32/stm32_adc.h index 9d73a709988..97ee324e1dc 100644 --- a/radio/src/targets/common/arm/stm32/stm32_adc.h +++ b/radio/src/targets/common/arm/stm32/stm32_adc.h @@ -24,6 +24,7 @@ #include "stm32_hal_ll.h" #include "hal/adc_driver.h" +#define MAX_ADC_INPUTS 32 struct stm32_adc_input_t { GPIO_TypeDef* GPIOx; diff --git a/radio/src/targets/common/arm/stm32/usb_bsp.c b/radio/src/targets/common/arm/stm32/usb_bsp.c index 1317a11a87c..26a964749e9 100644 --- a/radio/src/targets/common/arm/stm32/usb_bsp.c +++ b/radio/src/targets/common/arm/stm32/usb_bsp.c @@ -49,7 +49,8 @@ void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev) GPIO_PinAFConfig(USB_GPIO, USB_GPIO_PinSource_DM, USB_GPIO_AF); GPIO_PinAFConfig(USB_GPIO, USB_GPIO_PinSource_DP, USB_GPIO_AF); - + +#if defined(USB_GPIO_PIN_VBUS) /* Configure VBUS Pin */ GPIO_InitStructure.GPIO_Pin = USB_GPIO_PIN_VBUS; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; @@ -57,6 +58,7 @@ void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev) GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(USB_GPIO, &GPIO_InitStructure); +#endif RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE) ; diff --git a/radio/src/targets/common/arm/stm32/usb_conf.h b/radio/src/targets/common/arm/stm32/usb_conf.h index 22f3b2656db..337195ed4c9 100644 --- a/radio/src/targets/common/arm/stm32/usb_conf.h +++ b/radio/src/targets/common/arm/stm32/usb_conf.h @@ -29,6 +29,8 @@ #include "stm32f2xx.h" #endif +#include "hal.h" + /* USB Core and PHY interface configuration. Tip: To avoid modifying these defines each time you need to change the USB configuration, you can declare the needed define in your toolchain @@ -97,7 +99,9 @@ #endif /****************** USB OTG MISC CONFIGURATION ********************************/ +#if defined(USB_GPIO_PIN_VBUS) #define VBUS_SENSING_ENABLED +#endif /****************** USB OTG MODE CONFIGURATION ********************************/ //#define USE_HOST_MODE diff --git a/radio/src/targets/common/arm/stm32/usb_driver.cpp b/radio/src/targets/common/arm/stm32/usb_driver.cpp index 57545f2e90b..67f43716dae 100644 --- a/radio/src/targets/common/arm/stm32/usb_driver.cpp +++ b/radio/src/targets/common/arm/stm32/usb_driver.cpp @@ -57,6 +57,7 @@ void setSelectedUsbMode(int mode) selectedUsbMode = usbMode(mode); } +#if defined(USB_GPIO_PIN_VBUS) int usbPlugged() { static uint8_t debouncedState = 0; @@ -71,6 +72,7 @@ int usbPlugged() return debouncedState; } +#endif USB_OTG_CORE_HANDLE USB_OTG_dev; diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 8d409d6cf71..62b2a30e399 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -158,7 +158,6 @@ add_definitions(-DPCBHORUS -DSTM32F429_439xx -DSTM32F429xx -DSDRAM -DCCMRAM -DCO add_definitions(-DEEPROM_VARIANT=0 -DAUDIO -DVOICE -DRTCLOCK) add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE}) add_definitions(-DPWR_BUTTON_${PWR_BUTTON}) -add_definitions(-DHARDWARE_TRAINER_JACK) add_definitions(-DSTM32_SUPPORT_32BIT_TIMERS) set(SDRAM ON) diff --git a/radio/src/targets/nv14/CMakeLists.txt b/radio/src/targets/nv14/CMakeLists.txt index cc502c9307b..3913b075ed1 100644 --- a/radio/src/targets/nv14/CMakeLists.txt +++ b/radio/src/targets/nv14/CMakeLists.txt @@ -19,7 +19,6 @@ set(BITMAPS_DIR 480x272) set(HARDWARE_EXTERNAL_MODULE YES) set(TARGET_DIR nv14) -add_definitions(-DHARDWARE_TRAINER_JACK) set(RTC_BACKUP_RAM YES) set(PPM_LIMITS_SYMETRICAL YES) diff --git a/radio/src/targets/nv14/board.cpp b/radio/src/targets/nv14/board.cpp index becfd623c3c..2c1ba8680dd 100644 --- a/radio/src/targets/nv14/board.cpp +++ b/radio/src/targets/nv14/board.cpp @@ -38,7 +38,6 @@ #include "flysky_gimbal_driver.h" #include "timers_driver.h" -#include "lcd_driver.h" #include "lcd_driver.h" #include "battery_driver.h" #include "touch_driver.h" @@ -73,7 +72,8 @@ void delay_self(int count) for (; count > 0; count--); } } -#define RCC_AHB1PeriphMinimum (PWR_RCC_AHB1Periph |\ + +#define RCC_AHB1PeriphMinimum (PWR_RCC_AHB1Periph | \ LCD_RCC_AHB1Periph |\ BACKLIGHT_RCC_AHB1Periph |\ SDRAM_RCC_AHB1Periph \ diff --git a/radio/src/targets/nv14/board.h b/radio/src/targets/nv14/board.h index af203d5de4b..19f50e6a643 100644 --- a/radio/src/targets/nv14/board.h +++ b/radio/src/targets/nv14/board.h @@ -115,25 +115,17 @@ extern HardwareOptions hardwareOptions; #endif // defined(SIMU) #define EXTERNAL_MODULE_PWR_OFF EXTERNAL_MODULE_OFF -#define IS_UART_MODULE(port) (port == INTERNAL_MODULE) -#define IS_PXX2_INTERNAL_ENABLED() (false) #if !defined(NUM_FUNCTIONS_SWITCHES) #define NUM_FUNCTIONS_SWITCHES 0 #endif -#define NUM_TRIMS_KEYS (NUM_TRIMS * 2) - -#define DEFAULT_STICK_DEADZONE 2 - -// 2 pots without detent -#define DEFAULT_POTS_CONFIG \ - (POT_WITHOUT_DETENT << 0) + \ - (POT_WITHOUT_DETENT << 2) +#define DEFAULT_STICK_DEADZONE 2 #define BATTERY_WARN 36 // 3.6V #define BATTERY_MIN 35 // 3.5V #define BATTERY_MAX 42 // 4.2V +#define BATTERY_DIVIDER 2942 #if defined(__cplusplus) && !defined(SIMU) extern "C" { @@ -275,6 +267,4 @@ bool touchPanelEventOccured(); struct TouchState touchPanelRead(); struct TouchState getInternalTouchState(); -#define BATTERY_DIVIDER 2942 - #endif // _BOARD_H_ diff --git a/radio/src/targets/pl18/CMakeLists.txt b/radio/src/targets/pl18/CMakeLists.txt new file mode 100644 index 00000000000..10eb2ed1469 --- /dev/null +++ b/radio/src/targets/pl18/CMakeLists.txt @@ -0,0 +1,167 @@ +option(UNEXPECTED_SHUTDOWN "Enable the Unexpected Shutdown screen" ON) +option(PXX1 "PXX1 protocol support" ON) +option(PXX2 "PXX2 protocol support" OFF) +option(AFHDS3 "AFHDS3 TX Module" ON) +option(MULTIMODULE "DIY Multiprotocol TX Module (https://github.com/pascallanger/DIY-Multiprotocol-TX-Module)" ON) +option(GHOST "Ghost TX Module" ON) +option(MODULE_SIZE_STD "Standard size TX Module" ON) +option(LUA_MIXER "Enable LUA mixer/model scripts support" ON) + +set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)") +set(CPU_TYPE STM32F4) +set(HSE_VALUE 12000000) +set(SDCARD YES) +set(STORAGE_MODELSLIST YES) +set(HAPTIC YES) +set(GUI_DIR colorlcd) +set(BITMAPS_DIR 480x272) +set(TARGET_DIR pl18) +set(LINKER_SCRIPT targets/pl18/stm32f4_flash.ld) +set(RTC_BACKUP_RAM YES) +set(PPM_LIMITS_SYMETRICAL YES) +set(USB_SERIAL ON CACHE BOOL "Enable USB serial (CDC)") +set(HARDWARE_EXTERNAL_MODULE YES) +set(WIRELESS_CHARGER YES) + +#option(STICKS_DEAD_ZONE "Enable sticks dead zone" YES) +#option(AFHDS2 "Support for AFHDS2" OFF) + +# for size report script +set(CPU_TYPE_FULL STM32F429xI) +set(TARGET_LINKER_DIR stm32f429_sdram) +set(TARGET_LINKER_PARAMS "-Wl,--defsym=__SDRAM_START__=0xC0000000") +set(SIZE_TARGET_MEM_DEFINE "MEM_SIZE_SDRAM1=8192") + +#set(RF_BAUD_RATE 921600 230400 115200 57600 38400 19200 9600 4800 2400 1200) +#set(PCB_RF_BAUD 921600 CACHE STRING "INTERNAL_MODULE_BAUDRATE: ${RF_BAUD_RATE}") +#set_property(CACHE PCB_RF_BAUD PROPERTY STRINGS ${RF_BAUD_RATE}) + +add_definitions(-DPCBPL18 -DPCBFLYSKY) +add_definitions(-DBATTERY_CHARGE) +add_definitions(-DSOFTWARE_VOLUME) +add_definitions(-DSPI_FLASH) +add_definitions(-DSTM32_SUPPORT_32BIT_TIMERS) + +if(PCBREV STREQUAL PL18EV) + set(FLAVOUR pl18ev) + add_definitions(-DRADIO_PL18EV) +else() + set(FLAVOUR pl18) + add_definitions(-DRADIO_PL18) + + # Defines internal modules for PL18 via UART7 + set(INTERNAL_MODULES MULTI CACHE STRING "Internal modules") + set(DEFAULT_INTERNAL_MODULE MULTIMODULE CACHE STRING "Default internal module") +endif() + +set(BITMAPS_TARGET pl18_bitmaps) +set(FONTS_TARGET x12_fonts) +set(LCD_DRIVER lcd_driver.cpp) +set(TOUCH_DRIVER touch_driver.cpp) +set(HARDWARE_TOUCH YES) +set(RADIO_DEPENDENCIES ${RADIO_DEPENDENCIES} ${BITMAPS_TARGET}) +set(FIRMWARE_DEPENDENCIES datacopy) + +set(HARDWARE_TOUCH ON) +set(SOFTWARE_KEYBOARD ON) +set(FLYSKY_GIMBAL ON) + +add_definitions( + -DSTM32F429_439xx -DSTM32F429xx + -DSDRAM -DCCMRAM -DCOLORLCD -DLIBOPENUI + -DHARDWARE_TOUCH -DHARDWARE_KEYS + -DSOFTWARE_KEYBOARD -DUSE_HATS_AS_KEYS) + +set(SDRAM ON) + +add_definitions(-DEEPROM_VARIANT=0 -DAUDIO -DVOICE -DRTCLOCK) +add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE}) +add_definitions(-DPWR_BUTTON_${PWR_BUTTON}) +add_definitions(-DCROSSFIRE_NATIVE) +add_definitions(-DHARDWARE_EXTERNAL_MODULE) + +if(WIRELESS_CHARGER) + add_definitions(-DWIRELESS_CHARGER) +endif() + +if(STICKS_DEAD_ZONE) + add_definitions(-DSTICK_DEAD_ZONE) +endif() + +if(NOT UNEXPECTED_SHUTDOWN) + add_definitions(-DNO_UNEXPECTED_SHUTDOWN) +endif() + +set(AFHDS3 ON) + +# VCP CLI +set(ENABLE_SERIAL_PASSTHROUGH ON CACHE BOOL "Enable serial passthrough") +set(CLI ON CACHE BOOL "Enable CLI") + +include_directories(${RADIO_SRC_DIR}/fonts/colorlcd gui/${GUI_DIR} gui/${GUI_DIR}/layouts) + +file(GLOB THEMES_SRC RELATIVE ${RADIO_SRC_DIR}/gui/colorlcd ${RADIO_SRC_DIR}/gui/colorlcd/themes/*.cpp) +file(GLOB LAYOUTS_SRC RELATIVE ${RADIO_SRC_DIR}/gui/colorlcd ${RADIO_SRC_DIR}/gui/colorlcd/layouts/*.cpp) +file(GLOB WIDGETS_SRC RELATIVE ${RADIO_SRC_DIR}/gui/colorlcd ${RADIO_SRC_DIR}/gui/colorlcd/widgets/*.cpp) + +set(SRC + ${SRC} + io/frsky_firmware_update.cpp + ) + +set(GVAR_SCREEN model_gvars.cpp) + +if(BOOTLOADER) + set(FIRMWARE_TARGET_SRC + ${FIRMWARE_TARGET_SRC} + ../common/arm/loadboot.cpp + ) +endif() + +set(SRC + ${SRC} + io/frsky_firmware_update.cpp + io/multi_firmware_update.cpp + ) + +if (MULTIMODULE) + add_definitions(-DMULTI_PROTOLIST) + set(SRC ${SRC} + io/multi_protolist.cpp + ) +endif() + +set(FIRMWARE_TARGET_SRC + ${FIRMWARE_TARGET_SRC} + ${LCD_DRIVER} + ${TOUCH_DRIVER} + board.cpp + key_driver.cpp + battery_driver.cpp + backlight_driver.cpp + led_driver.cpp + sdram_driver.c + ) + +set(FIRMWARE_SRC + ${FIRMWARE_SRC} + targets/common/arm/stm32/audio_dac_driver.cpp + targets/common/arm/stm32/dma2d.cpp + targets/common/arm/stm32/spi_flash.cpp + targets/common/arm/stm32/diskio_spi_flash.cpp + targets/common/arm/stm32/stm32_ws2812.cpp + boards/generic_stm32/rgb_leds.cpp + drivers/frftl.cpp + ) + +# Make malloc() thread-safe +add_definitions(-DTHREADSAFE_MALLOC) + +set(STM32LIB_SRC + STM32F4xx_StdPeriph_Driver/src/stm32f4xx_sdio.c + STM32F4xx_StdPeriph_Driver/src/stm32f4xx_fmc.c + STM32F4xx_StdPeriph_Driver/src/stm32f4xx_ltdc.c + STM32F4xx_StdPeriph_Driver/src/stm32f4xx_tim.c + STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dma2d.c + ) + diff --git a/radio/src/targets/pl18/backlight_driver.cpp b/radio/src/targets/pl18/backlight_driver.cpp new file mode 100644 index 00000000000..3ddd078c2c6 --- /dev/null +++ b/radio/src/targets/pl18/backlight_driver.cpp @@ -0,0 +1,95 @@ +/* + * 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 "opentx_types.h" +#include "board.h" + +#include "globals.h" +#include "lcd_driver.h" + +void backlightLowInit( void ) +{ + RCC_AHB1PeriphClockCmd(BACKLIGHT_RCC_AHB1Periph, ENABLE); + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = BACKLIGHT_GPIO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_Init(BACKLIGHT_GPIO, &GPIO_InitStructure); + GPIO_WriteBit( BACKLIGHT_GPIO, BACKLIGHT_GPIO_PIN, Bit_RESET ); +} + +void backlightInit() +{ + // PIN init + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = BACKLIGHT_GPIO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(BACKLIGHT_GPIO, &GPIO_InitStructure); + GPIO_PinAFConfig(BACKLIGHT_GPIO, BACKLIGHT_GPIO_PinSource, BACKLIGHT_GPIO_AF); + + // TODO review this when the timer will be chosen + BACKLIGHT_TIMER->ARR = 100; + BACKLIGHT_TIMER->PSC = BACKLIGHT_TIMER_FREQ / 1000000 - 1; // 10kHz (same as FrOS) + BACKLIGHT_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1PE; // PWM mode 1 + BACKLIGHT_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1NE; + BACKLIGHT_TIMER->CCR1 = 100; // 100% on init + BACKLIGHT_TIMER->EGR = TIM_EGR_UG; + BACKLIGHT_TIMER->CR1 |= TIM_CR1_CEN; // Counter enable + BACKLIGHT_TIMER->BDTR |= TIM_BDTR_MOE; +} + +uint8_t lastDutyCycle = 0; + +void backlightEnable(uint8_t dutyCycle) +{ + BACKLIGHT_TIMER->CCR1 = dutyCycle; + if(!dutyCycle) { + //experimental to turn off LCD when no backlight + if(lcdOffFunction) lcdOffFunction(); + } + else if(!lastDutyCycle) { + if(lcdOnFunction) lcdOnFunction(); + else lcdInit(); + } + lastDutyCycle = dutyCycle; +} + +void lcdOff() { + backlightEnable(0); +} + +void lcdOn(){ + if(lcdOnFunction) lcdOnFunction(); + else lcdInit(); + backlightEnable(BACKLIGHT_LEVEL_MAX); +} + +bool boardBacklightOn; + +bool isBacklightEnabled() +{ + return boardBacklightOn; +} diff --git a/radio/src/targets/pl18/battery_driver.cpp b/radio/src/targets/pl18/battery_driver.cpp new file mode 100644 index 00000000000..b12a1ea7ff2 --- /dev/null +++ b/radio/src/targets/pl18/battery_driver.cpp @@ -0,0 +1,436 @@ +/* + * 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 "opentx.h" +#include "battery_driver.h" + +#define __BATTERY_DRIVER_C__ + +#define BATTERY_W 140 +#define BATTERY_H 200 +#define BATTERY_TOP ((LCD_H - BATTERY_H)/2) +#define BATTERY_CONNECTOR_W 32 +#define BATTERY_CONNECTOR_H 10 +#define BATTERY_BORDER 4 +#define BATTERY_W_INNER (BATTERY_W - 2*BATTERY_BORDER) +#define BATTERY_H_INNER (BATTERY_H - 2*BATTERY_BORDER) +#define BATTERY_TOP_INNER (BATTERY_TOP + BATTERY_BORDER) + +#define UCHARGER_SAMPLING_CNT 10 +#define UCHARGER_CHARGING_SAMPLING_CNT 10 +#define WCHARGER_SAMPLING_CNT 30 +#define WCHARGER_CHARGING_SAMPLING_CNT 10 +#define WCHARGER_LOW_CURRENT_DELAY_CNT 6000 +#define WCHARGER_HIGH_CURRENT_DELAY_CNT 24000 + +typedef struct +{ + bool hasCharger : 1; + bool isChargeEnd : 1; + bool isChargerDetectionReady : 1; + bool isChargingDetectionReady : 1; + bool isHighCurrent : 1; + uint8_t chargerSamplingCount; + uint8_t chargingSamplingCount; + uint8_t chargeEndSamplingCount; +} STRUCT_BATTERY_CHARGER; + +STRUCT_BATTERY_CHARGER uCharger; // USB charger +#if defined(WIRELESS_CHARGER) +STRUCT_BATTERY_CHARGER wCharger; // Wireless charger +uint16_t wirelessLowCurrentDelay = 0; +uint16_t wirelessHighCurrentDelay = 0; +#endif + +void chargerDetection(STRUCT_BATTERY_CHARGER* charger, uint8_t chargerPinActive, uint8_t samplingCountThreshold) +{ + if ((charger->hasCharger && chargerPinActive) || (!charger->hasCharger && !chargerPinActive)) + { + charger->chargerSamplingCount = 0; + } + else + { + charger->chargerSamplingCount++; + if (charger->chargerSamplingCount >= samplingCountThreshold) + { + charger->chargerSamplingCount = 0; + charger->hasCharger = !charger->hasCharger; + charger->isChargerDetectionReady = true; + } + } +} + +void resetChargeEndDetection(STRUCT_BATTERY_CHARGER* charger) +{ + charger->isChargeEnd = false; + charger->isChargingDetectionReady = false; + charger->chargingSamplingCount = 0; + charger->isHighCurrent = false; +} + +void chargeEndDetection(STRUCT_BATTERY_CHARGER* charger, uint8_t chargeEndPinActive, uint8_t samplingCountThreshold) +{ + if (charger->isChargeEnd) + { + if (chargeEndPinActive) + { + charger->chargingSamplingCount = 0; + if (charger->isChargingDetectionReady) + { + charger->chargeEndSamplingCount = 0; + } + else + { + charger->chargeEndSamplingCount++; + if (charger->chargeEndSamplingCount >= samplingCountThreshold) + { + charger->chargeEndSamplingCount = 0; + charger->isChargingDetectionReady = true; + } + } + } + else + { + charger->chargeEndSamplingCount = 0; + charger->chargingSamplingCount++; + if (charger->chargingSamplingCount >= samplingCountThreshold) + { + charger->chargingSamplingCount = 0; + charger->isChargeEnd = false; + charger->isChargingDetectionReady = true; + } + } + } + else + { + if (!chargeEndPinActive) + { + charger->chargeEndSamplingCount = 0; + if (charger->isChargingDetectionReady) + { + charger->chargingSamplingCount = 0; + } + else + { + charger->chargingSamplingCount++; + if (charger->chargingSamplingCount >= samplingCountThreshold) + { + charger->chargingSamplingCount = 0; + charger->isChargingDetectionReady = true; + } + } + } + else + { + charger->chargingSamplingCount = 0; + charger->chargeEndSamplingCount++; + if (charger->chargeEndSamplingCount >= samplingCountThreshold) + { + charger->chargeEndSamplingCount = 0; + charger->isChargeEnd = true; + charger->isChargingDetectionReady = true; + } + } + } +} + +uint16_t get_battery_charge_state() +{ + uint16_t state = CHARGE_UNKNOWN; + + chargerDetection(&uCharger, IS_UCHARGER_ACTIVE(), UCHARGER_SAMPLING_CNT); + if (uCharger.isChargerDetectionReady) + { + if (uCharger.hasCharger) // USB charger can be detected properly no matter it is enabled or not + { + ENABLE_UCHARGER(); + chargeEndDetection(&uCharger, IS_UCHARGER_CHARGE_END_ACTIVE(), UCHARGER_CHARGING_SAMPLING_CNT); + if (uCharger.isChargingDetectionReady) + { + if (uCharger.isChargeEnd) + { + state = CHARGE_FINISHED; + } + else + { + state = CHARGE_STARTED; + } + } + } + else + { + resetChargeEndDetection(&uCharger); + + // Disable USB charger if it is not present, so that wireless charger can be detected properly + DISABLE_UCHARGER(); + } + } + +#if defined(WIRELESS_CHARGER) + chargerDetection(&wCharger, IS_WCHARGER_ACTIVE(), WCHARGER_SAMPLING_CNT); + if (wCharger.isChargerDetectionReady) + { + if (wCharger.hasCharger) // Wireless charger can only be detected when USB charger is disabled + { + chargeEndDetection(&wCharger, IS_WCHARGER_CHARGE_END_ACTIVE(), WCHARGER_CHARGING_SAMPLING_CNT); + if (wCharger.isChargingDetectionReady) + { + if (wCharger.isChargeEnd) + { + state = CHARGE_FINISHED; + } + else + { + state = CHARGE_STARTED; + } + } + + // Charge current control + wirelessLowCurrentDelay = 0; + if (wirelessHighCurrentDelay >= WCHARGER_HIGH_CURRENT_DELAY_CNT) + { + wCharger.isHighCurrent = true; + WCHARGER_CURRENT_HIGH(); + } + else + { + wirelessHighCurrentDelay++; + } + } + else + { + resetChargeEndDetection(&wCharger); + + // Charge current control + wirelessHighCurrentDelay = 0; + if (wirelessLowCurrentDelay >= WCHARGER_LOW_CURRENT_DELAY_CNT) + { + wCharger.isHighCurrent = false; + WCHARGER_CURRENT_LOW(); + } + else + { + wirelessLowCurrentDelay++; + } + } + } + +#endif + + return state; +} + +bool isChargerActive() +{ +#if defined(WIRELESS_CHARGER) + while (!(uCharger.isChargerDetectionReady && wCharger.isChargerDetectionReady)) + { + get_battery_charge_state(); + delay_ms(10); + } + return uCharger.hasCharger || wCharger.hasCharger; +#else + while (!uCharger.isChargerDetectionReady) + { + get_battery_charge_state(); + delay_ms(10); + } + return uCharger.hasCharger; +#endif +} + +void battery_charge_init() +{ + GPIO_InitTypeDef GPIO_InitStructure; + + // Input pins + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + + // USB charger status pins + GPIO_InitStructure.GPIO_Pin = UCHARGER_GPIO_PIN; + GPIO_Init(UCHARGER_GPIO, &GPIO_InitStructure); + GPIO_InitStructure.GPIO_Pin = UCHARGER_CHARGE_END_GPIO_PIN; + GPIO_Init(UCHARGER_CHARGE_END_GPIO, &GPIO_InitStructure); + +#if defined(WIRELESS_CHARGER) + // Wireless charger status pins + GPIO_InitStructure.GPIO_Pin = WCHARGER_GPIO_PIN; + GPIO_Init(WCHARGER_GPIO, &GPIO_InitStructure); + GPIO_InitStructure.GPIO_Pin = WCHARGER_CHARGE_END_GPIO_PIN; + GPIO_Init(WCHARGER_CHARGE_END_GPIO, &GPIO_InitStructure); +#endif + + // Output pins + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + + // USB charger control pins + GPIO_InitStructure.GPIO_Pin = UCHARGER_EN_GPIO_PIN; + GPIO_Init(UCHARGER_EN_GPIO, &GPIO_InitStructure); + + // USB charger state init + ENABLE_UCHARGER(); + uCharger.hasCharger = !IS_UCHARGER_ACTIVE(); // Init for sampling count works + uCharger.isChargerDetectionReady = false; + resetChargeEndDetection(&uCharger); + +#if defined(WIRELESS_CHARGER) + // Wireless charger control pins + GPIO_InitStructure.GPIO_Pin = WCHARGER_EN_GPIO_PIN; + GPIO_Init(WCHARGER_EN_GPIO, &GPIO_InitStructure); + GPIO_InitStructure.GPIO_Pin = WCHARGER_I_CONTROL_GPIO_PIN; + GPIO_Init(WCHARGER_I_CONTROL_GPIO, &GPIO_InitStructure); + + // Wireless charger state init + ENABLE_WCHARGER(); + WCHARGER_CURRENT_LOW(); + wCharger.hasCharger = !IS_WCHARGER_ACTIVE(); // Init for sampling count works + wCharger.isChargerDetectionReady = false; + resetChargeEndDetection(&wCharger); + +#endif +} + +void drawChargingInfo(uint16_t chargeState) { + static int progress = 0; + const char* text = chargeState == CHARGE_STARTED ? STR_BATTERYCHARGING : STR_BATTERYFULL; + int h = 0; + LcdFlags color = 0; + if (CHARGE_STARTED == chargeState) + { + if (progress >= 100) + { + progress = 0; + } + else + { + progress += 25; + } + text = STR_BATTERYCHARGING; + h = ((BATTERY_H_INNER * progress) / 100); + color = COLOR_THEME_EDIT; + } + else if (CHARGE_FINISHED == chargeState) + { + text = STR_BATTERYFULL; + h = BATTERY_H_INNER; + color = COLOR_THEME_EDIT; + } + else + { + text = STR_BATTERYNONE; + h = BATTERY_H_INNER; + color = COLOR_THEME_PRIMARY1; + } + + BACKLIGHT_ENABLE(); + lcd->drawSizedText(LCD_W / 2, LCD_H - 50, text, strlen(text), CENTERED | COLOR_THEME_PRIMARY2); + + lcd->drawFilledRect((LCD_W - BATTERY_W) / 2, BATTERY_TOP, BATTERY_W, BATTERY_H, SOLID, COLOR_THEME_PRIMARY2); + lcd->drawFilledRect((LCD_W - BATTERY_W_INNER) / 2, BATTERY_TOP_INNER, BATTERY_W_INNER, BATTERY_H_INNER, SOLID, COLOR_THEME_PRIMARY1); + + lcd->drawFilledRect((LCD_W - BATTERY_W_INNER) / 2, BATTERY_TOP_INNER + BATTERY_H_INNER - h, BATTERY_W_INNER, h, SOLID, color); + lcd->drawFilledRect((LCD_W - BATTERY_CONNECTOR_W) / 2, BATTERY_TOP - BATTERY_CONNECTOR_H, BATTERY_CONNECTOR_W, BATTERY_CONNECTOR_H, SOLID, COLOR_THEME_PRIMARY2); +} +#define CHARGE_INFO_DURATION 500 + +//this method should be called by timer interrupt or by GPIO interrupt +void handle_battery_charge(uint32_t last_press_time) +{ +#if !defined(SIMU) + static uint32_t updateTime = 0; + static uint16_t lastState = CHARGE_UNKNOWN; + static uint32_t info_until = 0; + static bool lcdInited = false; + + uint32_t now = get_tmr10ms(); + uint16_t chargeState = get_battery_charge_state(); + if (chargeState != CHARGE_UNKNOWN) { + + if (lastState != chargeState) { + //avoid positive check when none and unknown + if (lastState + chargeState > 1) { + //charge state changed - last state known + info_until = now + (CHARGE_INFO_DURATION); + } + } + //power buttons pressed + else if (now - last_press_time < POWER_ON_DELAY) { + info_until = now + CHARGE_INFO_DURATION; + } + lastState = chargeState; + } + + + if(now > info_until) { + info_until = 0; + lcd->clear(); + BACKLIGHT_DISABLE(); + if(lcdInited) { + lcdOff(); + } + return; + } + + + if (updateTime == 0 || ((get_tmr10ms() - updateTime) >= 50)) + { + if (!lcdInited) { + backlightInit(); + lcdInit(); + lcdInitDisplayDriver(); + lcdInited = true; + } + else { + lcdOn(); + } + updateTime = get_tmr10ms(); + lcdInitDirectDrawing(); + lcd->clear(); + drawChargingInfo(chargeState); + + // DEBUG INFO +#if 0 + char buffer[1024]; + + sprintf(buffer, "%d,%d,%d,%d", uCharger.isChargerDetectionReady, uCharger.hasCharger, IS_UCHARGER_ACTIVE(), uCharger.chargerSamplingCount); + lcd->drawSizedText(100, 10, buffer, strlen(buffer), CENTERED | COLOR_THEME_PRIMARY2); + + sprintf(buffer, "%d,%d,%d,%d,%d,", uCharger.isChargingDetectionReady, uCharger.isChargeEnd, IS_UCHARGER_CHARGE_END_ACTIVE(), uCharger.chargingSamplingCount, uCharger.chargeEndSamplingCount); + lcd->drawSizedText(100, 40, buffer, strlen(buffer), CENTERED | COLOR_THEME_PRIMARY2); + + sprintf(buffer, "%d,%d,%d,%d,%d", wCharger.isChargerDetectionReady, wCharger.hasCharger, IS_WCHARGER_ACTIVE(), wCharger.chargerSamplingCount, wCharger.isHighCurrent); + lcd->drawSizedText(100, 70, buffer, strlen(buffer), CENTERED | COLOR_THEME_PRIMARY2); + + sprintf(buffer, "%d,%d,%d,%d,%d,", wCharger.isChargingDetectionReady, wCharger.isChargeEnd, IS_WCHARGER_CHARGE_END_ACTIVE(), wCharger.chargingSamplingCount, wCharger.chargeEndSamplingCount); + lcd->drawSizedText(100, 100, buffer, strlen(buffer), CENTERED | COLOR_THEME_PRIMARY2); + + sprintf(buffer, "%d", isChargerActive()); + lcd->drawSizedText(100, 130, buffer, strlen(buffer), CENTERED | COLOR_THEME_PRIMARY2); +#endif + + lcdRefresh(); + } +#endif +} + diff --git a/radio/src/targets/pl18/battery_driver.h b/radio/src/targets/pl18/battery_driver.h new file mode 100644 index 00000000000..6fdd651d51f --- /dev/null +++ b/radio/src/targets/pl18/battery_driver.h @@ -0,0 +1,60 @@ +/* + * 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. + */ + +/*************************************************************************************************** + +***************************************************************************************************/ +#ifndef __BATTERY_DRIVER_H__ + #define __BATTERY_DRIVER_H__ +/*************************************************************************************************** + +***************************************************************************************************/ + +#include "board.h" +#include "hal.h" + +enum ChargeState +{ + CHARGE_UNKNOWN, + CHARGE_NONE, + CHARGE_STARTED, + CHARGE_FINISHED +}; + +#define IS_UCHARGER_ACTIVE() GPIO_ReadInputDataBit(UCHARGER_GPIO, UCHARGER_GPIO_PIN) +#define IS_UCHARGER_CHARGE_END_ACTIVE() GPIO_ReadInputDataBit(UCHARGER_CHARGE_END_GPIO, UCHARGER_CHARGE_END_GPIO_PIN) +#define ENABLE_UCHARGER() GPIO_SetBits(UCHARGER_EN_GPIO, UCHARGER_EN_GPIO_PIN) +#define DISABLE_UCHARGER() GPIO_ResetBits(UCHARGER_EN_GPIO, UCHARGER_EN_GPIO_PIN) + +#define IS_WCHARGER_ACTIVE() GPIO_ReadInputDataBit(WCHARGER_GPIO, WCHARGER_GPIO_PIN) +#define IS_WCHARGER_CHARGE_END_ACTIVE() GPIO_ReadInputDataBit(WCHARGER_CHARGE_END_GPIO, WCHARGER_CHARGE_END_GPIO_PIN) +#define ENABLE_WCHARGER() GPIO_SetBits(WCHARGER_EN_GPIO, WCHARGER_EN_GPIO_PIN) +#define DISABLE_WCHARGER() GPIO_ResetBits(WCHARGER_EN_GPIO, WCHARGER_EN_GPIO_PIN) +#define WCHARGER_CURRENT_LOW() GPIO_ResetBits(WCHARGER_I_CONTROL_GPIO, WCHARGER_I_CONTROL_GPIO_PIN) +#define WCHARGER_CURRENT_HIGH() GPIO_SetBits(WCHARGER_I_CONTROL_GPIO, WCHARGER_I_CONTROL_GPIO_PIN) + +extern void battery_charge_init(); +extern void handle_battery_charge(uint32_t last_press_time); +extern uint16_t get_battery_charge_state(); +extern uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps +extern bool isChargerActive(); + +#endif diff --git a/radio/src/targets/pl18/board.cpp b/radio/src/targets/pl18/board.cpp new file mode 100644 index 00000000000..7c4cd43166b --- /dev/null +++ b/radio/src/targets/pl18/board.cpp @@ -0,0 +1,261 @@ +/* + * 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 "stm32_adc.h" + +#include "stm32_ws2812.h" +#include "boards/generic_stm32/rgb_leds.h" + +#include "board.h" +#include "boards/generic_stm32/module_ports.h" + +#include "hal/adc_driver.h" +#include "hal/trainer_driver.h" +#include "hal/switch_driver.h" +#include "hal/abnormal_reboot.h" +#include "hal/watchdog_driver.h" + +#include "globals.h" +#include "sdcard.h" +#include "touch.h" +#include "debug.h" + +#include "flysky_gimbal_driver.h" +#include "timers_driver.h" + +#include "battery_driver.h" +#include "touch_driver.h" + +#include "bitmapbuffer.h" +#include "colors.h" + +#include + +#if defined(__cplusplus) && !defined(SIMU) +extern "C" { +#endif +#include "usb_dcd_int.h" +#include "usb_bsp.h" +#if defined(__cplusplus) && !defined(SIMU) +} +#endif + +// common ADC driver +extern const etx_hal_adc_driver_t _adc_driver; + +#if defined(SEMIHOSTING) +extern "C" void initialise_monitor_handles(); +#endif + +#if defined(SPI_FLASH) +extern "C" void flushFTL(); +#endif + +void delay_self(int count) +{ + for (int i = 50000; i > 0; i--) + { + for (; count > 0; count--); + } +} +#define RCC_AHB1PeriphMinimum (PWR_RCC_AHB1Periph |\ + LCD_RCC_AHB1Periph |\ + BACKLIGHT_RCC_AHB1Periph |\ + SDRAM_RCC_AHB1Periph \ + ) +#define RCC_AHB1PeriphOther (AUDIO_RCC_AHB1Periph |\ + TELEMETRY_RCC_AHB1Periph |\ + TRAINER_RCC_AHB1Periph |\ + HAPTIC_RCC_AHB1Periph |\ + EXTMODULE_RCC_AHB1Periph \ + ) +#define RCC_AHB3PeriphMinimum (SDRAM_RCC_AHB3Periph) +#define RCC_APB1PeriphMinimum (BACKLIGHT_RCC_APB1Periph) +#define RCC_APB1PeriphOther (TELEMETRY_RCC_APB1Periph |\ + AUDIO_RCC_APB1Periph \ + ) +#define RCC_APB2PeriphMinimum (LCD_RCC_APB2Periph) +#define RCC_APB2PeriphOther (HAPTIC_RCC_APB2Periph) + +void boardInit() +{ +#if defined(SEMIHOSTING) + initialise_monitor_handles(); +#endif + +#if !defined(SIMU) + RCC_AHB1PeriphClockCmd(RCC_AHB1PeriphMinimum | RCC_AHB1PeriphOther, ENABLE); + RCC_AHB3PeriphClockCmd(RCC_AHB3PeriphMinimum, ENABLE); + RCC_APB1PeriphClockCmd(RCC_APB1PeriphMinimum | RCC_APB1PeriphOther, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2PeriphMinimum | RCC_APB2PeriphOther, ENABLE); + + // enable interrupts + __enable_irq(); +#endif + +#if defined(DEBUG) + serialSetMode(SP_AUX1, UART_MODE_DEBUG); // indicate AUX1 is used + serialInit(SP_AUX1, UART_MODE_DEBUG); // early AUX1 init +#endif + + TRACE("\nPL18 board started :)"); + delay_ms(10); + TRACE("RCC->CSR = %08x", RCC->CSR); + + pwrInit(); + boardInitModulePorts(); + + init_trainer(); + battery_charge_init(); + flysky_gimbal_init(); + timersInit(); + touchPanelInit(); + usbInit(); + + extern const stm32_pulse_timer_t _led_timer; + + ws2812_init(&_led_timer, LED_STRIP_LENGTH); + for (uint8_t i = 0; i < LED_STRIP_LENGTH; i++) { + ws2812_set_color(i, 0, 0, 0); + } + ws2812_update(&_led_timer); + + uint32_t press_start = 0; + uint32_t press_end = 0; + + if (UNEXPECTED_SHUTDOWN()) { + pwrOn(); + } else if (isChargerActive()) { + while (true) { + pwrOn(); + uint32_t now = get_tmr10ms(); + if (pwrPressed()) { + press_end = now; + if (press_start == 0) press_start = now; + if ((now - press_start) > POWER_ON_DELAY) { + break; + } + } else if (!isChargerActive()) { + boardOff(); + } else { + uint32_t press_end_touch = press_end; + if (touchPanelEventOccured()) { + touchPanelRead(); + press_end_touch = get_tmr10ms(); + } + press_start = 0; + handle_battery_charge(press_end_touch); + delay_ms(10); + press_end = 0; + } + } + } + + keysInit(); + switchInit(); + audioInit(); + adcInit(&_adc_driver); + hapticInit(); + + + #if defined(RTCLOCK) + rtcInit(); // RTC must be initialized before rambackupRestore() is called +#endif + + lcdSetInitalFrameBuffer(lcdFront->getData()); + +#if defined(DEBUG) + DBGMCU_APB1PeriphConfig( + DBGMCU_IWDG_STOP | DBGMCU_TIM1_STOP | DBGMCU_TIM2_STOP | + DBGMCU_TIM3_STOP | DBGMCU_TIM4_STOP | DBGMCU_TIM5_STOP | + DBGMCU_TIM6_STOP | DBGMCU_TIM7_STOP | DBGMCU_TIM8_STOP | + DBGMCU_TIM9_STOP | DBGMCU_TIM10_STOP | DBGMCU_TIM11_STOP | + DBGMCU_TIM12_STOP | DBGMCU_TIM13_STOP | DBGMCU_TIM14_STOP, + ENABLE); +#endif +} + +extern void rtcDisableBackupReg(); + +void boardOff() +{ + lcdOff(); + + while (pwrPressed()) { + WDG_RESET(); + } + + SysTick->CTRL = 0; // turn off systick + + // Shutdown the Haptic + hapticDone(); + + rtcDisableBackupReg(); + +#if !defined(BOOT) + if (isChargerActive()) + { + delay_ms(100); // Add a delay to wait for lcdOff +// RTC->BKP0R = SOFTRESET_REQUEST; + NVIC_SystemReset(); + } + else +#endif + { +// RTC->BKP0R = SHUTDOWN_REQUEST; + pwrOff(); + } + + // We reach here only in forced power situations, such as hw-debugging with external power + // Enter STM32 stop mode / deep-sleep + // Code snippet from ST Nucleo PWR_EnterStopMode example +#define PDMode 0x00000000U +#if defined(PWR_CR_MRUDS) && defined(PWR_CR_LPUDS) && defined(PWR_CR_FPDS) + MODIFY_REG(PWR->CR, (PWR_CR_PDDS | PWR_CR_LPDS | PWR_CR_FPDS | PWR_CR_LPUDS | PWR_CR_MRUDS), PDMode); +#elif defined(PWR_CR_MRLVDS) && defined(PWR_CR_LPLVDS) && defined(PWR_CR_FPDS) + MODIFY_REG(PWR->CR, (PWR_CR_PDDS | PWR_CR_LPDS | PWR_CR_FPDS | PWR_CR_LPLVDS | PWR_CR_MRLVDS), PDMode); +#else + MODIFY_REG(PWR->CR, (PWR_CR_PDDS| PWR_CR_LPDS), PDMode); +#endif /* PWR_CR_MRUDS && PWR_CR_LPUDS && PWR_CR_FPDS */ + +/* Set SLEEPDEEP bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); + + // To avoid HardFault at return address, end in an endless loop + while (1) { + + } +} + +int usbPlugged() +{ + static uint8_t debouncedState = 0; + static uint8_t lastState = 0; + + uint8_t state = GPIO_ReadInputDataBit(UCHARGER_GPIO, UCHARGER_GPIO_PIN); + + if (state == lastState) + debouncedState = state; + else + lastState = state; + + return debouncedState; +} diff --git a/radio/src/targets/pl18/board.h b/radio/src/targets/pl18/board.h new file mode 100644 index 00000000000..631f0b82d2d --- /dev/null +++ b/radio/src/targets/pl18/board.h @@ -0,0 +1,250 @@ +/* + * 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. + */ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +#include "definitions.h" +#include "opentx_constants.h" + +#include "board_common.h" +#include "hal.h" +#include "hal/serial_port.h" +#include "hal/watchdog_driver.h" + +#define FLASHSIZE 0x200000 +#define BOOTLOADER_SIZE 0x20000 +#define FIRMWARE_ADDRESS 0x08000000 + +#define MB *1024*1024 +#define LUA_MEM_EXTRA_MAX (2 MB) // max allowed memory usage for Lua bitmaps (in bytes) +#define LUA_MEM_MAX (6 MB) // max allowed memory usage for complete Lua (in bytes), 0 means unlimited + +extern uint16_t sessionTimer; + +#define SLAVE_MODE() (g_model.trainerData.mode == TRAINER_MODE_SLAVE) + +// Board driver +void boardInit(); +void boardOff(); + +// CPU Unique ID +#define LEN_CPU_UID (3*8+2) +void getCPUUniqueID(char * s); + +// Flash Write driver +#define FLASH_PAGESIZE 256 +void unlockFlash(); +void lockFlash(); +void flashWrite(uint32_t * address, const uint32_t * buffer); +uint32_t isFirmwareStart(const uint8_t * buffer); +uint32_t isBootloaderStart(const uint8_t * buffer); + +// SDRAM driver +void SDRAM_Init(); + +// Pulses driver +#if !defined(SIMU) + +#define INTERNAL_MODULE_ON() GPIO_SetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) +#define INTERNAL_MODULE_OFF() GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) +#define EXTERNAL_MODULE_ON() GPIO_SetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) +#define EXTERNAL_MODULE_OFF() GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) +#define EXTERNAL_MODULE_PWR_OFF EXTERNAL_MODULE_OFF +#define BLUETOOTH_MODULE_ON() GPIO_ResetBits(BT_EN_GPIO, BT_EN_GPIO_PIN) +#define BLUETOOTH_MODULE_OFF() GPIO_SetBits(BT_EN_GPIO, BT_EN_GPIO_PIN) +#define IS_INTERNAL_MODULE_ON() (false) +#define IS_EXTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) == Bit_SET) + +#else + +#define INTERNAL_MODULE_OFF() +#define INTERNAL_MODULE_ON() +#define EXTERNAL_MODULE_ON() +#define EXTERNAL_MODULE_OFF() +#define BLUETOOTH_MODULE_ON() +#define BLUETOOTH_MODULE_OFF() +#define IS_INTERNAL_MODULE_ON() (false) +#define IS_EXTERNAL_MODULE_ON() (false) + +#endif // defined(SIMU) + +#if !defined(NUM_FUNCTIONS_SWITCHES) +#define NUM_FUNCTIONS_SWITCHES 0 +#endif + +#define NUM_TRIMS 8 +#define DEFAULT_STICK_DEADZONE 2 + +#define BATTERY_WARN 37 // 3.7V +#define BATTERY_MIN 35 // 3.4V +#define BATTERY_MAX 43 // 4.3V +#define BATTERY_DIVIDER 962 + +#if defined(__cplusplus) && !defined(SIMU) +extern "C" { +#endif + +// Power driver +#define SOFT_PWR_CTRL +#define POWER_ON_DELAY 10 // 1s +void pwrInit(); +void extModuleInit(); +uint32_t pwrCheck(); +uint32_t lowPowerCheck(); + +void pwrOn(); +void pwrSoftReboot(); +void pwrOff(); +void pwrResetHandler(); +bool pwrPressed(); +bool pwrOffPressed(); +#if defined(PWR_EXTRA_SWITCH_GPIO) + bool pwrForcePressed(); +#else + #define pwrForcePressed() false +#endif +uint32_t pwrPressedDuration();; + +const etx_serial_port_t* auxSerialGetPort(int port_nr); +#define AUX_SERIAL_POWER_ON() +#define AUX_SERIAL_POWER_OFF() + +// LED driver +void ledInit(); +void ledOff(); +void ledRed(); +void ledBlue(); +void ledGreen(); + +// LCD driver +void lcdSetInitalFrameBuffer(void* fbAddress); +void lcdInit(); +void lcdCopy(void * dest, void * src); + +void lcdOff(); +void lcdOn(); + +#define lcdRefreshWait(...) + +// Backlight driver +#define BACKLIGHT_LEVEL_MAX 100 +#define BACKLIGHT_FORCED_ON BACKLIGHT_LEVEL_MAX + 1 +#define BACKLIGHT_LEVEL_MIN 1 + +extern bool boardBacklightOn; +void backlightLowInit( void ); +void backlightInit(); +void backlightEnable(uint8_t dutyCycle); +void backlightFullOn(); +bool isBacklightEnabled(); + +#define BACKLIGHT_ENABLE() \ + { \ + boardBacklightOn = true; \ + backlightEnable(BACKLIGHT_LEVEL_MAX - currentBacklightBright); \ + } + +#define BACKLIGHT_DISABLE() \ + { \ + boardBacklightOn = false; \ + backlightEnable(((g_eeGeneral.blOffBright == BACKLIGHT_LEVEL_MIN) && \ + (g_eeGeneral.backlightMode != e_backlight_mode_off)) \ + ? 0 \ + : g_eeGeneral.blOffBright); \ + } + +#if !defined(SIMU) +void usbJoystickUpdate(); +#endif +#if defined(RADIO_PL18EV) +#define USB_NAME "FlySky PL18EV" +#define USB_MANUFACTURER 'F', 'l', 'y', 'S', 'k', 'y', ' ', ' ' /* 8 bytes */ +#define USB_PRODUCT 'P', 'L', '1', '8', 'E', 'V', ' ', ' ' /* 8 Bytes */ +#else +#define USB_NAME "FlySky PL18" +#define USB_MANUFACTURER 'F', 'l', 'y', 'S', 'k', 'y', ' ', ' ' /* 8 bytes */ +#define USB_PRODUCT 'P', 'L', '1', '8', ' ', ' ', ' ', ' ' /* 8 Bytes */ +#endif + +#if defined(__cplusplus) && !defined(SIMU) +} +#endif + +// Audio driver +void audioInit(); +void audioConsumeCurrentBuffer(); +void audioSpiWriteBuffer(const uint8_t * buffer, uint32_t size); +void audioSpiSetSpeed(uint8_t speed); +uint8_t audioHardReset(); +uint8_t audioSoftReset(); +void audioSendRiffHeader(); +void audioOn(); +void audioOff(); +bool isAudioReady(); +bool audioChipReset(); + +#define SPI_SPEED_2 0 +#define SPI_SPEED_4 1 +#define SPI_SPEED_8 2 +#define SPI_SPEED_16 3 +#define SPI_SPEED_32 4 +#define SPI_SPEED_64 5 +#define SPI_SPEED_128 6 +#define SPI_SPEED_256 7 + +#define audioDisableIrq() // interrupts must stay enabled on Horus +#define audioEnableIrq() // interrupts must stay enabled on Horus +#if defined(PCBNV14) +#define setSampleRate(freq) +#else +void setSampleRate(uint32_t frequency); +#endif +void setScaledVolume(uint8_t volume); +void setVolume(uint8_t volume); +int32_t getVolume(); +#define VOLUME_LEVEL_MAX 23 +#define VOLUME_LEVEL_DEF 12 + +// Telemetry driver +#define INTMODULE_FIFO_SIZE 512 +#define TELEMETRY_FIFO_SIZE 512 + +// Haptic driver +void hapticInit(); +void hapticDone(); +void hapticOff(); +void hapticOn(uint32_t pwmPercent); + +// Second serial port driver +//#define AUX_SERIAL +#define DEBUG_BAUDRATE 115200 +#define LUA_DEFAULT_BAUDRATE 115200 + +extern uint8_t currentTrainerMode; +void checkTrainerSettings(); + +// Touch panel driver +bool touchPanelEventOccured(); +struct TouchState touchPanelRead(); +struct TouchState getInternalTouchState(); + +#endif // _BOARD_H_ diff --git a/radio/src/targets/pl18/bootloader/boot_menu.cpp b/radio/src/targets/pl18/bootloader/boot_menu.cpp new file mode 100644 index 00000000000..3acc373092c --- /dev/null +++ b/radio/src/targets/pl18/bootloader/boot_menu.cpp @@ -0,0 +1,261 @@ +/* + * 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 "board.h" +#include "fw_version.h" +#include "lcd.h" + +#include "translations.h" + +#include "../../common/arm/stm32/bootloader/boot.h" +#include "../../common/arm/stm32/bootloader/bin_files.h" + +#include + +#define SELECTED_COLOR (INVERS | COLOR_THEME_SECONDARY1) +#define DEFAULT_PADDING 28 +#define DOUBLE_PADDING 56 +#define MESSAGE_TOP (LCD_H - (2*DOUBLE_PADDING)) + +const uint8_t __bmp_plug_usb[] { +#include "bmp_plug_usb.lbm" +}; +LZ4Bitmap BMP_PLUG_USB(BMP_ARGB4444, __bmp_plug_usb); + +const uint8_t __bmp_usb_plugged[] { +#include "bmp_usb_plugged.lbm" +}; +LZ4Bitmap BMP_USB_PLUGGED(BMP_ARGB4444, __bmp_usb_plugged); + +#define BL_GREEN COLOR2FLAGS(RGB(73, 219, 62)) +#define BL_RED COLOR2FLAGS(RGB(229, 32, 30)) +#define BL_BACKGROUND COLOR2FLAGS(BLACK) +#define BL_FOREGROUND COLOR2FLAGS(WHITE) +#define BL_SELECTED COLOR2FLAGS(RGB(11, 65, 244)) // deep blue + +extern BitmapBuffer * lcd; + +void bootloaderInitScreen() +{ + lcdInitDisplayDriver(); + backlightInit(); + backlightEnable(100); + setHatsAsKeys(true); +} + +static void bootloaderDrawTitle(const char* text) +{ + lcd->drawText(LCD_W/2, DEFAULT_PADDING, text, CENTERED | BL_FOREGROUND); + lcd->drawSolidFilledRect(DEFAULT_PADDING, DOUBLE_PADDING, LCD_W - DOUBLE_PADDING, 2, BL_FOREGROUND); +} + +static void bootloaderDrawFooter() +{ + lcd->drawSolidFilledRect(DEFAULT_PADDING, LCD_H - (DEFAULT_PADDING + 10), LCD_W - DOUBLE_PADDING, 2, BL_FOREGROUND); +} + +static void bootloaderDrawBackground() +{ + lcd->clear(BL_BACKGROUND); +} + +void bootloaderDrawScreen(BootloaderState st, int opt, const char* str) +{ + lcdInitDirectDrawing(); + bootloaderDrawBackground(); + + int center = LCD_W/2; + if (st == ST_START) { + + bootloaderDrawTitle(BOOTLOADER_TITLE); + + lcd->drawText(102, 75, LV_SYMBOL_CHARGE, BL_FOREGROUND); + coord_t pos = lcd->drawText(124, 75, TR_BL_WRITE_FW, BL_FOREGROUND); + pos += 8; + +#if defined(SPI_FLASH) + lcd->drawText(102, 110, LV_SYMBOL_SD_CARD, BL_FOREGROUND); + pos = lcd->drawText(124, 110, TR_BL_ERASE_FLASH, BL_FOREGROUND); + pos += 8; + + lcd->drawText(100, 145, LV_SYMBOL_NEW_LINE, BL_FOREGROUND); + lcd->drawText(124, 145, TR_BL_EXIT, BL_FOREGROUND); +#else + lcd->drawText(100, 110, LV_SYMBOL_NEW_LINE, BL_FOREGROUND); + lcd->drawText(124, 110, TR_BL_EXIT, BL_FOREGROUND); +#endif + + pos -= 92; + lcd->drawSolidRect(92, 72 + (opt * 35), pos, 26, 2, BL_SELECTED); + + lcd->drawBitmap(60, 214, (const BitmapBuffer*)&BMP_PLUG_USB); + lcd->drawText(195, 223, TR_BL_USB_PLUGIN, BL_FOREGROUND); + lcd->drawText(195, 248, TR_BL_USB_MASS_STORE, BL_FOREGROUND); + + bootloaderDrawFooter(); + lcd->drawText(center, LCD_H - DEFAULT_PADDING, getFirmwareVersion(), CENTERED | BL_FOREGROUND); + } +#if defined(SPI_FLASH) + else if (st == ST_CLEAR_FLASH_CHECK) { + + bootloaderDrawTitle(TR_BL_ERASE_INT_FLASH); + + lcd->drawText(102, 75, LV_SYMBOL_SD_CARD, BL_FOREGROUND); + coord_t pos = lcd->drawText(124, 75, TR_BL_ERASE_FLASH, BL_FOREGROUND); + pos += 8; + + lcd->drawText(100, 110, LV_SYMBOL_NEW_LINE, BL_FOREGROUND); + lcd->drawText(124, 110, TR_BL_EXIT, BL_FOREGROUND); + + pos -= 92; + lcd->drawSolidRect(92, 72 + (opt * 35), pos, 26, 2, BL_SELECTED); + + bootloaderDrawFooter(); + lcd->drawText(DEFAULT_PADDING, LCD_H - DEFAULT_PADDING, + LV_SYMBOL_SD_CARD TR_BL_ERASE_KEY, BL_FOREGROUND); + lcd->drawText(305, LCD_H - DEFAULT_PADDING, + LV_SYMBOL_NEW_LINE TR_BL_EXIT_KEY, BL_FOREGROUND); + } + else if (st == ST_CLEAR_FLASH) { + bootloaderDrawTitle(TR_BL_ERASE_INT_FLASH); + + lcd->drawText(center, 75, TR_BL_ERASE_FLASH_MSG, CENTERED | BL_FOREGROUND); + bootloaderDrawFooter(); + } +#endif + + else if (st == ST_USB) { + lcd->drawBitmap(center - 26, 98, (const BitmapBuffer*)&BMP_USB_PLUGGED); + lcd->drawText(center, 168, TR_BL_USB_CONNECTED, CENTERED | BL_FOREGROUND); + } else if (st == ST_FILE_LIST || st == ST_DIR_CHECK || + st == ST_FLASH_CHECK || st == ST_FLASHING || + st == ST_FLASH_DONE) { + + bootloaderDrawTitle(LV_SYMBOL_SD_CARD " /FIRMWARE"); + + if (st == ST_FLASHING || st == ST_FLASH_DONE) { + LcdFlags color = BL_RED; // red + + if (st == ST_FLASH_DONE) { + color = BL_GREEN /* green */; + opt = 100; // Completed > 100% + } + + lcd->drawRect(DEFAULT_PADDING, 120, LCD_W - DOUBLE_PADDING, 31, 2, + SOLID, BL_SELECTED); + lcd->drawSolidFilledRect(DEFAULT_PADDING + 4, 124, + ((LCD_W - DOUBLE_PADDING - 8) * opt) / 100, 23, + color); + } else if (st == ST_DIR_CHECK) { + if (opt == FR_NO_PATH) { + lcd->drawText(20, MESSAGE_TOP, + LV_SYMBOL_CLOSE TR_BL_DIR_MISSING, BL_FOREGROUND); + } else { + lcd->drawText(20, MESSAGE_TOP, LV_SYMBOL_CLOSE TR_BL_DIR_EMPTY, + BL_FOREGROUND); + } + } else if (st == ST_FLASH_CHECK) { + bootloaderDrawFilename(str, 0, true); + + if (opt == FC_ERROR) { + lcd->drawText(20, MESSAGE_TOP, + LV_SYMBOL_CLOSE " " TR_BL_INVALID_FIRMWARE, + BL_FOREGROUND); + } else if (opt == FC_OK) { + VersionTag tag; + memset(&tag, 0, sizeof(tag)); + extractFirmwareVersion(&tag); + + lcd->drawText(LCD_W / 4 + DEFAULT_PADDING, + MESSAGE_TOP - DEFAULT_PADDING, + TR_BL_FORK, RIGHT | BL_FOREGROUND); + lcd->drawSizedText(LCD_W / 4 + 6 + DEFAULT_PADDING, + MESSAGE_TOP - DEFAULT_PADDING, tag.fork, 6, + BL_FOREGROUND); + + lcd->drawText(LCD_W / 4 + DEFAULT_PADDING, MESSAGE_TOP, + TR_BL_VERSION, RIGHT | BL_FOREGROUND); + lcd->drawText(LCD_W / 4 + 6 + DEFAULT_PADDING, MESSAGE_TOP, + tag.version, BL_FOREGROUND); + + lcd->drawText(LCD_W / 4 + DEFAULT_PADDING, + MESSAGE_TOP + DEFAULT_PADDING, + TR_BL_RADIO, RIGHT | BL_FOREGROUND); + lcd->drawText(LCD_W / 4 + 6 + DEFAULT_PADDING, + MESSAGE_TOP + DEFAULT_PADDING, tag.flavour, + BL_FOREGROUND); + + lcd->drawText(DOUBLE_PADDING, MESSAGE_TOP, LV_SYMBOL_OK, BL_GREEN); + } + } + + bootloaderDrawFooter(); + + if (st != ST_DIR_CHECK && (st != ST_FLASH_CHECK || opt == FC_OK)) { + + if (st == ST_FILE_LIST) { + lcd->drawText(DEFAULT_PADDING, LCD_H - DEFAULT_PADDING, + LV_SYMBOL_CHARGE TR_BL_SELECT_KEY, BL_FOREGROUND); + } else if (st == ST_FLASH_CHECK && opt == FC_OK) { + lcd->drawText(DEFAULT_PADDING, LCD_H - DEFAULT_PADDING, + LV_SYMBOL_CHARGE TR_BL_FLASH_KEY, BL_FOREGROUND); + } else if (st == ST_FLASHING) { + lcd->drawText(DEFAULT_PADDING, LCD_H - DEFAULT_PADDING, + LV_SYMBOL_CHARGE TR_BL_WRITING_FW, BL_FOREGROUND); + } else if (st == ST_FLASH_DONE) { + lcd->drawText(DEFAULT_PADDING, LCD_H - DEFAULT_PADDING, + LV_SYMBOL_CHARGE TR_BL_WRITING_COMPL, BL_FOREGROUND); + } + } + + if (st != ST_FLASHING) { + lcd->drawText(305, LCD_H - DEFAULT_PADDING, + LV_SYMBOL_NEW_LINE TR_BL_EXIT_KEY, BL_FOREGROUND); + } + } +} + +void bootloaderDrawFilename(const char* str, uint8_t line, bool selected) +{ + lcd->drawText(DEFAULT_PADDING, 75 + (line * 25), LV_SYMBOL_FILE, BL_FOREGROUND); + lcd->drawText(DEFAULT_PADDING + 30, 75 + (line * 25), str, BL_FOREGROUND); + + if (selected) { + lcd->drawSolidRect(DEFAULT_PADDING + 25, 72 + (line * 25), + LCD_W - (DEFAULT_PADDING + 25) - 28, 26, 2, BL_SELECTED); + } +} +uint32_t bootloaderGetMenuItemCount(int baseCount) +{ + return baseCount; +} + +bool bootloaderRadioMenu(uint32_t menuItem, event_t event) +{ + return true; +} + +void blExit(void) +{ + lcdClear(); + lcdRefresh(); + lcdRefreshWait(); +} diff --git a/radio/src/targets/pl18/extmodule_helper.cpp b/radio/src/targets/pl18/extmodule_helper.cpp new file mode 100644 index 00000000000..dbb02e90be2 --- /dev/null +++ b/radio/src/targets/pl18/extmodule_helper.cpp @@ -0,0 +1,49 @@ +/* + * 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 "board.h" + +void EXTERNAL_MODULE_ON() +{ + GPIO_SetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN); +} + +void EXTERNAL_MODULE_OFF() +{ + GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN); +} + +void extModuleInit() +{ + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = EXTMODULE_TX_INVERT_GPIO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(EXTMODULE_TX_INVERT_GPIO, &GPIO_InitStructure); + + GPIO_InitStructure.GPIO_Pin = EXTMODULE_RX_INVERT_GPIO_PIN; + GPIO_Init(EXTMODULE_RX_INVERT_GPIO, &GPIO_InitStructure); + + EXTMODULE_TX_INVERTED(); + EXTMODULE_RX_INVERTED(); +} diff --git a/radio/src/targets/pl18/hal.h b/radio/src/targets/pl18/hal.h new file mode 100644 index 00000000000..ce3f32c9623 --- /dev/null +++ b/radio/src/targets/pl18/hal.h @@ -0,0 +1,719 @@ +/* + * 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. + */ + +#ifndef _HAL_H_ +#define _HAL_H_ + +#define CPU_FREQ 168000000 + +// HSI is at 168Mhz (over-drive is not enabled!) +#define PERI1_FREQUENCY 42000000 +#define PERI2_FREQUENCY 84000000 +#define TIMER_MULT_APB1 2 +#define TIMER_MULT_APB2 2 + +/* Timers Allocation: + * TIM1 = Haptic + * TIM4 = Trainer + * TIM6 = Audio + * TIM7 = 2 MHz counter + * + * + * TIM14 = 5 ms counter + */ + +/* DMA Allocation: + DMA/Stream/Channel + 1/5/7 DAC/Audio + 2/4/0 ADC1 + 2/0/2 ADC3 + 2/3/4 SDIO +*/ + +// Keys +// PL18/PL18EV only has virtual keys via trim buttons +// #define KEYS_GPIO_PIN_PGUP /* for activating PGUP in keys diagnose screen */ + +// Trims +#define TRIMS_GPIO_REG_LHL +#define TRIMS_GPIO_PIN_LHL + +#define TRIMS_GPIO_REG_LHR +#define TRIMS_GPIO_PIN_LHR + +#define TRIMS_GPIO_REG_LVD +#define TRIMS_GPIO_PIN_LVD + +#define TRIMS_GPIO_REG_LVU +#define TRIMS_GPIO_PIN_LVU + +#define TRIMS_GPIO_REG_RHL +#define TRIMS_GPIO_PIN_RHL + +#define TRIMS_GPIO_REG_RHR +#define TRIMS_GPIO_PIN_RHR + +#define TRIMS_GPIO_REG_RVD +#define TRIMS_GPIO_PIN_RVD + +#define TRIMS_GPIO_REG_RVU +#define TRIMS_GPIO_PIN_RVU + +#define TRIMS_GPIO_REG_LSD +#define TRIMS_GPIO_PIN_LSD + +#define TRIMS_GPIO_REG_LSU +#define TRIMS_GPIO_PIN_LSU + +#define TRIMS_GPIO_REG_RSD +#define TRIMS_GPIO_PIN_RSD + +#define TRIMS_GPIO_REG_RSU +#define TRIMS_GPIO_PIN_RSU + +#define TRIMS_GPIO_REG_T7L +#define TRIMS_GPIO_PIN_T7L + +#define TRIMS_GPIO_REG_T7R +#define TRIMS_GPIO_PIN_T7R + +#define TRIMS_GPIO_REG_T8D +#define TRIMS_GPIO_PIN_T8D + +#define TRIMS_GPIO_REG_T8U +#define TRIMS_GPIO_PIN_T8U + +#define TRIMS_GPIO_REG_TR1U GPIOH->IDR +#define TRIMS_GPIO_PIN_TR1U LL_GPIO_PIN_8 // PH.08 +#define TRIMS_GPIO_REG_TR1D GPIOH->IDR +#define TRIMS_GPIO_PIN_TR1D LL_GPIO_PIN_9 // PH.09 +#define TRIMS_GPIO_REG_TR2U GPIOH->IDR +#define TRIMS_GPIO_PIN_TR2U LL_GPIO_PIN_10 // PH.10 +#define TRIMS_GPIO_REG_TR2D GPIOH->IDR +#define TRIMS_GPIO_PIN_TR2D LL_GPIO_PIN_11 // PH.11 + +// active 4x4 column/row based key-matrix to support up to 16 buttons with only 8 GPIOs +#define TRIMS_GPIO_OUT1 GPIOG +#define TRIMS_GPIO_OUT1_PIN LL_GPIO_PIN_2 // PG.02 +#define TRIMS_GPIO_OUT2 GPIOG +#define TRIMS_GPIO_OUT2_PIN LL_GPIO_PIN_10 // PG.10 +#define TRIMS_GPIO_OUT3 GPIOG +#define TRIMS_GPIO_OUT3_PIN LL_GPIO_PIN_11 // PG.11 +// OUT4 routed on MCU PCB, but not attached to any physical buttons, free to use for extensions +#define TRIMS_GPIO_OUT4 GPIOH +#define TRIMS_GPIO_OUT4_PIN LL_GPIO_PIN_7 // PH.07 + +#define TRIMS_GPIO_REG_IN1 GPIOB->IDR +#define TRIMS_GPIO_PIN_IN1 LL_GPIO_PIN_15 // PB.15 +#define TRIMS_GPIO_REG_IN2 GPIOC->IDR +#define TRIMS_GPIO_PIN_IN2 LL_GPIO_PIN_13 // PC.13 +#define TRIMS_GPIO_REG_IN3 GPIOD->IDR +#define TRIMS_GPIO_PIN_IN3 LL_GPIO_PIN_7 // PD.07 +#define TRIMS_GPIO_REG_IN4 GPIOJ->IDR +#define TRIMS_GPIO_PIN_IN4 LL_GPIO_PIN_12 // PJ.12 + +// Index of all trims + +#define KEYS_GPIOB_PINS (LL_GPIO_PIN_15) + +// PC8 allocated to SDIO D0, is not required to sample SWA ! +#define KEYS_GPIOC_PINS (LL_GPIO_PIN_13) + +#define KEYS_GPIOD_PINS (LL_GPIO_PIN_7) + +#define KEYS_GPIOH_PINS \ + (LL_GPIO_PIN_8 | LL_GPIO_PIN_9 | LL_GPIO_PIN_10 | LL_GPIO_PIN_11) + +#define KEYS_GPIOJ_PINS (LL_GPIO_PIN_12) + +#define KEYS_OUT_GPIOG_PINS (LL_GPIO_PIN_2 | LL_GPIO_PIN_10 | LL_GPIO_PIN_11) + +#define KEYS_OUT_GPIOH_PINS (LL_GPIO_PIN_7) + + +// Monitor pin +// #define MONITOR_RCC_AHB1Periph (RCC_AHB1Periph_GPIOJ) +// #define VBUS_MONITOR_GPIO (GPIOJ) +// #define VBUS_MONITOR_PIN (LL_GPIO_PIN_14) + +// Switches: +// Switches A and C on PL18/PL18EV are 2-position switches, +// so there is no NEED to configure two pins for Switches A and C. +// +// Especially, as on current dev. state, using PC8 for SDIO D0. +// (happy coincidence ;) +// +// #define SWITCHES_GPIO_REG_A_H GPIOC +// #define SWITCHES_GPIO_PIN_A_H LL_GPIO_PIN_8 // PC.08 +// #define SWITCHES_GPIO_REG_A_L GPIOC +// #define SWITCHES_GPIO_PIN_A_L LL_GPIO_PIN_9 // PC.09 + +#define SWITCHES_GPIO_REG_A GPIOC +#define SWITCHES_GPIO_PIN_A LL_GPIO_PIN_9 // PC.09 + +// High rail of Switch C is not required and thus PC10 is free to use for +// customizations. +// +// #define SWITCHES_GPIO_REG_C_H GPIOC +// #define SWITCHES_GPIO_PIN_C_H LL_GPIO_PIN_10 // PC.10 +// #define SWITCHES_GPIO_REG_C_L GPIOC +// #define SWITCHES_GPIO_PIN_C_L LL_GPIO_PIN_11 // PC.11 + +#define SWITCHES_GPIO_REG_C GPIOC +#define SWITCHES_GPIO_PIN_C LL_GPIO_PIN_11 // PC.11 + +// ADC + +#define ADC_GPIO_PIN_STICK_LH +#define ADC_GPIO_PIN_STICK_LV +#define ADC_GPIO_PIN_STICK_RV +#define ADC_GPIO_PIN_STICK_RH + +#define ADC_GPIO_PIN_POT1 LL_GPIO_PIN_6 // PA.06 VRA +#define ADC_GPIO_PIN_POT2 LL_GPIO_PIN_4 // PC.04 VRB +#define ADC_GPIO_PIN_POT3 LL_GPIO_PIN_8 // PF.08 VRC +#define ADC_GPIO_PIN_SLIDER1 LL_GPIO_PIN_9 // PF.09 VRD/LS +#define ADC_GPIO_PIN_SLIDER2 LL_GPIO_PIN_7 // PA.07 VRE/RS + +#if defined(RADIO_PL18EV) +#define ADC_GPIO_PIN_EXT1 LL_GPIO_PIN_5 // PA.05 +#define ADC_GPIO_PIN_EXT2 LL_GPIO_PIN_2 // PA.02 +#define ADC_GPIO_PIN_EXT3 LL_GPIO_PIN_6 // PF.06 +#define ADC_GPIO_PIN_EXT4 LL_GPIO_PIN_3 // PA.03 +#endif + +#define ADC_GPIO_PIN_SWB LL_GPIO_PIN_1 // PC.01 +#define ADC_GPIO_PIN_SWD LL_GPIO_PIN_0 // PC.00 +#define ADC_GPIO_PIN_SWE LL_GPIO_PIN_2 // PC.02 +#define ADC_GPIO_PIN_SWF LL_GPIO_PIN_0 // PB.00 +#define ADC_GPIO_PIN_SWG LL_GPIO_PIN_1 // PB.01 +#define ADC_GPIO_PIN_SWH LL_GPIO_PIN_10 // PF.10 + +#define ADC_GPIO_PIN_BATT LL_GPIO_PIN_5 // PC.05 + +#define ADC_GPIOA_PINS (ADC_GPIO_PIN_POT1 | ADC_GPIO_PIN_SLIDER2 | \ + ADC_GPIO_PIN_EXT1 | ADC_GPIO_PIN_EXT2 | ADC_GPIO_PIN_EXT4) +#define ADC_GPIOB_PINS (ADC_GPIO_PIN_SWF | ADC_GPIO_PIN_SWG) +#define ADC_GPIOC_PINS (ADC_GPIO_PIN_POT2 | ADC_GPIO_PIN_BATT | \ + ADC_GPIO_PIN_SWB | ADC_GPIO_PIN_SWD | ADC_GPIO_PIN_SWE) +#define ADC_GPIOF_PINS (ADC_GPIO_PIN_POT3 | ADC_GPIO_PIN_SLIDER1 | \ + ADC_GPIO_PIN_EXT3 | ADC_GPIO_PIN_SWH) + +#define ADC_CHANNEL_STICK_LH +#define ADC_CHANNEL_STICK_LV +#define ADC_CHANNEL_STICK_RV +#define ADC_CHANNEL_STICK_RH + +// Each ADC cannot map more than 8 channels, otherwise it will cause problems + +#define ADC_CHANNEL_POT1 LL_ADC_CHANNEL_6 // ADC12_IN6 -> ADC1_IN6 +#define ADC_CHANNEL_POT2 LL_ADC_CHANNEL_14 // ADC12_IN14 -> ADC1_IN14 +#define ADC_CHANNEL_POT3 LL_ADC_CHANNEL_6 // ADC3_IN6 -> ADC3_IN6 +#define ADC_CHANNEL_SLIDER1 LL_ADC_CHANNEL_7 // ADC3_IN7 -> ADC3_IN7 +#define ADC_CHANNEL_SLIDER2 LL_ADC_CHANNEL_7 // ADC12_IN7 -> ADC1_IN7 + +#if defined(RADIO_PL18EV) +// Left, right stick end pot on PL18EV +#define ADC_CHANNEL_EXT1 LL_ADC_CHANNEL_5 // ADC12_IN5 -> ADC1_IN5 +#define ADC_CHANNEL_EXT2 LL_ADC_CHANNEL_2 // ADC123_IN2 -> ADC1_IN2 + +// Left, right stick end buttons on PL18EV +#define ADC_CHANNEL_EXT3 LL_ADC_CHANNEL_4 // ADC3_IN4 -> ADC3_IN4 +#define ADC_CHANNEL_EXT4 LL_ADC_CHANNEL_3 // ADC123_IN3 -> ADC3_IN3 +#endif + +// Analog switches +#define ADC_CHANNEL_SWB LL_ADC_CHANNEL_11 // ADC123_IN11 -> ADC3_IN11 +#define ADC_CHANNEL_SWD LL_ADC_CHANNEL_10 // ADC123_IN10 -> ADC3_IN10 +#define ADC_CHANNEL_SWE LL_ADC_CHANNEL_12 // ADC123_IN12 -> ADC3_IN12 +#define ADC_CHANNEL_SWF LL_ADC_CHANNEL_8 // ADC12_IN8 -> ADC1_IN8 +#define ADC_CHANNEL_SWG LL_ADC_CHANNEL_9 // ADC12_IN9 -> ADC1_IN9 +#define ADC_CHANNEL_SWH LL_ADC_CHANNEL_8 // ADC3_IN8 -> ADC3_IN8 + +#define ADC_CHANNEL_BATT LL_ADC_CHANNEL_15 // ADC12_IN15 -> ADC1_IN15 + +#if !defined(RADIO_PL18EV) +// Disabled for PL18EV because 2 ADC 16 channels are fully mapped already +#define ADC_CHANNEL_RTC_BAT LL_ADC_CHANNEL_VBAT // ADC1_IN18 +#endif + +#define ADC_MAIN ADC1 +#define ADC_EXT ADC3 + +#define ADC_EXT_CHANNELS \ + { ADC_CHANNEL_POT3, ADC_CHANNEL_SLIDER1, ADC_CHANNEL_EXT3, ADC_CHANNEL_EXT4, \ + ADC_CHANNEL_SWB, ADC_CHANNEL_SWD, ADC_CHANNEL_SWE, ADC_CHANNEL_SWH \ + } + +#define ADC_SAMPTIME LL_ADC_SAMPLINGTIME_28CYCLES +#define ADC_DMA DMA2 +#define ADC_DMA_CHANNEL LL_DMA_CHANNEL_0 +#define ADC_DMA_STREAM LL_DMA_STREAM_4 +#define ADC_DMA_STREAM_IRQ DMA2_Stream4_IRQn +#define ADC_DMA_STREAM_IRQHandler DMA2_Stream4_IRQHandler + +#define ADC_EXT_DMA DMA2 +#define ADC_EXT_DMA_CHANNEL LL_DMA_CHANNEL_2 +#define ADC_EXT_DMA_STREAM LL_DMA_STREAM_0 +#define ADC_EXT_DMA_STREAM_IRQ DMA2_Stream0_IRQn +#define ADC_EXT_DMA_STREAM_IRQHandler DMA2_Stream0_IRQHandler +#define ADC_EXT_SAMPTIME LL_ADC_SAMPLINGTIME_28CYCLES + +#define ADC_VREF_PREC2 660 + +#if defined(RADIO_PL18EV) +#define ADC_DIRECTION { \ + 0,0,0,0, /* gimbals */ \ + 0,0,0, /* pots */ \ + -1,-1, /* sliders */ \ + 0,0,0,0, /* ext1-4 */ \ + 0, /* vbat */ \ + -1, /* SWB */ \ + -1, /* SWD */ \ + 0, /* SWE */ \ + 0, /* SWF */ \ + 0, /* SWG */ \ + 0 /* SWH */ \ + } +#else +#define ADC_DIRECTION { \ + 0,0,0,0, /* gimbals */ \ + 0,0,0, /* pots */ \ + -1,-1, /* sliders */ \ + 0, /* vbat */ \ + 0, /* rtc_bat */ \ + -1, /* SWB */ \ + -1, /* SWD */ \ + 0, /* SWE */ \ + 0, /* SWF */ \ + 0, /* SWG */ \ + 0 /* SWH */ \ + } +#endif + +// Power +#define PWR_RCC_AHB1Periph RCC_AHB1Periph_GPIOI +#define PWR_ON_GPIO GPIOI +#define PWR_SWITCH_GPIO GPIOI +#define PWR_SWITCH_GPIO_PIN GPIO_Pin_11 // PI.11 +#define PWR_ON_GPIO_PIN GPIO_Pin_14 // PI.14 + +// Chargers (USB and wireless) +#define CHARGER_RCC_AHB1Periph ( RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOH | RCC_AHB1Periph_GPIOI ) + +#define UCHARGER_GPIO GPIOB +#define UCHARGER_GPIO_PIN GPIO_Pin_14 // PB.14 input + +#define UCHARGER_CHARGE_END_GPIO GPIOB +#define UCHARGER_CHARGE_END_GPIO_PIN GPIO_Pin_13 // PB.13 input + +#define UCHARGER_EN_GPIO GPIOG +#define UCHARGER_EN_GPIO_PIN GPIO_Pin_3 // PG.03 output + +#if defined (WIRELESS_CHARGER) + + #define WCHARGER_GPIO GPIOI + #define WCHARGER_GPIO_PIN GPIO_Pin_9 // PI.09 input + + #define WCHARGER_CHARGE_END_GPIO GPIOI + #define WCHARGER_CHARGE_END_GPIO_PIN GPIO_Pin_10 // PI.10 input + + #define WCHARGER_EN_GPIO GPIOH + #define WCHARGER_EN_GPIO_PIN GPIO_Pin_4 // PH.04 output + + #define WCHARGER_I_CONTROL_GPIO GPIOH + #define WCHARGER_I_CONTROL_GPIO_PIN GPIO_Pin_13 // PH.13 output + +#endif + +// TODO! Check IOLL1 to PI.01 connectivity! + +// S.Port update connector +#define SPORT_MAX_BAUDRATE 400000 +#define SPORT_UPDATE_RCC_AHB1Periph 0 +#define HAS_SPORT_UPDATE_CONNECTOR() (false) + +// Serial Port (DEBUG) +// We will temporarily used the PPM and the HEARTBEAT PINS +#define AUX_SERIAL_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE) +#define AUX_SERIAL_RCC_APB1Periph 0 +#define AUX_SERIAL_RCC_APB2Periph RCC_APB2Periph_USART6 +#define AUX_SERIAL_GPIO GPIOC +#define AUX_SERIAL_GPIO_PIN_TX GPIO_Pin_6 // PC.06 +#define AUX_SERIAL_GPIO_PIN_RX GPIO_Pin_7 // PC.07 +#define AUX_SERIAL_GPIO_PinSource_TX GPIO_PinSource6 +#define AUX_SERIAL_GPIO_PinSource_RX GPIO_PinSource7 +#define AUX_SERIAL_GPIO_AF GPIO_AF_USART6 +#define AUX_SERIAL_USART USART6 +#define AUX_SERIAL_USART_IRQHandler USART6_IRQHandler +#define AUX_SERIAL_USART_IRQn USART6_IRQn +#define AUX_SERIAL_TX_INVERT_GPIO GPIOE +#define AUX_SERIAL_TX_INVERT_GPIO_PIN GPIO_Pin_3 // PE.03 +#define AUX_SERIAL_RX_INVERT_GPIO GPIOI +#define AUX_SERIAL_RX_INVERT_GPIO_PIN GPIO_Pin_15 // PI.15 + +//used in BOOTLOADER +#define SERIAL_RCC_AHB1Periph 0 +#define SERIAL_RCC_APB1Periph 0 +#define AUX2_SERIAL_RCC_AHB1Periph 0 +#define AUX2_SERIAL_RCC_APB1Periph 0 +#define AUX2_SERIAL_RCC_APB2Periph 0 +#define KEYS_BACKLIGHT_RCC_AHB1Periph 0 + +// Telemetry +#define TELEMETRY_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOJ | RCC_AHB1Periph_DMA1) +#define TELEMETRY_RCC_APB1Periph RCC_APB1Periph_USART2 +#define TELEMETRY_REV_GPIO GPIOJ +#define TELEMETRY_RX_REV_GPIO_PIN GPIO_Pin_8 // PJ.08 +#define TELEMETRY_TX_REV_GPIO_PIN GPIO_Pin_7 // PJ.07 +#define TELEMETRY_DIR_GPIO GPIOJ +#define TELEMETRY_DIR_GPIO_PIN GPIO_Pin_13 // PJ.13 +#define TELEMETRY_SET_INPUT 1 +#define TELEMETRY_GPIO GPIOD +#define TELEMETRY_TX_GPIO_PIN GPIO_Pin_5 // PD.05 +#define TELEMETRY_RX_GPIO_PIN GPIO_Pin_6 // PD.06 +#define TELEMETRY_GPIO_PinSource_TX GPIO_PinSource5 +#define TELEMETRY_GPIO_PinSource_RX GPIO_PinSource6 +#define TELEMETRY_GPIO_AF GPIO_AF_USART2 +#define TELEMETRY_USART USART2 +#define TELEMETRY_DMA DMA1 +#define TELEMETRY_DMA_Stream_TX LL_DMA_STREAM_6 +#define TELEMETRY_DMA_Channel_TX DMA_Channel_4 +#define TELEMETRY_DMA_TX_Stream_IRQ DMA1_Stream6_IRQn +#define TELEMETRY_DMA_TX_IRQHandler DMA1_Stream6_IRQHandler +#define TELEMETRY_DMA_TX_FLAG_TC DMA_IT_TCIF6 +// #define TELEMETRY_DMA_Stream_RX LL_DMA_STREAM_5 +// #define TELEMETRY_DMA_Channel_RX LL_DMA_CHANNEL_4 +#define TELEMETRY_USART_IRQHandler USART2_IRQHandler +#define TELEMETRY_USART_IRQn USART2_IRQn + +#define TELEMETRY_DIR_OUTPUT() TELEMETRY_DIR_GPIO->BSRRH = TELEMETRY_DIR_GPIO_PIN +#define TELEMETRY_DIR_INPUT() TELEMETRY_DIR_GPIO->BSRRL = TELEMETRY_DIR_GPIO_PIN +#define TELEMETRY_TX_POL_NORM() TELEMETRY_REV_GPIO->BSRRH = TELEMETRY_TX_REV_GPIO_PIN +#define TELEMETRY_TX_POL_INV() TELEMETRY_REV_GPIO->BSRRL = TELEMETRY_TX_REV_GPIO_PIN +#define TELEMETRY_RX_POL_NORM() TELEMETRY_REV_GPIO->BSRRH = TELEMETRY_RX_REV_GPIO_PIN +#define TELEMETRY_RX_POL_INV() TELEMETRY_REV_GPIO->BSRRL = TELEMETRY_RX_REV_GPIO_PIN + +// Software IRQ (Prio 5 -> FreeRTOS compatible) +#define TELEMETRY_RX_FRAME_EXTI_LINE LL_EXTI_LINE_4 +#define USE_EXTI4_IRQ +#define EXTI4_IRQ_Priority 5 + +// USB +#define USB_RCC_AHB1Periph_GPIO RCC_AHB1Periph_GPIOA +#define USB_GPIO GPIOA +// #define USB_GPIO_PIN_VBUS GPIO_Pin_9 // PA.09 +#define USB_GPIO_PIN_ID GPIO_Pin_10 // PA.10 +#define USB_GPIO_PIN_DM GPIO_Pin_11 // PA.11 +#define USB_GPIO_PIN_DP GPIO_Pin_12 // PA.12 +#define USB_GPIO_PinSource_DM GPIO_PinSource11 +#define USB_GPIO_PinSource_DP GPIO_PinSource12 +#define USB_GPIO_AF GPIO_AF_OTG1_FS + +// LCD +#define LCD_RCC_AHB1Periph (RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOJ | RCC_AHB1Periph_GPIOK | RCC_AHB1Periph_DMA2D) +#define LCD_RCC_APB1Periph 0 +#define LCD_RCC_APB2Periph RCC_APB2Periph_LTDC +#define LCD_NRST_GPIO GPIOG +#define LCD_NRST_GPIO_PIN LL_GPIO_PIN_9 // PG.09 +#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 + +// Backlight +// TODO TIM3, TIM8, TIM14, review the channel in backlight_driver.cpp according to the chosen timer +#define BACKLIGHT_RCC_AHB1Periph RCC_AHB1Periph_GPIOA +#define BACKLIGHT_RCC_APB1Periph RCC_APB1Periph_TIM2 +#define BACKLIGHT_RCC_APB2Periph 0 +#define BACKLIGHT_GPIO GPIOA +#define BACKLIGHT_GPIO_PIN GPIO_Pin_15 +#define BACKLIGHT_GPIO_PinSource GPIO_PinSource15 +#define BACKLIGHT_TIMER TIM2 +#define BACKLIGHT_GPIO_AF GPIO_AF_TIM2 +#define BACKLIGHT_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) + +//used in BOOTLOADER +#define SERIAL_RCC_AHB1Periph 0 +#define SERIAL_RCC_APB1Periph 0 +#define ROTARY_ENCODER_RCC_APB1Periph 0 + +// SPI NOR Flash +#define FLASH_SPI SPI6 +#define FLASH_SPI_CS_GPIO GPIOG +#define FLASH_SPI_CS_GPIO_PIN LL_GPIO_PIN_6 // PG.06 +#define FLASH_SPI_GPIO GPIOG +#define FLASH_SPI_SCK_GPIO_PIN LL_GPIO_PIN_13 // PG.13 +#define FLASH_SPI_MISO_GPIO_PIN LL_GPIO_PIN_12 // PG.12 +#define FLASH_SPI_MOSI_GPIO_PIN LL_GPIO_PIN_14 // PG.14 +// #define FLASH_SPI_DMA DMA2 +// #define FLASH_SPI_DMA_CHANNEL LL_DMA_CHANNEL_1 +// #define FLASH_SPI_DMA_TX_STREAM LL_DMA_STREAM_5 +// #define FLASH_SPI_DMA_TX_IRQn DMA2_Stream5_IRQn +// #define FLASH_SPI_DMA_TX_IRQHandler DMA2_Stream5_IRQHandler +// #define FLASH_SPI_DMA_RX_STREAM LL_DMA_STREAM_6 +// #define FLASH_SPI_DMA_RX_IRQn DMA2_Stream6_IRQn +// #define FLASH_SPI_DMA_RX_IRQHandler DMA2_Stream6_IRQHandler +#define STORAGE_USE_SPI_FLASH + +// SDRAM +#define SDRAM_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOH) +#define SDRAM_RCC_AHB3Periph RCC_AHB3Periph_FMC + +// Audio +#define AUDIO_RCC_APB1Periph (RCC_APB1Periph_TIM6 | RCC_APB1Periph_DAC) +#define AUDIO_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_DMA1) +#define AUDIO_OUTPUT_GPIO GPIOA +#define AUDIO_OUTPUT_GPIO_PIN GPIO_Pin_4 // PA.04 +#define AUDIO_GPIO_PinSource GPIO_PinSource4 +#define AUDIO_DMA_Stream DMA1_Stream5 +#define AUDIO_DMA_Stream_IRQn DMA1_Stream5_IRQn +#define AUDIO_TIM_IRQn TIM6_DAC_IRQn +#define AUDIO_TIM_IRQHandler TIM6_DAC_IRQHandler +#define AUDIO_DMA_Stream_IRQHandler DMA1_Stream5_IRQHandler +#define AUDIO_TIMER TIM6 +#define AUDIO_DMA DMA1 + +// I2C Bus +#define I2C_B1 I2C1 +#define I2C_B1_GPIO GPIOB +#define I2C_B1_SDA_GPIO_PIN LL_GPIO_PIN_7 // PB.07 +#define I2C_B1_SCL_GPIO_PIN LL_GPIO_PIN_8 // PB.08 +#define I2C_B1_GPIO_AF LL_GPIO_AF_4 + +// Touch +#define TOUCH_I2C_BUS I2C_Bus_1 +#define TOUCH_I2C_CLK_RATE 400000 +#define TOUCH_INT_GPIO GPIOB +#define TOUCH_INT_GPIO_PIN LL_GPIO_PIN_9 // PB.09 +#define TOUCH_RST_GPIO GPIOB +#define TOUCH_RST_GPIO_PIN LL_GPIO_PIN_12 // PB.12 +#define TOUCH_INT_EXTI_Line LL_EXTI_LINE_9 +#define TOUCH_INT_EXTI_Port LL_SYSCFG_EXTI_PORTB +#define TOUCH_INT_EXTI_SysCfgLine LL_SYSCFG_EXTI_LINE9 + +// TOUCH_INT_EXTI IRQ +#if !defined(USE_EXTI9_5_IRQ) + #define USE_EXTI9_5_IRQ + #define EXTI9_5_IRQ_Priority 9 +#endif + +// Haptic: TIM1_CH1 +#define HAPTIC_PWM +#define HAPTIC_RCC_AHB1Periph RCC_AHB1Periph_GPIOA +#define HAPTIC_RCC_APB2Periph RCC_APB2ENR_TIM1EN +#define HAPTIC_GPIO GPIOA +#define HAPTIC_GPIO_PIN GPIO_Pin_8 +#define HAPTIC_GPIO_TIMER TIM1 +#define HAPTIC_GPIO_AF GPIO_AF_TIM1 +#define HAPTIC_GPIO_PinSource GPIO_PinSource8 +#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 + +// Flysky Hall Stick +#define FLYSKY_HALL_SERIAL_USART UART4 +#define FLYSKY_HALL_SERIAL_GPIO GPIOA +#define FLYSKY_HALL_DMA_Channel LL_DMA_CHANNEL_4 +#define FLYSKY_HALL_SERIAL_TX_GPIO_PIN LL_GPIO_PIN_0 // PA.00 +#define FLYSKY_HALL_SERIAL_RX_GPIO_PIN LL_GPIO_PIN_1 // PA.01 +#define FLYSKY_HALL_SERIAL_GPIO_AF LL_GPIO_AF_8 + +#define FLYSKY_HALL_RCC_AHB1Periph RCC_AHB1Periph_DMA1 +#define FLYSKY_HALL_RCC_APB1Periph RCC_APB1Periph_UART4 + +#define FLYSKY_HALL_SERIAL_USART_IRQHandler UART4_IRQHandler +#define FLYSKY_HALL_SERIAL_USART_IRQn UART4_IRQn +#define FLYSKY_HALL_SERIAL_DMA DMA1 +#define FLYSKY_HALL_DMA_Stream_RX LL_DMA_STREAM_2 +#define FLYSKY_HALL_DMA_Stream_TX LL_DMA_STREAM_4 + +// LED Strip +#define LED_STRIP_LENGTH 4 +#define LED_STRIP_GPIO GPIOH +#define LED_STRIP_GPIO_PIN_DATA LL_GPIO_PIN_12 // PH.12 / TIM5_CH3 +#define LED_STRIP_GPIO_PIN_AF LL_GPIO_AF_2 // TIM3/4/5 +#define LED_STRIP_TIMER TIM5 +#define LED_STRIP_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) +#define LED_STRIP_TIMER_CHANNEL LL_TIM_CHANNEL_CH3 +#define LED_STRIP_TIMER_DMA DMA1 +#define LED_STRIP_TIMER_DMA_CHANNEL LL_DMA_CHANNEL_6 +#define LED_STRIP_TIMER_DMA_STREAM LL_DMA_STREAM_0 +#define LED_STRIP_TIMER_DMA_IRQn DMA1_Stream0_IRQn +#define LED_STRIP_TIMER_DMA_IRQHandler DMA1_Stream0_IRQHandler +#define LED_STRIP_REFRESH_PERIOD 50 //ms + +#define STATUS_LEDS + + +// Internal Module +#if defined(RADIO_PL18) +#define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_DMA1) +#define INTMODULE_PWR_GPIO GPIOI +#define INTMODULE_PWR_GPIO_PIN GPIO_Pin_0 // PI.00 +#define INTMODULE_GPIO GPIOF +#define INTMODULE_TX_GPIO_PIN LL_GPIO_PIN_7 // PF.07 +#define INTMODULE_RX_GPIO_PIN LL_GPIO_PIN_6 // PF.06 +#define INTMODULE_USART UART7 +#define INTMODULE_GPIO_AF LL_GPIO_AF_8 +#define INTMODULE_USART_IRQn UART7_IRQn +#define INTMODULE_USART_IRQHandler UART7_IRQHandler +#define INTMODULE_DMA DMA1 +#define INTMODULE_DMA_STREAM LL_DMA_STREAM_1 +#define INTMODULE_DMA_STREAM_IRQ DMA1_Stream1_IRQn +#define INTMODULE_DMA_FLAG_TC DMA_FLAG_TCIF1 +#define INTMODULE_DMA_CHANNEL LL_DMA_CHANNEL_5 +#define INTMODULE_RX_DMA DMA1 +#define INTMODULE_RX_DMA_STREAM LL_DMA_STREAM_3 +#define INTMODULE_RX_DMA_CHANNEL LL_DMA_CHANNEL_5 +// #define INTMODULE_RX_DMA_Stream_IRQn DMA1_Stream3_IRQn +// #define INTMODULE_RX_DMA_Stream_IRQHandler DMA1_Stream_IRQHandler + +#define INTMODULE_TIMER TIM3 +#define INTMODULE_TIMER_IRQn TIM3_IRQn +#define INTMODULE_TIMER_IRQHandler TIM3_IRQHandler +#define INTMODULE_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) +#endif + +// External Module +#define EXTMODULE +#define EXTMODULE_PULSES +#define EXTMODULE_PWR_GPIO GPIOD +#define EXTMODULE_PWR_GPIO_PIN GPIO_Pin_11 // PD.11 +#define EXTMODULE_RCC_AHB1Periph \ + (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOC | \ + RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_DMA2) +#define EXTMODULE_TX_GPIO GPIOC +#define EXTMODULE_TX_GPIO_PIN LL_GPIO_PIN_6 // PC.06 +#define EXTMODULE_TX_GPIO_AF LL_GPIO_AF_3 // TIM8_CH1 +#define EXTMODULE_TX_GPIO_AF_USART GPIO_AF_USART6 +#define EXTMODULE_RX_GPIO GPIOC +#define EXTMODULE_RX_GPIO_PIN LL_GPIO_PIN_7 // PC.07 +#define EXTMODULE_RX_GPIO_AF_USART GPIO_AF_USART6 +#define EXTMODULE_TIMER TIM8 +#define EXTMODULE_TIMER_Channel LL_TIM_CHANNEL_CH1 +#define EXTMODULE_TIMER_IRQn TIM8_UP_TIM13_IRQn +#define EXTMODULE_TIMER_IRQHandler TIM8_UP_TIM13_IRQHandler +#define EXTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2) +#define EXTMODULE_TIMER_TX_GPIO_AF LL_GPIO_AF_3 +//USART +#define EXTMODULE_USART USART6 +#define EXTMODULE_USART_GPIO GPIOC +#define EXTMODULE_USART_GPIO_AF GPIO_AF_USART6 +#define EXTMODULE_USART_GPIO_AF_LL LL_GPIO_AF_8 +#define EXTMODULE_USART_TX_DMA DMA2 +#define EXTMODULE_USART_TX_DMA_CHANNEL LL_DMA_CHANNEL_5 +#define EXTMODULE_USART_TX_DMA_STREAM DMA2_Stream7 +#define EXTMODULE_USART_TX_DMA_STREAM_LL LL_DMA_STREAM_7 + +#define EXTMODULE_USART_RX_DMA_CHANNEL LL_DMA_CHANNEL_5 +#define EXTMODULE_USART_RX_DMA_STREAM DMA2_Stream2 +#define EXTMODULE_USART_RX_DMA_STREAM_LL LL_DMA_STREAM_2 + +#define EXTMODULE_USART_IRQHandler USART6_IRQHandler +#define EXTMODULE_USART_IRQn USART6_IRQn + +//TIMER +#define EXTMODULE_TIMER_DMA_CHANNEL LL_DMA_CHANNEL_7 +#define EXTMODULE_TIMER_DMA_STREAM DMA2_Stream1 +#define EXTMODULE_TIMER_DMA DMA2 +#define EXTMODULE_TIMER_DMA_STREAM_LL LL_DMA_STREAM_1 +#define EXTMODULE_TIMER_DMA_STREAM_IRQn DMA2_Stream1_IRQn +#define EXTMODULE_TIMER_DMA_IRQHandler DMA2_Stream1_IRQHandler + +#define EXTMODULE_TX_INVERT_GPIO GPIOE +#define EXTMODULE_TX_INVERT_GPIO_PIN GPIO_Pin_3 // PE.03 +#define EXTMODULE_RX_INVERT_GPIO GPIOI +#define EXTMODULE_RX_INVERT_GPIO_PIN GPIO_Pin_15 // PI.15 + +#define EXTMODULE_TX_NORMAL() EXTMODULE_TX_INVERT_GPIO->BSRRH = EXTMODULE_TX_INVERT_GPIO_PIN +#define EXTMODULE_TX_INVERTED() EXTMODULE_TX_INVERT_GPIO->BSRRL = EXTMODULE_TX_INVERT_GPIO_PIN +#define EXTMODULE_RX_NORMAL() EXTMODULE_RX_INVERT_GPIO->BSRRH = EXTMODULE_RX_INVERT_GPIO_PIN +#define EXTMODULE_RX_INVERTED() EXTMODULE_RX_INVERT_GPIO->BSRRL = EXTMODULE_RX_INVERT_GPIO_PIN + +// Trainer Port +#define TRAINER_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD) +#define TRAINER_GPIO GPIOD + +#define TRAINER_IN_GPIO_PIN LL_GPIO_PIN_12 // PD.12 +#define TRAINER_IN_TIMER_Channel LL_TIM_CHANNEL_CH1 + +#define TRAINER_OUT_GPIO_PIN LL_GPIO_PIN_13 // PD.13 +#define TRAINER_OUT_TIMER_Channel LL_TIM_CHANNEL_CH2 + +#define TRAINER_TIMER TIM4 +#define TRAINER_TIMER_IRQn TIM4_IRQn +#define TRAINER_TIMER_IRQHandler TIM4_IRQHandler +#define TRAINER_GPIO_AF LL_GPIO_AF_2 +#define TRAINER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) + +//ROTARY emulation for trims as buttons +#define ROTARY_ENCODER_NAVIGATION + +//BLUETOOTH +#define BLUETOOTH_ON_RCC_AHB1Periph RCC_AHB1Periph_GPIOI +#define BT_EN_GPIO GPIOI +#define BT_EN_GPIO_PIN GPIO_Pin_8 // PI.8 + +#define BT_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOH) +#define BT_RCC_APB1Periph (RCC_APB1Periph_USART3) +#define BT_RCC_APB2Periph 0 + +#define BT_USART USART3 +#define BT_GPIO_AF GPIO_AF_USART3 +#define BT_USART_IRQn USART3_IRQn +#define BT_GPIO_TXRX GPIOB +#define BT_TX_GPIO_PIN GPIO_Pin_10 // PB.10 +#define BT_RX_GPIO_PIN GPIO_Pin_11 // PB.11 +#define BT_TX_GPIO_PinSource GPIO_PinSource10 +#define BT_RX_GPIO_PinSource GPIO_PinSource11 +#define BT_USART_IRQHandler USART3_IRQHandler + +#define BT_CONNECTED_GPIO GPIOJ +#define BT_CONNECTED_GPIO_PIN GPIO_Pin_1 // PJ.01 + +#define BT_CMD_MODE_GPIO GPIOH +#define BT_CMD_MODE_GPIO_PIN GPIO_Pin_6 // PH.6 + +// Millisecond timer +#define MS_TIMER TIM14 +#define MS_TIMER_IRQn TIM8_TRG_COM_TIM14_IRQn +#define MS_TIMER_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler + +// Mixer scheduler timer +#define MIXER_SCHEDULER_TIMER TIM12 +#define MIXER_SCHEDULER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) +#define MIXER_SCHEDULER_TIMER_IRQn TIM8_BRK_TIM12_IRQn +#define MIXER_SCHEDULER_TIMER_IRQHandler TIM8_BRK_TIM12_IRQHandler + +#define LCD_W 480 +#define LCD_H 320 + +#define LCD_PHYS_W 320 +#define LCD_PHYS_H 480 + +#define LCD_DEPTH 16 +#define LCD_CONTRAST_DEFAULT 20 + +#endif // _HAL_H_ diff --git a/radio/src/targets/pl18/haptic_driver.cpp b/radio/src/targets/pl18/haptic_driver.cpp new file mode 100644 index 00000000000..d8fc8f809da --- /dev/null +++ b/radio/src/targets/pl18/haptic_driver.cpp @@ -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. + */ + +#include "board.h" + +void hapticOff(void) +{ + HAPTIC_TIMER_COMPARE_VALUE = 0; +} + +void hapticOn(uint32_t pwmPercent) +{ + if (pwmPercent > 100) { + pwmPercent = 100; + } + HAPTIC_TIMER_COMPARE_VALUE = pwmPercent; +} + +void hapticInit(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = HAPTIC_GPIO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(HAPTIC_GPIO, &GPIO_InitStructure); + + GPIO_PinAFConfig(HAPTIC_GPIO, HAPTIC_GPIO_PinSource, HAPTIC_GPIO_AF); + + HAPTIC_GPIO_TIMER->ARR = 100; + HAPTIC_GPIO_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 10000 - 1; + HAPTIC_GPIO_TIMER->CCMR1 = HAPTIC_TIMER_MODE; // PWM + HAPTIC_GPIO_TIMER->CCER = HAPTIC_TIMER_OUTPUT_ENABLE; + HAPTIC_GPIO_TIMER->CCR1 = 0; + HAPTIC_GPIO_TIMER->EGR = TIM_EGR_UG; + HAPTIC_GPIO_TIMER->CR1 = TIM_CR1_CEN; // counter enable + HAPTIC_GPIO_TIMER->BDTR |= TIM_BDTR_MOE; +} + +void hapticDone(void) +{ + hapticOff(); + RCC_AHB1PeriphClockCmd(HAPTIC_RCC_AHB1Periph, DISABLE); +} diff --git a/radio/src/targets/pl18/key_driver.cpp b/radio/src/targets/pl18/key_driver.cpp new file mode 100644 index 00000000000..cd09c374d71 --- /dev/null +++ b/radio/src/targets/pl18/key_driver.cpp @@ -0,0 +1,220 @@ +/* + * 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 "hal/key_driver.h" + +#include "stm32_hal_ll.h" +#include "stm32_gpio_driver.h" + +#include "hal.h" +#include "delays_driver.h" +#include "keys.h" + +/* The output bit-order has to be: + 0 LHL TR7L (Left equals down) + 1 LHR TR7R + 2 LVD TR5D + 3 LVU TR5U + 4 RVD TR6D + 5 RVU TR6U + 6 RHL TR8L + 7 RHR TR8R + 8 LSD TR1D + 9 LSU TR1U + 10 RSD TR2D + 11 RSU TR2U + 12 EX1D TR3D + 13 EX1U TR3U + 14 EX2D TR4D + 15 EX2U TR4U +*/ + +enum PhysicalTrims +{ + TR7L = 0, + TR7R, + TR5D = 2, + TR5U, + TR6D = 4, + TR6U, + TR8L = 6, + TR8R, + TR1D = 8, + TR1U, + TR2D = 10, + TR2U, + TR3D = 12, + TR3U, + TR4D = 14, + TR4U, +}; + +void keysInit() +{ + stm32_gpio_enable_clock(GPIOB); + stm32_gpio_enable_clock(GPIOC); + stm32_gpio_enable_clock(GPIOD); + stm32_gpio_enable_clock(GPIOF); + stm32_gpio_enable_clock(GPIOH); + stm32_gpio_enable_clock(GPIOJ); + + LL_GPIO_InitTypeDef pinInit; + LL_GPIO_StructInit(&pinInit); + pinInit.Mode = LL_GPIO_MODE_INPUT; + pinInit.Pull = LL_GPIO_PULL_DOWN; + + pinInit.Pin = KEYS_GPIOB_PINS; + LL_GPIO_Init(GPIOB, &pinInit); + + pinInit.Pin = KEYS_GPIOC_PINS; + LL_GPIO_Init(GPIOC, &pinInit); + + pinInit.Pin = KEYS_GPIOD_PINS; + LL_GPIO_Init(GPIOD, &pinInit); + + pinInit.Pin = KEYS_GPIOH_PINS; + LL_GPIO_Init(GPIOH, &pinInit); + + pinInit.Pin = KEYS_GPIOJ_PINS; + LL_GPIO_Init(GPIOJ, &pinInit); + + // Matrix outputs + pinInit.Mode = LL_GPIO_MODE_OUTPUT; + pinInit.Pull = LL_GPIO_PULL_NO; + + pinInit.Pin = KEYS_OUT_GPIOG_PINS; + LL_GPIO_Init(GPIOG, &pinInit); + + pinInit.Pin = KEYS_OUT_GPIOH_PINS; + LL_GPIO_Init(GPIOH, &pinInit); +} + +static uint32_t _readKeyMatrix() +{ + // This function avoids concurrent matrix agitation + + uint32_t result = 0; + /* Bit 0 - TR3 down + * Bit 1 - TR3 up + * Bit 2 - TR4 down + * Bit 3 - TR4 up + * Bit 4 - TR5 down + * Bit 5 - TR5 up + * Bit 6 - TR6 down + * Bit 7 - TR6 up + * Bit 8 - TR7 left + * Bit 9 - TR7 right + * Bit 10 - TR8 left + * Bit 11 - TR8 right + */ + + volatile static struct + { + uint32_t oldResult = 0; + uint8_t ui8ReadInProgress = 0; + } syncelem; + + if (syncelem.ui8ReadInProgress != 0) return syncelem.oldResult; + + // ui8ReadInProgress was 0, increment it + syncelem.ui8ReadInProgress++; + // Double check before continuing, as non-atomic, non-blocking so far + // If ui8ReadInProgress is above 1, then there was concurrent task calling it, exit + if (syncelem.ui8ReadInProgress > 1) return syncelem.oldResult; + + // If we land here, we have exclusive access to Matrix + LL_GPIO_ResetOutputPin(TRIMS_GPIO_OUT1, TRIMS_GPIO_OUT1_PIN); + LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT2, TRIMS_GPIO_OUT2_PIN); + LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT3, TRIMS_GPIO_OUT3_PIN); + LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT4, TRIMS_GPIO_OUT4_PIN); + delay_us(10); + if (~TRIMS_GPIO_REG_IN1 & TRIMS_GPIO_PIN_IN1) + result |= 1 << TR7L; + if (~TRIMS_GPIO_REG_IN2 & TRIMS_GPIO_PIN_IN2) + result |= 1 << TR7R; + if (~TRIMS_GPIO_REG_IN3 & TRIMS_GPIO_PIN_IN3) + result |= 1 << TR5D; + if (~TRIMS_GPIO_REG_IN4 & TRIMS_GPIO_PIN_IN4) + result |= 1 << TR5U; + + LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT1, TRIMS_GPIO_OUT1_PIN); + LL_GPIO_ResetOutputPin(TRIMS_GPIO_OUT2, TRIMS_GPIO_OUT2_PIN); + delay_us(10); + if (~TRIMS_GPIO_REG_IN1 & TRIMS_GPIO_PIN_IN1) + result |= 1 << TR3D; + if (~TRIMS_GPIO_REG_IN2 & TRIMS_GPIO_PIN_IN2) + result |= 1 << TR3U; + if (~TRIMS_GPIO_REG_IN3 & TRIMS_GPIO_PIN_IN3) + result |= 1 << TR4U; + if (~TRIMS_GPIO_REG_IN4 & TRIMS_GPIO_PIN_IN4) + result |= 1 << TR4D; + + LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT2, TRIMS_GPIO_OUT2_PIN); + LL_GPIO_ResetOutputPin(TRIMS_GPIO_OUT3, TRIMS_GPIO_OUT3_PIN); + delay_us(10); + if (~TRIMS_GPIO_REG_IN1 & TRIMS_GPIO_PIN_IN1) + result |= 1 << TR6U; + if (~TRIMS_GPIO_REG_IN2 & TRIMS_GPIO_PIN_IN2) + result |= 1 << TR6D; + if (~TRIMS_GPIO_REG_IN3 & TRIMS_GPIO_PIN_IN3) + result |= 1 << TR8L; + if (~TRIMS_GPIO_REG_IN4 & TRIMS_GPIO_PIN_IN4) + result |= 1 << TR8R; + + LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT3, TRIMS_GPIO_OUT3_PIN); + + syncelem.oldResult = result; + syncelem.ui8ReadInProgress = 0; + + return result; +} + +uint32_t readKeys() +{ + uint32_t result = 0; + + if (getHatsAsKeys()) { + uint32_t mkeys = _readKeyMatrix(); + if (mkeys & (1 << TR4D)) result |= 1 << KEY_ENTER; + if (mkeys & (1 << TR4U)) result |= 1 << KEY_EXIT; + } + + return result; +} + +uint32_t readTrims() +{ + uint32_t result = 0; + + result |= _readKeyMatrix(); + + if (~TRIMS_GPIO_REG_TR1U & TRIMS_GPIO_PIN_TR1U) + result |= 1 << (TR1U); + if (~TRIMS_GPIO_REG_TR1D & TRIMS_GPIO_PIN_TR1D) + result |= 1 << (TR1D); + + if (~TRIMS_GPIO_REG_TR2U & TRIMS_GPIO_PIN_TR2U) + result |= 1 << (TR2U); + if (~TRIMS_GPIO_REG_TR2D & TRIMS_GPIO_PIN_TR2D) + result |= 1 << (TR2D); + + return result; +} diff --git a/radio/src/targets/pl18/lcd_driver.cpp b/radio/src/targets/pl18/lcd_driver.cpp new file mode 100644 index 00000000000..7067e9d4cb7 --- /dev/null +++ b/radio/src/targets/pl18/lcd_driver.cpp @@ -0,0 +1,2876 @@ +/* + * 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 "stm32_hal_ll.h" +#include "stm32_hal.h" +#include "opentx_types.h" +#include "dma2d.h" +#include "hal.h" +#include "delays_driver.h" +#include "debug.h" +#include "lcd.h" +#include "lcd_driver.h" + +uint8_t TouchControllerType = 0; //0:cst340; 1 ft6236 +static volatile uint16_t lcd_phys_w = LCD_PHYS_W; +static volatile uint16_t lcd_phys_h = LCD_PHYS_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 ©_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); +} + +lcdSpiInitFucPtr lcdInitFunction; +lcdSpiInitFucPtr lcdOffFunction; +lcdSpiInitFucPtr lcdOnFunction; +uint32_t lcdPixelClock; + +volatile uint8_t LCD_ReadBuffer[24] = { 0, 0 }; + +static void LCD_Delay(void) { + volatile unsigned int i; + + for (i = 0; i < 20; i++) { + ; + } +} + +enum ENUM_IO_SPEED +{ + IO_SPEED_LOW, + IO_SPEED_MID, + IO_SPEED_QUICK, + IO_SPEED_HIGH +}; + +enum ENUM_IO_MODE +{ + IO_MODE_INPUT, + IO_MODE_OUTPUT, + IO_MODE_ALTERNATE, + IO_MODE_ANALOG +}; + +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_LOW; + 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_LOW; + 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.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStructure.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + 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); +} + +unsigned char LCD_ReadByteOnFallingEdge(void) { + unsigned int i; + unsigned char ReceiveData = 0; + + LCD_MOSI_HIGH(); + LCD_MOSI_AS_INPUT(); + + for (i = 0; i < 8; i++) { + LCD_DELAY(); + LCD_SCK_HIGH(); + LCD_DELAY(); + LCD_DELAY(); + ReceiveData <<= 1; + + LCD_SCK_LOW(); + LCD_DELAY(); + LCD_DELAY(); + if (LCD_READ_DATA_PIN()) { + ReceiveData |= 0x01; + } + } + + LCD_MOSI_AS_OUTPUT(); + + return (ReceiveData); +} + +static void lcdWriteByte(uint8_t data_enable, uint8_t byte) { + + LCD_SCK_LOW(); + lcdDelay(); + + if (data_enable) { + LCD_MOSI_HIGH(); + } else { + LCD_MOSI_LOW(); + } + + LCD_SCK_HIGH(); + lcdDelay(); + + for (int i = 0; i < 8; i++) { + LCD_SCK_LOW(); + lcdDelay(); + + if (byte & 0x80) { + LCD_MOSI_HIGH(); + } else { + LCD_MOSI_LOW(); + } + + LCD_SCK_HIGH(); + byte <<= 1; + + lcdDelay(); + } + + LCD_SCK_LOW(); +} + +unsigned char LCD_ReadByte(void) { + unsigned int i; + unsigned char ReceiveData = 0; + + LCD_MOSI_HIGH(); + LCD_MOSI_AS_INPUT(); + for (i = 0; i < 8; i++) { + LCD_SCK_LOW(); + lcdDelay(); + ReceiveData <<= 1; + LCD_SCK_HIGH(); + lcdDelay(); + if (LCD_READ_DATA_PIN()) { + ReceiveData |= 0x01; + } + } + LCD_SCK_LOW(); + LCD_MOSI_AS_OUTPUT(); + return (ReceiveData); +} + +unsigned char LCD_ReadRegister(unsigned char Register) { + unsigned char ReadData = 0; + + lcdWriteByte(0, Register); + lcdDelay(); + lcdDelay(); + ReadData = LCD_ReadByte(); + return (ReadData); +} + +void lcdWriteCommand(uint8_t command) { + lcdWriteByte(0, command); +} + +void lcdWriteData(uint8_t data) { + lcdWriteByte(1, data); +} + +void LCD_HX8357D_Init(void) { +#if 0 + lcdWriteCommand(0x11); + delay_ms(200); + + lcdWriteCommand(0xB9); + lcdWriteData(0xFF); + lcdWriteData(0x83); + lcdWriteData(0x57); + + lcdWriteCommand(0xB1); + lcdWriteData(0x00); + lcdWriteData(0x14); + lcdWriteData(0x1C); + lcdWriteData(0x1C); + lcdWriteData(0xC7); + lcdWriteData(0x21); + + lcdWriteCommand(0xB3); + lcdWriteData(0x83); + lcdWriteData(0x00); + lcdWriteData(0x06); + lcdWriteData(0x06); + + lcdWriteCommand(0xB4); + lcdWriteData(0x11); + lcdWriteData(0x40); + lcdWriteData(0x00); + lcdWriteData(0x2A); + lcdWriteData(0x2A); + lcdWriteData(0x20); + lcdWriteData(0x4E); + + lcdWriteCommand(0xB5); + lcdWriteData(0x03); + lcdWriteData(0x03); + + lcdWriteCommand(0xB6); + lcdWriteData(0x38); + + lcdWriteCommand(0xC0); + lcdWriteData(0x24); + lcdWriteData(0x24); + lcdWriteData(0x00); + lcdWriteData(0x10); + lcdWriteData(0xc8); + lcdWriteData(0x08); + + lcdWriteCommand(0xC2); + lcdWriteData(0x00); + lcdWriteData(0x08); + lcdWriteData(0x04); + + lcdWriteCommand(0xCC); + lcdWriteData(0x00); + +//GAMMA 2.5" + lcdWriteCommand(0xE0); + lcdWriteData(0x00); + lcdWriteData(0x06); + lcdWriteData(0x0D); + lcdWriteData(0x18); + lcdWriteData(0x23); + lcdWriteData(0x3B); + lcdWriteData(0x45); + lcdWriteData(0x4D); + lcdWriteData(0x4D); + lcdWriteData(0x46); + lcdWriteData(0x40); + lcdWriteData(0x37); + lcdWriteData(0x34); + lcdWriteData(0x2F); + lcdWriteData(0x2B); + lcdWriteData(0x21); + lcdWriteData(0x00); + lcdWriteData(0x06); + lcdWriteData(0x0D); + lcdWriteData(0x18); + lcdWriteData(0x23); + lcdWriteData(0x3B); + lcdWriteData(0x45); + lcdWriteData(0x4D); + lcdWriteData(0x4D); + lcdWriteData(0x46); + lcdWriteData(0x40); + lcdWriteData(0x37); + lcdWriteData(0x34); + lcdWriteData(0x2F); + lcdWriteData(0x2B); + lcdWriteData(0x21); + lcdWriteData(0x00); + lcdWriteData(0x01); + + lcdWriteCommand(0x3A); + lcdWriteData(0x66); + + 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(0x29); + delay_ms(10); +#elif 0 + delay_ms(50); + lcdWriteCommand(0xB9); //EXTC + lcdWriteData(0xFF); //EXTC + lcdWriteData(0x83); //EXTC + lcdWriteData(0x57); //EXTC + delay_ms(5); + + lcdWriteCommand(0x3A); + lcdWriteData(0x65); //262k + + lcdWriteCommand(0xB3); //COLOR FORMAT + lcdWriteData(0x83); //SDO_EN,BYPASS,EPF[1:0],0,0,RM,DM //43 + + lcdWriteCommand(0xB6); // + lcdWriteData(0x5a); //VCOMDC + + lcdWriteCommand(0x35); // TE ON + lcdWriteData(0x01); + + lcdWriteCommand(0xB0); + lcdWriteData(0x68); //70Hz + + lcdWriteCommand(0xCC); // Set Panel + lcdWriteData(0x00); // + + lcdWriteCommand(0xB1); // + lcdWriteData(0x00); // + lcdWriteData(0x11); //BT + lcdWriteData(0x1C); //VSPR + lcdWriteData(0x1C); //VSNR + lcdWriteData(0x83); //AP + lcdWriteData(0x48); //FS 0xAA + + lcdWriteCommand(0xB4); // + lcdWriteData(0x02); //NW + lcdWriteData(0x40); //RTN + lcdWriteData(0x00); //DIV + lcdWriteData(0x2A); //DUM + lcdWriteData(0x2A); //DUM + lcdWriteData(0x0D); //GDON + lcdWriteData(0x78); //GDOFF 0x4F + lcdWriteCommand(0xC0); //STBA + lcdWriteData(0x50); //OPON + lcdWriteData(0x50); //OPON + lcdWriteData(0x01); // + lcdWriteData(0x3C); // + lcdWriteData(0x1E); // + lcdWriteData(0x08); //GEN + + /* + lcdWriteCommand(0xE0); // + lcdWriteData(0x02); //1 + lcdWriteData(0x06); //2 + lcdWriteData(0x09); //3 + lcdWriteData(0x1C); //4 + lcdWriteData(0x27); //5 + lcdWriteData(0x3C); //6 + lcdWriteData(0x48); //7 + lcdWriteData(0x50); //8 + lcdWriteData(0x49); //9 + lcdWriteData(0x42); //10 + lcdWriteData(0x3E); //11 + lcdWriteData(0x35); //12 + lcdWriteData(0x31); //13 + lcdWriteData(0x2A); //14 + lcdWriteData(0x28); //15 + lcdWriteData(0x03); //16 + lcdWriteData(0x02); //17 v1 + lcdWriteData(0x06); //18 + lcdWriteData(0x09); //19 + lcdWriteData(0x1C); //20 + lcdWriteData(0x27); //21 + lcdWriteData(0x3C); //22 + lcdWriteData(0x48); //23 + lcdWriteData(0x50); //24 + lcdWriteData(0x49); //25 + lcdWriteData(0x42); //26 + lcdWriteData(0x3E); //27 + lcdWriteData(0x35); //28 + lcdWriteData(0x31); //29 + lcdWriteData(0x2A); //30 + lcdWriteData(0x28); //31 + lcdWriteData(0x03); //32 + lcdWriteData(0x44); //33 + lcdWriteData(0x01); //34 + */ + lcdWriteCommand(0xE0); + lcdWriteData(0x00); + lcdWriteData(0x06); + lcdWriteData(0x0D); + lcdWriteData(0x18); + lcdWriteData(0x23); + lcdWriteData(0x3B); + lcdWriteData(0x45); + lcdWriteData(0x4D); + lcdWriteData(0x4D); + lcdWriteData(0x46); + lcdWriteData(0x40); + lcdWriteData(0x37); + lcdWriteData(0x34); + lcdWriteData(0x2F); + lcdWriteData(0x2B); + lcdWriteData(0x21); + lcdWriteData(0x00); + lcdWriteData(0x06); + lcdWriteData(0x0D); + lcdWriteData(0x18); + lcdWriteData(0x23); + lcdWriteData(0x3B); + lcdWriteData(0x45); + lcdWriteData(0x4D); + lcdWriteData(0x4D); + lcdWriteData(0x46); + lcdWriteData(0x40); + lcdWriteData(0x37); + lcdWriteData(0x34); + lcdWriteData(0x2F); + lcdWriteData(0x2B); + lcdWriteData(0x21); + lcdWriteData(0x00); + lcdWriteData(0x01); + lcdWriteCommand(0x36); + lcdWriteData(0x38); + + lcdWriteCommand(0x11); // SLPOUT + delay_ms(200); + + lcdWriteCommand(0x29); // Display On + delay_ms(25); + lcdWriteCommand(0x2C); +#else + lcdWriteCommand(0x11); + delay_ms(200); + + lcdWriteCommand(0xB9); + lcdWriteData(0xFF); + lcdWriteData(0x83); + lcdWriteData(0x57); + delay_ms(5); + +// lcdWriteCommand(0x36); +// lcdWriteData(0x10); + + lcdWriteCommand(0xB1); + lcdWriteData(0x00); + lcdWriteData(0x14); + lcdWriteData(0x1C); + lcdWriteData(0x1C); + lcdWriteData(0xC7); + lcdWriteData(0x21); + lcdWriteCommand(0xB3); + lcdWriteData(0x83); + lcdWriteData(0x00); + lcdWriteData(0x06); + lcdWriteData(0x06); + lcdWriteCommand(0xB4); + lcdWriteData(0x11); + lcdWriteData(0x40); + lcdWriteData(0x00); + lcdWriteData(0x2A); + lcdWriteData(0x2A); + lcdWriteData(0x20); + lcdWriteData(0x4E); + lcdWriteCommand(0xB5); + lcdWriteData(0x03); + lcdWriteData(0x03); + + lcdWriteCommand(0xB6); + lcdWriteData(0x38); + + lcdWriteCommand(0xC0); + lcdWriteData(0x24); + lcdWriteData(0x24); + lcdWriteData(0x00); + lcdWriteData(0x10); + lcdWriteData(0xc8); + lcdWriteData(0x08); + lcdWriteCommand(0xC2); + lcdWriteData(0x00); + lcdWriteData(0x08); + lcdWriteData(0x04); + //GAMMA 2.5" + lcdWriteCommand(0xE0); + lcdWriteData(0x00); + lcdWriteData(0x06); + lcdWriteData(0x0D); + lcdWriteData(0x18); + lcdWriteData(0x23); + lcdWriteData(0x3B); + lcdWriteData(0x45); + lcdWriteData(0x4D); + lcdWriteData(0x4D); + lcdWriteData(0x46); + lcdWriteData(0x40); + lcdWriteData(0x37); + lcdWriteData(0x34); + lcdWriteData(0x2F); + lcdWriteData(0x2B); + lcdWriteData(0x21); + lcdWriteData(0x00); + lcdWriteData(0x06); + lcdWriteData(0x0D); + lcdWriteData(0x18); + lcdWriteData(0x23); + lcdWriteData(0x3B); + lcdWriteData(0x45); + lcdWriteData(0x4D); + lcdWriteData(0x4D); + lcdWriteData(0x46); + lcdWriteData(0x40); + lcdWriteData(0x37); + lcdWriteData(0x34); + lcdWriteData(0x2F); + lcdWriteData(0x2B); + lcdWriteData(0x21); + lcdWriteData(0x00); + lcdWriteData(0x01); + // lcdWriteCommand(0x2A); + // lcdWriteData(0); + // lcdWriteData(0); + // lcdWriteData(480 >> 8); + // lcdWriteData(480); + // lcdWriteCommand(0x2B); + // lcdWriteData(0); + // lcdWriteData(0); + // lcdWriteData(320 >> 8); + // lcdWriteData(320); + lcdWriteCommand(0x3A); + lcdWriteData(0x66); + + lcdWriteCommand(0xCC); + lcdWriteData(0x01); + + lcdWriteCommand( 0x2A ); + lcdWriteData( 0x00 ); + lcdWriteData( 0x00 ); + lcdWriteData( 0x01 ); + lcdWriteData( 0xDF ); + lcdWriteCommand( 0x2B ); + lcdWriteData( 0x00 ); + lcdWriteData( 0x00 ); + lcdWriteData( 0x01 ); + lcdWriteData( 0x3F ); + + lcdWriteCommand(0x36); + lcdWriteData(0x20); + + lcdWriteCommand(0xB9); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + delay_ms(5); + lcdWriteCommand(0x29); +#endif +} + +void LCD_HX8357D_On(void) { + lcdWriteCommand(0x28); + lcdWriteCommand(0x29); +} + +void LCD_HX8357D_Off(void) { + lcdWriteCommand(0x28); +} + +unsigned int LCD_HX8357D_ReadID(void) { + lcdReset(); + int ID = 0; + + lcdWriteCommand( 0xB9 ); + lcdWriteData( 0xff ); + lcdWriteData( 0x83 ); + lcdWriteData( 0x57 ); + + lcdWriteCommand( 0xFE ); + lcdWriteData( 0xd0 ); + ID = LCD_ReadRegister( 0xff ); + + lcdWriteCommand( 0xB9 ); + lcdWriteData( 0x00 ); + lcdWriteData( 0x00 ); + lcdWriteData( 0x00 ); + + return (ID); +} + +void LCD_ILI9481_Init(void) { + lcdWriteCommand(0x11); + delay_ms(120); + + lcdWriteCommand(0xE4); + lcdWriteData(0x0A); + + lcdWriteCommand(0xF0); + lcdWriteData(0x01); + + lcdWriteCommand(0xF3); + lcdWriteData(0x02); + lcdWriteData(0x1A); + + lcdWriteCommand(0xD0); + lcdWriteData(0x07); + lcdWriteData(0x42); + lcdWriteData(0x1B); + + lcdWriteCommand(0xD1); + lcdWriteData(0x00); + lcdWriteData(0x00); //04 + lcdWriteData(0x1A); + + lcdWriteCommand(0xD2); + lcdWriteData(0x01); + lcdWriteData(0x00); //11 + + lcdWriteCommand(0xC0); + lcdWriteData(0x10); + lcdWriteData(0x3B); // + lcdWriteData(0x00); // + lcdWriteData(0x02); + lcdWriteData(0x11); + + lcdWriteCommand(0xC5); + lcdWriteData(0x03); + + lcdWriteCommand(0xC8); + lcdWriteData(0x00); + lcdWriteData(0x01); + lcdWriteData(0x47); + lcdWriteData(0x60); + lcdWriteData(0x04); + lcdWriteData(0x16); + lcdWriteData(0x03); + lcdWriteData(0x67); + lcdWriteData(0x67); + lcdWriteData(0x06); + lcdWriteData(0x0F); + lcdWriteData(0x00); + + lcdWriteCommand(0x36); + lcdWriteData(0x08); + + lcdWriteCommand(0x3A); + lcdWriteData(0x66); //0x55=65k color, 0x66=262k color. + + lcdWriteCommand(0x2A); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x01); + lcdWriteData(0x3F); + + lcdWriteCommand(0x2B); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x01); + lcdWriteData(0xE0); + + lcdWriteCommand(0xB4); + lcdWriteData(0x11); + + lcdWriteCommand(0xc6); + lcdWriteData(0x82); + + delay_ms(120); + + lcdWriteCommand(0x21); + lcdWriteCommand(0x29); + lcdWriteCommand(0x2C); + +} + +void LCD_ILI9481_On(void) { + lcdWriteCommand(0x29); +} + +void LCD_ILI9481_Off(void) { + lcdWriteCommand(0x28); +} + +unsigned int LCD_ILI9481_ReadID(void) { +#if 1 + /* Have a issue here */ + return 0; +#else + int ID = 0; + int Data; + + + lcdWriteByte(0, 0xBF); + + Data = LCD_ReadByteOnFallingEdge(); + Data = LCD_ReadByteOnFallingEdge(); + ID = LCD_ReadByteOnFallingEdge(); + ID <<= 8; + ID |= LCD_ReadByteOnFallingEdge(); + Data = LCD_ReadByteOnFallingEdge(); + Data = LCD_ReadByteOnFallingEdge(); + + LCD_DELAY(); + LCD_DELAY(); + LCD_DELAY(); + + lcdWriteCommand(0xC6); + lcdWriteData(0x82); + //lcdWriteData( 0x9b ); + return (ID); +#endif +} + +void LCD_ILI9486_On(void) { + lcdWriteCommand(0x29); +} + +void LCD_ILI9486_Init(void) { + lcdWriteCommand(0XFB); + lcdWriteData(0x00); + + lcdWriteCommand(0xf2); + lcdWriteData(0x18); + lcdWriteData(0xa3); + lcdWriteData(0x12); + lcdWriteData(0x02); + lcdWriteData(0xb2); + lcdWriteData(0x12); + lcdWriteData(0xff); + lcdWriteData(0x13); + lcdWriteData(0x00); + lcdWriteCommand(0xf1); + lcdWriteData(0x36); + lcdWriteData(0x04); + lcdWriteData(0x00); + lcdWriteData(0x3c); + lcdWriteData(0x0f); + lcdWriteData(0x8f); + lcdWriteCommand(0xf8); + lcdWriteData(0x21); + lcdWriteData(0x04); + lcdWriteCommand(0xf9); + lcdWriteData(0x00); + lcdWriteData(0x08); + lcdWriteCommand(0x36); + lcdWriteData(0x18); + lcdWriteCommand(0x3a); + lcdWriteData(0x65); + lcdWriteCommand(0xc0); + lcdWriteData(0x0f); + lcdWriteData(0x0f); + lcdWriteCommand(0xc1); + lcdWriteData(0x41); + + lcdWriteCommand(0xc5); + lcdWriteData(0x00); + lcdWriteData(0x27); + lcdWriteData(0x80); + lcdWriteCommand(0xb6); + lcdWriteData(0xb2); + lcdWriteData(0x42); + lcdWriteData(0x3b); + lcdWriteCommand(0xb1); + lcdWriteData(0xb0); + lcdWriteData(0x11); + lcdWriteCommand(0xb4); + lcdWriteData(0x02); + lcdWriteCommand(0xb7); + lcdWriteData(0xC6); + + lcdWriteCommand(0xe0); + lcdWriteData(0x0f); + lcdWriteData(0x1C); + lcdWriteData(0x18); + lcdWriteData(0x0B); + lcdWriteData(0x0D); + lcdWriteData(0x06); + lcdWriteData(0x48); + lcdWriteData(0x87); + lcdWriteData(0x3A); + lcdWriteData(0x09); + lcdWriteData(0x15); + lcdWriteData(0x08); + lcdWriteData(0x0D); + lcdWriteData(0x04); + lcdWriteData(0x00); + + lcdWriteCommand(0xe1); + lcdWriteData(0x0f); + lcdWriteData(0x37); + lcdWriteData(0x34); + lcdWriteData(0x0A); + lcdWriteData(0x0B); + lcdWriteData(0x03); + lcdWriteData(0x4B); + lcdWriteData(0x31); + lcdWriteData(0x39); + lcdWriteData(0x03); + lcdWriteData(0x0F); + lcdWriteData(0x03); + lcdWriteData(0x22); + lcdWriteData(0x1D); + lcdWriteData(0x00); + + lcdWriteCommand(0x21); + lcdWriteCommand(0x11); + delay_ms(120); + lcdWriteCommand(0x28); + + LCD_ILI9486_On(); +} + +void LCD_ILI9486_Off(void) { + lcdWriteCommand(0x28); +} + +unsigned int LCD_ILI9486_ReadID(void) { + int ID = 0; + + lcdWriteCommand(0XF7); + lcdWriteData(0xA9); + lcdWriteData(0x51); + lcdWriteData(0x2C); + lcdWriteData(0x82); + lcdWriteCommand(0XB0); + lcdWriteData(0X80); + + lcdWriteCommand(0XFB); + lcdWriteData(0x10 | 0x00); + ID = LCD_ReadRegister(0xd3); + + lcdWriteCommand(0XFB); + lcdWriteData(0x10 | 0x01); + ID = LCD_ReadRegister(0xd3); + + lcdWriteCommand(0XFB); + lcdWriteData(0x10 | 0x02); + ID = LCD_ReadRegister(0xd3); + ID <<= 8; + lcdWriteCommand(0XFB); + lcdWriteData(0x10 | 0x03); + ID |= LCD_ReadRegister(0xd3); + + lcdWriteCommand(0XFB); + lcdWriteData(0x00); + + return (ID); +} + +void LCD_ILI9488_On(void) { + // Display ON + lcdWriteCommand(0x29); +} + +void LCD_ILI9488_Init(void) { + + // lcdWriteCommand(0xFB); + // lcdWriteData(0x00); + + // Adjust Control 3: + // -> DSI write DCS command, use stream packet RGB 666 + lcdWriteCommand(0xF7); + lcdWriteData(0xA9); + lcdWriteData(0x51); + lcdWriteData(0x2C); + lcdWriteData(0x82); + + // Power Control 1: + // -> VREG1OUT = 4.6250 + // -> VREG2OUT = -4.1250 + lcdWriteCommand(0xC0); + lcdWriteData(0x11); + lcdWriteData(0x09); + + // Power Control 2: + // -> VGH = VCI x 6, VGL = VCI x 4 + lcdWriteCommand(0xC1); + lcdWriteData(0x41); + + // VCOM Control + lcdWriteCommand(0xC5); + lcdWriteData(0x00); // NV memory not programmed + lcdWriteData(0x0A); // VCM_REG + lcdWriteData(0x80); // VCM_REG_EN + + // Frame Rate Control + lcdWriteCommand(0xB1); + lcdWriteData(0xB0); + lcdWriteData(0x11); + + // Display Inversion Control + lcdWriteCommand(0xB4); + lcdWriteData(0x01); + + lcdWriteCommand(0xB5); + lcdWriteData(VFP); + lcdWriteData(VBP); + lcdWriteData(HFP); + lcdWriteData(HBP); + + // Display Function Control + lcdWriteCommand(0xB6); + // !DM | RM | RCM + lcdWriteData(0x20 | 0x40); + lcdWriteData(0x02); + lcdWriteData(0x3B); // (59 + 1) x 8 = 480 lines + + // Entry Set Mode + lcdWriteCommand(0xB7); + lcdWriteData(0xc6); + + lcdWriteCommand(0xBE); + lcdWriteData(0x00); + // lcdWriteData(0x04); // ???? + + lcdWriteCommand(0xE9); + lcdWriteData(0x00); + + // Column Address Set + // -> SC=0, EC=479 + lcdWriteCommand( 0x2A ); + lcdWriteData( 0x00 ); + lcdWriteData( 0x00 ); + lcdWriteData( 0x01 ); + lcdWriteData( 0xDF ); + + // Page Address Set + // -> SP=0, EP=319 + lcdWriteCommand( 0x2B ); + lcdWriteData( 0x00 ); + lcdWriteData( 0x00 ); + lcdWriteData( 0x01 ); + lcdWriteData( 0x3F ); + + // Memory Access Control + lcdWriteCommand(0x36); + lcdWriteData(0x28); // 0x20 -> swap col/rows + + lcdWriteCommand(0x3A); + lcdWriteData(0x66); + + lcdWriteCommand(0xE0); + lcdWriteData(0x00); + lcdWriteData(0x07); + lcdWriteData(0x10); + lcdWriteData(0x09); + lcdWriteData(0x17); + lcdWriteData(0x0B); + lcdWriteData(0x41); + lcdWriteData(0x89); + lcdWriteData(0x4B); + lcdWriteData(0x0A); + lcdWriteData(0x0C); + lcdWriteData(0x0E); + lcdWriteData(0x18); + lcdWriteData(0x1B); + lcdWriteData(0x0F); + + lcdWriteCommand(0xE1); + lcdWriteData(0x00); + lcdWriteData(0x17); + lcdWriteData(0x1A); + lcdWriteData(0x04); + lcdWriteData(0x0E); + lcdWriteData(0x06); + lcdWriteData(0x2F); + lcdWriteData(0x45); + lcdWriteData(0x43); + lcdWriteData(0x02); + lcdWriteData(0x0A); + lcdWriteData(0x09); + lcdWriteData(0x32); + lcdWriteData(0x36); + lcdWriteData(0x0F); + + // Sleep OUT + lcdWriteCommand(0x11); + delay_ms(120); + + // Display OFF + lcdWriteCommand(0x28); + + LCD_ILI9488_On(); +} + +void LCD_ILI9488_Off(void) { + lcdWriteCommand(0x28); +} + +void LCD_ILI9488_ReadDevice(void) { + int Index = 0; + int Parameter = 0x80; + + lcdWriteCommand(0xF7); + lcdWriteData(0xA9); + lcdWriteData(0x51); + lcdWriteData(0x2C); + lcdWriteData(0x82); + + lcdWriteCommand(0xB0); + lcdWriteData(0x80); + + lcdWriteCommand(0xFB); + lcdWriteData(Parameter | 0x00); + LCD_ReadBuffer[Index++] = LCD_ReadRegister(0xd3); + + //lcdWriteCommand(0X2E); + lcdWriteCommand(0xFB); + lcdWriteData(Parameter | 0x01); //Parameter2=0x88 + LCD_ReadBuffer[Index++] = LCD_ReadRegister(0xd3); + + lcdWriteCommand(0XFB); + lcdWriteData(Parameter | 0x02); //Parameter2=0x88 + LCD_ReadBuffer[Index++] = LCD_ReadRegister(0xd3); + + lcdWriteCommand(0XFB); + lcdWriteData(Parameter | 0x03); //Parameter2=0x88 + LCD_ReadBuffer[Index++] = LCD_ReadRegister(0xd3); +} + +unsigned int LCD_ILI9488_ReadID(void) { + int ID = 0; + + // Adjust Control 3: + // -> DSI write DCS command, use stream packet RGB 666 + lcdWriteCommand(0xF7); + lcdWriteData(0xA9); + lcdWriteData(0x51); + lcdWriteData(0x2C); + lcdWriteData(0x82); + + // Interface Mode Control: + // SDA_EN = 1, DIN/SDA pin is used for 3/4 wire serial + // interface and SDO pin is not used. + lcdWriteCommand(0xB0); + lcdWriteData(0x80); + + // first byte is dummy one + lcdWriteCommand(0xFB); + lcdWriteData(0x80 | 0x00); + ID = LCD_ReadRegister(0xd3); + + lcdWriteCommand(0xFB); + lcdWriteData(0x80 | 0x01); + ID = LCD_ReadRegister(0xd3); + + lcdWriteCommand(0xFB); + lcdWriteData(0x80 | 0x02); + ID = LCD_ReadRegister(0xd3); + ID <<= 8; + + lcdWriteCommand(0xFB); + lcdWriteData(0x80 | 0x03); + ID |= LCD_ReadRegister(0xd3); + + lcdWriteCommand(0xFB); + lcdWriteData(0x00); + + return (ID); +} + +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 ); + lcdWriteData( 0x66 ); + + //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( !TouchControllerType ) { + lcdWriteCommand( 0x21 ); + } + + LCD_ST7796S_On(); +} + +void LCD_ST7796S_Off(void) { + lcdWriteCommand(0x28); +} + +unsigned int LCD_ST7796S_ReadID(void) { + lcdReset(); + unsigned int ID = 0; + + lcdWriteCommand( 0XF0 ); + lcdWriteData( 0XC3 ); + lcdWriteCommand( 0XF0 ); + lcdWriteData( 0X96 ); + + lcdWriteCommand( 0XB0 ); + lcdWriteData( 0X80 ); + + lcdWriteCommand( 0XD3 ); + + LCD_MOSI_AS_INPUT(); + LCD_SCK_LOW(); + lcdDelay(); + lcdDelay(); + LCD_SCK_HIGH(); + lcdDelay(); + lcdDelay(); + + LCD_ReadByte(); + ID += (uint16_t)(LCD_ReadByte())<<8; + ID += LCD_ReadByte(); + + return (ID); + } + + +unsigned int LCD_NT35310_ReadID( void ) +{ + unsigned int ID = 0x3531; + + return( ID ); + +} + +void LCD_NT35310_Init( void ) +{ +#if 1 + lcdWriteCommand(0xED); + lcdWriteData(0x01); + lcdWriteData(0xFE); + + lcdWriteCommand(0xEE); + lcdWriteData(0xDE); + lcdWriteData(0x21); + + lcdWriteCommand(0x11); + delay_ms(120); + lcdWriteCommand(0xB3); + lcdWriteData(0x21); + + + + lcdWriteCommand(0xC0); + lcdWriteData(0x33); + lcdWriteData(0x33); + lcdWriteData(0x10); + lcdWriteData(0x10); + + + lcdWriteCommand(0xC4); + lcdWriteData(0x56); //3a + + lcdWriteCommand(0xBF); + lcdWriteData(0xAA); + + lcdWriteCommand(0xB0); + lcdWriteData(0x0D); + lcdWriteData(0x00); + lcdWriteData(0x0D); + lcdWriteData(0x00); + lcdWriteData(0x11); + lcdWriteData(0x00); + lcdWriteData(0x19); + lcdWriteData(0x00); + lcdWriteData(0x21); + lcdWriteData(0x00); + lcdWriteData(0x2D); + lcdWriteData(0x00); + lcdWriteData(0x3D); + lcdWriteData(0x00); + lcdWriteData(0x5D); + lcdWriteData(0x00); + lcdWriteData(0x5D); + lcdWriteData(0x00); + + lcdWriteCommand(0xB1); + lcdWriteData(0x80); + lcdWriteData(0x00); + lcdWriteData(0x8B); + lcdWriteData(0x00); + lcdWriteData(0x96); + lcdWriteData(0x00); + + lcdWriteCommand(0xB2); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x02); + lcdWriteData(0x00); + lcdWriteData(0x03); + lcdWriteData(0x00); + + lcdWriteCommand(0xB3); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xB4); + lcdWriteData(0x8B); + lcdWriteData(0x00); + lcdWriteData(0x96); + lcdWriteData(0x00); + lcdWriteData(0xA1); + lcdWriteData(0x00); + + lcdWriteCommand(0xB5); + lcdWriteData(0x02); + lcdWriteData(0x00); + lcdWriteData(0x03); + lcdWriteData(0x00); + lcdWriteData(0x04); + lcdWriteData(0x00); + lcdWriteCommand(0xB6); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xB7); + lcdWriteData(0x3E); + lcdWriteData(0x00); + lcdWriteData(0x5E); + lcdWriteData(0x00); + lcdWriteData(0x9E); + lcdWriteData(0x00); + lcdWriteData(0x74); + lcdWriteData(0x00); + lcdWriteData(0x8C); + lcdWriteData(0x00); + lcdWriteData(0xAC); + lcdWriteData(0x00); + lcdWriteData(0xDC); + lcdWriteData(0x00); + lcdWriteData(0x70); + lcdWriteData(0x00); + lcdWriteData(0xB9); + lcdWriteData(0x00); + lcdWriteData(0xEC); + lcdWriteData(0x00); + lcdWriteData(0xDC); + lcdWriteData(0x00); + + lcdWriteCommand(0xB8); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xBA); + lcdWriteData(0x24); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xC1); + lcdWriteData(0x20); + lcdWriteData(0x00); + lcdWriteData(0x54); + lcdWriteData(0x00); + lcdWriteData(0xFF); + lcdWriteData(0x00); + + lcdWriteCommand(0xC2); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x04); + lcdWriteData(0x00); + + lcdWriteCommand(0xC3); + lcdWriteData(0x3C); + lcdWriteData(0x00); + lcdWriteData(0x3A); + lcdWriteData(0x00); + lcdWriteData(0x39); + lcdWriteData(0x00); + lcdWriteData(0x37); + lcdWriteData(0x00); + lcdWriteData(0x3C); + lcdWriteData(0x00); + lcdWriteData(0x36); + lcdWriteData(0x00); + lcdWriteData(0x32); + lcdWriteData(0x00); + lcdWriteData(0x2F); + lcdWriteData(0x00); + lcdWriteData(0x2C); + lcdWriteData(0x00); + lcdWriteData(0x29); + lcdWriteData(0x00); + lcdWriteData(0x26); + lcdWriteData(0x00); + lcdWriteData(0x24); + lcdWriteData(0x00); + lcdWriteData(0x24); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + lcdWriteData(0x3C); + lcdWriteData(0x00); + lcdWriteData(0x36); + lcdWriteData(0x00); + lcdWriteData(0x32); + lcdWriteData(0x00); + lcdWriteData(0x2F); + lcdWriteData(0x00); + lcdWriteData(0x2C); + lcdWriteData(0x00); + lcdWriteData(0x29); + lcdWriteData(0x00); + lcdWriteData(0x26); + lcdWriteData(0x00); + lcdWriteData(0x24); + lcdWriteData(0x00); + lcdWriteData(0x24); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + + lcdWriteCommand(0xC4); + lcdWriteData(0x62); + lcdWriteData(0x00); + lcdWriteData(0x05); + lcdWriteData(0x00); + lcdWriteData(0x84); + lcdWriteData(0x00); + lcdWriteData(0xF0); + lcdWriteData(0x00); + lcdWriteData(0x18); + lcdWriteData(0x00); + lcdWriteData(0xA4); + lcdWriteData(0x00); + lcdWriteData(0x18); + lcdWriteData(0x00); + lcdWriteData(0x50); + lcdWriteData(0x00); + lcdWriteData(0x0C); + lcdWriteData(0x00); + lcdWriteData(0x17); + lcdWriteData(0x00); + lcdWriteData(0x95); + lcdWriteData(0x00); + lcdWriteData(0xF3); + lcdWriteData(0x00); + lcdWriteData(0xE6); + lcdWriteData(0x00); + + lcdWriteCommand(0xC5); + lcdWriteData(0x32); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x65); + lcdWriteData(0x00); + lcdWriteData(0x76); + lcdWriteData(0x00); + lcdWriteData(0x88); + lcdWriteData(0x00); + + lcdWriteCommand(0xC6); + lcdWriteData(0x20); + lcdWriteData(0x00); + lcdWriteData(0x17); + lcdWriteData(0x00); + lcdWriteData(0x01); + lcdWriteData(0x00); + + lcdWriteCommand(0xC7); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xC8); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xC9); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xE0); + lcdWriteData(0x02); + lcdWriteData(0x00); + lcdWriteData(0x06); + lcdWriteData(0x00); + lcdWriteData(0x10); + lcdWriteData(0x00); + lcdWriteData(0x25); + lcdWriteData(0x00); + lcdWriteData(0x36); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x57); + lcdWriteData(0x00); + lcdWriteData(0x6F); + lcdWriteData(0x00); + lcdWriteData(0x7F); + lcdWriteData(0x00); + lcdWriteData(0x8C); + lcdWriteData(0x00); + lcdWriteData(0x98); + lcdWriteData(0x00); + lcdWriteData(0xA6); + lcdWriteData(0x00); + lcdWriteData(0xAE); + lcdWriteData(0x00); + lcdWriteData(0xB4); + lcdWriteData(0x00); + lcdWriteData(0xBB); + lcdWriteData(0x00); + lcdWriteData(0xC0); + lcdWriteData(0x00); + lcdWriteData(0xC9); + lcdWriteData(0x00); + lcdWriteData(0xF3); + lcdWriteData(0x00); + + lcdWriteCommand(0xE1); + lcdWriteData(0x01); + lcdWriteData(0x00); + lcdWriteData(0x05); + lcdWriteData(0x00); + lcdWriteData(0x10); + lcdWriteData(0x00); + lcdWriteData(0x25); + lcdWriteData(0x00); + lcdWriteData(0x36); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x57); + lcdWriteData(0x00); + lcdWriteData(0x6F); + lcdWriteData(0x00); + lcdWriteData(0x7F); + lcdWriteData(0x00); + lcdWriteData(0x8C); + lcdWriteData(0x00); + lcdWriteData(0x98); + lcdWriteData(0x00); + lcdWriteData(0xA6); + lcdWriteData(0x00); + lcdWriteData(0xAE); + lcdWriteData(0x00); + lcdWriteData(0xB4); + lcdWriteData(0x00); + lcdWriteData(0xBB); + lcdWriteData(0x00); + lcdWriteData(0xC0); + lcdWriteData(0x00); + lcdWriteData(0xC9); + lcdWriteData(0x00); + lcdWriteData(0xF3); + lcdWriteData(0x00); + + lcdWriteCommand(0xE2); + lcdWriteData(0x02); + lcdWriteData(0x00); + lcdWriteData(0x06); + lcdWriteData(0x00); + lcdWriteData(0x10); + lcdWriteData(0x00); + lcdWriteData(0x25); + lcdWriteData(0x00); + lcdWriteData(0x36); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x57); + lcdWriteData(0x00); + lcdWriteData(0x6F); + lcdWriteData(0x00); + lcdWriteData(0x7F); + lcdWriteData(0x00); + lcdWriteData(0x8C); + lcdWriteData(0x00); + lcdWriteData(0x98); + lcdWriteData(0x00); + lcdWriteData(0xA6); + lcdWriteData(0x00); + lcdWriteData(0xAE); + lcdWriteData(0x00); + lcdWriteData(0xB4); + lcdWriteData(0x00); + lcdWriteData(0xBB); + lcdWriteData(0x00); + lcdWriteData(0xC0); + lcdWriteData(0x00); + lcdWriteData(0xC9); + lcdWriteData(0x00); + lcdWriteData(0xF3); + lcdWriteData(0x00); + + lcdWriteCommand(0xE3); + lcdWriteData(0x01); + lcdWriteData(0x00); + lcdWriteData(0x05); + lcdWriteData(0x00); + lcdWriteData(0x10); + lcdWriteData(0x00); + lcdWriteData(0x25); + lcdWriteData(0x00); + lcdWriteData(0x36); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x57); + lcdWriteData(0x00); + lcdWriteData(0x6F); + lcdWriteData(0x00); + lcdWriteData(0x7F); + lcdWriteData(0x00); + lcdWriteData(0x8C); + lcdWriteData(0x00); + lcdWriteData(0x98); + lcdWriteData(0x00); + lcdWriteData(0xA6); + lcdWriteData(0x00); + lcdWriteData(0xAE); + lcdWriteData(0x00); + lcdWriteData(0xB4); + lcdWriteData(0x00); + lcdWriteData(0xBB); + lcdWriteData(0x00); + lcdWriteData(0xC0); + lcdWriteData(0x00); + lcdWriteData(0xC9); + lcdWriteData(0x00); + lcdWriteData(0xF3); + lcdWriteData(0x00); + + lcdWriteCommand(0xE4); + lcdWriteData(0x02); + lcdWriteData(0x00); + lcdWriteData(0x06); + lcdWriteData(0x00); + lcdWriteData(0x10); + lcdWriteData(0x00); + lcdWriteData(0x25); + lcdWriteData(0x00); + lcdWriteData(0x36); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x57); + lcdWriteData(0x00); + lcdWriteData(0x6F); + lcdWriteData(0x00); + lcdWriteData(0x7F); + lcdWriteData(0x00); + lcdWriteData(0x8C); + lcdWriteData(0x00); + lcdWriteData(0x98); + lcdWriteData(0x00); + lcdWriteData(0xA6); + lcdWriteData(0x00); + lcdWriteData(0xAE); + lcdWriteData(0x00); + lcdWriteData(0xB4); + lcdWriteData(0x00); + lcdWriteData(0xBB); + lcdWriteData(0x00); + lcdWriteData(0xC0); + lcdWriteData(0x00); + lcdWriteData(0xC9); + lcdWriteData(0x00); + lcdWriteData(0xF3); + lcdWriteData(0x00); + + lcdWriteCommand(0xE5); + lcdWriteData(0x01); + lcdWriteData(0x00); + lcdWriteData(0x05); + lcdWriteData(0x00); + lcdWriteData(0x10); + lcdWriteData(0x00); + lcdWriteData(0x25); + lcdWriteData(0x00); + lcdWriteData(0x36); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x57); + lcdWriteData(0x00); + lcdWriteData(0x6F); + lcdWriteData(0x00); + lcdWriteData(0x7F); + lcdWriteData(0x00); + lcdWriteData(0x8C); + lcdWriteData(0x00); + lcdWriteData(0x98); + lcdWriteData(0x00); + lcdWriteData(0xA6); + lcdWriteData(0x00); + lcdWriteData(0xAE); + lcdWriteData(0x00); + lcdWriteData(0xB4); + lcdWriteData(0x00); + lcdWriteData(0xBB); + lcdWriteData(0x00); + lcdWriteData(0xC0); + lcdWriteData(0x00); + lcdWriteData(0xC9); + lcdWriteData(0x00); + lcdWriteData(0xF3); + lcdWriteData(0x00); + + lcdWriteCommand(0xE6); + lcdWriteData(0x55); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x56); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x57); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x77); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + lcdWriteData(0x65); + lcdWriteData(0x00); + + lcdWriteCommand(0xE7); + lcdWriteData(0x55); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x56); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x57); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x77); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + lcdWriteData(0x65); + lcdWriteData(0x00); + + lcdWriteCommand(0xE8); + lcdWriteData(0x55); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x56); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x57); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x77); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + lcdWriteData(0x65); + lcdWriteData(0x00); + + lcdWriteCommand(0xE9); + lcdWriteData(0xAA); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0x00); + lcdWriteData(0xAA); + + lcdWriteCommand(0xCF); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xF0); + lcdWriteData(0x00); + lcdWriteData(0x50); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xF1); + lcdWriteData(0x01); + + lcdWriteCommand(0xF9); + lcdWriteData(0x06); + lcdWriteData(0x10); + lcdWriteData(0x29); + lcdWriteData(0x00); + + lcdWriteCommand(0xDF); + lcdWriteData(0x10); + delay_ms(20); + lcdWriteCommand(0x36); +// if( IsHorizontal ) +// lcdWriteData(0x00);//需修改 +// else + lcdWriteData(0x14); + + lcdWriteCommand(0x3A); + lcdWriteData(0x66); + + lcdWriteCommand(0x21); + + lcdWriteCommand(0x35); + lcdWriteData(0x00); + + lcdWriteCommand(0x29); +#else + lcdWriteCommand(0xED); + lcdWriteData(0x01); + lcdWriteData(0xFE); + + lcdWriteCommand(0xEE); + lcdWriteData(0xDE); + lcdWriteData(0x21); + + lcdWriteCommand(0x11); + SYSTEM_DelayMS(120); + lcdWriteCommand(0xB3); + lcdWriteData(0x21); + + + lcdWriteCommand(0xc0); + lcdWriteData(0x56); + lcdWriteData(0x56); + lcdWriteData(0x24); + lcdWriteData(0x24); + + lcdWriteCommand(0xC4); + lcdWriteData(0x30); //3a + + lcdWriteCommand(0xBF); + lcdWriteData(0xAA); + + lcdWriteCommand(0xB0); + lcdWriteData(0x0D); + lcdWriteData(0x00); + lcdWriteData(0x0D); + lcdWriteData(0x00); + lcdWriteData(0x11); + lcdWriteData(0x00); + lcdWriteData(0x19); + lcdWriteData(0x00); + lcdWriteData(0x21); + lcdWriteData(0x00); + lcdWriteData(0x2D); + lcdWriteData(0x00); + lcdWriteData(0x3D); + lcdWriteData(0x00); + lcdWriteData(0x5D); + lcdWriteData(0x00); + lcdWriteData(0x5D); + lcdWriteData(0x00); + + lcdWriteCommand(0xB1); + lcdWriteData(0x80); + lcdWriteData(0x00); + lcdWriteData(0x8B); + lcdWriteData(0x00); + lcdWriteData(0x96); + lcdWriteData(0x00); + + lcdWriteCommand(0xB2); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x02); + lcdWriteData(0x00); + lcdWriteData(0x03); + lcdWriteData(0x00); + + lcdWriteCommand(0xB3); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xB4); + lcdWriteData(0x8B); + lcdWriteData(0x00); + lcdWriteData(0x96); + lcdWriteData(0x00); + lcdWriteData(0xA1); + lcdWriteData(0x00); + + lcdWriteCommand(0xB5); + lcdWriteData(0x02); + lcdWriteData(0x00); + lcdWriteData(0x03); + lcdWriteData(0x00); + lcdWriteData(0x04); + lcdWriteData(0x00); + lcdWriteCommand(0xB6); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xB7); + lcdWriteData(0x3E); + lcdWriteData(0x00); + lcdWriteData(0x5E); + lcdWriteData(0x00); + lcdWriteData(0x9E); + lcdWriteData(0x00); + lcdWriteData(0x74); + lcdWriteData(0x00); + lcdWriteData(0x8C); + lcdWriteData(0x00); + lcdWriteData(0xAC); + lcdWriteData(0x00); + lcdWriteData(0xDC); + lcdWriteData(0x00); + lcdWriteData(0x70); + lcdWriteData(0x00); + lcdWriteData(0xB9); + lcdWriteData(0x00); + lcdWriteData(0xEC); + lcdWriteData(0x00); + lcdWriteData(0xDC); + lcdWriteData(0x00); + + lcdWriteCommand(0xB8); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xBA); + lcdWriteData(0x24); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xC1); + lcdWriteData(0x20); + lcdWriteData(0x00); + lcdWriteData(0x54); + lcdWriteData(0x00); + lcdWriteData(0xFF); + lcdWriteData(0x00); + + lcdWriteCommand(0xC2); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x04); + lcdWriteData(0x00); + + lcdWriteCommand(0xC3); + lcdWriteData(0x3C); + lcdWriteData(0x00); + lcdWriteData(0x3A); + lcdWriteData(0x00); + lcdWriteData(0x39); + lcdWriteData(0x00); + lcdWriteData(0x37); + lcdWriteData(0x00); + lcdWriteData(0x3C); + lcdWriteData(0x00); + lcdWriteData(0x36); + lcdWriteData(0x00); + lcdWriteData(0x32); + lcdWriteData(0x00); + lcdWriteData(0x2F); + lcdWriteData(0x00); + lcdWriteData(0x2C); + lcdWriteData(0x00); + lcdWriteData(0x29); + lcdWriteData(0x00); + lcdWriteData(0x26); + lcdWriteData(0x00); + lcdWriteData(0x24); + lcdWriteData(0x00); + lcdWriteData(0x24); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + lcdWriteData(0x3C); + lcdWriteData(0x00); + lcdWriteData(0x36); + lcdWriteData(0x00); + lcdWriteData(0x32); + lcdWriteData(0x00); + lcdWriteData(0x2F); + lcdWriteData(0x00); + lcdWriteData(0x2C); + lcdWriteData(0x00); + lcdWriteData(0x29); + lcdWriteData(0x00); + lcdWriteData(0x26); + lcdWriteData(0x00); + lcdWriteData(0x24); + lcdWriteData(0x00); + lcdWriteData(0x24); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + + lcdWriteCommand(0xC4); + lcdWriteData(0x62); + lcdWriteData(0x00); + lcdWriteData(0x05); + lcdWriteData(0x00); + lcdWriteData(0x84); + lcdWriteData(0x00); + lcdWriteData(0xF0); + lcdWriteData(0x00); + lcdWriteData(0x18); + lcdWriteData(0x00); + lcdWriteData(0xA4); + lcdWriteData(0x00); + lcdWriteData(0x18); + lcdWriteData(0x00); + lcdWriteData(0x50); + lcdWriteData(0x00); + lcdWriteData(0x0C); + lcdWriteData(0x00); + lcdWriteData(0x17); + lcdWriteData(0x00); + lcdWriteData(0x95); + lcdWriteData(0x00); + lcdWriteData(0xF3); + lcdWriteData(0x00); + lcdWriteData(0xE6); + lcdWriteData(0x00); + + lcdWriteCommand(0xC5); + lcdWriteData(0x32); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x65); + lcdWriteData(0x00); + lcdWriteData(0x76); + lcdWriteData(0x00); + lcdWriteData(0x88); + lcdWriteData(0x00); + + lcdWriteCommand(0xC6); + lcdWriteData(0x20); + lcdWriteData(0x00); + lcdWriteData(0x17); + lcdWriteData(0x00); + lcdWriteData(0x01); + lcdWriteData(0x00); + + lcdWriteCommand(0xC7); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xC8); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xC9); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xE0); + lcdWriteData(0x01); + lcdWriteData(0x00); + lcdWriteData(0x1F); + lcdWriteData(0x00); + lcdWriteData(0x3C); + lcdWriteData(0x00); + lcdWriteData(0x59); + lcdWriteData(0x00); + lcdWriteData(0x67); + lcdWriteData(0x00); + lcdWriteData(0x72); + lcdWriteData(0x00); + lcdWriteData(0x82); + lcdWriteData(0x00); + lcdWriteData(0x93); + lcdWriteData(0x00); + lcdWriteData(0xA0); + lcdWriteData(0x00); + lcdWriteData(0xAB); + lcdWriteData(0x00); + lcdWriteData(0xB4); + lcdWriteData(0x00); + lcdWriteData(0xBF); + lcdWriteData(0x00); + lcdWriteData(0xC6); + lcdWriteData(0x00); + lcdWriteData(0xCA); + lcdWriteData(0x00); + lcdWriteData(0xCF); + lcdWriteData(0x00); + lcdWriteData(0xD3); + lcdWriteData(0x00); + lcdWriteData(0xDA); + lcdWriteData(0x00); + lcdWriteData(0xF3); + lcdWriteData(0x00); + + lcdWriteCommand(0xE1); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x1F); + lcdWriteData(0x00); + lcdWriteData(0x3C); + lcdWriteData(0x00); + lcdWriteData(0x59); + lcdWriteData(0x00); + lcdWriteData(0x67); + lcdWriteData(0x00); + lcdWriteData(0x72); + lcdWriteData(0x00); + lcdWriteData(0x82); + lcdWriteData(0x00); + lcdWriteData(0x93); + lcdWriteData(0x00); + lcdWriteData(0xA0); + lcdWriteData(0x00); + lcdWriteData(0xAB); + lcdWriteData(0x00); + lcdWriteData(0xB4); + lcdWriteData(0x00); + lcdWriteData(0xBF); + lcdWriteData(0x00); + lcdWriteData(0xC6); + lcdWriteData(0x00); + lcdWriteData(0xCA); + lcdWriteData(0x00); + lcdWriteData(0xD0); + lcdWriteData(0x00); + lcdWriteData(0xD4); + lcdWriteData(0x00); + lcdWriteData(0xD9); + lcdWriteData(0x00); + lcdWriteData(0xF3); + lcdWriteData(0x00); + + lcdWriteCommand(0xE2); + lcdWriteData(0x10); + lcdWriteData(0x00); + lcdWriteData(0x1F); + lcdWriteData(0x00); + lcdWriteData(0x3C); + lcdWriteData(0x00); + lcdWriteData(0x59); + lcdWriteData(0x00); + lcdWriteData(0x67); + lcdWriteData(0x00); + lcdWriteData(0x72); + lcdWriteData(0x00); + lcdWriteData(0x82); + lcdWriteData(0x00); + lcdWriteData(0x93); + lcdWriteData(0x00); + lcdWriteData(0xA0); + lcdWriteData(0x00); + lcdWriteData(0xAB); + lcdWriteData(0x00); + lcdWriteData(0xB4); + lcdWriteData(0x00); + lcdWriteData(0xBF); + lcdWriteData(0x00); + lcdWriteData(0xC6); + lcdWriteData(0x00); + lcdWriteData(0xCA); + lcdWriteData(0x00); + lcdWriteData(0xCF); + lcdWriteData(0x00); + lcdWriteData(0xD3); + lcdWriteData(0x00); + lcdWriteData(0xDA); + lcdWriteData(0x00); + lcdWriteData(0xF3); + lcdWriteData(0x00); + + lcdWriteCommand(0xE3); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x1F); + lcdWriteData(0x00); + lcdWriteData(0x3C); + lcdWriteData(0x00); + lcdWriteData(0x59); + lcdWriteData(0x00); + lcdWriteData(0x67); + lcdWriteData(0x00); + lcdWriteData(0x72); + lcdWriteData(0x00); + lcdWriteData(0x82); + lcdWriteData(0x00); + lcdWriteData(0x93); + lcdWriteData(0x00); + lcdWriteData(0xA0); + lcdWriteData(0x00); + lcdWriteData(0xAB); + lcdWriteData(0x00); + lcdWriteData(0xB4); + lcdWriteData(0x00); + lcdWriteData(0xBF); + lcdWriteData(0x00); + lcdWriteData(0xC6); + lcdWriteData(0x00); + lcdWriteData(0xCA); + lcdWriteData(0x00); + lcdWriteData(0xD0); + lcdWriteData(0x00); + lcdWriteData(0xD4); + lcdWriteData(0x00); + lcdWriteData(0xD9); + lcdWriteData(0x00); + lcdWriteData(0xF3); + lcdWriteData(0x00); + + lcdWriteCommand(0xE4); + lcdWriteData(0x01); + lcdWriteData(0x00); + lcdWriteData(0x1F); + lcdWriteData(0x00); + lcdWriteData(0x3C); + lcdWriteData(0x00); + lcdWriteData(0x59); + lcdWriteData(0x00); + lcdWriteData(0x67); + lcdWriteData(0x00); + lcdWriteData(0x72); + lcdWriteData(0x00); + lcdWriteData(0x82); + lcdWriteData(0x00); + lcdWriteData(0x93); + lcdWriteData(0x00); + lcdWriteData(0xA0); + lcdWriteData(0x00); + lcdWriteData(0xAB); + lcdWriteData(0x00); + lcdWriteData(0xB4); + lcdWriteData(0x00); + lcdWriteData(0xBF); + lcdWriteData(0x00); + lcdWriteData(0xC6); + lcdWriteData(0x00); + lcdWriteData(0xCA); + lcdWriteData(0x00); + lcdWriteData(0xCF); + lcdWriteData(0x00); + lcdWriteData(0xD3); + lcdWriteData(0x00); + lcdWriteData(0xDA); + lcdWriteData(0x00); + lcdWriteData(0xF3); + lcdWriteData(0x00); + + lcdWriteCommand(0xE5); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x1F); + lcdWriteData(0x00); + lcdWriteData(0x3C); + lcdWriteData(0x00); + lcdWriteData(0x59); + lcdWriteData(0x00); + lcdWriteData(0x67); + lcdWriteData(0x00); + lcdWriteData(0x72); + lcdWriteData(0x00); + lcdWriteData(0x82); + lcdWriteData(0x00); + lcdWriteData(0x93); + lcdWriteData(0x00); + lcdWriteData(0xA0); + lcdWriteData(0x00); + lcdWriteData(0xAB); + lcdWriteData(0x00); + lcdWriteData(0xB4); + lcdWriteData(0x00); + lcdWriteData(0xBF); + lcdWriteData(0x00); + lcdWriteData(0xC6); + lcdWriteData(0x00); + lcdWriteData(0xCA); + lcdWriteData(0x00); + lcdWriteData(0xD0); + lcdWriteData(0x00); + lcdWriteData(0xD4); + lcdWriteData(0x00); + lcdWriteData(0xD9); + lcdWriteData(0x00); + lcdWriteData(0xF3); + lcdWriteData(0x00); + + lcdWriteCommand(0xE6); + lcdWriteData(0x55); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x56); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x57); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x77); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + lcdWriteData(0x65); + lcdWriteData(0x00); + + lcdWriteCommand(0xE7); + lcdWriteData(0x55); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x56); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x57); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x77); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + lcdWriteData(0x65); + lcdWriteData(0x00); + + lcdWriteCommand(0xE8); + lcdWriteData(0x55); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x56); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x57); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x77); + lcdWriteData(0x00); + lcdWriteData(0x66); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x44); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + lcdWriteData(0x23); + lcdWriteData(0x00); + lcdWriteData(0x65); + lcdWriteData(0x00); + + lcdWriteCommand(0xE9); + lcdWriteData(0xAA); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0x00); + lcdWriteData(0xAA); + + lcdWriteCommand(0xCF); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xF0); + lcdWriteData(0x00); + lcdWriteData(0x50); + lcdWriteData(0x00); + lcdWriteData(0x00); + lcdWriteData(0x00); + + lcdWriteCommand(0xF1); + lcdWriteData(0x01); + + lcdWriteCommand(0xee); + lcdWriteData(0xde); + lcdWriteData(0x21); + + lcdWriteCommand(0xF3); + lcdWriteData(0x00); + + lcdWriteCommand(0xF9); + lcdWriteData(0x06); + lcdWriteData(0x10); + lcdWriteData(0x29); + lcdWriteData(0x00); + + lcdWriteCommand(0xDF); + lcdWriteData(0x10); + SYSTEM_DelayMS(20); + lcdWriteCommand(0x36); + if( IsHorizontal ) + lcdWriteData(0x14);//需修改 + else + lcdWriteData(0x14); + + lcdWriteCommand(0x3A); + lcdWriteData(0x66); + + lcdWriteCommand(0x21); + + lcdWriteCommand(0x35); + lcdWriteData(0x00); + + lcdWriteCommand(0x28); +#endif +} + +void LCD_NT35310_On( void ) +{ + lcdWriteCommand( 0x29 ); +} + +void LCD_NT35310_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_phys_w + HBP; + /* Configure accumulated active height */ + hltdc.Init.AccumulatedActiveH = lcd_phys_h + VBP; + /* Configure total width */ + hltdc.Init.TotalWidth = lcd_phys_w + HBP + HFP; + /* Configure total height */ + hltdc.Init.TotalHeigh = lcd_phys_h + 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_phys_h); + __HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI); +} + +void LCD_LayerInit() { + auto& layer = hltdc.LayerCfg[0]; + + /* Windowing configuration */ + layer.WindowX0 = 0; + layer.WindowX1 = lcd_phys_w; + layer.WindowY0 = 0; + layer.WindowY1 = lcd_phys_h; + + /* 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_phys_w; + layer.ImageHeight = lcd_phys_h; + + /* 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; +} + +const char* boardLcdType = ""; + +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 */ + if (LCD_ILI9481_ReadID() == LCD_ILI9481_ID) { + TRACE("LCD INIT: ILI9481"); + boardLcdType = "ILI9481"; + lcdInitFunction = LCD_ILI9481_Init; + lcdOffFunction = LCD_ILI9481_Off; + lcdOnFunction = LCD_ILI9481_On; + lcdPixelClock = 12000000; + } else if (LCD_ILI9486_ReadID() == LCD_ILI9486_ID) { + TRACE("LCD INIT: ILI9486"); + boardLcdType = "ILI9486"; + lcdInitFunction = LCD_ILI9486_Init; + lcdOffFunction = LCD_ILI9486_Off; + lcdOnFunction = LCD_ILI9486_On; + lcdPixelClock = 12000000; + } else if (LCD_ILI9488_ReadID() == LCD_ILI9488_ID) { + TRACE("LCD INIT: ILI9488"); + boardLcdType = "ILI9488"; + lcdInitFunction = LCD_ILI9488_Init; + lcdOffFunction = LCD_ILI9488_Off; + lcdOnFunction = LCD_ILI9488_On; + lcdPixelClock = 12000000; + lcd_phys_w = LCD_PHYS_H; + lcd_phys_h = LCD_PHYS_W; + } else if (LCD_HX8357D_ReadID() == LCD_HX8357D_ID) { + TRACE("LCD INIT: HX8357D"); + boardLcdType = "HX8357D"; + lcdInitFunction = LCD_HX8357D_Init; + lcdOffFunction = LCD_HX8357D_Off; + lcdOnFunction = LCD_HX8357D_On; + lcdPixelClock = 12000000; + } else if (LCD_ST7796S_ReadID() == LCD_ST7796S_ID ) { + TRACE("LCD INIT: ST7796S"); + boardLcdType = "ST7796S"; + lcdInitFunction = LCD_ST7796S_Init; + lcdOffFunction = LCD_ST7796S_Off; + lcdOnFunction = LCD_ST7796S_On; + lcdPixelClock = 14500000; + } + else{ + TRACE("LCD INIT (default): ST7796S"); + boardLcdType = "ST7796S (Default)"; + lcdInitFunction = LCD_ST7796S_Init; + lcdOffFunction = LCD_ST7796S_Off; + lcdOnFunction = LCD_ST7796S_On; + lcdPixelClock = 12000000; + } + + lcdInitFunction(); + + 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/pl18/lcd_driver.h b/radio/src/targets/pl18/lcd_driver.h new file mode 100644 index 00000000000..d1c4c756c64 --- /dev/null +++ b/radio/src/targets/pl18/lcd_driver.h @@ -0,0 +1,92 @@ +/* + * 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. + */ + +#ifndef __LCD_DRIVER_H__ +#define __LCD_DRIVER_H__ + +#define HBP ( 24 ) // TODO use names from FlySky +#define VBP ( 10 ) + +#define HSW ( 4 ) +#define VSH ( 2 ) + +#define HFP ( 140 - HBP ) +#define VFP ( 22 - VBP ) + +#define LCD_ST7796S_ID ( 0x7796 ) +#define LCD_ILI9481_ID ( 0x9481 ) +#define LCD_ILI9486_ID ( 0x9486 ) +#define LCD_ILI9488_ID ( 0x9488 ) +#define LCD_HX8357D_ID ( 0x99 ) + +#define LCD_DELAY() LCD_Delay() + +typedef void (*lcdSpiInitFucPtr)(void); +typedef unsigned int LcdReadIDFucPtr( void ); + +extern lcdSpiInitFucPtr lcdInitFunction; +extern lcdSpiInitFucPtr lcdOffFunction; +extern lcdSpiInitFucPtr lcdOnFunction; + +#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) + + +#if 1 +#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 ) +#else +#define HORIZONTAL_SYNC_WIDTH ( 4 ) +#define HORIZONTAL_BACK_PORCH ( 20 ) +#define HORIZONTAL_FRONT_PORCH ( 60 - HORIZONTAL_BACK_PORCH ) +#define VERTICAL_SYNC_HEIGHT ( 2 ) +#define VERTICAL_BACK_PORCH ( 6 ) +#define VERTICAL_FRONT_PORCH ( 14 - VERTICAL_BACK_PORCH ) +#endif + + + +#endif + + + + diff --git a/radio/src/targets/pl18/led_driver.cpp b/radio/src/targets/pl18/led_driver.cpp new file mode 100644 index 00000000000..8b909202fd0 --- /dev/null +++ b/radio/src/targets/pl18/led_driver.cpp @@ -0,0 +1,60 @@ +/* + * 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 "board.h" +#include "boards/generic_stm32/rgb_leds.h" + +void ledInit() +{ + // Do nothing +} + +void ledOff() +{ + for (uint8_t i = 0; i < LED_STRIP_LENGTH; i++) { + rgbSetLedColor(i, 0, 0, 0); + } + rgbLedColorApply(); +} + +void ledRed() +{ + for (uint8_t i = 0; i < LED_STRIP_LENGTH; i++) { + rgbSetLedColor(i, 50, 0, 0); + } + rgbLedColorApply(); +} + +void ledGreen() +{ + for (uint8_t i = 0; i < LED_STRIP_LENGTH; i++) { + rgbSetLedColor(i, 0, 50, 0); + } + rgbLedColorApply(); +} + +void ledBlue() +{ + for (uint8_t i = 0; i < LED_STRIP_LENGTH; i++) { + rgbSetLedColor(i, 0, 0, 50); + } + rgbLedColorApply(); +} diff --git a/radio/src/targets/pl18/libopenui_config.h b/radio/src/targets/pl18/libopenui_config.h new file mode 100644 index 00000000000..5a5abf70a3f --- /dev/null +++ b/radio/src/targets/pl18/libopenui_config.h @@ -0,0 +1,29 @@ +/* + * 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 + +constexpr coord_t INPUT_EDIT_CURVE_WIDTH = 132; +constexpr coord_t INPUT_EDIT_CURVE_HEIGHT = INPUT_EDIT_CURVE_WIDTH; +constexpr coord_t MENUS_MAX_HEIGHT = (MENUS_LINE_HEIGHT * 8) + 8; + +// Disable rotary encoder, as the PL18 does not have one +#define ROTARY_ENCODER_SPEED() 0 diff --git a/radio/src/targets/pl18/sdram_driver.c b/radio/src/targets/pl18/sdram_driver.c new file mode 100644 index 00000000000..2cc88ae84a5 --- /dev/null +++ b/radio/src/targets/pl18/sdram_driver.c @@ -0,0 +1,257 @@ +/* + * 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. + */ + +#include "board.h" +#include "stm32f4xx_fmc.h" + +#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000) +#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001) +#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002) +#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004) +#define SDRAM_MODEREG_BURST_FULL_PAGE ((uint16_t)0x0007) +#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) +#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) +#define SDRAM_MODEREG_CAS_LATENCY_1 ((uint16_t)0x0010) +#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020) +#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030) +#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000) +#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) +#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) + +void SDRAM_GPIOConfig(void) +{ + /* + ------------------------------------------------------------------------------------------------------------------------------------------------ + PC3 <-> FMC_SDCKE0 | PD0 <-> FMC_D2 | PE0 <-> FMC_NBL0 | PF0 <-> FMC_A0 | PG0 <-> FMC_A10 | PH3 <-> FMC_SDNE0 | PI0 <-> FMC_D24 + | PD1 <-> FMC_D3 | PE1 <-> FMC_NBL1 | PF1 <-> FMC_A1 | PG1 <-> FMC_A11 | PH5 <-> FMC_SDNWE | PI1 <-> FMC_D25 + | PD8 <-> FMC_D13 | PE7 <-> FMC_D4 | PF2 <-> FMC_A2 | PG4 <-> FMC_BA0 | PH8 <-> FMC_D16 | PI2 <-> FMC_D26 + | PD9 <-> FMC_D14 | PE8 <-> FMC_D5 | PF3 <-> FMC_A3 | PG5 <-> FMC_BA1 | PH9 <-> FMC_D17 | PI3 <-> FMC_D27 + | PD10 <-> FMC_D15 | PE9 <-> FMC_D6 | PF4 <-> FMC_A4 | PG8 <-> FMC_SDCLK | PH10 <-> FMC_D18 | PI4 <-> FMC_NBL2 + | PD14 <-> FMC_D0 | PE10 <-> FMC_D7 | PF5 <-> FMC_A5 | PG15 <-> FMC_NCAS | PH11 <-> FMC_D19 | PI5 <-> FMC_NBL3 + | PD15 <-> FMC_D1 | PE11 <-> FMC_D8 | PF11 <-> FMC_NRAS | | PH12 <-> FMC_D20 | PI6 <-> FMC_D28 + | | PE12 <-> FMC_D9 | PF12 <-> FMC_A6 | | PH13 <-> FMC_D21 | PI7 <-> FMC_D29 + | | PE13 <-> FMC_D10 | PF13 <-> FMC_A7 | | PH14 <-> FMC_D22 | PI9 <-> FMC_D30 + | | PE14 <-> FMC_D11 | PF14 <-> FMC_A8 | | PH15 <-> FMC_D23 | PI10 <-> FMC_D31 + | | PE15 <-> FMC_D12 | PF15 <-> FMC_A9 | | | + */ + + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + + /* GPIOC configuration */ + GPIO_PinAFConfig(GPIOC, GPIO_PinSource3 , GPIO_AF_FMC); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ; + GPIO_Init(GPIOC, &GPIO_InitStructure); + + /* GPIOD configuration */ + GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FMC); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15; + GPIO_Init(GPIOD, &GPIO_InitStructure); + + /* GPIOE configuration */ + GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_FMC); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; + GPIO_Init(GPIOE, &GPIO_InitStructure); + + /* GPIOF configuration */ + GPIO_PinAFConfig(GPIOF, GPIO_PinSource0, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOF, GPIO_PinSource1, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOF, GPIO_PinSource2, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOF, GPIO_PinSource3, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOF, GPIO_PinSource4, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOF, GPIO_PinSource5, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOF, GPIO_PinSource11, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOF, GPIO_PinSource12, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOF, GPIO_PinSource13, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOF, GPIO_PinSource14, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOF, GPIO_PinSource15, GPIO_AF_FMC); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; + GPIO_Init(GPIOF, &GPIO_InitStructure); + + /* GPIOG configuration */ + GPIO_PinAFConfig(GPIOG, GPIO_PinSource0 , GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOG, GPIO_PinSource1 , GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOG, GPIO_PinSource4 , GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOG, GPIO_PinSource5 , GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOG, GPIO_PinSource8 , GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOG, GPIO_PinSource15 , GPIO_AF_FMC); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_15; + GPIO_Init(GPIOG, &GPIO_InitStructure); + + /* GPIOH configuration */ + GPIO_PinAFConfig(GPIOH, GPIO_PinSource3, GPIO_AF_FMC); + GPIO_PinAFConfig(GPIOH, GPIO_PinSource5, GPIO_AF_FMC); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5; + GPIO_Init(GPIOH, &GPIO_InitStructure); +} + +void SDRAM_InitSequence(void) +{ + FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStructure; + uint32_t tmpr = 0; + + /* Step 3 --------------------------------------------------------------------*/ + /* Configure a clock configuration enable command */ + FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled; + FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1; + FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1; + FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0; + /* Wait until the SDRAM controller is ready */ + while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) { + } + /* Send the command */ + FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure); + + /* Step 4 --------------------------------------------------------------------*/ + /* Insert 100 ms delay */ + delay_ms(100); + + /* Step 5 --------------------------------------------------------------------*/ + /* Configure a PALL (precharge all) command */ + FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_PALL; + FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1; + FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1; + FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0; + /* Wait until the SDRAM controller is ready */ + while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) { + } + /* Send the command */ + FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure); + + /* Step 6 --------------------------------------------------------------------*/ + /* Configure a Auto-Refresh command */ + FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_AutoRefresh; + FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1; + FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 4; + FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0; + /* Wait until the SDRAM controller is ready */ + while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) { + } + /* Send the first command */ + FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure); + + /* Wait until the SDRAM controller is ready */ + while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) { + } + /* Send the second command */ + FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure); + + /* Step 7 --------------------------------------------------------------------*/ + /* Program the external memory mode register */ + tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2 | + SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | + SDRAM_MODEREG_CAS_LATENCY_3 | + SDRAM_MODEREG_OPERATING_MODE_STANDARD | + SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; + + /* Configure a load Mode register command*/ + FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_LoadMode; + FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1; + FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1; + FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = tmpr; + /* Wait until the SDRAM controller is ready */ + while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) { + } + /* Send the command */ + FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure); + + /* Step 8 --------------------------------------------------------------------*/ + /* Set the refresh rate counter */ + /* (15.62 us x Freq) - 20 */ + /* Set the device refresh counter */ + FMC_SetRefreshCount(683);//904 + /* Wait until the SDRAM controller is ready */ + while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) { + } +} + + +void SDRAM_Init(void) +{ + //delay funcion needed + delaysInit(); + // Clocks must be enabled here, because the sdramInit is called before main + RCC_AHB1PeriphClockCmd(SDRAM_RCC_AHB1Periph, ENABLE); + RCC_AHB3PeriphClockCmd(SDRAM_RCC_AHB3Periph, ENABLE); + + /* GPIO configuration for FMC SDRAM bank */ + SDRAM_GPIOConfig(); + + /* FMC Configuration ---------------------------------------------------------*/ + FMC_SDRAMInitTypeDef FMC_SDRAMInitStructure; + FMC_SDRAMTimingInitTypeDef FMC_SDRAMTimingInitStructure; + + /* FMC SDRAM Bank configuration */ + /* Timing configuration for 90 Mhz of SD clock frequency (168Mhz/2) */ + /* TMRD: 2 Clock cycles */ + FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay = 2; + /* TXSR: min=70ns (7x11.11ns) */ + FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 7; + /* TRAS: min=42ns (4x11.11ns) max=120k (ns) */ + FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime = 4; + /* TRC: min=70 (7x11.11ns) */ + FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay = 7; + /* TWR: min=1+ 7ns (1+1x11.11ns) */ + FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime = 2; + /* TRP: 20ns => 2x11.11ns */ + FMC_SDRAMTimingInitStructure.FMC_RPDelay = 2; + /* TRCD: 20ns => 2x11.11ns */ + FMC_SDRAMTimingInitStructure.FMC_RCDDelay = 2; + + /* FMC SDRAM control configuration */ + FMC_SDRAMInitStructure.FMC_Bank = FMC_Bank1_SDRAM; + /* Row addressing: [7:0] */ + FMC_SDRAMInitStructure.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_8b; + /* Column addressing: [11:0] */ + FMC_SDRAMInitStructure.FMC_RowBitsNumber = FMC_RowBits_Number_12b; + FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth = FMC_SDMemory_Width_16b; + FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4; + FMC_SDRAMInitStructure.FMC_CASLatency = FMC_CAS_Latency_3; + FMC_SDRAMInitStructure.FMC_WriteProtection = FMC_Write_Protection_Disable; + FMC_SDRAMInitStructure.FMC_SDClockPeriod = FMC_SDClock_Period_2; + FMC_SDRAMInitStructure.FMC_ReadBurst = FMC_Read_Burst_Enable; + FMC_SDRAMInitStructure.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_1; + FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingInitStructure; + + /* FMC SDRAM bank initialization */ + FMC_SDRAMInit(&FMC_SDRAMInitStructure); + + /* FMC SDRAM device initialization sequence */ + SDRAM_InitSequence(); +} diff --git a/radio/src/targets/pl18/touch_driver.cpp b/radio/src/targets/pl18/touch_driver.cpp new file mode 100644 index 00000000000..c672aa925bb --- /dev/null +++ b/radio/src/targets/pl18/touch_driver.cpp @@ -0,0 +1,470 @@ +/* + * 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 "stm32_hal_ll.h" +#include "stm32_hal.h" +#include "stm32_i2c_driver.h" +#include "stm32_gpio_driver.h" +#include "stm32_exti_driver.h" + +#include "hal.h" +#include "timers_driver.h" +#include "delays_driver.h" +#include "touch_driver.h" + +#include "debug.h" + +#define TAP_TIME 25 +#define I2C_TIMEOUT_MAX 5 // 5 ms + +// FT6236 definitions +#define TOUCH_FT6236_I2C_ADDRESS (0x70>>1) +#define TOUCH_FT6236_REG_TH_GROUP 0x80 +#define TOUCH_FT6236_REG_PERIODACTIVE 0x88 +#define TOUCH_FT6236_REG_LIB_VER_H 0xa1 +#define TOUCH_FT6236_REG_LIB_VER_L 0xa2 +#define TOUCH_FT6236_REG_CIPHER 0xa3 +#define TOUCH_FT6236_REG_FIRMID 0xa6 +#define TOUCH_FT6236_REG_FOCALTECH_ID 0xa8 +#define TOUCH_FT6236_REG_RELEASE_CODE_ID 0xaf +#define TOUCH_FT6206_REG_TD_STAT 0x02 +#define TOUCH_FT6206_REG_P1_XH 0x03 +#define TOUCH_FT6206_EVT_SHIFT 6 +#define TOUCH_FT6206_EVT_MASK (3 << TOUCH_FT6206_EVT_SHIFT) +#define TOUCH_FT6206_EVT_CONTACT 0x02 +#define TOUCH_FT6206_MASK_TD_STAT 0x0f + +// CST340 definitions +#define TOUCH_CST340_I2C_ADDRESS 0x1a +#define TOUCH_CST340_REG_FINGER1 0x00 +#define TOUCH_CST340_EVT_CONTACT 0x06 + +// CHSC5448 definitions +#define TOUCH_CHSC5448_I2C_ADDRESS 0x2e +#define TOUCH_CHSC5448_REG_ADDR 0x2c000020 +#define TOUCH_CHSC5448_EVT_CONTACT 0x08 +#define TOUCH_CHSC5448_MAX_POINTS 5 + +typedef enum {TC_NONE, TC_FT6236, TC_CST340, TC_CHSC5448} TouchController; + +#if defined(DEBUG) +const char TOUCH_CONTROLLER_STR[][10] = {"", "FT6236", "CST340", "CHSC5448"}; +#endif + +TouchController touchController = TC_NONE; + +struct TouchControllerDescriptor +{ + bool (*hasTouchEvent)(); + bool (*touchRead)(uint16_t * X, uint16_t * Y); + void (*printDebugInfo)(); + bool needTranspose; +}; + +union rpt_point_t +{ + struct + { + unsigned char x_l8; + unsigned char y_l8; + unsigned char z; + unsigned char x_h4:4; + unsigned char y_h4:4; + unsigned char id:4; + unsigned char event:4; + }rp; + unsigned char data[5]; +}; + +extern uint8_t TouchControllerType; + +static const TouchControllerDescriptor *tcd = nullptr; +static TouchState internalTouchState = {}; +volatile static bool touchEventOccured; +static tmr10ms_t downTime = 0; +static tmr10ms_t tapTime = 0; +static short tapCount = 0; + +static void _touch_exti_isr(void) +{ + touchEventOccured = true; +} + +static void _touch_exti_stop(void) +{ + stm32_exti_disable(TOUCH_INT_EXTI_Line); +} + +static void _touch_exti_config(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, _touch_exti_isr); +} + +static void _touch_gpio_config(void) +{ + LL_GPIO_InitTypeDef gpioInit; + LL_GPIO_StructInit(&gpioInit); + + stm32_gpio_enable_clock(TOUCH_RST_GPIO); + stm32_gpio_enable_clock(TOUCH_INT_GPIO); + + gpioInit.Mode = LL_GPIO_MODE_OUTPUT; + gpioInit.Speed = LL_GPIO_SPEED_FREQ_LOW; + gpioInit.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + gpioInit.Pull = LL_GPIO_PULL_NO; + + gpioInit.Pin = TOUCH_RST_GPIO_PIN; + LL_GPIO_Init(TOUCH_RST_GPIO, &gpioInit); + LL_GPIO_SetOutputPin(TOUCH_RST_GPIO, TOUCH_RST_GPIO_PIN); + + gpioInit.Pin = TOUCH_INT_GPIO_PIN; + gpioInit.Mode = LL_GPIO_MODE_INPUT; + gpioInit.Pull = LL_GPIO_PULL_UP; + gpioInit.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; + LL_GPIO_Init(TOUCH_INT_GPIO, &gpioInit); + LL_GPIO_SetOutputPin(TOUCH_INT_GPIO, TOUCH_INT_GPIO_PIN); +} + +static void _touch_reset() +{ + LL_GPIO_ResetOutputPin(TOUCH_RST_GPIO, TOUCH_RST_GPIO_PIN); + delay_ms(10); + LL_GPIO_SetOutputPin(TOUCH_RST_GPIO, TOUCH_RST_GPIO_PIN); + delay_ms(300); +} + +static void _i2c_init(void) +{ + TRACE("Touch I2C Init"); + + if (stm32_i2c_init(TOUCH_I2C_BUS, TOUCH_I2C_CLK_RATE) < 0) { + TRACE("Touch I2C Init ERROR: stm32_i2c_init failed"); + return; + } +} + +static void _i2c_reInit(void) +{ + stm32_i2c_deinit(TOUCH_I2C_BUS); + _i2c_init(); +} + +static int _i2c_read(uint8_t addr, uint32_t reg, uint8_t regSize, uint8_t* data, uint16_t len, uint32_t timeout) +{ + if (regSize > 2) { + if(stm32_i2c_master_tx(TOUCH_I2C_BUS, addr, (uint8_t*) ®, regSize, 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; + } else { + return stm32_i2c_read(TOUCH_I2C_BUS, addr, reg, regSize, data, len, timeout); + } +} + +static uint8_t _i2c_readRetry(uint8_t addr, uint32_t reg, uint8_t regSize) +{ + uint8_t result; + uint8_t tryCount = 3; + while (_i2c_read(addr, reg, regSize, &result, 1, I2C_TIMEOUT_MAX) < 0) { + if (--tryCount == 0) break; + _i2c_reInit(); + } + return result; +} + +static uint16_t _i2c_readMultipleRetry(uint8_t addr, uint32_t reg, uint8_t regSize, uint8_t * buffer, uint16_t length) +{ + uint8_t tryCount = 3; + while (_i2c_read(addr, reg, regSize, buffer, length, I2C_TIMEOUT_MAX) < 0) { + if (--tryCount == 0) break; + _i2c_reInit(); + } + return length; +} + +static bool ft6236TouchRead(uint16_t * X, uint16_t * Y) +{ + // Read register FT6206_TD_STAT_REG to check number of touches detection + uint8_t nbTouch = _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6206_REG_TD_STAT, 1); + nbTouch &= TOUCH_FT6206_MASK_TD_STAT; + bool hasTouch = nbTouch > 0; + + if (hasTouch) { + uint8_t dataxy[4]; + // Read X and Y positions and event + _i2c_readMultipleRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6206_REG_P1_XH, 1, dataxy, sizeof(dataxy)); + + // Send back ready X position to caller + *X = ((dataxy[0] & 0x0f) << 8) | dataxy[1]; + // Send back ready Y position to caller + *Y = ((dataxy[2] & 0x0f) << 8) | dataxy[3]; + + uint8_t event = (dataxy[0] & TOUCH_FT6206_EVT_MASK) >> TOUCH_FT6206_EVT_SHIFT; + return event == TOUCH_FT6206_EVT_CONTACT; + } + return false; +} + +static bool ft6236HasTouchEvent() +{ + return touchEventOccured; +} + +static void ft6236PrintDebugInfo() +{ +#if defined(DEBUG) + TRACE("ft6x36: thrhld = %d", _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_TH_GROUP, 1) * 4); + TRACE("ft6x36: rep rate=", _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_PERIODACTIVE, 1) * 10); + TRACE("ft6x36: fw lib 0x%02X %02X", _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_LIB_VER_H, 1), + _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_LIB_VER_L, 1)); + TRACE("ft6x36: fw v 0x%02X", _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_FIRMID, 1)); + TRACE("ft6x36: CHIP ID 0x%02X", _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_CIPHER, 1)); + TRACE("ft6x36: CTPM ID 0x%02X", _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_FOCALTECH_ID, 1)); + TRACE("ft6x36: rel code 0x%02X", _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_RELEASE_CODE_ID, 1)); +#endif + +} + +static bool cst340TouchRead(uint16_t * X, uint16_t * Y) +{ + uint8_t data[4]; + + // Read X and Y positions + _i2c_readMultipleRetry(TOUCH_CST340_I2C_ADDRESS, TOUCH_CST340_REG_FINGER1, 1, data, sizeof(data)); + + // Send back X position to caller + if (X) *X = ((data[1]<<4) + ((data[3]>>4)&0x0f)); + // Send back Y position to caller + if (Y) *Y = ((data[2]<<4) + ((data[3])&0x0f)); + + return data[0] == TOUCH_CST340_EVT_CONTACT; +} + +static bool cst340HasTouchEvent() +{ + static bool lastHasTouch = false; + bool ret = touchEventOccured; + if (ret) { + uint8_t hasTouch = cst340TouchRead(nullptr, nullptr); + if (!hasTouch && !lastHasTouch) { + TRACE("Interrupt occurs without touch event!!"); + touchEventOccured = false; + ret = false; + } + lastHasTouch = hasTouch; + } + + return ret; +} + +static void cst340PrintDebugInfo() +{ + // TODO, when necessary +} + +static bool chsc5448TouchRead(uint16_t * X, uint16_t * Y) +{ + static uint8_t readbuffer[84]; + const uint8_t reportSize = ((TOUCH_CHSC5448_MAX_POINTS * 5 + 2) + 3) & 0xfc; + + int ptCnt = 0; + union rpt_point_t* ppt; + + _i2c_readMultipleRetry(TOUCH_CHSC5448_I2C_ADDRESS, TOUCH_CHSC5448_REG_ADDR, 4, readbuffer, reportSize); + ptCnt = readbuffer[1] & 0x0f; + ppt = (union rpt_point_t*)&readbuffer[2]; + *X = ((ppt->rp.x_h4 & 0x0f) << 8) | ppt->rp.x_l8; + *Y = ((ppt->rp.y_h4 & 0x0f) << 8) | ppt->rp.y_l8; + uint8_t event = ppt->rp.event; + + return ptCnt > 0 && event == TOUCH_CHSC5448_EVT_CONTACT; +} + +static bool chsc5448HasTouchEvent() +{ + return touchEventOccured; +} + +static void chsc5448PrintDebugInfo() +{ + // TODO, when necessary +} + +static const TouchControllerDescriptor FT6236 = +{ + .hasTouchEvent = ft6236HasTouchEvent, + .touchRead = ft6236TouchRead, + .printDebugInfo = ft6236PrintDebugInfo, + .needTranspose = true, +}; + +static const TouchControllerDescriptor CST340 = +{ + .hasTouchEvent = cst340HasTouchEvent, + .touchRead = cst340TouchRead, + .printDebugInfo = cst340PrintDebugInfo, + .needTranspose = true, +}; + +static const TouchControllerDescriptor CHSC5448 = +{ + .hasTouchEvent = chsc5448HasTouchEvent, + .touchRead = chsc5448TouchRead, + .printDebugInfo = chsc5448PrintDebugInfo, + .needTranspose = false, +}; + +void _detect_touch_controller() +{ + if (stm32_i2c_is_dev_ready(TOUCH_I2C_BUS, TOUCH_CST340_I2C_ADDRESS, 3, I2C_TIMEOUT_MAX) == 0) { + touchController = TC_CST340; + tcd = &CST340; + TouchControllerType = 0; + } else if (stm32_i2c_is_dev_ready(TOUCH_I2C_BUS, TOUCH_CHSC5448_I2C_ADDRESS, 3, I2C_TIMEOUT_MAX) == 0) { + touchController = TC_CHSC5448; + tcd = &CHSC5448; + TouchControllerType = 0; + } else { + touchController = TC_FT6236; + tcd = &FT6236; + TouchControllerType = 1; + } +} + +void touchPanelDeInit() +{ + _touch_exti_stop(); +} + +bool touchPanelInit() +{ + _touch_gpio_config(); + _i2c_init(); + _touch_reset(); + _detect_touch_controller(); + _touch_exti_config(); + + tcd->printDebugInfo(); + + return touchController != TC_NONE; +} + +bool touchPanelEventOccured() +{ + return tcd->hasTouchEvent(); +} + +struct TouchState touchPanelRead() +{ + if (!touchEventOccured) return internalTouchState; + + touchEventOccured = false; + + tmr10ms_t now = get_tmr10ms(); + internalTouchState.tapCount = 0; + unsigned short touchX; + unsigned short touchY; + bool hasTouchContact = tcd->touchRead(&touchX, &touchY); + + if (tcd->needTranspose) { + // Touch sensor is rotated by 90 deg + unsigned short tmp = touchY; + touchY = 319 - touchX; + touchX = tmp; + } + + if (hasTouchContact) { + 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; + } + + 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; + +#if defined(DEBUG) + TRACE("%s: event=%d,X=%d,Y=%d", TOUCH_CONTROLLER_STR[touchController], ret.event, ret.x, ret.y); +#endif + + return ret; +} + +struct TouchState getInternalTouchState() +{ + return internalTouchState; +} diff --git a/radio/src/targets/pl18/touch_driver.h b/radio/src/targets/pl18/touch_driver.h new file mode 100644 index 00000000000..6b0fb01a8f6 --- /dev/null +++ b/radio/src/targets/pl18/touch_driver.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#include "touch.h" + +extern void touchPanelDeInit(); +extern bool touchPanelInit(); + +struct TouchState touchPanelRead(); +bool touchPanelEventOccured(); +struct TouchState getInternalTouchState(); diff --git a/radio/src/targets/pl18/tp_cst340.cpp b/radio/src/targets/pl18/tp_cst340.cpp new file mode 100644 index 00000000000..c8e633ff3cf --- /dev/null +++ b/radio/src/targets/pl18/tp_cst340.cpp @@ -0,0 +1,560 @@ +/* + * 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 "stm32_hal_ll.h" +#include "stm32_hal.h" +#include "stm32_i2c_driver.h" +#include "stm32_gpio_driver.h" +#include "stm32_exti_driver.h" + +#include "hal.h" +#include "timers_driver.h" +#include "delays_driver.h" +#include "tp_cst340.h" + +#include "debug.h" + +#define TOUCH_FT6236_I2C_ADDRESS (0x70>>1) +#define TOUCH_CST340_I2C_ADDRESS 0x1A + + +extern uint8_t TouchControllerType; + +volatile static bool touchEventOccured; +enum TouchControllers {TC_NONE, TC_FT6236, TC_CST340}; +TouchControllers touchController = TC_NONE; + +static tc_handle_TypeDef tc_handle = {0, 0}; + +tmr10ms_t downTime = 0; +tmr10ms_t tapTime = 0; +short tapCount = 0; +#define TAP_TIME 25 + +struct TouchControllerDescriptor +{ + void (*read)(uint16_t * X, uint16_t * Y, uint32_t * event); + uint8_t (*detectTouch)(); + void (*printDebugInfo)(); + uint32_t contactEvent; +}; + +static const TouchControllerDescriptor *tc = nullptr; + +static TouchState internalTouchState = {}; + +static void _cst340_exti_isr(void) +{ + touchEventOccured = true; +} + +static void TOUCH_AF_ExtiStop(void) +{ + stm32_exti_disable(TOUCH_INT_EXTI_Line); +} + +static void TOUCH_AF_ExtiConfig(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, + _cst340_exti_isr); +} + +static void TOUCH_AF_GPIOConfig(void) +{ + LL_GPIO_InitTypeDef gpioInit; + LL_GPIO_StructInit(&gpioInit); + + stm32_gpio_enable_clock(TOUCH_RST_GPIO); + stm32_gpio_enable_clock(TOUCH_INT_GPIO); + + gpioInit.Mode = LL_GPIO_MODE_OUTPUT; + gpioInit.Speed = LL_GPIO_SPEED_FREQ_LOW; + gpioInit.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + gpioInit.Pull = LL_GPIO_PULL_NO; + + gpioInit.Pin = TOUCH_RST_GPIO_PIN; + LL_GPIO_Init(TOUCH_RST_GPIO, &gpioInit); + LL_GPIO_SetOutputPin(TOUCH_RST_GPIO, TOUCH_RST_GPIO_PIN); + + gpioInit.Pin = TOUCH_INT_GPIO_PIN; + gpioInit.Mode = LL_GPIO_MODE_INPUT; + gpioInit.Pull = LL_GPIO_PULL_UP; + gpioInit.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; + LL_GPIO_Init(TOUCH_INT_GPIO, &gpioInit); + LL_GPIO_SetOutputPin(TOUCH_INT_GPIO, TOUCH_INT_GPIO_PIN); +} + +void I2C_Init_Radio(void) +{ + TRACE("CST340 I2C Init"); + + if (stm32_i2c_init(TOUCH_I2C_BUS, TOUCH_I2C_CLK_RATE) < 0) { + TRACE("CST340 ERROR: stm32_i2c_init failed"); + return; + } +} + +// void Touch_DeInit() +// { +// I2C_DeInit(I2C_B1); +// __HAL_RCC_I2C1_FORCE_RESET(); +// delay_ms(150); +// __HAL_RCC_I2C1_RELEASE_RESET(); +// } + +#define I2C_TIMEOUT_MAX 5 // 5 ms + +bool touch_i2c_read(uint8_t addr, uint8_t reg, uint8_t * data, uint8_t len) +{ +// if(touchController == TC_CST836U) +// { +// 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; +// } else { + if (stm32_i2c_read(TOUCH_I2C_BUS, addr, reg, 1, data, len, I2C_TIMEOUT_MAX) < 0) + return false; +// } + + return true; +} + +#if 0 +static bool touch_i2c_write(uint8_t addr, uint8_t reg, uint8_t * data, uint8_t len) +{ + if (stm32_i2c_write(TOUCH_I2C_BUS, addr, reg, 1, data, len, I2C_TIMEOUT_MAX) < 0) + return false; + + return true; +} + +static void TS_IO_Write(uint8_t addr, uint8_t reg, uint8_t data) +{ + uint8_t tryCount = 3; + while (!touch_i2c_write(addr, reg, &data, 1)) { + if (--tryCount == 0) break; + I2C_Init(); + } +} +#endif + +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; + I2C_Init_Radio(); +// I2C_Init(); + } + 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; + I2C_Init_Radio(); +// I2C_Init(); + } + return 1; +} + +static void touch_ft6236_debug_info(void) +{ +#if defined(DEBUG) + TRACE("ft6x36: thrhld = %d", TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_TH_GROUP) * 4); + TRACE("ft6x36: rep rate=", TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_PERIODACTIVE) * 10); + TRACE("ft6x36: fw lib 0x%02X %02X", TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_LIB_VER_H), TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_LIB_VER_L)); + TRACE("ft6x36: fw v 0x%02X", TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_FIRMID)); + TRACE("ft6x36: CHIP ID 0x%02X", TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_CIPHER)); + TRACE("ft6x36: CTPM ID 0x%02X", TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_FOCALTECH_ID)); + TRACE("ft6x36: rel code 0x%02X", TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_RELEASE_CODE_ID)); +#endif +} + +/** + * @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 ft6x06_TS_DetectTouch() +{ + volatile uint8_t nbTouch = 0; + + /* Read register FT6206_TD_STAT_REG to check number of touches detection */ + nbTouch = TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, FT6206_TD_STAT_REG); + nbTouch &= FT6206_TD_STAT_MASK; + if (nbTouch > FT6206_MAX_DETECTABLE_TOUCH) { + /* If invalid number of touch detected, set it to zero */ + nbTouch = 0; + } + /* Update ft6x06 driver internal global : current number of active touches */ + tc_handle.currActiveTouchNb = nbTouch; + + /* Reset current active touch index on which to work on */ + tc_handle.currActiveTouchIdx = 0; + return (nbTouch); +} + +#if 0 +/** + * @brief Get the touch detailed informations on touch number 'touchIdx' (0..1) + * This touch detailed information contains : + * - weight that was applied to this touch + * - sub-area of the touch in the touch panel + * - event of linked to the touch (press down, lift up, ...) + * @param DeviceAddr: Device address on communication Bus (I2C slave address of FT6x06). + * @param touchIdx : Passed index of the touch (0..1) on which we want to get the + * detailed information. + * @param pWeight : Pointer to to get the weight information of 'touchIdx'. + * @param pArea : Pointer to to get the sub-area information of 'touchIdx'. + * @param pEvent : Pointer to to get the event information of 'touchIdx'. + + * @retval None. + */ +static void ft6x06_TS_GetTouchInfo(uint16_t DeviceAddr, + uint32_t touchIdx, + uint32_t * pWeight, + uint32_t * pArea, + uint32_t * pEvent) +{ + uint8_t regAddress = 0; + uint8_t dataxy[3]; + + if (touchIdx < ft6x06_handle.currActiveTouchNb) { + switch (touchIdx) { + case 0 : + regAddress = FT6206_P1_WEIGHT_REG; + break; + + case 1 : + regAddress = FT6206_P2_WEIGHT_REG; + break; + + default : + break; + + } /* end switch(touchIdx) */ + + /* Read weight, area and Event Id of touch index */ + TS_IO_ReadMultiple(DeviceAddr, regAddress, dataxy, sizeof(dataxy)); + + /* Return weight of touch index */ + *pWeight = (dataxy[0] & FT6206_TOUCH_WEIGHT_MASK) >> FT6206_TOUCH_WEIGHT_SHIFT; + /* Return area of touch index */ + *pArea = (dataxy[1] & FT6206_TOUCH_AREA_MASK) >> FT6206_TOUCH_AREA_SHIFT; + /* Return Event Id of touch index */ + *pEvent = (dataxy[2] & FT6206_TOUCH_EVT_FLAG_MASK) >> FT6206_TOUCH_EVT_FLAG_SHIFT; + + } /* of if(touchIdx < ft6x06_handle.currActiveTouchNb) */ +} +#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 ft6x06_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 = FT6206_P1_XH_REG; + break; + case 1 : + regAddress = FT6206_P2_XH_REG; + break; + + default : + break; + } + + /* Read X and Y positions */ + TS_IO_ReadMultiple(TOUCH_FT6236_I2C_ADDRESS, regAddress, dataxy, sizeof(dataxy)); + /* Send back ready X position to caller */ + *X = ((dataxy[0] & FT6206_MSB_MASK) << 8) | (dataxy[1] & FT6206_LSB_MASK); + /* Send back ready Y position to caller */ + *Y = ((dataxy[2] & FT6206_MSB_MASK) << 8) | (dataxy[3] & FT6206_LSB_MASK); + + *event = (dataxy[0] & FT6206_TOUCH_EVT_FLAG_MASK) >> FT6206_TOUCH_EVT_FLAG_SHIFT; + /* + uint32_t weight; + uint32_t area; + ft6x06_TS_GetTouchInfo(DeviceAddr, ft6x06_handle.currActiveTouchIdx, &weight, &area, event); + */ + tc_handle.currActiveTouchIdx++; + } +} + +static void touch_cst340_debug_info(void) +{ +#if 0 // Disabled because cannot compile, will fix when necessary +#if defined(DEBUG) + uint8_t tmp[4]; + if (!TS_IO_Write(CST340_MODE_DEBUG_INFO, tmp, 0)) + TRACE("CST340 chip NOT FOUND"); + + // Check the value, expected ChipID + uint32_t chipId = tmp[0] << 8) + tmp[1]; + + if (!I2C_CST340_ReadRegister(CST340_FWVER_REG, tmp, 4)) + TRACE("Error reading CST340 firmware version!"); + uint32_t fwVersion = tmp[0] << 24 | tmp[1]<<16 | tmp[2]<<8 | tmp[0]; + + // Enter normal mode + if (!I2C_CST340_WriteRegister(CST340_MODE_NORMAL, tmp, 0)) + TRACE("ERROR chaning CST340 mode back to normal!"); + + TRACE("cst340: fw ver 0x%08X", fwVersion); + TRACE("cst836u: chip id 0x%04X", chipId); +#endif +#endif +} + +/** + * @brief Get the touch screen X and Y positions values + * @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 cst340_TS_GetXY(uint16_t * X, uint16_t * Y, uint32_t * event) +{ + uint8_t dataxy[4]; + + /* Read X and Y positions */ + TS_IO_ReadMultiple(TOUCH_CST340_I2C_ADDRESS, CST340_FINGER1_REG, dataxy, sizeof(dataxy)); + /* Send back ready X position to caller */ + *X = ((dataxy[1]<<4) + ((dataxy[3]>>4)&0x0f)); + *Y = ((dataxy[2]<<4) + ((dataxy[3])&0x0f)); + /* Send back ready Y position to caller */ + + *event = dataxy[0]; +} + +/** + * @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 + */ +static uint8_t cst340_TS_DetectTouch() +{ + uint8_t nbTouch; + uint8_t reg = TS_IO_Read(TOUCH_CST340_I2C_ADDRESS, CST340_FINGER1_REG); + if( reg == 0x06 ) + nbTouch = 1; + else + nbTouch = 0; + + tc_handle.currActiveTouchNb = nbTouch; + + tc_handle.currActiveTouchIdx = 0; + return (nbTouch); +} + +void TouchReset() +{ + LL_GPIO_ResetOutputPin(TOUCH_RST_GPIO, TOUCH_RST_GPIO_PIN); + delay_ms(10); + LL_GPIO_SetOutputPin(TOUCH_RST_GPIO, TOUCH_RST_GPIO_PIN); + delay_ms(300); +} + +static const TouchControllerDescriptor FT6236 = +{ + .read = ft6x06_TS_GetXY, + .detectTouch = ft6x06_TS_DetectTouch, + .printDebugInfo = touch_ft6236_debug_info, + .contactEvent = FT6206_TOUCH_EVT_FLAG_CONTACT +}; +static const TouchControllerDescriptor CST340 = +{ + .read = cst340_TS_GetXY, + .detectTouch = cst340_TS_DetectTouch, + .printDebugInfo = touch_cst340_debug_info, + .contactEvent = CST340_TOUCH_EVT_FLAG_CONTACT +}; + +void detectTouchController() +{ + if( stm32_i2c_is_dev_ready(TOUCH_I2C_BUS, TOUCH_CST340_I2C_ADDRESS, 3, 5) == 0) + { + TouchControllerType = 0; + touchController = TC_CST340; + tc = &CST340; + } else { + TouchControllerType = 1; + touchController = TC_FT6236; + tc = &FT6236; + } +} + +void TouchInit() +{ + TOUCH_AF_GPIOConfig(); // SET RST=OUT INT=IN INT=HIGH + I2C_Init_Radio(); + TouchReset(); + detectTouchController(); + TOUCH_AF_ExtiConfig(); + + tc->printDebugInfo(); +} + +void handleTouch() +{ + unsigned short touchX; + unsigned short touchY; + uint32_t tEvent = 0; + tc->read(&touchX, &touchY, &tEvent); + +#if defined(DEBUG) + TRACE("handleTouch: touchX=%d, touchY=%d, tEvent=%d", touchX, touchY, tEvent); +#endif + // touch sensor is rotated by 90 deg + unsigned short tmp = touchY; + touchY = 319 - touchX; + touchX = tmp; + + if (tEvent == tc->contactEvent) { + 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; + } + + } +} + +static bool lastHasTouch = false; +bool touchPanelEventOccured() +{ + bool result = touchEventOccured; + uint8_t hasTouch = false; + if (touchEventOccured) { + hasTouch = tc->detectTouch(); + if (!hasTouch && !lastHasTouch) { + touchEventOccured = false; + result = false; + } + lastHasTouch = hasTouch; + } + +#if defined(DEBUG) + TRACE("TouchEvent: %d, %d, %d, %d", touchEventOccured, lastHasTouch, hasTouch, result); +#endif + return result; +} + +TouchState touchPanelRead() +{ + if (!touchEventOccured) return internalTouchState; + + touchEventOccured = false; + + tmr10ms_t now = get_tmr10ms(); + internalTouchState.tapCount = 0; + + if (tc->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; + +#if defined(DEBUG) + TRACE("%s: Event = %d", touchController == TC_CST340 ? "CST340" : "FT6236", ret.event); +#endif + + return ret; +} + +TouchState getInternalTouchState() +{ + return internalTouchState; +} diff --git a/radio/src/targets/pl18/tp_cst340.h b/radio/src/targets/pl18/tp_cst340.h new file mode 100644 index 00000000000..ec5f1610749 --- /dev/null +++ b/radio/src/targets/pl18/tp_cst340.h @@ -0,0 +1,289 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#include "touch.h" + +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; + + +#define TOUCH_FT6236_MAX_TOUCH_POINTS 2 + +#define TOUCH_FT6236_REG_TH_GROUP 0x80 +#define TOUCH_FT6236_REG_PERIODACTIVE 0x88 +#define TOUCH_FT6236_REG_LIB_VER_H 0xa1 +#define TOUCH_FT6236_REG_LIB_VER_L 0xa2 +#define TOUCH_FT6236_REG_CIPHER 0xa3 +#define TOUCH_FT6236_REG_FIRMID 0xa6 +#define TOUCH_FT6236_REG_FOCALTECH_ID 0xa8 +#define TOUCH_FT6236_REG_RELEASE_CODE_ID 0xaf + +#define TOUCH_FT6236_EVENT_PRESS_DOWN 0 +#define TOUCH_FT6236_EVENT_LIFT_UP 1 +#define TOUCH_FT6236_EVENT_CONTACT 2 +#define TOUCH_FT6236_EVENT_NO_EVENT 3 + +#define TOUCH_FT6236_GESTURE_MOVE_FLAG 0x10 +#define TOUCH_FT6236_GESTURE_MOVE_UP 0x10 +#define TOUCH_FT6236_GESTURE_MOVE_RIGHT 0x14 +#define TOUCH_FT6236_GESTURE_MOVE_DOWN 0x18 +#define TOUCH_FT6236_GESTURE_MOVE_LEFT 0x1C +#define TOUCH_FT6236_GESTURE_ZOOM_IN 0x48 +#define TOUCH_FT6236_GESTURE_ZOOM_OUT 0x49 +#define TOUCH_FT6236_GESTURE_NONE 0x00 + +#define TOUCH_GESTURE_UP ((TOUCH_FT6236_GESTURE_MOVE_UP & 0x0F)+1) +#define TOUCH_GESTURE_DOWN ((TOUCH_FT6236_GESTURE_MOVE_DOWN & 0x0F)+1) +#define TOUCH_GESTURE_LEFT ((TOUCH_FT6236_GESTURE_MOVE_LEFT & 0x0F)+1) +#define TOUCH_GESTURE_RIGHT ((TOUCH_FT6236_GESTURE_MOVE_RIGHT & 0x0F)+1) +#define TOUCH_GESTURE_MOUSE_DOWN (0x80+TOUCH_FT6236_EVENT_PRESS_DOWN) +#define TOUCH_GESTURE_MOUSE_UP (0x80+TOUCH_FT6236_EVENT_LIFT_UP) +#define TOUCH_GESTURE_MOUSE_MOVE (0x80+TOUCH_FT6236_EVENT_CONTACT) +#define TOUCH_GESTURE_MOUSE_NONE (0x80+TOUCH_FT6236_EVENT_NO_EVENT) + + + + /* Maximum border values of the touchscreen pad */ +#define FT_6206_MAX_WIDTH ((uint16_t)800) /* Touchscreen pad max width */ +#define FT_6206_MAX_HEIGHT ((uint16_t)480) /* Touchscreen pad max height */ + + /* Possible values of driver functions return status */ +#define FT6206_STATUS_OK 0 +#define FT6206_STATUS_NOT_OK 1 + + /* Max detectable simultaneous touches */ +#define FT6206_MAX_DETECTABLE_TOUCH 2 + + /** + * @brief : Definitions for FT6206 I2C register addresses on 8 bit + **/ + + /* Current mode register of the FT6206 (R/W) */ +#define FT6206_DEV_MODE_REG 0x00 + + /* Possible values of FT6206_DEV_MODE_REG */ +#define FT6206_DEV_MODE_WORKING 0x00 +#define FT6206_DEV_MODE_FACTORY 0x04 + +#define FT6206_DEV_MODE_MASK 0x7 +#define FT6206_DEV_MODE_SHIFT 4 + + /* Gesture ID register */ +#define FT6206_GEST_ID_REG 0x01 + + /* Possible values of FT6206_GEST_ID_REG */ +#define FT6206_GEST_ID_NO_GESTURE 0x00 +#define FT6206_GEST_ID_MOVE_UP 0x10 +#define FT6206_GEST_ID_MOVE_RIGHT 0x14 +#define FT6206_GEST_ID_MOVE_DOWN 0x18 +#define FT6206_GEST_ID_MOVE_LEFT 0x1C +#define FT6206_GEST_ID_ZOOM_IN 0x48 +#define FT6206_GEST_ID_ZOOM_OUT 0x49 + + /* Touch Data Status register : gives number of active touch points (0..2) */ +#define FT6206_TD_STAT_REG 0x02 + + /* Values related to FT6206_TD_STAT_REG */ +#define FT6206_TD_STAT_MASK 0x0F +#define FT6206_TD_STAT_SHIFT 0x00 + + /* Values Pn_XH and Pn_YH related */ +#define FT6206_TOUCH_EVT_FLAG_PRESS_DOWN 0x00 +#define FT6206_TOUCH_EVT_FLAG_LIFT_UP 0x01 +#define FT6206_TOUCH_EVT_FLAG_CONTACT 0x02 +#define FT6206_TOUCH_EVT_FLAG_NO_EVENT 0x03 + +#define FT6206_TOUCH_EVT_FLAG_SHIFT 6 +#define FT6206_TOUCH_EVT_FLAG_MASK (3 << FT6206_TOUCH_EVT_FLAG_SHIFT) + +#define FT6206_MSB_MASK 0x0F +#define FT6206_MSB_SHIFT 0 + + /* Values Pn_XL and Pn_YL related */ +#define FT6206_LSB_MASK 0xFF +#define FT6206_LSB_SHIFT 0 + +#define FT6206_P1_XH_REG 0x03 +#define FT6206_P1_XL_REG 0x04 +#define FT6206_P1_YH_REG 0x05 +#define FT6206_P1_YL_REG 0x06 + + /* Touch Pressure register value (R) */ +#define FT6206_P1_WEIGHT_REG 0x07 + + /* Values Pn_WEIGHT related */ +#define FT6206_TOUCH_WEIGHT_MASK 0xFF +#define FT6206_TOUCH_WEIGHT_SHIFT 0 + + /* Touch area register */ +#define FT6206_P1_MISC_REG 0x08 + + /* Values related to FT6206_Pn_MISC_REG */ +#define FT6206_TOUCH_AREA_MASK (0x04 << 4) +#define FT6206_TOUCH_AREA_SHIFT 0x04 + +#define FT6206_P2_XH_REG 0x09 +#define FT6206_P2_XL_REG 0x0A +#define FT6206_P2_YH_REG 0x0B +#define FT6206_P2_YL_REG 0x0C +#define FT6206_P2_WEIGHT_REG 0x0D +#define FT6206_P2_MISC_REG 0x0E + + /* Threshold for touch detection */ +#define FT6206_TH_GROUP_REG 0x80 + + /* Values FT6206_TH_GROUP_REG : threshold related */ +#define FT6206_THRESHOLD_MASK 0xFF +#define FT6206_THRESHOLD_SHIFT 0 + + /* Filter function coefficients */ +#define FT6206_TH_DIFF_REG 0x85 + + /* Control register */ +#define FT6206_CTRL_REG 0x86 + + /* Values related to FT6206_CTRL_REG */ + + /* Will keep the Active mode when there is no touching */ +#define FT6206_CTRL_KEEP_ACTIVE_MODE 0x00 + + /* Switching from Active mode to Monitor mode automatically when there is no touching */ +#define FT6206_CTRL_KEEP_AUTO_SWITCH_MONITOR_MODE 0x01 + + /* The time period of switching from Active mode to Monitor mode when there is no touching */ +#define FT6206_TIMEENTERMONITOR_REG 0x87 + + /* Report rate in Active mode */ +#define FT6206_PERIODACTIVE_REG 0x88 + + /* Report rate in Monitor mode */ +#define FT6206_PERIODMONITOR_REG 0x89 + + /* The value of the minimum allowed angle while Rotating gesture mode */ +#define FT6206_RADIAN_VALUE_REG 0x91 + + /* Maximum offset while Moving Left and Moving Right gesture */ +#define FT6206_OFFSET_LEFT_RIGHT_REG 0x92 + + /* Maximum offset while Moving Up and Moving Down gesture */ +#define FT6206_OFFSET_UP_DOWN_REG 0x93 + + /* Minimum distance while Moving Left and Moving Right gesture */ +#define FT6206_DISTANCE_LEFT_RIGHT_REG 0x94 + + /* Minimum distance while Moving Up and Moving Down gesture */ +#define FT6206_DISTANCE_UP_DOWN_REG 0x95 + + /* Maximum distance while Zoom In and Zoom Out gesture */ +#define FT6206_DISTANCE_ZOOM_REG 0x96 + + /* High 8-bit of LIB Version info */ +#define FT6206_LIB_VER_H_REG 0xA1 + + /* Low 8-bit of LIB Version info */ +#define FT6206_LIB_VER_L_REG 0xA2 + + /* Chip Selecting */ +#define FT6206_CIPHER_REG 0xA3 + + /* Interrupt mode register (used when in interrupt mode) */ +#define FT6206_GMODE_REG 0xA4 + +#define FT6206_G_MODE_INTERRUPT_MASK 0x03 +#define FT6206_G_MODE_INTERRUPT_SHIFT 0x00 + + /* Possible values of FT6206_GMODE_REG */ +#define FT6206_G_MODE_INTERRUPT_POLLING 0x00 +#define FT6206_G_MODE_INTERRUPT_TRIGGER 0x01 + + /* Current power mode the FT6206 system is in (R) */ +#define FT6206_PWR_MODE_REG 0xA5 + + /* FT6206 firmware version */ +#define FT6206_FIRMID_REG 0xA6 + + /* FT6206 Chip identification register */ +#define FT6206_CHIP_ID_REG 0xA8 + + /* Possible values of FT6206_CHIP_ID_REG */ +#define FT6206_ID_VALUE 0x11 + + /* Release code version */ +#define FT6206_RELEASE_CODE_ID_REG 0xAF + + /* Current operating mode the FT6206 system is in (R) */ +#define FT6206_STATE_REG 0xBC + + + +#define HAS_TOUCH_PANEL() touchCST340Flag == true + +#define CST340_MODE_DEBUG_INFO 0xD101 // To read out chip ID and firmware version +#define CST340_MODE_NORMAL 0xD109 // Normal mode +#define CST340_FINGER1_REG 0xD000 // Touch info register +#define CST340_CHIPTYPE_REG 0xD204 // uint16_t chip IC type & uint16_t project ID register +#define CST340_FWVER_REG 0xD208 // Firmware version register(uint8_t major, uint8_t minor, uint16_t build) +#define CST340_TOUCH_EVT_FLAG_CONTACT 6 + +#define CST340_CHIP_ID 0x011C // Expected answer to CST340_CHIPTYPE_REG query for the ChipID field + +#define TOUCH_POINTS_MAX 5 // Max touch points + +#define TOUCH_ACK 0 +#define TOUCH_NACK 1 + +#define CST340_I2C_ADDR 0x1A + +extern bool touchCST340Flag; +extern uint32_t touchI2Chiccups; +extern uint16_t touchICfwver; +void TouchInit(); + +struct TouchState touchPanelRead(); +bool touchPanelEventOccured(); + +PACK(typedef struct { + uint8_t track; + uint16_t x; + uint16_t y; + uint16_t size; + uint8_t reserved; +}) TouchPoint; + +PACK(struct TouchData { + union + { + TouchPoint points[TOUCH_POINTS_MAX]; + uint8_t data[TOUCH_POINTS_MAX * sizeof(TouchPoint)]; + }; +}); + +#define TPRST_LOW() do { TOUCH_RST_GPIO->BSRRH = TOUCH_RST_GPIO_PIN; } while(0) +#define TPRST_HIGH() do { TOUCH_RST_GPIO->BSRRL = TOUCH_RST_GPIO_PIN; } while(0) diff --git a/radio/src/targets/simu/opentxsimulator.cpp b/radio/src/targets/simu/opentxsimulator.cpp index 3c13292347f..4f51bc44bb2 100644 --- a/radio/src/targets/simu/opentxsimulator.cpp +++ b/radio/src/targets/simu/opentxsimulator.cpp @@ -712,6 +712,8 @@ class OpenTxSimulatorFactory: public SimulatorFactory return Board::BOARD_TARANIS_X9LITE; #elif defined(PCBNV14) return Board::BOARD_FLYSKY_NV14; +#elif defined(PCBPL18) + return Board::BOARD_FLYSKY_PL18; #else return Board::BOARD_TARANIS_X9D; #endif diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index 76aaef71ee2..04e6dff25dd 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -535,7 +535,7 @@ void boardOff() void hapticOff() {} -#if defined(PCBFRSKY) || defined(PCBFLYSKY) +#if defined(PCBFRSKY) || defined(PCBNV14) HardwareOptions hardwareOptions; #endif diff --git a/radio/src/targets/simu/simufatfs.cpp b/radio/src/targets/simu/simufatfs.cpp index bd6abc90c0c..c1c15c63a97 100644 --- a/radio/src/targets/simu/simufatfs.cpp +++ b/radio/src/targets/simu/simufatfs.cpp @@ -616,6 +616,7 @@ FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs) #include "hal/storage.h" void storageInit() {} +void storageDeInit() {} void storagePreMountHook() {} bool storageIsPresent() { return true; } diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt index 7fc9ef2113c..4207ed87203 100644 --- a/radio/src/targets/taranis/CMakeLists.txt +++ b/radio/src/targets/taranis/CMakeLists.txt @@ -480,10 +480,6 @@ else() message( FATAL_ERROR "Unknown CPU_TYPE_FULL" ) endif() -if(NOT PCB STREQUAL PCBXLITE) - add_definitions(-DHARDWARE_TRAINER_JACK) -endif() - if(ENABLE_SERIAL_PASSTHROUGH) set(CLI ON "Enable CLI") endif() diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 26bfff7d1d1..d5400c773d3 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -479,4 +479,12 @@ void setTopBatteryValue(uint32_t volts); #define VOLTAGE_DROP 20 #endif +#if defined(RADIO_T20) +#define NUM_TRIMS 8 +#else +#define NUM_TRIMS 4 +#endif + +#define NUM_TRIMS_KEYS (NUM_TRIMS * 2) + #endif // _BOARD_H_ diff --git a/radio/src/tasks.h b/radio/src/tasks.h index 0e6181e5660..e12829108de 100644 --- a/radio/src/tasks.h +++ b/radio/src/tasks.h @@ -30,8 +30,15 @@ #else #define MENUS_STACK_SIZE 2000 #endif + +#if !defined(DEBUG) #define MIXER_STACK_SIZE 400 #define AUDIO_STACK_SIZE 400 +#else +#define MIXER_STACK_SIZE 512 +#define AUDIO_STACK_SIZE 512 +#endif + #define CLI_STACK_SIZE 1024 // only consumed with CLI build option #if defined(FREE_RTOS) diff --git a/radio/src/tests/images/color/bitmap_480x320.png b/radio/src/tests/images/color/bitmap_480x320.png new file mode 100644 index 00000000000..f3d818510e9 Binary files /dev/null and b/radio/src/tests/images/color/bitmap_480x320.png differ diff --git a/radio/src/tests/images/color/clipping_480x320.png b/radio/src/tests/images/color/clipping_480x320.png new file mode 100644 index 00000000000..f14ef839bd3 Binary files /dev/null and b/radio/src/tests/images/color/clipping_480x320.png differ diff --git a/radio/src/tests/images/color/lines_480x320.png b/radio/src/tests/images/color/lines_480x320.png new file mode 100644 index 00000000000..885a7a1e0ca Binary files /dev/null and b/radio/src/tests/images/color/lines_480x320.png differ diff --git a/radio/src/tests/images/color/masks_480x320.png b/radio/src/tests/images/color/masks_480x320.png new file mode 100644 index 00000000000..21a81ec7fd7 Binary files /dev/null and b/radio/src/tests/images/color/masks_480x320.png differ diff --git a/radio/src/tests/images/color/primitives_EN_480x320.png b/radio/src/tests/images/color/primitives_EN_480x320.png new file mode 100644 index 00000000000..365a2a20fb2 Binary files /dev/null and b/radio/src/tests/images/color/primitives_EN_480x320.png differ diff --git a/radio/src/tests/images/color/transparency_EN_480x320.png b/radio/src/tests/images/color/transparency_EN_480x320.png new file mode 100644 index 00000000000..54827cd1611 Binary files /dev/null and b/radio/src/tests/images/color/transparency_EN_480x320.png differ diff --git a/radio/src/tests/images/color/vline_480x320.png b/radio/src/tests/images/color/vline_480x320.png new file mode 100644 index 00000000000..7acb28b2413 Binary files /dev/null and b/radio/src/tests/images/color/vline_480x320.png differ diff --git a/radio/src/translations/cn.h b/radio/src/translations/cn.h index f338756d2e4..4f144dc0653 100644 --- a/radio/src/translations/cn.h +++ b/radio/src/translations/cn.h @@ -216,7 +216,7 @@ #if defined(PCBFRSKY) #define TR_ENTER "[ENTER]" -#elif defined(PCBNV14) +#elif defined(PCBNV14) || defined(PCBPL18) #define TR_ENTER "[NEXT]" #else #define TR_ENTER "[MENU]" @@ -1032,6 +1032,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] to select file" #define TR_BL_FLASH_KEY "Hold [R TRIM] long to flash" #define TR_BL_EXIT_KEY " [L TRIM] to exit" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/cz.h b/radio/src/translations/cz.h index aa001fff4e2..a3e8df750a3 100644 --- a/radio/src/translations/cz.h +++ b/radio/src/translations/cz.h @@ -229,7 +229,7 @@ #if defined(PCBTARANIS) || defined(PCBHORUS) #define TR_ENTER "[ENTER]" -#elif defined(PCBNV14) +#elif defined(PCBNV14) || defined(PCBPL18) #define TR_ENTER "[DALŠÍ]" #else #define TR_ENTER "[MENU]" @@ -330,7 +330,7 @@ #define TR_SLOWUP TR3("Zpomalení(+)", "Zpomal(\176)", "Zpomalení(\176)") #define TR_MIXES "MIXER" #define TR_CV "K" -#if defined(PCBNV14) +#if defined(PCBNV14) || defined(PCBPL18) #define TR_GV "GP" #else #define TR_GV TR("G", "GP") @@ -1053,6 +1053,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] pro vybrani souboru" #define TR_BL_FLASH_KEY "Drzet dlouze [R TRIM] pro nahrani" #define TR_BL_EXIT_KEY " [L TRIM] pro ukonceni" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/da.h b/radio/src/translations/da.h index 6b234030acb..ecffd00d5e1 100644 --- a/radio/src/translations/da.h +++ b/radio/src/translations/da.h @@ -1046,6 +1046,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] for at bruge fil" #define TR_BL_FLASH_KEY "[R TRIM] lang til for at starte" #define TR_BL_EXIT_KEY "[L TRIM] for at forlade" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/de.h b/radio/src/translations/de.h index 9b1697762e1..e406ceabaf6 100644 --- a/radio/src/translations/de.h +++ b/radio/src/translations/de.h @@ -220,7 +220,7 @@ #if defined(PCBFRSKY) #define TR_ENTER "[ENTER]" -#elif defined(PCBNV14) +#elif defined(PCBNV14) || defined(PCBPL18) #define TR_ENTER "[NEXT]" #else #define TR_ENTER "[MENU]" @@ -321,7 +321,7 @@ #define TR_SLOWUP "Langs.Up" #define TR_MIXES "MISCHER" #define TR_CV "KV" -#if defined(PCBNV14) +#if defined(PCBNV14) || defined(PCBPL18) #define TR_GV "GV" #else #define TR_GV TR("G", "GV") @@ -1034,6 +1034,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] um Datei auszuwählen" #define TR_BL_FLASH_KEY "Halte [R TRIM] gedrückt, zum schreiben" #define TR_BL_EXIT_KEY " [L TRIM] zum beenden" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // Taranis Info Zeile Anzeigen diff --git a/radio/src/translations/en.h b/radio/src/translations/en.h index 05e9267a613..43750aa4d8f 100644 --- a/radio/src/translations/en.h +++ b/radio/src/translations/en.h @@ -220,7 +220,7 @@ #if defined(PCBFRSKY) #define TR_ENTER "[ENTER]" -#elif defined(PCBNV14) +#elif defined(PCBNV14) || defined(PCBPL18) #define TR_ENTER "[NEXT]" #else #define TR_ENTER "[MENU]" @@ -320,7 +320,7 @@ #define TR_SLOWUP "Slow up" #define TR_MIXES "MIXES" #define TR_CV "CV" -#if defined(PCBNV14) +#if defined(PCBNV14) || defined(PCBPL18) #define TR_GV "GV" #else #define TR_GV TR("G", "GV") @@ -1042,6 +1042,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] to select file" #define TR_BL_FLASH_KEY "Hold [R TRIM] long to flash" #define TR_BL_EXIT_KEY " [L TRIM] to exit" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/es.h b/radio/src/translations/es.h index 71d1448c879..254c9866112 100644 --- a/radio/src/translations/es.h +++ b/radio/src/translations/es.h @@ -216,7 +216,7 @@ #if defined(PCBTARANIS) || defined(PCBHORUS) #define TR_ENTER "[ENTER]" -#elif defined(PCBNV14) +#elif defined(PCBNV14) || defined(PCBPL18) #define TR_ENTER "[NEXT]" #else #define TR_ENTER "[MENU]" @@ -318,7 +318,7 @@ #define TR_SLOWUP "Subir lento" #define TR_MIXES "MIXES" #define TR_CV "CV" -#if defined(PCBNV14) +#if defined(PCBNV14) || defined(PCBPL18) #define TR_GV "GV" #else #define TR_GV TR("G", "GV") @@ -1044,6 +1044,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] to select file" #define TR_BL_FLASH_KEY "Hold [R TRIM] long to flash" #define TR_BL_EXIT_KEY " [L TRIM] to exit" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/fi.h b/radio/src/translations/fi.h index acc72488422..6814f004e32 100644 --- a/radio/src/translations/fi.h +++ b/radio/src/translations/fi.h @@ -1057,6 +1057,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] to select file" #define TR_BL_FLASH_KEY "Hold [R TRIM] long to flash" #define TR_BL_EXIT_KEY " [L TRIM] to exit" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/fr.h b/radio/src/translations/fr.h index 490924f143d..c72e0d68ab3 100644 --- a/radio/src/translations/fr.h +++ b/radio/src/translations/fr.h @@ -226,7 +226,7 @@ #if defined(PCBFRSKY) #define TR_ENTER "[ENTER]" -#elif defined(PCBNV14) +#elif defined(PCBNV14) || defined(PCBPL18) #define TR_ENTER "[SUIVANT]" #else #define TR_ENTER "[MENU]" @@ -327,7 +327,7 @@ #define TR_SLOWUP "Ralenti haut" #define TR_MIXES "MIXEUR" #define TR_CV "CV" -#if defined(PCBNV14) +#if defined(PCBNV14) || defined(PCBPL18) #define TR_GV "VG" #else #define TR_GV TR("G", "VG") @@ -1058,6 +1058,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] pour sélect. fichier" #define TR_BL_FLASH_KEY "Appui long [R TRIM] pour flasher" #define TR_BL_EXIT_KEY " [L TRIM] pour quitter" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/he.h b/radio/src/translations/he.h index 234335035be..a2c47087b76 100644 --- a/radio/src/translations/he.h +++ b/radio/src/translations/he.h @@ -1050,6 +1050,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] to select file" #define TR_BL_FLASH_KEY "Hold [R TRIM] long to flash" #define TR_BL_EXIT_KEY " [L TRIM] ליציאה" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/it.h b/radio/src/translations/it.h index 0b87268d50b..2489dd2f376 100644 --- a/radio/src/translations/it.h +++ b/radio/src/translations/it.h @@ -220,7 +220,7 @@ #if defined(PCBFRSKY) #define TR_ENTER "[ENTER]" -#elif defined(PCBNV14) +#elif defined(PCBNV14) || defined(PCBPL18) #define TR_ENTER "[NEXT]" #else #define TR_ENTER "[MENU]" @@ -320,7 +320,7 @@ #define TR_SLOWUP "Rall.Su" #define TR_MIXES "MIXER" #define TR_CV "CV" -#if defined(PCBNV14) +#if defined(PCBNV14) || defined(PCBPL18) #define TR_GV "GV" #else #define TR_GV TR("G", "GV") @@ -1041,6 +1041,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] per scegliere il file" #define TR_BL_FLASH_KEY "Tener premuto [R TRIM] per scrivere" #define TR_BL_EXIT_KEY " [L TRIM] per uscire" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/jp.h b/radio/src/translations/jp.h index 1e961499e0a..540897e2037 100644 --- a/radio/src/translations/jp.h +++ b/radio/src/translations/jp.h @@ -1037,6 +1037,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] to select file" #define TR_BL_FLASH_KEY "Hold [R TRIM] long to flash" #define TR_BL_EXIT_KEY " [L TRIM] to exit" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/nl.h b/radio/src/translations/nl.h index afe22cb2a53..e7850c53634 100644 --- a/radio/src/translations/nl.h +++ b/radio/src/translations/nl.h @@ -217,7 +217,7 @@ #if defined(PCBFRSKY) #define TR_ENTER "[ENTER]" -#elif defined(PCBNV14) +#elif defined(PCBNV14) || defined(PCBPL18) #define TR_ENTER "[NEXT]" #else #define TR_ENTER "[MENU]" @@ -317,7 +317,7 @@ #define TR_SLOWUP "Langz.Up" #define TR_MIXES "MIXER" #define TR_CV "CV" -#if defined(PCBNV14) +#if defined(PCBNV14) || defined(PCBPL18) #define TR_GV "GV" #else #define TR_GV TR("G", "GV") @@ -1049,6 +1049,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] to select file" #define TR_BL_FLASH_KEY "Hold [R TRIM] long to flash" #define TR_BL_EXIT_KEY " [L TRIM] to exit" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/pl.h b/radio/src/translations/pl.h index 7dcb4acd8c1..0ddc68d059c 100644 --- a/radio/src/translations/pl.h +++ b/radio/src/translations/pl.h @@ -216,7 +216,7 @@ #if defined(PCBTARANIS) || defined(PCBHORUS) #define TR_ENTER "[ENTER]" -#elif defined(PCBNV14) +#elif defined(PCBNV14) || defined(PCBPL18) #define TR_ENTER "[NEXT]" #else #define TR_ENTER "[MENU]" @@ -318,7 +318,7 @@ #define TR_SLOWUP "Spowoln.(+)" #define TR_MIXES "MIKSERY" #define TR_CV "Kr" -#if defined(PCBNV14) +#if defined(PCBNV14) || defined(PCBPL18) #define TR_GV "ZG" #else #define TR_GV TR("G", "ZG") @@ -1039,6 +1039,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] aby wybrac plik" #define TR_BL_FLASH_KEY "Przytrzymaj [R TRIM] aby flashowac" #define TR_BL_EXIT_KEY " [L TRIM] aby wyjsc" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/pt.h b/radio/src/translations/pt.h index 2000191a1e8..44d38b0295b 100644 --- a/radio/src/translations/pt.h +++ b/radio/src/translations/pt.h @@ -223,7 +223,7 @@ #if defined(PCBFRSKY) #define TR_ENTER "[ENTER]" -#elif defined(PCBNV14) +#elif defined(PCBNV14) || defined(PCBPL18) #define TR_ENTER "[NEXT]" #else #define TR_ENTER "[MENU]" @@ -323,7 +323,7 @@ #define TR_SLOWUP "Slow up" #define TR_MIXES "MIXES" #define TR_CV "CV" -#if defined(PCBNV14) +#if defined(PCBNV14) || defined(PCBPL18) #define TR_GV "GV" #else #define TR_GV TR("G", "GV") @@ -1045,6 +1045,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] to select file" #define TR_BL_FLASH_KEY "Hold [R TRIM] long to flash" #define TR_BL_EXIT_KEY " [L TRIM] to exit" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/ru.h b/radio/src/translations/ru.h index eff4b3afc01..9679e3aa863 100644 --- a/radio/src/translations/ru.h +++ b/radio/src/translations/ru.h @@ -1044,6 +1044,16 @@ #define TR_BL_SELECT_KEY "[П ТРИМ] для выбора файла" #define TR_BL_FLASH_KEY "Удерживайте [П ТРИМ] для прошивки" #define TR_BL_EXIT_KEY "[Л ТРИМ] для выхода" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/se.h b/radio/src/translations/se.h index 5af95224792..c3b427a1ecb 100644 --- a/radio/src/translations/se.h +++ b/radio/src/translations/se.h @@ -1071,6 +1071,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] foer att vaelja fil" #define TR_BL_FLASH_KEY "Tryck [R TRIM] foer att flasha" #define TR_BL_EXIT_KEY " [L TRIM] för att avsluta" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/src/translations/tw.h b/radio/src/translations/tw.h index c589312a46e..0792092d191 100644 --- a/radio/src/translations/tw.h +++ b/radio/src/translations/tw.h @@ -1037,6 +1037,16 @@ #define TR_BL_SELECT_KEY "[R TRIM] to select file" #define TR_BL_FLASH_KEY "Hold [R TRIM] long to flash" #define TR_BL_EXIT_KEY " [L TRIM] to exit" +#elif defined(PCBPL18) + // Bootloader PL18 specific - Ascii only + #define TR_BL_RF_USB_ACCESS "RF USB access" + #define TR_BL_ERASE_INT_FLASH "Erase Internal Flash Storage" + #define TR_BL_ERASE_FLASH "Erase Flash Storage" + #define TR_BL_ERASE_FLASH_MSG "This may take up to 200s" + #define TR_BL_SELECT_KEY " [TR4 Dn] to select file" + #define TR_BL_FLASH_KEY " Hold [TR4 Dn] long to flash" + #define TR_BL_ERASE_KEY " Hold [TR4 Dn] long to erase" + #define TR_BL_EXIT_KEY " [TR4 Up] to exit" #endif // About screen diff --git a/radio/util/hw_defs/hal_keys.jinja b/radio/util/hw_defs/hal_keys.jinja index 499a41a397c..15b563d94e3 100644 --- a/radio/util/hw_defs/hal_keys.jinja +++ b/radio/util/hw_defs/hal_keys.jinja @@ -14,14 +14,11 @@ const char* const _key_labels[] = { {% endfor %} }; -constexpr uint32_t _defined_keys = +constexpr uint32_t _defined_keys = 0 {% for key in keys %} - {% if loop.last %} - (1 << {{ key.key }}); - {% else %} - (1 << {{ key.key }}) | - {% endif %} + | (1 << {{ key.key }}) {% endfor %} +; constexpr uint8_t _n_keys = {{ keys | length }}; constexpr uint8_t _n_trims = {{ trims | length }}; diff --git a/radio/util/hw_defs/legacy_names.py b/radio/util/hw_defs/legacy_names.py index 77f21d27c08..a313326a791 100644 --- a/radio/util/hw_defs/legacy_names.py +++ b/radio/util/hw_defs/legacy_names.py @@ -338,6 +338,142 @@ } } }, + { + "targets": { + "pl18" + }, + "inputs": { + "LH": { + "yaml": "Rud" + }, + "LV": { + "yaml": "Ele" + }, + "RV": { + "yaml": "Thr" + }, + "RH": { + "yaml": "Ail" + }, + "P1": { + "yaml": "POT1", + "lua": "s1", + "label": "S1", + "short_label": "1", + "description": "Potentiometer 1" + }, + "P2": { + "yaml": "POT2", + "lua": "s2", + "label": "S2", + "short_label": "2", + "description": "Potentiometer 2" + }, + "P3": { + "yaml": "POT3", + "lua": "s3", + "label": "S3", + "short_label": "3", + "description": "Potentiometer 3" + }, + "SL1": { + "yaml": "LS", + "lua": "ls", + "label": "LS", + "short_label": "L", + "description": "Left slider" + }, + "SL2": { + "yaml": "RS", + "lua": "rs", + "label": "RS", + "short_label": "R", + "description": "Right slider" + }, + } + }, + { + "targets": { + "pl18ev" + }, + "inputs": { + "LH": { + "yaml": "Rud" + }, + "LV": { + "yaml": "Ele" + }, + "RV": { + "yaml": "Thr" + }, + "RH": { + "yaml": "Ail" + }, + "P1": { + "yaml": "POT1", + "lua": "s1", + "label": "S1", + "short_label": "1", + "description": "Potentiometer 1" + }, + "P2": { + "yaml": "POT2", + "lua": "s2", + "label": "S2", + "short_label": "2", + "description": "Potentiometer 2" + }, + "P3": { + "yaml": "POT3", + "lua": "s3", + "label": "S3", + "short_label": "3", + "description": "Potentiometer 3" + }, + "SL1": { + "yaml": "LS", + "lua": "ls", + "label": "LS", + "short_label": "L", + "description": "Left slider" + }, + "SL2": { + "yaml": "RS", + "lua": "rs", + "label": "RS", + "short_label": "R", + "description": "Right slider" + }, + "EXT1": { + "yaml": "EXT1", + "lua": "ext1", + "label": "EXT1", + "short_label": "E1", + "description": "Ext 1" + }, + "EXT2": { + "yaml": "EXT2", + "lua": "ext2", + "label": "EXT2", + "short_label": "E2", + "description": "Ext 2" + }, + "EXT3": { + "yaml": "EXT3", + "lua": "ext3", + "label": "EXT3", + "short_label": "E3", + "description": "Ext 3" + }, + "EXT4": { + "yaml": "EXT4", + "lua": "ext4", + "label": "EXT4", + "short_label": "E4", + "description": "Ext 4" + } + } + }, { "targets": {"t20"}, "inputs": { diff --git a/radio/util/hw_defs/pot_config.py b/radio/util/hw_defs/pot_config.py index 637ac16717e..f80cd6fa142 100644 --- a/radio/util/hw_defs/pot_config.py +++ b/radio/util/hw_defs/pot_config.py @@ -14,6 +14,24 @@ "P1": {"default": "POT_CENTER"}, "P2": {"default": "POT_CENTER"} }, + "pl18": { + "P1": {"default": "POT"}, + "P2": {"default": "POT"}, + "P3": {"default": "POT"}, + "SL1": {"default": "SLIDER"}, + "SL2": {"default": "SLIDER"} + }, + "pl18ev": { + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "POT"}, + "P3": {"default": "POT_CENTER"}, + "SL1": {"default": "SLIDER"}, + "SL2": {"default": "SLIDER"}, + "EXT1": {"default": "POT_CENTER"}, + "EXT2": {"default": "POT_CENTER"}, + "EXT3": {"default": "MULTIPOS"}, + "EXT4": {"default": "MULTIPOS"} + }, "mt12": { "P1": {"default": "POT"}, "P2": {"default": "POT"}, diff --git a/radio/util/hw_defs/stm32_adc_inputs.jinja b/radio/util/hw_defs/stm32_adc_inputs.jinja index b30ce7d2c2c..fc1103021f5 100644 --- a/radio/util/hw_defs/stm32_adc_inputs.jinja +++ b/radio/util/hw_defs/stm32_adc_inputs.jinja @@ -6,6 +6,7 @@ static const stm32_adc_input_t _ADC_inputs[] = { {% for input in adc_inputs.inputs %} { + // {{ input.name }} // ADC_INPUT_{{ input.type }}, {{ input.gpio if input.gpio else 'nullptr' }}, {{ input.pin if input.gpio else '0' }}, diff --git a/radio/util/hw_defs/switch_config.py b/radio/util/hw_defs/switch_config.py index 3d7cb80cd25..de3461f53ca 100644 --- a/radio/util/hw_defs/switch_config.py +++ b/radio/util/hw_defs/switch_config.py @@ -29,6 +29,28 @@ "SG": { "default": "3POS" }, "SH": { "default": "TOGGLE" } }, + "pl18": { + "SA": { "default": "2POS" }, + "SB": { "default": "3POS" }, + "SC": { "default": "2POS" }, + "SD": { "default": "3POS" }, + "SE": { "default": "3POS" }, + "SF": { "default": "2POS" }, + "SG": { "default": "3POS" }, + "SH": { "default": "TOGGLE" } + }, + "pl18ev": { + "SA": { "default": "2POS" }, + "SB": { "default": "3POS" }, + "SC": { "default": "2POS" }, + "SD": { "default": "3POS" }, + "SE": { "default": "3POS" }, + "SF": { "default": "2POS" }, + "SG": { "default": "3POS" }, + "SH": { "default": "3POS" }, + "SI": { "default": "3POS" }, + "SJ": { "default": "3POS" } + }, "lr3pro": { # left side "SA": {"default": "3POS", "display": [0, 0]}, diff --git a/tools/build-companion.sh b/tools/build-companion.sh index 128fba24c5c..d1dc928b62e 100755 --- a/tools/build-companion.sh +++ b/tools/build-companion.sh @@ -70,7 +70,7 @@ declare -a simulator_plugins=(x9lite x9lites tlite tpro lr3pro x9d x9dp x9dp2019 x9e xlite xlites - nv14 + nv14 pl18 pl18ev x10 x10-access x12s t16 t18 tx16s) @@ -170,6 +170,12 @@ do commando8) BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=COMMANDO8" ;; + pl18) + BUILD_OPTIONS+="-DPCB=PL18" + ;; + pl18ev) + BUILD_OPTIONS+="-DPCB=PL18 -DPCBREV=PL18EV" + ;; *) echo "Unknown target: $target_name" exit 1 diff --git a/tools/build-flysky.py b/tools/build-flysky.py index c6c60ad74d0..22be920ccee 100644 --- a/tools/build-flysky.py +++ b/tools/build-flysky.py @@ -9,15 +9,10 @@ boards = { - "NV14": { - "PCB": "NV14", - "DEFAULT_MODE": "1", - }, - "EL18": { - "PCB": "NV14", - "PCBREV": "EL18", - "DEFAULT_MODE": "1", - }, + "NV14": { "PCB": "NV14" }, + "EL18": { "PCB": "NV14", "PCBREV": "EL18" }, + "PL18": { "PCB": "PL18" }, + "PL18EV": { "PCB": "PL18", "PCBREV": "PL18EV" }, } translations = [ diff --git a/tools/build-gh.sh b/tools/build-gh.sh index aa154af5959..16f0aa512ba 100755 --- a/tools/build-gh.sh +++ b/tools/build-gh.sh @@ -191,6 +191,12 @@ do el18) BUILD_OPTIONS+="-DPCB=NV14 -DPCBREV=EL18" ;; + pl18) + BUILD_OPTIONS+="-DPCB=PL18" + ;; + pl18ev) + BUILD_OPTIONS+="-DPCB=PL18 -DPCBREV=PL18EV" + ;; commando8) BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=COMMANDO8" ;; diff --git a/tools/commit-tests.sh b/tools/commit-tests.sh index 66ea77e8516..1d9c9634f6d 100755 --- a/tools/commit-tests.sh +++ b/tools/commit-tests.sh @@ -148,6 +148,12 @@ do el18) BUILD_OPTIONS+="-DPCB=NV14 -DPCBREV=EL18" ;; + pl18) + BUILD_OPTIONS+="-DPCB=PL18" + ;; + pl18ev) + BUILD_OPTIONS+="-DPCB=PL18 -DPCBREV=PL18EV" + ;; commando8) BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=COMMANDO8" ;; diff --git a/tools/generate-yaml.sh b/tools/generate-yaml.sh index aa1b04c33ec..cb834c7a05f 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;x9d;x9dp;x9e;x9lite;xlites;x7;tpro;t20"} +: ${FLAVOR:="tx16s;x12s;nv14;pl18;x9d;x9dp;x9e;x9lite;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"} @@ -110,6 +110,9 @@ do nv14) BUILD_OPTIONS+="-DPCB=NV14" ;; + pl18) + BUILD_OPTIONS+="-DPCB=PL18" + ;; commando8) BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=COMMANDO8" ;;