feat(radio): Senduwing H17 support (#7764)

Co-authored-by: 3djc <3djc@gh.com>
Co-authored-by: Risto <rotorman@users.noreply.github.com>
This commit is contained in:
3djc
2026-09-13 18:12:22 +10:00
committed by GitHub
co-authored by 3djc Risto
parent 65bb97dbcc
commit 244aab8919
46 changed files with 4473 additions and 23 deletions
+1
View File
@@ -143,6 +143,7 @@ body:
- RadioMaster TX16S / TX16S Mark II - RadioMaster TX16S / TX16S Mark II
- RadioMaster TX16S MK3 - RadioMaster TX16S MK3
- RadioMaster Zorro - RadioMaster Zorro
- Senduwing H17
- Other (Please specify below) - Other (Please specify below)
validations: validations:
required: true required: true
+2
View File
@@ -50,6 +50,7 @@ jobs:
- t22 - t22
- c14 - c14
- v12 - v12
- h17
container: container:
image: ghcr.io/edgetx/edgetx-dev:latest image: ghcr.io/edgetx/edgetx-dev:latest
volumes: volumes:
@@ -98,6 +99,7 @@ jobs:
- t22 - t22
- c14 - c14
- v12 - v12
- h17
container: container:
image: ghcr.io/edgetx/edgetx-dev:latest image: ghcr.io/edgetx/edgetx-dev:latest
volumes: volumes:
+1 -1
View File
@@ -67,7 +67,7 @@ jobs:
- id: color-4 - id: color-4
target: [nb4p, st16, pa01, c14] target: [nb4p, st16, pa01, c14]
- id: color-5 - id: color-5
target: [t15pro, tx16smk3, gx15] target: [t15pro, tx16smk3, gx15, h17]
steps: steps:
- name: Check out the repo - name: Check out the repo
+1
View File
@@ -41,6 +41,7 @@ jobs:
- tx15;gx15 - tx15;gx15
- t15pro - t15pro
- v12 - v12
- h17
container: container:
image: ghcr.io/edgetx/edgetx-dev:latest image: ghcr.io/edgetx/edgetx-dev:latest
volumes: volumes:
+1 -1
View File
@@ -177,7 +177,7 @@ jobs:
> If you are using a STM32 F2 based radio, *stop right now*, this release is not for you! EdgeTX v2.11 is the last release series to support these radios. Check [this list](https://hackmd.io/@edgetx/B12oQyQKye) if you are unsure if this affects you. Because of this, EdgeTX v2.11 will continue to be supported alongside 2.12, 3.0, etc., with a focus on bug fixes. > If you are using a STM32 F2 based radio, *stop right now*, this release is not for you! EdgeTX v2.11 is the last release series to support these radios. Check [this list](https://hackmd.io/@edgetx/B12oQyQKye) if you are unsure if this affects you. Because of this, EdgeTX v2.11 will continue to be supported alongside 2.12, 3.0, etc., with a focus on bug fixes.
> [!WARNING] > [!WARNING]
> Radios based on STM32H7 MCUs update differently to older radios. Do **not** use the "Flash via USB" option in EdgeTX Buddy with them (yet). To update radios such as the Flysky PA01 & ST16, Jumper T15 Pro, RM TX15, RM GX15 and RM TX16S MK3, please follow the instructions in the [EdgeTX Manual](https://manual.edgetx.org/installing-and-updating-edgetx/updating-your-stm32h7-radio). > Radios based on STM32H7 MCUs update differently to older radios. Do **not** use the "Flash via USB" option in EdgeTX Buddy with them (yet). To update radios such as the Flysky PA01 & ST16, Jumper T15 Pro, RM TX15, RM GX15, RM TX16S MK3 and Senduwing H17, please follow the instructions in the [EdgeTX Manual](https://manual.edgetx.org/installing-and-updating-edgetx/updating-your-stm32h7-radio).
> [!NOTE] > [!NOTE]
> For MacOS users, Companion is now only compiled for MacOS 12 and above. Stay with v2.10.5 or earlier if you need support for an older version of MacOS. > For MacOS users, Companion is now only compiled for MacOS 12 and above. Stay with v2.10.5 or earlier if you need support for an older version of MacOS.
+6
View File
@@ -339,6 +339,12 @@
"displayName": "RadioMaster Zorro", "displayName": "RadioMaster Zorro",
"inherits": "firmware", "inherits": "firmware",
"cacheVariables": { "PCB": "X7", "PCBREV": "ZORRO" } "cacheVariables": { "PCB": "X7", "PCBREV": "ZORRO" }
},
{
"name": "h17",
"displayName": "Senduwing H17",
"inherits": "firmware",
"cacheVariables": { "PCB": "H17" }
} }
], ],
"buildPresets": [ "buildPresets": [
+5 -3
View File
@@ -92,9 +92,11 @@ void BoardJson::afterLoadFixups(Board::Type board, InputsTable * inputs, Switche
{ {
// TODO json files do not contain gyro defs // TODO json files do not contain gyro defs
// Radio cmake directive IMU is currently used // Radio cmake directive IMU is currently used
if (IS_TARANIS_XLITES(board) || IS_FAMILY_HORUS_OR_T16(board) || // H17 has no IMU
IS_RADIOMASTER_TX15(board) || IS_RADIOMASTER_GX15(board) || if ((IS_TARANIS_XLITES(board) || IS_FAMILY_HORUS_OR_T16(board) ||
IS_RADIOMASTER_TX16SMK3(board) || IS_FLYSKY_PA01(board)) { IS_RADIOMASTER_TX15(board) || IS_RADIOMASTER_GX15(board) ||
IS_RADIOMASTER_TX16SMK3(board) || IS_FLYSKY_PA01(board)) &&
!IS_SENDUWING_H17(board)) {
if (getInputIndex(inputs, "TILT_X", Board::LVT_TAG) < 0) { if (getInputIndex(inputs, "TILT_X", Board::LVT_TAG) < 0) {
InputDefn defn; InputDefn defn;
defn.type = AIT_FLEX; defn.type = AIT_FLEX;
+12 -1
View File
@@ -173,6 +173,8 @@ uint32_t Boards::getFourCC(Type board)
return 0x4F78746F; return 0x4F78746F;
case BOARD_HELLORADIOSKY_V16: case BOARD_HELLORADIOSKY_V16:
return 0x4E78746F; return 0x4E78746F;
case BOARD_SENDUWING_H17:
return 0x5078746F;
default: default:
return 0; return 0;
} }
@@ -237,6 +239,7 @@ int Boards::getEEpromSize(Board::Type board)
case BOARD_FLYSKY_NB4P: case BOARD_FLYSKY_NB4P:
case BOARD_FLYSKY_ST16: case BOARD_FLYSKY_ST16:
case BOARD_IFLIGHT_COMMANDO14: case BOARD_IFLIGHT_COMMANDO14:
case BOARD_SENDUWING_H17:
case BOARD_FATFISH_F16: case BOARD_FATFISH_F16:
case BOARD_HELLORADIOSKY_V12: case BOARD_HELLORADIOSKY_V12:
case BOARD_HELLORADIOSKY_V16: case BOARD_HELLORADIOSKY_V16:
@@ -305,6 +308,7 @@ int Boards::getFlashSize(Type board)
case BOARD_FLYSKY_NB4P: case BOARD_FLYSKY_NB4P:
case BOARD_FLYSKY_ST16: // 8MB SDRAM case BOARD_FLYSKY_ST16: // 8MB SDRAM
case BOARD_IFLIGHT_COMMANDO14: // 8MB SDRAM case BOARD_IFLIGHT_COMMANDO14: // 8MB SDRAM
case BOARD_SENDUWING_H17: // 8MB SDRAM
case BOARD_FATFISH_F16: case BOARD_FATFISH_F16:
case BOARD_HELLORADIOSKY_V12: // 8MB SDRAM case BOARD_HELLORADIOSKY_V12: // 8MB SDRAM
case BOARD_HELLORADIOSKY_V16: case BOARD_HELLORADIOSKY_V16:
@@ -425,7 +429,8 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
IS_RADIOMASTER_ZORRO(board) || IS_RADIOMASTER_TX15(board) || IS_RADIOMASTER_ZORRO(board) || IS_RADIOMASTER_TX15(board) ||
IS_JUMPER_T15PRO(board) || IS_FLYSKY_PA01(board) || IS_JUMPER_T15PRO(board) || IS_FLYSKY_PA01(board) ||
IS_FLYSKY_ST16(board) || IS_RADIOMASTER_TX16SMK3(board) || IS_FLYSKY_ST16(board) || IS_RADIOMASTER_TX16SMK3(board) ||
IS_IFLIGHT_C14(board) || IS_RADIOMASTER_GX15(board)); IS_IFLIGHT_C14(board) || IS_RADIOMASTER_GX15(board) ||
IS_SENDUWING_H17(board));
default: default:
return getBoardJson(board)->getCapability(capability); return getBoardJson(board)->getCapability(capability);
@@ -691,6 +696,8 @@ QString Boards::getBoardName(Board::Type board)
return "iFlight Commando 8"; return "iFlight Commando 8";
case BOARD_IFLIGHT_COMMANDO14: case BOARD_IFLIGHT_COMMANDO14:
return "iFlight Commando 14"; return "iFlight Commando 14";
case BOARD_SENDUWING_H17:
return "Senduwing H17";
case BOARD_FATFISH_F16: case BOARD_FATFISH_F16:
return "Fatfish F16"; return "Fatfish F16";
case BOARD_HELLORADIOSKY_V16: case BOARD_HELLORADIOSKY_V16:
@@ -815,6 +822,7 @@ int Boards::getDefaultInternalModules(Board::Type board)
case BOARD_RADIOMASTER_TX16SMK3: case BOARD_RADIOMASTER_TX16SMK3:
case BOARD_IFLIGHT_COMMANDO8: case BOARD_IFLIGHT_COMMANDO8:
case BOARD_IFLIGHT_COMMANDO14: case BOARD_IFLIGHT_COMMANDO14:
case BOARD_SENDUWING_H17:
case BOARD_JUMPER_BUMBLEBEE: case BOARD_JUMPER_BUMBLEBEE:
case BOARD_JUMPER_T12MAX: case BOARD_JUMPER_T12MAX:
case BOARD_JUMPER_T14: case BOARD_JUMPER_T14:
@@ -914,6 +922,9 @@ void Boards::getBattRange(Board::Type board, int& vmin, int& vmax, unsigned int&
case BOARD_FLYSKY_PA01: case BOARD_FLYSKY_PA01:
BR(70, 86, 80) BR(70, 86, 80)
break; break;
case BOARD_SENDUWING_H17:
BR(70, 86, 74)
break;
case BOARD_IFLIGHT_COMMANDO8: case BOARD_IFLIGHT_COMMANDO8:
BR(30, 42, 32) BR(30, 42, 32)
break; break;
+7 -1
View File
@@ -102,6 +102,7 @@ namespace Board {
BOARD_HELLORADIOSKY_V14LCD, BOARD_HELLORADIOSKY_V14LCD,
BOARD_IFLIGHT_COMMANDO14, BOARD_IFLIGHT_COMMANDO14,
BOARD_HELLORADIOSKY_V12, BOARD_HELLORADIOSKY_V12,
BOARD_SENDUWING_H17,
BOARD_TYPE_COUNT, BOARD_TYPE_COUNT,
BOARD_TYPE_MAX = BOARD_TYPE_COUNT - 1 BOARD_TYPE_MAX = BOARD_TYPE_COUNT - 1
}; };
@@ -772,6 +773,11 @@ inline bool IS_IFLIGHT_C14(Board::Type board)
return (board == Board::BOARD_IFLIGHT_COMMANDO14); return (board == Board::BOARD_IFLIGHT_COMMANDO14);
} }
inline bool IS_SENDUWING_H17(Board::Type board)
{
return (board == Board::BOARD_SENDUWING_H17);
}
inline bool IS_FAMILY_PL18(Board::Type board) inline bool IS_FAMILY_PL18(Board::Type board)
{ {
return IS_FLYSKY_PL18(board) || IS_FLYSKY_PL18EV(board) || IS_FLYSKY_PL18U(board); return IS_FLYSKY_PL18(board) || IS_FLYSKY_PL18EV(board) || IS_FLYSKY_PL18U(board);
@@ -858,7 +864,7 @@ inline bool IS_FAMILY_HORUS_OR_T16(Board::Type board)
IS_FLYSKY_NV14(board)/*generally*/ || IS_FLYSKY_EL18(board)/*generally*/ IS_FLYSKY_NV14(board)/*generally*/ || IS_FLYSKY_EL18(board)/*generally*/
|| IS_FAMILY_PL18(board) || IS_FLYSKY_ST16(board)/*generally*/ || || IS_FAMILY_PL18(board) || IS_FLYSKY_ST16(board)/*generally*/ ||
IS_FLYSKY_PA01(board)/*generally*/ || IS_FLYSKY_NB4P(board)/*generally*/ || IS_FLYSKY_PA01(board)/*generally*/ || IS_FLYSKY_NB4P(board)/*generally*/ ||
IS_IFLIGHT_C14(board)/*generally*/; IS_IFLIGHT_C14(board)/*generally*/ || IS_SENDUWING_H17(board)/*generally*/;
} }
inline bool HAS_LARGE_LCD(Board::Type board) inline bool HAS_LARGE_LCD(Board::Type board)
@@ -93,7 +93,8 @@ int OpenTxFirmware::getCapability(::Capability capability)
return id.contains("internalelrs") || IS_RADIOMASTER_TX12_MK2(board) || return id.contains("internalelrs") || IS_RADIOMASTER_TX12_MK2(board) ||
IS_IFLIGHT_COMMANDO8(board) || IS_RADIOMASTER_BOXER(board) || IS_IFLIGHT_COMMANDO8(board) || IS_RADIOMASTER_BOXER(board) ||
IS_RADIOMASTER_POCKET(board) || IS_JUMPER_T20(board) || IS_RADIOMASTER_POCKET(board) || IS_JUMPER_T20(board) ||
IS_RADIOMASTER_MT12(board) || IS_RADIOMASTER_TX15(board) || IS_RADIOMASTER_GX15(board) || IS_JUMPER_T15PRO(board) || IS_JUMPER_T22(board); IS_RADIOMASTER_MT12(board) || IS_RADIOMASTER_TX15(board) || IS_RADIOMASTER_GX15(board) || IS_JUMPER_T15PRO(board) || IS_JUMPER_T22(board) ||
IS_SENDUWING_H17(board);
case HasIntModuleFlySky: case HasIntModuleFlySky:
return id.contains("afhds2a") || id.contains("afhds3") || return id.contains("afhds2a") || id.contains("afhds3") ||
IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_FAMILY_PL18(board); IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_FAMILY_PL18(board);
@@ -768,6 +769,12 @@ void registerOpenTxFirmwares()
registerOpenTxFirmware(firmware); registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX + AFHDS2A + AFHDS3); addOpenTxRfOptions(firmware, FLEX + AFHDS2A + AFHDS3);
/* Senduwing H17 board */
firmware = new OpenTxFirmware(FIRMWAREID("h17"), Firmware::tr("Senduwing H17"), BOARD_SENDUWING_H17);
addOpenTxFrskyOptions(firmware);
addOpenTxRfOptions(firmware, FLEX);
registerOpenTxFirmware(firmware);
Firmware::sortRegisteredFirmwares(); Firmware::sortRegisteredFirmwares();
Firmware::setDefaultVariant(Firmware::getFirmwareForFlavour("tx16s")); Firmware::setDefaultVariant(Firmware::getFirmwareForFlavour("tx16s"));
Firmware::setCurrentVariant(Firmware::getDefaultVariant()); Firmware::setCurrentVariant(Firmware::getDefaultVariant());
+1
View File
@@ -28,6 +28,7 @@ Selects the radio target.
| `T15PRO` | Jumper T15 Pro | | `T15PRO` | Jumper T15 Pro |
| `ST16` | Siyi ST16 | | `ST16` | Siyi ST16 |
| `PA01` | FrSky PA01 | | `PA01` | FrSky PA01 |
| `H17` | Senduwing H17 |
### `PCBREV` ### `PCBREV`
+2 -1
View File
@@ -42,7 +42,8 @@
["RadioMaster TX15", "tx15-"], ["RadioMaster TX15", "tx15-"],
["RadioMaster TX16S / TX16S Mark II", "tx16s-"], ["RadioMaster TX16S / TX16S Mark II", "tx16s-"],
["RadioMaster TX16S MK3", "tx16smk3-"], ["RadioMaster TX16S MK3", "tx16smk3-"],
["RadioMaster Zorro","zorro-"] ["RadioMaster Zorro","zorro-"],
["Senduwing H17", "h17-"]
], ],
"changelog": "- Major initial bug fixes" "changelog": "- Major initial bug fixes"
} }
+3 -1
View File
@@ -1,7 +1,7 @@
include(CMakeForceCompiler) include(CMakeForceCompiler)
include(Bitmaps) include(Bitmaps)
set(PCB_TYPES X9LITE X9LITES X7 XLITE XLITES X9D X9D+ X9E X10 X12S PL18 T15PRO ST16 PA01 TX15 GX15 TX16SMK3 T22 V12) set(PCB_TYPES X9LITE X9LITES X7 XLITE XLITES X9D X9D+ X9E X10 X12S PL18 T15PRO ST16 PA01 TX15 GX15 TX16SMK3 T22 V12 H17)
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(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) set(TTS_LANGUAGES CN CZ DA DE EN ES FI FR HE HU IT JP KO NL PL PT RU SE SK TW UA)
@@ -107,6 +107,8 @@ elseif(PCB STREQUAL GX15)
include(targets/gx15/CMakeLists.txt) include(targets/gx15/CMakeLists.txt)
elseif(PCB STREQUAL TX16SMK3) elseif(PCB STREQUAL TX16SMK3)
include(targets/tx16smk3/CMakeLists.txt) include(targets/tx16smk3/CMakeLists.txt)
elseif(PCB STREQUAL H17)
include(targets/h17/CMakeLists.txt)
elseif(PCB STREQUAL T22) elseif(PCB STREQUAL T22)
include(targets/t22/CMakeLists.txt) include(targets/t22/CMakeLists.txt)
elseif(PCB STREQUAL STM32H7S78_DK) elseif(PCB STREQUAL STM32H7S78_DK)
+476
View File
@@ -0,0 +1,476 @@
{
"adc_inputs": {
"adcs": [
{
"name": "MAIN",
"adc": "ADC1",
"dma": "DMA2",
"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_8CYCLES_5"
},
{
"name": "EXT",
"adc": "ADC3",
"dma": "DMA2",
"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_8CYCLES_5"
}
],
"inputs": [
{
"name": "LH",
"type": "STICK",
"adc": "MAIN",
"gpio": "GPIOA",
"pin": "LL_GPIO_PIN_6",
"channel": "LL_ADC_CHANNEL_3",
"inverted": true
},
{
"name": "LV",
"type": "STICK",
"adc": "MAIN",
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_3",
"channel": "LL_ADC_CHANNEL_13",
"inverted": true
},
{
"name": "RV",
"type": "STICK",
"adc": "MAIN",
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_4",
"channel": "LL_ADC_CHANNEL_4"
},
{
"name": "RH",
"type": "STICK",
"adc": "MAIN",
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_5",
"channel": "LL_ADC_CHANNEL_8",
"inverted": true
},
{
"name": "P1",
"type": "FLEX",
"adc": "MAIN",
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_1",
"channel": "LL_ADC_CHANNEL_11",
"label": "S1",
"short_label": "1",
"default": "POT"
},
{
"name": "SL1",
"type": "FLEX",
"adc": "EXT",
"gpio": "GPIOH",
"pin": "LL_GPIO_PIN_2",
"channel": "LL_ADC_CHANNEL_13",
"label": "S2",
"short_label": "2",
"default": "POT"
},
{
"name": "SL2",
"type": "FLEX",
"adc": "MAIN",
"gpio": "GPIOA",
"pin": "LL_GPIO_PIN_7",
"channel": "LL_ADC_CHANNEL_7",
"label": "S3",
"short_label": "3",
"default": "POT"
},
{
"name": "P3",
"type": "FLEX",
"adc": "MAIN",
"gpio": "GPIOB",
"pin": "LL_GPIO_PIN_1",
"channel": "LL_ADC_CHANNEL_5",
"label": "S4",
"short_label": "4",
"default": "POT"
},
{
"name": "P2",
"type": "FLEX",
"adc": "MAIN",
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_2",
"channel": "LL_ADC_CHANNEL_12",
"default": "MULTIPOS",
"label": "6POS",
"short_label": "6"
},
{
"name": "EXT1",
"type": "FLEX",
"adc": "MAIN",
"gpio": "GPIOA",
"pin": "LL_GPIO_PIN_1",
"channel": "LL_ADC_CHANNEL_17",
"default": "NONE",
"label": "EXT1",
"short_label": "E1"
},
{
"name": "EXT2",
"type": "FLEX",
"adc": "MAIN",
"gpio": "GPIOA",
"pin": "LL_GPIO_PIN_0",
"channel": "LL_ADC_CHANNEL_16",
"default": "NONE",
"label": "EXT2",
"short_label": "E2"
},
{
"name": "VBAT",
"type": "VBAT",
"adc": "EXT",
"gpio": "GPIOH",
"pin": "LL_GPIO_PIN_3",
"channel": "LL_ADC_CHANNEL_14"
},
{
"name": "RTC_BAT",
"type": "RTC_BAT",
"adc": "EXT",
"gpio": null,
"pin": null,
"channel": "LL_ADC_CHANNEL_VBAT"
}
]
},
"switches": [
{
"name": "SA",
"type": "3POS",
"flags": 0,
"inverted": true,
"default": "2POS",
"display": null,
"gpio_high": "GPIOB",
"pin_high": "LL_GPIO_PIN_0",
"gpio_low": "GPIOE",
"pin_low": "LL_GPIO_PIN_4",
"is_cfs": false
},
{
"name": "SB",
"type": "3POS",
"flags": 0,
"inverted": false,
"default": "3POS",
"display": null,
"gpio_high": "GPIOD",
"pin_high": "LL_GPIO_PIN_5",
"gpio_low": "GPIOJ",
"pin_low": "LL_GPIO_PIN_7",
"is_cfs": false
},
{
"name": "SC",
"type": "3POS",
"flags": 0,
"inverted": false,
"default": "3POS",
"display": null,
"gpio_high": "GPIOD",
"pin_high": "LL_GPIO_PIN_3",
"gpio_low": "GPIOJ",
"pin_low": "LL_GPIO_PIN_0",
"is_cfs": false
},
{
"name": "SD",
"type": "3POS",
"flags": 0,
"inverted": true,
"default": "2POS",
"display": null,
"gpio_high": "GPIOD",
"pin_high": "LL_GPIO_PIN_11",
"gpio_low": "GPIOH",
"pin_low": "LL_GPIO_PIN_15",
"is_cfs": false
},
{
"name": "SE",
"type": "3POS",
"flags": 0,
"inverted": false,
"default": "3POS",
"display": null,
"gpio_high": "GPIOE",
"pin_high": "LL_GPIO_PIN_6",
"gpio_low": "GPIOE",
"pin_low": "LL_GPIO_PIN_5",
"is_cfs": false
},
{
"name": "SF",
"type": "2POS",
"flags": 0,
"inverted": false,
"default": "2POS",
"display": null,
"gpio": "GPIOB",
"pin": "LL_GPIO_PIN_8",
"is_cfs": false
},
{
"name": "SG",
"type": "2POS",
"flags": 0,
"inverted": false,
"default": "TOGGLE",
"display": null,
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_6",
"is_cfs": false
},
{
"name": "SH",
"type": "2POS",
"flags": 0,
"inverted": false,
"default": "TOGGLE",
"display": null,
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_8",
"is_cfs": false
},
{
"name": "SI",
"type": "2POS",
"flags": 0,
"inverted": false,
"default": "2POS",
"display": null,
"gpio": "GPIOH",
"pin": "LL_GPIO_PIN_14",
"is_cfs": false
},
{
"name": "SJ",
"type": "2POS",
"flags": 0,
"inverted": false,
"default": "2POS",
"display": null,
"gpio": "GPIOH",
"pin": "LL_GPIO_PIN_13",
"is_cfs": false
}
],
"keys": [
{
"gpio": "GPIOG",
"pin": "LL_GPIO_PIN_3",
"active_low": true,
"key": "KEY_EXIT",
"name": "EXIT",
"label": "RTN"
},
{
"gpio": "GPIOG",
"pin": "LL_GPIO_PIN_12",
"active_low": true,
"key": "KEY_ENTER",
"name": "ENTER",
"label": "Enter"
},
{
"gpio": "GPIOG",
"pin": "LL_GPIO_PIN_7",
"active_low": true,
"key": "KEY_PAGEUP",
"name": "PAGEUP",
"label": "PAGE<"
},
{
"gpio": "GPIOA",
"pin": "LL_GPIO_PIN_8",
"active_low": true,
"key": "KEY_PAGEDN",
"name": "PAGEDN",
"label": "PAGE>"
},
{
"gpio": "GPIOE",
"pin": "LL_GPIO_PIN_3",
"active_low": true,
"key": "KEY_MODEL",
"name": "MDL",
"label": "MDL"
},
{
"gpio": "GPIOI",
"pin": "LL_GPIO_PIN_15",
"active_low": true,
"key": "KEY_TELE",
"name": "TELE",
"label": "TELE"
},
{
"gpio": "GPIOB",
"pin": "LL_GPIO_PIN_2",
"active_low": true,
"key": "KEY_SYS",
"name": "SYS",
"label": "SYS"
}
],
"trims": [
{
"name": "T1",
"dec": {
"gpio": "GPIOG",
"pin": "LL_GPIO_PIN_2",
"active_low": true
},
"inc": {
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_9",
"active_low": true
},
"active_low": true
},
{
"name": "T2",
"dec": {
"gpio": "GPIOB",
"pin": "LL_GPIO_PIN_12",
"active_low": true
},
"inc": {
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_10",
"active_low": true
},
"active_low": true
},
{
"name": "T3",
"dec": {
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_12",
"active_low": true
},
"inc": {
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_11",
"active_low": true
},
"active_low": true
},
{
"name": "T4",
"dec": {
"gpio": "GPIOD",
"pin": "LL_GPIO_PIN_2",
"active_low": true
},
"inc": {
"gpio": "GPIOI",
"pin": "LL_GPIO_PIN_9",
"active_low": true
},
"active_low": true
}
],
"display": {
"lcd_w": 480,
"lcd_h": 272,
"lcd_phys_w": 480,
"lcd_phys_h": 272,
"lcd_depth": 16,
"oled_screen": false,
"lcd_vertical_invert": true,
"ltdc_irq_prio": 4,
"dma_screen_irq_prio": 6
},
"backlight": {
"backlight_gpio": "GPIO_PIN(GPIOA, 10)",
"backlight_timer": "TIM1",
"backlight_timer_channel": "LL_TIM_CHANNEL_CH3",
"backlight_gpio_af": "GPIO_AF1",
"backlight_timer_freq": "(PERI2_FREQUENCY * TIMER_MULT_APB2)"
},
"haptic": {
"haptic_pwm": true,
"haptic_gpio": "GPIO_PIN(GPIOC, 7)",
"haptic_gpio_timer": "TIM3",
"haptic_gpio_af": "GPIO_AF2",
"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"
},
"leds": {
"status_leds": true,
"gpio_led_gpio_on": "gpio_set",
"gpio_led_gpio_off": "gpio_clear",
"led_red_gpio": "GPIO_PIN(GPIOI, 8)",
"led_green_gpio": "GPIO_PIN(GPIOI, 11)",
"led_blue_gpio": "GPIO_PIN(GPIOI, 10)"
},
"timers": {
"cpu_freq": 480000000,
"peri1_frequency": 120000000,
"peri2_frequency": 120000000,
"timer_mult_apb1": 2,
"timer_mult_apb2": 2,
"ms_timer": "TIM14",
"ms_timer_irqn": "TIM8_TRG_COM_TIM14_IRQn",
"ms_timer_irqhandler": "TIM8_TRG_COM_TIM14_IRQHandler",
"mixer_scheduler_timer": "TIM12",
"mixer_scheduler_timer_freq": "(PERI1_FREQUENCY * TIMER_MULT_APB1)",
"mixer_scheduler_timer_irqn": "TIM8_BRK_TIM12_IRQn",
"mixer_scheduler_timer_irqhandler": "TIM8_BRK_TIM12_IRQHandler"
},
"rotenc": {
"rotary_encoder_inverted": true,
"rotary_encoder_gpio_a": "GPIOI",
"rotary_encoder_gpio_pin_a": "LL_GPIO_PIN_7",
"rotary_encoder_gpio_b": "GPIOJ",
"rotary_encoder_gpio_pin_b": "LL_GPIO_PIN_8",
"rotary_encoder_position": "(((ROTARY_ENCODER_GPIO_A->IDR >> 7) & 0x01)|((ROTARY_ENCODER_GPIO_B->IDR >> 7) & 0x02))",
"rotary_encoder_exti_line1": "LL_EXTI_LINE_7",
"rotary_encoder_exti_line2": "LL_EXTI_LINE_8",
"exti": [
{ "irq": "EXTI9_5_IRQ", "priority": 5 }
],
"rotary_encoder_exti_port_a": "LL_SYSCFG_EXTI_PORTI",
"rotary_encoder_exti_port_b": "LL_SYSCFG_EXTI_PORTJ",
"rotary_encoder_exti_sys_line1": "LL_SYSCFG_EXTI_LINE7",
"rotary_encoder_exti_sys_line2": "LL_SYSCFG_EXTI_LINE8",
"rotary_encoder_timer": "TIM17",
"rotary_encoder_timer_irqn": "TIM17_IRQn",
"rotary_encoder_timer_irqhandler": "TIM17_IRQHandler"
},
"key_lock_combo": [
"KEY_SYS",
"KEY_MODEL"
],
"hardware": {
"has_audio_mute": true,
"has_ext_module_support": true,
"has_int_module_support": true,
"sport_max_baudrate": 400000,
"surface": false,
"cpu": "STM32H750xB",
"cpu_type": "STM32H7"
}
}
@@ -0,0 +1,78 @@
/*
* 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);
}
void backlightEnable(uint8_t dutyCycle)
{
stm32_pulse_set_cmp_val(&_bl_timer, dutyCycle);
}
void lcdOff() {
backlightEnable(0);
}
void lcdOn(){
backlightEnable(BACKLIGHT_LEVEL_MAX);
}
bool boardBacklightOn;
bool isBacklightEnabled()
{
return boardBacklightOn;
}
+212
View File
@@ -0,0 +1,212 @@
/*
* 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 "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 "gyro.h"
#include "flysky_gimbal_driver.h"
#include "timers_driver.h"
#include "touch_driver.h"
#include <string.h>
// common ADC driver
extern const etx_hal_adc_driver_t _adc_driver;
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 boardBLEarlyInit()
{
timersInit();
#if defined(USB_CHARGER)
usbChargerInit();
#endif
}
void boardBLPreJump()
{
ExtFLASH_Init();
SDRAM_Init();
// Stop 1ms timer
MS_TIMER->CR1 &= ~TIM_CR1_CEN;
}
void boardBLInit()
{
#if defined(ROTARY_ENCODER_NAVIGATION)
rotaryEncoderInit();
#endif
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 boardInit()
{
// enable interrupts
__enable_irq();
ledInit();
boardInitModulePorts();
pwrInit();
delaysInit();
timersInit();
#if !defined(POWER_LED_BLUE)
ledBlue();
#else
ledGreen();
#endif
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);
#if defined(FLYSKY_GIMBAL)
auto inittime = flysky_gimbal_init();
if (inittime)
TRACE("Serial gimbal detected in %d ms", inittime);
else
TRACE("No serial gimbal detected");
#endif
usbInit();
#if !defined(DEBUG_SEGGER_RTT)
// This is needed to prevent radio from starting when usb is plugged to charge
if (!UNEXPECTED_SHUTDOWN() && usbPlugged()) {
while (usbPlugged() && !pwrPressed()) {
delay_ms(1000);
}
if (!pwrPressed()) {
pwrOff();
// Wait power to drain
while (true) {
}
}
}
#endif
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();
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) {
}
}
+250
View File
@@ -0,0 +1,250 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _BOARD_H_
#define _BOARD_H_
#include "definitions.h"
#include "edgetx_constants.h"
#include "board_common.h"
#include "hal.h"
#include "hal/serial_port.h"
#include "hal/watchdog_driver.h"
#define FLASHSIZE 0x1000000
#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 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() (false)
#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 120 // kOhms
#define VBAT_DIV_R2 39 // kOhms
#define VBAT_MOSFET_DROP 0 // * 10mV
#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 35
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
// Audio driver
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_
@@ -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
@@ -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();
@@ -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(); }
@@ -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"
@@ -0,0 +1,371 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "stm32_hal_ll.h"
#include "stm32_hal.h"
#include "edgetx_types.h"
#include "dma2d.h"
#include "hal.h"
#include "delays_driver.h"
#include "debug.h"
#include "lcd.h"
#include "lcd_driver.h"
#include "board.h"
#include <lvgl/lvgl.h>
#include "hal/gpio.h"
#include "stm32_gpio.h"
#include "stm32_qspi.h"
uint8_t TouchControllerType = 0; // 0: other; 1: CST836U
static volatile uint16_t lcd_phys_w = LCD_PHYS_W;
static volatile uint16_t lcd_phys_h = LCD_PHYS_H;
static LTDC_HandleTypeDef hltdc;
static void* initialFrameBuffer = nullptr;
static volatile uint8_t _frame_addr_reloaded = 0;
#if defined(LCD_VERTICAL_INVERT)
// The H17 panel is mounted upside-down, exactly like the tx16s/horus panel.
// LTDC cannot rotate, so we software-rotate every refreshed area 180 into a
// dedicated back buffer and swap it in on the last flush of a frame. Mirrors
// radio/src/targets/horus/lcd_driver.cpp.
typedef uint16_t pixel_t;
static pixel_t _LCD_BUF_1[DISPLAY_BUFFER_SIZE] __SDRAM;
static pixel_t _LCD_BUF_2[DISPLAY_BUFFER_SIZE] __SDRAM;
static pixel_t _line_buffer[LCD_W];
static uint16_t* _front_buffer = _LCD_BUF_1;
static uint16_t* _back_buffer = _LCD_BUF_2;
// Copy 2 pixels at once to speed up a little
static void _copy_rotate_180(uint16_t* dst, uint16_t* src, const rect_t& copy_area)
{
coord_t x1 = LCD_W - copy_area.w - copy_area.x;
coord_t y1 = LCD_H - copy_area.h - copy_area.y;
src += copy_area.w - 2;
dst += (y1 + copy_area.h - 1) * LCD_W + x1;
for (auto line = 0; line < copy_area.h; line++) {
// invert line into _line_buffer first (SRAM)
auto px_dst = _line_buffer;
auto line_end = px_dst + (copy_area.w & ~1);
while (px_dst != line_end) {
uint32_t* px2_src = (uint32_t*)src;
*((uint32_t*)px_dst) = ((*px2_src & 0xFFFF0000) >> 16) | ((*px2_src & 0xFFFF) << 16);
src -= 2;
px_dst += 2;
}
if (copy_area.w & 1) {
*px_dst = *(src+1);
src--;
}
// ... and DMA back into SDRAM
DMACopyBitmap(dst, copy_area.w, 1, 0, 0,
_line_buffer, copy_area.w, 1, 0, 0,
copy_area.w, 1);
src += copy_area.w * 2;
dst -= LCD_W;
}
}
static void _rotate_area_180(lv_area_t& area)
{
lv_coord_t tmp_coord;
tmp_coord = area.y2;
area.y2 = LCD_H - area.y1 - 1;
area.y1 = LCD_H - tmp_coord - 1;
tmp_coord = area.x2;
area.x2 = LCD_W - area.x1 - 1;
area.x1 = LCD_W - tmp_coord - 1;
}
#endif
static void _update_frame_buffer_addr(uint16_t* buffer)
{
// given the data cache size, this is probably
// faster than cleaning by address
SCB_CleanDCache();
LTDC_Layer1->CFBAR = (uint32_t)buffer;
// reload shadow registers on vertical blank
_frame_addr_reloaded = 0;
LTDC->SRCR = LTDC_SRCR_VBR;
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
// wait for reload
// TODO: replace through some smarter mechanism without busy wait
while(_frame_addr_reloaded == 0);
}
static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
const rect_t &copy_area)
{
#if defined(LCD_VERTICAL_INVERT)
_copy_rotate_180(_back_buffer, buffer, copy_area);
if (lv_disp_flush_is_last(disp_drv)) {
// swap back/front
if (_front_buffer == _LCD_BUF_1) {
_front_buffer = _LCD_BUF_2;
_back_buffer = _LCD_BUF_1;
} else {
_front_buffer = _LCD_BUF_1;
_back_buffer = _LCD_BUF_2;
}
// Trigger async refresh
_update_frame_buffer_addr(_front_buffer);
// Copy refreshed & rotated areas into new back buffer
uint16_t* src = _front_buffer;
uint16_t* dst = _back_buffer;
lv_disp_t* disp = _lv_refr_get_disp_refreshing();
for(int i = 0; i < disp->inv_p; i++) {
if(disp->inv_area_joined[i]) continue;
lv_area_t refr_area;
lv_area_copy(&refr_area, &disp->inv_areas[i]);
_rotate_area_180(refr_area);
auto area_w = refr_area.x2 - refr_area.x1 + 1;
auto area_h = refr_area.y2 - refr_area.y1 + 1;
DMACopyBitmap(dst, LCD_W, LCD_H, refr_area.x1, refr_area.y1,
src, LCD_W, LCD_H, refr_area.x1, refr_area.y1,
area_w, area_h);
}
}
#else
(void)disp_drv;
(void)copy_area;
_update_frame_buffer_addr(buffer);
#endif
// Since #7483 the shared LVGL flush path (gui/colorlcd/lcd.cpp) no longer
// signals completion after invoking the flush callback; the driver must call
// lcdFlushed() itself, otherwise LVGL's flush stays pending forever and the
// UI freezes on the first frame (e.g. stuck on the boot logo).
lcdFlushed();
}
// LTDC RGB666 data + sync lines (all on AF14). Layout matches the tx15/rm-h750
// panel wiring: PI12-14 (HSYNC/VSYNC/CLK), PJ1-6 (R2-R7), PJ9-11 + PK0-2
// (G2-G7), PJ14-15 + PK3-6 (B2-B7), PK7 (DE).
gpio_t _lcd_af_gpios[] = {
GPIO_PIN(GPIOI, 12), GPIO_PIN(GPIOI, 13), GPIO_PIN(GPIOI, 14),
GPIO_PIN(GPIOJ, 1), GPIO_PIN(GPIOJ, 2), GPIO_PIN(GPIOJ, 3),
GPIO_PIN(GPIOJ, 4), GPIO_PIN(GPIOJ, 5), GPIO_PIN(GPIOJ, 6),
GPIO_PIN(GPIOJ, 9), GPIO_PIN(GPIOJ, 10), GPIO_PIN(GPIOJ, 11),
GPIO_PIN(GPIOJ, 14), GPIO_PIN(GPIOJ, 15),
GPIO_PIN(GPIOK, 0), GPIO_PIN(GPIOK, 1), GPIO_PIN(GPIOK, 2),
GPIO_PIN(GPIOK, 3), GPIO_PIN(GPIOK, 4), GPIO_PIN(GPIOK, 5),
GPIO_PIN(GPIOK, 6), GPIO_PIN(GPIOK, 7),
};
static void LCD_AF_GPIOConfig(void)
{
for (unsigned i = 0; i < sizeof(_lcd_af_gpios) / sizeof(_lcd_af_gpios[0]); i++) {
gpio_init_af(_lcd_af_gpios[i], GPIO_AF14, GPIO_SPEED_FREQ_LOW);
}
}
static void lcdResetConfig(void)
{
LL_GPIO_InitTypeDef GPIO_InitStructure;
LL_GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.Pin = LCD_RESET_GPIO_PIN;
GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStructure.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStructure.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(LCD_RESET_GPIO, &GPIO_InitStructure);
}
static void lcdReset() {
LCD_NRST_HIGH();
delay_ms(1);
LCD_NRST_LOW(); // RESET();
delay_ms(10);
LCD_NRST_HIGH();
delay_ms(100);
}
void LCD_Init_LTDC() {
hltdc.Instance = LTDC;
/* LTDC pixel clock is driven from PLL3R (see system_clock.c) */
/* LTDC Configuration *********************************************************/
/* Polarity configuration */
/* Initialize the horizontal synchronization polarity as active low */
hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL;
/* Initialize the vertical synchronization polarity as active low */
hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL;
/* Initialize the data enable polarity as active low */
hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL;
/* Initialize the pixel clock polarity as input pixel clock.
tx16s/horus drives this panel with IPC (non-inverted); jumper-h750 used
IIPC for a different panel. */
hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
/* Configure R,G,B component values for LCD background color */
hltdc.Init.Backcolor.Red = 0;
hltdc.Init.Backcolor.Green = 0;
hltdc.Init.Backcolor.Blue = 0;
/* Configure horizontal synchronization width */
hltdc.Init.HorizontalSync = HSW-1;
/* Configure vertical synchronization height */
hltdc.Init.VerticalSync = VSH-1;
/* Configure accumulated horizontal back porch */
hltdc.Init.AccumulatedHBP = HSW+HBP-1;
/* Configure accumulated vertical back porch */
hltdc.Init.AccumulatedVBP = VSH+VBP-1;
/* Configure accumulated active width */
hltdc.Init.AccumulatedActiveW = lcd_phys_w + HBP+HSW-1;
/* Configure accumulated active height */
hltdc.Init.AccumulatedActiveH = lcd_phys_h + VBP+VSH-1;
/* Configure total width */
hltdc.Init.TotalWidth = lcd_phys_w + HBP + HFP + HSW -1;
/* Configure total height */
hltdc.Init.TotalHeigh = lcd_phys_h + VBP + VFP+VSH-1;
HAL_LTDC_Init(&hltdc);
// Configure IRQ (line)
NVIC_SetPriority(LTDC_IRQn, LTDC_IRQ_PRIO);
NVIC_EnableIRQ(LTDC_IRQn);
// Trigger on last line
HAL_LTDC_ProgramLineEvent(&hltdc, lcd_phys_h);
__HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI);
}
void LCD_LayerInit() {
auto& layer = hltdc.LayerCfg[0];
/* Windowing configuration */
layer.WindowX0 = 0;
layer.WindowX1 = lcd_phys_w;
layer.WindowY0 = 0;
layer.WindowY1 = lcd_phys_h;
/* Pixel Format configuration*/
layer.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;
/* Alpha constant (255 totally opaque) */
layer.Alpha = 255;
/* Default Color configuration (configure A,R,G,B component values) */
layer.Backcolor.Blue = 0;
layer.Backcolor.Green = 0;
layer.Backcolor.Red = 0;
layer.Alpha0 = 0;
/* Configure blending factors */
layer.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
layer.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
layer.ImageWidth = lcd_phys_w;
layer.ImageHeight = lcd_phys_h;
/* Start Address configuration : the LCD Frame buffer is defined on SDRAM w/ Offset */
#if defined(LCD_VERTICAL_INVERT)
layer.FBStartAdress = (intptr_t)_LCD_BUF_1;
#else
layer.FBStartAdress = (intptr_t)initialFrameBuffer;
#endif
/* Initialize LTDC layer 1 */
HAL_LTDC_ConfigLayer(&hltdc, &hltdc.LayerCfg[0], 0);
/* dithering activation */
HAL_LTDC_EnableDither(&hltdc);
}
extern "C"
void lcdSetInitalFrameBuffer(void* fbAddress)
{
initialFrameBuffer = fbAddress;
}
const char* boardLcdType = "";
extern "C"
void lcdInit(void)
{
#if defined(LCD_VERTICAL_INVERT)
// Clear buffers first
memset(_LCD_BUF_1, 0, sizeof(_LCD_BUF_1));
memset(_LCD_BUF_2, 0, sizeof(_LCD_BUF_2));
#endif
/* Configure the LCD reset pin */
lcdResetConfig();
/* Reset the LCD --------------------------------------------------------*/
lcdReset();
/* Configure the LTDC RGB control pins */
LCD_AF_GPIOConfig();
TRACE("LCD INIT: parallel RGB (LTDC)");
boardLcdType = "RGB (LTDC)";
__HAL_RCC_LTDC_CLK_ENABLE();
LCD_Init_LTDC();
LCD_LayerInit();
// Enable LCD display
__HAL_LTDC_ENABLE(&hltdc);
lcdSetFlushCb(startLcdRefresh);
}
extern "C" void LTDC_IRQHandler(void)
{
__HAL_LTDC_CLEAR_FLAG(&hltdc, LTDC_FLAG_LI);
__HAL_LTDC_DISABLE_IT(&hltdc, LTDC_IT_LI);
_frame_addr_reloaded = 1;
}
@@ -0,0 +1,47 @@
/*
* 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__
// H17 uses a parallel RGB (LTDC) panel with no MCU-side SPI configuration bus.
// Only the LTDC data/sync lines and the panel reset line (LCD_RESET_GPIO) are
// wired, so the SPI bit-bang init/read path used by the RadioMaster boards is
// intentionally absent here.
// Timings taken from the horus/tx16s driver, which drives this same panel.
// Values are in this board's raw-porch convention (lcd_driver.cpp subtracts 1
// and accumulates), and reproduce the exact LTDC register values horus programs:
// HSync=2 AccHBP=42 AccActiveW=522 TotalWidth=525
// VSync=10 AccVBP=12 AccActiveH=284 TotalHeigh=286
#define HBP ( 40 )
#define VBP ( 2 )
#define HSW ( 3 )
#define VSH ( 11 )
#define HFP ( 3 )
#define VFP ( 2 )
#define LCD_NRST_HIGH() LL_GPIO_SetOutputPin(LCD_RESET_GPIO, LCD_RESET_GPIO_PIN)
#define LCD_NRST_LOW() LL_GPIO_ResetOutputPin(LCD_RESET_GPIO, LCD_RESET_GPIO_PIN)
#endif
@@ -0,0 +1,216 @@
/*
* 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 -----------------------------------------------------*/
/*
*/
/* GPIOC configuration */
gpio_init_af(GPIO_PIN(GPIOC, 0), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); // FMC_SDNWE (RAM_WE)
/* 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);
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);
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);
gpio_init_af(GPIO_PIN(GPIOG, 5), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOG, 8), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOG, 15), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
// NB: PH5 is USB_VBUS on this board, NOT FMC_SDNWE (write-enable is on PC0).
// Only PH6 (FMC_SDNE1 / RAM_CS) and PH7 (FMC_SDCKE1 / RAM_CKE) are FMC here.
gpio_init_af(GPIO_PIN(GPIOH, 6), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOH, 7), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
}
extern "C" void SDRAM_InitSequence(void)
{
FMC_SDRAM_CommandTypeDef FMC_SDRAMCommandStructure;
uint32_t tmpr = 0;
/* Step 3 --------------------------------------------------------------------*/
/* Configure a clock configuration enable command */
FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
FMC_SDRAMCommandStructure.AutoRefreshNumber = 1;
FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0;
/* 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_BANK2;
FMC_SDRAMCommandStructure.AutoRefreshNumber = 1;
FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0;
/* Send the command */
FMC_SDRAM_SendCommand(FMC_Bank5_6_R, &FMC_SDRAMCommandStructure, 10);
/* Step 6 --------------------------------------------------------------------*/
/* Configure a Auto-Refresh command */
FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
FMC_SDRAMCommandStructure.AutoRefreshNumber = 8;
FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0;
/* Send the command */
FMC_SDRAM_SendCommand(FMC_Bank5_6_R, &FMC_SDRAMCommandStructure, 10);
/* 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_BANK2;
FMC_SDRAMCommandStructure.AutoRefreshNumber = 1;
FMC_SDRAMCommandStructure.ModeRegisterDefinition = tmpr;
/* Send the command */
FMC_SDRAM_SendCommand(FMC_Bank5_6_R, &FMC_SDRAMCommandStructure, 10);
/* 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, 2479);
}
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 */
FMC_SDRAMTimingInitStructure.LoadToActiveDelay = 3; // tMRD
FMC_SDRAMTimingInitStructure.ExitSelfRefreshDelay = 11; // tXSR = 70ns
FMC_SDRAMTimingInitStructure.SelfRefreshTime = 7; // tRAS = 42ns
FMC_SDRAMTimingInitStructure.RowCycleDelay = 10; // tRC = 60ns
FMC_SDRAMTimingInitStructure.WriteRecoveryTime = 2; // tWR
FMC_SDRAMTimingInitStructure.RPDelay = 3; // tRP = 18ns
FMC_SDRAMTimingInitStructure.RCDDelay = 3; // tRCD = 18ns
/* FMC SDRAM control configuration */
FMC_SDRAMInitStructure.SDBank = FMC_SDRAM_BANK2;
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_3;
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_BANK2);
__FMC_ENABLE();
/* FMC SDRAM device initialization sequence */
SDRAM_InitSequence();
}
@@ -0,0 +1,118 @@
/*
* 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);
// HSE = 48 MHz. M=12 -> 4 MHz PFD input (matches RANGE_2_4). VCO = 4*240 =
// 960 MHz. Outputs unchanged from the previous (out-of-range M=3/N=60) config:
// P=2 -> 480 MHz sysclk, Q=20 -> 48 MHz (USB/SPI), R=2 -> 480 MHz.
LL_RCC_PLL1_SetM(12);
LL_RCC_PLL1_SetN(240);
LL_RCC_PLL1_SetP(2);
LL_RCC_PLL1_SetQ(20);
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_PLL2FRACN_Disable();
LL_RCC_PLL2_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_2_4);
LL_RCC_PLL2_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
LL_RCC_PLL2_SetM(24);
LL_RCC_PLL2_SetN(96);
LL_RCC_PLL2_SetP(17); // 11.294 MHz
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);
// HSE = 48 MHz. Previous M=1 gave a 48 MHz PFD input (3x over the 16 MHz PLL
// input max) so PLL3 could not lock -> no LTDC pixel clock. M=12 -> 4 MHz
// input (matches RANGE_2_4). VCO = 4*48 = 192 MHz, identical to before:
// P=2 -> 96 MHz, Q=2 -> 96 MHz, R=18 -> ~10.67 MHz LTDC pixel clock.
LL_RCC_PLL3_SetM(12);
LL_RCC_PLL3_SetN(48);
LL_RCC_PLL3_SetP(2);
LL_RCC_PLL3_SetQ(2);
LL_RCC_PLL3_SetR(18);
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_SetSPIClockSource(LL_RCC_SPI123_CLKSOURCE_PLL1Q);
LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLL1Q);
LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_CLKP);
}
@@ -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();
@@ -0,0 +1,31 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "touch.h"
extern void touchPanelDeInit();
extern bool touchPanelInit();
struct TouchState touchPanelRead();
bool touchPanelEventOccured();
struct TouchState getInternalTouchState();
@@ -0,0 +1,339 @@
/*
* 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 "hal/i2c_driver.h"
#include "stm32_gpio.h"
#include "stm32_hal_ll.h"
#include "stm32_hal.h"
#include "stm32_i2c_driver.h"
#include "stm32_gpio_driver.h"
#include "stm32_exti_driver.h"
#include "hal.h"
#include "timers_driver.h"
#include "tp_gt911.h"
#include "delays_driver.h"
#include "os/sleep.h"
#include "edgetx_types.h"
#include "debug.h"
#include <stdlib.h>
#include <string.h>
#define TP_GT911_ID "911"
bool touchGT911Flag = false;
volatile static bool touchEventOccured = false;
struct TouchData touchData;
uint16_t touchGT911fwver = 0;
uint32_t touchGT911hiccups = 0;
static tmr10ms_t downTime = 0;
static tmr10ms_t tapTime = 0;
static short tapCount = 0;
static TouchState internalTouchState = {};
static void _gt911_exti_isr(void)
{
touchEventOccured = true;
}
void I2C_Init_Radio(void)
{
TRACE("GT911 I2C Init");
if (i2c_init(TOUCH_I2C_BUS) < 0) {
TRACE("GT911 ERROR: i2c_init failed");
return;
}
}
bool I2C_GT911_WriteRegister(uint16_t reg, uint8_t *buf, uint8_t len)
{
uint8_t uAddrAndBuf[258];
uAddrAndBuf[0] = (uint8_t)((reg & 0xFF00) >> 8);
uAddrAndBuf[1] = (uint8_t)(reg & 0x00FF);
if (len > 0) {
for (int i = 0; i < len; i++) {
uAddrAndBuf[i + 2] = buf[i];
}
}
if (stm32_i2c_master_tx(TOUCH_I2C_BUS, GT911_I2C_ADDR, uAddrAndBuf, len + 2,
100) < 0) {
TRACE("I2C B1 ERROR: WriteRegister failed");
return false;
}
return true;
}
bool I2C_GT911_ReadRegister(uint16_t reg, uint8_t *buf, uint8_t len)
{
uint8_t uRegAddr[2];
uRegAddr[0] = (uint8_t)((reg & 0xFF00) >> 8);
uRegAddr[1] = (uint8_t)(reg & 0x00FF);
if (stm32_i2c_master_tx(TOUCH_I2C_BUS, GT911_I2C_ADDR, uRegAddr, 2, 10) < 0) {
TRACE("I2C B1 ERROR: ReadRegister write reg address failed");
return false;
}
if (stm32_i2c_master_rx(TOUCH_I2C_BUS, GT911_I2C_ADDR, buf, len, 100) < 0) {
TRACE("I2C B1 ERROR: ReadRegister read reg address failed");
return false;
}
return true;
}
void touchPanelDeInit(void)
{
gpio_int_disable(TOUCH_INT_GPIO);
touchGT911Flag = false;
}
uint8_t tp_gt911_cfgVer = GT911_CFG_NUMBER;
bool touchPanelInit(void)
{
uint8_t tmp[4] = {0};
if (touchGT911Flag) {
gpio_init_int(TOUCH_INT_GPIO, GPIO_IN_PU, GPIO_RISING, _gt911_exti_isr);
return true;
} else {
TRACE("Touchpanel init start ...");
gpio_init(TOUCH_RST_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
gpio_init(TOUCH_INT_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
I2C_Init_Radio();
gpio_clear(TOUCH_RST_GPIO);
gpio_set(TOUCH_INT_GPIO);
delay_us(200);
gpio_set(TOUCH_RST_GPIO);
delay_ms(6);
gpio_clear(TOUCH_INT_GPIO);
delay_ms(55);
gpio_init(TOUCH_INT_GPIO, GPIO_IN_PU, GPIO_PIN_SPEED_LOW);
delay_ms(50);
TRACE("Reading Touch registry");
if (!I2C_GT911_ReadRegister(GT911_PRODUCT_ID_REG, tmp, 4)) {
TRACE("GT911 ERROR: Product ID read failed");
}
if (strcmp((char *)tmp, TP_GT911_ID) == 0) {
TRACE("GT911 chip detected");
tmp[0] = 0X02;
if (!I2C_GT911_WriteRegister(GT911_COMMAND_REG, tmp, 1)) {
TRACE("GT911 ERROR: write to control register failed");
}
if (!I2C_GT911_ReadRegister(GT911_CONFIG_REG, tmp, 1)) {
TRACE("GT911 ERROR: configuration register read failed");
}
TRACE("Chip config Ver:%x", tmp[0]);
if ((tp_gt911_cfgVer == 0) || (tmp[0] < tp_gt911_cfgVer)) { // Config ver
TRACE("Sending new config %d", GT911_CFG_NUMBER);
if (!I2C_GT911_ReadRegister(GT911_CONFIG_REG, tmp, 1)) {
TRACE("GT911 ERROR: configuration register read failed");
}
tp_gt911_cfgVer = tmp[0];
}
if (!I2C_GT911_ReadRegister(GT911_FIRMWARE_VERSION_REG, tmp, 2)) {
TRACE("GT911 ERROR: reading firmware version failed");
} else {
touchGT911fwver = (tmp[1] << 8) + tmp[0];
TRACE("GT911 FW version: %u", touchGT911fwver);
}
delay_ms(10);
tmp[0] = 0X00;
if (!I2C_GT911_WriteRegister(GT911_COMMAND_REG, tmp, 1)) { // end reset
TRACE("GT911 ERROR: write to command register failed");
}
touchGT911Flag = true;
gpio_init_int(TOUCH_INT_GPIO, GPIO_IN_PU, GPIO_RISING, _gt911_exti_isr);
return true;
}
TRACE("GT911 chip NOT FOUND");
return false;
}
}
bool I2C_ReInit(void)
{
TRACE("I2C B1 ReInit");
touchPanelDeInit();
if (stm32_i2c_deinit(TOUCH_I2C_BUS) < 0)
TRACE("I2C B1 ReInit - I2C DeInit failed");
// If DeInit fails, try to re-init anyway
if (!touchPanelInit()) {
TRACE("I2C B1 ReInit - touchPanelInit failed");
return false;
}
return true;
}
#if defined(SIMU) || defined(SEMIHOSTING) || defined(DEBUG)
static const char *event2str(uint8_t ev)
{
switch (ev) {
case TE_NONE:
return "NONE";
case TE_UP:
return "UP";
case TE_DOWN:
return "DOWN";
case TE_SLIDE_END:
return "SLIDE_END";
case TE_SLIDE:
return "SLIDE";
default:
return "UNKNOWN";
}
}
#endif
struct TouchState touchPanelRead()
{
uint8_t state = 0;
if (!touchEventOccured) return internalTouchState;
touchEventOccured = false;
uint32_t startReadStatus = timersGetMsTick();
do {
if (!I2C_GT911_ReadRegister(GT911_READ_XY_REG, &state, 1)) {
touchGT911hiccups++;
TRACE("GT911 I2C read XY error");
if (!I2C_ReInit()) TRACE("I2C B1 ReInit failed");
return internalTouchState;
}
if (state & 0x80u) {
// ready
break;
}
sleep_ms(1);
} while (timersGetMsTick() - startReadStatus < GT911_TIMEOUT);
internalTouchState.deltaX = 0;
internalTouchState.deltaY = 0;
TRACE("touch state = 0x%x", state);
if (state & 0x80u) {
uint8_t pointsCount = (state & 0x0Fu);
uint32_t now = timersGetMsTick();
internalTouchState.tapCount = 0;
if (pointsCount > 0 && pointsCount <= GT911_MAX_TP) {
if (!I2C_GT911_ReadRegister(GT911_READ_XY_REG + 1, touchData.data,
pointsCount * sizeof(TouchPoint))) {
touchGT911hiccups++;
TRACE("GT911 I2C data read error");
if (!I2C_ReInit()) TRACE("I2C B1 ReInit failed");
return internalTouchState;
}
#if defined(LCD_VERTICAL_INVERT)
// Panel (and thus the GT911) is mounted upside-down, matching the 180
// display rotation in lcd_driver.cpp. Flip the reported coordinates so
// touches line up with what is drawn.
for (uint8_t i = 0; i < pointsCount; i++) {
touchData.points[i].x = LCD_W - 1 - touchData.points[i].x;
touchData.points[i].y = LCD_H - 1 - touchData.points[i].y;
}
#endif
if (internalTouchState.event == TE_NONE ||
internalTouchState.event == TE_UP ||
internalTouchState.event == TE_SLIDE_END) {
internalTouchState.event = TE_DOWN;
internalTouchState.startX = internalTouchState.x =
touchData.points[0].x;
internalTouchState.startY = internalTouchState.y =
touchData.points[0].y;
downTime = now;
} else {
internalTouchState.deltaX =
touchData.points[0].x - internalTouchState.x;
internalTouchState.deltaY =
touchData.points[0].y - internalTouchState.y;
if (internalTouchState.event == TE_SLIDE ||
abs(internalTouchState.deltaX) >= SLIDE_RANGE ||
abs(internalTouchState.deltaY) >= SLIDE_RANGE) {
internalTouchState.event = TE_SLIDE;
internalTouchState.x = touchData.points[0].x;
internalTouchState.y = touchData.points[0].y;
}
}
} else {
if (internalTouchState.event == TE_SLIDE) {
internalTouchState.event = TE_SLIDE_END;
} else if (internalTouchState.event == TE_DOWN) {
internalTouchState.event = TE_UP;
if (now - downTime <= GT911_TAP_TIME) {
if (now - tapTime > GT911_TAP_TIME)
tapCount = 1;
else
tapCount++;
internalTouchState.tapCount = tapCount;
tapTime = now;
}
} else {
internalTouchState.event = TE_NONE;
}
}
}
uint8_t zero = 0;
if (!I2C_GT911_WriteRegister(GT911_READ_XY_REG, &zero, 1)) {
TRACE("GT911 ERROR: clearing XY register failed");
}
TRACE("touch event = %s", event2str(internalTouchState.event));
return internalTouchState;
}
bool touchPanelEventOccured()
{
return touchEventOccured;
}
TouchState getInternalTouchState()
{
return internalTouchState;
}
@@ -0,0 +1,83 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "touch.h"
#include "definitions.h"
#define HAS_TOUCH_PANEL() (touchGT911Flag == true)
extern bool touchGT911Flag;
extern uint16_t touchGT911fwver;
extern uint32_t touchGT911hiccups;
extern void touchPanelDeInit();
extern bool touchPanelInit();
struct TouchState touchPanelRead();
bool touchPanelEventOccured();
struct TouchState getInternalTouchState();
#define GT911_TIMEOUT 3 // 3ms
#define GT911_TAP_TIME 250 // 250 ms
#define GT911_MAX_TP 5
#define GT911_CFG_NUMBER 0x6D
//I2C
#define GT911_I2C_ADDR 0x14
//#define GT_CMD_WR 0x28
//#define GT_CMD_RD 0x29
//#define I2C_TIMEOUT_MAX 1000
#define GT911_COMMAND_REG 0x8040
#define GT911_CONFIG_REG 0x8047
#define GT911_COORDINATE_REG 0x804D
#define GT911_CONFIG_CHECKSUM_REG 0x80FF
#define GT911_PRODUCT_ID_REG 0x8140
#define GT911_FIRMWARE_VERSION_REG 0x8144
#define GT911_VENDOR_ID_REG 0x814A
#define GT911_READ_XY_REG 0x814E
#define GT911_TP1_REG 0x8150
#define GT911_TP2_REG 0x8158
#define GT911_TP3_REG 0x8160
#define GT911_TP4_REG 0x8168
#define GT911_TP5_REG 0x8170
PACK(typedef struct {
uint8_t track;
uint16_t x;
uint16_t y;
uint16_t size;
uint8_t reserved;
}) TouchPoint;
PACK(struct TouchData {
union
{
TouchPoint points[GT911_MAX_TP];
uint8_t data[GT911_MAX_TP * sizeof(TouchPoint)];
};
});
+3 -1
View File
@@ -82,6 +82,8 @@ static inline void check_struct()
CHKSIZE(RadioData, 1183); CHKSIZE(RadioData, 1183);
#elif defined(RADIO_V12) #elif defined(RADIO_V12)
CHKSIZE(RadioData, 1180); CHKSIZE(RadioData, 1180);
#elif defined(RADIO_H17)
CHKSIZE(RadioData, 1060);
#elif defined(COLORLCD) #elif defined(COLORLCD)
#if defined(IMU) #if defined(IMU)
CHKSIZE(RadioData, 1063); CHKSIZE(RadioData, 1063);
@@ -116,7 +118,7 @@ static inline void check_struct()
CHKSIZE(ModelData, 7641); CHKSIZE(ModelData, 7641);
#elif defined(RADIO_V12) #elif defined(RADIO_V12)
CHKSIZE(ModelData, 7640); CHKSIZE(ModelData, 7640);
#elif defined(PCBC14) #elif defined(PCBC14) || defined(RADIO_H17)
CHKSIZE(ModelData, 7573); CHKSIZE(ModelData, 7573);
#elif defined(PCBPA01) #elif defined(PCBPA01)
CHKSIZE(ModelData, 7582); CHKSIZE(ModelData, 7582);
+1
View File
@@ -438,6 +438,7 @@ void generalDefault()
uint8_t defaultCalib[] = DEFAULT_6POS_CALIB; uint8_t defaultCalib[] = DEFAULT_6POS_CALIB;
StepsCalibData* calib = (StepsCalibData*)&g_eeGeneral.calib[DEFAULT_6POS_IDX]; StepsCalibData* calib = (StepsCalibData*)&g_eeGeneral.calib[DEFAULT_6POS_IDX];
calib->count = XPOTS_MULTIPOS_COUNT - 1;
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
calib->steps[i] = defaultCalib[i]; calib->steps[i] = defaultCalib[i];
} }
@@ -156,6 +156,79 @@ rect_t ViewMainDecoration::getWidgetsZone(bool showTopBar) const
return rect_t{x, y, w, h}; return rect_t{x, y, w, h};
} }
#if defined(MAIN_VIEW_FLEX_SLOTS)
// Explicit slot -> flex input map, for targets whose flex order differs
enum {
SLOT_BOTTOM_LEFT = 0,
SLOT_BOTTOM_CENTER,
SLOT_BOTTOM_RIGHT,
SLOT_LEFT,
SLOT_RIGHT,
SLOT_LEFT_2,
SLOT_RIGHT_2,
SLOT_COUNT
};
static const int8_t _flex_slots[SLOT_COUNT] = MAIN_VIEW_FLEX_SLOTS;
static int slotPot(uint8_t slot)
{
int pot = _flex_slots[slot];
if (pot < 0 || pot >= adcGetMaxInputs(ADC_INPUT_FLEX)) return -1;
return IS_POT_AVAILABLE(pot) ? pot : -1;
}
void ViewMainDecoration::createSliders(Window* ml, Window* mr, Window* bl, Window* bc, Window* br)
{
int pot;
if ((pot = slotPot(SLOT_BOTTOM_LEFT)) >= 0)
sliders[pot] = new MainViewHorizontalSlider(bl, pot);
if ((pot = slotPot(SLOT_BOTTOM_CENTER)) >= 0) {
if (IS_POT_MULTIPOS(pot)) {
has6POS = true;
sliders[pot] = new MainView6POS(bc, pot);
} else {
sliders[pot] = new MainViewHorizontalSlider(bc, pot);
}
}
if ((pot = slotPot(SLOT_BOTTOM_RIGHT)) >= 0)
sliders[pot] = new MainViewHorizontalSlider(br, pot);
int left = slotPot(SLOT_LEFT);
int right = slotPot(SLOT_RIGHT);
int left2 = slotPot(SLOT_LEFT_2);
int right2 = slotPot(SLOT_RIGHT_2);
if (left >= 0 || right >= 0 || left2 >= 0 || right2 >= 0) {
hasVerticalSliders = true;
auto leftPots = layoutBox(ml, LV_ALIGN_LEFT_MID, LV_FLEX_FLOW_COLUMN);
leftPots->setHeight(MainViewSlider::VERTICAL_SLIDERS_HEIGHT);
auto rightPots = layoutBox(mr, LV_ALIGN_RIGHT_MID, LV_FLEX_FLOW_COLUMN);
rightPots->setHeight(MainViewSlider::VERTICAL_SLIDERS_HEIGHT);
coord_t lsh = (left2 >= 0) ? MainViewSlider::VERTICAL_SLIDERS_HEIGHT / 2 : MainViewSlider::VERTICAL_SLIDERS_HEIGHT;
coord_t rsh = (right2 >= 0) ? MainViewSlider::VERTICAL_SLIDERS_HEIGHT / 2 : MainViewSlider::VERTICAL_SLIDERS_HEIGHT;
for (auto p : {left, left2}) {
if (p >= 0)
sliders[p] = new MainViewVerticalSlider(leftPots, rect_t{0, 0, MainViewSlider::SLIDER_BAR_SIZE, lsh}, p);
}
for (auto p : {right, right2}) {
if (p >= 0)
sliders[p] = new MainViewVerticalSlider(rightPots, rect_t{0, 0, MainViewSlider::SLIDER_BAR_SIZE, rsh}, p);
}
}
}
#else
void ViewMainDecoration::createSliders(Window* ml, Window* mr, Window* bl, Window* bc, Window* br) void ViewMainDecoration::createSliders(Window* ml, Window* mr, Window* bl, Window* bc, Window* br)
{ {
int pot = 0; int pot = 0;
@@ -238,6 +311,8 @@ void ViewMainDecoration::createSliders(Window* ml, Window* mr, Window* bl, Windo
} }
} }
#endif // MAIN_VIEW_FLEX_SLOTS
void ViewMainDecoration::createTrims(Window* ml, Window* mr, Window* bl, Window* br) void ViewMainDecoration::createTrims(Window* ml, Window* mr, Window* bl, Window* br)
{ {
// Trim order TRIM_LH, TRIM_LV, TRIM_RV, TRIM_RH // Trim order TRIM_LH, TRIM_LV, TRIM_RV, TRIM_RH
+2
View File
@@ -50,6 +50,8 @@ elseif(PCB STREQUAL TX15)
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_gx15.cpp) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_gx15.cpp)
elseif(PCB STREQUAL TX16SMK3) elseif(PCB STREQUAL TX16SMK3)
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_tx16smk3.cpp) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_tx16smk3.cpp)
elseif(PCB STREQUAL H17)
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_h17.cpp)
elseif(PCB STREQUAL X7) elseif(PCB STREQUAL X7)
if(PCBREV STREQUAL TPRO) if(PCBREV STREQUAL TPRO)
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_tpro.cpp) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_tpro.cpp)
@@ -46,6 +46,8 @@
#include "yaml_datastructs_tx16smk3.cpp" #include "yaml_datastructs_tx16smk3.cpp"
#elif defined(PCBV12) #elif defined(PCBV12)
#include "yaml_datastructs_v12.cpp" #include "yaml_datastructs_v12.cpp"
#elif defined(PCBH17)
#include "yaml_datastructs_h17.cpp"
#elif defined(RADIO_T22) #elif defined(RADIO_T22)
#include "yaml_datastructs_t22.cpp" #include "yaml_datastructs_t22.cpp"
#elif defined(PCBPL18) #elif defined(PCBPL18)
File diff suppressed because it is too large Load Diff
@@ -89,6 +89,29 @@ void audioUnmute()
} }
#endif #endif
// DAC output channel; a board on DAC1_OUT2 (PA5) sets AUDIO_DAC_CH 2 in hal.h
#ifndef AUDIO_DAC_CH
#define AUDIO_DAC_CH 1
#endif
#define _AUDIO_DAC_CAT(a, b) a##b
#define _AUDIO_DAC_XCAT(a, b) _AUDIO_DAC_CAT(a, b)
#define AUDIO_DAC_CHANNEL _AUDIO_DAC_XCAT(LL_DAC_CHANNEL_, AUDIO_DAC_CH)
#define AUDIO_DAC_DHR12L _AUDIO_DAC_XCAT(DHR12L, AUDIO_DAC_CH)
#define AUDIO_DAC_CR_EN _AUDIO_DAC_XCAT(DAC_CR_EN, AUDIO_DAC_CH)
#define AUDIO_DAC_CR_TEN _AUDIO_DAC_XCAT(DAC_CR_TEN, AUDIO_DAC_CH)
#define AUDIO_DAC_CR_DMAEN _AUDIO_DAC_XCAT(DAC_CR_DMAEN, AUDIO_DAC_CH)
#define AUDIO_DAC_SR_DMAUDR _AUDIO_DAC_XCAT(DAC_SR_DMAUDR, AUDIO_DAC_CH)
#define AUDIO_DAC_CLEAR_DMAUDR() _AUDIO_DAC_XCAT(LL_DAC_ClearFlag_DMAUDR, AUDIO_DAC_CH)(AUDIO_DAC)
// Channel-2 control/trigger bits sit 16 bits above the channel-1 ones
#if AUDIO_DAC_CH == 2
#define AUDIO_DAC_TRIGGER (DAC_TRIGGER << 16)
#else
#define AUDIO_DAC_TRIGGER DAC_TRIGGER
#endif
#if defined(STM32H5) || defined(STM32H7) || defined(STM32H7RS) #if defined(STM32H5) || defined(STM32H7) || defined(STM32H7RS)
#define DAC_TRIGGER LL_DAC_TRIG_EXT_TIM6_TRGO #define DAC_TRIGGER LL_DAC_TRIG_EXT_TIM6_TRGO
@@ -165,7 +188,7 @@ static void dac_dma_init()
dmaInit.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD; dmaInit.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD;
dmaInit.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_HALFWORD; dmaInit.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_HALFWORD;
dmaInit.PeriphOrM2MSrcAddress = LL_DAC_DMA_GetRegAddr( dmaInit.PeriphOrM2MSrcAddress = LL_DAC_DMA_GetRegAddr(
DAC1, LL_DAC_CHANNEL_1, LL_DAC_DMA_REG_DATA_12BITS_LEFT_ALIGNED); AUDIO_DAC, AUDIO_DAC_CHANNEL, LL_DAC_DMA_REG_DATA_12BITS_LEFT_ALIGNED);
dmaInit.MemoryOrM2MDstAddress = (uintptr_t)_dma_buffer; dmaInit.MemoryOrM2MDstAddress = (uintptr_t)_dma_buffer;
dmaInit.NbData = DMA_BUFFER_LEN; dmaInit.NbData = DMA_BUFFER_LEN;
#elif defined(STM32H7RS) #elif defined(STM32H7RS)
@@ -215,10 +238,10 @@ static void dac_start_dma()
LL_DMA_EnableStream(AUDIO_DMA, AUDIO_DMA_Stream); LL_DMA_EnableStream(AUDIO_DMA, AUDIO_DMA_Stream);
// clear underrun flag // clear underrun flag
LL_DAC_ClearFlag_DMAUDR1(AUDIO_DAC); AUDIO_DAC_CLEAR_DMAUDR();
// enable DAC // enable DAC
AUDIO_DAC->CR |= DAC_CR_EN1 | DAC_CR_DMAEN1; AUDIO_DAC->CR |= AUDIO_DAC_CR_EN | AUDIO_DAC_CR_DMAEN;
} }
void audioConsumeCurrentBuffer() void audioConsumeCurrentBuffer()
@@ -407,14 +430,14 @@ static void dac_periph_init()
gpio_init_analog(AUDIO_OUTPUT_GPIO); gpio_init_analog(AUDIO_OUTPUT_GPIO);
// set data registre to silence // set data registre to silence
AUDIO_DAC->DHR12L1 = AUDIO_DATA_SILENCE; AUDIO_DAC->AUDIO_DAC_DHR12L = AUDIO_DATA_SILENCE;
// clear underrun flag // clear underrun flag
AUDIO_DAC->SR = DAC_SR_DMAUDR1; AUDIO_DAC->SR = AUDIO_DAC_SR_DMAUDR;
// use TIM6 TRGO as trigger // use TIM6 TRGO as trigger
// enable DAC & channel 1 trigger // enable DAC & channel trigger
AUDIO_DAC->CR = DAC_CR_TEN1 | DAC_CR_EN1 | DAC_TRIGGER; AUDIO_DAC->CR = AUDIO_DAC_CR_TEN | AUDIO_DAC_CR_EN | AUDIO_DAC_TRIGGER;
} }
// Configure DAC0 // Configure DAC0
@@ -274,7 +274,11 @@ static DSTATUS sdio_initialize(BYTE lun)
{ {
#if defined(SD2_PRESENT_GPIO) #if defined(SD2_PRESENT_GPIO)
/* Define active SD */ /* Define active SD */
if (gpio_read(SD2_PRESENT_GPIO) == 0) { // SD_SDIO2_ONLY: no internal SDMMC1 to fall back to, always use the reader
#if !defined(SD_SDIO2_ONLY)
if (gpio_read(SD2_PRESENT_GPIO) == 0)
#endif
{
currentSD.periph = SDMMC2; currentSD.periph = SDMMC2;
currentSD.D0 = SD2_SDIO_PIN_D0; currentSD.D0 = SD2_SDIO_PIN_D0;
currentSD.AF_D0 = SD2_SDIO_AF_D0; currentSD.AF_D0 = SD2_SDIO_AF_D0;
@@ -391,7 +395,12 @@ static DSTATUS sdio_status(BYTE lun)
{ {
DSTATUS stat = RES_OK; DSTATUS stat = RES_OK;
#if defined(SD2_PRESENT_GPIO) #if defined(SD_SDIO2_ONLY)
// Single SDMMC2 reader: card-detect is just the present pin
if (gpio_read(SD2_PRESENT_GPIO)) {
stat |= STA_NODISK;
}
#elif defined(SD2_PRESENT_GPIO)
if (currentSD.periph == SDMMC2 && gpio_read(SD2_PRESENT_GPIO)) { if (currentSD.periph == SDMMC2 && gpio_read(SD2_PRESENT_GPIO)) {
stat |= STA_NODISK; stat |= STA_NODISK;
} }
+191
View File
@@ -0,0 +1,191 @@
option(UNEXPECTED_SHUTDOWN "Enable the Unexpected Shutdown screen" ON)
option(PXX1 "PXX1 protocol support" ON)
option(PXX2 "PXX2 protocol support" ON)
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)
option(BLUETOOTH "FrSky BT module support" OFF)
option(INTERNAL_GPS "Support for internal GPS" 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 48000000)
set(SDCARD YES)
set(STORAGE_MODELSLIST YES)
set(HAPTIC YES)
set(GUI_DIR colorlcd)
set(BITMAPS_DIR 480x272)
set(TARGET_DIR h17)
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(ROTARY_ENCODER YES)
set(INTERNAL_GPS_BAUDRATE "9600" CACHE STRING "Baud rate for internal GPS")
#option(STICK_DEAD_ZONE "Enable sticks dead zone" YES)
if(BLUETOOTH)
set(AUX2_SERIAL OFF)
else()
set(AUX2_SERIAL ON)
endif()
# for size report script
set(CPU_TYPE_FULL STM32H750xB)
set(TARGET_LINKER_DIR stm32h750_sdram)
set(TARGET_EXTRAM_START 0xD0000000)
set(SIZE_TARGET_MEM_DEFINE "MEM_SIZE_SDRAM1=8192")
set(FIRMWARE_STRIP_BOOTLOADER YES)
add_definitions(-DPCBH17 -DPCBHORUS)
add_definitions(-DSTM32_SUPPORT_32BIT_TIMERS)
add_definitions(-DFIRMWARE_QSPI)
add_definitions(-DFIRMWARE_FORMAT_UF2)
add_definitions(-DUSE_CUSTOM_EXTI_IRQ)
set(FLAVOUR h17)
add_definitions(-DRADIO_H17)
add_definitions(-DMANUFACTURER_SENDUWING)
# 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 bm480_bitmaps)
set(FONTS_TARGET x12_fonts)
set(LCD_DRIVER lcd_driver.cpp)
set(HARDWARE_TOUCH YES)
set(RADIO_DEPENDENCIES ${RADIO_DEPENDENCIES} ${BITMAPS_TARGET})
set(FIRMWARE_DEPENDENCIES datacopy)
set(SOFTWARE_KEYBOARD ON)
set(FLYSKY_GIMBAL OFF)
set(AUX_SERIAL YES)
set(AUX2_SERIAL YES)
add_definitions(
-DSTM32H750XBTx -DSTM32H750xx
-DSDRAM -DCCMRAM
-DHARDWARE_TOUCH -DHARDWARE_KEYS -DSOFTWARE_KEYBOARD
)
set(SDRAM ON)
add_definitions(-DSOFTWARE_VOLUME)
add_definitions(-DRTCLOCK)
add_definitions(-DPWR_BUTTON_${PWR_BUTTON})
add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE})
if(STICK_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(INTERNAL_GPS)
message("-- Internal GPS enabled")
add_definitions(-DINTERNAL_GPS)
add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE})
set(SRC ${SRC} gps.cpp gps_nmea.cpp gps_ubx.cpp)
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 senduwing-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
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
)
# 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
)
add_dependencies(board_bl minimal_board_lib)
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $<TARGET_OBJECTS:board_bl>)
set(CMSIS_SRC ${BOARD_SRC_DIR}/system_clock.c)
# Firmware board library
add_library(board OBJECT EXCLUDE_FROM_ALL
${BOARD_COMMON_SRC}
${BOARD_SRC_DIR}/tp_gt911.cpp
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/trainer_driver.cpp
)
add_dependencies(board board_lib)
set(FIRMWARE_SRC ${FIRMWARE_SRC} $<TARGET_OBJECTS:board>)
if(BLUETOOTH)
target_sources(board PRIVATE targets/common/arm/stm32/bluetooth_driver.cpp)
endif()
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)
+303
View File
@@ -0,0 +1,303 @@
/*
* 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.
*/
/*
Senduwing H17 - STM32H750XBH6
Hardware notes (vs RadioMaster TX15, on which the display/LTDC wiring is based):
- No I2C IO expander: switches, keys and trims are wired directly to GPIO
(see boards/hw_defs/h17.json which is the source of truth for those).
- Parallel RGB (LTDC) panel, no MCU-side SPI configuration bus.
- Analog audio through DAC1 + external amplifier with hardware mute.
DMA1
Stream0: AUDIO_DMA_Stream (DAC)
Stream1: INTMODULE_DMA_STREAM
Stream2:
Stream3: TELEMETRY_DMA_Stream_RX
Stream4:
Stream5: INTMODULE_RX_DMA_STREAM
Stream6: AUX2_SERIAL_DMA_RX_STREAM
Stream7: TELEMETRY_DMA_Stream_TX
DMA2
Stream0: ADC_EXT_DMA_STREAM (do not move)
Stream1: AUX_SERIAL_DMA_TX_STREAM
Stream2: AUX_SERIAL_DMA_RX_STREAM
Stream3: EXTMODULE_TIMER_DMA_STREAM
Stream4: ADC_DMA_STREAM (do not move)
Stream5: EXTMODULE_USART_RX_DMA_STREAM
Stream6: EXTMODULE_USART_TX_DMA_STREAM
Stream7: AUX2_SERIAL_DMA_TX_STREAM
TIM1: BACKLIGHT_TIMER
TIM3: HAPTIC_GPIO_TIMER
TIM5: EXTMODULE_TIMER
TIM6: AUDIO_TIMER
TIM8: TRAINER_TIMER
TIM12: MIXER_SCHEDULER_TIMER
TIM14: MS_TIMER
TIM17: ROTARY_ENCODER_TIMER
*/
#ifndef _HAL_H_
#define _HAL_H_
// Clocks, timers, LCD, backlight, haptic, status LEDs and rotenc: see h17.json
#include "hal_settings.h"
// ADC
#define ADC_VREF_PREC2 330
// P2 is an analog 6POS (FLEX_MULTIPOS), steps measured on H17 hardware.
// DEFAULT_6POS_IDX = calib index 8 (4 sticks + flex idx 4).
#define XPOS_CALIB_DEFAULT {0x5, 0xe, 0x17, 0x20, 0x29}
#define DEFAULT_6POS_CALIB {5, 14, 23, 32, 41}
#define DEFAULT_6POS_IDX 8
// Flex inputs are declared as S1,S2,S3,S4,6POS for the hardware pages; the
// main view slots { BL, BC, BR, left, right, left2, right2 } map back here.
#define MAIN_VIEW_FLEX_SLOTS { 0, 4, 3, 1, 2, 5, 6 }
// Power
#define PWR_SWITCH_GPIO GPIO_PIN(GPIOA, 4) // PWR_BUTTON
#define PWR_ON_GPIO GPIO_PIN(GPIOH, 12) // PWR_ON
// No USB charger on this board.
// S.Port update connector
#define HAS_SPORT_UPDATE_CONNECTOR() (false)
// Telemetry (internal module S.PORT / CRSF telemetry line on PA9)
#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(GPIOH, 5)
#define USB_GPIO_DM GPIO_PIN(GPIOA, 11)
#define USB_GPIO_DP GPIO_PIN(GPIOA, 12)
#define USB_GPIO_AF GPIO_AF10
// LCD - parallel RGB (LTDC), no SPI configuration bus (see lcd_driver.cpp)
#define LCD_RESET_GPIO GPIOJ
#define LCD_RESET_GPIO_PIN LL_GPIO_PIN_12
// QSPI Flash
#define QSPI_CLK_GPIO GPIO_PIN(GPIOF, 10)
#define QSPI_CLK_GPIO_AF GPIO_AF9
#define QSPI_CS_GPIO GPIO_PIN(GPIOG, 6)
#define QSPI_CS_GPIO_AF GPIO_AF10
#define QSPI_MISO_GPIO GPIO_PIN(GPIOF, 9)
#define QSPI_MISO_GPIO_AF GPIO_AF10
#define QSPI_MOSI_GPIO GPIO_PIN(GPIOF, 8)
#define QSPI_MOSI_GPIO_AF GPIO_AF10
#define QSPI_WP_GPIO GPIO_PIN(GPIOF, 7)
#define QSPI_WP_GPIO_AF GPIO_AF9
#define QSPI_HOLD_GPIO GPIO_PIN(GPIOF, 6)
#define QSPI_HOLD_GPIO_AF GPIO_AF9
#define QSPI_FLASH_SIZE 0x1000000
// SD (SDIO) - only the external reader on SDMMC2, no internal SDMMC1 device
#define SD_SDIO2_ONLY
#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) // Hz
#define SD2_PRESENT_GPIO GPIO_PIN(GPIOH, 8) // PH.08
#define SD2_SDIO SDMMC2
#define SD2_SDIO_PIN_D0 GPIO_PIN(GPIOB, 14)
#define SD2_SDIO_AF_D0 GPIO_AF9
#define SD2_SDIO_PIN_D1 GPIO_PIN(GPIOB, 15)
#define SD2_SDIO_AF_D1 GPIO_AF9
#define SD2_SDIO_PIN_D2 GPIO_PIN(GPIOG, 11)
#define SD2_SDIO_AF_D2 GPIO_AF10
#define SD2_SDIO_PIN_D3 GPIO_PIN(GPIOB, 4)
#define SD2_SDIO_AF_D3 GPIO_AF9
#define SD2_SDIO_PIN_CLK GPIO_PIN(GPIOD, 6)
#define SD2_SDIO_AF_CLK GPIO_AF11
#define SD2_SDIO_PIN_CMD GPIO_PIN(GPIOD, 7)
#define SD2_SDIO_AF_CMD GPIO_AF11
#define SD2_SDIO_TRANSFER_CLK_DIV SD_SDIO_CLK_DIV(24000000) // Hz
#define STORAGE_USE_SDIO
// AUDIO (analog, DAC1 channel 2 / PA5 + external amp with hardware mute)
#define AUDIO_MUTE_GPIO GPIO_PIN(GPIOH, 10)
#define AUDIO_MUTE_DELAY 200 // ms
#define AUDIO_UNMUTE_DELAY 100 // ms
#define AUDIO_OUTPUT_GPIO GPIO_PIN(GPIOA, 5) // DAC1_OUT2
#define AUDIO_DAC DAC1
#define AUDIO_DAC_CH 2
#define AUDIO_DMA DMA1
#define AUDIO_DMA_Stream LL_DMA_STREAM_0
#define AUDIO_DMA_Channel LL_DMAMUX1_REQ_DAC1_CH2
#define AUDIO_TIM_IRQn TIM6_DAC_IRQn
#define AUDIO_TIM_IRQHandler TIM6_DAC_IRQHandler
#define AUDIO_DMA_Stream_IRQn DMA1_Stream0_IRQn
#define AUDIO_DMA_Stream_IRQHandler DMA1_Stream0_IRQHandler
#define AUDIO_TIMER TIM6
// I2C Bus (touch)
#define I2C_B1 I2C4
#define I2C_B1_SDA_GPIO GPIO_PIN(GPIOD, 13) // PD.13
#define I2C_B1_SCL_GPIO GPIO_PIN(GPIOD, 12) // PD.12
#define I2C_B1_GPIO_AF LL_GPIO_AF_4
#define I2C_B1_CLK_RATE 400000
// Internal Module (CRSF)
#define INTMODULE_PWR_GPIO GPIO_PIN(GPIOB, 13) // PB.13
#define INTMODULE_BOOTCMD_GPIO GPIO_PIN(GPIOH, 9) // PH.09
#define INTMODULE_BOOTCMD_DEFAULT 0
#define INTMODULE_TX_GPIO GPIO_PIN(GPIOG, 14)
#define INTMODULE_RX_GPIO GPIO_PIN(GPIOG, 9)
#define INTMODULE_USART USART6
#define INTMODULE_GPIO_AF LL_GPIO_AF_7
#define INTMODULE_USART_IRQn USART6_IRQn
#define INTMODULE_USART_IRQHandler USART6_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_USART6_TX
#define INTMODULE_RX_DMA DMA1
#define INTMODULE_RX_DMA_STREAM LL_DMA_STREAM_5
#define INTMODULE_RX_DMA_CHANNEL LL_DMAMUX1_REQ_USART6_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(GPIOD, 4) // PD.04
#define EXTMODULE_TX_GPIO GPIO_PIN(GPIOA, 2) // TIM5_CH3
#define EXTMODULE_RX_GPIO GPIO_PIN(GPIOA, 3)
#define EXTMODULE_TX_GPIO_AF LL_GPIO_AF_3 // TIM5_CH3
#define EXTMODULE_TIMER TIM5
#define EXTMODULE_TIMER_32BITS
#define EXTMODULE_TIMER_Channel LL_TIM_CHANNEL_CH3
#define EXTMODULE_TIMER_IRQn TIM5_IRQn
#define EXTMODULE_TIMER_IRQHandler TIM5_IRQHandler
#define EXTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2)
#define EXTMODULE_TIMER_TX_GPIO_AF LL_GPIO_AF_2
//USART
#define EXTMODULE_USART USART2
#define EXTMODULE_USART_TX_DMA DMA2
#define EXTMODULE_USART_TX_DMA_CHANNEL LL_DMAMUX1_REQ_USART2_TX
#define EXTMODULE_USART_TX_DMA_STREAM LL_DMA_STREAM_6
#define EXTMODULE_USART_RX_DMA_CHANNEL LL_DMAMUX1_REQ_USART2_RX
#define EXTMODULE_USART_RX_DMA_STREAM LL_DMA_STREAM_5
#define EXTMODULE_USART_IRQHandler USART2_IRQHandler
#define EXTMODULE_USART_IRQn USART2_IRQn
//TIMER
#define EXTMODULE_TIMER_DMA_CHANNEL LL_DMAMUX1_REQ_TIM5_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_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA)
#define TRAINER_IN_GPIO GPIO_PIN(GPIOI, 6)
#define TRAINER_IN_TIMER_Channel LL_TIM_CHANNEL_CH2
#define TRAINER_OUT_GPIO GPIO_PIN(GPIOI, 5)
#define TRAINER_OUT_TIMER_Channel LL_TIM_CHANNEL_CH1
#define TRAINER_TIMER TIM8
#define TRAINER_TIMER_IRQn TIM8_CC_IRQn
#define TRAINER_TIMER_IRQHandler TIM8_CC_IRQHandler
#define TRAINER_GPIO_AF LL_GPIO_AF_3
#define TRAINER_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2)
#define TRAINER_DETECT_GPIO GPIO_PIN(GPIOH, 4)
// AUX ports
#define AUX_SERIAL_TX_GPIO GPIO_PIN(GPIOB, 6) // PB.06
#define AUX_SERIAL_RX_GPIO GPIO_PIN(GPIOB, 5) // PB.05
#define AUX_SERIAL_USART UART5
#define AUX_SERIAL_USART_IRQHandler UART5_IRQHandler
#define AUX_SERIAL_USART_IRQn UART5_IRQn
#define AUX_SERIAL_DMA_TX DMA2
#define AUX_SERIAL_DMA_TX_STREAM LL_DMA_STREAM_1
#define AUX_SERIAL_DMA_TX_CHANNEL LL_DMAMUX1_REQ_UART5_TX
#define AUX_SERIAL_DMA_RX DMA2
#define AUX_SERIAL_DMA_RX_STREAM LL_DMA_STREAM_2
#define AUX_SERIAL_DMA_RX_CHANNEL LL_DMAMUX1_REQ_UART5_RX
#define AUX_SERIAL_PWR_GPIO GPIO_PIN(GPIOB, 7) // PB.07
#define AUX2_SERIAL_TX_GPIO GPIO_PIN(GPIOB, 10) // PB.10
#define AUX2_SERIAL_RX_GPIO GPIO_PIN(GPIOB, 11) // PB.11
#define AUX2_SERIAL_USART USART3
#define AUX2_SERIAL_USART_IRQHandler USART3_IRQHandler
#define AUX2_SERIAL_USART_IRQn USART3_IRQn
#define AUX2_SERIAL_DMA_TX DMA2
#define AUX2_SERIAL_DMA_TX_STREAM LL_DMA_STREAM_7
#define AUX2_SERIAL_DMA_TX_CHANNEL LL_DMAMUX1_REQ_USART3_TX
#define AUX2_SERIAL_DMA_RX DMA1
#define AUX2_SERIAL_DMA_RX_STREAM LL_DMA_STREAM_6
#define AUX2_SERIAL_DMA_RX_CHANNEL LL_DMAMUX1_REQ_USART3_RX
#define AUX2_SERIAL_PWR_GPIO GPIO_PIN(GPIOC, 13) // PC.13
// Touch
#define TOUCH_I2C_BUS I2C_Bus_1
#define TOUCH_INT_GPIO GPIO_PIN(GPIOE, 2) // PE.02
#define TOUCH_RST_GPIO GPIO_PIN(GPIOJ, 13) // PJ.13
// TOUCH_INT_EXTI IRQ
#if !defined(USE_EXTI2_IRQ)
#define USE_EXTI2_IRQ
#define EXTI2_IRQ_Priority 9
#endif
// No I2C IO-expander here, so the rotenc exti list carries USE_EXTI9_5_IRQ.
#define LANDSCAPE_LCD true
#define PORTRAIT_LCD false
#define LANDSCAPE_LCD_SML false
#define LANDSCAPE_LCD_STD true
#define LANDSCAPE_LCD_LRG false
#define LSE_DRIVE_STRENGTH RCC_LSEDRIVE_HIGH
#endif // _HAL_H_
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _USB_DESCRIPTOR_H_
#define _USB_DESCRIPTOR_H_
#define USB_NAME "Senduwing H17"
#define USB_MANUFACTURER 'S', 'E', 'N', 'D', ' ', ' ', ' ', ' ' /* 8 bytes */
#define USB_PRODUCT 'H', '1', '7', ' ', ' ', ' ', ' ', ' ' /* 8 Bytes */
#endif // _USB_DESCRIPTOR_H_
+74
View File
@@ -262,6 +262,80 @@ LEGACY_NAMES = [
} }
} }
}, },
{
"targets": {"h17"},
"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": "S1",
"lua": "s1",
"label": "S1",
"short_label": "1",
"description": "Potentiometer S1"
},
"P2": {
"yaml": "6POS",
"lua": "6pos",
"label": "6POS",
"short_label": "6",
"description": "Multipos Switch"
},
"P3": {
"yaml": "S4",
"lua": "s4",
"label": "S4",
"short_label": "4",
"description": "Potentiometer S4"
},
"SL1": {
"yaml": "S2",
"lua": "s2",
"label": "S2",
"short_label": "2",
"description": "Potentiometer S2"
},
"SL2": {
"yaml": "S3",
"lua": "s3",
"label": "S3",
"short_label": "3",
"description": "Potentiometer S3"
},
"EXT1": {
"yaml": "EXT1",
"lua": "ext1",
"label": "EXT1",
"short_label": "E1",
"description": "Ext 1"
},
"EXT2": {
"yaml": "EXT2",
"lua": "ext2",
"label": "EXT2",
"short_label": "E2",
"description": "Ext 2"
}
}
},
{ {
"targets": {"x12s"}, "targets": {"x12s"},
"inputs": { "inputs": {
+3
View File
@@ -170,6 +170,9 @@ get_target_build_options() {
pa01) pa01)
BUILD_OPTIONS+="-DPCB=PA01" BUILD_OPTIONS+="-DPCB=PA01"
;; ;;
h17)
BUILD_OPTIONS+="-DPCB=H17"
;;
*) *)
echo "Unknown target: $target_name" echo "Unknown target: $target_name"
return 1 return 1
+1 -1
View File
@@ -226,7 +226,7 @@ else
tx12mk2 zorro v14 v14lcd tx12mk2 zorro v14 v14lcd
x7access x9dp2019 x9e x7access x9dp2019 x9e
# colour # colour
c14 el18 nb4p nv14 st16 pa01 c14 el18 h17 nb4p nv14 st16 pa01
pl18 pl18ev pl18u pl18 pl18ev pl18u
t15 t15pro t16 t18 t22 t15 t15pro t16 t18 t22
tx15 gx15 tx16s tx16smk3 f16 v12 v16 tx15 gx15 tx16s tx16smk3 f16 v12 v16
+1 -1
View File
@@ -9,7 +9,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
: "${SRCDIR:=$(dirname "$(pwd)/$0")/..}" : "${SRCDIR:=$(dirname "$(pwd)/$0")/..}"
: ${FLAVOR:="nv14;el18;pl18;pl18ev;pl18u;nb4p;st16;c14;pa01;t12;t12max;t15;t15pro;t22;t16;t18;t8;zorro;pocket;commando8;tlite;tpro;tprov2;tpros;bumblebee;t20;t20v2;t14;lr3pro;mt12;gx12;tx12;tx12mk2;boxer;tx16s;tx16smk3;x10;x10express;x12s;x7;x7access;x9d;x9dp;x9dp2019;x9e;x9lite;x9lites;xlite;xlites;f16;v16;v14;v14lcd;v12;tx15;gx15"} : ${FLAVOR:="nv14;el18;pl18;pl18ev;pl18u;nb4p;st16;c14;pa01;t12;t12max;t15;t15pro;t22;t16;t18;t8;zorro;pocket;commando8;tlite;tpro;tprov2;tpros;bumblebee;t20;t20v2;t14;lr3pro;mt12;gx12;tx12;tx12mk2;boxer;tx16s;tx16smk3;x10;x10express;x12s;x7;x7access;x9d;x9dp;x9dp2019;x9e;x9lite;x9lites;xlite;xlites;f16;v16;v14;v14lcd;v12;tx15;gx15;h17"}
: ${COMMON_OPTIONS:="-DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_RULE_MESSAGES=OFF -Wno-dev -DCMAKE_MESSAGE_LOG_LEVEL=WARNING"} : ${COMMON_OPTIONS:="-DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_RULE_MESSAGES=OFF -Wno-dev -DCMAKE_MESSAGE_LOG_LEVEL=WARNING"}
# wipe build directory clean # wipe build directory clean
+1 -1
View File
@@ -11,7 +11,7 @@ if [[ -n ${GCC_ARM} ]] ; then
export PATH=${GCC_ARM}:$PATH export PATH=${GCC_ARM}:$PATH
fi fi
: ${FLAVOR:="x10;t15;pl18;nv14;pl18u;nb4p;x9d;x9dp2019;x9e;xlite;xlites;x7;tpro;t20;f16;gx12;st16;c14;pa01;tx15;gx15;t15pro;tx16smk3;t22;v12"} : ${FLAVOR:="x10;t15;pl18;nv14;pl18u;nb4p;x9d;x9dp2019;x9e;xlite;xlites;x7;tpro;t20;f16;gx12;st16;c14;pa01;tx15;gx15;t15pro;tx16smk3;t22;v12;h17"}
: ${SRCDIR:="$(dirname "$SCRIPT_DIR")"} : ${SRCDIR:="$(dirname "$SCRIPT_DIR")"}
: ${COMMON_OPTIONS:="-DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_RULE_MESSAGES=OFF -Wno-dev -DDISABLE_COMPANION=YES -DCMAKE_MESSAGE_LOG_LEVEL=WARNING"} : ${COMMON_OPTIONS:="-DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_RULE_MESSAGES=OFF -Wno-dev -DDISABLE_COMPANION=YES -DCMAKE_MESSAGE_LOG_LEVEL=WARNING"}
+176
View File
@@ -6535,5 +6535,181 @@
"side": "R" "side": "R"
} }
] ]
},
{
"name": "Senduwing H17",
"wasm": "edgetx-h17-simulator.wasm",
"display": {
"w": 480,
"h": 272,
"depth": 16
},
"inputs": [
{
"name": "LH",
"type": "STICK",
"label": "LH"
},
{
"name": "LV",
"type": "STICK",
"label": "LV"
},
{
"name": "RV",
"type": "STICK",
"label": "RV"
},
{
"name": "RH",
"type": "STICK",
"label": "RH"
},
{
"name": "P1",
"type": "FLEX",
"label": "S1",
"default": "POT"
},
{
"name": "SL1",
"type": "FLEX",
"label": "S2",
"default": "POT"
},
{
"name": "SL2",
"type": "FLEX",
"label": "S3",
"default": "POT"
},
{
"name": "P3",
"type": "FLEX",
"label": "S4",
"default": "POT"
},
{
"name": "P2",
"type": "FLEX",
"label": "6POS",
"default": "MULTIPOS"
},
{
"name": "EXT1",
"type": "FLEX",
"label": "EXT1",
"default": "NONE"
},
{
"name": "EXT2",
"type": "FLEX",
"label": "EXT2",
"default": "NONE"
}
],
"switches": [
{
"name": "SA",
"type": "3POS",
"default": "2POS"
},
{
"name": "SB",
"type": "3POS",
"default": "3POS"
},
{
"name": "SC",
"type": "3POS",
"default": "3POS"
},
{
"name": "SD",
"type": "3POS",
"default": "2POS"
},
{
"name": "SE",
"type": "3POS",
"default": "3POS"
},
{
"name": "SF",
"type": "2POS",
"default": "2POS"
},
{
"name": "SG",
"type": "2POS",
"default": "TOGGLE"
},
{
"name": "SH",
"type": "2POS",
"default": "TOGGLE"
},
{
"name": "SI",
"type": "2POS",
"default": "2POS"
},
{
"name": "SJ",
"type": "2POS",
"default": "2POS"
}
],
"trims": [
{
"name": "T1"
},
{
"name": "T2"
},
{
"name": "T3"
},
{
"name": "T4"
}
],
"keys": [
{
"key": "KEY_MODEL",
"label": "MDL",
"side": "R"
},
{
"key": "KEY_SYS",
"label": "SYS",
"side": "L"
},
{
"key": "KEY_PAGEUP",
"label": "PAGE◀",
"side": "L"
},
{
"key": "KEY_PAGEDN",
"label": "PAGE▶",
"side": "R"
},
{
"key": "KEY_TELE",
"label": "TELE",
"side": "R"
},
{
"key": "KEY_EXIT",
"label": "RTN",
"side": "L"
},
{
"key": "KEY_ENTER",
"label": "Enter ⏎",
"side": "R"
}
]
} }
] ]