diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 5c2235ab2..f6cce928b 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -91,7 +91,8 @@ body: multiple: true options: - BetaFPV LiteRadio3 Pro - - iFlight Commando8 + - iFlight Commando 8 + - iFlight Commando 14 - Fatfish F16 - Flysky EL18 - Flysky NB4+ diff --git a/.github/workflows/build_fw.yml b/.github/workflows/build_fw.yml index 202d614c0..5609098fc 100644 --- a/.github/workflows/build_fw.yml +++ b/.github/workflows/build_fw.yml @@ -48,6 +48,7 @@ jobs: - t15pro - pa01 - t22 + - c14 container: image: ghcr.io/edgetx/edgetx-dev:latest volumes: @@ -93,6 +94,7 @@ jobs: - nb4p;st16 - tx16smk3;t14;t15pro - t22 + - c14 container: image: ghcr.io/edgetx/edgetx-dev:latest volumes: diff --git a/.github/workflows/companion.yml b/.github/workflows/companion.yml index acc0f7546..3cdde32d1 100644 --- a/.github/workflows/companion.yml +++ b/.github/workflows/companion.yml @@ -57,7 +57,7 @@ jobs: - id: bw-3 target: [x7access, x9dp2019, x9e, x9e-hall] - id: color-4 - target: [nb4p, st16, pa01] + target: [nb4p, st16, pa01, c14] - id: color-5 target: [t15pro, tx16smk3] diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 7536c66ac..1c21ac414 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -37,6 +37,7 @@ jobs: - mt12 - nb4p - st16 + - c14 - tx15 - t15pro container: diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp index 8195d114e..456f20dbf 100644 --- a/companion/src/firmwares/boards.cpp +++ b/companion/src/firmwares/boards.cpp @@ -161,6 +161,8 @@ uint32_t Boards::getFourCC(Type board) return 0x4A78746F; case BOARD_FLYSKY_ST16: return 0x4C78746F; + case BOARD_IFLIGHT_COMMANDO14: + return 0x4F78746F; case BOARD_HELLORADIOSKY_V14: return 0x4D78746F; case BOARD_HELLORADIOSKY_V14LCD: @@ -230,6 +232,7 @@ int Boards::getEEpromSize(Board::Type board) case BOARD_FLYSKY_PL18U: case BOARD_FLYSKY_NB4P: case BOARD_FLYSKY_ST16: + case BOARD_IFLIGHT_COMMANDO14: case BOARD_FATFISH_F16: case BOARD_HELLORADIOSKY_V16: return 0; @@ -295,6 +298,7 @@ int Boards::getFlashSize(Type board) case BOARD_FLYSKY_PL18U: case BOARD_FLYSKY_NB4P: case BOARD_FLYSKY_ST16: // 8MB SDRAM + case BOARD_IFLIGHT_COMMANDO14: // 8MB SDRAM case BOARD_FATFISH_F16: case BOARD_HELLORADIOSKY_V16: return FSIZE_2MB; @@ -402,7 +406,8 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) IS_RADIOMASTER_TX12_MK2(board) || IS_RADIOMASTER_TX16S(board) || IS_RADIOMASTER_ZORRO(board) || IS_RADIOMASTER_TX15(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)); default: return getBoardJson(board)->getCapability(capability); @@ -664,6 +669,8 @@ QString Boards::getBoardName(Board::Type board) return "BETAFPV LR3PRO"; case BOARD_IFLIGHT_COMMANDO8: return "iFlight Commando 8"; + case BOARD_IFLIGHT_COMMANDO14: + return "iFlight Commando 14"; case BOARD_FATFISH_F16: return "Fatfish F16"; case BOARD_HELLORADIOSKY_V16: @@ -783,6 +790,7 @@ int Boards::getDefaultInternalModules(Board::Type board) case BOARD_RADIOMASTER_TX15: case BOARD_RADIOMASTER_TX16SMK3: case BOARD_IFLIGHT_COMMANDO8: + case BOARD_IFLIGHT_COMMANDO14: case BOARD_JUMPER_BUMBLEBEE: case BOARD_JUMPER_T12MAX: case BOARD_JUMPER_T14: @@ -844,6 +852,7 @@ void Boards::getBattRange(Board::Type board, int& vmin, int& vmax, unsigned int& break; case BOARD_TARANIS_X9E: case BOARD_HORUS_X12S: + case BOARD_IFLIGHT_COMMANDO14: BR(85, 115, 87) break; case BOARD_TARANIS_XLITE: diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index 466ff4c0c..66996096b 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -99,6 +99,7 @@ namespace Board { BOARD_RADIOMASTER_MT12, BOARD_HELLORADIOSKY_V14, BOARD_HELLORADIOSKY_V14LCD, + BOARD_IFLIGHT_COMMANDO14, BOARD_TYPE_COUNT, BOARD_TYPE_MAX = BOARD_TYPE_COUNT - 1 }; @@ -750,6 +751,11 @@ inline bool IS_FLYSKY_ST16(Board::Type board) return (board == Board::BOARD_FLYSKY_ST16); } +inline bool IS_IFLIGHT_C14(Board::Type board) +{ + return (board == Board::BOARD_IFLIGHT_COMMANDO14); +} + inline bool IS_FAMILY_PL18(Board::Type board) { return IS_FLYSKY_PL18(board) || IS_FLYSKY_PL18EV(board) || IS_FLYSKY_PL18U(board); @@ -835,7 +841,8 @@ inline bool IS_FAMILY_HORUS_OR_T16(Board::Type board) return IS_FAMILY_HORUS(board) || IS_FAMILY_T16(board) || IS_FLYSKY_NV14(board)/*generally*/ || IS_FLYSKY_EL18(board)/*generally*/ || 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*/; } inline bool HAS_LARGE_LCD(Board::Type board) diff --git a/companion/src/firmwares/moduledata.cpp b/companion/src/firmwares/moduledata.cpp index 075734fcb..f68b81129 100644 --- a/companion/src/firmwares/moduledata.cpp +++ b/companion/src/firmwares/moduledata.cpp @@ -508,6 +508,9 @@ bool ModuleData::isProtocolAvailable(int moduleidx, unsigned int protocol, Gener const int moduleSize = g.currentProfile().externalModuleSize(); const int moduleType = getTypeFromProtocol(protocol); + if (IS_IFLIGHT_C14(getCurrentBoard())) + return moduleType == MODULE_TYPE_CROSSFIRE || moduleType == MODULE_TYPE_GHOST; + switch(moduleSize) { case Board::EXTMODSIZE_NONE: return false; diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 7e28d68d3..1a53e3c23 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -517,7 +517,7 @@ void registerOpenTxFirmwares() registerOpenTxFirmware(firmware); /* iFlight Commando8 board */ - firmware = new OpenTxFirmware(FIRMWAREID("commando8"), QCoreApplication::translate("Firmware", "iFlight Commando8"), BOARD_IFLIGHT_COMMANDO8); + firmware = new OpenTxFirmware(FIRMWAREID("commando8"), QCoreApplication::translate("Firmware", "iFlight Commando 8"), BOARD_IFLIGHT_COMMANDO8); addOpenTxCommonOptions(firmware); firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support")); firmware->addOption("nogvars", Firmware::tr("Disable Global variables")); @@ -526,6 +526,12 @@ void registerOpenTxFirmwares() registerOpenTxFirmware(firmware); addOpenTxRfOptions(firmware, NONE); + /* iFlight Commando 14 board */ + firmware = new OpenTxFirmware(FIRMWAREID("c14"), Firmware::tr("iFlight Commando 14"), BOARD_IFLIGHT_COMMANDO14); + addOpenTxFrskyOptions(firmware); + addOpenTxRfOptions(firmware, FLEX); + registerOpenTxFirmware(firmware); + /* Jumper T-Lite board */ firmware = new OpenTxFirmware(FIRMWAREID("tlite"), QCoreApplication::translate("Firmware", "Jumper T-Lite"), BOARD_JUMPER_TLITE); addOpenTxCommonOptions(firmware); diff --git a/fw.json b/fw.json index ba067d41f..21403470a 100644 --- a/fw.json +++ b/fw.json @@ -20,6 +20,7 @@ ["HelloRadioSky V14LCD", "v14lcd-"], ["HelloRadioSky V16", "v16-"], ["iFlight Commando 8", "commando8-"], + ["iFlight Commando 14", "c14-"], ["Jumper Bumblebee", "bumblebee-"], ["Jumper T12 MAX", "t12max-"], ["Jumper T14", "t14-"], diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index d38b54e9f..8d4cd2146 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -95,6 +95,8 @@ elseif(PCB STREQUAL T15PRO) include(targets/t15pro/CMakeLists.txt) elseif(PCB STREQUAL ST16) include(targets/st16/CMakeLists.txt) + elseif(PCB STREQUAL C14) + include(targets/c14/CMakeLists.txt) elseif(PCB STREQUAL PA01) include(targets/pa01/CMakeLists.txt) elseif(PCB STREQUAL TX15) diff --git a/radio/src/boards/generic_stm32/module_ports.cpp b/radio/src/boards/generic_stm32/module_ports.cpp index 19127f928..9fd2e7638 100644 --- a/radio/src/boards/generic_stm32/module_ports.cpp +++ b/radio/src/boards/generic_stm32/module_ports.cpp @@ -207,6 +207,7 @@ DEFINE_STM32_SERIAL_PORT(SbusTrainer, sbus_trainer_USART, 32, 0); #endif +#if defined(EXTMODULE_TIMER) static stm32_pulse_dma_tc_cb_t _ext_timer_DMA_TC_Callback; static const stm32_pulse_timer_t extmoduleTimer = { @@ -250,6 +251,7 @@ extern "C" void EXTMODULE_TIMER_IRQHandler() } DEFINE_STM32_SOFTSERIAL_PORT(ExternalModule, extmoduleTimer); +#endif // EXTMODULE_TIMER #if defined(TRAINER_MODULE_CPPM_TIMER) @@ -489,6 +491,7 @@ static const etx_module_port_t _external_ports[] = { #endif }, #endif +#if defined(EXTMODULE_TIMER) // Timer output on PPM { .port = ETX_MOD_PORT_TIMER, @@ -515,6 +518,7 @@ static const etx_module_port_t _external_ports[] = { .set_inverted = nullptr, #endif }, +#endif // EXTMODULE_TIMER #if !defined(EXTMODULE_USART) && defined(TRAINER_MODULE_SBUS_USART) // RX on HEARTBEAT { diff --git a/radio/src/boards/hw_defs/c14.json b/radio/src/boards/hw_defs/c14.json new file mode 100644 index 000000000..1550f88b1 --- /dev/null +++ b/radio/src/boards/hw_defs/c14.json @@ -0,0 +1,380 @@ +{ + "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_64CYCLES_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_64CYCLES_5" + } + ], + "inputs": [ + { + "name": "LH", + "type": "STICK", + "adc": "MAIN", + "gpio": "GPIOA", + "pin": "LL_GPIO_PIN_1", + "channel": "LL_ADC_CHANNEL_14", + "pwm_channel": 0 + }, + { + "name": "LV", + "type": "STICK", + "adc": "MAIN", + "gpio": "GPIOA", + "pin": "LL_GPIO_PIN_0", + "channel": "LL_ADC_CHANNEL_15", + "pwm_channel": 1 + }, + { + "name": "RV", + "type": "STICK", + "adc": "MAIN", + "gpio": "GPIOA", + "pin": "LL_GPIO_PIN_3", + "channel": "LL_ADC_CHANNEL_16", + "pwm_channel": 2 + }, + { + "name": "RH", + "type": "STICK", + "adc": "MAIN", + "gpio": "GPIOA", + "pin": "LL_GPIO_PIN_2", + "channel": "LL_ADC_CHANNEL_17", + "pwm_channel": 3 + }, + { + "name": "P1", + "type": "FLEX", + "adc": "MAIN", + "gpio": "GPIOA", + "pin": "LL_GPIO_PIN_6", + "channel": "LL_ADC_CHANNEL_3", + "label": "S1", + "short_label": "1", + "default": "POT" + }, + { + "name": "P2", + "type": "FLEX", + "adc": "MAIN", + "gpio": "GPIOB", + "pin": "LL_GPIO_PIN_1", + "channel": "LL_ADC_CHANNEL_5", + "label": "S2", + "short_label": "2", + "default": "POT" + }, + { + "name": "SL1", + "type": "FLEX", + "adc": "MAIN", + "gpio": "GPIOB", + "pin": "LL_GPIO_PIN_0", + "channel": "LL_ADC_CHANNEL_9", + "inverted": true, + "label": "LS", + "short_label": "L", + "default": "SLIDER" + }, + { + "name": "SL2", + "type": "FLEX", + "adc": "MAIN", + "gpio": "GPIOA", + "pin": "LL_GPIO_PIN_7", + "channel": "LL_ADC_CHANNEL_7", + "label": "RS", + "short_label": "R", + "default": "SLIDER" + }, + { + "name": "VBAT", + "type": "VBAT", + "adc": "EXT", + "gpio": "GPIOC", + "pin": "LL_GPIO_PIN_1", + "channel": "LL_ADC_CHANNEL_11" + }, + { + "name": "RTC_BAT", + "type": "RTC_BAT", + "adc": "EXT", + "gpio": null, + "pin": null, + "channel": "LL_ADC_CHANNEL_VBAT" + }, + { + "name": "SWA", + "type": "SWITCH", + "adc": "EXT", + "gpio": "GPIOC", + "pin": "LL_GPIO_PIN_2", + "channel": "LL_ADC_CHANNEL_0" + }, + { + "name": "SWB", + "type": "SWITCH", + "adc": "EXT", + "gpio": "GPIOC", + "pin": "LL_GPIO_PIN_3", + "channel": "LL_ADC_CHANNEL_1" + }, + { + "name": "SWC", + "type": "SWITCH", + "adc": "EXT", + "gpio": "GPIOF", + "pin": "LL_GPIO_PIN_9", + "channel": "LL_ADC_CHANNEL_2" + }, + { + "name": "SWD", + "type": "SWITCH", + "adc": "EXT", + "gpio": "GPIOF", + "pin": "LL_GPIO_PIN_7", + "channel": "LL_ADC_CHANNEL_3" + } + ] + }, + "switches": [ + { + "name": "SA", + "type": "ADC", + "flags": 0, + "inverted": false, + "default": "3POS", + "display": null, + "adc_input": "SWA", + "is_cfs": false + }, + { + "name": "SB", + "type": "ADC", + "flags": 0, + "inverted": false, + "default": "3POS", + "display": null, + "adc_input": "SWB", + "is_cfs": false + }, + { + "name": "SC", + "type": "ADC", + "flags": 0, + "inverted": false, + "default": "3POS", + "display": null, + "adc_input": "SWC", + "is_cfs": false + }, + { + "name": "SD", + "type": "ADC", + "flags": 0, + "inverted": false, + "default": "3POS", + "display": null, + "adc_input": "SWD", + "is_cfs": false + }, + { + "name": "SE", + "type": "2POS", + "flags": 0, + "inverted": false, + "default": "2POS", + "display": null, + "gpio": "GPIOF", + "pin": "LL_GPIO_PIN_8", + "is_cfs": false + }, + { + "name": "SF", + "type": "2POS", + "flags": 0, + "inverted": false, + "default": "2POS", + "display": null, + "gpio": "GPIOF", + "pin": "LL_GPIO_PIN_6", + "is_cfs": false + } + ], + "keys": [ + { + "gpio": "GPIOG", + "pin": "LL_GPIO_PIN_14", + "active_low": true, + "key": "KEY_EXIT", + "name": "EXIT", + "label": "EXIT" + }, + { + "gpio": "GPIOC", + "pin": "LL_GPIO_PIN_5", + "active_low": true, + "key": "KEY_ENTER", + "name": "ENTER", + "label": "Enter" + }, + { + "gpio": "GPIOC", + "pin": "LL_GPIO_PIN_13", + "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": "GPIOG", + "pin": "LL_GPIO_PIN_2", + "active_low": true, + "key": "KEY_UP", + "name": "UP", + "label": "Up" + }, + { + "gpio": "GPIOG", + "pin": "LL_GPIO_PIN_3", + "active_low": true, + "key": "KEY_DOWN", + "name": "DOWN", + "label": "Down" + }, + { + "gpio": "GPIOA", + "pin": "LL_GPIO_PIN_10", + "active_low": true, + "key": "KEY_MODEL", + "name": "MDL", + "label": "MDL" + }, + { + "gpio": "GPIOC", + "pin": "LL_GPIO_PIN_4", + "active_low": true, + "key": "KEY_SYS", + "name": "SYS", + "label": "SYS" + } + ], + "trims": [ + { + "name": "T1" + }, + { + "name": "T2" + }, + { + "name": "T3" + }, + { + "name": "T4" + } + ], + "display": { + "lcd_w": 480, + "lcd_h": 272, + "lcd_phys_w": 480, + "lcd_phys_h": 272, + "lcd_depth": 16, + "oled_screen": false, + "ltdc_irq_prio": 4, + "dma_screen_irq_prio": 6 + }, + "leds": { + "status_leds": true, + "led_red_gpio": "GPIO_PIN(GPIOG, 10)", + "led_green_gpio": "GPIO_PIN(GPIOG, 12)", + "led_blue_gpio": "GPIO_PIN(GPIOG, 13)", + "gpio_led_gpio_on": "gpio_set", + "gpio_led_gpio_off": "gpio_clear", + "led_strip_gpio": "GPIO_PIN(GPIOA, 15)", + "led_strip_gpio_af": "LL_GPIO_AF_1", + "led_strip_timer": "TIM2", + "led_strip_timer_freq": "(PERI1_FREQUENCY * TIMER_MULT_APB1)", + "led_strip_timer_channel": "LL_TIM_CHANNEL_CH1", + "led_strip_timer_dma": "DMA1", + "led_strip_timer_dma_channel": "LL_DMAMUX1_REQ_TIM2_UP", + "led_strip_timer_dma_stream": "LL_DMA_STREAM_0", + "led_strip_timer_dma_irqn": "DMA1_Stream0_IRQn", + "led_strip_timer_dma_irqhandler": "DMA1_Stream0_IRQHandler", + "led_strip_length": 27, + "led_strip_refresh_period": 50, + "bling_led_strip_start": 0, + "bling_led_strip_length": 27 + }, + "backlight": { + "backlight_gpio": "GPIO_PIN(GPIOC, 06)", + "backlight_gpio_af": "GPIO_AF2", + "backlight_timer": "TIM3", + "backlight_timer_freq": "(PERI1_FREQUENCY * TIMER_MULT_APB1)" + }, + "imu": { + "imu_i2c_bus": "I2C_Bus_2", + "imu_int_gpio": "GPIO_PIN(GPIOH, 4)", + "imu_invert_x": true, + "imu_invert_y": true, + "exti": [ + { "irq": "EXTI4_IRQ", "priority": 6 } + ] + }, + "haptic": { + "haptic_pwm": true, + "haptic_gpio": "GPIO_PIN(GPIOB, 5)", + "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" + }, + "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" + }, + "timers": { + "cpu_freq": 400000000, + "peri1_frequency": 100000000, + "peri2_frequency": 100000000, + "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" + } +} diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index 68cf59c57..4c22283b6 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -112,6 +112,8 @@ static inline void check_struct() #endif #elif defined(PCBST16) || defined(RADIO_T15PRO) || defined(RADIO_TX15) CHKSIZE(ModelData, 7641); +#elif defined(PCBC14) + CHKSIZE(ModelData, 7573); #elif defined(PCBPA01) CHKSIZE(ModelData, 7582); #elif defined(RADIO_T15) diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index 47ecd9cf4..41475b424 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -629,7 +629,7 @@ static_assert(sizeof(potwarnen_t) * 8 >= MAX_POTS, #define TOPBAR_DATA #endif -#if defined(PCBHORUS) || defined(PCBTARANIS) || defined(PCBPL18) || defined(PCBST16) +#if defined(PCBHORUS) || defined(PCBTARANIS) || defined(PCBPL18) || defined(PCBST16) || defined(PCBC14) #define SCRIPT_DATA \ NOBACKUP(ScriptData scriptsData[MAX_SCRIPTS]); #else diff --git a/radio/src/edgetx.cpp b/radio/src/edgetx.cpp index e856137ca..f0d256023 100644 --- a/radio/src/edgetx.cpp +++ b/radio/src/edgetx.cpp @@ -411,6 +411,10 @@ void generalDefault() g_eeGeneral.pwrOffSpeed = 2; #endif +#if defined(RADIO_C14) + g_eeGeneral.rotEncMode = ROTARY_ENCODER_MODE_INVERT_BOTH; +#endif + #if defined(MANUFACTURER_RADIOMASTER) g_eeGeneral.audioMuteEnable = 1; #if defined(RADIO_TX15) @@ -1197,7 +1201,7 @@ void edgeTxClose(uint8_t shutdown) sdDone(); -#if defined(FUNCTION_SWITCHES_RGB_LEDS) +#if defined(RGB_LEDS) turnOffRGBLeds(); #endif } @@ -1726,11 +1730,13 @@ int pwrDelayToYaml(int delay) inline uint32_t PWR_PRESS_SHUTDOWN_DELAY() { - // Instant off when both power button are pressed +#if defined(PWR_BUTTON_MANAGED) + return 0; +#else if (pwrForcePressed()) return 0; - return pwrDelayTime(g_eeGeneral.pwrOffSpeed); +#endif } uint32_t pwr_press_time = 0; @@ -1783,7 +1789,26 @@ uint32_t pwrCheck() if (pwr_check_state == PWR_CHECK_OFF) { return e_power_off; } - else if (pwrPressed() || inactivityShutdown) { + +#if defined(PWR_BUTTON_MANAGED) + if (pwrPressed()) { + bool needConfirm = + (TELEMETRY_STREAMING() && !g_eeGeneral.disableRssiPoweroffAlarm) || + (usbPlugged() && getSelectedUsbMode() != USB_UNSELECTED_MODE) || + (isTrainerConnected() && !g_eeGeneral.disableTrainerPoweroffAlarm); + if (!needConfirm) { +#if defined(HAPTIC) + if (!g_eeGeneral.disablePwrOnOffHaptic && + (g_eeGeneral.hapticMode != e_mode_quiet)) + haptic.play(15, 3, PLAY_NOW); +#endif + pwr_check_state = PWR_CHECK_OFF; + return e_power_off; + } + } +#endif + + if (pwrPressed() || inactivityShutdown) { if (!inactivityShutdown) inactivityTimerReset(ActivitySource::Keys); diff --git a/radio/src/gui/colorlcd/boot_lcd.cpp b/radio/src/gui/colorlcd/boot_lcd.cpp index 4cad2268e..d1fd67f75 100644 --- a/radio/src/gui/colorlcd/boot_lcd.cpp +++ b/radio/src/gui/colorlcd/boot_lcd.cpp @@ -123,7 +123,6 @@ void lcdInitDisplayDriver() // Init hardware LCD driver lcdInit(); - backlightInit(); init_lvgl_disp_drv(); @@ -144,6 +143,12 @@ void lcdInitDisplayDriver() lv_draw_ctx_t* draw_ctx = disp_drv.draw_ctx; lcd->setDrawCtx(draw_ctx); lcdFront->setDrawCtx(draw_ctx); + +#if defined(LCD_BACKLIGHT_INIT_DELAY_MS) + delay_ms(LCD_BACKLIGHT_INIT_DELAY_MS); +#endif + + backlightInit(); } void lcdClear() { lcd->clear(); } diff --git a/radio/src/gui/colorlcd/radio/radio_setup.cpp b/radio/src/gui/colorlcd/radio/radio_setup.cpp index ff7988f0f..f0f2956bf 100644 --- a/radio/src/gui/colorlcd/radio/radio_setup.cpp +++ b/radio/src/gui/colorlcd/radio/radio_setup.cpp @@ -809,7 +809,7 @@ const static SetupLineDef setupLines[] = { new ToggleSwitch(parent, {x, y, 0, 0}, GET_SET_INVERTED(g_eeGeneral.dontPlayHello)); } }, -#if defined(PWR_BUTTON_PRESS) +#if defined(PWR_BUTTON_PRESS) && !defined(PWR_BUTTON_MANAGED) { // Pwr Off Delay STR_DEF(STR_PWR_OFF_DELAY), @@ -823,7 +823,8 @@ const static SetupLineDef setupLines[] = { }); } }, - +#endif +#if defined(PWR_BUTTON_PRESS) // Pwr Off If Inactive { STR_DEF(STR_PWR_AUTO_OFF), diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index e8b1186a6..5f716d537 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -960,6 +960,19 @@ bool isExternalModuleAvailable(int moduleType) return false; #endif +#if defined(EXTMODULE_USART) && !defined(EXTMODULE_TIMER) + // Serial external bay with no PPM timer (e.g. C14, S.PORT-only): restrict to + // the protocols that run over the half-duplex telemetry line. + switch (moduleType) { + case MODULE_TYPE_NONE: + case MODULE_TYPE_CROSSFIRE: + case MODULE_TYPE_GHOST: + break; + default: + return false; + } +#endif + #if !defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML) if (isModuleTypeR9MLite(moduleType) || moduleType == MODULE_TYPE_XJT_LITE_PXX2) return false; diff --git a/radio/src/gyro.cpp b/radio/src/gyro.cpp index 283e4fba9..2605e3e55 100644 --- a/radio/src/gyro.cpp +++ b/radio/src/gyro.cpp @@ -184,12 +184,28 @@ void gyroWakeup() int16_t gyroScaledX() { - return limit(-RESX, gyroOutputs[0], RESX); +#if defined(IMU_SWAP_TILT_XY) + float v = gyroOutputs[1]; +#else + float v = gyroOutputs[0]; +#endif +#if defined(IMU_INVERT_TILT_X) + v = -v; +#endif + return limit(-RESX, v, RESX); } int16_t gyroScaledY() { - return limit(-RESX, gyroOutputs[1], RESX); +#if defined(IMU_SWAP_TILT_XY) + float v = gyroOutputs[0]; +#else + float v = gyroOutputs[1]; +#endif +#if defined(IMU_INVERT_TILT_Y) + v = -v; +#endif + return limit(-RESX, v, RESX); } void gyroSetIMU_X(int16_t offset, int16_t range) diff --git a/radio/src/hal/CMakeLists.txt b/radio/src/hal/CMakeLists.txt index 7e4ed1485..bc32b2130 100644 --- a/radio/src/hal/CMakeLists.txt +++ b/radio/src/hal/CMakeLists.txt @@ -7,7 +7,7 @@ set(SRC ${SRC} hal/usb_driver.cpp ) -if(FUNCTION_SWITCHES) +if(FUNCTION_SWITCHES OR RGB_LEDS) set(SRC ${SRC} hal/rgbleds.cpp ) diff --git a/radio/src/hal/rgbleds.cpp b/radio/src/hal/rgbleds.cpp index e8c1b6058..a2268bff4 100644 --- a/radio/src/hal/rgbleds.cpp +++ b/radio/src/hal/rgbleds.cpp @@ -24,6 +24,7 @@ #include "definitions.h" #include "dataconstants.h" +#if defined(FUNCTION_SWITCHES) #if defined(FUNCTION_SWITCHES_RGB_LEDS) static bool hasLedOverride[NUM_FUNCTIONS_SWITCHES] = { false }; static RGBLedColor ledOverride[NUM_FUNCTIONS_SWITCHES]; @@ -99,6 +100,7 @@ bool getFSLedState(uint8_t index) { return fsLedState(index); } #endif +#endif // FUNCTION_SWITCHES void turnOffRGBLeds() { diff --git a/radio/src/hal/rgbleds.h b/radio/src/hal/rgbleds.h index 410332caf..c28c8206d 100644 --- a/radio/src/hal/rgbleds.h +++ b/radio/src/hal/rgbleds.h @@ -25,10 +25,13 @@ // "Off", "White", "Red", "Green", "Yellow", "Orange", "Blue", "Pink" constexpr uint32_t colorTable[] = {0x000000, 0xFFFFFF, 0xFF0000, 0x00FF00, 0xFFFF00, 0xFF4000, 0x0000FF, 0xFF00FF}; +#if defined(FUNCTION_SWITCHES) void setFSEditOverride(int index, uint32_t color); void setFSLedOverride(uint8_t index, bool state, uint8_t r, uint8_t g, uint8_t b); void setFSLedOFF(uint8_t index); void setFSLedON(uint8_t index); bool getFSLedState(uint8_t index); uint32_t getFSLedRGBColor(uint8_t index); +#endif + void turnOffRGBLeds(); diff --git a/radio/src/storage/yaml/CMakeLists.txt b/radio/src/storage/yaml/CMakeLists.txt index 72ba073ee..8dc63e4a6 100644 --- a/radio/src/storage/yaml/CMakeLists.txt +++ b/radio/src/storage/yaml/CMakeLists.txt @@ -38,6 +38,8 @@ elseif(PCB STREQUAL T22) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_t22.cpp) elseif(PCB STREQUAL ST16) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_st16.cpp) +elseif(PCB STREQUAL C14) + set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_c14.cpp) elseif(PCB STREQUAL PA01) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_pa01.cpp) elseif(PCB STREQUAL TX15) diff --git a/radio/src/storage/yaml/yaml_datastructs.cpp b/radio/src/storage/yaml/yaml_datastructs.cpp index 9d209b3da..7f77d70b3 100644 --- a/radio/src/storage/yaml/yaml_datastructs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs.cpp @@ -56,6 +56,8 @@ #endif #elif defined(PCBST16) #include "yaml_datastructs_st16.cpp" +#elif defined(PCBC14) + #include "yaml_datastructs_c14.cpp" #elif defined(PCBPA01) #include "yaml_datastructs_pa01.cpp" #elif defined(PCBX7) diff --git a/radio/src/storage/yaml/yaml_datastructs_c14.cpp b/radio/src/storage/yaml/yaml_datastructs_c14.cpp new file mode 100644 index 000000000..8e437024e --- /dev/null +++ b/radio/src/storage/yaml/yaml_datastructs_c14.cpp @@ -0,0 +1,1002 @@ +// generated by generate_yaml.py + +// +// Enums first +// + +const struct YamlIdStr enum_BacklightMode[] = { + { e_backlight_mode_off, "backlight_mode_off" }, + { e_backlight_mode_keys, "backlight_mode_keys" }, + { e_backlight_mode_sticks, "backlight_mode_sticks" }, + { e_backlight_mode_all, "backlight_mode_all" }, + { e_backlight_mode_on, "backlight_mode_on" }, + { 0, NULL } +}; +const struct YamlIdStr enum_AntennaModes[] = { + { ANTENNA_MODE_INTERNAL, "MODE_INTERNAL" }, + { ANTENNA_MODE_ASK, "MODE_ASK" }, + { ANTENNA_MODE_PER_MODEL, "MODE_PER_MODEL" }, + { ANTENNA_MODE_EXTERNAL, "MODE_EXTERNAL" }, + { 0, NULL } +}; +const struct YamlIdStr enum_ModuleType[] = { + { MODULE_TYPE_NONE, "TYPE_NONE" }, + { MODULE_TYPE_PPM, "TYPE_PPM" }, + { MODULE_TYPE_XJT_PXX1, "TYPE_XJT_PXX1" }, + { MODULE_TYPE_ISRM_PXX2, "TYPE_ISRM_PXX2" }, + { MODULE_TYPE_DSM2, "TYPE_DSM2" }, + { MODULE_TYPE_CROSSFIRE, "TYPE_CROSSFIRE" }, + { MODULE_TYPE_MULTIMODULE, "TYPE_MULTIMODULE" }, + { MODULE_TYPE_R9M_PXX1, "TYPE_R9M_PXX1" }, + { MODULE_TYPE_R9M_PXX2, "TYPE_R9M_PXX2" }, + { MODULE_TYPE_R9M_LITE_PXX1, "TYPE_R9M_LITE_PXX1" }, + { MODULE_TYPE_R9M_LITE_PXX2, "TYPE_R9M_LITE_PXX2" }, + { MODULE_TYPE_GHOST, "TYPE_GHOST" }, + { MODULE_TYPE_R9M_LITE_PRO_PXX2, "TYPE_R9M_LITE_PRO_PXX2" }, + { MODULE_TYPE_SBUS, "TYPE_SBUS" }, + { MODULE_TYPE_XJT_LITE_PXX2, "TYPE_XJT_LITE_PXX2" }, + { MODULE_TYPE_FLYSKY_AFHDS2A, "TYPE_FLYSKY_AFHDS2A" }, + { MODULE_TYPE_FLYSKY_AFHDS3, "TYPE_FLYSKY_AFHDS3" }, + { MODULE_TYPE_LEMON_DSMP, "TYPE_LEMON_DSMP" }, + { 0, NULL } +}; +const struct YamlIdStr enum_TrainerMultiplex[] = { + { TRAINER_OFF, "OFF" }, + { TRAINER_ADD, "ADD" }, + { TRAINER_REPL, "REPL" }, + { 0, NULL } +}; +const struct YamlIdStr enum_BeeperMode[] = { + { e_mode_quiet, "mode_quiet" }, + { e_mode_alarms, "mode_alarms" }, + { e_mode_nokeys, "mode_nokeys" }, + { e_mode_all, "mode_all" }, + { 0, NULL } +}; +const struct YamlIdStr enum_BluetoothModes[] = { + { BLUETOOTH_OFF, "OFF" }, + { BLUETOOTH_TELEMETRY, "TELEMETRY" }, + { BLUETOOTH_TRAINER, "TRAINER" }, + { 0, NULL } +}; +const struct YamlIdStr enum_Functions[] = { + { FUNC_OVERRIDE_CHANNEL, "OVERRIDE_CHANNEL" }, + { FUNC_TRAINER, "TRAINER" }, + { FUNC_INSTANT_TRIM, "INSTANT_TRIM" }, + { FUNC_RESET, "RESET" }, + { FUNC_SET_TIMER, "SET_TIMER" }, + { FUNC_ADJUST_GVAR, "ADJUST_GVAR" }, + { FUNC_VOLUME, "VOLUME" }, + { FUNC_SET_FAILSAFE, "SET_FAILSAFE" }, + { FUNC_RANGECHECK, "RANGECHECK" }, + { FUNC_BIND, "BIND" }, + { FUNC_PLAY_SOUND, "PLAY_SOUND" }, + { FUNC_PLAY_TRACK, "PLAY_TRACK" }, + { FUNC_PLAY_VALUE, "PLAY_VALUE" }, + { FUNC_PLAY_SCRIPT, "PLAY_SCRIPT" }, + { FUNC_BACKGND_MUSIC, "BACKGND_MUSIC" }, + { FUNC_BACKGND_MUSIC_PAUSE, "BACKGND_MUSIC_PAUSE" }, + { FUNC_VARIO, "VARIO" }, + { FUNC_HAPTIC, "HAPTIC" }, + { FUNC_LOGS, "LOGS" }, + { FUNC_BACKLIGHT, "BACKLIGHT" }, + { FUNC_SCREENSHOT, "SCREENSHOT" }, + { FUNC_RACING_MODE, "RACING_MODE" }, + { FUNC_DISABLE_TOUCH, "DISABLE_TOUCH" }, + { FUNC_SET_SCREEN, "SET_SCREEN" }, + { FUNC_DISABLE_AUDIO_AMP, "DISABLE_AUDIO_AMP" }, + { FUNC_RGB_LED, "RGB_LED" }, + { FUNC_TEST, "TEST" }, + { 0, NULL } +}; +const struct YamlIdStr enum_SwitchConfig[] = { + { SWITCH_NONE, "NONE" }, + { SWITCH_TOGGLE, "TOGGLE" }, + { SWITCH_2POS, "2POS" }, + { SWITCH_3POS, "3POS" }, + { SWITCH_none, "none" }, + { SWITCH_toggle, "toggle" }, + { SWITCH_2pos, "2pos" }, + { SWITCH_3pos, "3pos" }, + { 0, NULL } +}; +const struct YamlIdStr enum_QMPage[] = { + { QM_NONE, "NONE" }, + { QM_OPEN_QUICK_MENU, "OPEN_QUICK_MENU" }, + { QM_MANAGE_MODELS, "MANAGE_MODELS" }, + { QM_MODEL_SETUP, "MODEL_SETUP" }, + { QM_MODEL_FLIGHTMODES, "MODEL_FLIGHTMODES" }, + { QM_MODEL_INPUTS, "MODEL_INPUTS" }, + { QM_MODEL_MIXES, "MODEL_MIXES" }, + { QM_MODEL_OUTPUTS, "MODEL_OUTPUTS" }, + { QM_MODEL_CURVES, "MODEL_CURVES" }, + { QM_MODEL_GVARS, "MODEL_GVARS" }, + { QM_MODEL_LS, "MODEL_LS" }, + { QM_MODEL_SF, "MODEL_SF" }, + { QM_MODEL_SCRIPTS, "MODEL_SCRIPTS" }, + { QM_MODEL_TELEMETRY, "MODEL_TELEMETRY" }, + { QM_MODEL_NOTES, "MODEL_NOTES" }, + { QM_RADIO_SETUP, "RADIO_SETUP" }, + { QM_RADIO_GF, "RADIO_GF" }, + { QM_RADIO_TRAINER, "RADIO_TRAINER" }, + { QM_RADIO_HARDWARE, "RADIO_HARDWARE" }, + { QM_RADIO_VERSION, "RADIO_VERSION" }, + { QM_UI_THEMES, "UI_THEMES" }, + { QM_UI_SETUP, "UI_SETUP" }, + { QM_UI_SCREEN1, "UI_SCREEN1" }, + { QM_UI_SCREEN2, "UI_SCREEN2" }, + { QM_UI_SCREEN3, "UI_SCREEN3" }, + { QM_UI_SCREEN4, "UI_SCREEN4" }, + { QM_UI_SCREEN5, "UI_SCREEN5" }, + { QM_UI_SCREEN6, "UI_SCREEN6" }, + { QM_UI_SCREEN7, "UI_SCREEN7" }, + { QM_UI_SCREEN8, "UI_SCREEN8" }, + { QM_UI_SCREEN9, "UI_SCREEN9" }, + { QM_UI_SCREEN10, "UI_SCREEN10" }, + { QM_UI_ADD_PG, "UI_ADD_PG" }, + { QM_TOOLS_APPS, "TOOLS_APPS" }, + { QM_TOOLS_STORAGE, "TOOLS_STORAGE" }, + { QM_TOOLS_RESET, "TOOLS_RESET" }, + { QM_TOOLS_CHAN_MON, "TOOLS_CHAN_MON" }, + { QM_TOOLS_LS_MON, "TOOLS_LS_MON" }, + { QM_TOOLS_STATS, "TOOLS_STATS" }, + { QM_TOOLS_DEBUG, "TOOLS_DEBUG" }, + { QM_APP, "APP" }, + { 0, NULL } +}; +const struct YamlIdStr enum_TimerModes[] = { + { TMRMODE_OFF, "OFF" }, + { TMRMODE_ON, "ON" }, + { TMRMODE_START, "START" }, + { TMRMODE_THR, "THR" }, + { TMRMODE_THR_REL, "THR_REL" }, + { TMRMODE_THR_START, "THR_START" }, + { 0, NULL } +}; +const struct YamlIdStr enum_MixerMultiplex[] = { + { MLTPX_ADD, "ADD" }, + { MLTPX_MUL, "MUL" }, + { MLTPX_REPL, "REPL" }, + { 0, NULL } +}; +const struct YamlIdStr enum_MixSources[] = { + { MIXSRC_NONE, "NONE" }, + { MIXSRC_TILT_X, "TILT_X" }, + { MIXSRC_TILT_Y, "TILT_Y" }, + { MIXSRC_SPACEMOUSE_A, "SPACEMOUSE_A" }, + { MIXSRC_SPACEMOUSE_B, "SPACEMOUSE_B" }, + { MIXSRC_SPACEMOUSE_C, "SPACEMOUSE_C" }, + { MIXSRC_SPACEMOUSE_D, "SPACEMOUSE_D" }, + { MIXSRC_SPACEMOUSE_E, "SPACEMOUSE_E" }, + { MIXSRC_SPACEMOUSE_F, "SPACEMOUSE_F" }, + { MIXSRC_MIN, "MIN" }, + { MIXSRC_MAX, "MAX" }, + { MIXSRC_TX_VOLTAGE, "TX_VOLTAGE" }, + { MIXSRC_TX_TIME, "TX_TIME" }, + { MIXSRC_TX_GPS, "TX_GPS" }, + { 0, NULL } +}; +const struct YamlIdStr enum_LogicalSwitchesFunctions[] = { + { LS_FUNC_NONE, "FUNC_NONE" }, + { LS_FUNC_VEQUAL, "FUNC_VEQUAL" }, + { LS_FUNC_VALMOSTEQUAL, "FUNC_VALMOSTEQUAL" }, + { LS_FUNC_VPOS, "FUNC_VPOS" }, + { LS_FUNC_VNEG, "FUNC_VNEG" }, + { LS_FUNC_APOS, "FUNC_APOS" }, + { LS_FUNC_ANEG, "FUNC_ANEG" }, + { LS_FUNC_AND, "FUNC_AND" }, + { LS_FUNC_OR, "FUNC_OR" }, + { LS_FUNC_XOR, "FUNC_XOR" }, + { LS_FUNC_EDGE, "FUNC_EDGE" }, + { LS_FUNC_EQUAL, "FUNC_EQUAL" }, + { LS_FUNC_GREATER, "FUNC_GREATER" }, + { LS_FUNC_LESS, "FUNC_LESS" }, + { LS_FUNC_DIFFEGREATER, "FUNC_DIFFEGREATER" }, + { LS_FUNC_ADIFFEGREATER, "FUNC_ADIFFEGREATER" }, + { LS_FUNC_TIMER, "FUNC_TIMER" }, + { LS_FUNC_STICKY, "FUNC_STICKY" }, + { 0, NULL } +}; +const struct YamlIdStr enum_SwashType[] = { + { SWASH_TYPE_NONE, "TYPE_NONE" }, + { SWASH_TYPE_120, "TYPE_120" }, + { SWASH_TYPE_120X, "TYPE_120X" }, + { SWASH_TYPE_140, "TYPE_140" }, + { SWASH_TYPE_90, "TYPE_90" }, + { 0, NULL } +}; +const struct YamlIdStr enum_SwitchSources[] = { + { SWSRC_NONE, "NONE" }, + { SWSRC_ON, "ON" }, + { SWSRC_ONE, "ONE" }, + { SWSRC_TELEMETRY_STREAMING, "TELEMETRY_STREAMING" }, + { SWSRC_RADIO_ACTIVITY, "RADIO_ACTIVITY" }, + { SWSRC_TRAINER_CONNECTED, "TRAINER_CONNECTED" }, + { SWSRC_OFF, "OFF" }, + { 0, NULL } +}; +const struct YamlIdStr enum_PotsWarnMode[] = { + { POTS_WARN_OFF, "WARN_OFF" }, + { POTS_WARN_MANUAL, "WARN_MANUAL" }, + { POTS_WARN_AUTO, "WARN_AUTO" }, + { 0, NULL } +}; +const struct YamlIdStr enum_ModelOverridableEnable[] = { + { OVERRIDE_GLOBAL, "GLOBAL" }, + { OVERRIDE_OFF, "OFF" }, + { OVERRIDE_ON, "ON" }, + { 0, NULL } +}; +const struct YamlIdStr enum_FailsafeModes[] = { + { FAILSAFE_NOT_SET, "NOT_SET" }, + { FAILSAFE_HOLD, "HOLD" }, + { FAILSAFE_CUSTOM, "CUSTOM" }, + { FAILSAFE_NOPULSES, "NOPULSES" }, + { FAILSAFE_RECEIVER, "RECEIVER" }, + { 0, NULL } +}; +const struct YamlIdStr enum_TelemetrySensorFormula[] = { + { TELEM_FORMULA_ADD, "FORMULA_ADD" }, + { TELEM_FORMULA_AVERAGE, "FORMULA_AVERAGE" }, + { TELEM_FORMULA_MIN, "FORMULA_MIN" }, + { TELEM_FORMULA_MAX, "FORMULA_MAX" }, + { TELEM_FORMULA_MULTIPLY, "FORMULA_MULTIPLY" }, + { TELEM_FORMULA_TOTALIZE, "FORMULA_TOTALIZE" }, + { TELEM_FORMULA_CELL, "FORMULA_CELL" }, + { TELEM_FORMULA_CONSUMPTION, "FORMULA_CONSUMPTION" }, + { TELEM_FORMULA_DIST, "FORMULA_DIST" }, + { 0, NULL } +}; +const struct YamlIdStr enum_TelemetrySensorType[] = { + { TELEM_TYPE_CUSTOM, "TYPE_CUSTOM" }, + { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" }, + { 0, NULL } +}; +const struct YamlIdStr enum_USBJoystickIfMode[] = { + { USBJOYS_JOYSTICK, "JOYSTICK" }, + { USBJOYS_GAMEPAD, "GAMEPAD" }, + { USBJOYS_MULTIAXIS, "MULTIAXIS" }, + { 0, NULL } +}; +const struct YamlIdStr enum_USBJoystickCh[] = { + { USBJOYS_CH_NONE, "CH_NONE" }, + { USBJOYS_CH_BUTTON, "CH_BUTTON" }, + { USBJOYS_CH_AXIS, "CH_AXIS" }, + { USBJOYS_CH_SIM, "CH_SIM" }, + { 0, NULL } +}; + +// +// Structs last +// + +static const struct YamlNode struct_CalibData[] = { + YAML_IDX_CUST("calib",r_calib,w_calib), + YAML_SIGNED( "mid", 16 ), + YAML_SIGNED( "spanNeg", 16 ), + YAML_SIGNED( "spanPos", 16 ), + YAML_END +}; +static const struct YamlNode struct_signed_16[] = { + YAML_IDX, + YAML_SIGNED( "val", 16 ), + YAML_END +}; +static const struct YamlNode struct_TrainerMix[] = { + YAML_IDX, + YAML_UNSIGNED( "srcChn", 6 ), + YAML_ENUM("mode", 2, enum_TrainerMultiplex, NULL), + YAML_SIGNED( "studWeight", 8 ), + YAML_END +}; +static const struct YamlNode struct_TrainerData[] = { + YAML_ARRAY("calib", 16, 4, struct_signed_16, NULL), + YAML_ARRAY("mix", 16, 4, struct_TrainerMix, NULL), + YAML_END +}; +static const struct YamlNode struct_anonymous_1[] = { + YAML_STRING("name", 8), + YAML_END +}; +static const struct YamlNode struct_anonymous_2[] = { + YAML_SIGNED( "val", 16 ), + YAML_UNSIGNED( "mode", 8 ), + YAML_UNSIGNED( "param", 8 ), + YAML_SIGNED( "val2", 32 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_3[] = { + YAML_SIGNED( "val1", 32 ), + YAML_SIGNED( "val2", 32 ), + YAML_END +}; +static const struct YamlNode union_anonymous_0_elmts[] = { + YAML_STRUCT("play", 64, struct_anonymous_1, NULL), + YAML_STRUCT("all", 64, struct_anonymous_2, NULL), + YAML_STRUCT("clear", 64, struct_anonymous_3, NULL), + YAML_END +}; +static const struct YamlNode struct_CustomFunctionData[] = { + YAML_IDX, + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), + YAML_ENUM("func", 6, enum_Functions, NULL), + YAML_CUSTOM("def",r_customFn,w_customFn), + YAML_PADDING( 64 ), + YAML_PADDING( 1 ), + YAML_PADDING( 7 ), + YAML_END +}; +static const struct YamlNode struct_switchDef[] = { + YAML_IDX_CUST("sw",sw_idx_read,sw_idx_write), + YAML_STRING("name", 3), + YAML_ENUM("type", 3, enum_SwitchConfig, NULL), + YAML_PADDING( 5 ), + YAML_END +}; +static const struct YamlNode struct_KeyShortcut[] = { + YAML_IDX, + YAML_CUSTOM("shortcut",r_keyShortcut,w_keyShortcut), + YAML_PADDING( 8 ), + YAML_END +}; +static const struct YamlNode struct_QMFavorite[] = { + YAML_IDX, + YAML_CUSTOM("shortcut",r_qmFavorite,w_qmFavorite), + YAML_PADDING( 8 ), + YAML_END +}; +static const struct YamlNode struct_RadioData[] = { + YAML_UNSIGNED( "manuallyEdited", 1 ), + YAML_SIGNED( "timezoneMinutes", 3 ), + YAML_UNSIGNED( "ppmunit", 2 ), + YAML_PADDING( 2 ), + YAML_CUSTOM("semver",nullptr,w_semver), + YAML_CUSTOM("board",nullptr,w_board), + YAML_ARRAY("calib", 48, 20, struct_CalibData, NULL), + YAML_PADDING( 16 ), + YAML_UNSIGNED( "vBatWarn", 8 ), + YAML_SIGNED( "txVoltageCalibration", 8 ), + YAML_ENUM("backlightMode", 3, enum_BacklightMode, NULL), + YAML_ENUM("antennaMode", 2, enum_AntennaModes, NULL), + YAML_UNSIGNED( "disableRtcWarning", 1 ), + YAML_UNSIGNED( "keysBacklight", 1 ), + YAML_UNSIGNED( "dontPlayHello", 1 ), + YAML_ENUM("internalModule", 8, enum_ModuleType, NULL), + YAML_STRUCT("trainer", 128, struct_TrainerData, NULL), + YAML_UNSIGNED( "view", 8 ), + YAML_PADDING( 2 ), + YAML_UNSIGNED( "fai", 1 ), + YAML_SIGNED_CUST( "beepMode", 2, r_beeperMode, w_beeperMode ), + YAML_UNSIGNED( "alarmsFlash", 1 ), + YAML_UNSIGNED( "disableMemoryWarning", 1 ), + YAML_UNSIGNED( "disableAlarmWarning", 1 ), + YAML_UNSIGNED( "stickMode", 2 ), + YAML_SIGNED( "timezone", 5 ), + YAML_UNSIGNED( "adjustRTC", 1 ), + YAML_UNSIGNED( "inactivityTimer", 8 ), + YAML_CUSTOM("telemetryBaudrate",r_telemetryBaudrate,nullptr), + YAML_UNSIGNED( "internalModuleBaudrate", 3 ), + YAML_SIGNED( "splashMode", 3 ), + YAML_SIGNED_CUST( "hapticMode", 2, r_beeperMode, w_beeperMode ), + YAML_SIGNED( "switchesDelay", 8 ), + YAML_UNSIGNED( "lightAutoOff", 8 ), + YAML_UNSIGNED( "templateSetup", 8 ), + YAML_SIGNED( "PPM_Multiplier", 8 ), + YAML_SIGNED_CUST( "hapticLength", 8, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "beepLength", 3, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "hapticStrength", 3, r_5pos, w_5pos ), + YAML_UNSIGNED( "gpsFormat", 1 ), + YAML_UNSIGNED( "audioMuteEnable", 1 ), + YAML_UNSIGNED_CUST( "speakerPitch", 8, r_spPitch, w_spPitch ), + YAML_SIGNED_CUST( "speakerVolume", 8, r_vol, w_vol ), + YAML_SIGNED_CUST( "vBatMin", 8, r_vbat_min, w_vbat_min ), + YAML_SIGNED_CUST( "vBatMax", 8, r_vbat_max, w_vbat_max ), + YAML_UNSIGNED( "backlightBright", 8 ), + YAML_UNSIGNED( "globalTimer", 32 ), + YAML_UNSIGNED( "bluetoothBaudrate", 4 ), + YAML_ENUM("bluetoothMode", 4, enum_BluetoothModes, NULL), + YAML_UNSIGNED( "countryCode", 2 ), + YAML_SIGNED( "pwrOnSpeed", 3 ), + YAML_SIGNED( "pwrOffSpeed", 3 ), + YAML_CUSTOM("jitterFilter",r_jitterFilter,nullptr), + YAML_UNSIGNED( "noJitterFilter", 1 ), + YAML_UNSIGNED( "imperial", 1 ), + YAML_UNSIGNED( "disableRssiPoweroffAlarm", 1 ), + YAML_UNSIGNED( "USBMode", 2 ), + YAML_UNSIGNED( "jackMode", 2 ), + YAML_PADDING( 1 ), + YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), + YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "backgroundVolume", 4, r_5pos, w_5pos ), + YAML_SIGNED_CUST( "varioPitch", 8, r_vPitch, w_vPitch ), + YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ), + YAML_SIGNED( "varioRepeat", 8 ), + YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active), + YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr), + YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr), + YAML_ARRAY("serialPort", 8, 4, struct_serialConfig, nullptr), + YAML_ARRAY("sticksConfig", 0, MAX_STICKS, struct_stickConfig, stick_name_valid), + YAML_ARRAY("slidersConfig", 0, MAX_POTS, struct_sliderConfig, nullptr), + YAML_PADDING( 8 ), + YAML_ARRAY("potsConfig", 4, 16, struct_potConfig, nullptr), + YAML_ARRAY("switchConfig", 32, 20, struct_switchDef, switchIsActive), + YAML_ARRAY("flexSwitches", 0, MAX_FLEX_SWITCHES, struct_flexSwitch, flex_sw_valid), + YAML_STRING("currModelFilename", 17), + YAML_UNSIGNED( "blOffBright", 8 ), + YAML_STRING("bluetoothName", 10), + YAML_STRING("ownerRegistrationID", 8), + YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr), + YAML_UNSIGNED( "rotEncMode", 3 ), + YAML_PADDING( 2 ), + YAML_UNSIGNED( "stickDeadZone", 3 ), + YAML_SIGNED( "imuMax", 8 ), + YAML_SIGNED( "imuOffset", 8 ), + YAML_UNSIGNED( "imuInvert", 8 ), + YAML_STRING("selectedTheme", 26), + YAML_SIGNED_CUST( "backlightSrc", 10, r_mixSrcRawEx, w_mixSrcRawEx ), + YAML_SIGNED( "radioGFDisabled", 1 ), + YAML_SIGNED( "radioTrainerDisabled", 1 ), + YAML_SIGNED( "modelHeliDisabled", 1 ), + YAML_SIGNED( "modelFMDisabled", 1 ), + YAML_SIGNED( "modelCurvesDisabled", 1 ), + YAML_SIGNED( "modelGVDisabled", 1 ), + YAML_SIGNED_CUST( "volumeSrc", 10, r_mixSrcRawEx, w_mixSrcRawEx ), + YAML_SIGNED( "modelLSDisabled", 1 ), + YAML_SIGNED( "modelSFDisabled", 1 ), + YAML_SIGNED( "modelCustomScriptsDisabled", 1 ), + YAML_SIGNED( "modelTelemetryDisabled", 1 ), + YAML_SIGNED( "disableTrainerPoweroffAlarm", 1 ), + YAML_SIGNED( "disablePwrOnOffHaptic", 1 ), + YAML_UNSIGNED( "modelQuickSelect", 1 ), + YAML_UNSIGNED( "labelSingleSelect", 1 ), + YAML_UNSIGNED( "labelMultiMode", 1 ), + YAML_UNSIGNED( "favMultiMode", 1 ), + YAML_UNSIGNED( "modelSelectLayout", 2 ), + YAML_UNSIGNED( "radioThemesDisabled", 1 ), + YAML_UNSIGNED( "oneLogPerDay", 1 ), + YAML_UNSIGNED( "pwrOffIfInactive", 8 ), + YAML_ARRAY("keyShortcuts", 8, 6, struct_KeyShortcut, NULL), + YAML_ARRAY("qmFavorites", 8, 12, struct_QMFavorite, NULL), + YAML_END +}; +static const struct YamlNode struct_unsigned_8[] = { + YAML_IDX, + YAML_UNSIGNED( "val", 8 ), + YAML_END +}; +static const struct YamlNode struct_ModelHeader[] = { + YAML_STRING("name", 15), + YAML_ARRAY("modelId", 8, 2, struct_unsigned_8, NULL), + YAML_STRING("bitmap", 14), + YAML_STRING("labels", 100), + YAML_END +}; +static const struct YamlNode struct_TimerData[] = { + YAML_IDX, + YAML_UNSIGNED( "start", 22 ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), + YAML_SIGNED( "value", 22 ), + YAML_ENUM("mode", 3, enum_TimerModes, NULL), + YAML_UNSIGNED( "countdownBeep", 2 ), + YAML_UNSIGNED( "minuteBeep", 1 ), + YAML_UNSIGNED( "persistent", 2 ), + YAML_SIGNED( "countdownStart", 2 ), + YAML_UNSIGNED( "showElapsed", 1 ), + YAML_UNSIGNED( "extraHaptic", 1 ), + YAML_PADDING( 6 ), + YAML_STRING("name", 8), + YAML_END +}; +static const struct YamlNode struct_CurveRef[] = { + YAML_UNSIGNED( "type", 5 ), + YAML_UNSIGNED_CUST( "value", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_END +}; +static const struct YamlNode struct_MixData[] = { + YAML_UNSIGNED( "destCh", 5 ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), + YAML_UNSIGNED( "carryTrim", 1 ), + YAML_UNSIGNED( "mixWarn", 2 ), + YAML_ENUM("mltpx", 2, enum_MixerMultiplex, NULL), + YAML_UNSIGNED( "delayPrec", 1 ), + YAML_UNSIGNED( "speedPrec", 1 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_PADDING( 1 ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), + YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "delayUp", 8 ), + YAML_UNSIGNED( "delayDown", 8 ), + YAML_UNSIGNED( "speedUp", 8 ), + YAML_UNSIGNED( "speedDown", 8 ), + YAML_STRING("name", 6), + YAML_END +}; +static const struct YamlNode struct_LimitData[] = { + YAML_IDX, + YAML_SIGNED_CUST( "min", 11, in_read_weight, in_write_weight ), + YAML_SIGNED_CUST( "max", 11, in_read_weight, in_write_weight ), + YAML_SIGNED( "ppmCenter", 10 ), + YAML_SIGNED_CUST( "offset", 11, in_read_weight, in_write_weight ), + YAML_UNSIGNED( "symetrical", 1 ), + YAML_UNSIGNED( "revert", 1 ), + YAML_PADDING( 3 ), + YAML_SIGNED( "curve", 8 ), + YAML_STRING("name", 6), + YAML_END +}; +static const struct YamlNode struct_ExpoData[] = { + YAML_UNSIGNED( "mode", 2 ), + YAML_UNSIGNED( "scale", 14 ), + YAML_CUSTOM("carryTrim",r_carryTrim,nullptr), + YAML_SIGNED( "trimSource", 6 ), + YAML_SIGNED_CUST( "srcRaw", 10, r_mixSrcRawEx, w_mixSrcRawEx ), + YAML_UNSIGNED_CUST( "weight", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_UNSIGNED_CUST( "offset", 11, r_sourceNumVal, w_sourceNumVal ), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), + YAML_STRUCT("curve", 16, struct_CurveRef, NULL), + YAML_UNSIGNED( "chn", 5 ), + YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ), + YAML_PADDING( 2 ), + YAML_STRING("name", 6), + YAML_END +}; +static const struct YamlNode struct_CurveHeader[] = { + YAML_IDX, + YAML_UNSIGNED( "type", 1 ), + YAML_UNSIGNED( "smooth", 1 ), + YAML_SIGNED( "points", 6 ), + YAML_STRING("name", 3), + YAML_END +}; +static const struct YamlNode struct_signed_8[] = { + YAML_IDX, + YAML_SIGNED( "val", 8 ), + YAML_END +}; +static const struct YamlNode struct_LogicalSwitchData[] = { + YAML_IDX, + YAML_ENUM("func", 8, enum_LogicalSwitchesFunctions, NULL), + YAML_CUSTOM("def",r_logicSw,w_logicSw), + YAML_PADDING( 10 ), + YAML_PADDING( 10 ), + YAML_SIGNED_CUST( "andsw", 10, r_swtchSrc, w_swtchSrc ), + YAML_UNSIGNED( "lsPersist", 1 ), + YAML_UNSIGNED( "lsState", 1 ), + YAML_PADDING( 16 ), + YAML_UNSIGNED( "delay", 8 ), + YAML_UNSIGNED( "duration", 8 ), + YAML_END +}; +static const struct YamlNode struct_SwashRingData[] = { + YAML_ENUM("type", 8, enum_SwashType, NULL), + YAML_UNSIGNED( "value", 8 ), + YAML_UNSIGNED_CUST( "collectiveSource", 8, r_mixSrcRaw, w_mixSrcRaw ), + YAML_UNSIGNED_CUST( "aileronSource", 8, r_mixSrcRaw, w_mixSrcRaw ), + YAML_UNSIGNED_CUST( "elevatorSource", 8, r_mixSrcRaw, w_mixSrcRaw ), + YAML_SIGNED( "collectiveWeight", 8 ), + YAML_SIGNED( "aileronWeight", 8 ), + YAML_SIGNED( "elevatorWeight", 8 ), + YAML_END +}; +static const struct YamlNode struct_trim_t[] = { + YAML_IDX, + YAML_SIGNED( "value", 11 ), + YAML_UNSIGNED( "mode", 5 ), + YAML_END +}; +static const struct YamlNode struct_FlightModeData[] = { + YAML_IDX, + YAML_ARRAY("trim", 16, 8, struct_trim_t, NULL), + YAML_STRING("name", 10), + YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ), + YAML_PADDING( 6 ), + YAML_UNSIGNED( "fadeIn", 8 ), + YAML_UNSIGNED( "fadeOut", 8 ), + YAML_ARRAY("gvars", 16, 15, struct_signed_16, gvar_is_active), + YAML_END +}; +static const struct YamlNode struct_GVarData[] = { + YAML_IDX, + YAML_STRING("name", 3), + YAML_UNSIGNED( "min", 12 ), + YAML_UNSIGNED( "max", 12 ), + YAML_UNSIGNED( "popup", 1 ), + YAML_UNSIGNED( "prec", 1 ), + YAML_UNSIGNED( "unit", 2 ), + YAML_PADDING( 4 ), + YAML_END +}; +static const struct YamlNode struct_VarioData[] = { + YAML_UNSIGNED_CUST( "source", 7, r_tele_sensor, w_tele_sensor ), + YAML_UNSIGNED( "centerSilent", 1 ), + YAML_SIGNED( "centerMax", 8 ), + YAML_SIGNED( "centerMin", 8 ), + YAML_SIGNED( "min", 8 ), + YAML_SIGNED( "max", 8 ), + YAML_END +}; +static const struct YamlNode struct_RssiAlarmData[] = { + YAML_CUSTOM("disabled",r_rssiDisabled,nullptr), + YAML_CUSTOM("warning",r_rssiWarning,nullptr), + YAML_CUSTOM("critical",r_rssiCritical,nullptr), + YAML_END +}; +static const struct YamlNode struct_RFAlarmData[] = { + YAML_SIGNED( "warning", 8 ), + YAML_SIGNED( "critical", 8 ), + YAML_END +}; +static const struct YamlNode struct_PpmModule[] = { + YAML_SIGNED( "delay", 6 ), + YAML_UNSIGNED( "pulsePol", 1 ), + YAML_UNSIGNED( "outputType", 1 ), + YAML_SIGNED( "frameLength", 8 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_5[] = { + YAML_PADDING( 8 ), + YAML_UNSIGNED( "disableTelemetry", 1 ), + YAML_UNSIGNED( "disableMapping", 1 ), + YAML_UNSIGNED( "autoBindMode", 1 ), + YAML_UNSIGNED( "lowPowerMode", 1 ), + YAML_UNSIGNED( "receiverTelemetryOff", 1 ), + YAML_UNSIGNED( "receiverHigherChannels", 1 ), + YAML_PADDING( 2 ), + YAML_SIGNED( "optionValue", 8 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_6[] = { + YAML_UNSIGNED( "power", 2 ), + YAML_PADDING( 2 ), + YAML_UNSIGNED( "receiverTelemetryOff", 1 ), + YAML_UNSIGNED( "receiverHigherChannels", 1 ), + YAML_SIGNED( "antennaMode", 2 ), + YAML_PADDING( 8 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_7[] = { + YAML_PADDING( 6 ), + YAML_UNSIGNED( "noninverted", 1 ), + YAML_PADDING( 1 ), + YAML_SIGNED( "refreshRate", 8 ), + YAML_END +}; +static const struct YamlNode struct_string_64[] = { + YAML_IDX, + YAML_STRING("val", 8), + YAML_END +}; +static const struct YamlNode struct_anonymous_8[] = { + YAML_UNSIGNED( "receivers", 7 ), + YAML_UNSIGNED( "racingMode", 1 ), + YAML_ARRAY("receiverName", 64, 3, struct_string_64, NULL), + YAML_END +}; +static const struct YamlNode struct_anonymous_9[] = { + YAML_ARRAY("rx_id", 8, 4, struct_unsigned_8, NULL), + YAML_UNSIGNED( "mode", 3 ), + YAML_UNSIGNED( "rfPower", 1 ), + YAML_UNSIGNED( "reserved", 4 ), + YAML_ARRAY("rx_freq", 8, 2, struct_unsigned_8, NULL), + YAML_END +}; +static const struct YamlNode struct_anonymous_10[] = { + YAML_UNSIGNED( "emi", 2 ), + YAML_UNSIGNED( "telemetry", 1 ), + YAML_UNSIGNED( "phyMode", 3 ), + YAML_UNSIGNED( "reserved", 2 ), + YAML_UNSIGNED( "rfPower", 8 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_11[] = { + YAML_UNSIGNED( "raw12bits", 1 ), + YAML_UNSIGNED( "telemetryBaudrate", 3 ), + YAML_PADDING( 4 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_12[] = { + YAML_UNSIGNED( "telemetryBaudrate", 3 ), + YAML_UNSIGNED( "crsfArmingMode", 1 ), + YAML_PADDING( 4 ), + YAML_SIGNED_CUST( "crsfArmingTrigger", 10, r_swtchSrc, w_swtchSrc ), + YAML_SIGNED( "spare3", 6 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_13[] = { + YAML_UNSIGNED( "flags", 8 ), + YAML_UNSIGNED( "enableAETR", 1 ), + YAML_END +}; +static const struct YamlNode union_anonymous_4_elmts[] = { + YAML_ARRAY("raw", 8, 25, struct_unsigned_8, NULL), + YAML_STRUCT("ppm", 16, struct_PpmModule, NULL), + YAML_STRUCT("multi", 24, struct_anonymous_5, NULL), + YAML_STRUCT("pxx", 16, struct_anonymous_6, NULL), + YAML_STRUCT("sbus", 16, struct_anonymous_7, NULL), + YAML_STRUCT("pxx2", 200, struct_anonymous_8, NULL), + YAML_STRUCT("flysky", 56, struct_anonymous_9, NULL), + YAML_STRUCT("afhds3", 16, struct_anonymous_10, NULL), + YAML_STRUCT("ghost", 8, struct_anonymous_11, NULL), + YAML_STRUCT("crsf", 24, struct_anonymous_12, NULL), + YAML_STRUCT("dsmp", 16, struct_anonymous_13, NULL), + YAML_END +}; +static const struct YamlNode struct_ModuleData[] = { + YAML_IDX, + YAML_UNSIGNED_CUST( "type", 8, r_moduleType, w_moduleType ), + YAML_CUSTOM("subType",r_modSubtype,w_modSubtype), + YAML_UNSIGNED( "channelsStart", 8 ), + YAML_SIGNED_CUST( "channelsCount", 8, r_channelsCount, w_channelsCount ), + YAML_ENUM("failsafeMode", 4, enum_FailsafeModes, NULL), + YAML_PADDING( 4 ), + YAML_UNION("mod", 200, union_anonymous_4_elmts, select_mod_type), + YAML_END +}; +static const struct YamlNode struct_TrainerModuleData[] = { + YAML_UNSIGNED_CUST( "mode", 8, r_trainerMode, w_trainerMode ), + YAML_UNSIGNED( "channelsStart", 8 ), + YAML_SIGNED( "channelsCount", 8 ), + YAML_SIGNED( "frameLength", 8 ), + YAML_SIGNED( "delay", 6 ), + YAML_UNSIGNED( "pulsePol", 1 ), + YAML_PADDING( 1 ), + YAML_END +}; +static const struct YamlNode union_ScriptDataInput_elmts[] = { + YAML_SIGNED( "value", 16 ), + YAML_UNSIGNED_CUST( "source", 16, r_mixSrcRaw, w_mixSrcRaw ), + YAML_END +}; +static const struct YamlNode union_ScriptDataInput[] = { + YAML_IDX, + YAML_UNION("u", 16, union_ScriptDataInput_elmts, select_script_input), + YAML_END +}; +static const struct YamlNode struct_ScriptData[] = { + YAML_IDX, + YAML_STRING("file", 6), + YAML_STRING("name", 6), + YAML_ARRAY("inputs", 16, 6, union_ScriptDataInput, NULL), + YAML_END +}; +static const struct YamlNode struct_string_32[] = { + YAML_IDX, + YAML_STRING("val", 4), + YAML_END +}; +static const struct YamlNode union_anonymous_14_elmts[] = { + YAML_UNSIGNED( "id", 16 ), + YAML_UNSIGNED( "persistentValue", 16 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_16[] = { + YAML_UNSIGNED( "physID", 5 ), + YAML_UNSIGNED( "rxIndex", 3 ), + YAML_END +}; +static const struct YamlNode union_anonymous_15_elmts[] = { + YAML_STRUCT("frskyInstance", 8, struct_anonymous_16, NULL), + YAML_UNSIGNED( "instance", 8 ), + YAML_ENUM("formula", 8, enum_TelemetrySensorFormula, NULL), + YAML_END +}; +static const struct YamlNode struct_anonymous_18[] = { + YAML_UNSIGNED( "ratio", 16 ), + YAML_SIGNED( "offset", 16 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_19[] = { + YAML_UNSIGNED( "source", 8 ), + YAML_UNSIGNED( "index", 8 ), + YAML_PADDING( 16 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_20[] = { + YAML_ARRAY("sources", 8, 4, struct_signed_8, NULL), + YAML_END +}; +static const struct YamlNode struct_anonymous_21[] = { + YAML_UNSIGNED( "source", 8 ), + YAML_PADDING( 24 ), + YAML_END +}; +static const struct YamlNode struct_anonymous_22[] = { + YAML_UNSIGNED( "gps", 8 ), + YAML_UNSIGNED( "alt", 8 ), + YAML_PADDING( 16 ), + YAML_END +}; +static const struct YamlNode union_anonymous_17_elmts[] = { + YAML_STRUCT("custom", 32, struct_anonymous_18, NULL), + YAML_STRUCT("cell", 32, struct_anonymous_19, NULL), + YAML_STRUCT("calc", 32, struct_anonymous_20, NULL), + YAML_STRUCT("consumption", 32, struct_anonymous_21, NULL), + YAML_STRUCT("dist", 32, struct_anonymous_22, NULL), + YAML_UNSIGNED( "param", 32 ), + YAML_END +}; +static const struct YamlNode struct_TelemetrySensor[] = { + YAML_IDX, + YAML_UNION("id1", 16, union_anonymous_14_elmts, select_id1), + YAML_UNION("id2", 8, union_anonymous_15_elmts, select_id2), + YAML_STRING("label", 4), + YAML_UNSIGNED( "subId", 8 ), + YAML_ENUM("type", 1, enum_TelemetrySensorType, NULL), + YAML_PADDING( 1 ), + YAML_UNSIGNED( "unit", 6 ), + YAML_UNSIGNED( "prec", 2 ), + YAML_UNSIGNED( "autoOffset", 1 ), + YAML_UNSIGNED( "filter", 1 ), + YAML_UNSIGNED( "logs", 1 ), + YAML_UNSIGNED( "persistent", 1 ), + YAML_UNSIGNED( "onlyPositive", 1 ), + YAML_PADDING( 1 ), + YAML_UNION("cfg", 32, union_anonymous_17_elmts, select_sensor_cfg), + YAML_END +}; +static const struct YamlNode union_WidgetOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("signedValue",r_wov_signed,w_wov_signed), + YAML_CUSTOM("boolValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("stringValue",r_wov_string,w_wov_string), + YAML_CUSTOM("source",r_wov_source,w_wov_source), + YAML_CUSTOM("color",r_wov_color,w_wov_color), + YAML_END +}; +static const struct YamlNode struct_WidgetOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_wov_type,w_wov_type), + YAML_UNION("value", 0, union_WidgetOptionValue_elmts, select_wov), + YAML_END +}; +static const struct YamlNode struct_WidgetPersistentData[] = { + YAML_ARRAY("options", 0, 50, struct_WidgetOptionValueTyped, widget_option_is_active), + YAML_END +}; +static const struct YamlNode struct_ZonePersistentData[] = { + YAML_IDX, + YAML_CUSTOM("widgetName",r_widget_name,w_widget_name), + YAML_STRUCT("widgetData", 0, struct_WidgetPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode union_LayoutOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("boolValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("color",r_lov_color,w_lov_color), + YAML_END +}; +static const struct YamlNode struct_LayoutOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_lov_type,w_lov_type), + YAML_UNION("value", 0, union_LayoutOptionValue_elmts, select_lov), + YAML_END +}; +static const struct YamlNode struct_LayoutPersistentData[] = { + YAML_ARRAY("zones", 0, 10, struct_ZonePersistentData, widget_is_active), + YAML_ARRAY("options", 0, 10, struct_LayoutOptionValueTyped, layout_option_is_active), + YAML_END +}; +static const struct YamlNode struct_CustomScreenData[] = { + YAML_IDX, + YAML_CUSTOM("LayoutId",r_screen_id,w_screen_id), + YAML_STRUCT("layoutData", 0, struct_LayoutPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode struct_TopBarPersistentData[] = { + YAML_ARRAY("zones", 0, 6, struct_ZonePersistentData, widget_is_active), + YAML_END +}; +static const struct YamlNode struct_USBJoystickChData[] = { + YAML_IDX, + YAML_ENUM("mode", 3, enum_USBJoystickCh, NULL), + YAML_UNSIGNED( "inversion", 1 ), + YAML_UNSIGNED( "param", 4 ), + YAML_UNSIGNED( "btn_num", 5 ), + YAML_UNSIGNED( "switch_npos", 3 ), + YAML_END +}; +static const struct YamlNode struct_ModelData[] = { + YAML_CUSTOM("semver",nullptr,w_semver), + YAML_STRUCT("header", 1048, struct_ModelHeader, NULL), + YAML_ARRAY("timers", 136, 3, struct_TimerData, NULL), + YAML_UNSIGNED( "telemetryProtocol", 3 ), + YAML_UNSIGNED( "thrTrim", 1 ), + YAML_UNSIGNED( "noGlobalFunctions", 1 ), + YAML_UNSIGNED( "displayTrims", 2 ), + YAML_UNSIGNED( "ignoreSensorIds", 1 ), + YAML_SIGNED( "trimInc", 3 ), + YAML_UNSIGNED( "disableThrottleWarning", 1 ), + YAML_UNSIGNED( "displayChecklist", 1 ), + YAML_UNSIGNED( "extendedLimits", 1 ), + YAML_UNSIGNED( "extendedTrims", 1 ), + YAML_UNSIGNED( "throttleReversed", 1 ), + YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ), + YAML_UNSIGNED( "disableTelemetryWarning", 1 ), + YAML_UNSIGNED( "showInstanceIds", 1 ), + YAML_UNSIGNED( "checklistInteractive", 1 ), + YAML_PADDING( 4 ), + YAML_SIGNED( "customThrottleWarningPosition", 8 ), + YAML_UNSIGNED( "beepANACenter", 16 ), + YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL), + YAML_ARRAY("limitData", 104, 32, struct_LimitData, NULL), + YAML_ARRAY("expoData", 144, 64, struct_ExpoData, NULL), + YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL), + YAML_ARRAY("points", 8, 512, struct_signed_8, NULL), + YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL), + YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active), + YAML_STRUCT("swashR", 64, struct_SwashRingData, swash_is_active), + YAML_ARRAY("flightModeData", 480, 9, struct_FlightModeData, fmd_is_active), + YAML_UNSIGNED_CUST( "thrTraceSrc", 8, r_thrSrc, w_thrSrc ), + YAML_CUSTOM("switchWarningState",r_swtchWarn,nullptr), + YAML_ARRAY("switchWarning", 2, 32, struct_swtchWarn, nullptr), + YAML_ARRAY("gvars", 56, 15, struct_GVarData, NULL), + YAML_STRUCT("varioData", 40, struct_VarioData, NULL), + YAML_UNSIGNED_CUST( "rssiSource", 8, r_tele_sensor, w_tele_sensor ), + YAML_STRUCT("rssiAlarms", 0, struct_RssiAlarmData, NULL), + YAML_STRUCT("rfAlarms", 16, struct_RFAlarmData, NULL), + YAML_UNSIGNED( "thrTrimSw", 3 ), + YAML_ENUM("potsWarnMode", 2, enum_PotsWarnMode, NULL), + YAML_ENUM("jitterFilter", 2, enum_ModelOverridableEnable, NULL), + YAML_PADDING( 1 ), + YAML_ARRAY("moduleData", 232, 2, struct_ModuleData, NULL), + YAML_ARRAY("failsafeChannels", 16, 32, struct_signed_16, NULL), + YAML_STRUCT("trainerData", 40, struct_TrainerModuleData, NULL), + YAML_ARRAY("scriptsData", 192, 9, struct_ScriptData, NULL), + YAML_ARRAY("inputNames", 32, 32, struct_string_32, NULL), + YAML_UNSIGNED( "potsWarnEnabled", 16 ), + YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL), + YAML_ARRAY("telemetrySensors", 112, 99, struct_TelemetrySensor, NULL), + YAML_ARRAY("screenData", 0, 10, struct_CustomScreenData, screen_is_active), + YAML_STRUCT("topbarData", 0, struct_TopBarPersistentData, isAlwaysActive), + YAML_ARRAY("topbarWidgetWidth", 8, 6, struct_unsigned_8, NULL), + YAML_UNSIGNED( "view", 8 ), + YAML_STRING("modelRegistrationID", 8), + YAML_UNSIGNED( "usbJoystickExtMode", 1 ), + YAML_ENUM("usbJoystickIfMode", 3, enum_USBJoystickIfMode, NULL), + YAML_UNSIGNED( "usbJoystickCircularCut", 4 ), + YAML_ARRAY("usbJoystickCh", 16, 26, struct_USBJoystickChData, NULL), + YAML_ENUM("radioThemesDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("radioGFDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("radioTrainerDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelHeliDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelFMDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelCurvesDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelGVDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelLSDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelSFDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelCustomScriptsDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_ENUM("modelTelemetryDisabled", 2, enum_ModelOverridableEnable, NULL), + YAML_END +}; +static const struct YamlNode struct_PartialModel[] = { + YAML_STRUCT("header", 1048, struct_ModelHeader, NULL), + YAML_ARRAY("timers", 136, 3, struct_TimerData, NULL), + YAML_END +}; + +#define MAX_RADIODATA_MODELDATA_PARTIALMODEL_STR_LEN 29 + +static const struct YamlNode __RadioData_root_node = YAML_ROOT( struct_RadioData ); + +const YamlNode* get_radiodata_nodes() +{ + return &__RadioData_root_node; +} +static const struct YamlNode __ModelData_root_node = YAML_ROOT( struct_ModelData ); + +const YamlNode* get_modeldata_nodes() +{ + return &__ModelData_root_node; +} +static const struct YamlNode __PartialModel_root_node = YAML_ROOT( struct_PartialModel ); + +const YamlNode* get_partialmodel_nodes() +{ + return &__PartialModel_root_node; +} + diff --git a/radio/src/targets/c14/CMakeLists.txt b/radio/src/targets/c14/CMakeLists.txt new file mode 100644 index 000000000..293577c9a --- /dev/null +++ b/radio/src/targets/c14/CMakeLists.txt @@ -0,0 +1,203 @@ +option(UNEXPECTED_SHUTDOWN "Enable the Unexpected Shutdown screen" ON) +option(PXX1 "PXX1 protocol support" ON) +option(PXX2 "PXX2 protocol support" OFF) +option(AFHDS3 "AFHDS3 TX Module" ON) +option(MULTIMODULE "DIY Multiprotocol TX Module (https://github.com/pascallanger/DIY-Multiprotocol-TX-Module)" ON) +option(GHOST "Ghost TX Module" ON) +option(LUA_MIXER "Enable LUA mixer/model scripts support" ON) +option(DISK_CACHE "Enable SD card disk cache" ON) +option(STICK_DEAD_ZONE "Enable sticks dead zone" YES) + +# defines existing internal modules +set(INTERNAL_MODULES CRSF CACHE STRING "Internal modules") +set(DEFAULT_INTERNAL_MODULE CROSSFIRE CACHE STRING "Default internal module") + +set(FIRMWARE_QSPI YES) +set(FIRMWARE_FORMAT_UF2 YES) +set(PWR_BUTTON "MANAGED" CACHE STRING "Pwr button type (PRESS/SWITCH/MANAGED)") +set(CPU_TYPE STM32H7) +set(HSE_VALUE 8000000) +set(SDCARD YES) +set(STORAGE_MODELSLIST YES) +set(HAPTIC YES) +set(GUI_DIR colorlcd) +set(BITMAPS_DIR 480x272) +set(TARGET_DIR c14) +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(FUNCTION_SWITCHES NO) +set(RGB_LEDS YES) +set(ROTARY_ENCODER YES) +set(MODULE_SIZE_SML YES) + +# IMU support +set(IMU ON) +add_definitions(-DIMU_ICM4207C) +add_definitions(-DIMU_INVERT_TILT_X) +add_definitions(-DIMU_INVERT_TILT_Y) +add_definitions(-DIMU_SWAP_TILT_XY) + +# for size report script +set(CPU_TYPE_FULL STM32H750xB) +set(TARGET_LINKER_DIR stm32h750_sdram) +set(TARGET_EXTRAM_START 0xC0000000) + +set(SIZE_TARGET_MEM_DEFINE "MEM_SIZE_SDRAM1=8192") +set(FIRMWARE_STRIP_BOOTLOADER YES) + +add_definitions(-DPCBC14 -DPCBHORUS -DPCBFLYSKY) +add_definitions(-DBATTERY_CHARGE) +add_definitions(-DUSB_CHARGER) +add_definitions(-DSTM32_SUPPORT_32BIT_TIMERS) +add_definitions(-DFIRMWARE_QSPI) +add_definitions(-DFIRMWARE_FORMAT_UF2) +add_definitions(-DUSE_CUSTOM_EXTI_IRQ) + +set(FLAVOUR c14) +add_definitions(-DRADIO_C14) + +# Defines internal modules for PL18 via UART7 +# set(INTERNAL_MODULES MULTI CACHE STRING "Internal modules") +# set(DEFAULT_INTERNAL_MODULE MULTIMODULE CACHE STRING "Default internal module") + +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 NO) + + +add_definitions( + -DSTM32H750IBTx -DSTM32H750xx + -DSDRAM -DCCMRAM + -DHARDWARE_TOUCH -DHARDWARE_KEYS -DSOFTWARE_KEYBOARD + -DWS2812_MAX_LEDS=24 +) + +set(SDRAM ON) + +add_definitions(-DAUDIO -DVOICE -DRTCLOCK -DSOFTWARE_VOLUME) +add_definitions(-DPWR_BUTTON_${PWR_BUTTON}) +if(PWR_BUTTON STREQUAL "MANAGED") + add_definitions(-DPWR_BUTTON_PRESS) +endif() + +if(INTERNAL_GPS) + add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE}) +endif() + +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(FUNCTION_SWITCHES_RGB_LEDS) + set(RGB_LEDS YES) + add_definitions(-DFUNCTION_SWITCHES_RGB_LEDS) +endif() + +if(RGB_LEDS) + add_definitions(-DRGB_LEDS) +endif() + +if(FUNCTION_SWITCHES) +add_definitions(-DFUNCTION_SWITCHES) +endif() + +# VCP CLI +set(ENABLE_SERIAL_PASSTHROUGH ON CACHE BOOL "Enable serial passthrough") +set(CLI ON CACHE BOOL "Enable CLI") + +set(TARGET_SRC_DIR targets/${TARGET_DIR}) + +set(BOARD_COMMON_SRC + ${TARGET_SRC_DIR}/board.cpp + ${TARGET_SRC_DIR}/bsp_io.cpp + ${TARGET_SRC_DIR}/key_driver.cpp + ${TARGET_SRC_DIR}/lcd_driver.cpp + ${TARGET_SRC_DIR}/backlight_driver.cpp + ${TARGET_SRC_DIR}/haptic_driver.cpp + ${TARGET_SRC_DIR}/extflash_driver.cpp + ${TARGET_SRC_DIR}/rotary_enc_simulator.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/rtc_driver.cpp + targets/common/arm/stm32/watchdog_driver.cpp + drivers/pca95xx.cpp +) + +# Bootloader board library +add_library(board_bl OBJECT EXCLUDE_FROM_ALL + ${BOARD_COMMON_SRC} + ${TARGET_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} $) + +set(CMSIS_SRC ${TARGET_SRC_DIR}/system_clock.c) + +# Firmware board library +add_library(board OBJECT EXCLUDE_FROM_ALL + ${BOARD_COMMON_SRC} + ${TARGET_SRC_DIR}/led_driver.cpp + ${TARGET_SRC_DIR}/tp_gt911.cpp + ${TARGET_SRC_DIR}/battery_driver.cpp + targets/common/arm/stm32/heartbeat_driver.cpp + drivers/icm42607C.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/audio_dac_driver.cpp + targets/common/arm/stm32/stm32_rgbleds.cpp + targets/common/arm/stm32/trainer_driver.cpp + targets/common/arm/stm32/sticks_pwm_driver.cpp +) +add_dependencies(board board_lib) +set(FIRMWARE_SRC ${FIRMWARE_SRC} $) + +include_directories(${RADIO_SRC_DIR}/fonts/colorlcd gui/${GUI_DIR} gui/${GUI_DIR}/layouts) + +if(BOOTLOADER) + set(FIRMWARE_TARGET_SRC + ${FIRMWARE_TARGET_SRC} + ../../bootloader/loadboot.cpp + ) +endif() + +set(SRC + ${SRC} + io/frsky_firmware_update.cpp + io/multi_firmware_update.cpp + ) + +if (MULTIMODULE) + add_definitions(-DMULTI_PROTOLIST) + set(SRC ${SRC} + io/multi_protolist.cpp + ) +endif() + +# Make malloc() thread-safe +add_definitions(-DTHREADSAFE_MALLOC) diff --git a/radio/src/targets/c14/backlight_driver.cpp b/radio/src/targets/c14/backlight_driver.cpp new file mode 100644 index 000000000..0c27e4b72 --- /dev/null +++ b/radio/src/targets/c14/backlight_driver.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "hal/gpio.h" +#include "stm32_gpio.h" +#include "stm32_timer.h" +#include "stm32_pulse_driver.h" + +#include "edgetx_types.h" +#include "board.h" + +#include "globals.h" +#include "lcd_driver.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 = LL_TIM_CHANNEL_CH1, + .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, 1000000); + + stm32_pulse_config_output(&_bl_timer, true, LL_TIM_OCMODE_PWM1, 0); + + LL_TIM_SetAutoReload(_bl_timer.TIMx, BACKLIGHT_LEVEL_MAX); + + LL_TIM_EnableCounter(_bl_timer.TIMx); +} + +uint8_t lastDutyCycle = 0; + +void backlightEnable(uint8_t dutyCycle) +{ + stm32_pulse_set_cmp_val(&_bl_timer, dutyCycle); + + // The panel is LTDC-only and stays initialised; re-init the controller when + // waking from a fully-off backlight. + if (dutyCycle && !lastDutyCycle) { + lcdInit(); + } + + lastDutyCycle = dutyCycle; +} + +void lcdOff() { + backlightEnable(0); +} + +void lcdOn(){ + // backlightEnable() re-inits the LTDC on the 0->nonzero transition, so no + // separate lcdInit() here (avoids a double init on wake). + backlightEnable(BACKLIGHT_LEVEL_MAX); +} + +bool boardBacklightOn; + +bool isBacklightEnabled() +{ + return boardBacklightOn; +} diff --git a/radio/src/targets/c14/battery_driver.cpp b/radio/src/targets/c14/battery_driver.cpp new file mode 100644 index 000000000..e0cebe22f --- /dev/null +++ b/radio/src/targets/c14/battery_driver.cpp @@ -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. + */ + +#include "edgetx.h" +#include "battery_driver.h" +#include "hal/usb_driver.h" + +bool usbChargerLed() +{ + return (gpio_read(UCHARGER_CHARGE_END_GPIO) ? 0 : 1) && usbPlugged(); +} diff --git a/radio/src/targets/c14/battery_driver.h b/radio/src/targets/c14/battery_driver.h new file mode 100644 index 000000000..f6b2800ec --- /dev/null +++ b/radio/src/targets/c14/battery_driver.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#include "board.h" +#include "hal.h" + +#include "hal/gpio.h" +#include "stm32_gpio.h" + +extern uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps +extern bool usbChargerLed(); diff --git a/radio/src/targets/c14/board.cpp b/radio/src/targets/c14/board.cpp new file mode 100644 index 000000000..01e2106c0 --- /dev/null +++ b/radio/src/targets/c14/board.cpp @@ -0,0 +1,246 @@ +/* + * 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_rgbleds.h" +#include "stm32_spi.h" + +#include "flash_driver.h" +#include "extflash_driver.h" + +#include "board.h" +#include "boards/generic_stm32/module_ports.h" +#include "boards/generic_stm32/rgb_leds.h" +#include "bsp_io.h" + +#include "hal/adc_driver.h" +#include "hal/trainer_driver.h" +#include "hal/rotary_encoder.h" +#include "hal/key_driver.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 "gyro.h" +#include "hal/audio_driver.h" +#include "boards/generic_stm32/analog_inputs.h" + +#include "flysky_gimbal_driver.h" +#include "timers_driver.h" + +#include "battery_driver.h" + +#if defined(IMU_ICM4207C) +#include "drivers/icm42607C.h" +#endif + +#include "bitmapbuffer.h" +#include "colors.h" + +// Module control needs g_model — firmware only, not bootloader +#if !defined(BOOT) +#include "myeeprom.h" +#include "pulses/modules_constants.h" +#include "dataconstants.h" +#endif + +#include "tp_gt911.h" + +#include + +// common ADC driver +extern const etx_hal_adc_driver_t _adc_driver; + +// RGB LED timer +extern const stm32_pulse_timer_t _led_timer; + +#if defined(SEMIHOSTING) +extern "C" void initialise_monitor_handles(); +#endif + +static const etx_imu_t _imu_candidates[] = { +#if defined(IMU_ICM4207C) + { &imu_icm42607_driver, IMU_I2C_BUS, ICM426xx_I2C_BASE_ADDR }, + { &imu_icm42607_driver, IMU_I2C_BUS, ICM426xx_I2C_BASE_ADDR + 1 }, +#endif +}; + +static void gyroInit() +{ + gyroStart(imuDetect(_imu_candidates, DIM(_imu_candidates))); +} + +void INTERNAL_MODULE_ON() +{ + bsp_output_set(BSP_INT_PWR); +} + +void INTERNAL_MODULE_OFF() +{ + bsp_output_clear(BSP_INT_PWR); +} + +void INTERNAL_MODULE_BOOTCMD(uint8_t enable) +{ + if (enable) + bsp_output_clear(BSP_RF_BOOT0); + else + bsp_output_set(BSP_RF_BOOT0); +} + +void EXTERNAL_MODULE_ON() +{ + bsp_output_clear(BSP_EXT_PWR); +} + +void EXTERNAL_MODULE_OFF() +{ + bsp_output_set(BSP_EXT_PWR); +} + +void boardBLEarlyInit() +{ + timersInit(); + bsp_io_init(); +} + +void boardBLPreJump() +{ + ExtFLASH_Init(); + SDRAM_Init(); + + // Stop 1ms timer + MS_TIMER->CR1 &= ~TIM_CR1_CEN; +} + +void boardBLInit() +{ + ExtFLASH_Init(); + SDRAM_Init(); + + // register external FLASH for DFU + usbRegisterDFUMedia((void*)extflash_dfu_media); + + // register internal & external FLASH for UF2 + flashRegisterDriver(FLASH_BANK1_BASE, BOOTLOADER_SIZE, &stm32_flash_driver); + flashRegisterDriver(QSPI_BASE, 8 * 1024 * 1024, &extflash_driver); +} + + +void boardInit() +{ + // enable interrupts + __enable_irq(); + + boardInitModulePorts(); + + pwrInit(); + delaysInit(); + timersInit(); + + bsp_io_init(); + bsp_output_set(BSP_PWR_LED); + + 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); + + board_trainer_init(); + + gpio_init(UCHARGER_CHARGE_END_GPIO, GPIO_IN_PD, GPIO_PIN_SPEED_LOW); + + usbInit(); + + gimbalsDetect(); + + ledInit(); + rgbLedInit(); + + + rgbLedClearAll(); + keysInit(); + rotaryEncoderInit(); + switchInit(); + touchPanelInit(); + audioInit(); + adcInit(&_adc_driver); + hapticInit(); + +#if defined(RTCLOCK) + rtcInit(); // RTC must be initialized before rambackupRestore() is called +#endif + + gyroInit(); +} + +extern void rtcDisableBackupReg(); + +void boardOff() +{ + lcdOff(); + + while (pwrPressed()) { + WDG_RESET(); + } + + SysTick->CTRL = 0; // turn off systick + + // Shutdown the Haptic + hapticDone(); + + rtcDisableBackupReg(); + +#if !defined(BOOT) +#if defined(LED_STRIP_GPIO) + rgbLedClearAll(); +#endif +#endif + 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); +#endif + +/* 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. + // __WFI() actually enters deep sleep (SLEEPDEEP alone keeps the core spinning). + while (1) { + __WFI(); + } +} diff --git a/radio/src/targets/c14/board.h b/radio/src/targets/c14/board.h new file mode 100644 index 000000000..f9193a0dc --- /dev/null +++ b/radio/src/targets/c14/board.h @@ -0,0 +1,258 @@ +/* + * 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 "definitions.h" +#include "edgetx_constants.h" + +#include "board_common.h" +#include "hal.h" +#include "hal/serial_port.h" +#include "hal/watchdog_driver.h" + +#define FLASHSIZE 0x800000 +#define FLASH_PAGESIZE 256 +#define BOOTLOADER_SIZE 0x10000 +#define BOOTLOADER_ADDRESS 0x08000000 +#define FIRMWARE_ADDRESS 0x90000000 +#define FIRMWARE_LEN(fsize) (fsize) +#define FIRMWARE_MAX_LEN FLASHSIZE +#define APP_START_ADDRESS (uint32_t)(FIRMWARE_ADDRESS) + +#define BOOTLOADER_KEYS 0x42 + +#define MB *1024*1024 +#define LUA_MEM_EXTRA_MAX (2 MB) // max allowed memory usage for Lua bitmaps (in bytes) +#define LUA_MEM_MAX (6 MB) // max allowed memory usage for complete Lua (in bytes), 0 means unlimited + +extern uint16_t sessionTimer; + +#define SLAVE_MODE() (g_model.trainerData.mode == TRAINER_MODE_SLAVE) + +// Board driver +void boardInit(); +void boardOff(); + +// CPU Unique ID +#define LEN_CPU_UID (3*8+2) +void getCPUUniqueID(char * s); + +// Flash Write driver +#define FLASH_PAGESIZE 256 +void unlockFlash(); +void lockFlash(); +void flashWrite(uint32_t * address, const uint32_t * buffer); +uint32_t isFirmwareStart(const uint8_t * buffer); +uint32_t isBootloaderStart(const uint8_t * buffer); + +// SDRAM driver +extern "C" void SDRAM_Init(); + +// Pulses driver +#if !defined(SIMU) + + +void INTERNAL_MODULE_BOOTCMD(uint8_t enable); +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_ReadInputDataBit(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) == Bit_SET) + +#else + +#define INTERNAL_MODULE_OFF() +#define INTERNAL_MODULE_ON() +#define EXTERNAL_MODULE_ON() +#define EXTERNAL_MODULE_OFF() +#define BLUETOOTH_MODULE_ON() +#define BLUETOOTH_MODULE_OFF() +#define IS_INTERNAL_MODULE_ON() (false) +#define IS_EXTERNAL_MODULE_ON() (false) + +#endif // defined(SIMU) + +#if defined(FUNCTION_SWITCHES) +#define NUM_FUNCTIONS_SWITCHES 6 +#define NUM_FUNCTIONS_GROUPS 3 + +#else +#define NUM_FUNCTIONS_SWITCHES 0 +#endif + +#define NUM_TRIMS 8 +#define DEFAULT_STICK_DEADZONE 2 + +// NI-MH 9.6V +#define BATTERY_WARN 87 // 8.7V +#define BATTERY_MIN 85 // 8.5V +#define BATTERY_MAX 115 // 11.5V +// --- 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 99 +#define BACKLIGHT_FORCED_ON BACKLIGHT_LEVEL_MAX + 1 +#define BACKLIGHT_LEVEL_MIN 1 + +#define LCD_BACKLIGHT_INIT_DELAY_MS 1500 + +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); \ + } + +bool usbChargerLed(); + +#if defined(__cplusplus) && !defined(SIMU) +} +#endif + +// Telemetry driver +#define INTMODULE_FIFO_SIZE 512 +#define TELEMETRY_FIFO_SIZE 512 + +// Audio driver +void audioInit(); +void setSampleRate(uint32_t frequency); +#define VOLUME_LEVEL_MAX 23 +#define VOLUME_LEVEL_DEF 12 +#if !defined(SOFTWARE_VOLUME) +void setScaledVolume(uint8_t volume); +void setVolume(uint8_t volume); +int32_t getVolume(); +#endif +#if defined(AUDIO_SPEAKER_ENABLE_GPIO) +void initSpeakerEnable(); +void enableSpeaker(); +void disableSpeaker(); +#else +static inline void initSpeakerEnable() { } +static inline void enableSpeaker() { } +static inline void disableSpeaker() { } +#endif +#if defined(HEADPHONE_TRAINER_SWITCH_GPIO) +void initHeadphoneTrainerSwitch(); +void enableHeadphone(); +void enableTrainer(); +#else +static inline void initHeadphoneTrainerSwitch() { } +static inline void enableHeadphone() { } +static inline void enableTrainer() { } +#endif +#if defined(JACK_DETECT_GPIO) +void initJackDetect(); +bool isJackPlugged(); +#endif +void audioConsumeCurrentBuffer(); +#define audioDisableIrq() __disable_irq() +#define audioEnableIrq() __enable_irq() + +// Haptic driver +void hapticInit(); +void hapticDone(); +void hapticOff(); +void hapticOn(uint32_t pwmPercent); + +// Second serial port driver +#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(); diff --git a/radio/src/targets/c14/bsp_io.cpp b/radio/src/targets/c14/bsp_io.cpp new file mode 100644 index 000000000..31eee9d9d --- /dev/null +++ b/radio/src/targets/c14/bsp_io.cpp @@ -0,0 +1,131 @@ +/* + * 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 "bsp_io.h" + +#include "stm32_i2c_driver.h" +#include "stm32_switch_driver.h" + +extern const stm32_switch_t* boardGetSwitchDef(uint8_t idx); + +#define BSP_IN_I2C_BUS I2C_Bus_2 +#define BSP_IN_I2C_ADDR 0x20 + +#define BSP_IN_MASK 0xFFFF + +#define BSP_OUT_I2C_BUS I2C_Bus_2 +#define BSP_OUT_I2C_ADDR 0x21 + +#define BSP_OUT_MASK \ + (PCA95XX_PIN_0 | PCA95XX_PIN_1 | PCA95XX_PIN_2 | PCA95XX_PIN_3 | \ + PCA95XX_PIN_4 | PCA95XX_PIN_5 | PCA95XX_PIN_6 | PCA95XX_PIN_7 | \ + PCA95XX_PIN_8 | PCA95XX_PIN_9 | PCA95XX_PIN_10) + +#define BSP_CHECK(x) \ + if ((x) < 0) return -1 + +static pca95xx_t output_exp; +static pca95xx_t input_exp; + +static uint16_t inputState = 0; +static bool updateInputState = false; + +void bsp_port_extender_irq_handler() { updateInputState = true; } + +static void bsp_input_read() +{ + // this is a fall back, the interrupts from the port extender + // are unreliable under some circumstances + static int readCount = 0; + readCount++; + + if (!updateInputState && readCount < 50) return; + + uint16_t value=0; + + readCount=0; + updateInputState = false; + + if (pca95xx_read(&input_exp, BSP_IN_MASK, &value) < 0) return; + inputState = value; +} + +int bsp_io_init() +{ + // init outputs + BSP_CHECK(pca95xx_init(&output_exp, BSP_OUT_I2C_BUS, BSP_OUT_I2C_ADDR)); + BSP_CHECK(pca95xx_write(&output_exp, BSP_OUT_MASK, BSP_RF_BOOT0)); + BSP_CHECK(pca95xx_set_direction(&output_exp, BSP_OUT_MASK, 0)); + + bsp_output_set(BSP_EXT_PWR); + + // init inputs + BSP_CHECK(pca95xx_init(&input_exp, BSP_IN_I2C_BUS, BSP_IN_I2C_ADDR)); + + gpio_init_int(GPIO_PIN(GPIOH, 6), GPIO_IN, GPIO_FALLING, + bsp_port_extender_irq_handler); + updateInputState = true; + bsp_input_read(); + + return 0; +} + +// EXT_PWR is active-low on the port extender; invert sense for that pin only. +void bsp_output_set(uint16_t pin) +{ + if (pin == BSP_EXT_PWR) { + pca95xx_write(&output_exp, pin, 0); + } else { + pca95xx_write(&output_exp, pin, pin); + } +} + +void bsp_output_clear(uint16_t pin) +{ + if (pin == BSP_EXT_PWR) { + pca95xx_write(&output_exp, pin, pin); + } else { + pca95xx_write(&output_exp, pin, 0); + } +} + +uint16_t bsp_input_get() +{ + bsp_input_read(); + return inputState; +} + +SwitchHwPos boardSwitchGetPosition(uint8_t idx) +{ + const stm32_switch_t* sw = boardGetSwitchDef(idx); + + if (sw->type == SWITCH_HW_ADC || sw->GPIOx_high != nullptr) + return stm32_switch_get_position(sw); + + bool val = false; + uint16_t pins = bsp_input_get(); + + val = (pins & sw->Pin_high) != 0; + + if (sw->inverted) val = !val; + + return val ? SWITCH_HW_UP : SWITCH_HW_DOWN; +} diff --git a/radio/src/targets/c14/bsp_io.h b/radio/src/targets/c14/bsp_io.h new file mode 100644 index 000000000..c7dcaba9d --- /dev/null +++ b/radio/src/targets/c14/bsp_io.h @@ -0,0 +1,55 @@ +/* + * 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 "drivers/pca95xx.h" +#include "hal/switch_driver.h" + +// Input port expander +#define BSP_TR1U PCA95XX_PIN_8 +#define BSP_TR1D PCA95XX_PIN_9 +#define BSP_TR3L PCA95XX_PIN_10 +#define BSP_TR3R PCA95XX_PIN_11 +#define BSP_TR2U PCA95XX_PIN_12 +#define BSP_TR2D PCA95XX_PIN_13 +#define BSP_TR4L PCA95XX_PIN_14 +#define BSP_TR4R PCA95XX_PIN_15 + +// Output port expander +#define BSP_AUDIO_RST PCA95XX_PIN_0 +#define BSP_PA_NMUTE PCA95XX_PIN_1 +#define BSP_INT_PWR PCA95XX_PIN_2 +#define BSP_EXT_PWR PCA95XX_PIN_3 +#define BSP_CHARGE_EN PCA95XX_PIN_4 +#define BSP_LCD_NRST PCA95XX_PIN_5 +#define BSP_USB_SW PCA95XX_PIN_6 +#define BSP_PWR_LED PCA95XX_PIN_7 +#define BSP_LCD_CS PCA95XX_PIN_8 +#define BSP_RF_BOOT0 PCA95XX_PIN_9 +#define BSP_USB_SWB PCA95XX_PIN_10 + +int bsp_io_init(); + +void bsp_output_set(uint16_t pin); +void bsp_output_clear(uint16_t pin); + +uint16_t bsp_input_get(); diff --git a/radio/src/targets/c14/extflash_driver.cpp b/radio/src/targets/c14/extflash_driver.cpp new file mode 100644 index 000000000..2fb52421d --- /dev/null +++ b/radio/src/targets/c14/extflash_driver.cpp @@ -0,0 +1,175 @@ +/* + * 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 "extflash_driver.h" + +#include "stm32_hal.h" +#include "stm32_qspi.h" + +#include "board.h" + +#define QSPI_NOR_PAGE_SIZE 256 + +int32_t ExtFLASH_Init() +{ + if (stm32_qspi_nor_init() != 0) { + return -1; + } + + return stm32_qspi_nor_memory_mapped(); +} + +void ExtFLASH_InitRuntime() { stm32_qspi_no_init_runtime(); } + +// +// ETX HAL flash interface +// + +static uint32_t extflash_get_size_kb() +{ + return QSPI_FLASH_SIZE / 1024; +} + +static uint32_t extflash_get_sector(uint32_t address) +{ + address -= QSPI_BASE; + return address / (64 * 1024); +} + +static uint32_t extflash_get_sector_size(uint32_t sector) +{ + (void)sector; + return (64 * 1024); +} + +static int extflash_erase_sector(uint32_t address) +{ + address -= QSPI_BASE; + return stm32_qspi_nor_erase_sector(address); +} + +static int extflash_program(uint32_t address, void* data, uint32_t len) +{ + address -= QSPI_BASE; + + int ret = 0; + while (len > 0) { + uint32_t size = (len > QSPI_NOR_PAGE_SIZE) ? QSPI_NOR_PAGE_SIZE : len; + ret = stm32_qspi_nor_program(address, data, size); + if (ret != 0) break; + len -= size; + address += size; + data = (uint8_t*)data + size; + } + + return ret; +} + +static int extflash_read(uint32_t address, void* data, uint32_t len) +{ + address -= QSPI_BASE; + return stm32_qspi_nor_read(address, data, len); +} + +const etx_flash_driver_t extflash_driver = { + .get_size_kb = extflash_get_size_kb, + .get_sector = extflash_get_sector, + .get_sector_size = extflash_get_sector_size, + .erase_sector = extflash_erase_sector, + .program = extflash_program, + .read = extflash_read, +}; + +#if defined(BOOT) +// +// USB DFU interface +// +#include "usbd_dfu.h" + +#define MEDIA_DESC_STR "@External Flash /0x90000000/128*064Kg" + +static uint16_t extflash_dfu_init() +{ + return USBD_OK; +} + +static uint16_t extflash_dfu_deinit() +{ + return USBD_OK; +} + +static uint16_t extflash_dfu_erase(uint32_t address) +{ + if (extflash_erase_sector(address) < 0) { + return USBD_FAIL; + } + return USBD_OK; +} + +static uint16_t extflash_dfu_write(uint8_t* src, uint8_t* dest, uint32_t len) +{ + if (extflash_program((intptr_t)dest, (void*)src, len) < 0) { + return USBD_FAIL; + } + return USBD_OK; +} + +static uint8_t* extflash_dfu_read(uint8_t* src, uint8_t* dest, uint32_t len) +{ + if (extflash_read((intptr_t)src, (void*)dest, len) < 0) { + return nullptr; + } + return dest; +} + +static uint16_t extflash_dfu_get_status(uint32_t address, uint8_t cmd, uint8_t *buffer) +{ + switch (cmd) { + case DFU_MEDIA_PROGRAM: + buffer[1] = 1; + buffer[2] = 0; + buffer[3] = 0; + break; + + case DFU_MEDIA_ERASE: + default: + buffer[1] = 20; + buffer[2] = 0; + buffer[3] = 0; + break; + } + + return USBD_OK; +} + +const USBD_DFU_MediaTypeDef _extflash_dfu_media = { + .pStrDesc = (uint8_t*)MEDIA_DESC_STR, + .Init = extflash_dfu_init, + .DeInit = extflash_dfu_deinit, + .Erase = extflash_dfu_erase, + .Write = extflash_dfu_write, + .Read = extflash_dfu_read, + .GetStatus = extflash_dfu_get_status, +}; + +const void* extflash_dfu_media = &_extflash_dfu_media; + +#endif // BOOT diff --git a/radio/src/targets/c14/extflash_driver.h b/radio/src/targets/c14/extflash_driver.h new file mode 100644 index 000000000..c51d6a3aa --- /dev/null +++ b/radio/src/targets/c14/extflash_driver.h @@ -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. + */ + +#pragma once + +#include "hal/flash_driver.h" + +extern const etx_flash_driver_t extflash_driver; +extern const void* extflash_dfu_media; + +// init external FLASH hardware +int32_t ExtFLASH_Init(); + +// init only runtime structures +void ExtFLASH_InitRuntime(); diff --git a/radio/src/targets/c14/hal.h b/radio/src/targets/c14/hal.h new file mode 100644 index 000000000..3dd8bc884 --- /dev/null +++ b/radio/src/targets/c14/hal.h @@ -0,0 +1,391 @@ +/* + * 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 "hal_settings.h" + +/* + +STM32H750 + +SDMMC uses its own DMA controller (SDMMC1). + +DMA1 +Stream0: LED_STRIP_TIMER_DMA_STREAM (TIM2_UP) +Stream1: AUDIO_DMA_Stream (DAC1_CH1) +Stream2: EXTMODULE_USART_RX_DMA_STREAM (USART2_RX) +Stream3: TELEMETRY_DMA_Stream_RX (UART5_RX) +Stream4: EXTMODULE_USART_TX_DMA_STREAM (USART2_TX) +Stream7: TELEMETRY_DMA_Stream_TX (UART5_TX) + +DMA2 +Stream0: ADC_EXT_DMA_STREAM (ADC3, do not move) +Stream4: ADC_DMA_STREAM (ADC1, do not move) + +TIM2: LED_STRIP_TIMER +TIM3: BACKLIGHT_TIMER (CH1) / HAPTIC_GPIO_TIMER (CH2) +TIM5: PWM_TIMER (stick PWM) +TIM6: AUDIO_TIMER +TIM12: MIXER_SCHEDULER_TIMER +TIM14: MS_TIMER +TIM15: TRAINER_TIMER +TIM17: ROTARY_ENCODER_TIMER + +USART2: EXTMODULE_USART +USART3: INTMODULE_USART (CRSF internal module, interrupt-driven; its + DMA defines are disabled below) +UART5: TELEMETRY_USART + + */ + + +#define KEYS_GPIO_REG_ENTER GPIOC +#define KEYS_GPIO_PIN_ENTER LL_GPIO_PIN_5 +#define KEYS_GPIO_REG_PAGEDN GPIOA +#define KEYS_GPIO_PIN_PAGEDN LL_GPIO_PIN_8 +#define KEYS_GPIO_REG_EXIT GPIOG +#define KEYS_GPIO_PIN_EXIT LL_GPIO_PIN_14 + +#define KEYS_GPIO_REG_SYS GPIOC +#define KEYS_GPIO_PIN_SYS LL_GPIO_PIN_4 +#define KEYS_GPIO_REG_PAGEUP GPIOC +#define KEYS_GPIO_PIN_PAGEUP LL_GPIO_PIN_13 +#define KEYS_GPIO_REG_MDL GPIOA +#define KEYS_GPIO_PIN_MDL LL_GPIO_PIN_10 + +#define KEYS_GPIO_REG_UP GPIOG +#define KEYS_GPIO_PIN_UP LL_GPIO_PIN_2 +#define KEYS_GPIO_REG_DOWN GPIOG +#define KEYS_GPIO_PIN_DOWN LL_GPIO_PIN_3 + +// Rotary encoder simulated via KEY_UP (PG.02) and KEY_DOWN (PG.03) buttons +#define ROTARY_ENCODER_NAVIGATION +#define ROTARY_ENCODER_GPIO GPIOG +#define ROTARY_ENCODER_GPIO_PIN_A LL_GPIO_PIN_2 // PG.02 KEY_UP +#define ROTARY_ENCODER_GPIO_PIN_B LL_GPIO_PIN_3 // PG.03 KEY_DOWN +#define ROTARY_ENCODER_TIMER TIM17 +#define ROTARY_ENCODER_TIMER_IRQn TIM17_IRQn +#define ROTARY_ENCODER_TIMER_IRQHandler TIM17_IRQHandler + +// Direct switches +#define SWITCHES_GPIO_REG_E GPIOF +#define SWITCHES_GPIO_PIN_E LL_GPIO_PIN_8 + +#define SWITCHES_GPIO_REG_F GPIOF +#define SWITCHES_GPIO_PIN_F LL_GPIO_PIN_6 + +// Trims +#define TRIMS_GPIO_REG_LHL +#define TRIMS_GPIO_PIN_LHL + +#define TRIMS_GPIO_REG_LHR +#define TRIMS_GPIO_PIN_LHR + +#define TRIMS_GPIO_REG_LVD +#define TRIMS_GPIO_PIN_LVD + +#define TRIMS_GPIO_REG_LVU +#define TRIMS_GPIO_PIN_LVU + +#define TRIMS_GPIO_REG_RHL +#define TRIMS_GPIO_PIN_RHL + +#define TRIMS_GPIO_REG_RHR +#define TRIMS_GPIO_PIN_RHR + +#define TRIMS_GPIO_REG_RVD +#define TRIMS_GPIO_PIN_RVD + +#define TRIMS_GPIO_REG_RVU +#define TRIMS_GPIO_PIN_RVU + + +#define ADC_GPIO_PIN_STICK_LH LL_GPIO_PIN_1 // PA.01 +#define ADC_GPIO_PIN_STICK_LV LL_GPIO_PIN_0 // PA.00 +#define ADC_GPIO_PIN_STICK_RV LL_GPIO_PIN_3 // PA.03 +#define ADC_GPIO_PIN_STICK_RH LL_GPIO_PIN_2 // PA.02 + +#define ADC_GPIO_PIN_SWA LL_GPIO_PIN_2 // PC.02 +#define ADC_GPIO_PIN_SWB LL_GPIO_PIN_3 // PC.03 +#define ADC_GPIO_PIN_SWC LL_GPIO_PIN_9 // PF.09 +#define ADC_GPIO_PIN_SWD LL_GPIO_PIN_7 // PF.07 + +//S1,S2 +#define ADC_GPIO_PIN_POT1 LL_GPIO_PIN_6 // PA.06 VRA +#define ADC_GPIO_PIN_POT2 LL_GPIO_PIN_1 // PB.01 VRB +//LS,LR +#define ADC_GPIO_PIN_SLIDER1 LL_GPIO_PIN_0 // PB.00 VRC/LS +#define ADC_GPIO_PIN_SLIDER2 LL_GPIO_PIN_7 // PA.07 VRD/RS + +#define ADC_GPIO_PIN_BATT LL_GPIO_PIN_1 // PC.01 + +#define ADC_GPIOA_PINS \ + (ADC_GPIO_PIN_POT1 | ADC_GPIO_PIN_SLIDER2 | ADC_GPIO_PIN_STICK_LH | \ + ADC_GPIO_PIN_STICK_LV | ADC_GPIO_PIN_STICK_RH | ADC_GPIO_PIN_STICK_RV) + +#define ADC_GPIOB_PINS (ADC_GPIO_PIN_POT2 | ADC_GPIO_PIN_SLIDER1) + +#define ADC_GPIOC_PINS (ADC_GPIO_PIN_SWA | ADC_GPIO_PIN_SWB | ADC_GPIO_PIN_BATT) + +#define ADC_GPIOF_PINS \ + (ADC_GPIO_PIN_SWC | ADC_GPIO_PIN_SWD ) + +#define ADC_CHANNEL_STICK_LH LL_ADC_CHANNEL_14 // ADC12_INP14 +#define ADC_CHANNEL_STICK_LV LL_ADC_CHANNEL_15 // ADC12_INP15 +#define ADC_CHANNEL_STICK_RV LL_ADC_CHANNEL_16 // ADC12_INP16 +#define ADC_CHANNEL_STICK_RH LL_ADC_CHANNEL_17 // ADC12_INP17 + +// Each ADC cannot map more than 8 channels, otherwise it will cause problems +#define ADC_CHANNEL_POT1 LL_ADC_CHANNEL_3 // ADC12_INP3 +#define ADC_CHANNEL_POT2 LL_ADC_CHANNEL_5 // ADC12_INP5 +#define ADC_CHANNEL_SLIDER1 LL_ADC_CHANNEL_9 // ADC12_INP9 +#define ADC_CHANNEL_SLIDER2 LL_ADC_CHANNEL_7 // ADC12_INP7 + +// Analog switches +#define ADC_CHANNEL_SWA LL_ADC_CHANNEL_0 // ADC3_INP0 +#define ADC_CHANNEL_SWB LL_ADC_CHANNEL_1 // ADC3_INP1 +#define ADC_CHANNEL_SWC LL_ADC_CHANNEL_2 // ADC3_INP2 +#define ADC_CHANNEL_SWD LL_ADC_CHANNEL_3 // ADC3_INP3 + +#define ADC_CHANNEL_BATT LL_ADC_CHANNEL_11 // ADC123_INP11 +#define ADC_CHANNEL_RTC_BAT LL_ADC_CHANNEL_VBAT // ADC12_IN16 + +#define ADC_MAIN ADC1 +#define ADC_DMA DMA2 +#define ADC_DMA_CHANNEL LL_DMAMUX1_REQ_ADC1 +#define ADC_DMA_STREAM LL_DMA_STREAM_4 +#define ADC_DMA_STREAM_IRQ DMA2_Stream4_IRQn +#define ADC_DMA_STREAM_IRQHandler DMA2_Stream4_IRQHandler +#define ADC_SAMPTIME LL_ADC_SAMPLINGTIME_64CYCLES_5 + +#define ADC_EXT ADC3 +#define ADC_EXT_CHANNELS \ +{ \ + ADC_CHANNEL_SWA, ADC_CHANNEL_SWB, ADC_CHANNEL_SWC, ADC_CHANNEL_SWD, \ + ADC_CHANNEL_BATT, ADC_CHANNEL_RTC_BAT \ +} + +#define ADC_EXT_DMA DMA2 +#define ADC_EXT_DMA_CHANNEL LL_DMAMUX1_REQ_ADC3 +#define ADC_EXT_DMA_STREAM LL_DMA_STREAM_0 +#define ADC_EXT_DMA_STREAM_IRQ DMA2_Stream0_IRQn +#define ADC_EXT_DMA_STREAM_IRQHandler DMA2_Stream0_IRQHandler +#define ADC_EXT_SAMPTIME LL_ADC_SAMPLINGTIME_64CYCLES_5 + +#define ADC_VREF_PREC2 329 + +#define PWM_STICKS +#define PWM_TIMER TIM5 +#define PWM_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) +#define PWM_GPIO GPIOA +#define PWM_GPIO_AF GPIO_AF2 + +#define PWM_IRQHandler TIM5_IRQHandler +#define PWM_IRQn TIM5_IRQn +#define PWM_GPIOA_PINS (ADC_GPIO_PIN_STICK_RV | ADC_GPIO_PIN_STICK_RH | ADC_GPIO_PIN_STICK_LH | ADC_GPIO_PIN_STICK_LV) + +#define STICK_PWM_CHANNEL_LH 0 +#define STICK_PWM_CHANNEL_LV 1 +#define STICK_PWM_CHANNEL_RV 2 +#define STICK_PWM_CHANNEL_RH 3 + +#define USE_EXTI9_5_IRQ // used for I2C port extender interrupt +#define EXTI9_5_IRQ_Priority 5 + +// Power +#define PWR_SWITCH_GPIO GPIO_PIN(GPIOB, 3) // PB.03 +#define PWR_ON_GPIO GPIO_PIN(GPIOI, 8) // PI.08 + +// Charger +#define UCHARGER_CHARGE_END_GPIO GPIO_PIN(GPIOD, 4) // PD.04 + +// TODO! Check IOLL1 to PI.01 connectivity! + +// S.Port update connector +#define HAS_SPORT_UPDATE_CONNECTOR() (false) + +// Telemetry + #define TELEMETRY_TX_GPIO GPIO_PIN(GPIOB, 13) + #define TELEMETRY_RX_GPIO GPIO_UNDEF //GPIO_PIN(GPIOB, 12) + #define TELEMETRY_USART UART5 + #define TELEMETRY_USART_IRQn UART5_IRQn + #define TELEMETRY_DMA DMA1 + #define TELEMETRY_DMA_Stream_TX LL_DMA_STREAM_7 + #define TELEMETRY_DMA_Channel_TX LL_DMAMUX1_REQ_UART5_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_UART5_RX + #define TELEMETRY_USART_IRQHandler UART5_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(GPIOC, 0) // PC.00 +#define USB_GPIO_DM GPIO_PIN(GPIOA, 11) // PA.11 +#define USB_GPIO_DP GPIO_PIN(GPIOA, 12) // PA.12 +#define USB_GPIO_AF GPIO_AF10 + +// LCD +#define LCD_DISP_PORT GPIOC +#define LCD_GPIO_NRST GPIO_PIN(GPIOC, 7) // PC.7 OK + +// QSPI Flash +#define QSPI_MAX_FREQ 80000000U // 80 MHz +#define QSPI_CLK_GPIO GPIO_PIN(GPIOB, 2) +#define QSPI_CLK_GPIO_AF GPIO_AF9 +#define QSPI_CS_GPIO GPIO_PIN(GPIOB, 6) +#define QSPI_CS_GPIO_AF GPIO_AF10 +#define QSPI_MISO_GPIO GPIO_PIN(GPIOD, 12) +#define QSPI_MISO_GPIO_AF GPIO_AF9 +#define QSPI_MOSI_GPIO GPIO_PIN(GPIOD, 11) +#define QSPI_MOSI_GPIO_AF GPIO_AF9 +#define QSPI_WP_GPIO GPIO_PIN(GPIOE, 2) +#define QSPI_WP_GPIO_AF GPIO_AF9 +#define QSPI_HOLD_GPIO GPIO_PIN(GPIOD, 13) +#define QSPI_HOLD_GPIO_AF GPIO_AF9 +#define QSPI_FLASH_SIZE 0x800000 + +/* +// SPI NOR Flash +#define FLASH_SPI SPI6 +#define FLASH_SPI_CS_GPIO GPIOG +#define FLASH_SPI_CS_GPIO_PIN LL_GPIO_PIN_6 // PG.06 +#define FLASH_SPI_GPIO GPIOG +#define FLASH_SPI_SCK_GPIO_PIN LL_GPIO_PIN_13 // PG.13 +#define FLASH_SPI_MISO_GPIO_PIN LL_GPIO_PIN_12 // PG.12 +#define FLASH_SPI_MOSI_GPIO_PIN LL_GPIO_PIN_14 // PG.14 +*/ +#define SD_PRESENT_GPIO GPIO_PIN(GPIOD, 3) // PD.03 +#define SD_SDIO SDMMC1 +#define SD_SDIO_CLK_DIV(fq) (HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC) / (2 * fq)) +#define SD_SDIO_INIT_CLK_DIV SD_SDIO_CLK_DIV(400000) +#define SD_SDIO_TRANSFER_CLK_DIV SD_SDIO_CLK_DIV(20000000) +#define STORAGE_USE_SDIO + + +// Audio +#define AUDIO_MUTE_GPIO GPIO_PIN(GPIOD, 7) // PD.07 +#define AUDIO_MUTE_DELAY 500 // ms +#define AUDIO_UNMUTE_DELAY 100 // ms +#define AUDIO_OUTPUT_GPIO GPIO_PIN(GPIOA, 4) // PA.04 +#define AUDIO_DAC DAC1 +#define AUDIO_DMA_Stream LL_DMA_STREAM_1 +#define AUDIO_DMA_Channel LL_DMAMUX1_REQ_DAC1_CH1 + +#define AUDIO_TIM_IRQn TIM6_DAC_IRQn +#define AUDIO_TIM_IRQHandler TIM6_DAC_IRQHandler +#define AUDIO_DMA_Stream_IRQn DMA1_Stream1_IRQn +#define AUDIO_DMA_Stream_IRQHandler DMA1_Stream1_IRQHandler +#define AUDIO_TIMER TIM6 +#define AUDIO_DMA DMA1 +// Mute unmute don't seem necessary, but mute pin need to be set nonetheless +#define INVERTED_MUTE_PIN + +// I2C Bus touch +#define I2C_B1 I2C1 +#define I2C_B1_SDA_GPIO GPIO_PIN(GPIOB, 7) // PB.07 OK +#define I2C_B1_SCL_GPIO GPIO_PIN(GPIOB, 8) // PB.08 OK +#define I2C_B1_GPIO_AF LL_GPIO_AF_4 +#define I2C_B1_CLK_RATE 400000 + +//PCA9555 +#define I2C_B2 I2C3 +#define I2C_B2_SDA_GPIO GPIO_PIN(GPIOH, 8) // PH.08 +#define I2C_B2_SCL_GPIO GPIO_PIN(GPIOH, 7) // PH.07 +#define I2C_B2_GPIO_AF LL_GPIO_AF_4 +#define I2C_B2_CLK_RATE 400000 + +// Internal Module +#define INTMODULE_BOOTCMD_BSP +#define INTMODULE_TX_GPIO GPIO_PIN(GPIOB, 11) // PB.11 +#define INTMODULE_RX_GPIO GPIO_PIN(GPIOB, 10) // PB.10 +#define INTMODULE_USART USART3 +#define INTMODULE_GPIO_AF LL_GPIO_AF_7 +#define INTMODULE_USART_IRQn USART3_IRQn +#define INTMODULE_USART_IRQHandler USART3_IRQHandler +//#define INTMODULE_DMA DMA1 +#define INTMODULE_DMA_STREAM LL_DMA_STREAM_1 +#define INTMODULE_DMA_STREAM_IRQ DMA1_Stream1_IRQn +#define INTMODULE_DMA_FLAG_TC DMA_FLAG_TCIF1 +#define INTMODULE_DMA_CHANNEL LL_DMA_CHANNEL_5 +//#define INTMODULE_RX_DMA DMA1 +#define INTMODULE_RX_DMA_STREAM LL_DMA_STREAM_3 +#define INTMODULE_RX_DMA_CHANNEL LL_DMA_CHANNEL_5 + +// c14 ext-module is wired to USART2 on PD.5 (TX) / PD.6 (RX). PPM via timer is +// not supported: PD.5 has no TIM4 alternate function. EXTMODULE_TIMER is +// intentionally left undefined so the timer-pulse port is compiled out of +// module_ports.cpp (the `extmoduleTimer` block there is guarded by +// `#if defined(EXTMODULE_TIMER)`); the module uses USART only. +#define EXTMODULE +// Module is powered by BSP +#define EXTMODULE_TX_GPIO GPIO_PIN(GPIOD, 5) +#define EXTMODULE_RX_GPIO GPIO_PIN(GPIOD, 6) + +//USART +#define EXTMODULE_USART USART2 +#define EXTMODULE_USART_RX_GPIO EXTMODULE_RX_GPIO +#define EXTMODULE_USART_TX_GPIO EXTMODULE_TX_GPIO +#define EXTMODULE_USART_TX_DMA DMA1 +#define EXTMODULE_USART_TX_DMA_CHANNEL LL_DMAMUX1_REQ_USART2_TX +#define EXTMODULE_USART_TX_DMA_STREAM LL_DMA_STREAM_4 + +#define EXTMODULE_USART_RX_DMA_CHANNEL LL_DMAMUX1_REQ_USART2_RX +#define EXTMODULE_USART_RX_DMA_STREAM LL_DMA_STREAM_2 + +#define EXTMODULE_USART_IRQHandler USART2_IRQHandler +#define EXTMODULE_USART_IRQn USART2_IRQn + +// Trainer Port +#define TRAINER_IN_GPIO GPIO_PIN(GPIOE, 5) // PE.05 +#define TRAINER_IN_TIMER_Channel LL_TIM_CHANNEL_CH1 + +#define TRAINER_OUT_GPIO GPIO_PIN(GPIOE, 6) // PE.06 +#define TRAINER_OUT_TIMER_Channel LL_TIM_CHANNEL_CH2 + +#define TRAINER_TIMER TIM15 +#define TRAINER_TIMER_IRQn TIM15_IRQn +#define TRAINER_TIMER_IRQHandler TIM15_IRQHandler +#define TRAINER_GPIO_AF LL_GPIO_AF_4 +#define TRAINER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) + +// Touch +#define TOUCH_I2C_BUS I2C_Bus_1 +#define TOUCH_INT_GPIO GPIO_PIN(GPIOI, 3) // PI.03 OK +#define TOUCH_RST_GPIO GPIO_PIN(GPIOI, 11) // PI.11 OK +#define TOUCH_INT_EXTI_Line LL_EXTI_LINE_3 +#define TOUCH_INT_EXTI_Port LL_SYSCFG_EXTI_PORTI +#define TOUCH_INT_EXTI_SysCfgLine LL_SYSCFG_EXTI_LINE3 +#define USE_EXTI3_IRQ +#define EXTI3_IRQ_Priority 9 +#define GT911_ROTATION_MODE 180 + +#define TOUCH_I2C_CLK_RATE 100000 + +#define LSE_DRIVE_STRENGTH RCC_LSEDRIVE_HIGH diff --git a/radio/src/targets/c14/haptic_driver.cpp b/radio/src/targets/c14/haptic_driver.cpp new file mode 100644 index 000000000..148312717 --- /dev/null +++ b/radio/src/targets/c14/haptic_driver.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "hal/gpio.h" +#include "stm32_gpio.h" +#include "stm32_timer.h" +#include "stm32_pulse_driver.h" + +#include "board.h" + +#define HAPTIC_TIMER_FREQ 200000000 + +static const stm32_pulse_timer_t _haptic_timer = { + .GPIO = (gpio_t)HAPTIC_GPIO, + .GPIO_Alternate = HAPTIC_GPIO_AF, + .TIMx = HAPTIC_GPIO_TIMER, + .TIM_Freq = HAPTIC_TIMER_FREQ, + .TIM_Channel = LL_TIM_CHANNEL_CH2, + .TIM_IRQn = (IRQn_Type)-1, + .DMAx = nullptr, + .DMA_Stream = 0, + .DMA_Channel = 0, + .DMA_IRQn = (IRQn_Type)-1, + .DMA_TC_CallbackPtr = nullptr, +}; + +void hapticInit(void) +{ + stm32_pulse_init(&_haptic_timer, 10000); + stm32_pulse_config_output(&_haptic_timer, true, LL_TIM_OCMODE_PWM1, 0); + LL_TIM_SetAutoReload(_haptic_timer.TIMx, 100); + LL_TIM_EnableCounter(_haptic_timer.TIMx); +} + +void hapticOn(uint32_t pwmPercent) +{ + if (pwmPercent > 100) pwmPercent = 100; + stm32_pulse_set_cmp_val(&_haptic_timer, pwmPercent); +} + +void hapticOff(void) { hapticOn(0); } +void hapticDone(void) { hapticOff(); } diff --git a/radio/src/targets/c14/key_driver.cpp b/radio/src/targets/c14/key_driver.cpp new file mode 100644 index 000000000..d1b1afad8 --- /dev/null +++ b/radio/src/targets/c14/key_driver.cpp @@ -0,0 +1,86 @@ +/* + * 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 "bsp_io.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" + +void keysInit() { _init_keys(); } + +uint32_t readKeys() { return _read_keys(); } + +/* The output bit-order has to be: + 0 LHL TR3L (Left equals down) + 1 LHR TR3R + 2 LVD TR1D + 3 LVU TR1U + 4 RVD TR2D + 5 RVU TR2U + 6 RHL TR4L + 7 RHR TR4R +*/ + +enum PhysicalTrims { + TR3L = 0, + TR3R, + TR1D = 2, + TR1U, + TR2D = 4, + TR2U, + TR4L = 6, + TR4R +}; + +extern bool suspendI2CTasks; + +uint32_t readTrims() +{ + uint32_t result = 0; + + if (suspendI2CTasks) return result; + + uint16_t keys = bsp_input_get(); + +#define _TRIM(t) \ + if ((keys & BSP_##t) == 0) result |= 1 << t; + + _TRIM(TR1U); + _TRIM(TR1D); + _TRIM(TR3L); + _TRIM(TR3R); + _TRIM(TR2U); + _TRIM(TR2D); + _TRIM(TR4L); + _TRIM(TR4R); + +#undef _TRIM + + return result; +} diff --git a/radio/src/targets/c14/lcd_driver.cpp b/radio/src/targets/c14/lcd_driver.cpp new file mode 100644 index 000000000..fa466ba6e --- /dev/null +++ b/radio/src/targets/c14/lcd_driver.cpp @@ -0,0 +1,252 @@ +/* + * 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 "stm32_gpio.h" +#include "hal/gpio.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; + +static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer, + const rect_t ©_area) +{ + (void)disp_drv; + (void)copy_area; + + // 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 LCD_AF_GPIOConfig(void) { + /**LTDC GPIO Configuration + PI10 ------> LTDC_HSYNC + PF10 ------> LTDC_DE + PA4 ------> LTDC_VSYNC + PH9 ------> LTDC_R3 + PH10 ------> LTDC_R4 + PH11 ------> LTDC_R5 + PH12 ------> LTDC_R6 + PG6 ------> LTDC_R7 + PG7 ------> LTDC_CLK + PH13 ------> LTDC_G2 + PH14 ------> LTDC_G3 + PH15 ------> LTDC_G4 + PI0 ------> LTDC_G5 + PI1 ------> LTDC_G6 + PI2 ------> LTDC_G7 + PG11 ------> LTDC_B3 + PI4 ------> LTDC_B4 + PI5 ------> LTDC_B5 + PI6 ------> LTDC_B6 + PI7 ------> LTDC_B7 + */ + + gpio_init_af(GPIO_PIN(GPIOI, 0), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOI, 1), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOI, 2), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOI, 4), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOI, 5), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOI, 6), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOI, 7), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOI, 10), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + + gpio_init_af(GPIO_PIN(GPIOF, 10), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOI, 9), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + + gpio_init_af(GPIO_PIN(GPIOH, 9), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOH, 10), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOH, 11), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOH, 12), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOH, 13), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOH, 14), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOH, 15), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + + gpio_init_af(GPIO_PIN(GPIOG, 6), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOG, 7), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + gpio_init_af(GPIO_PIN(GPIOG, 11), GPIO_AF14, GPIO_SPEED_FREQ_LOW); + +} + +inline void LCD_NRST_LOW() { gpio_clear(LCD_GPIO_NRST); } +inline void LCD_NRST_HIGH() { gpio_set(LCD_GPIO_NRST); } + +static void lcdReset() +{ + LCD_NRST_HIGH(); + delay_ms(1); + LCD_NRST_LOW(); + delay_ms(20); + LCD_NRST_HIGH(); + delay_ms(30); +} + +void LCD_Init_LTDC() { + __HAL_RCC_LTDC_CLK_ENABLE(); + hltdc.Instance = LTDC; + + /* LTDC Configuration *********************************************************/ + /* Polarity configuration */ + /* Initialize the horizontal synchronization polarity as active low */ + hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL; + /* Initialize the vertical synchronization polarity as active low */ + hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL; + /* Initialize the data enable polarity as active low */ + hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL; + /* Initialize the pixel clock polarity as input pixel clock */ + hltdc.Init.PCPolarity = LTDC_PCPOLARITY_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; + /* Configure vertical synchronization height */ + hltdc.Init.VerticalSync = VSH; + + /* Configure accumulated horizontal back porch */ + hltdc.Init.AccumulatedHBP = HBP; + /* Configure accumulated vertical back porch */ + hltdc.Init.AccumulatedVBP = VBP; + /* Configure accumulated active width */ + hltdc.Init.AccumulatedActiveW = lcd_phys_w + HBP; + /* Configure accumulated active height */ + hltdc.Init.AccumulatedActiveH = lcd_phys_h + VBP; + /* Configure total width */ + hltdc.Init.TotalWidth = lcd_phys_w + HBP + HFP; + /* Configure total height */ + hltdc.Init.TotalHeigh = lcd_phys_h + VBP + VFP; + + HAL_LTDC_Init(&hltdc); + + // Configure IRQ (line) + NVIC_SetPriority(LTDC_IRQn, LTDC_IRQ_PRIO); + NVIC_EnableIRQ(LTDC_IRQn); + + // Trigger on last line + HAL_LTDC_ProgramLineEvent(&hltdc, lcd_phys_h); + __HAL_LTDC_ENABLE_IT(&hltdc, LTDC_IT_LI); +} + +void LCD_LayerInit() { + auto& layer = hltdc.LayerCfg[0]; + + /* Windowing configuration */ + layer.WindowX0 = 0; + layer.WindowX1 = lcd_phys_w; + layer.WindowY0 = 0; + layer.WindowY1 = lcd_phys_h; + + /* Pixel Format configuration*/ + layer.PixelFormat = LTDC_PIXEL_FORMAT_RGB565; + + /* Alpha constant (255 totally opaque) */ + layer.Alpha = 255; + + /* Default Color configuration (configure A,R,G,B component values) */ + layer.Backcolor.Blue = 0; + layer.Backcolor.Green = 0; + layer.Backcolor.Red = 0; + layer.Alpha0 = 0; + + /* Configure blending factors */ + layer.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA; + layer.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA; + + layer.ImageWidth = lcd_phys_w; + layer.ImageHeight = lcd_phys_h; + + /* Start Address configuration : the LCD Frame buffer is defined on SDRAM w/ Offset */ + layer.FBStartAdress = (intptr_t)initialFrameBuffer; + + /* Initialize LTDC layer 1 */ + HAL_LTDC_ConfigLayer(&hltdc, &hltdc.LayerCfg[0], 0); + + /* dithering activation */ + HAL_LTDC_EnableDither(&hltdc); +} + +extern "C" +void lcdSetInitalFrameBuffer(void* fbAddress) +{ + initialFrameBuffer = fbAddress; +} + +const char* boardLcdType = ""; + +extern "C" void LCD_NRSTConfig(void) +{ + gpio_init(LCD_GPIO_NRST, GPIO_OUT, GPIO_PIN_SPEED_LOW); +} + +void lcdInit(void) +{ + LCD_NRSTConfig(); + lcdReset(); + LCD_AF_GPIOConfig(); + + LCD_Init_LTDC(); + LCD_LayerInit(); + + __HAL_LTDC_ENABLE(&hltdc); + + lcdSetFlushCb(startLcdRefresh); +} + +extern "C" void LTDC_IRQHandler(void) +{ + __HAL_LTDC_CLEAR_FLAG(&hltdc, LTDC_FLAG_LI); + __HAL_LTDC_DISABLE_IT(&hltdc, LTDC_IT_LI); + _frame_addr_reloaded = 1; +} diff --git a/radio/src/targets/c14/lcd_driver.h b/radio/src/targets/c14/lcd_driver.h new file mode 100644 index 000000000..2a40a6436 --- /dev/null +++ b/radio/src/targets/c14/lcd_driver.h @@ -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. + */ + +#pragma once + +#include "bsp_io.h" + +// LTDC sync/porch timings +#define HBP ( 24 ) +#define VBP ( 10 ) +#define HSW ( 4 ) +#define VSH ( 2 ) +#define HFP ( 140 - HBP ) +#define VFP ( 22 - VBP ) +#define VSW 10 diff --git a/radio/src/targets/c14/led_driver.cpp b/radio/src/targets/c14/led_driver.cpp new file mode 100644 index 000000000..be36e6d13 --- /dev/null +++ b/radio/src/targets/c14/led_driver.cpp @@ -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. + */ + +#include "hal/gpio.h" +#include "hal/rgbleds.h" +#include "stm32_gpio.h" +#include "boards/generic_stm32/rgb_leds.h" +#include "board.h" + +#define GET_RED(color) (((color) & 0xFF0000) >>16) +#define GET_GREEN(color) (((color) & 0x00FF00) >> 8) +#define GET_BLUE(color) ((color) & 0x0000FF) + +#if !defined(CFS_LED_STRIP_START) +#define CFS_LED_STRIP_START 0 +#endif + +void fsLedRGB(uint8_t index, uint32_t color) +{ + index = (index * 2) + CFS_LED_STRIP_START; + rgbSetLedColor(index, GET_RED(color), GET_GREEN(color),GET_BLUE(color)); + rgbSetLedColor(index+1, GET_RED(color), GET_GREEN(color),GET_BLUE(color)); +} + +uint32_t fsGetLedRGB(uint8_t index) +{ + return rgbGetLedColor((index * 2) + CFS_LED_STRIP_START); +} + diff --git a/radio/src/targets/c14/rotary_enc_simulator.cpp b/radio/src/targets/c14/rotary_enc_simulator.cpp new file mode 100644 index 000000000..06c1744ae --- /dev/null +++ b/radio/src/targets/c14/rotary_enc_simulator.cpp @@ -0,0 +1,134 @@ +/* + * 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. + */ + +// Rotary encoder simulator: uses KEY_UP / KEY_DOWN buttons (PG.02 / PG.03) +// to drive the encoder position, with repeat and acceleration on hold. + +#include "stm32_hal_ll.h" +#include "stm32_gpio_driver.h" +#include "stm32_timer.h" +#include "board.h" +#include "hal.h" +#include "timers_driver.h" + +#include "hal/rotary_encoder.h" + +// Repeat timing (units = 10ms ISR ticks) +#define REPEAT_INITIAL_DELAY 40 // 400ms before first repeat +#define REPEAT_INTERVAL_START 10 // 100ms between steps at start +#define REPEAT_INTERVAL_MIN 2 // 20ms between steps at max speed +#define REPEAT_ACCEL_TICKS 100 // ticks of hold until max speed + +volatile rotenc_t rotencValue = 0; +volatile uint32_t rotencDt = 0; + +rotenc_t rotaryEncoderGetValue() +{ + return rotencValue; +} + +static uint8_t lastPins = 0; + +// Per-button hold state +static uint16_t holdTicks[2] = {0, 0}; +static uint16_t repeatCounter[2] = {0, 0}; + +static void stepEncoder(int8_t dir) +{ + static uint32_t last_tick = 0; + rotencValue += dir; + uint32_t now = timersGetMsTick(); + uint32_t dt = last_tick ? (now - last_tick) : 100; + rotencDt += dt; + last_tick = now; +} + +static void updateFromButtons() +{ + uint8_t pins = 0; + if (!LL_GPIO_IsInputPinSet(ROTARY_ENCODER_GPIO, ROTARY_ENCODER_GPIO_PIN_A)) + pins |= 0x01; // KEY_UP (bit 0) + if (!LL_GPIO_IsInputPinSet(ROTARY_ENCODER_GPIO, ROTARY_ENCODER_GPIO_PIN_B)) + pins |= 0x02; // KEY_DOWN (bit 1) + + static const int8_t dir[2] = {-1, +1}; // KEY_UP decrements, KEY_DOWN increments + + for (int i = 0; i < 2; i++) { + uint8_t mask = (1 << i); + bool pressed = (pins & mask) != 0; + bool wasPressed = (lastPins & mask) != 0; + + if (!wasPressed && pressed) { + // Fresh press: step immediately, start hold tracking + stepEncoder(dir[i]); + holdTicks[i] = 0; + repeatCounter[i] = REPEAT_INITIAL_DELAY; + } else if (pressed) { + // Held: count ticks and fire on interval + holdTicks[i]++; + if (repeatCounter[i] > 0) { + repeatCounter[i]--; + } else { + stepEncoder(dir[i]); + // Compute next interval: linearly interpolate from START to MIN + uint16_t hold = holdTicks[i]; + if (hold > REPEAT_ACCEL_TICKS) hold = REPEAT_ACCEL_TICKS; + uint16_t interval = REPEAT_INTERVAL_START - + (hold * (REPEAT_INTERVAL_START - REPEAT_INTERVAL_MIN)) / REPEAT_ACCEL_TICKS; + repeatCounter[i] = interval; + } + } else { + holdTicks[i] = 0; + repeatCounter[i] = 0; + } + } + + lastPins = pins; +} + +// Called from charger loop before main init +void rotaryEncoderCheck() +{ + updateFromButtons(); +} + +void rotaryEncoderInit() +{ + LL_GPIO_InitTypeDef pinInit; + LL_GPIO_StructInit(&pinInit); + pinInit.Mode = LL_GPIO_MODE_INPUT; + pinInit.Pull = LL_GPIO_PULL_UP; + pinInit.Pin = ROTARY_ENCODER_GPIO_PIN_A | ROTARY_ENCODER_GPIO_PIN_B; + stm32_gpio_enable_clock(ROTARY_ENCODER_GPIO); + LL_GPIO_Init(ROTARY_ENCODER_GPIO, &pinInit); + + // Periodic 10ms timer for button polling + stm32_timer_enable_clock(ROTARY_ENCODER_TIMER); + ROTARY_ENCODER_TIMER->ARR = 9999; // 10ms at 1µS tick + ROTARY_ENCODER_TIMER->PSC = + (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1; // 1µS + ROTARY_ENCODER_TIMER->CCER = 0; + ROTARY_ENCODER_TIMER->CCMR1 = 0; + ROTARY_ENCODER_TIMER->EGR = TIM_EGR_UG; // reload PSC/ARR immediately + ROTARY_ENCODER_TIMER->SR = 0; + ROTARY_ENCODER_TIMER->CR1 = TIM_CR1_CEN; // continuous + ROTARY_ENCODER_TIMER->DIER |= TIM_DIER_UIE; + + NVIC_EnableIRQ(ROTARY_ENCODER_TIMER_IRQn); + NVIC_SetPriority(ROTARY_ENCODER_TIMER_IRQn, 7); + + lastPins = 0; +} + +extern "C" void ROTARY_ENCODER_TIMER_IRQHandler(void) +{ + ROTARY_ENCODER_TIMER->SR &= ~TIM_SR_UIF; + updateFromButtons(); +} diff --git a/radio/src/targets/c14/sdram_driver.cpp b/radio/src/targets/c14/sdram_driver.cpp new file mode 100644 index 000000000..abee3b34a --- /dev/null +++ b/radio/src/targets/c14/sdram_driver.cpp @@ -0,0 +1,188 @@ +/* + * 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_hal_ll.h" + +#include "board.h" + +#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000) +#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001) +#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002) +#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004) +#define SDRAM_MODEREG_BURST_FULL_PAGE ((uint16_t)0x0007) +#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) +#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) +#define SDRAM_MODEREG_CAS_LATENCY_1 ((uint16_t)0x0010) +#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020) +#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030) +#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000) +#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) +#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) + +#define GPIO_AF_FMC GPIO_AF12 + +extern "C" void SDRAM_GPIOConfig(void) +{ + /* 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); + + + gpio_init_af(GPIO_PIN(GPIOH, 2), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOH, 3), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH); + gpio_init_af(GPIO_PIN(GPIOH, 5), 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: clock configuration enable command */ + FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE; + FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; + FMC_SDRAMCommandStructure.AutoRefreshNumber = 1; + FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0; + FMC_SDRAM_SendCommand(FMC_Bank5_6_R, &FMC_SDRAMCommandStructure, 10); + + /* Step 4: insert delay */ + delay_ms(100); + + /* Step 5: PALL (precharge all) command */ + FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_PALL; + FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; + FMC_SDRAMCommandStructure.AutoRefreshNumber = 1; + FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0; + FMC_SDRAM_SendCommand(FMC_Bank5_6_R, &FMC_SDRAMCommandStructure, 10); + + /* Step 6: Auto-Refresh command */ + FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE; + FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; + FMC_SDRAMCommandStructure.AutoRefreshNumber = 8; + FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0; + 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; + + FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_LOAD_MODE; + FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; + FMC_SDRAMCommandStructure.AutoRefreshNumber = 1; + FMC_SDRAMCommandStructure.ModeRegisterDefinition = tmpr; + FMC_SDRAM_SendCommand(FMC_Bank5_6_R, &FMC_SDRAMCommandStructure, 10); + + /* Step 8: refresh rate counter — (15.62 us x Freq) - 20 */ + FMC_SDRAM_SetAutoRefreshNumber(FMC_Bank5_6_R, 15); + FMC_SDRAM_ProgramRefreshRate(FMC_Bank5_6_R, 1855); +} + +extern "C" void SDRAM_Init(void) +{ + //delay funcion needed + delaysInit(); + + /* GPIO configuration for FMC SDRAM bank */ + SDRAM_GPIOConfig(); + + /* Enable FMC clock */ + LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_FMC); + + /* FMC Configuration ---------------------------------------------------------*/ + FMC_SDRAM_InitTypeDef FMC_SDRAMInitStructure; + FMC_SDRAM_TimingTypeDef FMC_SDRAMTimingInitStructure; + + /* FMC SDRAM Bank configuration */ + /* Timing configuration for 80 Mhz of SD clock */ + FMC_SDRAMTimingInitStructure.LoadToActiveDelay = 2; + FMC_SDRAMTimingInitStructure.ExitSelfRefreshDelay = 7; + FMC_SDRAMTimingInitStructure.SelfRefreshTime = 4; + FMC_SDRAMTimingInitStructure.RowCycleDelay = 7; + FMC_SDRAMTimingInitStructure.WriteRecoveryTime = 3; + FMC_SDRAMTimingInitStructure.RPDelay = 2; + FMC_SDRAMTimingInitStructure.RCDDelay = 2; + + /* FMC SDRAM control configuration */ + FMC_SDRAMInitStructure.SDBank = FMC_SDRAM_BANK1; + FMC_SDRAMInitStructure.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8; + FMC_SDRAMInitStructure.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12; + FMC_SDRAMInitStructure.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16; + FMC_SDRAMInitStructure.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4; + FMC_SDRAMInitStructure.CASLatency = FMC_SDRAM_CAS_LATENCY_3; + FMC_SDRAMInitStructure.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE; + FMC_SDRAMInitStructure.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2; + FMC_SDRAMInitStructure.ReadBurst = FMC_SDRAM_RBURST_ENABLE; + FMC_SDRAMInitStructure.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0; + + /* FMC SDRAM bank initialization */ + FMC_SDRAM_Init(FMC_Bank5_6_R, &FMC_SDRAMInitStructure); + FMC_SDRAM_Timing_Init(FMC_Bank5_6_R, &FMC_SDRAMTimingInitStructure, FMC_SDRAM_BANK1); + + __FMC_ENABLE(); + + /* FMC SDRAM device initialization sequence */ + SDRAM_InitSequence(); +} diff --git a/radio/src/targets/c14/system_clock.c b/radio/src/targets/c14/system_clock.c new file mode 100644 index 000000000..3fe2c01e0 --- /dev/null +++ b/radio/src/targets/c14/system_clock.c @@ -0,0 +1,116 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "stm32h7xx_ll_pwr.h" +#include "stm32h7xx_ll_rcc.h" +#include "stm32h7xx_ll_system.h" +#include "stm32h7xx_ll_bus.h" + +#define BOOTSTRAP __attribute__((section(".bootstrap"))) + +BOOTSTRAP void SystemClock_Config(void) +{ + /* Power Configuration */ + LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY); + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + while (LL_PWR_IsActiveFlag_VOS() == 0){ + } + + /* Enable HSE oscillator */ + LL_RCC_HSE_Enable(); + while (LL_RCC_HSE_IsReady() != 1) { + } + + /* Set FLASH latency */ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_5); + + /* Main PLL configuration and activation */ + LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSE); + LL_RCC_PLL1P_Enable(); + LL_RCC_PLL1Q_Enable(); + LL_RCC_PLL1R_Enable(); + LL_RCC_PLL1FRACN_Disable(); + LL_RCC_PLL1_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_2_4); + LL_RCC_PLL1_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE); + LL_RCC_PLL1_SetM(1); + LL_RCC_PLL1_SetN(100); + LL_RCC_PLL1_SetP(2); + LL_RCC_PLL1_SetQ(4); + LL_RCC_PLL1_SetR(2); + LL_RCC_PLL1_Enable(); + while (LL_RCC_PLL1_IsReady() != 1) { + } + + /* Set Sys & AHB & APB1 & APB2 & APB4 prescaler */ + LL_RCC_SetSysPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2); + LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_2); + + /* Set PLL1 as System Clock Source */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) { + } + + /* Config & activate PLL2 */ + LL_RCC_PLL2P_Enable(); + LL_RCC_PLL2Q_Enable(); + LL_RCC_PLL2R_Enable(); + LL_RCC_PLL2FRACN_Disable(); + LL_RCC_PLL2_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_2_4); + LL_RCC_PLL2_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE); + LL_RCC_PLL2_SetM(1); + LL_RCC_PLL2_SetN(120); + LL_RCC_PLL2_SetP(12); + LL_RCC_PLL2_SetQ(2); + LL_RCC_PLL2_SetR(4); + LL_RCC_PLL2_Enable(); + while (LL_RCC_PLL2_IsReady() != 1) { + } + + /* Config & activate PLL3 */ + LL_RCC_PLL3P_Enable(); + LL_RCC_PLL3Q_Enable(); + LL_RCC_PLL3R_Enable(); + LL_RCC_PLL3FRACN_Disable(); + LL_RCC_PLL3_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_2_4); + LL_RCC_PLL3_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE); + LL_RCC_PLL3_SetM(1); + LL_RCC_PLL3_SetN(120); + LL_RCC_PLL3_SetP(5); + LL_RCC_PLL3_SetQ(20); + LL_RCC_PLL3_SetR(80); + LL_RCC_PLL3_Enable(); + while (LL_RCC_PLL3_IsReady() != 1) { + } + + /* Enable SRAM1, SRAM2 & SRAM3 */ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_D2SRAM1 | + LL_AHB2_GRP1_PERIPH_D2SRAM2 | + LL_AHB2_GRP1_PERIPH_D2SRAM3); + + /* Set periph clock sources */ + LL_RCC_SetFMCClockSource(LL_RCC_FMC_CLKSOURCE_HCLK); + LL_RCC_SetSPIClockSource(LL_RCC_SPI123_CLKSOURCE_PLL3P); + LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLL3Q); + LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_CLKP); +} diff --git a/radio/src/targets/c14/system_clock.h b/radio/src/targets/c14/system_clock.h new file mode 100644 index 000000000..10b69a118 --- /dev/null +++ b/radio/src/targets/c14/system_clock.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +void SystemClock_Config(); + diff --git a/radio/src/targets/c14/tp_gt911.cpp b/radio/src/targets/c14/tp_gt911.cpp new file mode 100644 index 000000000..6e5f433c4 --- /dev/null +++ b/radio/src/targets/c14/tp_gt911.cpp @@ -0,0 +1,798 @@ +/* + * 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 +#include + +#define TP_GT911_ID "911" + +#if defined (RADIO_T18) +const uint8_t TOUCH_GT911_Cfg[] = { + GT911_CFG_NUMBER, // 0x8047 Config version + 0xE0, // 0x8048 X output map : x 480 + 0x01, + 0x10, // 0x804A Y ouptut max : y 272 + 0x01, + GT911_MAX_TP, // 0x804C Touch number + 0x0C, // 0x804D Module switch 1 : bit4= xy change Int mode + 0x00, // 0x804E Module switch 2 + 0x01, // 0x804F Shake_Count + 0x18, // 0x8050 Filter + 0x28, // 0x8051 Larger touch + 0x0F, // 0x8052 Noise reduction + 0x50, // 0x8053 Screen touch level + 0x3C, // 0x8054 Screen touch leave + 0x03, // 0x8055 Low power control + 0x0F, // 0x8056 Refresh rate + 0x01, // 0x8057 X threshold + 0x01, // 0x8058 Y threshold + 0x00, // 0x8059 Reserved + 0x00, // 0x805A Reserved + 0x00, // 0x805B Space (top, bottom) + 0x00, // 0x805C Space (left, right) + 0x04, // 0x805D Mini filter + 0x18, // 0x805E Strech R0 + 0x1A, // 0x805F Strech R1 + 0x1E, // 0x8060 Strech R2 + 0x14, // 0x8061 Strech RM + 0x87, // 0x8062 Drv groupA num + 0x29, // 0x8063 Drv groupB num + 0x0A, // 0x8064 Sensor num + 0x4B, // 0x8065 FreqA factor + 0x4D, // 0x8066 FreqB factor + 0xD3, // 0x8067 Panel bit freq + 0x07, + 0x00, // 0x8069 Reserved + 0x00, + 0x00, // 0x806B Panel tx gain + 0x19, // 0x806C Panel rx gain + 0x02, // 0x806D Panel dump shift + 0x10, // 0x806E Drv frame control + 0x32, // 0x806F Charging level up + 0x00, // 0x8070 Module switch 3 + 0x00, // 0x8071 Gesture distance + 0x00, // 0x8072 Gesture long press time + 0x00, // 0x8073 X/Y slope adjust + 0x03, // 0x8074 Gesture control + 0x00, // 0x8075 Gesture switch 1 + 0x00, // 0x8076 Gesture switch 2 + 0x00, // 0x8077 Gesture refresh rate + 0x00, // 0x8078 Gesture touch level + 0x00, // 0x8079 New green wake up level + 0x32, // 0x807A Freq hopping start + 0x73, // 0x807B Freq hopping end + 0x94, // 0x807C Noise detect time + 0xD5, // 0x807D Hopping flag + 0x02, // 0x807E Hopping flag + 0x07, // 0x807F Noise threshold + 0x00, // 0x8080 Nois min threshold old + 0x00, // 0x8081 Reserved + 0x04, // 0x8082 Hopping sensor group + 0xAE, // 0x8083 Hopping Seg1 normalize + 0x36, // 0x8084 Hopping Seg1 factor + 0x00, // 0x8085 Main clock adjust + 0x94, // 0x8086 Hopping Seg2 normalize + 0x40, // 0x8087 Hopping Seg2 factor + 0x00, // 0x8088 Reserved + 0x7E, // 0x8089 Hopping Seg3 normalize + 0x4C, // 0x808A Hopping Seg3 factor + 0x00, // 0x808B Reserved + 0x6D, // 0x808C Hopping Seg4 normalize + 0x59, // 0x808D Hopping Seg4 factor + 0x00, // 0x808E Reserved + 0x5D, // 0x808F Hopping Seg5 normalize + 0x6A, // 0x8090 Hopping Seg5 factor + 0x00, // 0x8091 Reserved + 0x5D, // 0x8092 Hopping Seg6 normalize + 0x00, // 0x8093 Key1 + 0x00, // 0x8094 Key2 + 0x00, // 0x8095 Key3 + 0x00, // 0x8096 Key4 + 0x00, // 0x8097 Key area + 0x00, // 0x8098 Key touch level + 0x00, // 0x8099 Key leave level + 0x00, // 0x809A Key sens + 0x00, // 0x809B Key sens + 0x00, // 0x809C Key restrain + 0x00, // 0x809D Key restrain time + 0x00, // 0x809E Large gesture touch + 0x00, // 0x809F Reserved + 0x00, // 0x80A0 Reserved + 0x00, // 0x80A1 Hotknot noise map + 0x00, // 0x80A2 Link threshold + 0x00, // 0x80A3 Pxy threshold + 0x00, // 0x80A4 GHot dump shift + 0x00, // 0x80A5 GHot rx gain + 0x00, // 0x80A6 Freg gain + 0x00, // 0x80A7 Freg gain 1 + 0x00, // 0x80A8 Freg gain 2 + 0x00, // 0x80A9 Freg gain 3 + 0x00, // 0x80AA Reserved + 0x00, // 0x80AB Reserved + 0x00, // 0x80AC Reserved + 0x00, // 0x80AD Reserved + 0x00, // 0x80AE Reserved + 0x00, // 0x80AF Reserved + 0x00, // 0x80B0 Reserved + 0x00, // 0x80B1 Reserved + 0x00, // 0x80B2 Reserved + 0x00, // 0x80B3 Combine dis + 0x00, // 0x80B4 Split set + 0x00, // 0x80B5 Reserved + 0x00, // 0x80B6 Reserved + 0x0A, // 0x80B7 Sensor CH0 + 0x0C, // 0x80B8 Sensor CH1 + 0x0E, // 0x80B9 Sensor CH2 + 0x10, // 0x80BA Sensor CH3 + 0x12, // 0x80BB Sensor CH4 + 0x14, // 0x80BC Sensor CH5 + 0x16, // 0x80BD Sensor CH6 + 0x18, // 0x80BE Sensor CH7 + 0x1A, // 0x80BF Sensor CH8 + 0x1C, // 0x80C0 Sensor CH9 + 0xFF, // 0x80C1 Sensor CH10 + 0xFF, // 0x80C2 Sensor CH11 + 0xFF, // 0x80C3 Sensor CH12 + 0xFF, // 0x80C4 Sensor CH13 + 0xFF, // 0x80C5 Reserved + 0xFF, // 0x80C6 Reserved + 0xFF, // 0x80C7 Reserved + 0xFF, // 0x80C8 Reserved + 0xFF, // 0x80C9 Reserved + 0xFF, // 0x80CA Reserved + 0xFF, // 0x80CB Reserved + 0xFF, // 0x80CC Reserved + 0xFF, // 0x80CD Reserved + 0xFF, // 0x80CE Reserved + 0xFF, // 0x80CF Reserved + 0xFF, // 0x80D0 Reserved + 0xFF, // 0x80D1 Reserved + 0xFF, // 0x80D2 Reserved + 0xFF, // 0x80D3 Reserved + 0xFF, // 0x80D4 Reserved + 0x00, // 0x80D5 Driver CH0 + 0x02, // 0x80D6 Driver CH1 + 0x04, // 0x80D7 Driver CH2 + 0x06, // 0x80D8 Driver CH3 + 0x08, // 0x80D9 Driver CH4 + 0x0A, // 0x80DA Driver CH5 + 0x0C, // 0x80DB Driver CH6 + 0x1D, // 0x80DC Driver CH7 + 0x1E, // 0x80DD Driver CH8 + 0x1F, // 0x80DE Driver CH9 + 0x20, // 0x80DF Driver CH10 + 0x21, // 0x80E0 Driver CH11 + 0x22, // 0x80E1 Driver CH12 + 0x24, // 0x80E2 Driver CH13 + 0x26, // 0x80E3 Driver CH14 + 0x28, // 0x80E4 Driver CH15 + 0xFF, // 0x80E5 Driver CH16 + 0xFF, // 0x80E6 Driver CH17 + 0xFF, // 0x80E7 Driver CH18 + 0xFF, // 0x80E8 Driver CH19 + 0xFF, // 0x80E9 Driver CH20 + 0xFF, // 0x80EA Driver CH21 + 0xFF, // 0x80EB Driver CH22 + 0xFF, // 0x80EC Driver CH23 + 0xFF, // 0x80ED Driver CH24 + 0xFF, // 0x80EE Driver CH25 + 0xFF, // 0x80EF Reserved + 0xFF, // 0x80F0 Reserved + 0xFF, // 0x80F1 Reserved + 0xFF, // 0x80F2 Reserved + 0xFF, // 0x80F3 Reserved + 0xFF, // 0x80F4 Reserved + 0xFF, // 0x80F5 Reserved + 0xFF, // 0x80F6 Reserved + 0xFF, // 0x80F7 Reserved + 0xFF, // 0x80F8 Reserved + 0xFF, // 0x80F9 Reserved + 0xFF, // 0x80FA Reserved + 0xFF, // 0x80FB Reserved + 0xFF, // 0x80FC Reserved + 0xFF, // 0x80FD Reserved + 0xFF // 0x80FE Reserved +}; + +#else + +//GT911 param table +const uint8_t TOUCH_GT911_Cfg[] = + { + GT911_CFG_NUMBER, // 0x8047 Config version + 0xE0, // 0x8048 X output map : x 480 + 0x01, + 0x10, // 0x804A Y ouptut max : y 272 + 0x01, + GT911_MAX_TP, // 0x804C Touch number +#if defined(TOUCH_PANEL_INVERTED) + 0x3C | 0xC0, // 0x804D Module switch 1 : 180° rotation +#else + 0x3C, // 0x804D Module switch 1 : bit4= xy change Int mode +#endif + 0x20, // 0x804E Module switch 2 + 0x22, // 0x804F Shake_Count + 0x0A, // 0x8050 Filter + 0x28, // 0x8051 Larger touch + 0x0F, // 0x8052 Noise reduction + 0x5A, // 0x8053 Screen touch level + 0x3C, // 0x8054 Screen touch leave + 0x03, // 0x8055 Low power control + 0x0F, // 0x8056 Refresh rate + 0x01, // 0x8057 X threshold + 0x01, // 0x8058 Y threshold + 0x00, // 0x8059 Reserved + 0x00, // 0x805A Reserved + 0x11, // 0x805B Space (top, bottom) + 0x11, // 0x805C Space (left, right) + 0x08, // 0x805D Mini filter + 0x18, // 0x805E Strech R0 + 0x1A, // 0x805F Strech R1 + 0x1E, // 0x8060 Strech R2 + 0x14, // 0x8061 Strech RM + 0x87, // 0x8062 Drv groupA num + 0x29, // 0x8063 Drv groupB num + 0x0A, // 0x8064 Sensor num + 0xCF, // 0x8065 FreqA factor + 0xD1, // 0x8066 FreqB factor + 0xB2, // 0x8067 Panel bit freq + 0x04, + 0x00, // 0x8069 Reserved + 0x00, + 0x00, // 0x806B Panel tx gain + 0xD8, // 0x806C Panel rx gain + 0x02, // 0x806D Panel dump shift + 0x1D, // 0x806E Drv frame control + 0x00, // 0x806F Charging level up + 0x01, // 0x8070 Module switch 3 + 0x00, // 0x8071 Gesture distance + 0x00, // 0x8072 Gesture long press time + 0x00, // 0x8073 X/Y slope adjust + 0x00, // 0x8074 Gesture control + 0x00, // 0x8075 Gesture switch 1 + 0x00, // 0x8076 Gesture switch 2 + 0x00, // 0x8077 Gesture refresh rate + 0x00, // 0x8078 Gesture touch level + 0x00, // 0x8079 New green wake up level + 0xB4, // 0x807A Freq hopping start + 0xEF, // 0x807B Freq hopping end + 0x94, // 0x807C Noise detect time + 0xD5, // 0x807D Hopping flag + 0x02, // 0x807E Hopping flag + 0x07, // 0x807F Noise threshold + 0x00, // 0x8080 Nois min threshold old + 0x00, // 0x8081 Reserved + 0x04, // 0x8082 Hopping sensor group + 0x6E, // 0x8083 Hopping Seg1 normalize + 0xB9, // 0x8084 Hopping Seg1 factor + 0x00, // 0x8085 Main clock adjust + 0x6A, // 0x8086 Hopping Seg2 normalize + 0xC4, // 0x8087 Hopping Seg2 factor + 0x00, // 0x8088 Reserved + 0x66, // 0x8089 Hopping Seg3 normalize + 0xCF, // 0x808A Hopping Seg3 factor + 0x00, // 0x808B Reserved + 0x62, // 0x808C Hopping Seg4 normalize + 0xDB, // 0x808D Hopping Seg4 factor + 0x00, // 0x808E Reserved + 0x5E, // 0x808F Hopping Seg5 normalize + 0xE8, // 0x8090 Hopping Seg5 factor + 0x00, // 0x8091 Reserved + 0x5E, // 0x8092 Hopping Seg6 normalize + 0x00, // 0x8093 Key1 + 0x00, // 0x8094 Key2 + 0x00, // 0x8095 Key3 + 0x00, // 0x8096 Key4 + 0x00, // 0x8097 Key area + 0x00, // 0x8098 Key touch level + 0x00, // 0x8099 Key leave level + 0x00, // 0x809A Key sens + 0x00, // 0x809B Key sens + 0x00, // 0x809C Key restrain + 0x00, // 0x809D Key restrain time + 0x00, // 0x809E Large gesture touch + 0x00, // 0x809F Reserved + 0x00, // 0x80A0 Reserved + 0x00, // 0x80A1 Hotknot noise map + 0x00, // 0x80A2 Link threshold + 0x00, // 0x80A3 Pxy threshold + 0x00, // 0x80A4 GHot dump shift + 0x00, // 0x80A5 GHot rx gain + 0x00, // 0x80A6 Freg gain + 0x00, // 0x80A7 Freg gain 1 + 0x00, // 0x80A8 Freg gain 2 + 0x00, // 0x80A9 Freg gain 3 + 0x00, // 0x80AA Reserved + 0x00, // 0x80AB Reserved + 0x00, // 0x80AC Reserved + 0x00, // 0x80AD Reserved + 0x00, // 0x80AE Reserved + 0x00, // 0x80AF Reserved + 0x00, // 0x80B0 Reserved + 0x00, // 0x80B1 Reserved + 0x00, // 0x80B2 Reserved + 0x00, // 0x80B3 Combine dis + 0x00, // 0x80B4 Split set + 0x00, // 0x80B5 Reserved + 0x00, // 0x80B6 Reserved + 0x14, // 0x80B7 Sensor CH0 + 0x12, // 0x80B8 Sensor CH1 + 0x10, // 0x80B9 Sensor CH2 + 0x0E, // 0x80BA Sensor CH3 + 0x0C, // 0x80BB Sensor CH4 + 0x0A, // 0x80BC Sensor CH5 + 0x08, // 0x80BD Sensor CH6 + 0x06, // 0x80BE Sensor CH7 + 0x04, // 0x80BF Sensor CH8 + 0x02, // 0x80C0 Sensor CH9 + 0xFF, // 0x80C1 Sensor CH10 + 0xFF, // 0x80C2 Sensor CH11 + 0xFF, // 0x80C3 Sensor CH12 + 0xFF, // 0x80C4 Sensor CH13 + 0x00, // 0x80C5 Reserved + 0x00, // 0x80C6 Reserved + 0x00, // 0x80C7 Reserved + 0x00, // 0x80C8 Reserved + 0x00, // 0x80C9 Reserved + 0x00, // 0x80CA Reserved + 0x00, // 0x80CB Reserved + 0x00, // 0x80CC Reserved + 0x00, // 0x80CD Reserved + 0x00, // 0x80CE Reserved + 0x00, // 0x80CF Reserved + 0x00, // 0x80D0 Reserved + 0x00, // 0x80D1 Reserved + 0x00, // 0x80D2 Reserved + 0x00, // 0x80D3 Reserved + 0x00, // 0x80D4 Reserved + 0x28, // 0x80D5 Driver CH0 + 0x26, // 0x80D6 Driver CH1 + 0x24, // 0x80D7 Driver CH2 + 0x22, // 0x80D8 Driver CH3 + 0x21, // 0x80D9 Driver CH4 + 0x20, // 0x80DA Driver CH5 + 0x1F, // 0x80DB Driver CH6 + 0x1E, // 0x80DC Driver CH7 + 0x1D, // 0x80DD Driver CH8 + 0x0C, // 0x80DE Driver CH9 + 0x0A, // 0x80DF Driver CH10 + 0x08, // 0x80E0 Driver CH11 + 0x06, // 0x80E1 Driver CH12 + 0x04, // 0x80E2 Driver CH13 + 0x02, // 0x80E3 Driver CH14 + 0x00, // 0x80E4 Driver CH15 + 0xFF, // 0x80E5 Driver CH16 + 0xFF, // 0x80E6 Driver CH17 + 0xFF, // 0x80E7 Driver CH18 + 0xFF, // 0x80E8 Driver CH19 + 0xFF, // 0x80E9 Driver CH20 + 0xFF, // 0x80EA Driver CH21 + 0xFF, // 0x80EB Driver CH22 + 0xFF, // 0x80EC Driver CH23 + 0xFF, // 0x80ED Driver CH24 + 0xFF, // 0x80EE Driver CH25 + 0x00, // 0x80EF Reserved + 0x00, // 0x80F0 Reserved + 0x00, // 0x80F1 Reserved + 0x00, // 0x80F2 Reserved + 0x00, // 0x80F3 Reserved + 0x00, // 0x80F4 Reserved + 0x00, // 0x80F5 Reserved + 0x00, // 0x80F6 Reserved + 0x00, // 0x80F7 Reserved + 0x00, // 0x80F8 Reserved + 0x00, // 0x80F9 Reserved + 0x00, // 0x80FA Reserved + 0x00, // 0x80FB Reserved + 0x00, // 0x80FC Reserved + 0x00, // 0x80FD Reserved + 0x00 // 0x80FE Reserved + }; + +#endif + +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; +} + +bool I2C_GT911_SendConfig(uint8_t cfgVer) +{ + uint8_t buf[2] = { cfgVer, 1 }; + bool bResult = true; + + for (uint8_t i = 1; i < sizeof(TOUCH_GT911_Cfg); i++) { + buf[0] += TOUCH_GT911_Cfg[i]; //check sum + } + + buf[0] = (~buf[0]) + 1; + + if (!I2C_GT911_WriteRegister(GT911_CONFIG_REG, (uint8_t *)&cfgVer, 1)) { + TRACE("GT911 ERROR: write config failed"); + bResult = false; + } + + if (!I2C_GT911_WriteRegister(GT911_CONFIG_REG+1, (uint8_t *)&TOUCH_GT911_Cfg[1], + sizeof(TOUCH_GT911_Cfg)-1)) { + TRACE("GT911 ERROR: write config failed"); + bResult = false; + } + + // write checksum and config_fresh + if (!I2C_GT911_WriteRegister(GT911_CONFIG_CHECKSUM_REG, buf, 2)) { + TRACE("GT911 ERROR: write config checksum failed"); + bResult = false; + } + + return bResult; +} + +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_SendConfig(tp_gt911_cfgVer)) { + TRACE("GT911 ERROR: sending configration failed"); + } + 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 + +#if defined(CSD203_SENSOR) + extern bool IICReadStatusFlag; +#endif + +struct TouchState touchPanelRead() +{ + uint8_t state = 0; + static bool gt911_needTranspose = true; // 是否需要旋转 + if (!touchEventOccured) return internalTouchState; +#if defined(CSD203_SENSOR) + for(int a=0;a<6;a++) + {//IIC bus preemption + if(IICReadStatusFlag==false){ + IICReadStatusFlag=true; + break; + } + else if(a>6){ + return internalTouchState; + } + delay_us(10); + } +#endif + + touchEventOccured = false; + + uint32_t startReadStatus = timersGetMsTick(); + do { + if (!I2C_GT911_ReadRegister(GT911_READ_XY_REG, &state, 1)) { + // ledRed(); + touchGT911hiccups++; + TRACE("GT911 I2C read XY error"); + if (!I2C_ReInit()) TRACE("I2C B1 ReInit failed"); + #if defined(CSD203_SENSOR) + IICReadStatusFlag=false; + #endif + 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))) { + // ledRed(); + touchGT911hiccups++; + TRACE("GT911 I2C data read error"); + if (!I2C_ReInit()) TRACE("I2C B1 ReInit failed"); + #if defined(CSD203_SENSOR) + IICReadStatusFlag=false; + #endif + return internalTouchState; + } + + // Rotate the raw touch point into screen coordinates up-front, so that + // position, start position and slide deltas all live in the same + // coordinate space. (Computing deltas from raw points against a + // previously-rotated internalTouchState would otherwise yield wrong + // slide/scroll deltas, e.g. for GT911_ROTATION_MODE == 180.) + coord_t px = touchData.points[0].x; + coord_t py = touchData.points[0].y; + if (gt911_needTranspose) { + coord_t rawX = px, rawY = py; + switch (GT911_ROTATION_MODE) { + case 90: + px = LCD_H - rawY - 1; + py = rawX; + break; + case 180: + px = LCD_W - rawX - 1; + py = LCD_H - rawY - 1; + break; + case 270: + px = rawY; + py = LCD_W - rawX - 1; + break; + default: + break; + } + } + + if (internalTouchState.event == TE_NONE || + internalTouchState.event == TE_UP || + internalTouchState.event == TE_SLIDE_END) { + internalTouchState.event = TE_DOWN; + internalTouchState.startX = internalTouchState.x = px; + internalTouchState.startY = internalTouchState.y = py; + downTime = now; + } else { + internalTouchState.deltaX = px - internalTouchState.x; + internalTouchState.deltaY = py - internalTouchState.y; + if (internalTouchState.event == TE_SLIDE || + abs(internalTouchState.deltaX) >= SLIDE_RANGE || + abs(internalTouchState.deltaY) >= SLIDE_RANGE) { + internalTouchState.event = TE_SLIDE; + internalTouchState.x = px; + internalTouchState.y = py; + } + } + } 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)); +#if defined(CSD203_SENSOR) + IICReadStatusFlag=false; +#endif + return internalTouchState; +} + +bool touchPanelEventOccured() +{ + return touchEventOccured; +} + +TouchState getInternalTouchState() +{ + return internalTouchState; +} + diff --git a/radio/src/targets/c14/tp_gt911.h b/radio/src/targets/c14/tp_gt911.h new file mode 100644 index 000000000..2e7f2c818 --- /dev/null +++ b/radio/src/targets/c14/tp_gt911.h @@ -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)]; + }; +}); diff --git a/radio/src/targets/c14/usb_descriptor.h b/radio/src/targets/c14/usb_descriptor.h new file mode 100644 index 000000000..cb31f1617 --- /dev/null +++ b/radio/src/targets/c14/usb_descriptor.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#define USB_NAME "C14" +#define USB_MANUFACTURER 'I', 'F', 'l', 'i', 'g', 'h', 't', ' ' /* 8 bytes */ +#define USB_PRODUCT 'C', '1', '4', ' ', ' ', ' ', ' ', ' ' /* 8 Bytes */ diff --git a/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp b/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp index 3843c0947..233db0453 100644 --- a/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp +++ b/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp @@ -145,6 +145,12 @@ static void dac_dma_init() { stm32_dma_enable_clock(AUDIO_DMA); + // _dma_buffer lives in a NOLOAD section, so it holds random SRAM contents at + // power-on. Prime it with silence so the DAC never clocks out garbage (heard + // as a crackle) on the very first transfer. + for (unsigned i = 0; i < DMA_BUFFER_LEN; i++) + _dma_buffer[i] = AUDIO_DATA_SILENCE; + LL_DMA_DeInit(AUDIO_DMA, AUDIO_DMA_Stream); LL_DMA_InitTypeDef dmaInit; diff --git a/radio/src/targets/common/arm/stm32/pwr_driver.cpp b/radio/src/targets/common/arm/stm32/pwr_driver.cpp index 01913c95f..d6f6b99c0 100644 --- a/radio/src/targets/common/arm/stm32/pwr_driver.cpp +++ b/radio/src/targets/common/arm/stm32/pwr_driver.cpp @@ -19,11 +19,11 @@ * GNU General Public License for more details. */ -#include "hal/gpio.h" -#include "stm32_gpio.h" - #include "board.h" #include "hal/abnormal_reboot.h" +#include "hal/gpio.h" +#include "hal/usb_driver.h" +#include "stm32_gpio.h" void pwrInit() { @@ -114,6 +114,16 @@ bool pwrForcePressed() bool pwrPressed() { +#if defined(RADIO_C14) && defined(DEBUG_SEGGER_RTT) + // Required to allow powering with USB the MCU for RTT flashing + // and not have the radio turn itself off on power on + if (usbPlugged()) { + return false; + } + else { + return !gpio_read(PWR_SWITCH_GPIO); + } +#endif #if defined(PWR_EXTRA_SWITCH_GPIO) return !gpio_read(PWR_SWITCH_GPIO) || !gpio_read(PWR_EXTRA_SWITCH_GPIO); #elif defined(PWR_SWITCH_GPIO) diff --git a/radio/src/targets/common/arm/stm32/stm32_adc.cpp b/radio/src/targets/common/arm/stm32/stm32_adc.cpp index 11f594198..d4ccf1281 100644 --- a/radio/src/targets/common/arm/stm32/stm32_adc.cpp +++ b/radio/src/targets/common/arm/stm32/stm32_adc.cpp @@ -40,7 +40,7 @@ #define OVERSAMPLING 4 #endif -#define SAMPLING_TIMEOUT_US 200 +#define SAMPLING_TIMEOUT_US 500 // Please note that we use the same prio for DMA TC and ADC IRQs // to avoid issues with preemption between these 2 diff --git a/radio/src/targets/pa01/CMakeLists.txt b/radio/src/targets/pa01/CMakeLists.txt index 888410fd6..d24112cbf 100644 --- a/radio/src/targets/pa01/CMakeLists.txt +++ b/radio/src/targets/pa01/CMakeLists.txt @@ -26,7 +26,8 @@ set(USB_SERIAL ON CACHE BOOL "Enable USB serial (CDC)") set(HARDWARE_EXTERNAL_MODULE YES) set(INTERNAL_MODULE_AFHDS3 YES) set(ROTARY_ENCODER YES) -set(FUNCTION_SWITCHES_WITH_RGB YES) +set(FUNCTION_SWITCHES YES) +set(FUNCTION_SWITCHES_RGB_LEDS YES) # IMU support set(IMU ON) @@ -89,13 +90,16 @@ if(DISK_CACHE) add_definitions(-DDISK_CACHE) endif() -if(FUNCTION_SWITCHES_WITH_RGB) - set(FUNCTION_SWITCHES YES) - add_definitions(-DFUNCTION_SWITCHES) +if(FUNCTION_SWITCHES_RGB_LEDS) + set(RGB_LEDS YES) add_definitions(-DFUNCTION_SWITCHES_RGB_LEDS) add_definitions(-DRGB_LEDS_900NS) endif() +if(RGB_LEDS) + add_definitions(-DRGB_LEDS) +endif() + if(FUNCTION_SWITCHES) add_definitions(-DFUNCTION_SWITCHES) endif() diff --git a/radio/src/targets/st16/CMakeLists.txt b/radio/src/targets/st16/CMakeLists.txt index aaad18f83..9d0a56ab2 100644 --- a/radio/src/targets/st16/CMakeLists.txt +++ b/radio/src/targets/st16/CMakeLists.txt @@ -26,7 +26,8 @@ set(USB_SERIAL ON CACHE BOOL "Enable USB serial (CDC)") set(HARDWARE_EXTERNAL_MODULE YES) set(INTERNAL_MODULE_AFHDS3 YES) set(ROTARY_ENCODER YES) -set(FUNCTION_SWITCHES_WITH_RGB YES) +set(FUNCTION_SWITCHES YES) +set(FUNCTION_SWITCHES_RGB_LEDS YES) # IMU support set(IMU ON) @@ -92,12 +93,15 @@ if(DISK_CACHE) add_definitions(-DDISK_CACHE) endif() -if(FUNCTION_SWITCHES_WITH_RGB) - set(FUNCTION_SWITCHES YES) - add_definitions(-DFUNCTION_SWITCHES) +if(FUNCTION_SWITCHES_RGB_LEDS) + set(RGB_LEDS YES) add_definitions(-DFUNCTION_SWITCHES_RGB_LEDS) endif() +if(RGB_LEDS) + add_definitions(-DRGB_LEDS) +endif() + if(FUNCTION_SWITCHES) add_definitions(-DFUNCTION_SWITCHES) endif() diff --git a/radio/src/targets/t15pro/CMakeLists.txt b/radio/src/targets/t15pro/CMakeLists.txt index f2d9fd78b..ad559bb3b 100644 --- a/radio/src/targets/t15pro/CMakeLists.txt +++ b/radio/src/targets/t15pro/CMakeLists.txt @@ -25,7 +25,8 @@ 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(FUNCTION_SWITCHES_WITH_RGB YES) +set(FUNCTION_SWITCHES YES) +set(FUNCTION_SWITCHES_RGB_LEDS YES) #option(STICK_DEAD_ZONE "Enable sticks dead zone" YES) @@ -61,7 +62,8 @@ set(RADIO_DEPENDENCIES ${RADIO_DEPENDENCIES} ${BITMAPS_TARGET}) set(FIRMWARE_DEPENDENCIES datacopy) set(SOFTWARE_KEYBOARD ON) set(FLYSKY_GIMBAL OFF) -set(FUNCTION_SWITCHES_WITH_RGB YES) +set(FUNCTION_SWITCHES YES) +set(FUNCTION_SWITCHES_RGB_LEDS YES) add_definitions( -DSTM32H750XBTx -DSTM32H750xx @@ -89,13 +91,16 @@ if(DISK_CACHE) add_definitions(-DDISK_CACHE) endif() -if(FUNCTION_SWITCHES_WITH_RGB) - set(FUNCTION_SWITCHES YES) - add_definitions(-DFUNCTION_SWITCHES) +if(FUNCTION_SWITCHES_RGB_LEDS) + set(RGB_LEDS YES) add_definitions(-DFUNCTION_SWITCHES_RGB_LEDS) add_definitions(-DRGB_LEDS_900NS) endif() +if(RGB_LEDS) + add_definitions(-DRGB_LEDS) +endif() + if(FUNCTION_SWITCHES) add_definitions(-DFUNCTION_SWITCHES) endif() diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt index 25f7624c4..313350b8a 100644 --- a/radio/src/targets/taranis/CMakeLists.txt +++ b/radio/src/targets/taranis/CMakeLists.txt @@ -291,7 +291,8 @@ elseif(PCB STREQUAL X7) endif() set(AUX2_SERIAL OFF) set(RGBLEDS YES) - set(FUNCTION_SWITCHES_WITH_RGB YES) + set(FUNCTION_SWITCHES YES) + set(FUNCTION_SWITCHES_RGB_LEDS YES) elseif(PCBREV STREQUAL ZORRO) set(DEFAULT_INTERNAL_MODULE CROSSFIRE CACHE STRING "Default internal module") set(INTERNAL_MODULE_SERIAL YES) @@ -524,12 +525,15 @@ if(FUNCTION_SWITCHES) add_definitions(-DFUNCTION_SWITCHES) endif() -if(FUNCTION_SWITCHES_WITH_RGB) - set(FUNCTION_SWITCHES YES) - add_definitions(-DFUNCTION_SWITCHES) +if(FUNCTION_SWITCHES_RGB_LEDS) + set(RGB_LEDS YES) add_definitions(-DFUNCTION_SWITCHES_RGB_LEDS) endif() +if(RGB_LEDS) + add_definitions(-DRGB_LEDS) +endif() + if(ENABLE_SERIAL_PASSTHROUGH) set(CLI ON "Enable CLI") endif() diff --git a/radio/src/targets/tx15/CMakeLists.txt b/radio/src/targets/tx15/CMakeLists.txt index 1afa7da04..299fd8bbe 100644 --- a/radio/src/targets/tx15/CMakeLists.txt +++ b/radio/src/targets/tx15/CMakeLists.txt @@ -29,7 +29,8 @@ 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(FUNCTION_SWITCHES_WITH_RGB YES) +set(FUNCTION_SWITCHES YES) +set(FUNCTION_SWITCHES_RGB_LEDS YES) set(INTERNAL_GPS_BAUDRATE "9600" CACHE STRING "Baud rate for internal GPS") # BT and serial gimbal share same UART @@ -113,13 +114,16 @@ if(INTERNAL_GPS) add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE}) endif() -if(FUNCTION_SWITCHES_WITH_RGB) - set(FUNCTION_SWITCHES YES) - add_definitions(-DFUNCTION_SWITCHES) +if(FUNCTION_SWITCHES_RGB_LEDS) + set(RGB_LEDS YES) add_definitions(-DFUNCTION_SWITCHES_RGB_LEDS) add_definitions(-DRGB_LEDS_900NS) endif() +if(RGB_LEDS) + add_definitions(-DRGB_LEDS) +endif() + if(FUNCTION_SWITCHES) add_definitions(-DFUNCTION_SWITCHES) endif() diff --git a/radio/src/targets/tx16smk3/CMakeLists.txt b/radio/src/targets/tx16smk3/CMakeLists.txt index 579ebcddf..113a5f896 100644 --- a/radio/src/targets/tx16smk3/CMakeLists.txt +++ b/radio/src/targets/tx16smk3/CMakeLists.txt @@ -28,7 +28,8 @@ 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(FUNCTION_SWITCHES_WITH_RGB YES) +set(FUNCTION_SWITCHES YES) +set(FUNCTION_SWITCHES_RGB_LEDS YES) set(FLEXSW "2" CACHE STRING "Max flex inputs usable as switches") set(INTERNAL_GPS_BAUDRATE "9600" CACHE STRING "Baud rate for internal GPS") @@ -111,13 +112,16 @@ if(DISK_CACHE) add_definitions(-DDISK_CACHE) endif() -if(FUNCTION_SWITCHES_WITH_RGB) - set(FUNCTION_SWITCHES YES) - add_definitions(-DFUNCTION_SWITCHES) +if(FUNCTION_SWITCHES_RGB_LEDS) + set(RGB_LEDS YES) add_definitions(-DFUNCTION_SWITCHES_RGB_LEDS) add_definitions(-DRGB_LEDS_900NS) endif() +if(RGB_LEDS) + add_definitions(-DRGB_LEDS) +endif() + if(FUNCTION_SWITCHES) add_definitions(-DFUNCTION_SWITCHES) endif() diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index 653d78b44..b4d31ff17 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -95,7 +95,9 @@ static void menusTask() toplcdOff(); #endif +#if !defined(PWR_BUTTON_MANAGED) drawSleepBitmap(); +#endif edgeTxClose(); boardOff(); } diff --git a/radio/src/translations/bl_translations.h b/radio/src/translations/bl_translations.h index f91e917e1..f919807a4 100644 --- a/radio/src/translations/bl_translations.h +++ b/radio/src/translations/bl_translations.h @@ -39,7 +39,7 @@ #define BL_SELECT_KEY "[TR4 Dn]" #define BL_EXIT_KEY "[TR4 Up]" #endif -#elif defined(RADIO_ST16) +#elif defined(RADIO_ST16) || defined(RADIO_C14) #define BL_SELECT_KEY "[ENT]" #define BL_EXIT_KEY "[EXIT]" #else diff --git a/radio/util/hw_defs/legacy_names.py b/radio/util/hw_defs/legacy_names.py index f2dad9fd5..354cc0f72 100644 --- a/radio/util/hw_defs/legacy_names.py +++ b/radio/util/hw_defs/legacy_names.py @@ -1013,7 +1013,7 @@ LEGACY_NAMES = [ }, }, { - "targets": {"st16"}, + "targets": {"st16","c14"}, "inputs": { "LH": {"yaml": "Rud", "lua": "rud", "description": "Rudder"}, "LV": {"yaml": "Ele", "lua": "ele", "description": "Elevator"}, diff --git a/tools/build-common.sh b/tools/build-common.sh index 3e04784ee..99276b986 100644 --- a/tools/build-common.sh +++ b/tools/build-common.sh @@ -164,6 +164,9 @@ get_target_build_options() { st16) BUILD_OPTIONS+="-DPCB=ST16" ;; + c14) + BUILD_OPTIONS+="-DPCB=C14" + ;; pa01) BUILD_OPTIONS+="-DPCB=PA01" ;; diff --git a/tools/build-iflight.py b/tools/build-iflight.py index f1ed66719..339684ae1 100644 --- a/tools/build-iflight.py +++ b/tools/build-iflight.py @@ -13,7 +13,12 @@ boards = { "PCBREV": "COMMANDO8", "DEFAULT_MODE": "1", "IFLIGHT_RELEASE": "YES", - } + }, + "C14": { + "PCB": "C14", + "DEFAULT_MODE": "1", + "IFLIGHT_RELEASE": "YES", + }, } diff --git a/tools/build-wasm-modules.sh b/tools/build-wasm-modules.sh index d24166c6e..0c83cabda 100755 --- a/tools/build-wasm-modules.sh +++ b/tools/build-wasm-modules.sh @@ -226,7 +226,7 @@ else tx12mk2 zorro v12 v14 v14lcd x7access x9dp2019 x9e # colour - el18 nb4p nv14 st16 pa01 + c14 el18 nb4p nv14 st16 pa01 pl18 pl18ev pl18u t15 t15pro t16 t18 t22 tx15 tx16s tx16smk3 f16 v16 diff --git a/tools/generate-hw-defs.sh b/tools/generate-hw-defs.sh index 17f315ad0..f20535d2f 100755 --- a/tools/generate-hw-defs.sh +++ b/tools/generate-hw-defs.sh @@ -9,7 +9,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" : "${SRCDIR:=$(dirname "$(pwd)/$0")/..}" -: ${FLAVOR:="nv14;el18;pl18;pl18ev;pl18u;nb4p;st16;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"} +: ${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"} : ${COMMON_OPTIONS:="-DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_RULE_MESSAGES=OFF -Wno-dev -DCMAKE_MESSAGE_LOG_LEVEL=WARNING"} # wipe build directory clean diff --git a/tools/generate-yaml.sh b/tools/generate-yaml.sh index c6bddf117..ca4413b18 100755 --- a/tools/generate-yaml.sh +++ b/tools/generate-yaml.sh @@ -11,7 +11,7 @@ if [[ -n ${GCC_ARM} ]] ; then export PATH=${GCC_ARM}:$PATH fi -: ${FLAVOR:="x10;t15;tx16s;pl18;nv14;pl18u;nb4p;x9d;x9dp2019;x9e;xlite;xlites;x7;tpro;t20;f16;gx12;st16;pa01;tx15;t15pro;tx16smk3;t22"} +: ${FLAVOR:="x10;t15;tx16s;pl18;nv14;pl18u;nb4p;x9d;x9dp2019;x9e;xlite;xlites;x7;tpro;t20;f16;gx12;st16;c14;pa01;tx15;t15pro;tx16smk3;t22"} : ${SRCDIR:=$(dirname "$(pwd)/$0")/..} : ${COMMON_OPTIONS:="-DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_RULE_MESSAGES=OFF -Wno-dev -DDISABLE_COMPANION=YES -DCMAKE_MESSAGE_LOG_LEVEL=WARNING"}