From 866ee0a92e59676c1868410fe3d0d6224c9bb633 Mon Sep 17 00:00:00 2001 From: richardclli Date: Wed, 5 Aug 2026 12:57:46 +0800 Subject: [PATCH] feat(v12): support for HelloRadioSky V12 (#7114) Co-authored-by: Peter Feerick <5500713+pfeerick@users.noreply.github.com> Co-authored-by: radiosky <839034809@qq.com> Co-authored-by: Claude Sonnet 5 --- .github/workflows/build_fw.yml | 2 + .github/workflows/nightly.yml | 1 + companion/src/firmwares/boardjson.cpp | 4 +- companion/src/firmwares/boards.cpp | 17 + companion/src/firmwares/boards.h | 13 +- .../src/firmwares/edgetx/yaml_moduledata.cpp | 17 +- companion/src/firmwares/moduledata.h | 2 +- .../src/firmwares/opentx/opentxinterface.cpp | 7 + companion/src/generaledit/hardware.cpp | 11 +- companion/src/modeledit/setup_module.cpp | 12 +- fw.json | 1 + radio/src/CMakeLists.txt | 4 +- radio/src/boards/generic_stm32/i2c_bus.cpp | 22 + radio/src/boards/generic_stm32/rgb_6pos.cpp | 5 +- .../helloradio-h750/backlight_driver.cpp | 94 ++ radio/src/boards/helloradio-h750/board.cpp | 419 +++++++ radio/src/boards/helloradio-h750/board.h | 272 +++++ .../helloradio-h750/extflash_driver.cpp | 154 +++ .../boards/helloradio-h750/extflash_driver.h | 27 + .../boards/helloradio-h750/haptic_driver.cpp | 60 + .../src/boards/helloradio-h750/key_driver.cpp | 33 + .../src/boards/helloradio-h750/lcd_driver.cpp | 423 +++++++ radio/src/boards/helloradio-h750/lcd_driver.h | 77 ++ .../boards/helloradio-h750/sdram_driver.cpp | 252 ++++ .../src/boards/helloradio-h750/system_clock.c | 116 ++ .../src/boards/helloradio-h750/system_clock.h | 23 + .../boards/helloradio-h750/touch_driver.cpp | 291 +++++ .../src/boards/helloradio-h750/touch_driver.h | 110 ++ .../helloradio-h750/usb_charger_driver.cpp | 52 + radio/src/boards/hw_defs/v12.json | 371 +++--- radio/src/datastructs.h | 4 + radio/src/datastructs_private.h | 9 +- radio/src/edgetx.cpp | 35 +- radio/src/gui/128x64/model_setup.cpp | 29 +- radio/src/gui/128x64/view_main.cpp | 4 +- radio/src/gui/colorlcd/CMakeLists.txt | 4 +- radio/src/gui/colorlcd/bitmaps.cpp | 4 +- radio/src/gui/colorlcd/bitmaps.h | 2 +- .../colorlcd/module/crossfire_settings.cpp | 2 - ..._settings.cpp => ext_antenna_settings.cpp} | 30 +- ...pxx1_settings.h => ext_antenna_settings.h} | 4 +- .../src/gui/colorlcd/module/module_setup.cpp | 23 +- radio/src/gui/colorlcd/radio/hw_intmodule.cpp | 26 +- radio/src/gui/colorlcd/widgets/radio_info.cpp | 9 +- .../src/gui/common/stdlcd/radio_hardware.cpp | 22 +- radio/src/gui/gui_common.cpp | 117 +- radio/src/gui/gui_common.h | 10 +- radio/src/hal/rotary_encoder.h | 2 +- radio/src/pulses/modules_helpers.cpp | 2 +- radio/src/storage/yaml/CMakeLists.txt | 2 + radio/src/storage/yaml/yaml_datastructs.cpp | 2 + .../storage/yaml/yaml_datastructs_128x64.cpp | 2 +- .../src/storage/yaml/yaml_datastructs_c14.cpp | 2 +- .../src/storage/yaml/yaml_datastructs_f16.cpp | 2 +- .../storage/yaml/yaml_datastructs_gx12.cpp | 2 +- .../storage/yaml/yaml_datastructs_nb4p.cpp | 2 +- .../storage/yaml/yaml_datastructs_nv14.cpp | 2 +- .../storage/yaml/yaml_datastructs_pa01.cpp | 2 +- .../storage/yaml/yaml_datastructs_pl18.cpp | 2 +- .../storage/yaml/yaml_datastructs_pl18u.cpp | 2 +- .../storage/yaml/yaml_datastructs_st16.cpp | 2 +- .../src/storage/yaml/yaml_datastructs_t15.cpp | 2 +- .../storage/yaml/yaml_datastructs_t15pro.cpp | 2 +- .../src/storage/yaml/yaml_datastructs_t20.cpp | 2 +- .../src/storage/yaml/yaml_datastructs_t22.cpp | 2 +- .../storage/yaml/yaml_datastructs_tpro.cpp | 2 +- .../storage/yaml/yaml_datastructs_tx15.cpp | 2 +- .../yaml/yaml_datastructs_tx16smk3.cpp | 2 +- .../src/storage/yaml/yaml_datastructs_v12.cpp | 1048 +++++++++++++++++ .../src/storage/yaml/yaml_datastructs_x10.cpp | 5 +- .../src/storage/yaml/yaml_datastructs_x9d.cpp | 2 +- .../yaml/yaml_datastructs_x9dp2019.cpp | 2 +- .../src/storage/yaml/yaml_datastructs_x9e.cpp | 2 +- .../storage/yaml/yaml_datastructs_xlite.cpp | 5 +- .../storage/yaml/yaml_datastructs_xlites.cpp | 5 +- .../targets/common/arm/stm32/pwr_driver.cpp | 16 +- .../common/arm/stm32/stm32_i2c_driver.cpp | 2 +- .../common/arm/stm32/stm32_i2c_driver.h | 4 +- .../targets/common/arm/stm32/usb_driver.cpp | 7 +- radio/src/targets/horus/CMakeLists.txt | 8 + radio/src/targets/horus/hal.h | 5 +- radio/src/targets/taranis/CMakeLists.txt | 15 - radio/src/targets/taranis/hal.h | 26 +- radio/src/targets/taranis/lcd_driver_spi.cpp | 20 +- radio/src/targets/taranis/usb_descriptor.h | 4 - radio/src/targets/v12/CMakeLists.txt | 195 +++ radio/src/targets/v12/hal.h | 272 +++++ radio/src/targets/v12/usb_descriptor.h | 26 + radio/util/build-firmware.py | 3 +- radio/util/hw_defs/legacy_names.py | 41 +- tools/boards.py | 3 +- tools/build-common.sh | 2 +- tools/generate-yaml.sh | 2 +- 93 files changed, 4582 insertions(+), 406 deletions(-) create mode 100644 radio/src/boards/helloradio-h750/backlight_driver.cpp create mode 100644 radio/src/boards/helloradio-h750/board.cpp create mode 100644 radio/src/boards/helloradio-h750/board.h create mode 100644 radio/src/boards/helloradio-h750/extflash_driver.cpp create mode 100644 radio/src/boards/helloradio-h750/extflash_driver.h create mode 100644 radio/src/boards/helloradio-h750/haptic_driver.cpp create mode 100644 radio/src/boards/helloradio-h750/key_driver.cpp create mode 100644 radio/src/boards/helloradio-h750/lcd_driver.cpp create mode 100644 radio/src/boards/helloradio-h750/lcd_driver.h create mode 100644 radio/src/boards/helloradio-h750/sdram_driver.cpp create mode 100644 radio/src/boards/helloradio-h750/system_clock.c create mode 100644 radio/src/boards/helloradio-h750/system_clock.h create mode 100644 radio/src/boards/helloradio-h750/touch_driver.cpp create mode 100644 radio/src/boards/helloradio-h750/touch_driver.h create mode 100644 radio/src/boards/helloradio-h750/usb_charger_driver.cpp rename radio/src/gui/colorlcd/module/{pxx1_settings.cpp => ext_antenna_settings.cpp} (61%) rename radio/src/gui/colorlcd/module/{pxx1_settings.h => ext_antenna_settings.h} (85%) create mode 100644 radio/src/storage/yaml/yaml_datastructs_v12.cpp create mode 100644 radio/src/targets/v12/CMakeLists.txt create mode 100644 radio/src/targets/v12/hal.h create mode 100644 radio/src/targets/v12/usb_descriptor.h diff --git a/.github/workflows/build_fw.yml b/.github/workflows/build_fw.yml index 5609098fc..425bf9df9 100644 --- a/.github/workflows/build_fw.yml +++ b/.github/workflows/build_fw.yml @@ -49,6 +49,7 @@ jobs: - pa01 - t22 - c14 + - v12 container: image: ghcr.io/edgetx/edgetx-dev:latest volumes: @@ -95,6 +96,7 @@ jobs: - tx16smk3;t14;t15pro - t22 - c14 + - v12 container: image: ghcr.io/edgetx/edgetx-dev:latest volumes: diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 1c21ac414..06a78f093 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -40,6 +40,7 @@ jobs: - c14 - tx15 - t15pro + - v12 container: image: ghcr.io/edgetx/edgetx-dev:latest volumes: diff --git a/companion/src/firmwares/boardjson.cpp b/companion/src/firmwares/boardjson.cpp index 460391252..67cc5c076 100644 --- a/companion/src/firmwares/boardjson.cpp +++ b/companion/src/firmwares/boardjson.cpp @@ -92,7 +92,9 @@ void BoardJson::afterLoadFixups(Board::Type board, InputsTable * inputs, Switche { // TODO json files do not contain gyro defs // Radio cmake directive IMU is currently used - if (IS_TARANIS_XLITES(board) || IS_FAMILY_HORUS_OR_T16(board) || IS_RADIOMASTER_TX15(board)) { + if (IS_TARANIS_XLITES(board) || IS_FAMILY_HORUS_OR_T16(board) || + IS_RADIOMASTER_TX15(board) || IS_RADIOMASTER_TX16SMK3(board) || + IS_FLYSKY_PA01(board)) { if (getInputIndex(inputs, "TILT_X", Board::LVT_TAG) < 0) { InputDefn defn; defn.type = AIT_FLEX; diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp index 456f20dbf..eba1055bf 100644 --- a/companion/src/firmwares/boards.cpp +++ b/companion/src/firmwares/boards.cpp @@ -163,6 +163,8 @@ uint32_t Boards::getFourCC(Type board) return 0x4C78746F; case BOARD_IFLIGHT_COMMANDO14: return 0x4F78746F; + case BOARD_HELLORADIOSKY_V12: + return 0x4478746F; case BOARD_HELLORADIOSKY_V14: return 0x4D78746F; case BOARD_HELLORADIOSKY_V14LCD: @@ -234,6 +236,7 @@ int Boards::getEEpromSize(Board::Type board) case BOARD_FLYSKY_ST16: case BOARD_IFLIGHT_COMMANDO14: case BOARD_FATFISH_F16: + case BOARD_HELLORADIOSKY_V12: case BOARD_HELLORADIOSKY_V16: return 0; default: @@ -300,6 +303,7 @@ int Boards::getFlashSize(Type board) case BOARD_FLYSKY_ST16: // 8MB SDRAM case BOARD_IFLIGHT_COMMANDO14: // 8MB SDRAM case BOARD_FATFISH_F16: + case BOARD_HELLORADIOSKY_V12: // 8MB SDRAM case BOARD_HELLORADIOSKY_V16: return FSIZE_2MB; case BOARD_UNKNOWN: @@ -342,6 +346,13 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) IS_TARANIS_X9DP_2019(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_FAMILY_PL18(board)); + case HasExternalAntenna: + return IS_FAMILY_HORUS(board) || IS_TARANIS_XLITE(board) || + getCapability(board, HasHardwareAntennaSwitch); + + case HasHardwareAntennaSwitch: + return IS_HELLORADIOSKY_V12(board); + case HasIMU: return (IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS(board) || IS_RADIOMASTER_TX15(board)); @@ -675,6 +686,8 @@ QString Boards::getBoardName(Board::Type board) return "Fatfish F16"; case BOARD_HELLORADIOSKY_V16: return "HelloRadioSky V16"; + case BOARD_HELLORADIOSKY_V12: + return "HelloRadioSky V12"; case BOARD_HELLORADIOSKY_V14: return "HelloRadioSky V14"; case BOARD_HELLORADIOSKY_V14LCD: @@ -784,6 +797,7 @@ int Boards::getDefaultInternalModules(Board::Type board) case BOARD_BETAFPV_LR3PRO: case BOARD_FATFISH_F16: + case BOARD_HELLORADIOSKY_V12: case BOARD_HELLORADIOSKY_V14: case BOARD_HELLORADIOSKY_V14LCD: case BOARD_HELLORADIOSKY_V16: @@ -827,6 +841,7 @@ int Boards::getDefaultInternalModules(Board::Type board) void Boards::getBattRange(Board::Type board, int& vmin, int& vmax, unsigned int& vwarn) { switch (board) { + case BOARD_HELLORADIOSKY_V12: case BOARD_HELLORADIOSKY_V14: case BOARD_HELLORADIOSKY_V14LCD: case BOARD_JUMPER_T12: @@ -903,6 +918,8 @@ int Boards::getDefaultExternalModuleSize(Board::Type board) if (getCapability(board, HasColorLcd)) { if (IS_FLYSKY_EL18(board)) return EXTMODSIZE_BOTH; + else if (IS_HELLORADIOSKY_V12(board)) + return EXTMODSIZE_SMALL; else return EXTMODSIZE_STD; } diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index 66996096b..c157d8d07 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -100,6 +100,7 @@ namespace Board { BOARD_HELLORADIOSKY_V14, BOARD_HELLORADIOSKY_V14LCD, BOARD_IFLIGHT_COMMANDO14, + BOARD_HELLORADIOSKY_V12, BOARD_TYPE_COUNT, BOARD_TYPE_MAX = BOARD_TYPE_COUNT - 1 }; @@ -232,7 +233,9 @@ namespace Board { HasBlingLEDS, HasBluetooth, HasColorLcd, + HasExternalAntenna, HasExternalModuleSupport, + HasHardwareAntennaSwitch, HasIMU, HasInternalGPS, HasInternalModuleSupport, @@ -656,6 +659,11 @@ inline bool IS_FATFISH_F16(Board::Type board) return board == Board::BOARD_FATFISH_F16; } +inline bool IS_HELLORADIOSKY_V12(Board::Type board) +{ + return board == Board::BOARD_HELLORADIOSKY_V12; +} + inline bool IS_HELLORADIOSKY_V14(Board::Type board) { return board == Board::BOARD_HELLORADIOSKY_V14; @@ -674,6 +682,7 @@ inline bool IS_HELLORADIOSKY_V16(Board::Type board) inline bool IS_FAMILY_T16(Board::Type board) { return board == Board::BOARD_FATFISH_F16 || + board == Board::BOARD_HELLORADIOSKY_V12 || board == Board::BOARD_HELLORADIOSKY_V16 || board == Board::BOARD_JUMPER_T15 || board == Board::BOARD_JUMPER_T15PRO || @@ -850,10 +859,6 @@ inline bool HAS_LARGE_LCD(Board::Type board) return IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS_X9(board); } -inline bool HAS_EXTERNAL_ANTENNA(Board::Type board) -{ - return (IS_FAMILY_HORUS(board) || IS_FAMILY_T16(board) || (IS_TARANIS_XLITE(board) && !IS_TARANIS_XLITES(board))); -} inline bool IS_TARANIS_X9DP_2019(Board::Type board) { diff --git a/companion/src/firmwares/edgetx/yaml_moduledata.cpp b/companion/src/firmwares/edgetx/yaml_moduledata.cpp index 3d77ae941..2fcbdd7c7 100644 --- a/companion/src/firmwares/edgetx/yaml_moduledata.cpp +++ b/companion/src/firmwares/edgetx/yaml_moduledata.cpp @@ -138,6 +138,13 @@ static const YamlLookupTable failsafeLut = { { FAILSAFE_RECEIVER, "RECEIVER" }, }; +static const YamlLookupTable moduleAntennaModeLut = { + { GeneralSettings::ANTENNA_MODE_INTERNAL, "MODE_INTERNAL" }, + { GeneralSettings::ANTENNA_MODE_ASK, "MODE_ASK" }, + { GeneralSettings::ANTENNA_MODE_PER_MODEL, "MODE_PER_MODEL" }, + { GeneralSettings::ANTENNA_MODE_EXTERNAL, "MODE_EXTERNAL" }, +}; + static int exportPpmDelay(int delay) { return (delay - 300) / 50; } static int importPpmDelay(int delay) { return 300 + 50 * delay; } @@ -197,6 +204,8 @@ Node convert::encode(const ModuleData& rhs) node["channelsStart"] = rhs.channelsStart; node["channelsCount"] = rhs.channelsCount; node["failsafeMode"] = LookupValue(failsafeLut, rhs.failsafeMode); + if (rhs.antennaMode) + node["antennaMode"] = LookupValue(moduleAntennaModeLut, rhs.antennaMode); Node mod; switch (protocol) { @@ -207,7 +216,6 @@ Node convert::encode(const ModuleData& rhs) pxx["power"] = rhs.pxx.power; // pxx["receiverTelemetryOff"] = rhs.pxx.receiverTelemetryOff; // pxx["receiverHigherChannels"] = rhs.pxx.receiverHigherChannels; - pxx["antennaMode"] = rhs.pxx.antennaMode; mod["pxx"] = pxx; } break; case PULSES_ACCESS_ISRM: @@ -362,6 +370,8 @@ bool convert::decode(const Node& node, ModuleData& rhs) node["channelsStart"] >> rhs.channelsStart; node["channelsCount"] >> rhs.channelsCount; node["failsafeMode"] >> failsafeLut >> rhs.failsafeMode; + if (node["antennaMode"]) + node["antennaMode"] >> moduleAntennaModeLut >> rhs.antennaMode; if (node["mod"]) { const Node& mod = node["mod"]; @@ -386,7 +396,10 @@ bool convert::decode(const Node& node, ModuleData& rhs) pxx["power"] >> rhs.pxx.power; // pxx["receiverTelemetryOff"] >> rhs.pxx.receiverTelemetryOff; // pxx["receiverHigherChannels"] >> rhs.pxx.receiverHigherChannels; - pxx["antennaMode"] >> rhs.pxx.antennaMode; + // Migration: legacy raw-int antennaMode, only if not already set + if (!node["antennaMode"] && pxx["antennaMode"]) { + pxx["antennaMode"] >> rhs.antennaMode; + } } else if (mod["sbus"]) { mod["sbus"]["refreshRate"] >> rhs.ppm.frameLength; } else if (mod["pxx2"]) { diff --git a/companion/src/firmwares/moduledata.h b/companion/src/firmwares/moduledata.h index fea3c14c8..103a05917 100644 --- a/companion/src/firmwares/moduledata.h +++ b/companion/src/firmwares/moduledata.h @@ -138,6 +138,7 @@ class ModuleData { unsigned int channelsStart; int channelsCount; unsigned int failsafeMode; + int antennaMode; // false = internal antenna, true = external antenna struct PPM { int delay; @@ -191,7 +192,6 @@ class ModuleData { unsigned int power; // 0 10 mW, 1 100 mW, 2 500 mW, 3 1W bool receiverTelemetryOff; // false = receiver telem enabled bool receiverHigherChannels; // false = pwm out 1-8, true 9-16 - int antennaMode; // false = internal antenna, true = external antenna } pxx; struct GHOST { diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 1a53e3c23..e0f745229 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -495,6 +495,13 @@ void registerOpenTxFirmwares() registerOpenTxFirmware(firmware); addOpenTxRfOptions(firmware, EU + FLEX); + /* HelloRadioSky V12 board */ + firmware = new OpenTxFirmware(FIRMWAREID("v12"), Firmware::tr("HelloRadioSky V12"), BOARD_HELLORADIOSKY_V12); + addOpenTxCommonOptions(firmware); + addOpenTxFontOptions(firmware); + registerOpenTxFirmware(firmware); + addOpenTxRfOptions(firmware, FLEX); + /* HelloRadioSky V14 board */ firmware = new OpenTxFirmware(FIRMWAREID("v14"), Firmware::tr("HelloRadioSky V14"), BOARD_HELLORADIOSKY_V14); addOpenTxCommonOptions(firmware); diff --git a/companion/src/generaledit/hardware.cpp b/companion/src/generaledit/hardware.cpp index 58377f12c..88ed7d16d 100644 --- a/companion/src/generaledit/hardware.cpp +++ b/companion/src/generaledit/hardware.cpp @@ -279,7 +279,7 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings antennaMode->setField(generalSettings.antennaMode, this); params->append(antennaMode); - if (!(m_internalModule == MODULE_TYPE_XJT_PXX1 && HAS_EXTERNAL_ANTENNA(board))) { + if (!((m_internalModule == MODULE_TYPE_XJT_PXX1 || Boards::getCapability(board, Board::HasHardwareAntennaSwitch)) && Boards::getCapability(board, Board::HasExternalAntenna))) { antennaLabel->setVisible(false); antennaMode->setVisible(false); } @@ -418,11 +418,10 @@ void HardwarePanel::on_internalModuleChanged() internalModuleBaudRate->setVisible(false); } - if (m_internalModule == MODULE_TYPE_XJT_PXX1 && HAS_EXTERNAL_ANTENNA(board)) { - antennaLabel->setVisible(true); - antennaMode->setVisible(true); - } - else { + if ((m_internalModule == MODULE_TYPE_XJT_PXX1 || Boards::getCapability(board, Board::HasHardwareAntennaSwitch)) && Boards::getCapability(board, Board::HasExternalAntenna)) { + antennaLabel->setVisible(true); + antennaMode->setVisible(true); + } else { antennaLabel->setVisible(false); antennaMode->setVisible(false); } diff --git a/companion/src/modeledit/setup_module.cpp b/companion/src/modeledit/setup_module.cpp index 712403cff..806b6b6dc 100644 --- a/companion/src/modeledit/setup_module.cpp +++ b/companion/src/modeledit/setup_module.cpp @@ -331,7 +331,7 @@ void ModulePanel::update() if (isInternalModule(moduleIdx) && (protocol==PULSES_PXX_XJT_X16 || protocol==PULSES_PXX_XJT_D8 || protocol==PULSES_PXX_XJT_LR12) && - HAS_EXTERNAL_ANTENNA(board) && generalSettings.antennaMode == GeneralSettings::ANTENNA_MODE_PER_MODEL) + Boards::getCapability(board, Board::HasExternalAntenna) && generalSettings.antennaMode == GeneralSettings::ANTENNA_MODE_PER_MODEL) mask |= MASK_ANTENNA; if (protocol == PULSES_ACCESS_ISRM && module.channelsCount == 8) mask |= MASK_RF_RACING_MODE; @@ -353,6 +353,10 @@ void ModulePanel::update() mask |= MASK_CSRF_ARMING_TRIGGER; ui->crsfArmingTrigger->setCurrentIndex(ui->crsfArmingTrigger->findData(RawSwitch(module.crsf.crsfArmingTrigger).toValue())); } + if (isInternalModule(moduleIdx) && + Boards::getCapability(board, Board::HasHardwareAntennaSwitch) && + generalSettings.antennaMode == GeneralSettings::ANTENNA_MODE_PER_MODEL) + mask |= MASK_ANTENNA; break; case PULSES_GHOST: mask |= MASK_CHANNELS_RANGE | MASK_GHOST | MASK_BAUDRATE; @@ -467,9 +471,9 @@ void ModulePanel::update() ui->ppmFrameLength->setValue(22.5 + ((double)module.ppm.frameLength) * 0.5); if (mask & MASK_ANTENNA) { - if (module.pxx.antennaMode == GeneralSettings::ANTENNA_MODE_PER_MODEL) - module.pxx.antennaMode = GeneralSettings::ANTENNA_MODE_INTERNAL; - ui->antennaMode->setField(module.pxx.antennaMode, this); + if (module.antennaMode == GeneralSettings::ANTENNA_MODE_PER_MODEL) + module.antennaMode = GeneralSettings::ANTENNA_MODE_INTERNAL; + ui->antennaMode->setField(module.antennaMode, this); ui->antennaLabel->show(); ui->antennaMode->show(); } diff --git a/fw.json b/fw.json index 21403470a..41124d8db 100644 --- a/fw.json +++ b/fw.json @@ -16,6 +16,7 @@ ["FrSky X9D Plus 2019", "x9dp2019-"], ["FrSky X9E", "x9e-"], ["FrSky X9E Hall", "x9e-hall-"], + ["HelloRadioSky V12", "v12-"], ["HelloRadioSky V14", "v14-"], ["HelloRadioSky V14LCD", "v14lcd-"], ["HelloRadioSky V16", "v16-"], diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 3607d1319..f12cb998a 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 PL18 T15PRO ST16 PA01 TX15 TX16SMK3 T22) +set(PCB_TYPES X9LITE X9LITES X7 XLITE XLITES X9D X9D+ X9E X10 X12S PL18 T15PRO ST16 PA01 TX15 TX16SMK3 T22 V12) set(RADIO_LANGUAGES CN CZ DA DE EN ES FI FR HE HU IT JP KO NL PL PT RU SE SK TW UA) set(TTS_LANGUAGES CN CZ DA DE EN ES FI FR HE HU IT JP KO NL PL PT RU SE SK TW UA) @@ -99,6 +99,8 @@ elseif(PCB STREQUAL ST16) include(targets/c14/CMakeLists.txt) elseif(PCB STREQUAL PA01) include(targets/pa01/CMakeLists.txt) +elseif(PCB STREQUAL V12) + include(targets/v12/CMakeLists.txt) elseif(PCB STREQUAL TX15) include(targets/tx15/CMakeLists.txt) elseif(PCB STREQUAL TX16SMK3) diff --git a/radio/src/boards/generic_stm32/i2c_bus.cpp b/radio/src/boards/generic_stm32/i2c_bus.cpp index 4160ea1cc..a2ebfefbd 100644 --- a/radio/src/boards/generic_stm32/i2c_bus.cpp +++ b/radio/src/boards/generic_stm32/i2c_bus.cpp @@ -58,6 +58,16 @@ static const stm32_i2c_hw_def_t _i2c2 = { }; #endif +#if defined(I2C_B4) +static const stm32_i2c_hw_def_t _i2c4 = { + .I2Cx = I2C_B4, + .SCL_GPIO = (gpio_t)I2C_B4_SCL_GPIO, + .SDA_GPIO = (gpio_t)I2C_B4_SDA_GPIO, + .GPIO_AF = I2C_B4_GPIO_AF, + .set_pwr = nullptr, +}; +#endif + int i2c_init(etx_i2c_bus_t bus) { #if defined(I2C_B1) @@ -72,6 +82,12 @@ int i2c_init(etx_i2c_bus_t bus) } #endif +#if defined(I2C_B4) + if (bus == I2C_Bus_4) { + return stm32_i2c_init(I2C_Bus_4, I2C_B4_CLK_RATE, &_i2c4); + } +#endif + return -1; } @@ -89,6 +105,12 @@ int i2c_deinit(etx_i2c_bus_t bus) } #endif +#if defined(I2C_B4) + if (bus == I2C_Bus_4) { + return stm32_i2c_deinit(I2C_Bus_4); + } +#endif + return -1; } diff --git a/radio/src/boards/generic_stm32/rgb_6pos.cpp b/radio/src/boards/generic_stm32/rgb_6pos.cpp index fafbdadff..587360d19 100644 --- a/radio/src/boards/generic_stm32/rgb_6pos.cpp +++ b/radio/src/boards/generic_stm32/rgb_6pos.cpp @@ -48,7 +48,10 @@ static uint8_t _last_adc_state = 0; static volatile uint8_t _six_pos_state = 0; -void sixPosUpdateFromAdc() +// Called whenever the sticky 6POS position changes. Boards that need to +// map position to a switch-expander state (e.g. FUNCTION_SWITCHES) can +// override this to react to position changes without polling adcValues[]. +__attribute__((weak)) void sixPosUpdateFromAdc() { uint16_t* values = getAnalogValues(); uint16_t adcValue = values[SIXPOS_SWITCH_INDEX]; diff --git a/radio/src/boards/helloradio-h750/backlight_driver.cpp b/radio/src/boards/helloradio-h750/backlight_driver.cpp new file mode 100644 index 000000000..b87dc4a26 --- /dev/null +++ b/radio/src/boards/helloradio-h750/backlight_driver.cpp @@ -0,0 +1,94 @@ +/* + * 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/gpio.h" +#include "stm32_gpio.h" +#include "stm32_timer.h" +#include "stm32_pulse_driver.h" + +#include "edgetx_types.h" +#include "board.h" + +#include "globals.h" + +static const stm32_pulse_timer_t _bl_timer = { + .GPIO = (gpio_t)BACKLIGHT_GPIO, + .GPIO_Alternate = BACKLIGHT_GPIO_AF, + .TIMx = BACKLIGHT_TIMER, + .TIM_Freq = BACKLIGHT_TIMER_FREQ, + .TIM_Channel = BACKLIGHT_TIMER_CHANNEL, + .TIM_IRQn = (IRQn_Type)-1, + .DMAx = nullptr, + .DMA_Stream = 0, + .DMA_Channel = 0, + .DMA_IRQn = (IRQn_Type)-1, + .DMA_TC_CallbackPtr = nullptr, +}; + +void backlightLowInit() +{ + gpio_init(BACKLIGHT_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW); + gpio_clear(BACKLIGHT_GPIO); +} + +void backlightInit() +{ + stm32_pulse_init(&_bl_timer, 10000); + stm32_pulse_config_output(&_bl_timer, true, LL_TIM_OCMODE_PWM1, 100); + LL_TIM_SetAutoReload(_bl_timer.TIMx, 100); + LL_TIM_EnableCounter(_bl_timer.TIMx); +} + +uint8_t lastDutyCycle = 0; + +void backlightEnable(uint8_t dutyCycle) +{ + stm32_pulse_set_cmp_val(&_bl_timer, dutyCycle); + + // TODO: removed until QSPI & LCD SPI are split + // 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/boards/helloradio-h750/board.cpp b/radio/src/boards/helloradio-h750/board.cpp new file mode 100644 index 000000000..51088d162 --- /dev/null +++ b/radio/src/boards/helloradio-h750/board.cpp @@ -0,0 +1,419 @@ +/* + * 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_gpio.h" +#include "stm32_i2c_driver.h" +#include "stm32_hal.h" +#include "stm32_spi.h" + +#include "flash_driver.h" +#include "extflash_driver.h" + +#include "board.h" +#include "boards/generic_stm32/module_ports.h" +#include "boards/generic_stm32/rgb_leds.h" + +#include "stm32_switch_driver.h" +#include "hal/adc_driver.h" +#include "hal/flash_driver.h" +#include "hal/trainer_driver.h" +#include "hal/rotary_encoder.h" +#include "hal/switch_driver.h" +#include "hal/abnormal_reboot.h" +#include "hal/watchdog_driver.h" +#include "hal/usb_driver.h" +#include "hal/gpio.h" + +#include "globals.h" +#include "sdcard.h" +#include "debug.h" +#include "keys.h" + +#include "flysky_gimbal_driver.h" +#include "timers_driver.h" + +#include "bitmapbuffer.h" +#include "colors.h" + + +// #include "touch_driver.h" + +#include + +// common ADC driver +extern const etx_hal_adc_driver_t _adc_driver; + +#if defined(SIXPOS_SWITCH_INDEX) + +#if defined(FUNCTION_SWITCHES) + +extern const stm32_switch_t* boardGetSwitchDef(uint8_t idx); +extern SwitchHwPos stm32_switch_get_position(const stm32_switch_t* sw); + +extern uint8_t isSwitch3Pos(uint8_t idx); +struct _adckey_switches_expander { + uint8_t state; +}; +// Bitmask of all 6 function switch bits +#define FS_ALL_BITS 0x3F + +// For each 6POS position (0=none, 1-6=SW1-SW6): bit of the active switch, +// inverted so active switch pin reads low (DOWN) like real PCA95xx hardware. +// position 0 (none): all bits set = all UP +// position N: all bits set except SW_N's bit = SW_N is DOWN +static uint8_t _pos_to_state(uint8_t pos) +{ + if (pos == 0) return FS_ALL_BITS; + uint8_t active_bit = (1 << (pos - 1)); + return FS_ALL_BITS & ~active_bit; +} +static _adckey_switches_expander _adckey_switches = { FS_ALL_BITS }; + +// Called whenever the sticky 6POS position changes. Boards that need to +// map position to a switch-expander state (e.g. FUNCTION_SWITCHES) can +// override this to react to position changes without polling adcValues[]. +void sixPosUpdateFromAdc() +{ + uint16_t* values = getAnalogValues(); + uint16_t adcValue = values[SIXPOS_SWITCH_INDEX]; + + uint8_t current = 0; + if (adcValue > 3800) current = 1; + else if (adcValue > 3100) current = 2; + else if (adcValue > 2300) current = 3; + else if (adcValue > 1500) current = 4; + else if (adcValue > 1000) current = 5; + else if (adcValue > 400) current = 6; + + static uint8_t lastSeen = 0; + static uint8_t debounce = 0; + static uint8_t sixPosState = 0; + + if (current != lastSeen) { + lastSeen = current; + debounce = 2; // require this many more stable samples before committing + } else if (debounce > 0) { + if (--debounce == 0) { + // Switch state always reflects the true debounced position + _adckey_switches.state = _pos_to_state(current); + if (current != 0) { + // Indicator value stays sticky on the last active position + sixPosState = current; + } + } + } + + values[SIXPOS_SWITCH_INDEX] = sixPosState ? (4096 / 5) * (7 - sixPosState) : 0; +} + +static SwitchHwPos _get_switch_pos(uint8_t idx) +{ + SwitchHwPos pos = SWITCH_HW_UP; + + const stm32_switch_t* def = boardGetSwitchDef(idx); + uint8_t state = _adckey_switches.state; + + if (def->isCustomSwitch) { + if ((state & def->Pin_high) == 0) { + return SWITCH_HW_DOWN; + } else { + return SWITCH_HW_UP; + } + } + else if (!def->Pin_low) { + // 2POS switch + if ((state & def->Pin_high) != 0) { + pos = SWITCH_HW_DOWN; + } + } else { + bool hi = state & def->Pin_high; + bool lo = state & def->Pin_low; + + if(!isSwitch3Pos(idx)) + { + // Switch not declared as 3POS installed in a 3POS HW + if (!(hi && lo)) { + pos = SWITCH_HW_DOWN; + } + } else if (hi && lo) { + pos = SWITCH_HW_MID; + } else if (!hi && lo) { + pos = SWITCH_HW_DOWN; + } + } + return pos; +} + +static SwitchHwPos _get_fs_switch_pos(uint8_t idx) +{ + const stm32_switch_t* def = boardGetSwitchDef(idx); + uint8_t state = _adckey_switches.state; + if ((state & def->Pin_high) == 0) { + return SWITCH_HW_DOWN; + } else { + return SWITCH_HW_UP; + } +} + +bool boardIsCustomSwitch(uint8_t idx); + +SwitchHwPos boardSwitchGetPosition(uint8_t idx) +{ + if (boardIsCustomSwitch(idx)) { + return _get_fs_switch_pos(idx); + } else if (boardGetSwitchDef(idx)->GPIOx_high != nullptr) { + return stm32_switch_get_position(boardGetSwitchDef(idx)); + } else { + return _get_switch_pos(idx); + } +} + +#endif + +#endif + +static void led_strip_off() +{ + rgbLedClearAll(); + rgbLedColorApply(); +} + +void INTERNAL_MODULE_ON() +{ + gpio_set(INTMODULE_PWR_GPIO); +} + +void INTERNAL_MODULE_OFF() +{ + gpio_clear(INTMODULE_PWR_GPIO); +} + +void EXTERNAL_MODULE_ON() +{ + gpio_set(EXTMODULE_PWR_GPIO); +} + +void EXTERNAL_MODULE_OFF() +{ + gpio_clear(EXTMODULE_PWR_GPIO); +} + +void INTMODULE_ANTSEL_EXT() +{ + gpio_set(INTMODULE_ANTSEL_GPIO); +} + +void INTMODULE_ANTSEL_INT() +{ + gpio_clear(INTMODULE_ANTSEL_GPIO); +} + +void boardBLEarlyInit() +{ + timersInit(); + usbChargerInit(); +} + +void boardBLPreJump() +{ + ExtFLASH_Init(); + SDRAM_Init(); + + // Stop 1ms timer + MS_TIMER->CR1 &= ~TIM_CR1_CEN; +} + +void boardBLInit() +{ + ExtFLASH_Init(); + SDRAM_Init(); + + // register external FLASH for DFU + usbRegisterDFUMedia((void*)extflash_dfu_media); + + // register internal & external FLASH for UF2 + flashRegisterDriver(FLASH_BANK1_BASE, BOOTLOADER_SIZE, &stm32_flash_driver); + flashRegisterDriver(QSPI_BASE, 8 * 1024 * 1024, &extflash_driver); +} + +void USBCharger(uint32_t usbchgstatus) +{ + // USB Charger init code can be added here if needed + static uint32_t usbchgmode=0; + + if(usbchgstatus>10){ + rgbLedClearAll(); + rgbLedColorApply(); + return; + } + switch (++usbchgmode) { + case 1: + rgbSetLedColor(0, SIXPOS_LED_RED, SIXPOS_LED_GREEN, SIXPOS_LED_BLUE); + break; + case 2: + rgbSetLedColor(1, SIXPOS_LED_RED, SIXPOS_LED_GREEN, SIXPOS_LED_BLUE); + break; + case 3: + rgbSetLedColor(2, SIXPOS_LED_RED, SIXPOS_LED_GREEN, SIXPOS_LED_BLUE); + break; + case 4: + rgbSetLedColor(3, SIXPOS_LED_RED, SIXPOS_LED_GREEN, SIXPOS_LED_BLUE); + break; + case 5: + rgbSetLedColor(4, SIXPOS_LED_RED, SIXPOS_LED_GREEN, SIXPOS_LED_BLUE); + break; + case 6: + rgbSetLedColor(5, SIXPOS_LED_RED, SIXPOS_LED_GREEN, SIXPOS_LED_BLUE); + break; + case 7: + usbchgmode=0; + rgbLedClearAll(); + break; + default: + break; + } + rgbLedColorApply(); +} + +void boardInit() +{ + // enable interrupts + __enable_irq(); + + ledInit(); + boardInitModulePorts(); + + pwrInit(); + delaysInit(); + timersInit(); + + usbChargerInit(); + gpio_set(LED_BLUE_GPIO); + + ExtFLASH_InitRuntime(); + + // register internal & external FLASH for UF2 + flashRegisterDriver(FLASH_BANK1_BASE, BOOTLOADER_SIZE, &stm32_flash_driver); + flashRegisterDriver(QSPI_BASE, QSPI_FLASH_SIZE, &extflash_driver); + + usbInit(); + + rgbLedInit(); + led_strip_off(); + +#if !defined(DEBUG_SEGGER_RTT) + + static uint32_t usbchgstatus=0; + + // This is needed to prevent radio from starting when usb is plugged to charge + if (usbPlugged()) { + while (usbPlugged() && !pwrPressed()) {//charging loop + delay_ms(500); + USBCharger(usbchgstatus); + if (IS_UCHARGER_ACTIVE()) { + /* code */ + ledRed(); + usbchgstatus=0; + } + else{ + ledGreen(); + usbchgstatus++; + } + } + if (!pwrPressed()) { + pwrOff(); + // Wait power to drain + while (true) { + } + } + } +#endif + + rgbLedInit(); + led_strip_off(); + + keysInit(); + switchInit(); + rotaryEncoderInit(); + // touchPanelInit(); + audioInit(); + adcInit(&_adc_driver); + hapticInit(); + + rtcInit(); // RTC must be initialized before rambackupRestore() is called +} + +extern void rtcDisableBackupReg(); + + +void boardOff() +{ + lcdOff(); + + while (pwrPressed()) { + WDG_RESET(); + } + + SysTick->CTRL = 0; // turn off systick + + // Shutdown the Haptic + hapticDone(); + + rtcDisableBackupReg(); + +#if !defined(BOOT) + rgbLedClearAll(); + while (pwrPressed()) { + WDG_RESET(); + } + if (IS_UCHARGER_ACTIVE()||usbPlugged()) + { + while (pwrPressed()) { + WDG_RESET(); + } +// RTC->BKP0R = SOFTRESET_REQUEST; + NVIC_SystemReset(); + } +#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_CR1_MRUDS) && defined(PWR_CR1_LPUDS) && defined(PWR_CR1_FPDS) + MODIFY_REG(PWR->CR1, (PWR_CR1_PDDS | PWR_CR1_LPDS | PWR_CR1_FPDS | PWR_CR1_LPUDS | PWR_CR1_MRUDS), PDMode); +#elif defined(PWR_CR_MRLVDS) && defined(PWR_CR_LPLVDS) && defined(PWR_CR_FPDS) + MODIFY_REG(PWR->CR1, (PWR_CR1_PDDS | PWR_CR1_LPDS | PWR_CR1_FPDS | PWR_CR1_LPLVDS | PWR_CR1_MRLVDS), PDMode); +#else +// MODIFY_REG(PWR->CR1, (PWR_CR1_P_PDDS| PWR_CR1_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) { + + } +} diff --git a/radio/src/boards/helloradio-h750/board.h b/radio/src/boards/helloradio-h750/board.h new file mode 100644 index 000000000..5c3f98631 --- /dev/null +++ b/radio/src/boards/helloradio-h750/board.h @@ -0,0 +1,272 @@ +/* + * 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 "edgetx_constants.h" + +#include "board_common.h" +#include "hal.h" +#include "hal/serial_port.h" +#include "hal/watchdog_driver.h" + +#define FLASHSIZE 0x800000 +#define FLASH_PAGESIZE 256 +#define BOOTLOADER_SIZE 0x10000 +#define BOOTLOADER_ADDRESS 0x08000000 +#define FIRMWARE_ADDRESS 0x90000000 +#define FIRMWARE_LEN(fsize) (fsize) +#define FIRMWARE_MAX_LEN FLASHSIZE +#define APP_START_ADDRESS (uint32_t)(FIRMWARE_ADDRESS) + +#define BOOTLOADER_KEYS 0x42 + +#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 +extern "C" void SDRAM_Init(); + +// Pulses driver +#if !defined(SIMU) + +void INTMODULE_ANTSEL_EXT(); +void INTMODULE_ANTSEL_INT(); + +void INTERNAL_MODULE_ON(); +void INTERNAL_MODULE_OFF(); +void EXTERNAL_MODULE_ON(); +void EXTERNAL_MODULE_OFF(); +#define EXTERNAL_MODULE_PWR_OFF EXTERNAL_MODULE_OFF +#define BLUETOOTH_MODULE_ON() gpio_clear(BLUETOOTH_ON_GPIO) +#define BLUETOOTH_MODULE_OFF() gpio_set(BLUETOOTH_ON_GPIO) +#define IS_INTERNAL_MODULE_ON() (gpio_read(INTMODULE_PWR_GPIO) ? 1 : 0) +#define IS_EXTERNAL_MODULE_ON() (gpio_read(EXTMODULE_PWR_GPIO) ? 1 : 0) + +#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(FUNCTION_SWITCHES) +#define NUM_FUNCTIONS_SWITCHES 6 +#define NUM_FUNCTIONS_GROUPS 3 +#define DEFAULT_FS_CONFIG \ + (SWITCH_2POS << 10) + (SWITCH_2POS << 8) + (SWITCH_2POS << 6) + \ + (SWITCH_2POS << 4) + (SWITCH_2POS << 2) + (SWITCH_2POS << 0) + +#define DEFAULT_FS_GROUPS \ + (1 << 10) + (1 << 8) + (1 << 6) + (1 << 4) + (1 << 2) + \ + (1 << 0) // Set all FS to group 1 to act like a 6pos + +#define DEFAULT_FS_STARTUP_CONFIG \ + ((FS_START_PREVIOUS << 10) + (FS_START_PREVIOUS << 8) + \ + (FS_START_PREVIOUS << 6) + (FS_START_PREVIOUS << 4) + \ + (FS_START_PREVIOUS << 2) + \ + (FS_START_PREVIOUS << 0)) // keep last state by default + +#else +#define NUM_FUNCTIONS_SWITCHES 0 +#endif + +#define NUM_TRIMS 8 +#define DEFAULT_STICK_DEADZONE 2 + +#define BATTERY_WARN 74 // 7.4V +#define BATTERY_MIN 70 // 6.8V +#define BATTERY_MAX 86 // 8.6V + +// --- MOSFET ---- R1 --- MCU +// |__ R2 --- GND +// +#define VBAT_DIV_R1 100 // kOhms +#define VBAT_DIV_R2 56 // kOhms +#define VBAT_MOSFET_DROP 10 // * 10mV + +// #define BATTERY_DIVIDER 1211 // = 2047 * 165k / (165k + 680k) * 10 / 3.3V + +#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(__cplusplus) && !defined(SIMU) +} +#endif + + +#define IS_UCHARGER_ACTIVE() !gpio_read(UCHARGER_GPIO) ? 1 : 0 +#define IS_UCHARGER_CHARGE_END_ACTIVE() gpio_read(UCHARGER_CHARGE_END_GPIO) ? 0 : 1 +#define ENABLE_UCHARGER() bsp_output_set(BSP_CHARGE_EN); +#define DISABLE_UCHARGER() bsp_output_clear(BSP_CHARGE_EN) + +// Audio driver +class stm32_spi_t; +struct AudioConfig_t +{ + stm32_spi_t* spi; + void (*setMuteHigh)(); + void (*setMuteLow)(); + void (*setResetHigh)(); + void (*setResetLow)(); +}; +void audioInit(); +void audioConsumeCurrentBuffer(); + +#define audioDisableIrq() // interrupts must stay enabled on Horus +#define audioEnableIrq() // interrupts must stay enabled on Horus +#define setSampleRate(freq) +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(); + +// USB Charger +#if defined(USB_CHARGER) +void usbChargerInit(); +bool usbChargerLed(); +#endif + +#endif // _BOARD_H_ + diff --git a/radio/src/boards/helloradio-h750/extflash_driver.cpp b/radio/src/boards/helloradio-h750/extflash_driver.cpp new file mode 100644 index 000000000..2354db468 --- /dev/null +++ b/radio/src/boards/helloradio-h750/extflash_driver.cpp @@ -0,0 +1,154 @@ +#include "extflash_driver.h" + +#include "stm32_hal.h" +#include "stm32_qspi.h" + +#include "board.h" + +#define QSPI_NOR_PAGE_SIZE 256 + +int32_t ExtFLASH_Init() +{ + if (stm32_qspi_nor_init() != 0) { + return -1; + } + + return stm32_qspi_nor_memory_mapped(); +} + +void ExtFLASH_InitRuntime() { stm32_qspi_no_init_runtime(); } + +// +// ETX HAL flash interface +// + +static uint32_t extflash_get_size_kb() +{ + return QSPI_FLASH_SIZE / 1024; +} + +static uint32_t extflash_get_sector(uint32_t address) +{ + address -= QSPI_BASE; + return address / (64 * 1024); +} + +static uint32_t extflash_get_sector_size(uint32_t sector) +{ + (void)sector; + return (64 * 1024); +} + +static int extflash_erase_sector(uint32_t address) +{ + address -= QSPI_BASE; + return stm32_qspi_nor_erase_sector(address); +} + +static int extflash_program(uint32_t address, void* data, uint32_t len) +{ + address -= QSPI_BASE; + + int ret = 0; + while (len > 0) { + uint32_t size = (len > QSPI_NOR_PAGE_SIZE) ? QSPI_NOR_PAGE_SIZE : len; + ret = stm32_qspi_nor_program(address, data, size); + if (ret != 0) break; + len -= size; + address += size; + data = (uint8_t*)data + size; + } + + return ret; +} + +static int extflash_read(uint32_t address, void* data, uint32_t len) +{ + address -= QSPI_BASE; + return stm32_qspi_nor_read(address, data, len); +} + +const etx_flash_driver_t extflash_driver = { + .get_size_kb = extflash_get_size_kb, + .get_sector = extflash_get_sector, + .get_sector_size = extflash_get_sector_size, + .erase_sector = extflash_erase_sector, + .program = extflash_program, + .read = extflash_read, +}; + +#if defined(BOOT) +// +// USB DFU interface +// +#include "usbd_dfu.h" + +#define MEDIA_DESC_STR "@External Flash /0x90000000/128*064Kg" + +static uint16_t extflash_dfu_init() +{ + return USBD_OK; +} + +static uint16_t extflash_dfu_deinit() +{ + return USBD_OK; +} + +static uint16_t extflash_dfu_erase(uint32_t address) +{ + if (extflash_erase_sector(address) < 0) { + return USBD_FAIL; + } + return USBD_OK; +} + +static uint16_t extflash_dfu_write(uint8_t* src, uint8_t* dest, uint32_t len) +{ + if (extflash_program((intptr_t)dest, (void*)src, len) < 0) { + return USBD_FAIL; + } + return USBD_OK; +} + +static uint8_t* extflash_dfu_read(uint8_t* src, uint8_t* dest, uint32_t len) +{ + if (extflash_read((intptr_t)src, (void*)dest, len) < 0) { + return nullptr; + } + return dest; +} + +static uint16_t extflash_dfu_get_status(uint32_t address, uint8_t cmd, uint8_t *buffer) +{ + switch (cmd) { + case DFU_MEDIA_PROGRAM: + buffer[1] = 1; + buffer[2] = 0; + buffer[3] = 0; + break; + + case DFU_MEDIA_ERASE: + default: + buffer[1] = 20; + buffer[2] = 0; + buffer[3] = 0; + break; + } + + return USBD_OK; +} + +const USBD_DFU_MediaTypeDef _extflash_dfu_media = { + .pStrDesc = (uint8_t*)MEDIA_DESC_STR, + .Init = extflash_dfu_init, + .DeInit = extflash_dfu_deinit, + .Erase = extflash_dfu_erase, + .Write = extflash_dfu_write, + .Read = extflash_dfu_read, + .GetStatus = extflash_dfu_get_status, +}; + +const void* extflash_dfu_media = &_extflash_dfu_media; + +#endif // BOOT diff --git a/radio/src/boards/helloradio-h750/extflash_driver.h b/radio/src/boards/helloradio-h750/extflash_driver.h new file mode 100644 index 000000000..22a8b3b77 --- /dev/null +++ b/radio/src/boards/helloradio-h750/extflash_driver.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) EdgeTX + * + * 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 "hal/flash_driver.h" + +extern const etx_flash_driver_t extflash_driver; +extern const void* extflash_dfu_media; + +// init external FLASH hardware +int32_t ExtFLASH_Init(); + +// init only runtime structures +void ExtFLASH_InitRuntime(); diff --git a/radio/src/boards/helloradio-h750/haptic_driver.cpp b/radio/src/boards/helloradio-h750/haptic_driver.cpp new file mode 100644 index 000000000..148312717 --- /dev/null +++ b/radio/src/boards/helloradio-h750/haptic_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 "hal/gpio.h" +#include "stm32_gpio.h" +#include "stm32_timer.h" +#include "stm32_pulse_driver.h" + +#include "board.h" + +#define HAPTIC_TIMER_FREQ 200000000 + +static const stm32_pulse_timer_t _haptic_timer = { + .GPIO = (gpio_t)HAPTIC_GPIO, + .GPIO_Alternate = HAPTIC_GPIO_AF, + .TIMx = HAPTIC_GPIO_TIMER, + .TIM_Freq = HAPTIC_TIMER_FREQ, + .TIM_Channel = LL_TIM_CHANNEL_CH2, + .TIM_IRQn = (IRQn_Type)-1, + .DMAx = nullptr, + .DMA_Stream = 0, + .DMA_Channel = 0, + .DMA_IRQn = (IRQn_Type)-1, + .DMA_TC_CallbackPtr = nullptr, +}; + +void hapticInit(void) +{ + stm32_pulse_init(&_haptic_timer, 10000); + stm32_pulse_config_output(&_haptic_timer, true, LL_TIM_OCMODE_PWM1, 0); + LL_TIM_SetAutoReload(_haptic_timer.TIMx, 100); + LL_TIM_EnableCounter(_haptic_timer.TIMx); +} + +void hapticOn(uint32_t pwmPercent) +{ + if (pwmPercent > 100) pwmPercent = 100; + stm32_pulse_set_cmp_val(&_haptic_timer, pwmPercent); +} + +void hapticOff(void) { hapticOn(0); } +void hapticDone(void) { hapticOff(); } diff --git a/radio/src/boards/helloradio-h750/key_driver.cpp b/radio/src/boards/helloradio-h750/key_driver.cpp new file mode 100644 index 000000000..3577ebb10 --- /dev/null +++ b/radio/src/boards/helloradio-h750/key_driver.cpp @@ -0,0 +1,33 @@ +/* + * 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 "stm32_i2c_driver.h" + +#include "hal.h" +#include "delays_driver.h" +#include "keys.h" + +#include "stm32_keys.inc" +#include "debug.h" diff --git a/radio/src/boards/helloradio-h750/lcd_driver.cpp b/radio/src/boards/helloradio-h750/lcd_driver.cpp new file mode 100644 index 000000000..db167fbe4 --- /dev/null +++ b/radio/src/boards/helloradio-h750/lcd_driver.cpp @@ -0,0 +1,423 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "lcd_driver.h" + +#include "stm32_gpio.h" +#include "stm32_spi.h" + +#include "delays_driver.h" +#include "hal/gpio.h" +#include "lcd.h" + +#include "hal.h" +#include "board.h" + +#define LCD_NRST_HIGH() gpio_set(LCD_NRST) +#define LCD_NRST_LOW() gpio_clear(LCD_NRST) +#define LCD_COMMAND_MODE() gpio_clear(LCD_SPI_RS) +#define LCD_DATA_MODE() gpio_set(LCD_SPI_RS) + +#define CASET 0x2A +#define RASET 0x2B +#define RAMWR 0x2C + +static const stm32_spi_t lcdSpi = { + .SPIx = LCD_SPI, + .SCK = LCD_SPI_CLK, + .MISO = LCD_SPI_MISO, + .MOSI = LCD_SPI_MOSI, + .CS = LCD_SPI_CS, + .DMA = LCD_SPI_DMA, + .txDMA_PeriphRequest = LCD_SPI_TX_DMA, + .rxDMA_PeriphRequest = LCD_SPI_RX_DMA, + .txDMA_Stream = LCD_SPI_TX_DMA_STREAM, + .rxDMA_Stream = LCD_SPI_RX_DMA_STREAM, +}; + +static void* initialFrameBuffer = nullptr; + +static void write_start_end(uint8_t cmd, uint16_t start, uint16_t end) +{ + // big endian format + uint8_t buf[4] = { + (uint8_t)(start >> 8), + (uint8_t)(start & 0xFF), + (uint8_t)(end >> 8), + (uint8_t)(end & 0xFF), + }; + + stm32_spi_select(&lcdSpi); + + LCD_COMMAND_MODE(); + stm32_spi_transfer_byte(&lcdSpi, cmd); + + LCD_DATA_MODE(); + stm32_spi_transfer_bytes(&lcdSpi, (uint8_t *)buf, nullptr, sizeof(buf)); + + stm32_spi_unselect(&lcdSpi); +} + +static inline void set_column_addr(uint16_t xs, uint16_t xe) +{ + write_start_end(CASET, xs, xe); +} + +static inline void set_row_addr(uint16_t ys, uint16_t ye) +{ + write_start_end(RASET, ys, ye); +} + +static void memory_write(const uint16_t* data, uint32_t length) +{ + stm32_spi_select(&lcdSpi); + + LCD_COMMAND_MODE(); + stm32_spi_transfer_byte(&lcdSpi, RAMWR); + + LCD_DATA_MODE(); + stm32_spi_set_data_width(&lcdSpi, LL_SPI_DATAWIDTH_16BIT); + + SCB_CleanDCache_by_Addr((void *)data, length * sizeof(uint16_t)); + stm32_spi_dma_transmit_words(&lcdSpi, data, length); + + stm32_spi_unselect(&lcdSpi); + stm32_spi_set_data_width(&lcdSpi, LL_SPI_DATAWIDTH_8BIT); +} + +static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer, + const rect_t ©_area) +{ + (void)disp_drv; + + // TODO: replace through some smarter mechanism without busy wait + while (!gpio_read(LCD_FMARK)); + + coord_t x1 = copy_area.x; + coord_t x2 = x1 + copy_area.w - 1; + set_column_addr(x1, x2); + + coord_t y1 = copy_area.y; + coord_t y2 = y1 + copy_area.h - 1; + set_row_addr(y1, y2); + + memory_write(buffer, copy_area.w * copy_area.h); + + lcdFlushed(); +} + +lcdSpiInitFucPtr lcdInitFunction; +lcdSpiInitFucPtr lcdOffFunction; +lcdSpiInitFucPtr lcdOnFunction; +uint32_t lcdPixelClock; + +static void lcdSpiConfig(void) +{ + stm32_spi_init(&lcdSpi, LL_SPI_DATAWIDTH_8BIT); + stm32_spi_set_max_baudrate(&lcdSpi, LCD_SPI_BAUD); + + gpio_init(LCD_FMARK, GPIO_IN, GPIO_PIN_SPEED_HIGH); + gpio_init(LCD_NRST, GPIO_OUT, GPIO_PIN_SPEED_HIGH); + gpio_init(LCD_SPI_RS, GPIO_OUT, GPIO_PIN_SPEED_HIGH); +} + +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(120); +} + +static void lcdWriteCommand(uint8_t cmd) +{ + LCD_COMMAND_MODE(); + stm32_spi_select(&lcdSpi); + stm32_spi_transfer_byte(&lcdSpi, cmd); + stm32_spi_unselect(&lcdSpi); +} + +// static void lcdWriteReg(uint8_t reg, uint8_t data) +// { +// LCD_COMMAND_MODE(); +// stm32_spi_select(&lcdSpi); +// stm32_spi_transfer_byte(&lcdSpi, reg); +// LCD_DATA_MODE(); +// stm32_spi_transfer_byte(&lcdSpi, data); +// stm32_spi_unselect(&lcdSpi); +// } + +static void lcdWriteData(uint8_t data) +{ + LCD_DATA_MODE(); + stm32_spi_select(&lcdSpi); + stm32_spi_transfer_byte(&lcdSpi, data); + stm32_spi_unselect(&lcdSpi); +} + +// static uint8_t lcdReadReg(uint8_t reg) +// { +// uint8_t data = 0; +// LCD_COMMAND_MODE(); +// stm32_spi_select(&lcdSpi); +// stm32_spi_transfer_byte(&lcdSpi, reg); +// LCD_DATA_MODE(); +// data = stm32_spi_transfer_byte(&lcdSpi, 0xFF); +// stm32_spi_unselect(&lcdSpi); +// return data; +// } + +extern "C" void lcdSetInitalFrameBuffer(void *fbAddress) +{ + initialFrameBuffer = fbAddress; +} + +static void lcdSetOn(void) { lcdWriteCommand(0x29); } +static void lcdSetOff(void) { lcdWriteCommand(0x28); } + +extern "C" void lcdInit() +{ + // Configure the LCD SPI + RESET pins + lcdSpiConfig(); + stm32_spi_unselect(&lcdSpi); + + // hard reset + lcdReset(); + + // Init command start + lcdWriteCommand( 0xFE ); + lcdWriteCommand( 0xEF ); + + // Display orientation + lcdWriteCommand( 0x36 ); + lcdWriteData( 0x60 ); + + // Color mode + lcdWriteCommand( 0x3A ); + lcdWriteData( 0x05 ); // 16-bit color + + // Display control + lcdWriteCommand( 0x86 ); + lcdWriteData( 0x98 ); + lcdWriteCommand( 0x89 ); + lcdWriteData( 0x33 ); + lcdWriteCommand( 0x8B ); + lcdWriteData( 0x80 ); + lcdWriteCommand( 0x8D ); + lcdWriteData( 0x33 ); + lcdWriteCommand( 0x3A ); + lcdWriteData( 0x05 ); + lcdWriteCommand( 0x8E ); + lcdWriteData( 0x0F ); + + lcdWriteCommand( 0xEC ); + lcdWriteData( 0x33 ); + lcdWriteData( 0x07 ); + lcdWriteData( 0x00 ); + + lcdWriteCommand( 0xED ); + lcdWriteData( 0x18 ); + lcdWriteData( 0x08 ); + + lcdWriteCommand( 0xE8 ); + lcdWriteData( 0x12 ); + lcdWriteData( 0x00 ); + + // Init command ends + lcdWriteCommand( 0xFF ); + lcdWriteCommand( 0x62 ); + + // Display control + lcdWriteCommand( 0x99 ); + lcdWriteData( 0x3E ); + lcdWriteCommand( 0x9D ); + lcdWriteData( 0x4B ); + lcdWriteCommand( 0x98 ); + lcdWriteData( 0x3E ); + lcdWriteCommand( 0x9C ); + lcdWriteData( 0x4B ); + lcdWriteCommand( 0xC3 ); + lcdWriteData( 0x39 ); + lcdWriteCommand( 0xC4 ); + lcdWriteData( 0x29 ); + lcdWriteCommand( 0xC9 ); + lcdWriteData( 0x09 ); + + // Gamma Control + lcdWriteCommand( 0xF0 ); + lcdWriteData( 0x0B ); + lcdWriteData( 0x0C ); + lcdWriteData( 0x07 ); + lcdWriteData( 0x07 ); + lcdWriteData( 0x05 ); + lcdWriteData( 0x22 ); + lcdWriteCommand( 0xF1); + lcdWriteData( 0x42 ); + lcdWriteData( 0x78 ); + lcdWriteData( 0x56 ); + lcdWriteData( 0x1E ); + lcdWriteData( 0x1A ); + lcdWriteData( 0x95 ); + lcdWriteCommand( 0xF2 ); + lcdWriteData( 0x0B ); + lcdWriteData( 0x0C ); + lcdWriteData( 0x07 ); + lcdWriteData( 0x07 ); + lcdWriteData( 0x05 ); + lcdWriteData( 0x44 ); + lcdWriteCommand( 0xF3 ); + lcdWriteData( 0x56 ); + lcdWriteData( 0x92 ); + lcdWriteData( 0x30 ); + lcdWriteData( 0x31 ); + lcdWriteData( 0x35 ); + lcdWriteData( 0x7F ); + + // Display orientation + lcdWriteCommand( 0x36 ); + //lcdWriteData( 0xA0 ); + lcdWriteData( 0x60 ); + + // Display size + lcdWriteCommand( 0x2A ); + lcdWriteData( 0x00 ); + lcdWriteData( 0x00 ); + lcdWriteData( 0x01 ); + lcdWriteData( 0x40 ); + lcdWriteCommand( 0x2B ); + lcdWriteData( 0x00 ); + lcdWriteData( 0x00 ); + lcdWriteData( 0x00 ); + lcdWriteData( 0xF0 ); + + // Invert color + lcdWriteCommand( 0x21 ); + + // Tear on + lcdWriteCommand( 0x35 ); + + // Exit sleep + lcdWriteCommand( 0x11 ); + + + /* + lcdWriteCommand(0x11); + + delay_ms(120); + + lcdWriteCommand(0xB2); + lcdWriteData(0x0C); + lcdWriteData(0x0C); + lcdWriteData(0x00); + lcdWriteData(0x33); + lcdWriteData(0x33); + + lcdWriteCommand(0x35); + lcdWriteData(0x00); + + lcdWriteCommand(0x36); + lcdWriteData(0x60); + + lcdWriteCommand(0x3A); + lcdWriteData(0x05); + + lcdWriteCommand(0xB7); + lcdWriteData(0x35); + + lcdWriteCommand(0xBB); + lcdWriteData(0x34); + + lcdWriteCommand(0xC0); + lcdWriteData(0x2C); + + lcdWriteCommand(0xC2); + lcdWriteData( 0x01); + + lcdWriteCommand(0xC3); + lcdWriteData(0x13);//4.5V + + lcdWriteCommand(0xC4); + lcdWriteData(0x20); + + lcdWriteCommand(0xC6); + lcdWriteData(0x0F); + + lcdWriteCommand(0xD0); + lcdWriteData(0xA4); + lcdWriteData(0xA1); + + lcdWriteCommand(0xD6); + lcdWriteData(0xA1); + + lcdWriteCommand(0xE0); + lcdWriteData(0xD0); + lcdWriteData(0x0A); + lcdWriteData(0x10); + lcdWriteData(0x0C); + lcdWriteData(0x0C); + lcdWriteData(0x18); + lcdWriteData(0x35); + lcdWriteData(0x43); + lcdWriteData(0x4D); + lcdWriteData(0x39); + lcdWriteData(0x13); + lcdWriteData(0x13); + lcdWriteData(0x2D); + lcdWriteData(0x34); + + lcdWriteCommand(0xE1); + lcdWriteData(0xD0); + lcdWriteData(0x05); + lcdWriteData(0x0B); + lcdWriteData(0x06); + lcdWriteData(0x05); + lcdWriteData(0x02); + lcdWriteData(0x35); + lcdWriteData(0x43); + lcdWriteData(0x4D); + lcdWriteData(0x16); + lcdWriteData(0x15); + lcdWriteData(0x15); + lcdWriteData(0x2E); + lcdWriteData(0x32); + + lcdWriteCommand(0x21); + + lcdWriteCommand(0x29); + + lcdWriteCommand(0x2C); */ + + lcdSetOn(); + // Init LCD RAM + memory_write((const uint16_t*)initialFrameBuffer, LCD_W * LCD_H); + + lcdOnFunction = lcdSetOn; + lcdOffFunction = lcdSetOff; + + lcdSetFlushCb(startLcdRefresh); +} diff --git a/radio/src/boards/helloradio-h750/lcd_driver.h b/radio/src/boards/helloradio-h750/lcd_driver.h new file mode 100644 index 000000000..b3e0fa6a5 --- /dev/null +++ b/radio/src/boards/helloradio-h750/lcd_driver.h @@ -0,0 +1,77 @@ +/* + * 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_CS_GPIO, LCD_SPI_CS_GPIO_PIN) +//#define LCD_CS_LOW() LL_GPIO_ResetOutputPin(LCD_SPI_CS_GPIO, LCD_SPI_CS_GPIO_PIN) + +#define LCD_SCK_HIGH() LL_GPIO_SetOutputPin(LCD_SPI_GPIO, LCD_SPI_SCK_GPIO_PIN) +#define LCD_SCK_LOW() LL_GPIO_ResetOutputPin(LCD_SPI_GPIO, LCD_SPI_SCK_GPIO_PIN) + +#define LCD_MOSI_HIGH() LL_GPIO_SetOutputPin(LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN) +#define LCD_MOSI_LOW() LL_GPIO_ResetOutputPin(LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN) + +#define LCD_MOSI_AS_INPUT() SET_IO_INPUT( LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN ) +#define LCD_MOSI_AS_OUTPUT() SET_IO_OUTPUT( LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN ) + +#define LCD_READ_DATA_PIN() LL_GPIO_IsInputPinSet(LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN) + + +#define HORIZONTAL_SYNC_WIDTH ( 4 ) +#define HORIZONTAL_BACK_PORCH ( 24 ) +#define HORIZONTAL_FRONT_PORCH ( 140 - HORIZONTAL_BACK_PORCH ) +#define VERTICAL_SYNC_HEIGHT ( 2 ) +#define VERTICAL_BACK_PORCH ( 10 ) +#define VERTICAL_FRONT_PORCH ( 22 - VERTICAL_BACK_PORCH ) + +#endif \ No newline at end of file diff --git a/radio/src/boards/helloradio-h750/sdram_driver.cpp b/radio/src/boards/helloradio-h750/sdram_driver.cpp new file mode 100644 index 000000000..fc66af9c9 --- /dev/null +++ b/radio/src/boards/helloradio-h750/sdram_driver.cpp @@ -0,0 +1,252 @@ +/* + * 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 "hal/gpio.h" +#include "stm32_gpio.h" +#include "stm32_hal_ll.h" + +#include "board.h" + +#define SDRAM_MEMORY_WIDTH FMC_SDRAM_MEM_BUS_WIDTH_16 + +#define SDRAM_CAS_LATENCY FMC_SDRAM_CAS_LATENCY_3 + +#define SDCLOCK_PERIOD FMC_SDRAM_CLOCK_PERIOD_2 + +#define SDRAM_TIMEOUT ((uint32_t)0xFFFF) + +#define SDRAM_READBURST FMC_SDRAM_RBURST_DISABLE + +#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) + +#define GPIO_AF_FMC GPIO_AF12 + +extern "C" void SDRAM_GPIOConfig(void) +{ + /*-- GPIOs Configuration -----------------------------------------------------*/ + /* + */ + + /* GPIOD configuration */ + gpio_init_af(GPIO_PIN(GPIOD, 0), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOD, 1), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOD, 8), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOD, 9), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOD, 10), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOD, 14), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOD, 15), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + + /* GPIOE configuration */ + gpio_init_af(GPIO_PIN(GPIOE, 0), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOE, 1), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//BL1 + gpio_init_af(GPIO_PIN(GPIOE, 7), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOE, 8), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOE, 9), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOE, 10), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOE, 11), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOE, 12), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOE, 13), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOE, 14), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOE, 15), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + + /* GPIOF configuration */ + gpio_init_af(GPIO_PIN(GPIOF, 0), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOF, 1), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOF, 2), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOF, 3), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOF, 4), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOF, 5), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOF, 11), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//RAS + gpio_init_af(GPIO_PIN(GPIOF, 12), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);// + gpio_init_af(GPIO_PIN(GPIOF, 13), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOF, 14), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOF, 15), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + + /* GPIOG configuration */ + gpio_init_af(GPIO_PIN(GPIOG, 0), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOG, 1), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOG, 4), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//BA0 + gpio_init_af(GPIO_PIN(GPIOG, 5), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//BA1 + gpio_init_af(GPIO_PIN(GPIOG, 8), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//CLK + gpio_init_af(GPIO_PIN(GPIOG, 15), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//NCAS + + + gpio_init_af(GPIO_PIN(GPIOH, 2), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//CLKE0 PH2 + gpio_init_af(GPIO_PIN(GPIOH, 3), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//NE0 PH3 + gpio_init_af(GPIO_PIN(GPIOH, 5), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//NWE PH5 V14P OK + +} + +extern "C" void SDRAM_InitSequence(void) +{ + FMC_SDRAM_CommandTypeDef FMC_SDRAMCommandStructure; + uint32_t tmpr = 0; + uint32_t timeout = SDRAM_TIMEOUT; + + /* Step 3 --------------------------------------------------------------------*/ + /* Configure a clock configuration enable command */ + FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE; + FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; + FMC_SDRAMCommandStructure.AutoRefreshNumber = 1; + FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0; + /* Wait until the SDRAM controller is ready */ + // while((__FMC_SDRAM_GET_FLAG(FMC_Bank5_6_R, FMC_SDRAM_FLAG_BUSY) != 0) && + // (timeout > 0)) + // { + // timeout--; + // } + /* Send the command */ + FMC_SDRAM_SendCommand(FMC_Bank5_6_R, &FMC_SDRAMCommandStructure, 10); + + /* Step 4 --------------------------------------------------------------------*/ + /* Insert 1 ms delay */ + delay_ms(100); + + /* Step 5 --------------------------------------------------------------------*/ + /* Configure a PALL (precharge all) command */ + FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_PALL; + FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; + FMC_SDRAMCommandStructure.AutoRefreshNumber = 1; + FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0; + /* Wait until the SDRAM controller is ready */ + // timeout = SDRAM_TIMEOUT; + // while((__FMC_SDRAM_GET_FLAG(FMC_Bank5_6_R, FMC_SDRAM_FLAG_BUSY) != 0) && (timeout > 0)) + // { + // timeout--; + // } + /* Send the command */ + FMC_SDRAM_SendCommand(FMC_Bank5_6_R, &FMC_SDRAMCommandStructure, 10); + // delay_ms(1); + + /* Step 6 --------------------------------------------------------------------*/ + /* Configure a Auto-Refresh command */ + FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE; + FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; + FMC_SDRAMCommandStructure.AutoRefreshNumber = 8; + FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0; + + /* Wait until the SDRAM controller is ready */ + // timeout = SDRAM_TIMEOUT; + // while((__FMC_SDRAM_GET_FLAG(FMC_Bank5_6_R, FMC_SDRAM_FLAG_BUSY) != 0) && + // (timeout > 0)) + // { + // timeout--; + // } + /* Send the command */ + FMC_SDRAM_SendCommand(FMC_Bank5_6_R, &FMC_SDRAMCommandStructure, 10); + // delay_ms(1); + + /* 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.CommandMode = FMC_SDRAM_CMD_LOAD_MODE; + FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; + FMC_SDRAMCommandStructure.AutoRefreshNumber = 1; + FMC_SDRAMCommandStructure.ModeRegisterDefinition = tmpr; + + /* Wait until the SDRAM controller is ready */ + // timeout = SDRAM_TIMEOUT; + // while((__FMC_SDRAM_GET_FLAG(FMC_Bank5_6_R, FMC_SDRAM_FLAG_BUSY) != 0) && (timeout > 0)) + // { + // timeout--; + // } + /* Send the command */ + FMC_SDRAM_SendCommand(FMC_Bank5_6_R, &FMC_SDRAMCommandStructure, 10); + // delay_ms(1); + + /* Step 8 --------------------------------------------------------------------*/ + /* Set the refresh rate counter */ + /* (15.62 us x Freq) - 20 */ + /* Set the device refresh counter */ + FMC_SDRAM_SetAutoRefreshNumber(FMC_Bank5_6_R, 15); + FMC_SDRAM_ProgramRefreshRate(FMC_Bank5_6_R, 1855); + /* Wait until the SDRAM controller is ready */ + // timeout = SDRAM_TIMEOUT; + // while((__FMC_SDRAM_GET_FLAG(FMC_Bank5_6_R, FMC_SDRAM_FLAG_BUSY) != 0) && (timeout > 0)) + // { + // timeout--; + // } + // delay_ms(1); +} + +extern "C" void SDRAM_Init(void) +{ + //delay funcion needed + delaysInit(); + + /* GPIO configuration for FMC SDRAM bank */ + SDRAM_GPIOConfig(); + + /* Enable FMC clock */ + LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_FMC); + + /* FMC Configuration ---------------------------------------------------------*/ + FMC_SDRAM_InitTypeDef FMC_SDRAMInitStructure; + FMC_SDRAM_TimingTypeDef FMC_SDRAMTimingInitStructure; + + /* FMC SDRAM Bank configuration */ + /* Timing configuration for 80 Mhz of SD clock */ + FMC_SDRAMTimingInitStructure.LoadToActiveDelay = 2; + FMC_SDRAMTimingInitStructure.ExitSelfRefreshDelay = 7; + FMC_SDRAMTimingInitStructure.SelfRefreshTime = 4; + FMC_SDRAMTimingInitStructure.RowCycleDelay = 7; + FMC_SDRAMTimingInitStructure.WriteRecoveryTime = 3; + FMC_SDRAMTimingInitStructure.RPDelay = 2; + FMC_SDRAMTimingInitStructure.RCDDelay = 2; + + /* FMC SDRAM control configuration */ + FMC_SDRAMInitStructure.SDBank = FMC_SDRAM_BANK1; + FMC_SDRAMInitStructure.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8; + FMC_SDRAMInitStructure.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12; + FMC_SDRAMInitStructure.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16; + FMC_SDRAMInitStructure.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4; + FMC_SDRAMInitStructure.CASLatency = FMC_SDRAM_CAS_LATENCY_3; + FMC_SDRAMInitStructure.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE; + FMC_SDRAMInitStructure.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2; + FMC_SDRAMInitStructure.ReadBurst = FMC_SDRAM_RBURST_ENABLE; + FMC_SDRAMInitStructure.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0; + + /* FMC SDRAM bank initialization */ + FMC_SDRAM_Init(FMC_Bank5_6_R, &FMC_SDRAMInitStructure); + FMC_SDRAM_Timing_Init(FMC_Bank5_6_R, &FMC_SDRAMTimingInitStructure, FMC_SDRAM_BANK1); + + __FMC_ENABLE(); + + /* FMC SDRAM device initialization sequence */ + SDRAM_InitSequence(); +} diff --git a/radio/src/boards/helloradio-h750/system_clock.c b/radio/src/boards/helloradio-h750/system_clock.c new file mode 100644 index 000000000..3fe2c01e0 --- /dev/null +++ b/radio/src/boards/helloradio-h750/system_clock.c @@ -0,0 +1,116 @@ +/* + * 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 "stm32h7xx_ll_pwr.h" +#include "stm32h7xx_ll_rcc.h" +#include "stm32h7xx_ll_system.h" +#include "stm32h7xx_ll_bus.h" + +#define BOOTSTRAP __attribute__((section(".bootstrap"))) + +BOOTSTRAP void SystemClock_Config(void) +{ + /* Power Configuration */ + LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY); + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + while (LL_PWR_IsActiveFlag_VOS() == 0){ + } + + /* Enable HSE oscillator */ + LL_RCC_HSE_Enable(); + while (LL_RCC_HSE_IsReady() != 1) { + } + + /* Set FLASH latency */ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_5); + + /* Main PLL configuration and activation */ + LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSE); + LL_RCC_PLL1P_Enable(); + LL_RCC_PLL1Q_Enable(); + LL_RCC_PLL1R_Enable(); + LL_RCC_PLL1FRACN_Disable(); + LL_RCC_PLL1_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_2_4); + LL_RCC_PLL1_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE); + LL_RCC_PLL1_SetM(1); + LL_RCC_PLL1_SetN(100); + LL_RCC_PLL1_SetP(2); + LL_RCC_PLL1_SetQ(4); + LL_RCC_PLL1_SetR(2); + LL_RCC_PLL1_Enable(); + while (LL_RCC_PLL1_IsReady() != 1) { + } + + /* Set Sys & AHB & APB1 & APB2 & APB4 prescaler */ + LL_RCC_SetSysPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2); + LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_2); + + /* Set PLL1 as System Clock Source */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) { + } + + /* Config & activate PLL2 */ + LL_RCC_PLL2P_Enable(); + LL_RCC_PLL2Q_Enable(); + LL_RCC_PLL2R_Enable(); + LL_RCC_PLL2FRACN_Disable(); + LL_RCC_PLL2_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_2_4); + LL_RCC_PLL2_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE); + LL_RCC_PLL2_SetM(1); + LL_RCC_PLL2_SetN(120); + LL_RCC_PLL2_SetP(12); + LL_RCC_PLL2_SetQ(2); + LL_RCC_PLL2_SetR(4); + LL_RCC_PLL2_Enable(); + while (LL_RCC_PLL2_IsReady() != 1) { + } + + /* Config & activate PLL3 */ + LL_RCC_PLL3P_Enable(); + LL_RCC_PLL3Q_Enable(); + LL_RCC_PLL3R_Enable(); + LL_RCC_PLL3FRACN_Disable(); + LL_RCC_PLL3_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_2_4); + LL_RCC_PLL3_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE); + LL_RCC_PLL3_SetM(1); + LL_RCC_PLL3_SetN(120); + LL_RCC_PLL3_SetP(5); + LL_RCC_PLL3_SetQ(20); + LL_RCC_PLL3_SetR(80); + LL_RCC_PLL3_Enable(); + while (LL_RCC_PLL3_IsReady() != 1) { + } + + /* Enable SRAM1, SRAM2 & SRAM3 */ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_D2SRAM1 | + LL_AHB2_GRP1_PERIPH_D2SRAM2 | + LL_AHB2_GRP1_PERIPH_D2SRAM3); + + /* Set periph clock sources */ + LL_RCC_SetFMCClockSource(LL_RCC_FMC_CLKSOURCE_HCLK); + LL_RCC_SetSPIClockSource(LL_RCC_SPI123_CLKSOURCE_PLL3P); + LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLL3Q); + LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_CLKP); +} diff --git a/radio/src/boards/helloradio-h750/system_clock.h b/radio/src/boards/helloradio-h750/system_clock.h new file mode 100644 index 000000000..10b69a118 --- /dev/null +++ b/radio/src/boards/helloradio-h750/system_clock.h @@ -0,0 +1,23 @@ +/* + * 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. + */ + +void SystemClock_Config(); + diff --git a/radio/src/boards/helloradio-h750/touch_driver.cpp b/radio/src/boards/helloradio-h750/touch_driver.cpp new file mode 100644 index 000000000..96ed51480 --- /dev/null +++ b/radio/src/boards/helloradio-h750/touch_driver.cpp @@ -0,0 +1,291 @@ +/* + * 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 "touch_driver.h" +#include "stm32_hal.h" +#include "stm32_hal_ll.h" + +#include "stm32_exti_driver.h" +#include "stm32_gpio.h" +#include "stm32_gpio_driver.h" +#include "stm32_i2c_driver.h" +#include "timers_driver.h" + +#include "debug.h" +#include "delays_driver.h" +#include "hal.h" +#include "hal/gpio.h" +#include "hal/i2c_driver.h" +#include "rtos.h" + +volatile static bool touchEventOccured; + +#define TOUCH_CST836U_I2C_ADDRESS (0x15) + +static tc_handle_TypeDef tc_handle = {0, 0}; + +tmr10ms_t downTime = 0; +tmr10ms_t tapTime = 0; +short tapCount = 0; +#define TAP_TIME 250 // ms + +static TouchState internalTouchState = {}; + +static void _cst836u_exti_isr(void) { + touchEventOccured = true; +} + +static void TouchAFExtiConfig(void) +{ + TRACE("TOUCH_AF_EXTI_CONFIG"); + gpio_init_int(TOUCH_INT_GPIO, GPIO_IN_PU, GPIO_FALLING, _cst836u_exti_isr); +} + +void initTouchI2C(void) +{ + TRACE("CST836U I2C Init"); + + if (i2c_init(TOUCH_I2C_BUS) < 0) { + TRACE("CST836U ERROR: i2c_init failed"); + return; + } +} + +#define I2C_TIMEOUT_MAX 5 // 5 ms + +bool touch_i2c_read(uint8_t addr, uint8_t reg, uint8_t* data, uint8_t len) +{ + if (stm32_i2c_master_tx(TOUCH_I2C_BUS, addr, ®, 1, 3) < 0) return false; + delay_us(5); + if (stm32_i2c_master_rx(TOUCH_I2C_BUS, addr, data, len, I2C_TIMEOUT_MAX) < 0) + return false; + + return true; +} + +static uint8_t TS_IO_Read(uint8_t addr, uint8_t reg) +{ + uint8_t result; + uint8_t tryCount = 3; + while (!touch_i2c_read(addr, reg, &result, 1)) { + if (--tryCount == 0) break; + initTouchI2C(); + } + return result; +} + +static uint16_t TS_IO_ReadMultiple(uint8_t addr, uint8_t reg, uint8_t* buffer, + uint16_t length) +{ + uint8_t tryCount = 3; + while (!touch_i2c_read(addr, reg, buffer, length)) { + if (--tryCount == 0) break; + initTouchI2C(); + } + return 1; +} + +static void touch_cst836u_debug_info(void) +{ +#if defined(DEBUG) + TRACE("cst836u: fw ver 0x%02X %02X", + TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_FW_VERSION_H_REG), + TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_FW_VERSION_L_REG)); + TRACE("cst836u: module version 0x%02X", + TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_MODULE_VERSION_REG)); + TRACE("cst836u: project name 0x%02X", + TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_PROJECT_NAME_REG)); + TRACE("cst836u: chip type 0x%02X 0x%02X", + TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_CHIP_TYPE_H_REG), + TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_CHIP_TYPE_L_REG)); +#endif +} + +/** + * @brief Get the touch screen X and Y positions values + * Manage multi touch thanks to touch Index global + * variable 'tc_handle.currActiveTouchIdx'. + * @param DeviceAddr: Device address on communication Bus. + * @param X: Pointer to X position value + * @param Y: Pointer to Y position value + * @retval None. + */ +static void cst836u_TS_GetXY(uint16_t* X, uint16_t* Y, uint32_t* event) +{ + uint8_t regAddress = 0; + uint8_t dataxy[4]; + + if (tc_handle.currActiveTouchIdx < tc_handle.currActiveTouchNb) { + switch (tc_handle.currActiveTouchIdx) { + case 0: + regAddress = CST836U_TOUCH1_XH_REG; + break; + case 1: + regAddress = CST836U_TOUCH2_XH_REG; + break; + default: + break; + } + + /* Read X and Y positions */ + TS_IO_ReadMultiple(TOUCH_CST836U_I2C_ADDRESS, regAddress, dataxy, + sizeof(dataxy)); + /* Send back ready X position to caller */ + *X = ((dataxy[0] & CST836U_MSB_MASK) << 8) | dataxy[1]; + /* Send back ready Y position to caller */ + *Y = ((dataxy[2] & CST836U_MSB_MASK) << 8) | dataxy[3]; + + *event = (dataxy[0] & CST836U_TOUCH_EVT_FLAG_MASK) >> + CST836U_TOUCH_EVT_FLAG_SHIFT; + /* + uint32_t weight; + uint32_t area; + */ + tc_handle.currActiveTouchIdx++; + } +} + +/** + * @brief Return if there is touches detected or not. + * Try to detect new touches and forget the old ones (reset internal + * global variables). + * @param DeviceAddr: Device address on communication Bus. + * @retval : Number of active touches detected (can be 0, 1 or 2). + */ +static uint8_t cst836u_TS_DetectTouch() +{ + volatile uint8_t nbTouch = 0; + + /* Read register CST836U_TOUCH_NUM_REG to check number of touches detection */ + nbTouch = TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_TOUCH_NUM_REG); + if (nbTouch > CST836U_MAX_DETECTABLE_TOUCH) { + /* If invalid number of touch detected, set it to zero */ + nbTouch = 0; + } + tc_handle.currActiveTouchNb = nbTouch; + + tc_handle.currActiveTouchIdx = 0; + return (nbTouch); +} + +void TouchReset() +{ + gpio_clear(TOUCH_RST_GPIO); + delay_ms(10); + gpio_set(TOUCH_RST_GPIO); + delay_ms(300); +} + +void touchPanelInit(void) +{ + gpio_init(TOUCH_RST_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW); + initTouchI2C(); + TouchReset(); + TouchAFExtiConfig(); + touch_cst836u_debug_info(); +} + +void handleTouch() +{ + unsigned short touchX; + unsigned short touchY; + uint32_t tEvent = 0; + cst836u_TS_GetXY(&touchX, &touchY, &tEvent); + + if (tEvent == CST836U_TOUCH_EVT_FLAG_CONTACT) { + int dx = touchX - internalTouchState.x; + int dy = touchY - internalTouchState.y; + + internalTouchState.x = touchX; + internalTouchState.y = touchY; + + if (internalTouchState.event == TE_NONE || + internalTouchState.event == TE_UP || + internalTouchState.event == TE_SLIDE_END) { + internalTouchState.startX = internalTouchState.x; + internalTouchState.startY = internalTouchState.y; + internalTouchState.event = TE_DOWN; + } else if (internalTouchState.event == TE_DOWN) { + if (dx >= SLIDE_RANGE || dx <= -SLIDE_RANGE || dy >= SLIDE_RANGE || + dy <= -SLIDE_RANGE) { + internalTouchState.event = TE_SLIDE; + internalTouchState.deltaX = (short)dx; + internalTouchState.deltaY = (short)dy; + } else { + internalTouchState.event = TE_DOWN; + internalTouchState.deltaX = 0; + internalTouchState.deltaY = 0; + } + } else if (internalTouchState.event == TE_SLIDE) { + internalTouchState.event = TE_SLIDE; // no change + internalTouchState.deltaX = (short)dx; + internalTouchState.deltaY = (short)dy; + } + } +} + +bool touchPanelEventOccured() { return touchEventOccured; } + +TouchState touchPanelRead() +{ + if (!touchEventOccured) return internalTouchState; + + touchEventOccured = false; + + tmr10ms_t now = timersGetMsTick(); + internalTouchState.tapCount = 0; + + if (cst836u_TS_DetectTouch()) { + handleTouch(); + if (internalTouchState.event == TE_DOWN && downTime == 0) { + downTime = now; + } + } else { + if (internalTouchState.event == TE_DOWN) { + internalTouchState.event = TE_UP; + if (now - downTime <= TAP_TIME) { + if (now - tapTime > TAP_TIME) { + tapCount = 1; + } else { + tapCount++; + } + internalTouchState.tapCount = tapCount; + tapTime = now; + } else { + internalTouchState.tapCount = 0; // not a tap + } + downTime = 0; + } else { + tapCount = 0; + internalTouchState.tapCount = 0; + internalTouchState.event = TE_SLIDE_END; + } + } + TouchState ret = internalTouchState; + internalTouchState.deltaX = 0; + internalTouchState.deltaY = 0; + if (internalTouchState.event == TE_UP || + internalTouchState.event == TE_SLIDE_END) + internalTouchState.event = TE_NONE; + return ret; +} + +TouchState getInternalTouchState() { return internalTouchState; } diff --git a/radio/src/boards/helloradio-h750/touch_driver.h b/radio/src/boards/helloradio-h750/touch_driver.h new file mode 100644 index 000000000..b4c8eb6b9 --- /dev/null +++ b/radio/src/boards/helloradio-h750/touch_driver.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + Copyright 2016 fishpepper gmail.com + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + author: fishpepper gmail.com +*/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* Set Multi-touch as non supported */ +#ifndef TS_MULTI_TOUCH_SUPPORTED +#define TS_MULTI_TOUCH_SUPPORTED 0 +#endif + +/* Set Auto-calibration as non supported */ +#ifndef TS_AUTO_CALIBRATION_SUPPORTED +#define TS_AUTO_CALIBRATION_SUPPORTED 0 +#endif + +/* Macros --------------------------------------------------------------------*/ + +/** @typedef ft6x06_handle_TypeDef + * ft6x06 Handle definition. + */ +typedef struct { + /* field holding the current number of simultaneous active touches */ + uint8_t currActiveTouchNb; + + /* field holding the touch index currently managed */ + uint8_t currActiveTouchIdx; + +} tc_handle_TypeDef; +/* clang-format off */ +#define CST836U_WORK_MODE_REG 0x00 +#define CST836U_PROXIMITY_ID_REG 0x01 +#define CST836U_TOUCH_NUM_REG 0x02 +#define CST836U_TOUCH1_XH_REG 0x03 +#define CST836U_TOUCH1_XL_REG 0x04 +#define CST836U_TOUCH1_YH_REG 0x05 +#define CST836U_TOUCH1_YL_REG 0x06 + +#define CST836U_TOUCH2_XH_REG 0x09 +#define CST836U_TOUCH2_XL_REG 0x0A +#define CST836U_TOUCH2_YH_REG 0x0B +#define CST836U_TOUCH2_YL_REG 0x0C + +#define CST836U_FW_VERSION_L_REG 0xA6 +#define CST836U_FW_VERSION_H_REG 0xA7 +#define CST836U_MODULE_VERSION_REG 0xA8 +#define CST836U_PROJECT_NAME_REG 0xA9 +#define CST836U_CHIP_TYPE_L_REG 0xAA +#define CST836U_CHIP_TYPE_H_REG 0xAB +#define CST836U_CHECKSUM_L_REG 0xAC +#define CST836U_CHECKSUM_H_REG 0xAD + +#define CST836U_PROX_STATE_REG 0xB0 +#define CST836U_GES_STATE_REG 0xD0 +#define CST836U_GES_ID_REG_REG 0xD3 + +#define CST836U_MAX_DETECTABLE_TOUCH 2 + +#define CST836U_MSB_MASK 0x0F + +#define CST836U_TOUCH_EVT_FLAG_SHIFT 6 +#define CST836U_TOUCH_EVT_FLAG_MASK (3 << CST836U_TOUCH_EVT_FLAG_SHIFT) +#define CST836U_TOUCH_EVT_FLAG_CONTACT 0x02 +/* clang-format on */ + +extern void touchPanelInit(void); +extern void TouchDriver(void); + +#ifdef __cplusplus +} +#endif diff --git a/radio/src/boards/helloradio-h750/usb_charger_driver.cpp b/radio/src/boards/helloradio-h750/usb_charger_driver.cpp new file mode 100644 index 000000000..9d66afbba --- /dev/null +++ b/radio/src/boards/helloradio-h750/usb_charger_driver.cpp @@ -0,0 +1,52 @@ +/* + * 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/gpio.h" +#include "stm32_gpio.h" + +#include "board.h" +#include "hal/usb_driver.h" + +void usbChargerInit() +{ + gpio_init(UCHARGER_GPIO, GPIO_IN_PU, GPIO_PIN_SPEED_LOW); +#if defined(UCHARGER_PW) + gpio_init(UCHARGER_PW, GPIO_OUT, GPIO_PIN_SPEED_LOW); + gpio_set(UCHARGER_PW); + //gpio_clear(UCHARGER_PW); 0=DISABLE 1=ENABLE +#endif +#if defined(UCHARGER_EN) + gpio_init(UCHARGER_EN, GPIO_OUT, GPIO_PIN_SPEED_LOW); + //gpio_set(UCHARGER_EN); + gpio_clear(UCHARGER_EN); //cherge EN 0=ENANLE 1=DISABLE +#endif +#if defined(USB_GPIO_SEL) + gpio_init(USB_GPIO_SEL, GPIO_OUT, GPIO_PIN_SPEED_LOW); + gpio_set(USB_GPIO_SEL); + + //gpio_clear(USB_GPIO_SEL); // USB HUB SELECT 0->H7 MCU 1->CHARGE MCU +#endif +} + +bool usbChargerLed() +{ + return (!gpio_read(UCHARGER_GPIO) && usbPlugged()); +} diff --git a/radio/src/boards/hw_defs/v12.json b/radio/src/boards/hw_defs/v12.json index ac726ddfc..078ebed8f 100644 --- a/radio/src/boards/hw_defs/v12.json +++ b/radio/src/boards/hw_defs/v12.json @@ -5,21 +5,21 @@ "name": "MAIN", "adc": "ADC1", "dma": "DMA2", - "dma_channel": "LL_DMA_CHANNEL_0", + "dma_channel": "LL_DMAMUX1_REQ_ADC1", "dma_stream": "LL_DMA_STREAM_4", "dma_stream_irq": "DMA2_Stream4_IRQn", "dma_stream_irq_handler": "DMA2_Stream4_IRQHandler", - "sample_time": "LL_ADC_SAMPLINGTIME_28CYCLES" + "sample_time": "LL_ADC_SAMPLINGTIME_8CYCLES_5" }, { "name": "EXT", "adc": "ADC3", "dma": "DMA2", - "dma_channel": "LL_DMA_CHANNEL_2", + "dma_channel": "LL_DMAMUX1_REQ_ADC3", "dma_stream": "LL_DMA_STREAM_0", "dma_stream_irq": "DMA2_Stream0_IRQn", "dma_stream_irq_handler": "DMA2_Stream0_IRQHandler", - "sample_time": "LL_ADC_SAMPLINGTIME_56CYCLES" + "sample_time": "LL_ADC_SAMPLINGTIME_8CYCLES_5" } ], "inputs": [ @@ -29,7 +29,7 @@ "adc": "MAIN", "gpio": "GPIOA", "pin": "LL_GPIO_PIN_2", - "channel": "LL_ADC_CHANNEL_2" + "channel": "LL_ADC_CHANNEL_14" }, { "name": "LV", @@ -37,8 +37,7 @@ "adc": "MAIN", "gpio": "GPIOA", "pin": "LL_GPIO_PIN_3", - "channel": "LL_ADC_CHANNEL_3", - "inverted": true + "channel": "LL_ADC_CHANNEL_15" }, { "name": "RV", @@ -46,7 +45,8 @@ "adc": "MAIN", "gpio": "GPIOA", "pin": "LL_GPIO_PIN_0", - "channel": "LL_ADC_CHANNEL_0" + "channel": "LL_ADC_CHANNEL_17", + "inverted": true }, { "name": "RH", @@ -54,17 +54,16 @@ "adc": "MAIN", "gpio": "GPIOA", "pin": "LL_GPIO_PIN_1", - "channel": "LL_ADC_CHANNEL_1", + "channel": "LL_ADC_CHANNEL_16", "inverted": true }, { "name": "P1", "type": "FLEX", "adc": "MAIN", - "gpio": "GPIOB", - "pin": "LL_GPIO_PIN_0", - "channel": "LL_ADC_CHANNEL_8", - "inverted": true, + "gpio": "GPIOC", + "pin": "LL_GPIO_PIN_1", + "channel": "LL_ADC_CHANNEL_11", "label": "S1", "short_label": "1", "default": "POT_CENTER" @@ -73,64 +72,36 @@ "name": "P2", "type": "FLEX", "adc": "MAIN", - "gpio": "GPIOA", - "pin": "LL_GPIO_PIN_6", - "channel": "LL_ADC_CHANNEL_6", - "inverted": true, + "gpio": "GPIOC", + "pin": "LL_GPIO_PIN_0", + "channel": "LL_ADC_CHANNEL_10", "label": "S2", "short_label": "2", "default": "POT_CENTER" }, { - "name": "P3", - "type": "FLEX", - "adc": "EXT", + "name": "RAW1", + "type": "RAW", + "adc": "MAIN", "gpio": "GPIOC", - "pin": "LL_GPIO_PIN_2", - "channel": "LL_ADC_CHANNEL_12", - "label": "S3", - "short_label": "3", - "default": "MULTIPOS" + "pin": "LL_GPIO_PIN_5", + "channel": "LL_ADC_CHANNEL_8" + }, + { + "name": "VBAT", + "type": "VBAT", + "adc": "MAIN", + "gpio": "GPIOC", + "pin": "LL_GPIO_PIN_3", + "channel": "LL_ADC_CHANNEL_13" }, { "name": "RTC_BAT", "type": "RTC_BAT", - "adc": "MAIN", + "adc": "EXT", "gpio": null, "pin": null, "channel": "LL_ADC_CHANNEL_VBAT" - }, - { - "name": "SWB", - "type": "SWITCH", - "adc": "MAIN", - "gpio": "GPIOA", - "pin": "LL_GPIO_PIN_5", - "channel": "LL_ADC_CHANNEL_5" - }, - { - "name": "SWC", - "type": "SWITCH", - "adc": "MAIN", - "gpio": "GPIOC", - "pin": "LL_GPIO_PIN_0", - "channel": "LL_ADC_CHANNEL_10" - }, - { - "name": "SWE", - "type": "SWITCH", - "adc": "MAIN", - "gpio": "GPIOA", - "pin": "LL_GPIO_PIN_7", - "channel": "LL_ADC_CHANNEL_7" - }, - { - "name": "SWF", - "type": "SWITCH", - "adc": "MAIN", - "gpio": "GPIOC", - "pin": "LL_GPIO_PIN_5", - "channel": "LL_ADC_CHANNEL_15" } ] }, @@ -140,39 +111,33 @@ "type": "2POS", "flags": 0, "inverted": false, - "default": "3POS", - "display": [ - 0, - 0 - ], - "gpio": "GPIOC", - "pin": "LL_GPIO_PIN_13", + "default": "2POS", + "gpio": "GPIOH", + "pin": "LL_GPIO_PIN_8", "is_cfs": false }, { "name": "SB", - "type": "ADC", + "type": "3POS", "flags": 0, - "inverted": false, + "inverted": true, "default": "3POS", - "display": [ - 0, - 1 - ], - "adc_input": "SWB", + "gpio_high": "GPIOD", + "pin_high": "LL_GPIO_PIN_11", + "gpio_low": "GPIOH", + "pin_low": "LL_GPIO_PIN_7", "is_cfs": false }, { "name": "SC", - "type": "ADC", + "type": "3POS", "flags": 0, - "inverted": false, + "inverted": true, "default": "3POS", - "display": [ - 1, - 0 - ], - "adc_input": "SWC", + "gpio_high": "GPIOG", + "pin_high": "LL_GPIO_PIN_3", + "gpio_low": "GPIOD", + "pin_low": "LL_GPIO_PIN_4", "is_cfs": false }, { @@ -180,70 +145,98 @@ "type": "2POS", "flags": 0, "inverted": false, - "default": "3POS", - "display": [ - 1, - 1 - ], - "gpio": "GPIOE", - "pin": "LL_GPIO_PIN_8", + "default": "TOGGLE", + "gpio": "GPIOI", + "pin": "LL_GPIO_PIN_3", "is_cfs": false }, { - "name": "SE", - "type": "ADC", + "name": "SW1", + "type": "2POS", "flags": 0, "inverted": false, "default": "2POS", - "display": [ - 0, - 2 - ], - "adc_input": "SWE", - "is_cfs": false + "gpio": null, + "pin": "PCA95XX_P0", + "is_cfs": true, + "cfs_idx": 0 }, { - "name": "SF", - "type": "ADC", + "name": "SW2", + "type": "2POS", "flags": 0, "inverted": false, - "default": "TOGGLE", - "display": [ - 1, - 2 - ], - "adc_input": "SWF", - "is_cfs": false + "default": "2POS", + "gpio": null, + "pin": "PCA95XX_P1", + "is_cfs": true, + "cfs_idx": 1 + }, + { + "name": "SW3", + "type": "2POS", + "flags": 0, + "inverted": false, + "default": "2POS", + "gpio": null, + "pin": "PCA95XX_P2", + "is_cfs": true, + "cfs_idx": 2 + }, + { + "name": "SW4", + "type": "2POS", + "flags": 0, + "inverted": false, + "default": "2POS", + "gpio": null, + "pin": "PCA95XX_P3", + "is_cfs": true, + "cfs_idx": 3 + }, + { + "name": "SW5", + "type": "2POS", + "flags": 0, + "inverted": false, + "default": "2POS", + "gpio": null, + "pin": "PCA95XX_P4", + "is_cfs": true, + "cfs_idx": 4 + }, + { + "name": "SW6", + "type": "2POS", + "flags": 0, + "inverted": false, + "default": "2POS", + "gpio": null, + "pin": "PCA95XX_P5", + "is_cfs": true, + "cfs_idx": 5 } ], "keys": [ { - "gpio": "GPIOE", - "pin": "LL_GPIO_PIN_1", - "active_low": true, - "key": "KEY_EXIT", - "name": "EXIT", - "label": "EXIT" - }, - { - "gpio": "GPIOD", - "pin": "LL_GPIO_PIN_11", + "gpio": "GPIOI", + "pin": "LL_GPIO_PIN_8", "active_low": true, "key": "KEY_ENTER", "name": "ENTER", "label": "Enter" }, { - "gpio": "GPIOD", - "pin": "LL_GPIO_PIN_3", + "gpio": "GPIOI", + "pin": "LL_GPIO_PIN_10", "active_low": true, "key": "KEY_PAGEUP", "name": "PAGEUP", "label": "PAGE<" }, { - "gpio": "GPIOD", - "pin": "LL_GPIO_PIN_7", + "gpio": "GPIOI", + "pin": "LL_GPIO_PIN_11", "active_low": true, "key": "KEY_PAGEDN", "name": "PAGEDN", @@ -251,40 +244,48 @@ }, { "gpio": "GPIOE", - "pin": "LL_GPIO_PIN_11", + "pin": "LL_GPIO_PIN_5", "active_low": true, "key": "KEY_MODEL", "name": "MDL", "label": "MDL" }, { - "gpio": "GPIOD", - "pin": "LL_GPIO_PIN_2", + "gpio": "GPIOK", + "pin": "LL_GPIO_PIN_5", "active_low": true, - "key": "KEY_TELE", - "name": "TELE", - "label": "TELE" + "key": "KEY_EXIT", + "name": "EXIT", + "label": "EXIT" }, { - "gpio": "GPIOB", - "pin": "LL_GPIO_PIN_4", + "gpio": "GPIOJ", + "pin": "LL_GPIO_PIN_3", "active_low": true, "key": "KEY_SYS", "name": "SYS", "label": "SYS" + }, + { + "gpio": "GPIOK", + "pin": "LL_GPIO_PIN_4", + "active_low": true, + "key": "KEY_TELE", + "name": "TELE", + "label": "TELE" } ], "trims": [ { "name": "T1", "dec": { - "gpio": "GPIOD", - "pin": "LL_GPIO_PIN_15", + "gpio": "GPIOB", + "pin": "LL_GPIO_PIN_2", "active_low": true }, "inc": { - "gpio": "GPIOC", - "pin": "LL_GPIO_PIN_1", + "gpio": "GPIOJ", + "pin": "LL_GPIO_PIN_4", "active_low": true }, "active_low": true @@ -292,13 +293,13 @@ { "name": "T2", "dec": { - "gpio": "GPIOE", - "pin": "LL_GPIO_PIN_6", + "gpio": "GPIOJ", + "pin": "LL_GPIO_PIN_2", "active_low": true }, "inc": { - "gpio": "GPIOE", - "pin": "LL_GPIO_PIN_5", + "gpio": "GPIOI", + "pin": "LL_GPIO_PIN_15", "active_low": true }, "active_low": true @@ -307,12 +308,12 @@ "name": "T3", "dec": { "gpio": "GPIOC", - "pin": "LL_GPIO_PIN_3", + "pin": "LL_GPIO_PIN_13", "active_low": true }, "inc": { - "gpio": "GPIOD", - "pin": "LL_GPIO_PIN_0", + "gpio": "GPIOC", + "pin": "LL_GPIO_PIN_2", "active_low": true }, "active_low": true @@ -320,12 +321,12 @@ { "name": "T4", "dec": { - "gpio": "GPIOE", - "pin": "LL_GPIO_PIN_3", + "gpio": "GPIOB", + "pin": "LL_GPIO_PIN_6", "active_low": true }, "inc": { - "gpio": "GPIOE", + "gpio": "GPIOB", "pin": "LL_GPIO_PIN_4", "active_low": true }, @@ -333,45 +334,53 @@ } ], "display": { - "lcd_w": 128, - "lcd_h": 64, - "lcd_phys_w": 128, - "lcd_phys_h": 64, - "lcd_depth": 1, - "lcd_vertical_invert": true + "lcd_w": 320, + "lcd_h": 240, + "lcd_phys_w": 320, + "lcd_phys_h": 240, + "lcd_depth": 16 }, "backlight": { - "backlight_bdtr": "TIM_BDTR_MOE" + "backlight_gpio": "GPIO_PIN(GPIOI, 2)", + "backlight_timer": "TIM8", + "backlight_timer_channel": "LL_TIM_CHANNEL_CH4", + "backlight_gpio_af": "GPIO_AF3", + "backlight_timer_freq": "(PERI1_FREQUENCY * TIMER_MULT_APB1)" }, "leds": { - "led_strip_length": 6, + "led_strip_length": 7, + "bling_led_strip_start": 6, + "bling_led_strip_length": 1, + "cfs_led_strip_start": 0, + "cfs_led_strip_length": 6, + "cfs_leds_per_switch": 1, "led_strip_gpio": "GPIO_PIN(GPIOA, 10)", "led_strip_gpio_af": "LL_GPIO_AF_1", "led_strip_timer": "TIM1", - "led_strip_timer_freq": "(PERI2_FREQUENCY * TIMER_MULT_APB2)", + "led_strip_timer_freq": "(PERI1_FREQUENCY * TIMER_MULT_APB1)", "led_strip_timer_channel": "LL_TIM_CHANNEL_CH3", - "led_strip_timer_dma": "DMA2", - "led_strip_timer_dma_channel": "LL_DMA_CHANNEL_6", - "led_strip_timer_dma_stream": "LL_DMA_STREAM_5", - "led_strip_timer_dma_irqn": "DMA2_Stream5_IRQn", - "led_strip_timer_dma_irqhandler": "DMA2_Stream5_IRQHandler", + "led_strip_timer_dma": "DMA1", + "led_strip_timer_dma_channel": "LL_DMAMUX1_REQ_TIM1_UP", + "led_strip_timer_dma_stream": "LL_DMA_STREAM_0", + "led_strip_timer_dma_irqn": "DMA1_Stream0_IRQn", + "led_strip_timer_dma_irqhandler": "DMA1_Stream0_IRQHandler", "led_strip_refresh_period": 50, "status_leds": true, - "led_red_gpio": "GPIO_PIN(GPIOE, 13)", - "led_green_gpio": "GPIO_PIN(GPIOE, 14)", - "led_blue_gpio": "GPIO_PIN(GPIOE, 2)" + "led_red_gpio": "GPIO_PIN(GPIOI, 12)", + "led_green_gpio": "GPIO_PIN(GPIOI, 13)", + "led_blue_gpio": "GPIO_PIN(GPIOI, 14)" }, "hardware": { "has_ext_module_support": true, "has_int_module_support": true, "sport_max_baudrate": 400000, - "cpu": "STM32F407xG", - "cpu_type": "STM32F4" + "cpu": "STM32H750xB", + "cpu_type": "STM32H7" }, "timers": { - "cpu_freq": 168000000, - "peri1_frequency": 42000000, - "peri2_frequency": 84000000, + "cpu_freq": 400000000, + "peri1_frequency": 100000000, + "peri2_frequency": 100000000, "timer_mult_apb1": 2, "timer_mult_apb2": 2, "ms_timer": "TIM14", @@ -382,14 +391,40 @@ "mixer_scheduler_timer_irqn": "TIM8_BRK_TIM12_IRQn", "mixer_scheduler_timer_irqhandler": "TIM8_BRK_TIM12_IRQHandler" }, + "rotenc": { + "rotary_encoder_gpio_a": "GPIOE", + "rotary_encoder_gpio_pin_a": "LL_GPIO_PIN_3", + "rotary_encoder_gpio_b": "GPIOE", + "rotary_encoder_gpio_pin_b": "LL_GPIO_PIN_4", + "rotary_encoder_inverted": true, + "rotary_encoder_position": "(((ROTARY_ENCODER_GPIO_A->IDR >> 3) & 0x01)|((ROTARY_ENCODER_GPIO_B->IDR >> 3) & 0x02))", + "rotary_encoder_exti_line1": "LL_EXTI_LINE_3", + "rotary_encoder_exti_line2": "LL_EXTI_LINE_4", + "exti": [ + { + "irq": "EXTI3_IRQ", + "priority": 5 + }, + { + "irq": "EXTI4_IRQ", + "priority": 5 + } + ], + "rotary_encoder_exti_port_a": "LL_SYSCFG_EXTI_PORTE", + "rotary_encoder_exti_port_b": "LL_SYSCFG_EXTI_PORTE", + "rotary_encoder_exti_sys_line1": "LL_SYSCFG_EXTI_LINE3", + "rotary_encoder_exti_sys_line2": "LL_SYSCFG_EXTI_LINE4", + "rotary_encoder_timer": "TIM17", + "rotary_encoder_timer_irqn": "TIM17_IRQn", + "rotary_encoder_timer_irqhandler": "TIM17_IRQHandler" + }, "haptic": { "haptic_pwm": true, - "haptic_gpio": "GPIO_PIN(GPIOB, 3)", - "haptic_gpio_af": "GPIO_AF1", - "haptic_timer": "TIM2", - "haptic_timer_freq": "(PERI1_FREQUENCY * TIMER_MULT_APB1)", - "haptic_counter_register": "HAPTIC_TIMER->CCR2", - "haptic_ccmr1": "TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2", - "haptic_ccer": "TIM_CCER_CC2E" + "haptic_gpio": "GPIO_PIN(GPIOE, 6)", + "haptic_gpio_timer": "TIM15", + "haptic_gpio_af": "GPIO_AF4", + "haptic_timer_output_enable": "TIM_CCER_CC2E | TIM_CCER_CC2NE", + "haptic_timer_mode": "TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2PE", + "haptic_timer_compare_value": "HAPTIC_GPIO_TIMER->CCR2" } } diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index b0942a59d..8cc176972 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -80,6 +80,8 @@ static inline void check_struct() CHKSIZE(RadioData, 951); #elif defined(RADIO_ST16) || defined(PCBPA01) || defined(RADIO_TX15) || defined(RADIO_T15PRO) || defined(RADIO_TX16SMK3) || defined(RADIO_T22) CHKSIZE(RadioData, 1183); +#elif defined(RADIO_V12) + CHKSIZE(RadioData, 1180); #elif defined(COLORLCD) #if defined(IMU) CHKSIZE(RadioData, 1063); @@ -112,6 +114,8 @@ static inline void check_struct() #endif #elif defined(PCBST16) || defined(RADIO_T15PRO) || defined(RADIO_TX15) CHKSIZE(ModelData, 7641); +#elif defined(RADIO_V12) + CHKSIZE(ModelData, 7640); #elif defined(PCBC14) CHKSIZE(ModelData, 7573); #elif defined(PCBPA01) diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index 73ec4a51f..e4ad3e0c4 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -504,7 +504,12 @@ PACK(struct ModuleData { uint8_t channelsStart; int8_t channelsCount CUST(r_channelsCount,w_channelsCount); // 0=8 channels uint8_t failsafeMode:4 ENUM(FailsafeModes); // only 3 bits used + #if defined(EXTERNAL_ANTENNA) + uint8_t subType:2 SKIP; + int8_t antennaMode:2 ENUM(AntennaModes); + #else uint8_t subType:4 SKIP; + #endif union { uint8_t raw[PXX2_MAX_RECEIVERS_PER_MODULE * PXX2_LEN_RX_NAME + 1]; @@ -525,8 +530,8 @@ PACK(struct ModuleData { uint8_t spare1:2 SKIP; uint8_t receiverTelemetryOff:1; // false = receiver telem enabled uint8_t receiverHigherChannels:1; // false = pwm out 1-8, true 9-16 - int8_t antennaMode:2; - uint8_t spare2 SKIP; + uint8_t spare2:2 SKIP; + uint8_t spare3 SKIP; } pxx); NOBACKUP(struct { uint8_t spare1:6 SKIP; diff --git a/radio/src/edgetx.cpp b/radio/src/edgetx.cpp index 4cb2763a5..fd0a42542 100644 --- a/radio/src/edgetx.cpp +++ b/radio/src/edgetx.cpp @@ -614,7 +614,7 @@ void calcBacklightValue(int16_t source) { getvalue_t raw = getValue(source); #if defined(COLORLCD) - requiredBacklightBright = BACKLIGHT_LEVEL_MAX - (g_eeGeneral.blOffBright + + requiredBacklightBright = BACKLIGHT_LEVEL_MAX - (g_eeGeneral.blOffBright + ((1024 + raw) * ((BACKLIGHT_LEVEL_MAX - g_eeGeneral.backlightBright) - g_eeGeneral.blOffBright) / 2048)); #elif OLED_SCREEN requiredBacklightBright = (raw + 1024) * 254 / 2048; @@ -736,7 +736,7 @@ static void checkFailsafe() void checkAll(bool isBootCheck) { checkSDfreeStorage(); - + // we don't check the throttle stick if the radio is not calibrated if (g_eeGeneral.chkSum == evalChkSum()) { checkThrottleStick(); @@ -803,7 +803,7 @@ void checkAll(bool isBootCheck) } #endif -#if defined(EXTERNAL_ANTENNA) && defined(INTERNAL_MODULE_PXX1) +#if defined(EXTERNAL_ANTENNA) checkExternalAntenna(); #endif @@ -1353,6 +1353,18 @@ uint32_t pwrDelayTime(int delay) static uint8_t vals[] = { 0, 5, 10, 20, 30 }; return vals[pwrDelayFromYaml(delay)] * 10; } + +// On radios requiring a two-button chord as accidental-activation +// protection, only the chord itself should start/continue the on/off delay +// countdown; a single button held alone must not. +inline bool pwrDelayHoldActive() +{ +#if defined(PWR_BUTTON_DUAL) + return pwrForcePressed(); +#else + return pwrPressed(); +#endif +} #endif #if defined(STARTUP_ANIMATION) @@ -1370,7 +1382,7 @@ void runStartupAnimation() tmr10ms_t duration = 0; bool isPowerOn = false; - while (pwrPressed()) { + while (pwrDelayHoldActive()) { duration = get_tmr10ms() - start; if (duration < PWR_PRESS_DURATION_MIN()) { drawStartupAnimation(duration, PWR_PRESS_DURATION_MIN()); @@ -1737,8 +1749,10 @@ inline uint32_t PWR_PRESS_SHUTDOWN_DELAY() #if defined(PWR_BUTTON_MANAGED) return 0; #else +#if !defined(PWR_BUTTON_DUAL) if (pwrForcePressed()) return 0; +#endif return pwrDelayTime(g_eeGeneral.pwrOffSpeed); #endif } @@ -1789,7 +1803,7 @@ uint32_t pwrCheck() static uint8_t pwr_check_state = PWR_CHECK_ON; bool inactivityShutdown = pwrOffDueToInactivity(); - + if (pwr_check_state == PWR_CHECK_OFF) { return e_power_off; } @@ -1812,10 +1826,17 @@ uint32_t pwrCheck() } #endif - if (pwrPressed() || inactivityShutdown) { + if (pwrDelayHoldActive() || inactivityShutdown) { if (!inactivityShutdown) inactivityTimerReset(ActivitySource::Keys); - +#if defined(PWR_BUTTON_DUAL_KEY1) + if (!inactivityShutdown) { + killEvents(PWR_BUTTON_DUAL_KEY1); +#if defined(PWR_BUTTON_DUAL_KEY2) + killEvents(PWR_BUTTON_DUAL_KEY2); +#endif + } +#endif if (TELEMETRY_STREAMING()) { message = STR_MODEL_STILL_POWERED; } diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 5f032ae72..fbef235c4 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -161,7 +161,7 @@ enum MenuModelSetupItems { #endif ITEM_MODEL_SETUP_INTERNAL_MODULE_DISABLE_MAPPING, #endif -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) +#if defined(EXTERNAL_ANTENNA) ITEM_MODEL_SETUP_INTERNAL_MODULE_ANTENNA, #endif ITEM_MODEL_SETUP_INTERNAL_MODULE_POWER, @@ -407,18 +407,25 @@ inline uint8_t TIMER_ROW(uint8_t timer, uint8_t value) #define TRAINER_BLUETOOTH_S_ROW (bluetooth.distantAddr[0] == '\0' ? HIDDEN_ROW : LABEL()) #define IF_BT_TRAINER_ON(x) (g_eeGeneral.bluetoothMode == BLUETOOTH_TRAINER ? (uint8_t)(x) : HIDDEN_ROW) -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) -#define EXTERNAL_ANTENNA_ROW ((isModuleXJT(INTERNAL_MODULE) && g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL) ? (uint8_t)0 : HIDDEN_ROW), +#if defined(EXTERNAL_ANTENNA) +#if defined(INTMODULE_ANTSEL_GPIO) +#define EXTERNAL_ANTENNA_ROW ((g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL) ? (uint8_t)0 : HIDDEN_ROW), +#else +#define EXTERNAL_ANTENNA_ROW ((isModuleXJT(INTERNAL_MODULE) && g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL) ? (uint8_t)0 : HIDDEN_ROW), +#endif void onModelAntennaSwitchConfirm(const char * result) { if (result == STR_OK) { // Switch to external antenna confirmation - g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode = ANTENNA_MODE_EXTERNAL; - globalData.externalAntennaEnabled = true; + g_model.moduleData[INTERNAL_MODULE].antennaMode = ANTENNA_MODE_EXTERNAL; storageDirty(EE_MODEL); + // Consent already obtained above; mark enabled so checkExternalAntenna() + // applies the GPIO instead of asking again. + globalData.externalAntennaEnabled = true; + checkExternalAntenna(); } else { - reusableBuffer.moduleSetup.antennaMode = g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode; + reusableBuffer.moduleSetup.antennaMode = g_model.moduleData[INTERNAL_MODULE].antennaMode; } } #else @@ -885,8 +892,8 @@ void menuModelSetup(event_t event) reusableBuffer.moduleSetup.newType = g_model.moduleData[EXTERNAL_MODULE].type; #endif -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) - reusableBuffer.moduleSetup.antennaMode = g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode; +#if defined(EXTERNAL_ANTENNA) + reusableBuffer.moduleSetup.antennaMode = g_model.moduleData[INTERNAL_MODULE].antennaMode; #endif } @@ -2187,19 +2194,19 @@ void menuModelSetup(event_t event) } break; -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) +#if defined(EXTERNAL_ANTENNA) case ITEM_MODEL_SETUP_INTERNAL_MODULE_ANTENNA: reusableBuffer.moduleSetup.antennaMode = editChoice(MODEL_SETUP_2ND_COLUMN, y, STR_ANTENNA, STR_ANTENNA_MODES, reusableBuffer.moduleSetup.antennaMode == ANTENNA_MODE_PER_MODEL ? ANTENNA_MODE_INTERNAL : reusableBuffer.moduleSetup.antennaMode, ANTENNA_MODE_INTERNAL, ANTENNA_MODE_EXTERNAL, attr, event, INDENT_WIDTH, [](int value) { return value != ANTENNA_MODE_PER_MODEL; }); - if (event && !s_editMode && reusableBuffer.moduleSetup.antennaMode != g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode) { + if (event && !s_editMode && reusableBuffer.moduleSetup.antennaMode != g_model.moduleData[INTERNAL_MODULE].antennaMode) { if (reusableBuffer.moduleSetup.antennaMode == ANTENNA_MODE_EXTERNAL && !isExternalAntennaEnabled()) { POPUP_CONFIRMATION(STR_ANTENNACONFIRM1, onModelAntennaSwitchConfirm); SET_WARNING_INFO(STR_ANTENNACONFIRM2, strlen(STR_ANTENNACONFIRM2), 0); } else { - g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode = reusableBuffer.moduleSetup.antennaMode; + g_model.moduleData[INTERNAL_MODULE].antennaMode = reusableBuffer.moduleSetup.antennaMode; checkExternalAntenna(); } } diff --git a/radio/src/gui/128x64/view_main.cpp b/radio/src/gui/128x64/view_main.cpp index 2a8c6f5ef..b35ebe65a 100644 --- a/radio/src/gui/128x64/view_main.cpp +++ b/radio/src/gui/128x64/view_main.cpp @@ -76,8 +76,8 @@ static bool isAsteriskDisplayed() { void drawExternalAntennaAndRSSI() { -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) - if (isModuleXJT(INTERNAL_MODULE) && isExternalAntennaEnabled()) { +#if defined(EXTERNAL_ANTENNA) + if (isExternalAntennaEnabled()) { lcdDrawText(VBATT_X - 1, VBATT_Y + 8, "E", TINSIZE); } #endif diff --git a/radio/src/gui/colorlcd/CMakeLists.txt b/radio/src/gui/colorlcd/CMakeLists.txt index a6c1970aa..11af5d2f6 100644 --- a/radio/src/gui/colorlcd/CMakeLists.txt +++ b/radio/src/gui/colorlcd/CMakeLists.txt @@ -162,8 +162,8 @@ if(MULTIMODULE) add_gui_src(module/multi_rfprotos.cpp) endif() -if(INTERNAL_MODULE_PXX1) - add_gui_src(module/pxx1_settings.cpp) +if(INTERNAL_MODULE_PXX1 OR EXTERNAL_ANTENNA) + add_gui_src(module/ext_antenna_settings.cpp) endif() if(PXX2) diff --git a/radio/src/gui/colorlcd/bitmaps.cpp b/radio/src/gui/colorlcd/bitmaps.cpp index b00c7804f..98a585099 100644 --- a/radio/src/gui/colorlcd/bitmaps.cpp +++ b/radio/src/gui/colorlcd/bitmaps.cpp @@ -324,7 +324,7 @@ static const uint8_t mask_btn_list_two[] __FLASH = { // gfx for widgets -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) +#if defined(EXTERNAL_ANTENNA) static const uint8_t mask_topmenu_antenna[] __FLASH = { #include "mask_widget_antenna.lbm" }; @@ -473,7 +473,7 @@ static const _BuiltinIcon _builtinIcons[EDGETX_ICONS_COUNT] = { #if defined(USB_CHARGER) BI(ICON_TOPMENU_TXBATT_CHARGE, mask_widget_txbatt_charging), #endif -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) +#if defined(EXTERNAL_ANTENNA) BI(ICON_TOPMENU_ANTENNA, mask_topmenu_antenna), #endif #if defined(INTERNAL_GPS) diff --git a/radio/src/gui/colorlcd/bitmaps.h b/radio/src/gui/colorlcd/bitmaps.h index 5fe22c2d8..a2faffad7 100644 --- a/radio/src/gui/colorlcd/bitmaps.h +++ b/radio/src/gui/colorlcd/bitmaps.h @@ -100,7 +100,7 @@ enum EdgeTxIcon { #if defined(USB_CHARGER) ICON_TOPMENU_TXBATT_CHARGE, #endif -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) +#if defined(EXTERNAL_ANTENNA) ICON_TOPMENU_ANTENNA, #endif #if defined(INTERNAL_GPS) diff --git a/radio/src/gui/colorlcd/module/crossfire_settings.cpp b/radio/src/gui/colorlcd/module/crossfire_settings.cpp index faf6be854..9a3aac3f5 100644 --- a/radio/src/gui/colorlcd/module/crossfire_settings.cpp +++ b/radio/src/gui/colorlcd/module/crossfire_settings.cpp @@ -67,8 +67,6 @@ CrossfireSettings::CrossfireSettings(Window* parent, const FlexGridLayout& g, return std::string(msg); }); - moduleIdx = moduleIdx; - auto armingLine = newLine(grid); lblArmMode = new StaticText(armingLine, rect_t{}, STR_CRSF_ARMING_MODE); auto box = new Window(armingLine, rect_t{}); diff --git a/radio/src/gui/colorlcd/module/pxx1_settings.cpp b/radio/src/gui/colorlcd/module/ext_antenna_settings.cpp similarity index 61% rename from radio/src/gui/colorlcd/module/pxx1_settings.cpp rename to radio/src/gui/colorlcd/module/ext_antenna_settings.cpp index 4e236a675..aee88e993 100644 --- a/radio/src/gui/colorlcd/module/pxx1_settings.cpp +++ b/radio/src/gui/colorlcd/module/ext_antenna_settings.cpp @@ -19,18 +19,16 @@ * GNU General Public License for more details. */ -#include "pxx1_settings.h" +#include "ext_antenna_settings.h" #include "choice.h" #include "edgetx.h" #include "getset_helpers.h" -#define SET_DIRTY() storageDirty(EE_MODEL) - #if defined(EXTERNAL_ANTENNA) -PXX1AntennaSettings::PXX1AntennaSettings(Window* parent, - const FlexGridLayout& g, - uint8_t moduleIdx) : +ExtAntennaSettings::ExtAntennaSettings(Window* parent, + const FlexGridLayout& g, + uint8_t moduleIdx) : Window(parent, rect_t{}), md(&g_model.moduleData[moduleIdx]) { FlexGridLayout grid(g); @@ -39,25 +37,17 @@ PXX1AntennaSettings::PXX1AntennaSettings(Window* parent, auto line = newLine(grid); new StaticText(line, rect_t{}, STR_ANTENNA); - if (md->pxx.antennaMode == ANTENNA_MODE_PER_MODEL) { - md->pxx.antennaMode = ANTENNA_MODE_INTERNAL; - SET_DIRTY(); + if (md->antennaMode == ANTENNA_MODE_PER_MODEL) { + md->antennaMode = ANTENNA_MODE_INTERNAL; + storageDirty(EE_MODEL); } auto antennaChoice = new Choice( line, rect_t{}, STR_ANTENNA_MODES, ANTENNA_MODE_INTERNAL, - ANTENNA_MODE_EXTERNAL, GET_DEFAULT(md->pxx.antennaMode), + ANTENNA_MODE_EXTERNAL, GET_DEFAULT(md->antennaMode), [=](int32_t antenna) -> void { - if (!isExternalAntennaEnabled() && (antenna == ANTENNA_MODE_EXTERNAL)) { - if (confirmationDialog(STR_ANTENNACONFIRM1, STR_ANTENNACONFIRM2)) { - md->pxx.antennaMode = antenna; - SET_DIRTY(); - } - } else { - md->pxx.antennaMode = antenna; - SET_DIRTY(); - checkExternalAntenna(); - } + setAntennaModeWithConfirm(antenna, EE_MODEL, + [=](int8_t mode) { md->antennaMode = mode; }); }); antennaChoice->setAvailableHandler( diff --git a/radio/src/gui/colorlcd/module/pxx1_settings.h b/radio/src/gui/colorlcd/module/ext_antenna_settings.h similarity index 85% rename from radio/src/gui/colorlcd/module/pxx1_settings.h rename to radio/src/gui/colorlcd/module/ext_antenna_settings.h index 9842d7ffb..21342dd2e 100644 --- a/radio/src/gui/colorlcd/module/pxx1_settings.h +++ b/radio/src/gui/colorlcd/module/ext_antenna_settings.h @@ -26,12 +26,12 @@ struct ModuleData; -class PXX1AntennaSettings : public Window, public ModuleOptions +class ExtAntennaSettings : public Window, public ModuleOptions { ModuleData* md; void update() override {} public: - PXX1AntennaSettings(Window* parent, const FlexGridLayout& g, uint8_t moduleIdx); + ExtAntennaSettings(Window* parent, const FlexGridLayout& g, uint8_t moduleIdx); }; diff --git a/radio/src/gui/colorlcd/module/module_setup.cpp b/radio/src/gui/colorlcd/module/module_setup.cpp index 5d3957a1f..21e88b1da 100644 --- a/radio/src/gui/colorlcd/module/module_setup.cpp +++ b/radio/src/gui/colorlcd/module/module_setup.cpp @@ -37,8 +37,8 @@ #include "storage/modelslist.h" #include "toggleswitch.h" -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) -#include "pxx1_settings.h" +#if defined(EXTERNAL_ANTENNA) +#include "ext_antenna_settings.h" #endif #if defined(PXX2) @@ -165,18 +165,25 @@ class ModuleWindow : public Window modOpts = new MultimoduleSettings(this, grid, moduleIdx); } #endif - #if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) - else if (moduleIdx == INTERNAL_MODULE && isModuleXJT(moduleIdx) && - g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL) { - modOpts = new PXX1AntennaSettings(this, grid, moduleIdx); - } - #endif #if defined(DSMP) else if (isModuleDSMP(moduleIdx)) { modOpts = new DSMPSettings(this, grid, moduleIdx); } #endif + #if defined(EXTERNAL_ANTENNA) + if (moduleIdx == INTERNAL_MODULE && + g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL) { + bool antennaModuleOk = isModuleXJT(moduleIdx); + #if defined(INTMODULE_ANTSEL_GPIO) + antennaModuleOk = true; + #endif + if (antennaModuleOk) { + new ExtAntennaSettings(this, grid, moduleIdx); + } + } + #endif + // Channel Range auto line = newLine(grid); new StaticText(line, rect_t{}, STR_CHANNELRANGE); diff --git a/radio/src/gui/colorlcd/radio/hw_intmodule.cpp b/radio/src/gui/colorlcd/radio/hw_intmodule.cpp index 4f4d20afb..eff46689e 100644 --- a/radio/src/gui/colorlcd/radio/hw_intmodule.cpp +++ b/radio/src/gui/colorlcd/radio/hw_intmodule.cpp @@ -45,7 +45,7 @@ InternalModuleWindow::InternalModuleWindow(Window *parent, FlexGridLayout& grid) internalModule->setAvailableHandler( [](int module) { return isInternalModuleSupported(module); }); -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) +#if defined(EXTERNAL_ANTENNA) ant_box = parent->newLine(grid); ant_box->padLeft(PAD_SMALL); new StaticText(ant_box, rect_t{}, STR_ANTENNA); @@ -53,20 +53,8 @@ InternalModuleWindow::InternalModuleWindow(Window *parent, FlexGridLayout& grid) ant_box, rect_t{}, STR_ANTENNA_MODES, ANTENNA_MODE_INTERNAL, ANTENNA_MODE_EXTERNAL, GET_DEFAULT(g_eeGeneral.antennaMode), [](int antenna) { - if (!isExternalAntennaEnabled() && - (antenna == ANTENNA_MODE_EXTERNAL || - (antenna == ANTENNA_MODE_PER_MODEL && - g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode == - ANTENNA_MODE_EXTERNAL))) { - if (confirmationDialog(STR_ANTENNACONFIRM1, STR_ANTENNACONFIRM2)) { - g_eeGeneral.antennaMode = antenna; - SET_DIRTY(); - } - } else { - g_eeGeneral.antennaMode = antenna; - checkExternalAntenna(); - SET_DIRTY(); - } + setAntennaModeWithConfirm(antenna, EE_GENERAL, + [](int8_t mode) { g_eeGeneral.antennaMode = mode; }); }); updateAntennaLine(); @@ -112,7 +100,11 @@ void InternalModuleWindow::updateBaudrateLine() void InternalModuleWindow::updateAntennaLine() { -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) - ant_box->show(isInternalModuleAvailable(MODULE_TYPE_XJT_PXX1)); +#if defined(EXTERNAL_ANTENNA) +#if defined(INTMODULE_ANTSEL_GPIO) + ant_box->show(g_eeGeneral.internalModule != MODULE_TYPE_NONE); +#else + ant_box->show(isModuleXJT(INTERNAL_MODULE)); +#endif #endif } diff --git a/radio/src/gui/colorlcd/widgets/radio_info.cpp b/radio/src/gui/colorlcd/widgets/radio_info.cpp index 30a094911..2426ae5bc 100644 --- a/radio/src/gui/colorlcd/widgets/radio_info.cpp +++ b/radio/src/gui/colorlcd/widgets/radio_info.cpp @@ -68,7 +68,7 @@ class RadioInfoWidget : public Widget batteryChargeIcon->hide(); #endif -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) +#if defined(EXTERNAL_ANTENNA) extAntenna = new StaticIcon(this, W_RSSI_X - PAD_SMALL, 1, ICON_TOPMENU_ANTENNA, COLOR_THEME_PRIMARY2_INDEX); @@ -149,9 +149,8 @@ class RadioInfoWidget : public Widget batteryChargeIcon->show(usbChargerLed()); #endif -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) - extAntenna->show(isModuleXJT(INTERNAL_MODULE) && - isExternalAntennaEnabled()); +#if defined(EXTERNAL_ANTENNA) + extAntenna->show(isExternalAntennaEnabled()); #endif // Battery level @@ -219,7 +218,7 @@ class RadioInfoWidget : public Widget #if defined(USB_CHARGER) StaticIcon* batteryChargeIcon; #endif -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) +#if defined(EXTERNAL_ANTENNA) StaticIcon* extAntenna; #endif }; diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index 5c0169ba6..b62bda796 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -86,7 +86,7 @@ enum { ITEM_RADIO_HARDWARE_BLUETOOTH_DISTANT_ADDR, ITEM_RADIO_HARDWARE_BLUETOOTH_NAME, #endif -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) +#if defined(EXTERNAL_ANTENNA) ITEM_RADIO_HARDWARE_EXTERNAL_ANTENNA, #endif ITEM_RADIO_HARDWARE_SERIAL_PORT_LABEL, @@ -106,19 +106,23 @@ enum { ITEM_RADIO_HARDWARE_MAX }; -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) +#if defined(EXTERNAL_ANTENNA) static void onHardwareAntennaSwitchConfirm(const char * result) { if (result == STR_OK) { // Switch to external antenna confirmation g_eeGeneral.antennaMode = reusableBuffer.radioHardware.antennaMode; storageDirty(EE_GENERAL); + // Consent already obtained above; mark enabled so checkExternalAntenna() + // applies the GPIO instead of asking again. + globalData.externalAntennaEnabled = true; + checkExternalAntenna(); } else { reusableBuffer.radioHardware.antennaMode = g_eeGeneral.antennaMode; } } -#endif +#endif // defined(EXTERNAL_ANTENNA) #if defined(FUNCTION_SWITCHES) #define RADIO_SETUP_2ND_COLUMN (LCD_W-11*FW) @@ -344,9 +348,13 @@ static void _init_menu_tab_array(uint8_t* tab, size_t len) tab[ITEM_RADIO_HARDWARE_BLUETOOTH_NAME] = bt_off ? HIDDEN_ROW : 0; #endif -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) +#if defined(EXTERNAL_ANTENNA) tab[ITEM_RADIO_HARDWARE_EXTERNAL_ANTENNA] = +#if defined(INTMODULE_ANTSEL_GPIO) + 0; +#else g_eeGeneral.internalModule == MODULE_TYPE_XJT_PXX1 ? 0 : HIDDEN_ROW; +#endif #endif bool has_serial = false; @@ -409,7 +417,7 @@ void menuRadioHardware(event_t event) } else if (event == EVT_ENTRY) { enableVBatBridge(); -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) +#if defined(EXTERNAL_ANTENNA) reusableBuffer.radioHardware.antennaMode = g_eeGeneral.antennaMode; #endif } @@ -560,11 +568,11 @@ void menuRadioHardware(event_t event) break; #endif -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) +#if defined(EXTERNAL_ANTENNA) case ITEM_RADIO_HARDWARE_EXTERNAL_ANTENNA: reusableBuffer.radioHardware.antennaMode = editChoice(HW_SETTINGS_COLUMN2, y, STR_ANTENNA, STR_ANTENNA_MODES, reusableBuffer.radioHardware.antennaMode, ANTENNA_MODE_INTERNAL, ANTENNA_MODE_EXTERNAL, attr, event); if (!s_editMode && reusableBuffer.radioHardware.antennaMode != g_eeGeneral.antennaMode) { - if (!isExternalAntennaEnabled() && (reusableBuffer.radioHardware.antennaMode == ANTENNA_MODE_EXTERNAL || (reusableBuffer.radioHardware.antennaMode == ANTENNA_MODE_PER_MODEL && g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode == ANTENNA_MODE_EXTERNAL))) { + if (!isExternalAntennaEnabled() && (reusableBuffer.radioHardware.antennaMode == ANTENNA_MODE_EXTERNAL || (reusableBuffer.radioHardware.antennaMode == ANTENNA_MODE_PER_MODEL && g_model.moduleData[INTERNAL_MODULE].antennaMode == ANTENNA_MODE_EXTERNAL))) { POPUP_CONFIRMATION(STR_ANTENNACONFIRM1, onHardwareAntennaSwitchConfirm); SET_WARNING_INFO(STR_ANTENNACONFIRM2, strlen(STR_ANTENNACONFIRM2), 0); } diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index 5f716d537..d365b047f 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -717,7 +717,7 @@ bool isSourceAvailableInResetSpecialFunction(int index) } } -#if defined(EXTERNAL_ANTENNA) && defined(INTERNAL_MODULE_PXX1) +#if defined(EXTERNAL_ANTENNA) #if defined(COLORLCD) @@ -749,7 +749,9 @@ static void runAntennaSelectionMenu() return menu->deleted(); }); } -#else +#else // !COLORLCD + +#if defined(EXTERNAL_ANTENNA) void onAntennaSelection(const char* result) { if (result == STR_USE_INTERNAL_ANTENNA) { @@ -768,49 +770,96 @@ void onAntennaSwitchConfirm(const char * result) globalData.externalAntennaEnabled = true; } } -#endif +#endif // defined(EXTERNAL_ANTENNA) + +#endif // defined(COLORLCD) void checkExternalAntenna() { - if (isModuleXJT(INTERNAL_MODULE)) { - if (g_eeGeneral.antennaMode == ANTENNA_MODE_EXTERNAL) { - // TRACE("checkExternalAntenna(): External"); - globalData.externalAntennaEnabled = true; - } else if (g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL && - g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode == - ANTENNA_MODE_EXTERNAL) { - // TRACE("checkExternalAntenna(): Per Model, External"); - if (!globalData.externalAntennaEnabled) { -#if defined(COLORLCD) - if (confirmationDialog(STR_ANTENNACONFIRM1, STR_ANTENNACONFIRM2)) { - globalData.externalAntennaEnabled = true; - } -#else - POPUP_CONFIRMATION(STR_ANTENNACONFIRM1, onAntennaSwitchConfirm); - SET_WARNING_INFO(STR_ANTENNACONFIRM2, strlen(STR_ANTENNACONFIRM2), 0); + // Get the per-model antenna mode from the appropriate field + int8_t modelAntennaMode = g_model.moduleData[INTERNAL_MODULE].antennaMode; + +#if !defined(INTMODULE_ANTSEL_GPIO) + if (!isModuleXJT(INTERNAL_MODULE)) { + globalData.externalAntennaEnabled = false; + return; + } #endif + + if (g_eeGeneral.antennaMode == ANTENNA_MODE_EXTERNAL) { + globalData.externalAntennaEnabled = true; +#if defined(INTMODULE_ANTSEL_GPIO) && !defined(SIMU) + INTMODULE_ANTSEL_EXT(); + LED_ERROR_BEGIN(); + RAISE_ALERT(STR_ANTENNACONFIRM1, STR_ANTENNACONFIRM2, STR_PRESS_ANY_KEY_TO_SKIP, AU_WARNING1); +#endif + } else if (g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL && + modelAntennaMode == ANTENNA_MODE_EXTERNAL) { + if (!globalData.externalAntennaEnabled) { +#if defined(COLORLCD) + if (confirmationDialog(STR_ANTENNACONFIRM1, STR_ANTENNACONFIRM2)) { + globalData.externalAntennaEnabled = true; } - } else if (g_eeGeneral.antennaMode == ANTENNA_MODE_ASK || - (g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL && - g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode == - ANTENNA_MODE_ASK)) { - - // TRACE("checkExternalAntenna(): Ask"); - globalData.externalAntennaEnabled = false; - -#if defined(COLORLCD) - runAntennaSelectionMenu(); -#else - POPUP_MENU_START(onAntennaSelection, 2, STR_USE_INTERNAL_ANTENNA, STR_USE_EXTERNAL_ANTENNA); +#elif defined(EXTERNAL_ANTENNA) + POPUP_CONFIRMATION(STR_ANTENNACONFIRM1, onAntennaSwitchConfirm); + SET_WARNING_INFO(STR_ANTENNACONFIRM2, strlen(STR_ANTENNACONFIRM2), 0); #endif - } else { - globalData.externalAntennaEnabled = false; } + } else if (g_eeGeneral.antennaMode == ANTENNA_MODE_ASK || + (g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL && + modelAntennaMode == ANTENNA_MODE_ASK)) { + globalData.externalAntennaEnabled = false; +#if defined(COLORLCD) + runAntennaSelectionMenu(); +#elif defined(EXTERNAL_ANTENNA) + POPUP_MENU_START(onAntennaSelection, 2, STR_USE_INTERNAL_ANTENNA, STR_USE_EXTERNAL_ANTENNA); +#endif } else { globalData.externalAntennaEnabled = false; } -} + +#if defined(INTMODULE_ANTSEL_GPIO) && !defined(SIMU) + // Apply hardware GPIO switch based on result + if (g_eeGeneral.antennaMode != ANTENNA_MODE_EXTERNAL) { + if (globalData.externalAntennaEnabled) { + INTMODULE_ANTSEL_EXT(); + } else { + INTMODULE_ANTSEL_INT(); + } + } #endif +} + +#if defined(COLORLCD) +// Shared by every antenna-mode Choice widget (radio-level and per-model, +// GPIO and non-GPIO boards) so the "apply to hardware" step can't be +// forgotten in just one of the call sites. +void setAntennaModeWithConfirm(int8_t newMode, uint8_t storageId, + std::function setter) +{ + int8_t modelAntennaMode = g_model.moduleData[INTERNAL_MODULE].antennaMode; + bool willEnableExternal = + newMode == ANTENNA_MODE_EXTERNAL || + (newMode == ANTENNA_MODE_PER_MODEL && modelAntennaMode == ANTENNA_MODE_EXTERNAL); + + if (!isExternalAntennaEnabled() && willEnableExternal) { + if (confirmationDialog(STR_ANTENNACONFIRM1, STR_ANTENNACONFIRM2)) { + setter(newMode); + storageDirty(storageId); + // Consent already obtained above; mark enabled so checkExternalAntenna() + // applies the GPIO instead of asking again. + globalData.externalAntennaEnabled = true; + checkExternalAntenna(); + } + } else { + setter(newMode); + storageDirty(storageId); + checkExternalAntenna(); + } +} +#endif // defined(COLORLCD) + +#endif // defined(EXTERNAL_ANTENNA) #if defined(PXX2) bool isPxx2IsrmChannelsCountAllowed(int channels) diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 4b49466e3..5cc56636d 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -140,11 +140,17 @@ void drawSourceValue(coord_t x, coord_t y, source_t channel, LcdFlags flags=0); extern uint8_t MODULE_BIND_ROWS(int moduleIdx); extern uint8_t MODULE_CHANNELS_ROWS(int moduleIdx); -#if defined(EXTERNAL_ANTENNA) && defined(INTERNAL_MODULE_PXX1) -void onAntennaSwitchConfirm(const char * result); +#if defined(EXTERNAL_ANTENNA) void checkExternalAntenna(); +#if defined(COLORLCD) +void setAntennaModeWithConfirm(int8_t newMode, uint8_t storageId, + std::function setter); +#endif +#if defined(INTERNAL_MODULE_PXX1) && !defined(COLORLCD) +void onAntennaSwitchConfirm(const char* result); void onAntennaSelection(const char* result); #endif +#endif #if defined(PXX2) inline bool isRacingModeAllowed() diff --git a/radio/src/hal/rotary_encoder.h b/radio/src/hal/rotary_encoder.h index 32fd1c505..4cbaa80c0 100644 --- a/radio/src/hal/rotary_encoder.h +++ b/radio/src/hal/rotary_encoder.h @@ -27,7 +27,7 @@ #define ROTENC_MIDSPEED 5 #define ROTENC_HIGHSPEED 50 -#if defined(RADIO_FAMILY_T20) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_T15) || defined(RADIO_T15PRO) || defined(RADIO_T22) || defined(RADIO_BUMBLEBEE) +#if defined(RADIO_FAMILY_T20) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_T15) || defined(RADIO_T15PRO) || defined(RADIO_T22) || defined(RADIO_BUMBLEBEE) || defined(RADIO_V12) #define ROTARY_ENCODER_GRANULARITY 4 #else #define ROTARY_ENCODER_GRANULARITY 2 diff --git a/radio/src/pulses/modules_helpers.cpp b/radio/src/pulses/modules_helpers.cpp index d1fe9dfe3..87137b129 100644 --- a/radio/src/pulses/modules_helpers.cpp +++ b/radio/src/pulses/modules_helpers.cpp @@ -30,7 +30,7 @@ bool isExternalAntennaEnabled() case ANTENNA_MODE_EXTERNAL: return true; case ANTENNA_MODE_PER_MODEL: - switch (g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode) { + switch (g_model.moduleData[INTERNAL_MODULE].antennaMode) { case ANTENNA_MODE_EXTERNAL: case ANTENNA_MODE_ASK: return globalData.externalAntennaEnabled; diff --git a/radio/src/storage/yaml/CMakeLists.txt b/radio/src/storage/yaml/CMakeLists.txt index 8dc63e4a6..aaa01d575 100644 --- a/radio/src/storage/yaml/CMakeLists.txt +++ b/radio/src/storage/yaml/CMakeLists.txt @@ -34,6 +34,8 @@ elseif(PCB STREQUAL PL18) endif() elseif(PCB STREQUAL T15PRO) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_t15pro.cpp) +elseif(PCB STREQUAL V12) + set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_v12.cpp) elseif(PCB STREQUAL T22) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_t22.cpp) elseif(PCB STREQUAL ST16) diff --git a/radio/src/storage/yaml/yaml_datastructs.cpp b/radio/src/storage/yaml/yaml_datastructs.cpp index 7f77d70b3..c8afc78d5 100644 --- a/radio/src/storage/yaml/yaml_datastructs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs.cpp @@ -42,6 +42,8 @@ #include "yaml_datastructs_t15pro.cpp" #elif defined(PCBTX16SMK3) #include "yaml_datastructs_tx16smk3.cpp" +#elif defined(PCBV12) + #include "yaml_datastructs_v12.cpp" #elif defined(RADIO_T22) #include "yaml_datastructs_t22.cpp" #elif defined(PCBPL18) diff --git a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp index bcaa9b162..3fda6b58c 100644 --- a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp @@ -581,7 +581,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_c14.cpp b/radio/src/storage/yaml/yaml_datastructs_c14.cpp index f4238e127..74538d9a4 100644 --- a/radio/src/storage/yaml/yaml_datastructs_c14.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_c14.cpp @@ -657,7 +657,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_f16.cpp b/radio/src/storage/yaml/yaml_datastructs_f16.cpp index 5292bd2f4..86dedd54e 100644 --- a/radio/src/storage/yaml/yaml_datastructs_f16.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_f16.cpp @@ -658,7 +658,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_gx12.cpp b/radio/src/storage/yaml/yaml_datastructs_gx12.cpp index 90753d911..500ca9aed 100644 --- a/radio/src/storage/yaml/yaml_datastructs_gx12.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_gx12.cpp @@ -605,7 +605,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_nb4p.cpp b/radio/src/storage/yaml/yaml_datastructs_nb4p.cpp index 828067c59..646c2e159 100644 --- a/radio/src/storage/yaml/yaml_datastructs_nb4p.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_nb4p.cpp @@ -648,7 +648,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp index 504da097c..225047926 100644 --- a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp @@ -655,7 +655,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_pa01.cpp b/radio/src/storage/yaml/yaml_datastructs_pa01.cpp index 6e688662c..c247c0abe 100644 --- a/radio/src/storage/yaml/yaml_datastructs_pa01.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_pa01.cpp @@ -681,7 +681,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_pl18.cpp b/radio/src/storage/yaml/yaml_datastructs_pl18.cpp index 47755c93e..f51429640 100644 --- a/radio/src/storage/yaml/yaml_datastructs_pl18.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_pl18.cpp @@ -655,7 +655,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_pl18u.cpp b/radio/src/storage/yaml/yaml_datastructs_pl18u.cpp index aff93211b..5fd50df7b 100644 --- a/radio/src/storage/yaml/yaml_datastructs_pl18u.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_pl18u.cpp @@ -648,7 +648,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_st16.cpp b/radio/src/storage/yaml/yaml_datastructs_st16.cpp index d54976a4c..f578e329f 100644 --- a/radio/src/storage/yaml/yaml_datastructs_st16.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_st16.cpp @@ -681,7 +681,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_t15.cpp b/radio/src/storage/yaml/yaml_datastructs_t15.cpp index 72b8d46d9..4b92b899f 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t15.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t15.cpp @@ -666,7 +666,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_t15pro.cpp b/radio/src/storage/yaml/yaml_datastructs_t15pro.cpp index d54976a4c..f578e329f 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t15pro.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t15pro.cpp @@ -681,7 +681,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_t20.cpp b/radio/src/storage/yaml/yaml_datastructs_t20.cpp index f1441e3c7..3e10d44ac 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t20.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t20.cpp @@ -590,7 +590,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_t22.cpp b/radio/src/storage/yaml/yaml_datastructs_t22.cpp index 72f20e7b4..6a5ce05d9 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t22.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t22.cpp @@ -681,7 +681,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp index eca692f00..870b71024 100644 --- a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp @@ -590,7 +590,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_tx15.cpp b/radio/src/storage/yaml/yaml_datastructs_tx15.cpp index d54976a4c..f578e329f 100644 --- a/radio/src/storage/yaml/yaml_datastructs_tx15.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_tx15.cpp @@ -681,7 +681,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_tx16smk3.cpp b/radio/src/storage/yaml/yaml_datastructs_tx16smk3.cpp index f7c226902..ab9899f68 100644 --- a/radio/src/storage/yaml/yaml_datastructs_tx16smk3.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_tx16smk3.cpp @@ -682,7 +682,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_v12.cpp b/radio/src/storage/yaml/yaml_datastructs_v12.cpp new file mode 100644 index 000000000..e53681d11 --- /dev/null +++ b/radio/src/storage/yaml/yaml_datastructs_v12.cpp @@ -0,0 +1,1048 @@ +// generated by generate_yaml.py + +// +// Enums first +// + +const struct YamlIdStr enum_BacklightMode[] = { + { e_backlight_mode_off, "backlight_mode_off" }, + { e_backlight_mode_keys, "backlight_mode_keys" }, + { e_backlight_mode_sticks, "backlight_mode_sticks" }, + { e_backlight_mode_all, "backlight_mode_all" }, + { e_backlight_mode_on, "backlight_mode_on" }, + { 0, NULL } +}; +const struct YamlIdStr enum_AntennaModes[] = { + { ANTENNA_MODE_INTERNAL, "MODE_INTERNAL" }, + { ANTENNA_MODE_ASK, "MODE_ASK" }, + { ANTENNA_MODE_PER_MODEL, "MODE_PER_MODEL" }, + { ANTENNA_MODE_EXTERNAL, "MODE_EXTERNAL" }, + { 0, NULL } +}; +const struct YamlIdStr enum_ModuleType[] = { + { MODULE_TYPE_NONE, "TYPE_NONE" }, + { MODULE_TYPE_PPM, "TYPE_PPM" }, + { MODULE_TYPE_XJT_PXX1, "TYPE_XJT_PXX1" }, + { MODULE_TYPE_ISRM_PXX2, "TYPE_ISRM_PXX2" }, + { MODULE_TYPE_DSM2, "TYPE_DSM2" }, + { MODULE_TYPE_CROSSFIRE, "TYPE_CROSSFIRE" }, + { MODULE_TYPE_MULTIMODULE, "TYPE_MULTIMODULE" }, + { MODULE_TYPE_R9M_PXX1, "TYPE_R9M_PXX1" }, + { MODULE_TYPE_R9M_PXX2, "TYPE_R9M_PXX2" }, + { MODULE_TYPE_R9M_LITE_PXX1, "TYPE_R9M_LITE_PXX1" }, + { MODULE_TYPE_R9M_LITE_PXX2, "TYPE_R9M_LITE_PXX2" }, + { MODULE_TYPE_GHOST, "TYPE_GHOST" }, + { MODULE_TYPE_R9M_LITE_PRO_PXX2, "TYPE_R9M_LITE_PRO_PXX2" }, + { MODULE_TYPE_SBUS, "TYPE_SBUS" }, + { MODULE_TYPE_XJT_LITE_PXX2, "TYPE_XJT_LITE_PXX2" }, + { MODULE_TYPE_FLYSKY_AFHDS2A, "TYPE_FLYSKY_AFHDS2A" }, + { MODULE_TYPE_FLYSKY_AFHDS3, "TYPE_FLYSKY_AFHDS3" }, + { MODULE_TYPE_LEMON_DSMP, "TYPE_LEMON_DSMP" }, + { 0, NULL } +}; +const struct YamlIdStr enum_TrainerMultiplex[] = { + { TRAINER_OFF, "OFF" }, + { TRAINER_ADD, "ADD" }, + { TRAINER_REPL, "REPL" }, + { 0, NULL } +}; +const struct YamlIdStr enum_BeeperMode[] = { + { e_mode_quiet, "mode_quiet" }, + { e_mode_alarms, "mode_alarms" }, + { e_mode_nokeys, "mode_nokeys" }, + { e_mode_all, "mode_all" }, + { 0, NULL } +}; +const struct YamlIdStr enum_BluetoothModes[] = { + { BLUETOOTH_OFF, "OFF" }, + { BLUETOOTH_TELEMETRY, "TELEMETRY" }, + { BLUETOOTH_TRAINER, "TRAINER" }, + { 0, NULL } +}; +const struct YamlIdStr enum_Functions[] = { + { FUNC_OVERRIDE_CHANNEL, "OVERRIDE_CHANNEL" }, + { FUNC_TRAINER, "TRAINER" }, + { FUNC_INSTANT_TRIM, "INSTANT_TRIM" }, + { FUNC_RESET, "RESET" }, + { FUNC_SET_TIMER, "SET_TIMER" }, + { FUNC_ADJUST_GVAR, "ADJUST_GVAR" }, + { FUNC_VOLUME, "VOLUME" }, + { FUNC_SET_FAILSAFE, "SET_FAILSAFE" }, + { FUNC_RANGECHECK, "RANGECHECK" }, + { FUNC_BIND, "BIND" }, + { FUNC_PLAY_SOUND, "PLAY_SOUND" }, + { FUNC_PLAY_TRACK, "PLAY_TRACK" }, + { FUNC_PLAY_VALUE, "PLAY_VALUE" }, + { FUNC_PLAY_SCRIPT, "PLAY_SCRIPT" }, + { FUNC_BACKGND_MUSIC, "BACKGND_MUSIC" }, + { FUNC_BACKGND_MUSIC_PAUSE, "BACKGND_MUSIC_PAUSE" }, + { FUNC_VARIO, "VARIO" }, + { FUNC_HAPTIC, "HAPTIC" }, + { FUNC_LOGS, "LOGS" }, + { FUNC_BACKLIGHT, "BACKLIGHT" }, + { FUNC_SCREENSHOT, "SCREENSHOT" }, + { FUNC_RACING_MODE, "RACING_MODE" }, + { FUNC_DISABLE_TOUCH, "DISABLE_TOUCH" }, + { FUNC_SET_SCREEN, "SET_SCREEN" }, + { FUNC_DISABLE_AUDIO_AMP, "DISABLE_AUDIO_AMP" }, + { FUNC_RGB_LED, "RGB_LED" }, + { FUNC_PUSH_CUST_SWITCH, "PUSH_CUST_SWITCH" }, + { FUNC_TEST, "TEST" }, + { 0, NULL } +}; +const struct YamlIdStr enum_SwitchConfig[] = { + { SWITCH_NONE, "NONE" }, + { SWITCH_TOGGLE, "TOGGLE" }, + { SWITCH_2POS, "2POS" }, + { SWITCH_3POS, "3POS" }, + { SWITCH_GLOBAL, "GLOBAL" }, + { SWITCH_none, "none" }, + { SWITCH_toggle, "toggle" }, + { SWITCH_2pos, "2pos" }, + { SWITCH_3pos, "3pos" }, + { 0, NULL } +}; +const struct YamlIdStr enum_fsStartPositionType[] = { + { FS_START_OFF, "START_OFF" }, + { FS_START_ON, "START_ON" }, + { FS_START_PREVIOUS, "START_PREVIOUS" }, + { 0, NULL } +}; +const struct YamlIdStr enum_booleanEnum[] = { + { BOOL_OFF, "OFF" }, + { BOOL_ON, "ON" }, + { 0, NULL } +}; +const struct YamlIdStr enum_QMPage[] = { + { QM_NONE, "NONE" }, + { QM_OPEN_QUICK_MENU, "OPEN_QUICK_MENU" }, + { QM_MANAGE_MODELS, "MANAGE_MODELS" }, + { QM_MODEL_SETUP, "MODEL_SETUP" }, + { QM_MODEL_FLIGHTMODES, "MODEL_FLIGHTMODES" }, + { QM_MODEL_INPUTS, "MODEL_INPUTS" }, + { QM_MODEL_MIXES, "MODEL_MIXES" }, + { QM_MODEL_OUTPUTS, "MODEL_OUTPUTS" }, + { QM_MODEL_CURVES, "MODEL_CURVES" }, + { QM_MODEL_GVARS, "MODEL_GVARS" }, + { QM_MODEL_LS, "MODEL_LS" }, + { QM_MODEL_SF, "MODEL_SF" }, + { QM_MODEL_SCRIPTS, "MODEL_SCRIPTS" }, + { QM_MODEL_TELEMETRY, "MODEL_TELEMETRY" }, + { QM_MODEL_NOTES, "MODEL_NOTES" }, + { QM_RADIO_SETUP, "RADIO_SETUP" }, + { QM_RADIO_GF, "RADIO_GF" }, + { QM_RADIO_TRAINER, "RADIO_TRAINER" }, + { QM_RADIO_HARDWARE, "RADIO_HARDWARE" }, + { QM_RADIO_VERSION, "RADIO_VERSION" }, + { QM_UI_THEMES, "UI_THEMES" }, + { QM_UI_SETUP, "UI_SETUP" }, + { QM_UI_SCREEN1, "UI_SCREEN1" }, + { QM_UI_SCREEN2, "UI_SCREEN2" }, + { QM_UI_SCREEN3, "UI_SCREEN3" }, + { QM_UI_SCREEN4, "UI_SCREEN4" }, + { QM_UI_SCREEN5, "UI_SCREEN5" }, + { QM_UI_SCREEN6, "UI_SCREEN6" }, + { QM_UI_SCREEN7, "UI_SCREEN7" }, + { QM_UI_SCREEN8, "UI_SCREEN8" }, + { QM_UI_SCREEN9, "UI_SCREEN9" }, + { QM_UI_SCREEN10, "UI_SCREEN10" }, + { QM_UI_ADD_PG, "UI_ADD_PG" }, + { QM_TOOLS_APPS, "TOOLS_APPS" }, + { QM_TOOLS_STORAGE, "TOOLS_STORAGE" }, + { QM_TOOLS_RESET, "TOOLS_RESET" }, + { QM_TOOLS_CHAN_MON, "TOOLS_CHAN_MON" }, + { QM_TOOLS_LS_MON, "TOOLS_LS_MON" }, + { QM_TOOLS_STATS, "TOOLS_STATS" }, + { QM_TOOLS_DEBUG, "TOOLS_DEBUG" }, + { QM_APP, "APP" }, + { 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_SPACEMOUSE_A, "SPACEMOUSE_A" }, + { MIXSRC_SPACEMOUSE_B, "SPACEMOUSE_B" }, + { MIXSRC_SPACEMOUSE_C, "SPACEMOUSE_C" }, + { MIXSRC_SPACEMOUSE_D, "SPACEMOUSE_D" }, + { MIXSRC_SPACEMOUSE_E, "SPACEMOUSE_E" }, + { MIXSRC_SPACEMOUSE_F, "SPACEMOUSE_F" }, + { MIXSRC_MIN, "MIN" }, + { MIXSRC_MAX, "MAX" }, + { MIXSRC_TX_VOLTAGE, "TX_VOLTAGE" }, + { MIXSRC_TX_TIME, "TX_TIME" }, + { MIXSRC_TX_GPS, "TX_GPS" }, + { 0, NULL } +}; +const struct YamlIdStr enum_LogicalSwitchesFunctions[] = { + { LS_FUNC_NONE, "FUNC_NONE" }, + { LS_FUNC_VEQUAL, "FUNC_VEQUAL" }, + { LS_FUNC_VALMOSTEQUAL, "FUNC_VALMOSTEQUAL" }, + { LS_FUNC_VPOS, "FUNC_VPOS" }, + { LS_FUNC_VNEG, "FUNC_VNEG" }, + { LS_FUNC_APOS, "FUNC_APOS" }, + { LS_FUNC_ANEG, "FUNC_ANEG" }, + { LS_FUNC_AND, "FUNC_AND" }, + { LS_FUNC_OR, "FUNC_OR" }, + { LS_FUNC_XOR, "FUNC_XOR" }, + { LS_FUNC_EDGE, "FUNC_EDGE" }, + { LS_FUNC_EQUAL, "FUNC_EQUAL" }, + { LS_FUNC_GREATER, "FUNC_GREATER" }, + { LS_FUNC_LESS, "FUNC_LESS" }, + { LS_FUNC_DIFFEGREATER, "FUNC_DIFFEGREATER" }, + { LS_FUNC_ADIFFEGREATER, "FUNC_ADIFFEGREATER" }, + { LS_FUNC_TIMER, "FUNC_TIMER" }, + { LS_FUNC_STICKY, "FUNC_STICKY" }, + { 0, NULL } +}; +const struct YamlIdStr enum_SwashType[] = { + { SWASH_TYPE_NONE, "TYPE_NONE" }, + { SWASH_TYPE_120, "TYPE_120" }, + { SWASH_TYPE_120X, "TYPE_120X" }, + { SWASH_TYPE_140, "TYPE_140" }, + { SWASH_TYPE_90, "TYPE_90" }, + { 0, NULL } +}; +const struct YamlIdStr enum_SwitchSources[] = { + { SWSRC_NONE, "NONE" }, + { SWSRC_ON, "ON" }, + { SWSRC_ONE, "ONE" }, + { SWSRC_TELEMETRY_STREAMING, "TELEMETRY_STREAMING" }, + { SWSRC_RADIO_ACTIVITY, "RADIO_ACTIVITY" }, + { SWSRC_TRAINER_CONNECTED, "TRAINER_CONNECTED" }, + { SWSRC_OFF, "OFF" }, + { 0, NULL } +}; +const struct YamlIdStr enum_PotsWarnMode[] = { + { POTS_WARN_OFF, "WARN_OFF" }, + { POTS_WARN_MANUAL, "WARN_MANUAL" }, + { POTS_WARN_AUTO, "WARN_AUTO" }, + { 0, NULL } +}; +const struct YamlIdStr enum_ModelOverridableEnable[] = { + { OVERRIDE_GLOBAL, "GLOBAL" }, + { OVERRIDE_OFF, "OFF" }, + { OVERRIDE_ON, "ON" }, + { 0, NULL } +}; +const struct YamlIdStr enum_FailsafeModes[] = { + { FAILSAFE_NOT_SET, "NOT_SET" }, + { FAILSAFE_HOLD, "HOLD" }, + { FAILSAFE_CUSTOM, "CUSTOM" }, + { FAILSAFE_NOPULSES, "NOPULSES" }, + { FAILSAFE_RECEIVER, "RECEIVER" }, + { 0, NULL } +}; +const struct YamlIdStr enum_TelemetrySensorFormula[] = { + { TELEM_FORMULA_ADD, "FORMULA_ADD" }, + { TELEM_FORMULA_AVERAGE, "FORMULA_AVERAGE" }, + { TELEM_FORMULA_MIN, "FORMULA_MIN" }, + { TELEM_FORMULA_MAX, "FORMULA_MAX" }, + { TELEM_FORMULA_MULTIPLY, "FORMULA_MULTIPLY" }, + { TELEM_FORMULA_TOTALIZE, "FORMULA_TOTALIZE" }, + { TELEM_FORMULA_CELL, "FORMULA_CELL" }, + { TELEM_FORMULA_CONSUMPTION, "FORMULA_CONSUMPTION" }, + { TELEM_FORMULA_DIST, "FORMULA_DIST" }, + { 0, NULL } +}; +const struct YamlIdStr enum_TelemetrySensorType[] = { + { TELEM_TYPE_CUSTOM, "TYPE_CUSTOM" }, + { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" }, + { 0, NULL } +}; +const struct YamlIdStr enum_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, NULL), + YAML_SIGNED( "studWeight", 8 ), + YAML_END +}; +static const struct YamlNode struct_TrainerData[] = { + YAML_ARRAY("calib", 16, 4, struct_signed_16, NULL), + YAML_ARRAY("mix", 16, 4, struct_TrainerMix, NULL), + YAML_END +}; +static const struct YamlNode struct_anonymous_1[] = { + YAML_STRING("name", 8), + YAML_END +}; +static const struct YamlNode struct_anonymous_2[] = { + YAML_SIGNED( "val", 16 ), + YAML_UNSIGNED( "mode", 8 ), + YAML_UNSIGNED( "param", 8 ), + YAML_SIGNED( "val2", 32 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_3[] = { + YAML_SIGNED( "val1", 32 ), + YAML_SIGNED( "val2", 32 ), + YAML_END +}; +static const struct YamlNode union_anonymous_0_elmts[] = { + YAML_STRUCT("play", 64, struct_anonymous_1, NULL), + YAML_STRUCT("all", 64, struct_anonymous_2, NULL), + YAML_STRUCT("clear", 64, struct_anonymous_3, NULL), + YAML_END +}; +static const struct YamlNode struct_CustomFunctionData[] = { + YAML_IDX, + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), + YAML_ENUM("func", 6, enum_Functions, NULL), + YAML_CUSTOM("def",r_customFn,w_customFn), + YAML_PADDING( 64 ), + YAML_PADDING( 1 ), + YAML_PADDING( 7 ), + YAML_END +}; +static const struct YamlNode struct_RGBLedColor[] = { + YAML_UNSIGNED( "r", 8 ), + YAML_UNSIGNED( "g", 8 ), + YAML_UNSIGNED( "b", 8 ), + YAML_END +}; +static const struct YamlNode struct_switchDef[] = { + YAML_IDX_CUST("sw",sw_idx_read,sw_idx_write), + YAML_STRING("name", 3), + YAML_ENUM("type", 3, enum_SwitchConfig, NULL), + YAML_ENUM("start", 2, enum_fsStartPositionType, switch_is_cfs), + YAML_ENUM("onColorLuaOverride", 1, enum_booleanEnum, switch_is_cfs), + YAML_ENUM("offColorLuaOverride", 1, enum_booleanEnum, switch_is_cfs), + YAML_PADDING( 1 ), + YAML_STRUCT("onColor", 24, struct_RGBLedColor, switch_is_cfs), + YAML_STRUCT("offColor", 24, struct_RGBLedColor, switch_is_cfs), + YAML_END +}; +static const struct YamlNode struct_KeyShortcut[] = { + YAML_IDX, + YAML_CUSTOM("shortcut",r_keyShortcut,w_keyShortcut), + YAML_PADDING( 8 ), + YAML_END +}; +static const struct YamlNode struct_QMFavorite[] = { + YAML_IDX, + YAML_CUSTOM("shortcut",r_qmFavorite,w_qmFavorite), + YAML_PADDING( 8 ), + YAML_END +}; +static const struct YamlNode struct_RadioData[] = { + YAML_UNSIGNED( "manuallyEdited", 1 ), + YAML_SIGNED( "timezoneMinutes", 3 ), + YAML_UNSIGNED( "ppmunit", 2 ), + YAML_PADDING( 2 ), + YAML_CUSTOM("semver",nullptr,w_semver), + YAML_CUSTOM("board",nullptr,w_board), + YAML_ARRAY("calib", 48, 20, struct_CalibData, NULL), + YAML_PADDING( 16 ), + YAML_UNSIGNED( "vBatWarn", 8 ), + YAML_SIGNED( "txVoltageCalibration", 8 ), + YAML_ENUM("backlightMode", 3, enum_BacklightMode, NULL), + YAML_ENUM("antennaMode", 2, enum_AntennaModes, NULL), + YAML_UNSIGNED( "disableRtcWarning", 1 ), + YAML_UNSIGNED( "keysBacklight", 1 ), + YAML_UNSIGNED( "dontPlayHello", 1 ), + YAML_ENUM("internalModule", 8, enum_ModuleType, NULL), + YAML_STRUCT("trainer", 128, struct_TrainerData, NULL), + YAML_UNSIGNED( "view", 8 ), + YAML_PADDING( 2 ), + YAML_UNSIGNED( "fai", 1 ), + YAML_SIGNED_CUST( "beepMode", 2, r_beeperMode, w_beeperMode ), + YAML_UNSIGNED( "alarmsFlash", 1 ), + YAML_UNSIGNED( "disableMemoryWarning", 1 ), + YAML_UNSIGNED( "disableAlarmWarning", 1 ), + YAML_UNSIGNED( "stickMode", 2 ), + YAML_SIGNED( "timezone", 5 ), + YAML_UNSIGNED( "adjustRTC", 1 ), + YAML_UNSIGNED( "inactivityTimer", 8 ), + YAML_CUSTOM("telemetryBaudrate",r_telemetryBaudrate,nullptr), + YAML_UNSIGNED( "internalModuleBaudrate", 3 ), + YAML_SIGNED( "splashMode", 3 ), + YAML_SIGNED_CUST( "hapticMode", 2, r_beeperMode, w_beeperMode ), + YAML_SIGNED( "switchesDelay", 8 ), + YAML_UNSIGNED( "lightAutoOff", 8 ), + YAML_UNSIGNED( "templateSetup", 8 ), + YAML_SIGNED( "PPM_Multiplier", 8 ), + YAML_SIGNED_CUST( "hapticLength", 8, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "beepLength", 3, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "hapticStrength", 3, r_5pos, w_5pos ), + YAML_UNSIGNED( "gpsFormat", 1 ), + YAML_UNSIGNED( "audioMuteEnable", 1 ), + YAML_UNSIGNED_CUST( "speakerPitch", 8, r_spPitch, w_spPitch ), + YAML_SIGNED_CUST( "speakerVolume", 8, r_vol, w_vol ), + YAML_SIGNED_CUST( "vBatMin", 8, r_vbat_min, w_vbat_min ), + YAML_SIGNED_CUST( "vBatMax", 8, r_vbat_max, w_vbat_max ), + YAML_UNSIGNED( "backlightBright", 8 ), + YAML_UNSIGNED( "globalTimer", 32 ), + YAML_UNSIGNED( "bluetoothBaudrate", 4 ), + YAML_ENUM("bluetoothMode", 4, enum_BluetoothModes, NULL), + 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_STRING("uiLanguage", 2), + YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "backgroundVolume", 4, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "varioPitch", 8, r_vPitch, w_vPitch ), + YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ), + YAML_SIGNED( "varioRepeat", 8 ), + YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active), + YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr), + YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr), + YAML_ARRAY("serialPort", 8, 4, struct_serialConfig, nullptr), + YAML_ARRAY("sticksConfig", 0, MAX_STICKS, struct_stickConfig, stick_name_valid), + YAML_ARRAY("slidersConfig", 0, MAX_POTS, struct_sliderConfig, nullptr), + YAML_PADDING( 8 ), + YAML_ARRAY("potsConfig", 4, 16, struct_potConfig, nullptr), + YAML_ARRAY("switchConfig", 80, 20, struct_switchDef, switchIsActive), + YAML_ARRAY("flexSwitches", 0, MAX_FLEX_SWITCHES, struct_flexSwitch, flex_sw_valid), + YAML_STRING("currModelFilename", 17), + YAML_UNSIGNED( "blOffBright", 8 ), + YAML_STRING("bluetoothName", 10), + YAML_STRING("ownerRegistrationID", 8), + YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr), + YAML_UNSIGNED( "rotEncMode", 3 ), + YAML_PADDING( 2 ), + YAML_PADDING( 3 ), + YAML_STRING("selectedTheme", 26), + YAML_SIGNED_CUST( "backlightSrc", 10, r_mixSrcRawEx, w_mixSrcRawEx ), + YAML_SIGNED( "radioGFDisabled", 1 ), + YAML_SIGNED( "radioTrainerDisabled", 1 ), + YAML_SIGNED( "modelHeliDisabled", 1 ), + YAML_SIGNED( "modelFMDisabled", 1 ), + YAML_SIGNED( "modelCurvesDisabled", 1 ), + YAML_SIGNED( "modelGVDisabled", 1 ), + YAML_SIGNED_CUST( "volumeSrc", 10, r_mixSrcRawEx, w_mixSrcRawEx ), + YAML_SIGNED( "modelLSDisabled", 1 ), + YAML_SIGNED( "modelSFDisabled", 1 ), + YAML_SIGNED( "modelCustomScriptsDisabled", 1 ), + YAML_SIGNED( "modelTelemetryDisabled", 1 ), + YAML_SIGNED( "disableTrainerPoweroffAlarm", 1 ), + YAML_SIGNED( "disablePwrOnOffHaptic", 1 ), + YAML_UNSIGNED( "modelQuickSelect", 1 ), + YAML_UNSIGNED( "oneLogPerDay", 1 ), + YAML_UNSIGNED( "keyLockEnabled", 1 ), + YAML_UNSIGNED( "labelSingleSelect", 1 ), + YAML_UNSIGNED( "labelMultiMode", 1 ), + YAML_UNSIGNED( "favMultiMode", 1 ), + YAML_UNSIGNED( "modelSelectLayout", 2 ), + YAML_UNSIGNED( "radioThemesDisabled", 1 ), + YAML_PADDING( 7 ), + YAML_UNSIGNED( "pwrOffIfInactive", 8 ), + YAML_ARRAY("keyShortcuts", 8, 6, struct_KeyShortcut, NULL), + YAML_ARRAY("qmFavorites", 8, 12, struct_QMFavorite, NULL), + 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, NULL), + 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", 5 ), + YAML_UNSIGNED_CUST( "value", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_END +}; +static const struct YamlNode struct_MixData[] = { + YAML_UNSIGNED( "destCh", 5 ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), + YAML_UNSIGNED( "carryTrim", 1 ), + YAML_UNSIGNED( "mixWarn", 2 ), + YAML_ENUM("mltpx", 2, enum_MixerMultiplex, NULL), + YAML_UNSIGNED( "delayPrec", 1 ), + YAML_UNSIGNED( "speedPrec", 1 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_PADDING( 1 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), + YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "delayUp", 8 ), + YAML_UNSIGNED( "delayDown", 8 ), + YAML_UNSIGNED( "speedUp", 8 ), + YAML_UNSIGNED( "speedDown", 8 ), + YAML_STRING("name", 6), + YAML_END +}; +static const struct YamlNode struct_LimitData[] = { + YAML_IDX, + YAML_SIGNED_CUST( "min", 11, in_read_weight, in_write_weight ), + YAML_SIGNED_CUST( "max", 11, in_read_weight, in_write_weight ), + YAML_SIGNED( "ppmCenter", 10 ), + YAML_SIGNED_CUST( "offset", 11, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "symetrical", 1 ), + YAML_UNSIGNED( "revert", 1 ), + YAML_PADDING( 3 ), + YAML_SIGNED( "curve", 8 ), + YAML_STRING("name", 6), + YAML_END +}; +static const struct YamlNode struct_ExpoData[] = { + YAML_UNSIGNED( "mode", 2 ), + YAML_UNSIGNED( "scale", 14 ), + YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), + YAML_SIGNED( "trimSource", 6 ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), + YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_PADDING( 2 ), + YAML_STRING("name", 6), + 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, NULL), + YAML_CUSTOM("def",r_logicSw,w_logicSw), + YAML_PADDING( 10 ), + YAML_PADDING( 10 ), + YAML_SIGNED_CUST( "andsw", 10, r_swtchSrc, w_swtchSrc ), + YAML_UNSIGNED( "lsPersist", 1 ), + YAML_UNSIGNED( "lsState", 1 ), + YAML_PADDING( 16 ), + YAML_UNSIGNED( "delay", 8 ), + YAML_UNSIGNED( "duration", 8 ), + YAML_END +}; +static const struct YamlNode struct_SwashRingData[] = { + YAML_ENUM("type", 8, enum_SwashType, NULL), + 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, 15, 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_PADDING( 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_UNSIGNED( "crsfArmingMode", 1 ), + YAML_PADDING( 4 ), + YAML_SIGNED_CUST( "crsfArmingTrigger", 10, r_swtchSrc, w_swtchSrc ), + YAML_SIGNED( "spare3", 6 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_13[] = { + YAML_UNSIGNED( "flags", 8 ), + YAML_UNSIGNED( "enableAETR", 1 ), + 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", 24, struct_anonymous_12, NULL), + YAML_STRUCT("dsmp", 16, 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, NULL), + YAML_PADDING( 2 ), + YAML_ENUM("antennaMode", 2, enum_AntennaModes, NULL), + 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, NULL), + 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, NULL), + 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_WidgetOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("signedValue",r_wov_signed,w_wov_signed), + YAML_CUSTOM("boolValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("stringValue",r_wov_string,w_wov_string), + YAML_CUSTOM("source",r_wov_source,w_wov_source), + YAML_CUSTOM("color",r_wov_color,w_wov_color), + YAML_END +}; +static const struct YamlNode struct_WidgetOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_wov_type,w_wov_type), + YAML_UNION("value", 0, union_WidgetOptionValue_elmts, select_wov), + YAML_END +}; +static const struct YamlNode struct_WidgetPersistentData[] = { + YAML_ARRAY("options", 0, 50, struct_WidgetOptionValueTyped, widget_option_is_active), + YAML_END +}; +static const struct YamlNode struct_ZonePersistentData[] = { + YAML_IDX, + YAML_CUSTOM("widgetName",r_widget_name,w_widget_name), + YAML_STRUCT("widgetData", 0, struct_WidgetPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode union_LayoutOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("boolValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("color",r_lov_color,w_lov_color), + YAML_END +}; +static const struct YamlNode struct_LayoutOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_lov_type,w_lov_type), + YAML_UNION("value", 0, union_LayoutOptionValue_elmts, select_lov), + YAML_END +}; +static const struct YamlNode struct_LayoutPersistentData[] = { + YAML_ARRAY("zones", 0, 10, struct_ZonePersistentData, widget_is_active), + YAML_ARRAY("options", 0, 10, struct_LayoutOptionValueTyped, layout_option_is_active), + YAML_END +}; +static const struct YamlNode struct_CustomScreenData[] = { + YAML_IDX, + YAML_CUSTOM("LayoutId",r_screen_id,w_screen_id), + YAML_STRUCT("layoutData", 0, struct_LayoutPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode struct_TopBarPersistentData[] = { + YAML_ARRAY("zones", 0, 5, struct_ZonePersistentData, widget_is_active), + YAML_END +}; +static const struct YamlNode struct_customSwitch[] = { + YAML_IDX_CUST("sw",cfs_idx_read,cfs_idx_write), + YAML_STRING("name", 3), + YAML_ENUM("type", 3, enum_SwitchConfig, NULL), + YAML_UNSIGNED( "group", 2 ), + YAML_ENUM("start", 2, enum_fsStartPositionType, NULL), + YAML_UNSIGNED( "state", 1 ), + YAML_ENUM("onColorLuaOverride", 1, enum_booleanEnum, NULL), + YAML_ENUM("offColorLuaOverride", 1, enum_booleanEnum, NULL), + YAML_PADDING( 6 ), + YAML_STRUCT("onColor", 24, struct_RGBLedColor, isAlwaysActive), + YAML_STRUCT("offColor", 24, struct_RGBLedColor, isAlwaysActive), + YAML_END +}; +static const struct YamlNode struct_USBJoystickChData[] = { + YAML_IDX, + YAML_ENUM("mode", 3, enum_USBJoystickCh, NULL), + YAML_UNSIGNED( "inversion", 1 ), + YAML_UNSIGNED( "param", 4 ), + YAML_UNSIGNED( "btn_num", 5 ), + YAML_UNSIGNED( "switch_npos", 3 ), + YAML_END +}; +static const struct YamlNode struct_ModelData[] = { + YAML_CUSTOM("semver",nullptr,w_semver), + YAML_STRUCT("header", 1048, struct_ModelHeader, NULL), + YAML_ARRAY("timers", 136, 3, struct_TimerData, NULL), + YAML_UNSIGNED( "telemetryProtocol", 3 ), + YAML_UNSIGNED( "thrTrim", 1 ), + YAML_UNSIGNED( "noGlobalFunctions", 1 ), + YAML_UNSIGNED( "displayTrims", 2 ), + YAML_UNSIGNED( "ignoreSensorIds", 1 ), + YAML_SIGNED( "trimInc", 3 ), + YAML_UNSIGNED( "disableThrottleWarning", 1 ), + YAML_UNSIGNED( "displayChecklist", 1 ), + YAML_UNSIGNED( "extendedLimits", 1 ), + YAML_UNSIGNED( "extendedTrims", 1 ), + YAML_UNSIGNED( "throttleReversed", 1 ), + YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ), + YAML_UNSIGNED( "disableTelemetryWarning", 1 ), + YAML_UNSIGNED( "showInstanceIds", 1 ), + YAML_UNSIGNED( "checklistInteractive", 1 ), + YAML_PADDING( 4 ), + YAML_SIGNED( "customThrottleWarningPosition", 8 ), + YAML_UNSIGNED( "beepANACenter", 16 ), + YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), + YAML_ARRAY("limitData", 104, 32, struct_LimitData, NULL), + YAML_ARRAY("expoData", 144, 64, struct_ExpoData, NULL), + YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL), + YAML_ARRAY("points", 8, 512, struct_signed_8, NULL), + YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL), + YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active), + YAML_STRUCT("swashR", 64, struct_SwashRingData, swash_is_active), + YAML_ARRAY("flightModeData", 480, 9, struct_FlightModeData, fmd_is_active), + YAML_UNSIGNED_CUST( "thrTraceSrc", 8, r_thrSrc, w_thrSrc ), + YAML_CUSTOM("switchWarningState",r_swtchWarn,nullptr), + YAML_ARRAY("switchWarning", 2, 32, struct_swtchWarn, nullptr), + YAML_ARRAY("gvars", 56, 15, 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, NULL), + YAML_ENUM("jitterFilter", 2, enum_ModelOverridableEnable, NULL), + 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, 99, struct_TelemetrySensor, NULL), + YAML_ARRAY("screenData", 0, 10, struct_CustomScreenData, screen_is_active), + YAML_STRUCT("topbarData", 0, struct_TopBarPersistentData, isAlwaysActive), + YAML_ARRAY("topbarWidgetWidth", 8, 5, struct_unsigned_8, NULL), + YAML_UNSIGNED( "view", 8 ), + YAML_STRING("modelRegistrationID", 8), + YAML_CUSTOM("functionSwitchConfig",r_functionSwitchConfig,nullptr), + YAML_CUSTOM("functionSwitchGroup",r_functionSwitchGroup,nullptr), + YAML_CUSTOM("functionSwitchStartConfig",r_functionSwitchStartConfig,nullptr), + YAML_CUSTOM("functionSwitchLogicalState",r_functionSwitchLogicalState,nullptr), + YAML_ARRAY("switchNames", 0, NUM_FUNCTIONS_SWITCHES, struct_cfsNameConfig, nullptr), + YAML_ARRAY("functionSwitchLedONColor", 0, NUM_FUNCTIONS_SWITCHES, struct_cfsOnColorConfig, nullptr), + YAML_ARRAY("functionSwitchLedOFFColor", 0, NUM_FUNCTIONS_SWITCHES, struct_cfsOffColorConfig, nullptr), + YAML_ARRAY("customSwitches", 88, 6, struct_customSwitch, isAlwaysActive), + YAML_ARRAY("cfsGroupOn", 1, 8, struct_cfsGroupOn, cfsGroupIsActive), + YAML_PADDING( 8 ), + YAML_UNSIGNED( "usbJoystickExtMode", 1 ), + YAML_ENUM("usbJoystickIfMode", 3, enum_USBJoystickIfMode, NULL), + YAML_UNSIGNED( "usbJoystickCircularCut", 4 ), + YAML_ARRAY("usbJoystickCh", 16, 26, struct_USBJoystickChData, NULL), + YAML_ENUM("radioThemesDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("radioGFDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("radioTrainerDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelHeliDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelFMDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelCurvesDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelGVDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelLSDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelSFDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelCustomScriptsDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelTelemetryDisabled", 2, enum_ModelOverridableEnable, NULL), + 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/storage/yaml/yaml_datastructs_x10.cpp b/radio/src/storage/yaml/yaml_datastructs_x10.cpp index 0c942f03f..81665e00c 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x10.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x10.cpp @@ -657,7 +657,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; @@ -735,7 +735,8 @@ static const struct YamlNode struct_ModuleData[] = { YAML_UNSIGNED( "channelsStart", 8 ), YAML_SIGNED_CUST( "channelsCount", 8, r_channelsCount, w_channelsCount ), YAML_ENUM("failsafeMode", 4, enum_FailsafeModes, NULL), - YAML_PADDING( 4 ), + YAML_PADDING( 2 ), + YAML_ENUM("antennaMode", 2, enum_AntennaModes, NULL), YAML_UNION("mod", 200, union_anonymous_4_elmts, select_mod_type), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_x9d.cpp b/radio/src/storage/yaml/yaml_datastructs_x9d.cpp index 54992e240..2faea2ac2 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9d.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9d.cpp @@ -581,7 +581,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_x9dp2019.cpp b/radio/src/storage/yaml/yaml_datastructs_x9dp2019.cpp index 54992e240..2faea2ac2 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9dp2019.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9dp2019.cpp @@ -581,7 +581,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_x9e.cpp b/radio/src/storage/yaml/yaml_datastructs_x9e.cpp index 20ec6ec9d..3e6c1ee61 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9e.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9e.cpp @@ -581,7 +581,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_xlite.cpp b/radio/src/storage/yaml/yaml_datastructs_xlite.cpp index bcaa9b162..1d3a083ae 100644 --- a/radio/src/storage/yaml/yaml_datastructs_xlite.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_xlite.cpp @@ -581,7 +581,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; @@ -659,7 +659,8 @@ static const struct YamlNode struct_ModuleData[] = { YAML_UNSIGNED( "channelsStart", 8 ), YAML_SIGNED_CUST( "channelsCount", 8, r_channelsCount, w_channelsCount ), YAML_ENUM("failsafeMode", 4, enum_FailsafeModes, NULL), - YAML_PADDING( 4 ), + YAML_PADDING( 2 ), + YAML_ENUM("antennaMode", 2, enum_AntennaModes, NULL), YAML_UNION("mod", 200, union_anonymous_4_elmts, select_mod_type), YAML_END }; diff --git a/radio/src/storage/yaml/yaml_datastructs_xlites.cpp b/radio/src/storage/yaml/yaml_datastructs_xlites.cpp index f30b72c50..d096002dd 100644 --- a/radio/src/storage/yaml/yaml_datastructs_xlites.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_xlites.cpp @@ -586,7 +586,7 @@ static const struct YamlNode struct_anonymous_6[] = { YAML_PADDING( 2 ), YAML_UNSIGNED( "receiverTelemetryOff", 1 ), YAML_UNSIGNED( "receiverHigherChannels", 1 ), - YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 2 ), YAML_PADDING( 8 ), YAML_END }; @@ -664,7 +664,8 @@ static const struct YamlNode struct_ModuleData[] = { YAML_UNSIGNED( "channelsStart", 8 ), YAML_SIGNED_CUST( "channelsCount", 8, r_channelsCount, w_channelsCount ), YAML_ENUM("failsafeMode", 4, enum_FailsafeModes, NULL), - YAML_PADDING( 4 ), + YAML_PADDING( 2 ), + YAML_ENUM("antennaMode", 2, enum_AntennaModes, NULL), YAML_UNION("mod", 200, union_anonymous_4_elmts, select_mod_type), YAML_END }; diff --git a/radio/src/targets/common/arm/stm32/pwr_driver.cpp b/radio/src/targets/common/arm/stm32/pwr_driver.cpp index d6f6b99c0..356e2ddc8 100644 --- a/radio/src/targets/common/arm/stm32/pwr_driver.cpp +++ b/radio/src/targets/common/arm/stm32/pwr_driver.cpp @@ -47,6 +47,12 @@ void pwrInit() INTERNAL_MODULE_OFF(); #endif + // Internal module select +#if defined(HARDWARE_INTERNAL_MODULE) && defined(INTMODULE_ANTSEL_GPIO) + gpio_init(INTMODULE_ANTSEL_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW); + gpio_clear(INTMODULE_ANTSEL_GPIO); +#endif + // External module power #if defined(HARDWARE_EXTERNAL_MODULE) && defined(EXTMODULE_PWR_GPIO) gpio_init(EXTMODULE_PWR_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW); @@ -125,7 +131,13 @@ bool pwrPressed() } #endif #if defined(PWR_EXTRA_SWITCH_GPIO) - return !gpio_read(PWR_SWITCH_GPIO) || !gpio_read(PWR_EXTRA_SWITCH_GPIO); + + #if defined(PWR_BUTTON_DUAL) + return pwrForcePressed(); + #else + return !gpio_read(PWR_SWITCH_GPIO) || !gpio_read(PWR_EXTRA_SWITCH_GPIO); + #endif + #elif defined(PWR_SWITCH_GPIO) return !gpio_read(PWR_SWITCH_GPIO); #else @@ -153,6 +165,6 @@ void pwrResetHandler() #if defined(BOOT) void* _pwr_init_hook[] __INIT_HOOK = { - (void*)pwrResetHandler, + (void*)pwrResetHandler, }; #endif diff --git a/radio/src/targets/common/arm/stm32/stm32_i2c_driver.cpp b/radio/src/targets/common/arm/stm32/stm32_i2c_driver.cpp index 156519edd..c5f87e16c 100644 --- a/radio/src/targets/common/arm/stm32/stm32_i2c_driver.cpp +++ b/radio/src/targets/common/arm/stm32/stm32_i2c_driver.cpp @@ -32,7 +32,7 @@ #endif #include "debug.h" -#define MAX_I2C_DEVICES 2 +#define MAX_I2C_DEVICES 4 struct stm32_i2c_device { I2C_HandleTypeDef handle; diff --git a/radio/src/targets/common/arm/stm32/stm32_i2c_driver.h b/radio/src/targets/common/arm/stm32/stm32_i2c_driver.h index 015015334..a31837059 100644 --- a/radio/src/targets/common/arm/stm32/stm32_i2c_driver.h +++ b/radio/src/targets/common/arm/stm32/stm32_i2c_driver.h @@ -27,8 +27,8 @@ #include -// Maxmimum 2 I2C bus instances -enum { I2C_Bus_1 = 0, I2C_Bus_2 }; +// I2C bus instances +enum { I2C_Bus_1 = 0, I2C_Bus_2, I2C_Bus_3, I2C_Bus_4 }; typedef struct { I2C_TypeDef* I2Cx; diff --git a/radio/src/targets/common/arm/stm32/usb_driver.cpp b/radio/src/targets/common/arm/stm32/usb_driver.cpp index 291f94c3d..c204ca887 100644 --- a/radio/src/targets/common/arm/stm32/usb_driver.cpp +++ b/radio/src/targets/common/arm/stm32/usb_driver.cpp @@ -128,13 +128,18 @@ void usbInit() #endif gpio_init_af(USB_GPIO_DM, USB_GPIO_AF, GPIO_PIN_SPEED_VERY_HIGH); gpio_init_af(USB_GPIO_DP, USB_GPIO_AF, GPIO_PIN_SPEED_VERY_HIGH); - + #if defined(USB_GPIO_VBUS) #if defined(USB_GPIO_VBUS_OPEN_DRAIN) gpio_init(USB_GPIO_VBUS, GPIO_IN_PU, GPIO_PIN_SPEED_LOW); #else gpio_init(USB_GPIO_VBUS, GPIO_IN, GPIO_PIN_SPEED_LOW); #endif + +#if defined(USB_GPIO_SEL) + gpio_init(USB_GPIO_SEL, GPIO_OUT, GPIO_PIN_SPEED_LOW); + gpio_set(USB_GPIO_SEL); +#endif // prime debounce state... usbPlugged(); #endif diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 6f974fec0..b85ab0039 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -54,6 +54,7 @@ if (PCB STREQUAL X10) set(DEFAULT_INTERNAL_MODULE ISRM_PXX2 CACHE STRING "Default internal module") set(BLUETOOTH ON) set(AUX_SERIAL OFF) + set(EXTERNAL_ANTENNA ON) add_definitions(-DHARDWARE_POWER_MANAGEMENT_UNIT) add_definitions(-DMANUFACTURER_FRSKY) elseif (PCBREV STREQUAL T15) @@ -135,12 +136,14 @@ if (PCB STREQUAL X10) set(FLAVOUR x10) set(DEFAULT_INTERNAL_MODULE XJT_PXX1 CACHE STRING "Default internal module") set(BLUETOOTH ON) + set(EXTERNAL_ANTENNA ON) add_definitions(-DMANUFACTURER_FRSKY) endif() elseif (PCB STREQUAL X12S) set(DEFAULT_INTERNAL_MODULE XJT_PXX1 CACHE STRING "Default internal module") set(FLAVOUR x12s) set(BLUETOOTH ON) + set(EXTERNAL_ANTENNA ON) set(PCBREV "13" CACHE STRING "PCB Revision") set(AUX2_SERIAL ON) # wire to GPS set(USE_VS1053B ON) @@ -149,6 +152,11 @@ elseif (PCB STREQUAL X12S) add_definitions(-DMANUFACTURER_FRSKY) endif() +# Handset supports external antenna +if(EXTERNAL_ANTENNA) + add_definitions(-DEXTERNAL_ANTENNA) +endif() + # enable GPS support if there is AUX port available unless otherwise disabled if(AUX_SERIAL) option(INTERNAL_GPS "Support for internal GPS" ON) diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index 868c9d621..bff3139df 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -485,10 +485,7 @@ #define FLYSKY_HALL_DMA_Stream_TX LL_DMA_STREAM_4 #endif -// Internal PXX1 Module: -// -> let's assume all internal XJT modules used are either X10 or X12S type -#define EXTERNAL_ANTENNA - +// Internal Module #define INTMODULE_PWR_GPIO GPIO_PIN(GPIOA, 8) // PA.08 #define INTMODULE_TX_GPIO GPIO_PIN(GPIOB, 6) // PB.06 #define INTMODULE_RX_GPIO GPIO_PIN(GPIOB, 7) // PB.07 diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt index 7cfd625ce..9d6317d44 100644 --- a/radio/src/targets/taranis/CMakeLists.txt +++ b/radio/src/targets/taranis/CMakeLists.txt @@ -360,21 +360,6 @@ elseif(PCB STREQUAL X7) set(BLUETOOTH YES) set(ROTARY_ENCODER YES) add_definitions(-DMANUFACTURER_FRSKY) - elseif(PCBREV STREQUAL V12) - set(DEFAULT_INTERNAL_MODULE CROSSFIRE CACHE STRING "Default internal module") - set(INTERNAL_MODULE_SERIAL YES) - set(MODULE_SIZE_STD YES) - set(FLAVOUR v12) - set(CPU_TYPE_FULL STM32F407xG) - set(ROTARY_ENCODER YES) - set(USB_CHARGER YES) - add_definitions(-DSTM32_SUPPORT_32BIT_TIMERS) - set(PXX2 ON) - set(ENABLE_SERIAL_PASSTHROUGH ON CACHE BOOL "Enable serial passthrough") - set(CSD203_SENSOR ON) - if (NOT BLUETOOTH) - set(AUX_SERIAL ON) - endif() elseif(PCBREV STREQUAL V14 OR PCBREV STREQUAL V14LCD) set(DEFAULT_INTERNAL_MODULE CROSSFIRE CACHE STRING "Default internal module") set(INTERNAL_MODULE_SERIAL YES) diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 433dbef38..31940ab82 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -104,7 +104,7 @@ #define USE_EXTI15_10_IRQ #define EXTI15_10_IRQ_Priority 5 #endif -#elif defined(RADIO_TX12) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_ZORRO) || defined(RADIO_MT12) || defined(RADIO_POCKET) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) || defined(RADIO_GX12) +#elif defined(RADIO_TX12) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_ZORRO) || defined(RADIO_MT12) || defined(RADIO_POCKET) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_GX12) #define ROTARY_ENCODER_NAVIGATION #define ROTARY_ENCODER_GPIO GPIOE #define ROTARY_ENCODER_GPIO_PIN_A LL_GPIO_PIN_9 // PE.9 @@ -125,7 +125,7 @@ #define USE_EXTI15_10_IRQ #define EXTI15_10_IRQ_Priority 5 #endif - #if defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_ZORRO) || defined(RADIO_MT12) || defined(RADIO_POCKET) || defined(RADIO_T14) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) + #if defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_ZORRO) || defined(RADIO_MT12) || defined(RADIO_POCKET) || defined(RADIO_T14) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) #define ROTARY_ENCODER_INVERTED #endif #endif @@ -137,7 +137,7 @@ #endif // 6POS SW -#if defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) +#if defined(RADIO_V14) || defined(RADIO_V14LCD) #define SIXPOS_SWITCH_INDEX 6 #define SIXPOS_LED_RED 200 #define SIXPOS_LED_GREEN 0 @@ -192,7 +192,7 @@ #define ADC_VREF_PREC2 330 #elif defined(RADIO_GX12) #define ADC_VREF_PREC2 330 -#elif defined(RADIO_V12) || defined(RADIO_V14) || defined(RADIO_V14LCD) +#elif defined(RADIO_V14) || defined(RADIO_V14LCD) #define ADC_VREF_PREC2 330 #elif defined(PCBX7) #define ADC_VREF_PREC2 330 @@ -220,7 +220,7 @@ #elif defined(RADIO_FAMILY_T20) || defined(RADIO_BUMBLEBEE) #define PWR_SWITCH_GPIO GPIO_PIN(GPIOG, 5) // PG.05 #define PWR_ON_GPIO GPIO_PIN(GPIOG, 6) // PG.06 -#elif defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) +#elif defined(RADIO_V14) || defined(RADIO_V14LCD) #define PWR_SWITCH_GPIO GPIO_PIN(GPIOD, 1) // PD.01 #define PWR_ON_GPIO GPIO_PIN(GPIOB, 2) // PB.02 #else @@ -316,7 +316,7 @@ #define INTMODULE_DMA_STREAM_IRQ DMA2_Stream7_IRQn #define INTMODULE_DMA_STREAM_IRQHandler DMA2_Stream7_IRQHandler #define INTMODULE_DMA_CHANNEL LL_DMA_CHANNEL_4 -#elif defined(RADIO_ZORRO) || defined(RADIO_POCKET) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_MT12) || defined(RADIO_T20V2) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) || defined(RADIO_GX12) || defined(RADIO_BUMBLEBEE) +#elif defined(RADIO_ZORRO) || defined(RADIO_POCKET) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_MT12) || defined(RADIO_T20V2) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_GX12) || defined(RADIO_BUMBLEBEE) #if defined(RADIO_T20V2) || defined(RADIO_BUMBLEBEE) #define INTMODULE_BOOTCMD_GPIO GPIO_PIN(GPIOE, 4) // PE.04 #define INTMODULE_PWR_GPIO GPIO_PIN(GPIOC, 6) // PC.06 @@ -328,7 +328,7 @@ #endif #define INTMODULE_PWR_GPIO GPIO_PIN(GPIOC, 4) // PC.04 #endif -#if defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) +#if defined(RADIO_V14) || defined(RADIO_V14LCD) #define INTMODULE_BOOTCMD_DEFAULT 1 // RESET #else #define INTMODULE_BOOTCMD_DEFAULT 0 // RESET @@ -413,8 +413,8 @@ #endif // External Module -#if defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_X9DP2019) || defined(PCBX7ACCESS) || defined(RADIO_ZORRO) || defined(RADIO_POCKET) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_MT12) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) || defined(RADIO_T12MAX) || defined(RADIO_GX12) - #if defined(RADIO_X9DP2019) || defined(RADIO_X7ACCESS) || defined(RADIO_ZORRO)|| defined(RADIO_POCKET) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_MT12)|| defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) +#if defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_X9DP2019) || defined(PCBX7ACCESS) || defined(RADIO_ZORRO) || defined(RADIO_POCKET) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_MT12) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_T12MAX) || defined(RADIO_GX12) + #if defined(RADIO_X9DP2019) || defined(RADIO_X7ACCESS) || defined(RADIO_ZORRO)|| defined(RADIO_POCKET) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_MT12)|| defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) #define EXTMODULE_PWR_GPIO GPIO_PIN(GPIOD, 8) // PD.08 #elif defined(PCBX9LITE) #define EXTMODULE_PWR_GPIO GPIO_PIN(GPIOA, 8) // PA.08 @@ -447,7 +447,7 @@ #define EXTMODULE_USART_TX_DMA_STREAM LL_DMA_STREAM_6 #define EXTMODULE_USART_RX_DMA_CHANNEL LL_DMA_CHANNEL_5 #define EXTMODULE_USART_RX_DMA_STREAM LL_DMA_STREAM_1 - #if defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) + #if defined(RADIO_V14) || defined(RADIO_V14LCD) #define EXTMODULE_TX_INVERT_GPIO GPIO_PIN(GPIOE, 7) // PE.07 #define EXTMODULE_RX_INVERT_GPIO GPIO_PIN(GPIOE, 15) // PE.15 #endif @@ -563,7 +563,7 @@ #else #define TELEMETRY_SET_INPUT 0 #endif -#if defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) +#if defined(RADIO_V14) || defined(RADIO_V14LCD) #define TELEMETRY_RX_REV_GPIO GPIO_PIN(GPIOE, 0) // PE.00 #define TELEMETRY_TX_REV_GPIO GPIO_PIN(GPIOE, 0) // PE.00 #endif @@ -688,7 +688,7 @@ #if defined(PCBX9LITE) || defined(PCBXLITE) || defined(RADIO_X9DP2019) || \ defined(PCBX7ACCESS) || defined(RADIO_ZORRO) || defined(RADIO_POCKET) || \ defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_MT12) ||\ - defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) \ + defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_V14) || defined(RADIO_V14LCD) \ || defined(RADIO_GX12) #define TRAINER_MODULE_CPPM_TIMER TIM3 #define TRAINER_MODULE_CPPM_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) @@ -852,7 +852,7 @@ #if defined(PCBXLITE) || defined(PCBX9LITE) || defined(PCBX7ACCESS) || \ defined(RADIO_ZORRO) || defined(RADIO_POCKET) || defined(RADIO_X9DP2019) || \ - defined(RADIO_GX12) || defined(RADIO_V12) || defined(RADIO_V14) || defined(RADIO_V14LCD) + defined(RADIO_GX12) || defined(RADIO_V14) || defined(RADIO_V14LCD) #define I2C_B1_SCL_GPIO GPIO_PIN(GPIOB, 8) // PB.08 #define I2C_B1_SDA_GPIO GPIO_PIN(GPIOB, 9) // PB.09 #else diff --git a/radio/src/targets/taranis/lcd_driver_spi.cpp b/radio/src/targets/taranis/lcd_driver_spi.cpp index ada36f5c7..5de7d8d95 100644 --- a/radio/src/targets/taranis/lcd_driver_spi.cpp +++ b/radio/src/targets/taranis/lcd_driver_spi.cpp @@ -37,7 +37,7 @@ #if OLED_SCREEN #define LCD_CONTRAST_OFFSET 0 -#elif defined(RADIO_FAMILY_JUMPER_T12) || defined(MANUFACTURER_RADIOMASTER) || defined(RADIO_COMMANDO8) || defined(RADIO_TPRO) || defined(RADIO_T12MAX) || defined(RADIO_V12) || defined(RADIO_V14) || defined(RADIO_V14LCD) +#elif defined(RADIO_FAMILY_JUMPER_T12) || defined(MANUFACTURER_RADIOMASTER) || defined(RADIO_COMMANDO8) || defined(RADIO_TPRO) || defined(RADIO_T12MAX) || defined(RADIO_V14) || defined(RADIO_V14LCD) #define LCD_CONTRAST_OFFSET -10 #else #define LCD_CONTRAST_OFFSET 160 @@ -160,23 +160,10 @@ void lcdStart() #else #if LCD_VERTICAL_INVERT // T12 and TX12 have the screen inverted. - #if defined(RADIO_V12) - lcdWriteCommand(0xe2); // (14) Soft reset - lcdWriteCommand(0xa0); // Set seg - lcdWriteCommand(0xc8); // Set com - lcdWriteCommand(0xf8); // Set booster - lcdWriteCommand(0x00); // 5x - lcdWriteCommand(0xa2); // Set bias=1/6 - lcdWriteCommand(0x26); // Set internal rb/ra=5.0 - lcdWriteCommand(0x2f); // All built-in power circuits on - lcdWriteCommand(0x81); // Set contrast - lcdWriteCommand(0x1F); // Set Vop - lcdWriteCommand(0xa6); // Set display mode - #else lcdWriteCommand(0xe2); // (14) Soft reset #if LCD_HORIZONTAL_INVERT lcdWriteCommand(0xa1); // Set seg -#else +#else lcdWriteCommand(0xa0); // Set seg #endif lcdWriteCommand(0xc8); // Set com @@ -189,7 +176,6 @@ void lcdStart() lcdWriteCommand(0x81); // Set contrast lcdWriteCommand(0x0A); // Set Vop lcdWriteCommand(0xa6); // Set display mode - #endif #else #if defined(RADIO_V14) || defined(RADIO_V14LCD) lcdWriteCommand(0xe2); // (14) Soft reset @@ -453,7 +439,7 @@ void lcdSetRefVolt(uint8_t val) WAIT_FOR_DMA_END(); #endif -#if defined(RADIO_V12) || defined(RADIO_V14) || defined(RADIO_V14LCD) +#if defined(RADIO_V14) || defined(RADIO_V14LCD) lcdWriteCommand(0x81); // Set Vop lcdWriteCommand(val+LCD_CONTRAST_OFFSET+20);// 0-255 #else diff --git a/radio/src/targets/taranis/usb_descriptor.h b/radio/src/targets/taranis/usb_descriptor.h index cb83161da..f72c88148 100644 --- a/radio/src/targets/taranis/usb_descriptor.h +++ b/radio/src/targets/taranis/usb_descriptor.h @@ -93,10 +93,6 @@ #define USB_NAME "iFlight Commando 8" #define USB_MANUFACTURER 'i', 'F', 'l', 'i', 'g', 'h', 't', '-' /* 8 bytes */ #define USB_PRODUCT 'C', 'o', 'm', 'm', 'a', 'n', 'd', 'o' /* 8 Bytes */ -#elif defined(RADIO_V12) - #define USB_NAME "HelloRadioSky V12" - #define USB_MANUFACTURER 'H', 'R', 'S', 'k', 'y', ' ', ' ', ' ' /* 8 bytes */ - #define USB_PRODUCT 'V', '1', '2', ' ', ' ', ' ', ' ', ' ' /* 8 Bytes */ #elif defined(RADIO_V14) #define USB_NAME "HelloRadioSky V14" #define USB_MANUFACTURER 'H', 'R', 'S', 'k', 'y', ' ', ' ', ' ' /* 8 bytes */ diff --git a/radio/src/targets/v12/CMakeLists.txt b/radio/src/targets/v12/CMakeLists.txt new file mode 100644 index 000000000..44cb97d9e --- /dev/null +++ b/radio/src/targets/v12/CMakeLists.txt @@ -0,0 +1,195 @@ +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) +option(DISK_CACHE "Enable SD card disk cache" ON) + +set(FIRMWARE_QSPI YES) +set(FIRMWARE_FORMAT_UF2 YES) +set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)") +set(CPU_TYPE STM32H7) +set(HSE_VALUE 8000000) +set(SDCARD YES) +set(STORAGE_MODELSLIST YES) +set(HAPTIC YES) +set(GUI_DIR colorlcd) +set(BITMAPS_DIR 320x240) +set(TARGET_DIR v12) +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(INTERNAL_MODULE_AFHDS3 NO) +set(INTERNAL_EXTERNAL_ANT YES) +set(ROTARY_ENCODER YES) +set(FUNCTION_SWITCHES_WITH_RGB YES) + +#option(STICKS_DEAD_ZONE "Enable sticks dead zone" YES) + +# IMU is not populated on production V12/V12p units. +set(IMU OFF) + +# for size report script +set(CPU_TYPE_FULL STM32H750xB) +set(TARGET_LINKER_DIR stm32h750_sdram) +set(TARGET_EXTRAM_START 0xC0000000) +set(SIZE_TARGET_MEM_DEFINE "MEM_SIZE_SDRAM1=8192") +set(FIRMWARE_STRIP_BOOTLOADER YES) + +add_definitions(-DPCBV12 -DPCBHORUS) +add_definitions(-DSTM32_SUPPORT_32BIT_TIMERS) +add_definitions(-DFIRMWARE_QSPI) +add_definitions(-DFIRMWARE_FORMAT_UF2) +add_definitions(-DUSE_CUSTOM_EXTI_IRQ) +add_definitions(-DUSB_CHARGER) + +set(FLAVOUR v12) +add_definitions(-DRADIO_V12) +add_definitions(-DMANUFACTURER_HELLORADIOSKY) + +# defines existing internal modules +set(INTERNAL_MODULES CRSF CACHE STRING "Internal modules") +set(DEFAULT_INTERNAL_MODULE CROSSFIRE CACHE STRING "Default internal module") + +set(BITMAPS_TARGET bm320_bitmaps) +set(FONTS_TARGET x12_fonts) +set(LCD_DRIVER lcd_driver.cpp) +set(HARDWARE_TOUCH NO) +set(RADIO_DEPENDENCIES ${RADIO_DEPENDENCIES} ${BITMAPS_TARGET}) +set(FIRMWARE_DEPENDENCIES datacopy) +set(SOFTWARE_KEYBOARD ON) +set(FLYSKY_GIMBAL OFF) + +add_definitions( + -DSTM32H750XBTx -DSTM32H750xx + -DSDRAM -DCCMRAM + -DCOLORLCD -DLIBOPENUI + -DHARDWARE_KEYS -DSOFTWARE_KEYBOARD + -DINTERNAL_EXTERNAL_ANT +) + +set(SDRAM ON) + +set(AUX_SERIAL OFF CACHE BOOL "AUX serial port" FORCE) + +# Handset supports external antenna selection via hardware GPIO switch +set(EXTERNAL_ANTENNA ON) +add_definitions(-DEXTERNAL_ANTENNA) + +add_definitions(-DAUDIO -DVOICE) +add_definitions(-DSOFTWARE_VOLUME) +add_definitions(-DRTCLOCK) +add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE}) +add_definitions(-DPWR_BUTTON_${PWR_BUTTON}) +add_definitions(-DPWR_BUTTON_DUAL) +add_definitions(-DI2C_HAS_BUS_4) + +if(STICKS_DEAD_ZONE) + add_definitions(-DSTICK_DEAD_ZONE) +endif() + +if(NOT UNEXPECTED_SHUTDOWN) + add_definitions(-DNO_UNEXPECTED_SHUTDOWN) +endif() + +if(DISK_CACHE) + set(SRC ${SRC} disk_cache.cpp) + add_definitions(-DDISK_CACHE) +endif() + +if(FUNCTION_SWITCHES_WITH_RGB) + set(FUNCTION_SWITCHES YES) + add_definitions(-DFUNCTION_SWITCHES) + add_definitions(-DFUNCTION_SWITCHES_RGB_LEDS) +endif() + +set(AFHDS3 ON) + +# VCP CLI +set(ENABLE_SERIAL_PASSTHROUGH ON CACHE BOOL "Enable serial passthrough") +set(CLI ON CACHE BOOL "Enable CLI") + +set(BOARD helloradio-h750) +set(BOARD_SRC_DIR boards/${BOARD}) +include_directories(boards/${BOARD}) + +set(TARGET_SRC_DIR targets/${TARGET_DIR}) + +set(BOARD_COMMON_SRC + ${BOARD_SRC_DIR}/board.cpp + ${BOARD_SRC_DIR}/key_driver.cpp + ${BOARD_SRC_DIR}/lcd_driver.cpp + ${BOARD_SRC_DIR}/backlight_driver.cpp + ${BOARD_SRC_DIR}/haptic_driver.cpp + ${BOARD_SRC_DIR}/extflash_driver.cpp + ${BOARD_SRC_DIR}/usb_charger_driver.cpp + targets/common/arm/stm32/abnormal_reboot.cpp + targets/common/arm/stm32/delays_driver.cpp + targets/common/arm/stm32/dma2d.cpp + targets/common/arm/stm32/flash_driver.cpp + targets/common/arm/stm32/pwr_driver.cpp + targets/common/arm/stm32/rotary_encoder_driver.cpp + targets/common/arm/stm32/rtc_driver.cpp + targets/common/arm/stm32/watchdog_driver.cpp + drivers/pca95xx.cpp +) + +# Bootloader board library +add_library(board_bl OBJECT EXCLUDE_FROM_ALL + ${BOARD_COMMON_SRC} + ${BOARD_SRC_DIR}/sdram_driver.cpp + ${RADIO_SRC_DIR}/gui/colorlcd/boot_menu.cpp + targets/common/arm/stm32/stm32_qspi.cpp + targets/common/arm/stm32/stm32_pulse_driver.cpp + targets/common/arm/stm32/stm32_rgbleds.cpp +) +add_dependencies(board_bl minimal_board_lib) +set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $) + +set(CMSIS_SRC ${BOARD_SRC_DIR}/system_clock.c) + +# Firmware board library +add_library(board OBJECT EXCLUDE_FROM_ALL + ${BOARD_COMMON_SRC} + targets/common/arm/stm32/audio_dac_driver.cpp + targets/common/arm/stm32/heartbeat_driver.cpp + targets/common/arm/stm32/mixer_scheduler_driver.cpp + targets/common/arm/stm32/module_timer_driver.cpp + targets/common/arm/stm32/stm32_pulse_driver.cpp + targets/common/arm/stm32/stm32_softserial_driver.cpp + targets/common/arm/stm32/stm32_qspi.cpp + targets/common/arm/stm32/stm32_switch_driver.cpp + targets/common/arm/stm32/stm32_rgbleds.cpp + targets/common/arm/stm32/trainer_driver.cpp +) +add_dependencies(board board_lib) +set(FIRMWARE_SRC ${FIRMWARE_SRC} $) + +include_directories(${RADIO_SRC_DIR}/fonts/colorlcd gui/${GUI_DIR} gui/${GUI_DIR}/layouts) + +if(BOOTLOADER) + set(FIRMWARE_TARGET_SRC + ${FIRMWARE_TARGET_SRC} + ../../bootloader/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() + +# Make malloc() thread-safe +add_definitions(-DTHREADSAFE_MALLOC) diff --git a/radio/src/targets/v12/hal.h b/radio/src/targets/v12/hal.h new file mode 100644 index 000000000..11a27c1c4 --- /dev/null +++ b/radio/src/targets/v12/hal.h @@ -0,0 +1,272 @@ +/* + * 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. + */ + +/* +STM32H750 +DMA1 +Stream0: LED_STRIP_TIMER_DMA_STREAM +Stream1: INTMODULE_DMA_STREAM +Stream2: (free) +Stream3: TELEMETRY_DMA_Stream_RX +Stream4: LCD_SPI_TX_DMA_STREAM +Stream5: INTMODULE_RX_DMA_STREAM / LCD_SPI_RX_DMA_STREAM +Stream6: +Stream7: TELEMETRY_DMA_Stream_TX + +DMA2 +Stream0: ADC_EXT_DMA_STREAM (ADC3, see boards/hw_defs/v12.json) +Stream1: AUDIO_DMA_Stream +Stream2: +Stream3: EXTMODULE_TIMER_DMA_STREAM +Stream4: ADC_DMA_STREAM (ADC1, see boards/hw_defs/v12.json) +Stream5: EXTMODULE_USART_RX_DMA_STREAM +Stream6: EXTMODULE_USART_TX_DMA_STREAM + +TIM1: LED_STRIP_TIMER +TIM2: (free) +TIM3: EXTMODULE_TIMER +TIM4: TRAINER_TIMER +TIM5: (free) +TIM6: AUDIO_TIMER +TIM7: (free) +TIM8: BACKLIGHT_TIMER +TIM12: MIXER_SCHEDULER_TIMER +TIM13: +TIM14: MS_TIMER +TIM15: HAPTIC_GPIO_TIMER +TIM16: +TIM17: ROTARY_ENCODER_TIMER + +USARTS +USART1: TELEMETRY_USART +USART2: INTMODULE_USART +USART6: EXTMODULE_USART +*/ + +#ifndef _HAL_H_ +#define _HAL_H_ + +#include "hal_settings.h" + +#define ADC_VREF_PREC2 330 + +// 6POS SW +#define SIXPOS_SWITCH_INDEX 6 +// 6POS SW indicator color (used while charging / before Lua takes over) +#define SIXPOS_LED_RED 200 +#define SIXPOS_LED_GREEN 0 +#define SIXPOS_LED_BLUE 0 + +// Power +// SYS+MDL form the dual-button power-on/off chord on this radio. +#define PWR_SWITCH_GPIO GPIO_PIN(GPIOJ, 3) // SYS +#define PWR_EXTRA_SWITCH_GPIO GPIO_PIN(GPIOE, 5) // MDL +#define PWR_ON_GPIO GPIO_PIN(GPIOE, 2) +#define PWR_BUTTON_DUAL_KEY1 KEY_SYS +#define PWR_BUTTON_DUAL_KEY2 KEY_MODEL + +// S.Port update connector +#define HAS_SPORT_UPDATE_CONNECTOR() (false) + +// Telemetry SPORT +#define TELEMETRY_SET_INPUT 0 +#define TELEMETRY_TX_GPIO GPIO_PIN(GPIOA, 9) +#define TELEMETRY_RX_GPIO GPIO_UNDEF +#define TELEMETRY_USART USART1 +#define TELEMETRY_USART_IRQn USART1_IRQn +#define TELEMETRY_DMA DMA1 +#define TELEMETRY_DMA_Stream_TX LL_DMA_STREAM_7 +#define TELEMETRY_DMA_Channel_TX LL_DMAMUX1_REQ_USART1_TX +#define TELEMETRY_DMA_TX_Stream_IRQ DMA1_Stream7_IRQn +#define TELEMETRY_DMA_TX_IRQHandler DMA1_Stream7_IRQHandler +#define TELEMETRY_DMA_Stream_RX LL_DMA_STREAM_3 +#define TELEMETRY_DMA_Channel_RX LL_DMAMUX1_REQ_USART1_RX +#define TELEMETRY_USART_IRQHandler USART1_IRQHandler + +// Software IRQ (Prio 5 -> FreeRTOS compatible) +#define TELEMETRY_USE_CUSTOM_EXTI +#define CUSTOM_EXTI_IRQ_NAME ETH_WKUP_IRQ +#define ETH_WKUP_IRQ_Priority 5 +#define CUSTOM_EXTI_IRQ_LINE 86 +#define TELEMETRY_RX_FRAME_EXTI_LINE CUSTOM_EXTI_IRQ_LINE + +// USB +#define USB_GPIO GPIOA +#define USB_GPIO_VBUS GPIO_PIN(GPIOB, 12) +#define USB_GPIO_DM GPIO_PIN(GPIOA, 11) +#define USB_GPIO_DP GPIO_PIN(GPIOA, 12) +#define USB_GPIO_AF GPIO_AF10 + +// Chargers (USB and wireless) +#define UCHARGER_PW GPIO_PIN(GPIOJ, 5) // charge power sw 0=DISABLE 1=ENABLE +#define UCHARGER_EN GPIO_PIN(GPIOK, 6) // charge EN 0=ENABLE 1=DISABLE +#define USB_GPIO_SEL GPIO_PIN(GPIOH, 6) // USB HUB SELECT 0->H7 MCU 1->CHARGE MCU +#define UCHARGER_GPIO GPIO_PIN(GPIOJ, 15) // charge status + +// LCD (hardware SPI + DMA) +#define LCD_SPI SPI1 +#define LCD_SPI_DMA DMA1 +#define LCD_SPI_TX_DMA LL_DMAMUX1_REQ_SPI1_TX +#define LCD_SPI_RX_DMA LL_DMAMUX1_REQ_SPI1_RX +#define LCD_SPI_TX_DMA_STREAM LL_DMA_STREAM_4 +#define LCD_SPI_RX_DMA_STREAM LL_DMA_STREAM_5 +#define LCD_FMARK GPIO_PIN(GPIOH, 15) +#define LCD_NRST GPIO_PIN(GPIOI, 0) +#define LCD_SPI_RS GPIO_PIN(GPIOI, 1) +#define LCD_SPI_CS GPIO_PIN(GPIOG, 10) +#define LCD_SPI_CLK GPIO_PIN(GPIOG, 11) +#define LCD_SPI_MOSI GPIO_PIN(GPIOB, 5) +#define LCD_SPI_MISO GPIO_PIN(GPIOK, 0) +#define LCD_SPI_BAUD 100000000 + +// QSPI Flash +#define QSPI_CLK_GPIO GPIO_PIN(GPIOF, 10) +#define QSPI_CLK_GPIO_AF GPIO_AF9 +#define QSPI_CS_GPIO GPIO_PIN(GPIOB, 10) +#define QSPI_CS_GPIO_AF GPIO_AF9 +#define QSPI_MISO_GPIO GPIO_PIN(GPIOF, 9) // IO1 +#define QSPI_MISO_GPIO_AF GPIO_AF10 +#define QSPI_MOSI_GPIO GPIO_PIN(GPIOF, 8) // IO0 +#define QSPI_MOSI_GPIO_AF GPIO_AF10 +#define QSPI_WP_GPIO GPIO_PIN(GPIOF, 7) // IO2 +#define QSPI_WP_GPIO_AF GPIO_AF9 +#define QSPI_HOLD_GPIO GPIO_PIN(GPIOF, 6) // IO3 +#define QSPI_HOLD_GPIO_AF GPIO_AF9 +#define QSPI_FLASH_SIZE 0x800000 + +#define SD_SDIO SDMMC1 +#define SD_SDIO_CLK_DIV(fq) (HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC) / (2 * fq)) +#define SD_SDIO_TRANSFER_CLK_DIV SD_SDIO_CLK_DIV(24000000) +#define STORAGE_USE_SDIO + +// Audio +#define INVERTED_MUTE_PIN +#define AUDIO_MUTE_GPIO GPIO_PIN(GPIOB, 1) +#define AUDIO_OUTPUT_GPIO GPIO_PIN(GPIOA, 4) +#define AUDIO_DAC DAC1 +#define AUDIO_DMA_Stream LL_DMA_STREAM_1 +#define AUDIO_DMA_Channel LL_DMAMUX1_REQ_DAC1_CH1 +#define AUDIO_TIM_IRQn TIM6_DAC_IRQn +#define AUDIO_TIM_IRQHandler TIM6_DAC_IRQHandler +#define AUDIO_DMA_Stream_IRQn DMA2_Stream1_IRQn +#define AUDIO_DMA_Stream_IRQHandler DMA2_Stream1_IRQHandler +#define AUDIO_TIMER TIM6 +#define AUDIO_DMA DMA2 + +// I2C Bus (shared by touch and IMU) +#define I2C_B4 I2C4 +#define I2C_B4_SDA_GPIO GPIO_PIN(GPIOH, 12) +#define I2C_B4_SCL_GPIO GPIO_PIN(GPIOH, 11) +#define I2C_B4_GPIO_AF LL_GPIO_AF_4 +#define I2C_B4_CLK_RATE 400000 + +// Touch - not present +// #define TOUCH_I2C_BUS I2C_Bus_4 +// #define TOUCH_RST_GPIO GPIO_PIN(GPIOJ, 14) +// #define TOUCH_INT_GPIO GPIO_PIN(GPIOD, 11) + +// #define TOUCH_INT_EXTI_Line LL_EXTI_LINE_11 +// #define TOUCH_INT_EXTI_Port LL_SYSCFG_EXTI_PORTD +// #define TOUCH_INT_EXTI_SysCfgLine LL_SYSCFG_EXTI_LINE11 + +// TOUCH_INT_EXTI IRQ +// #if !defined(USE_EXTI15_10_IRQ) +// #define USE_EXTI15_10_IRQ +// #define EXTI15_10_IRQ_Priority 9 +// #endif + +// IMU (not populated on production units; kept disabled -- see CMakeLists IMU option) +#if defined(IMU) +#define IMU_I2C_BUS I2C_Bus_4 +#define IMU_I2C_ADDRESS 0x69 +#endif + +// Internal Module +// (EXTERNAL_ANTENNA is defined via CMakeLists.txt add_definitions) + +#define INTMODULE_PWR_GPIO GPIO_PIN(GPIOG, 13) +#define INTMODULE_ANTSEL_GPIO GPIO_PIN(GPIOA, 8) // antenna select 0=Int 1=Ext +#define INTMODULE_BOOTCMD_GPIO GPIO_PIN(GPIOG, 9) +#define INTMODULE_BOOTCMD_DEFAULT 0 +#define INTMODULE_TX_GPIO GPIO_PIN(GPIOD, 5) +#define INTMODULE_RX_GPIO GPIO_PIN(GPIOD, 6) +#define INTMODULE_USART USART2 +#define INTMODULE_GPIO_AF LL_GPIO_AF_7 +#define INTMODULE_USART_IRQn USART2_IRQn +#define INTMODULE_USART_IRQHandler USART2_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_DMAMUX1_REQ_USART2_TX +#define INTMODULE_RX_DMA DMA1 +#define INTMODULE_RX_DMA_STREAM LL_DMA_STREAM_5 +#define INTMODULE_RX_DMA_CHANNEL LL_DMAMUX1_REQ_USART2_RX +#define INTMODULE_RX_DMA_Stream_IRQn DMA1_Stream5_IRQn +#define INTMODULE_RX_DMA_Stream_IRQHandler DMA1_Stream5_IRQHandler + +// External Module +#define EXTMODULE +#define EXTMODULE_PULSES +#define EXTMODULE_PWR_GPIO GPIO_PIN(GPIOI, 4) +#define EXTMODULE_TX_GPIO GPIO_PIN(GPIOC, 6) // TIM3_CH1 +#define EXTMODULE_RX_GPIO GPIO_PIN(GPIOC, 7) + +#define EXTMODULE_TIMER TIM3 +#define EXTMODULE_TIMER_Channel LL_TIM_CHANNEL_CH1 +#define EXTMODULE_TIMER_IRQn TIM3_IRQn +#define EXTMODULE_TIMER_IRQHandler TIM3_IRQHandler +#define EXTMODULE_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) +#define EXTMODULE_TIMER_TX_GPIO_AF LL_GPIO_AF_2 + +// EXTMODULE USART +#define EXTMODULE_USART USART6 +#define EXTMODULE_USART_TX_DMA DMA2 +#define EXTMODULE_USART_TX_DMA_CHANNEL LL_DMAMUX1_REQ_USART6_TX +#define EXTMODULE_USART_TX_DMA_STREAM LL_DMA_STREAM_6 +#define EXTMODULE_USART_RX_DMA_CHANNEL LL_DMAMUX1_REQ_USART6_RX +#define EXTMODULE_USART_RX_DMA_STREAM LL_DMA_STREAM_5 +#define EXTMODULE_USART_IRQHandler USART6_IRQHandler +#define EXTMODULE_USART_IRQn USART6_IRQn + +// EXTMODULE TIMER DMA +#define EXTMODULE_TIMER_DMA_CHANNEL LL_DMAMUX1_REQ_TIM3_UP +#define EXTMODULE_TIMER_DMA DMA2 +#define EXTMODULE_TIMER_DMA_STREAM LL_DMA_STREAM_3 +#define EXTMODULE_TIMER_DMA_STREAM_IRQn DMA2_Stream3_IRQn +#define EXTMODULE_TIMER_DMA_IRQHandler DMA2_Stream3_IRQHandler + +// Trainer Port +#define TRAINER_IN_GPIO GPIO_PIN(GPIOD, 13) // TIM4_CH2 +#define TRAINER_IN_TIMER_Channel LL_TIM_CHANNEL_CH2 + +#define TRAINER_OUT_GPIO GPIO_PIN(GPIOD, 12) // TIM4_CH1 +#define TRAINER_OUT_TIMER_Channel LL_TIM_CHANNEL_CH1 + +#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 (PERI2_FREQUENCY * TIMER_MULT_APB2) + +#define LSE_DRIVE_STRENGTH RCC_LSEDRIVE_HIGH + +#endif // _HAL_H_ diff --git a/radio/src/targets/v12/usb_descriptor.h b/radio/src/targets/v12/usb_descriptor.h new file mode 100644 index 000000000..7543e3328 --- /dev/null +++ b/radio/src/targets/v12/usb_descriptor.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#define USB_NAME "HelloRadioSky V12" +#define USB_MANUFACTURER 'H', 'E', 'L', 'L', 'O', ' ', ' ', ' ' /* 8 bytes */ +#define USB_PRODUCT 'V', '1', '2', ' ', ' ', ' ', ' ', ' ' /* 8 Bytes */ diff --git a/radio/util/build-firmware.py b/radio/util/build-firmware.py index 3e2f6f0de..d253fca7f 100755 --- a/radio/util/build-firmware.py +++ b/radio/util/build-firmware.py @@ -200,8 +200,7 @@ def main(): firmware_options = options_fatfish_f16 maxsize = 2 * 1024 * 1024 elif board_name == "v12": - cmake_options["PCB"] = "X7" - cmake_options["PCBREV"] = "V12" + cmake_options["PCB"] = "V12" firmware_options = options_helloradiosky_v12 maxsize = 65536 * 8 * 2 elif board_name == "v14": diff --git a/radio/util/hw_defs/legacy_names.py b/radio/util/hw_defs/legacy_names.py index 354cc0f72..c9089dc4a 100644 --- a/radio/util/hw_defs/legacy_names.py +++ b/radio/util/hw_defs/legacy_names.py @@ -776,7 +776,46 @@ LEGACY_NAMES = [ } }, { - "targets": {"v12", "v14", "v14lcd"}, + "targets": {"v12"}, + "inputs": { + "LH": { + "yaml": "Rud", + "lua": "rud", + "description": "Rudder" + }, + "LV": { + "yaml": "Ele", + "lua": "ele", + "description": "Elevator" + }, + "RV": { + "yaml": "Thr", + "lua": "thr", + "description": "Throttle" + }, + "RH": { + "yaml": "Ail", + "lua": "ail", + "description": "Aileron" + }, + "P1": { + "yaml": "POT1", + "lua": "s1", + "label": "P1", + "short_label": "1", + "description": "Potentiometer 1" + }, + "P2": { + "yaml": "POT2", + "lua": "s2", + "label": "P2", + "short_label": "2", + "description": "Potentiometer 2" + } + } + }, + { + "targets": {"v14", "v14lcd"}, "inputs": { "LH": { "yaml": "Rud", diff --git a/tools/boards.py b/tools/boards.py index 2d44eb3c0..83ca2000c 100755 --- a/tools/boards.py +++ b/tools/boards.py @@ -69,8 +69,7 @@ boards = { "INTERNAL_MODULE_MULTI": "YES" }, "V12": { - "PCB": "X7", - "PCBREV": "V12", + "PCB": "V12", }, "V14": { "PCB": "X7", diff --git a/tools/build-common.sh b/tools/build-common.sh index 99276b986..871ce024d 100644 --- a/tools/build-common.sh +++ b/tools/build-common.sh @@ -132,7 +132,7 @@ get_target_build_options() { BUILD_OPTIONS+="-DPCB=X10 -DPCBREV=F16" ;; v12) - BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=V12" + BUILD_OPTIONS+="-DPCB=V12" ;; v14) BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=V14" diff --git a/tools/generate-yaml.sh b/tools/generate-yaml.sh index ca4413b18..342c8bca7 100755 --- a/tools/generate-yaml.sh +++ b/tools/generate-yaml.sh @@ -11,7 +11,7 @@ if [[ -n ${GCC_ARM} ]] ; then export PATH=${GCC_ARM}:$PATH fi -: ${FLAVOR:="x10;t15;tx16s;pl18;nv14;pl18u;nb4p;x9d;x9dp2019;x9e;xlite;xlites;x7;tpro;t20;f16;gx12;st16;c14;pa01;tx15;t15pro;tx16smk3;t22"} +: ${FLAVOR:="x10;t15;tx16s;pl18;nv14;pl18u;nb4p;x9d;x9dp2019;x9e;xlite;xlites;x7;tpro;t20;f16;gx12;st16;c14;pa01;tx15;t15pro;tx16smk3;t22;v12"} : ${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"}