diff --git a/radio/src/gui/common/stdlcd/menus_common.h b/radio/src/gui/common/stdlcd/menus_common.h index dff3e5f0f01..8f671052436 100644 --- a/radio/src/gui/common/stdlcd/menus_common.h +++ b/radio/src/gui/common/stdlcd/menus_common.h @@ -140,6 +140,7 @@ void menuRadioSpectrumAnalyser(event_t event); void menuRadioPowerMeter(event_t event); void menuRadioCalibration(event_t event); void menuGhostModuleConfig(event_t event); +void menuServoPwmTool(event_t event); void menuModelSelect(event_t event); void menuModelSetup(event_t event); diff --git a/radio/src/gui/common/stdlcd/radio_servo_pwm.cpp b/radio/src/gui/common/stdlcd/radio_servo_pwm.cpp new file mode 100644 index 00000000000..3afa4db0653 --- /dev/null +++ b/radio/src/gui/common/stdlcd/radio_servo_pwm.cpp @@ -0,0 +1,93 @@ +/* + * 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 "os/sleep.h" + +#if defined(SERVO_PWM) + +#if LCD_W >= 212 + #define HW_SETTINGS_COLUMN1 12*FW + #define HW_SETTINGS_COLUMN2 (20*FW - 3) + #define HW_SETTINGS_COLUMN3 HW_SETTINGS_COLUMN2 +#else + #define HW_SETTINGS_COLUMN1 30 + #define HW_SETTINGS_COLUMN2 (HW_SETTINGS_COLUMN1 + 5*FW) + #define HW_SETTINGS_COLUMN3 HW_SETTINGS_COLUMN2 + FW +#endif + +#if !defined(SIMU) +extern void pwmOutputDisable(); +extern void pwmOutputInit(); +extern void pwmOutputEnable(uint16_t pulse_width_us); +#else +void pwmOutputDisable() {} +void pwmOutputInit() {} +void pwmOutputEnable(uint16_t) {} +#endif + +static uint8_t pwmOutputSource; + +enum { + ITEM_PWM_SOURCE, + ITEM_SERVO_PWM_MAX, +}; + +void menuServoPwmTool(event_t event) +{ + SUBMENU(STR_PWM_OUTPUT, 0, {0}); + + if (menuEvent == EVT_ENTRY_UP) { + TRACE("stopping servo pwm..."); + pwmOutputDisable(); + return; + } + + if (event == EVT_ENTRY) { + TRACE("starting servo pwm..."); + pwmOutputSource = MIXSRC_NONE; + pwmOutputInit(); + } + + if (pwmOutputSource > MIXSRC_NONE) { + mixsrc_t chan = pwmOutputSource - MIXSRC_FIRST; + pwmOutputEnable(PPM_CH_CENTER(chan) + channelOutputs[chan] / 2); + } else { + pwmOutputDisable(); + } + + for (int i = 0; i < ITEM_SERVO_PWM_MAX; i++) { + LcdFlags attr = (menuVerticalPosition == i ? (s_editMode > 0 ? INVERS | BLINK : INVERS) : 0); + coord_t y = MENU_HEADER_HEIGHT + 12 + i * FH; + + switch (i) { + case ITEM_PWM_SOURCE: + lcdDrawTextAlignedLeft(y, STR_PWM_OUTPUT); + drawSource(HW_SETTINGS_COLUMN2, y, pwmOutputSource, attr); + if (attr & BLINK) + CHECK_INCDEC_GENVAR(event, pwmOutputSource, 0, MAX_OUTPUT_CHANNELS); + break; + } + } +} + +#endif + diff --git a/radio/src/gui/common/stdlcd/radio_tools.cpp b/radio/src/gui/common/stdlcd/radio_tools.cpp index 108f41ced66..9b8bed0a4ac 100644 --- a/radio/src/gui/common/stdlcd/radio_tools.cpp +++ b/radio/src/gui/common/stdlcd/radio_tools.cpp @@ -214,6 +214,10 @@ void menuRadioTools(event_t event) addRadioModuleToolHandler(index++, "Ghost Menu", menuGhostModuleConfig, EXTERNAL_MODULE); #endif +#if defined(SERVO_PWM) + addRadioModuleToolHandler(index++, STR_PWM_OUTPUT, menuServoPwmTool, 0); +#endif + #endif if (index == 0) { diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt index d5dfddaeccf..b57953b9eb3 100644 --- a/radio/src/targets/taranis/CMakeLists.txt +++ b/radio/src/targets/taranis/CMakeLists.txt @@ -696,6 +696,15 @@ if(FLAVOUR STREQUAL xlites) ) endif() +if(FLAVOUR STREQUAL mt12) + target_sources(board PRIVATE + ${TARGET_SRC_DIR}/pwm_ch_driver.cpp + ) + set(SRC ${SRC} + gui/common/stdlcd/radio_servo_pwm.cpp + ) +endif() + set(SRC ${SRC} io/frsky_firmware_update.cpp io/multi_firmware_update.cpp diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index e89d43e3e56..49039cdf582 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -2879,6 +2879,17 @@ #define HAPTIC_GPIO GPIO_PIN(GPIOC, 12) // PC.12 #endif +#if defined(RADIO_MT12) + #define SERVO_PWM + #define PWM_GPIO GPIO_PIN(GPIOB, 0) // PB.00 + #define PWM_GPIO_AF GPIO_AF2 + #define PWM_GPIO_TIMER TIM3 // Timer 3 Channel3 + #define PWM_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2) + #define PWM_COUNTER_REGISTER PWM_TIMER->CCR3 + #define PWM_CCMR2 TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2 + #define PWM_CCER TIM_CCER_CC3E +#endif + #if defined(RADIO_BOXER) || defined(RADIO_FAMILY_T20) || defined(RADIO_X9DP2019) || defined (RADIO_V14) || defined(RADIO_GX12) // Flysky Hall Stick #define FLYSKY_HALL_SERIAL_USART UART4 diff --git a/radio/src/targets/taranis/pwm_ch_driver.cpp b/radio/src/targets/taranis/pwm_ch_driver.cpp new file mode 100644 index 00000000000..0a542594a67 --- /dev/null +++ b/radio/src/targets/taranis/pwm_ch_driver.cpp @@ -0,0 +1,59 @@ +/* +* 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_pulse_driver.h" +#include "stm32_gpio.h" + +#include "edgetx_types.h" +#include "board.h" + +static const stm32_pulse_timer_t _pwm_timer = { + .GPIO = (gpio_t)PWM_GPIO, + .GPIO_Alternate = PWM_GPIO_AF, + .TIMx = PWM_GPIO_TIMER, + .TIM_Freq = PWM_TIMER_FREQ, + .TIM_Channel = LL_TIM_CHANNEL_CH3, + .TIM_IRQn = (IRQn_Type)-1, + .DMAx = nullptr, + .DMA_Stream = 0, + .DMA_Channel = 0, + .DMA_IRQn = (IRQn_Type)-1, + .DMA_TC_CallbackPtr = nullptr, +}; + +void pwmOutputDisable() +{ + stm32_pulse_stop(&_pwm_timer); +} + +void pwmOutputInit() +{ + stm32_pulse_init(&_pwm_timer, 2000000); + stm32_pulse_config_output(&_pwm_timer, true, LL_TIM_OCMODE_PWM1, 0); + LL_TIM_SetAutoReload(_pwm_timer.TIMx, 15000); // 15ms between PWM pulses + LL_TIM_EnableCounter(_pwm_timer.TIMx); +} + +void pwmOutputEnable(uint16_t pulse_width_us) +{ + stm32_pulse_set_cmp_val(&_pwm_timer, pulse_width_us); + stm32_pulse_start(&_pwm_timer); +} diff --git a/radio/src/translations/i18n/cn.h b/radio/src/translations/i18n/cn.h index 0ed345a73f7..0c66e70b1c2 100644 --- a/radio/src/translations/i18n/cn.h +++ b/radio/src/translations/i18n/cn.h @@ -1243,6 +1243,7 @@ #define TR_MENU_OTHER "其它" #define TR_MENU_INVERT "反向" #define TR_AUDIO_MUTE TR("自动静音","音频停播时自动静音") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "ADC滤波器" #define TR_DEAD_ZONE "死区" #define TR_RTC_CHECK TR("RTC电池", "RTC纽扣电池电压") diff --git a/radio/src/translations/i18n/cz.h b/radio/src/translations/i18n/cz.h index d1907fc12d4..583debb4625 100644 --- a/radio/src/translations/i18n/cz.h +++ b/radio/src/translations/i18n/cz.h @@ -1247,6 +1247,7 @@ #define TR_MENU_OTHER "Ostatní" #define TR_MENU_INVERT "Invertovat" #define TR_AUDIO_MUTE TR("Ztlumení zvuku","Ztlumení, pokud není slyšet zvuk") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "ADC Filtr" #define TR_DEAD_ZONE "Dead zone" #define TR_RTC_CHECK TR("Kontr RTC", "Hlídat RTC napětí") diff --git a/radio/src/translations/i18n/da.h b/radio/src/translations/i18n/da.h index dc5231853fe..2abc7bbcbbe 100644 --- a/radio/src/translations/i18n/da.h +++ b/radio/src/translations/i18n/da.h @@ -1250,6 +1250,7 @@ #define TR_MENU_OTHER "Andet" #define TR_MENU_INVERT "Invers" #define TR_AUDIO_MUTE TR("Audio fra","Audio fra, hvis der ikke gives lyd") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "ADC filter" #define TR_DEAD_ZONE "Dødt område" #define TR_RTC_CHECK TR("Check RTC", "Check RTC spænding") diff --git a/radio/src/translations/i18n/de.h b/radio/src/translations/i18n/de.h index 2b2ec6f33b3..9ab83958b0f 100644 --- a/radio/src/translations/i18n/de.h +++ b/radio/src/translations/i18n/de.h @@ -1246,6 +1246,7 @@ #define TR_MENU_OTHER "Weitere" #define TR_MENU_INVERT "Invertieren" #define TR_AUDIO_MUTE TR("Ton Stumm","Geräuschunterdrückung") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "ADC Filter" #define TR_DEAD_ZONE "Dead zone" #define TR_RTC_CHECK TR("RTC Prüfen", "RTC Spann. prüfen") diff --git a/radio/src/translations/i18n/en.h b/radio/src/translations/i18n/en.h index 6a7c272d41b..ff08b53d087 100644 --- a/radio/src/translations/i18n/en.h +++ b/radio/src/translations/i18n/en.h @@ -1244,6 +1244,7 @@ #define TR_MENU_OTHER "Other" #define TR_MENU_INVERT "Invert" #define TR_AUDIO_MUTE TR("Audio mute","Mute if no sound") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "ADC filter" #define TR_DEAD_ZONE "Dead zone" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") diff --git a/radio/src/translations/i18n/es.h b/radio/src/translations/i18n/es.h index edb7e8916e5..0485c2eaab7 100644 --- a/radio/src/translations/i18n/es.h +++ b/radio/src/translations/i18n/es.h @@ -1245,6 +1245,7 @@ #define TR_MENU_OTHER "Otros" #define TR_MENU_INVERT "Invertir" #define TR_AUDIO_MUTE TR("Audio mute","Mute if no sound") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "Filtro ADC" #define TR_DEAD_ZONE "Dead zone" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltaje") diff --git a/radio/src/translations/i18n/fi.h b/radio/src/translations/i18n/fi.h index 2ce0cffe9de..50de824a42c 100644 --- a/radio/src/translations/i18n/fi.h +++ b/radio/src/translations/i18n/fi.h @@ -1245,6 +1245,7 @@ #define TR_MENU_OTHER "Other" #define TR_MENU_INVERT "Invert" #define TR_AUDIO_MUTE TR("Audio mute","Mute if no sound") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "ADC Filter" #define TR_DEAD_ZONE "Dead zone" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") diff --git a/radio/src/translations/i18n/fr.h b/radio/src/translations/i18n/fr.h index 7b95ef2ad7b..f7d8fae4e66 100644 --- a/radio/src/translations/i18n/fr.h +++ b/radio/src/translations/i18n/fr.h @@ -1247,6 +1247,7 @@ #define TR_MENU_OTHER "Autres" #define TR_MENU_INVERT "Inverser" #define TR_AUDIO_MUTE TR("Audio muet","Muet si pas de son") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "Filtre ADC" #define TR_DEAD_ZONE "Zone Neutre" #define TR_RTC_CHECK TR("Vérif. RTC", "Vérif. pile RTC") diff --git a/radio/src/translations/i18n/he.h b/radio/src/translations/i18n/he.h index 9618607c3c1..814ae153474 100644 --- a/radio/src/translations/i18n/he.h +++ b/radio/src/translations/i18n/he.h @@ -1246,6 +1246,7 @@ #define TR_MENU_OTHER "Other" #define TR_MENU_INVERT "Invert" #define TR_AUDIO_MUTE TR("השתקת קול","השתק כאשר אין סאונד") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "ADC filter" #define TR_DEAD_ZONE "Dead zone" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") diff --git a/radio/src/translations/i18n/it.h b/radio/src/translations/i18n/it.h index bdb0cd75b9c..a7e53a2a8c8 100644 --- a/radio/src/translations/i18n/it.h +++ b/radio/src/translations/i18n/it.h @@ -1243,6 +1243,7 @@ #define TR_MENU_OTHER "Altro" #define TR_MENU_INVERT "Inverti" #define TR_AUDIO_MUTE TR("Audio muto","Muto senza suono") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "Filtro ADC" #define TR_DEAD_ZONE "Zona morta" #define TR_RTC_CHECK TR("Controllo RTC", "Controllo volt. RTC") diff --git a/radio/src/translations/i18n/jp.h b/radio/src/translations/i18n/jp.h index c80404c76b1..50742271d00 100644 --- a/radio/src/translations/i18n/jp.h +++ b/radio/src/translations/i18n/jp.h @@ -1242,6 +1242,7 @@ #define TR_MENU_OTHER "その他" #define TR_MENU_INVERT "リバース" #define TR_AUDIO_MUTE TR("Audio mute","音源ミュート") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "ADCフィルター" #define TR_DEAD_ZONE "デッドゾーン" #define TR_RTC_CHECK TR("Check RTC", "内蔵電池チェック") diff --git a/radio/src/translations/i18n/ko.h b/radio/src/translations/i18n/ko.h index 8575e9ebe85..cb27fcf6b36 100644 --- a/radio/src/translations/i18n/ko.h +++ b/radio/src/translations/i18n/ko.h @@ -1290,6 +1290,7 @@ #define TR_MENU_OTHER "기타" #define TR_MENU_INVERT "반전" #define TR_AUDIO_MUTE TR("오디오 음소거", "소리가 없을 때 음소거") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "ADC 필터" #define TR_DEAD_ZONE "데드존" #define TR_RTC_CHECK TR("RTC 확인", "RTC 전압 확인") diff --git a/radio/src/translations/i18n/nl.h b/radio/src/translations/i18n/nl.h index d087015572d..b42b9ca87bc 100644 --- a/radio/src/translations/i18n/nl.h +++ b/radio/src/translations/i18n/nl.h @@ -1246,6 +1246,7 @@ #define TR_MENU_OTHER "Verdere" #define TR_MENU_INVERT "Inverteer" #define TR_AUDIO_MUTE TR("Audio mute","Mute if no sound") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "ADC Filter" #define TR_DEAD_ZONE "Dead zone" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") diff --git a/radio/src/translations/i18n/pl.h b/radio/src/translations/i18n/pl.h index 02d11733a8a..69c3a56f7a0 100644 --- a/radio/src/translations/i18n/pl.h +++ b/radio/src/translations/i18n/pl.h @@ -1242,7 +1242,8 @@ #define TR_MENU_DISPLAY "DISPLAY" #define TR_MENU_OTHER "Inny " #define TR_MENU_INVERT "Odwróć" -#define TR_AUDIO_MUTE TR("Audio mute","Mute if no sound") +#define TR_AUDIO_MUTE TR("Audio mute","Mute if no sound") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "Filtr ADC" #define TR_DEAD_ZONE "Dead zone" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") diff --git a/radio/src/translations/i18n/pt.h b/radio/src/translations/i18n/pt.h index ec6d9f6969b..9bc6f7b0ac1 100644 --- a/radio/src/translations/i18n/pt.h +++ b/radio/src/translations/i18n/pt.h @@ -1244,6 +1244,7 @@ #define TR_MENU_OTHER "Outros" #define TR_MENU_INVERT "Invert" #define TR_AUDIO_MUTE TR("Audio mute","Mute if no sound") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "Filtro ADC" #define TR_DEAD_ZONE "Dead zone" #define TR_RTC_CHECK TR("Check RTC", "Checar tensão RTC") diff --git a/radio/src/translations/i18n/ru.h b/radio/src/translations/i18n/ru.h index 917a47ed99b..a2b7728f071 100644 --- a/radio/src/translations/i18n/ru.h +++ b/radio/src/translations/i18n/ru.h @@ -1245,6 +1245,7 @@ #define TR_MENU_OTHER "Другое" #define TR_MENU_INVERT "Инвертир" #define TR_AUDIO_MUTE TR("Выкл звук", "Выкл звук") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "Фильтр АЦП" #define TR_DEAD_ZONE "Зона нечувств" #define TR_RTC_CHECK TR("Проверка RTC", "Проверка RTC") diff --git a/radio/src/translations/i18n/se.h b/radio/src/translations/i18n/se.h index 49e9821e857..c1e80c2d772 100644 --- a/radio/src/translations/i18n/se.h +++ b/radio/src/translations/i18n/se.h @@ -1258,6 +1258,7 @@ #define TR_MENU_OTHER "Övrigt" #define TR_MENU_INVERT "Invertera" #define TR_AUDIO_MUTE TR("Audio av","Audio av om inget ljud") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "ADC-filter" #define TR_DEAD_ZONE "Dödläge" #define TR_RTC_CHECK TR("Kolla RTC", "Kolla RTC-batteriet") diff --git a/radio/src/translations/i18n/tw.h b/radio/src/translations/i18n/tw.h index 2223fa8df8b..267d25750cc 100644 --- a/radio/src/translations/i18n/tw.h +++ b/radio/src/translations/i18n/tw.h @@ -1241,6 +1241,7 @@ #define TR_MENU_OTHER "其它" #define TR_MENU_INVERT "反向" #define TR_AUDIO_MUTE TR("自動靜音","音頻停播時自動靜音") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "ADC濾波器" #define TR_DEAD_ZONE "死區" #define TR_RTC_CHECK TR("檢查時間電池", "檢查時間驅動電池電壓") diff --git a/radio/src/translations/i18n/ua.h b/radio/src/translations/i18n/ua.h index edf89846140..8b84e7208d3 100644 --- a/radio/src/translations/i18n/ua.h +++ b/radio/src/translations/i18n/ua.h @@ -1244,6 +1244,7 @@ #define TR_MENU_OTHER "Інше" #define TR_MENU_INVERT "Інверт" #define TR_AUDIO_MUTE TR("Аудіо стоп","Тихо якщо немає звуку") +#define TR_PWM_OUTPUT "PWM output" #define TR_JITTER_FILTER "Фільтр ADC" #define TR_DEAD_ZONE "Мертва зона" #define TR_RTC_CHECK TR("Перевір RTC", "Перевір напругу RTC") diff --git a/radio/src/translations/string_list.h b/radio/src/translations/string_list.h index 9430d859a18..bf5568ae42f 100644 --- a/radio/src/translations/string_list.h +++ b/radio/src/translations/string_list.h @@ -795,6 +795,7 @@ STR(MENU_DISPLAY) STR(MENU_OTHER) STR(MENU_INVERT) STR(AUDIO_MUTE) +STR(PWM_OUTPUT) STR(JITTER_FILTER) STR(DEAD_ZONE) STR(RTC_CHECK)