From 7a992a66315887a7ad0ac962d23cf588e28367df Mon Sep 17 00:00:00 2001 From: 3djc <3djc@gh.com> Date: Wed, 15 Jul 2026 11:11:00 +0200 Subject: [PATCH 1/3] feat: allows charge control when using USB Sd, joystick, or VCP mode. --- .../firmwares/edgetx/yaml_generalsettings.cpp | 2 ++ companion/src/firmwares/generalsettings.h | 1 + companion/src/generaledit/generalsetup.cpp | 18 +++++++++++ companion/src/generaledit/generalsetup.h | 1 + companion/src/generaledit/generalsetup.ui | 32 +++++++++++++------ .../src/boards/rm-h750/usb_charger_driver.cpp | 7 ++++ radio/src/datastructs_private.h | 7 ++++ radio/src/gui/colorlcd/radio/radio_setup.cpp | 10 ++++++ radio/src/main.cpp | 19 +++++++++++ .../storage/yaml/yaml_datastructs_tx15.cpp | 5 +-- .../yaml/yaml_datastructs_tx16smk3.cpp | 3 +- radio/src/targets/tx15/CMakeLists.txt | 1 + radio/src/targets/tx16smk3/CMakeLists.txt | 1 + radio/src/translations/i18n/cn.h | 1 + radio/src/translations/i18n/cz.h | 1 + radio/src/translations/i18n/da.h | 1 + radio/src/translations/i18n/de.h | 1 + radio/src/translations/i18n/en.h | 1 + radio/src/translations/i18n/es.h | 1 + radio/src/translations/i18n/fi.h | 1 + radio/src/translations/i18n/fr.h | 1 + radio/src/translations/i18n/he.h | 1 + radio/src/translations/i18n/it.h | 1 + radio/src/translations/i18n/jp.h | 1 + radio/src/translations/i18n/ko.h | 1 + radio/src/translations/i18n/nl.h | 1 + radio/src/translations/i18n/pl.h | 1 + radio/src/translations/i18n/pt.h | 1 + radio/src/translations/i18n/ru.h | 1 + radio/src/translations/i18n/se.h | 1 + radio/src/translations/i18n/tw.h | 1 + radio/src/translations/i18n/ua.h | 1 + radio/src/translations/sim_string_list.h | 1 + radio/src/translations/string_list.h | 1 + 34 files changed, 116 insertions(+), 12 deletions(-) diff --git a/companion/src/firmwares/edgetx/yaml_generalsettings.cpp b/companion/src/firmwares/edgetx/yaml_generalsettings.cpp index b148af4d16f..b7b24d23b8b 100644 --- a/companion/src/firmwares/edgetx/yaml_generalsettings.cpp +++ b/companion/src/firmwares/edgetx/yaml_generalsettings.cpp @@ -254,6 +254,7 @@ Node convert::encode(const GeneralSettings& rhs) node["disableRssiPoweroffAlarm"] = (int)rhs.disableRssiPoweroffAlarm; node["disableTrainerPoweroffAlarm"] = (int)rhs.disableTrainerPoweroffAlarm; node["USBMode"] = rhs.usbMode; + node["usbChargeDisabled"] = (int)rhs.usbChargeDisabled; node["hatsMode"] = hatsModeLut << rhs.hatsMode; node["stickDeadZone"] = rhs.stickDeadZone; node["jackMode"] = rhs.jackMode; @@ -542,6 +543,7 @@ bool convert::decode(const Node& node, GeneralSettings& rhs) node["disableRssiPoweroffAlarm"] >> rhs.disableRssiPoweroffAlarm; node["disableTrainerPoweroffAlarm"] >> rhs.disableTrainerPoweroffAlarm; node["USBMode"] >> rhs.usbMode; + node["usbChargeDisabled"] >> rhs.usbChargeDisabled; node["hatsMode"] >> hatsModeLut >> rhs.hatsMode; node["stickDeadZone"] >> rhs.stickDeadZone; node["jackMode"] >> rhs.jackMode; diff --git a/companion/src/firmwares/generalsettings.h b/companion/src/firmwares/generalsettings.h index e8873f90c88..14dad7e1277 100644 --- a/companion/src/firmwares/generalsettings.h +++ b/companion/src/firmwares/generalsettings.h @@ -318,6 +318,7 @@ class GeneralSettings { bool disableRssiPoweroffAlarm; bool disableTrainerPoweroffAlarm; unsigned int usbMode; + bool usbChargeDisabled; unsigned int hatsMode; unsigned int stickDeadZone; unsigned int jackMode; diff --git a/companion/src/generaledit/generalsetup.cpp b/companion/src/generaledit/generalsetup.cpp index abd60277ca5..23a5cb66a13 100644 --- a/companion/src/generaledit/generalsetup.cpp +++ b/companion/src/generaledit/generalsetup.cpp @@ -97,6 +97,16 @@ ui(new Ui::GeneralSetup) ui->adjustRTC->setChecked(generalSettings.adjustRTC); ui->usbModeCB->setCurrentIndex(generalSettings.usbMode); + // "USB SD/Joystick/VCP charge" is only available on RadioMaster radios + // that expose the charger-enable pin (rm-h750 based targets). + if (IS_RADIOMASTER_TX16SMK3(board) || IS_RADIOMASTER_TX15(board)) { + ui->usbChargeChkB->setChecked(!generalSettings.usbChargeDisabled); // Default is zero=checked + } + else { + ui->usbChargeLabel->hide(); + ui->usbChargeChkB->hide(); + } + if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board) || IS_FAMILY_PL18(board)) { ui->hatsModeCB->setModel(panelFilteredModels->getItemModel(FIM_HATSMODE)); ui->hatsModeCB->setField(generalSettings.hatsMode, this); @@ -375,6 +385,14 @@ void GeneralSetupPanel::on_usbModeCB_currentIndexChanged(int index) } } +void GeneralSetupPanel::on_usbChargeChkB_stateChanged(int) +{ + if (!lock) { + generalSettings.usbChargeDisabled = !ui->usbChargeChkB->isChecked(); + emit modified(); + } +} + void GeneralSetupPanel::on_jackModeCB_currentIndexChanged(int index) { if (!lock) { diff --git a/companion/src/generaledit/generalsetup.h b/companion/src/generaledit/generalsetup.h index 0aed9c92735..16c22f27b15 100644 --- a/companion/src/generaledit/generalsetup.h +++ b/companion/src/generaledit/generalsetup.h @@ -62,6 +62,7 @@ class GeneralSetupPanel : public GeneralPanel void on_hapticLengthCB_currentIndexChanged(int index); void on_backlightswCB_currentIndexChanged(int index); void on_usbModeCB_currentIndexChanged(int index); + void on_usbChargeChkB_stateChanged(int); void on_jackModeCB_currentIndexChanged(int index); void on_backlightColor_SL_valueChanged(); void on_mavbaud_CB_currentIndexChanged(int index); diff --git a/companion/src/generaledit/generalsetup.ui b/companion/src/generaledit/generalsetup.ui index b50148ce03e..ff778e19d4e 100644 --- a/companion/src/generaledit/generalsetup.ui +++ b/companion/src/generaledit/generalsetup.ui @@ -395,7 +395,7 @@ Mode 4: - + 0.-- @@ -417,7 +417,7 @@ Mode 4: - + @@ -509,7 +509,7 @@ Acceptable values are 3v..12v - + PPM Units @@ -862,7 +862,7 @@ p, li { white-space: pre-wrap; } - + @@ -905,6 +905,20 @@ p, li { white-space: pre-wrap; } + + + + USB SD/Joystick/VCP charge + + + + + + + + + + @@ -924,7 +938,7 @@ p, li { white-space: pre-wrap; } - + Hats Mode @@ -963,7 +977,7 @@ p, li { white-space: pre-wrap; } - + Jack Mode @@ -1085,7 +1099,7 @@ p, li { white-space: pre-wrap; } - + Qt::Orientation::Vertical @@ -1312,14 +1326,14 @@ p, li { white-space: pre-wrap; } - + One log per day - + diff --git a/radio/src/boards/rm-h750/usb_charger_driver.cpp b/radio/src/boards/rm-h750/usb_charger_driver.cpp index 5e01d872316..b00677abc2d 100644 --- a/radio/src/boards/rm-h750/usb_charger_driver.cpp +++ b/radio/src/boards/rm-h750/usb_charger_driver.cpp @@ -36,5 +36,12 @@ void usbChargerInit() bool usbChargerLed() { +#if defined(USB_CHARGE_CONTROL) + // When charging is disabled via the "USB SD/Joystick/VCP charge" setting, + // the charger-enable pin is driven high to hold the charger off, so it is + // not charging. + if (gpio_read(UCHARGER_EN_GPIO)) + return false; +#endif return (gpio_read(UCHARGER_GPIO) && usbPlugged()); } diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index e4ad3e0c49b..f9531dc3aa5 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -1169,7 +1169,14 @@ PACK(struct RadioData { // Radio level tabs control (global settings) NOBACKUP(uint8_t modelSelectLayout:2); NOBACKUP(uint8_t radioThemesDisabled:1); +#if defined(USB_CHARGE_CONTROL) + // 0 = charge while USB active (default), 1 = hold the charger off while USB + // is plugged in SD/Joystick/VCP mode + NOBACKUP(uint8_t usbChargeDisabled:1); + NOBACKUP(uint8_t spare:6 SKIP); +#else NOBACKUP(uint8_t spare:7 SKIP); +#endif #elif LCD_W == 128 uint8_t invertLCD:1; // Invert B&W LCD display NOBACKUP(uint8_t spare:4 SKIP); diff --git a/radio/src/gui/colorlcd/radio/radio_setup.cpp b/radio/src/gui/colorlcd/radio/radio_setup.cpp index f0f2956bf6f..17b1ae6690c 100644 --- a/radio/src/gui/colorlcd/radio/radio_setup.cpp +++ b/radio/src/gui/colorlcd/radio/radio_setup.cpp @@ -966,6 +966,16 @@ const static SetupLineDef setupLines[] = { GET_SET_DEFAULT(g_eeGeneral.USBMode)); } }, +#if defined(USB_CHARGE_CONTROL) + { + // USB SD/Joystick/VCP charge + STR_DEF(STR_USB_CHARGE), + [](Window* parent, coord_t x, coord_t y) { + new ToggleSwitch(parent, {x, y, 0, 0}, + GET_SET_INVERTED(g_eeGeneral.usbChargeDisabled)); + } + }, +#endif #if defined(ROTARY_ENCODER_NAVIGATION) && !defined(USE_HATS_AS_KEYS) { STR_DEF(STR_ROTARY_ENC_MODE), diff --git a/radio/src/main.cpp b/radio/src/main.cpp index ae0b95eb37c..9c68dbfed88 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -28,6 +28,11 @@ #include "edgetx.h" #include "lua/lua_states.h" +#if defined(USB_CHARGE_CONTROL) +#include "hal/gpio.h" +#include "stm32_gpio.h" +#endif + #if defined(COLORLCD) #include "view_main.h" #include "startup_shutdown.h" @@ -203,12 +208,26 @@ void handleUsbConnection() usbStart(); TRACE("USB started"); + +#if defined(USB_CHARGE_CONTROL) + // When "USB SD/Joystick/VCP charge" is set to OFF, disable charging by + // driving the charger-enable pin high while USB is active. + if (g_eeGeneral.usbChargeDisabled) { + gpio_set(UCHARGER_EN_GPIO); + } else { + gpio_clear(UCHARGER_EN_GPIO); + } +#endif } } if (usbStarted() && !usbPlugged()) { usbStop(); TRACE("USB stopped"); +#if defined(USB_CHARGE_CONTROL) + // Restore default charger-enable state on unplug + gpio_clear(UCHARGER_EN_GPIO); +#endif if (getSelectedUsbMode() == USB_MASS_STORAGE_MODE) { #if defined(COLORLCD) usbConnectedWindow->deleteLater(); diff --git a/radio/src/storage/yaml/yaml_datastructs_tx15.cpp b/radio/src/storage/yaml/yaml_datastructs_tx15.cpp index f578e329f3f..5ed336aa392 100644 --- a/radio/src/storage/yaml/yaml_datastructs_tx15.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_tx15.cpp @@ -455,7 +455,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr), YAML_UNSIGNED( "rotEncMode", 3 ), YAML_PADDING( 2 ), - YAML_UNSIGNED( "stickDeadZone", 3 ), + YAML_PADDING( 3 ), YAML_SIGNED( "imuMax", 8 ), YAML_SIGNED( "imuOffset", 8 ), YAML_UNSIGNED( "imuInvert", 8 ), @@ -482,7 +482,8 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "favMultiMode", 1 ), YAML_UNSIGNED( "modelSelectLayout", 2 ), YAML_UNSIGNED( "radioThemesDisabled", 1 ), - YAML_PADDING( 7 ), + YAML_UNSIGNED( "usbChargeDisabled", 1 ), + YAML_PADDING( 6 ), YAML_UNSIGNED( "pwrOffIfInactive", 8 ), YAML_ARRAY("keyShortcuts", 8, 6, struct_KeyShortcut, NULL), YAML_ARRAY("qmFavorites", 8, 12, struct_QMFavorite, NULL), diff --git a/radio/src/storage/yaml/yaml_datastructs_tx16smk3.cpp b/radio/src/storage/yaml/yaml_datastructs_tx16smk3.cpp index ab9899f688c..ec81463f339 100644 --- a/radio/src/storage/yaml/yaml_datastructs_tx16smk3.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_tx16smk3.cpp @@ -483,7 +483,8 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "favMultiMode", 1 ), YAML_UNSIGNED( "modelSelectLayout", 2 ), YAML_UNSIGNED( "radioThemesDisabled", 1 ), - YAML_PADDING( 7 ), + YAML_UNSIGNED( "usbChargeDisabled", 1 ), + YAML_PADDING( 6 ), YAML_UNSIGNED( "pwrOffIfInactive", 8 ), YAML_ARRAY("keyShortcuts", 8, 6, struct_KeyShortcut, NULL), YAML_ARRAY("qmFavorites", 8, 12, struct_QMFavorite, NULL), diff --git a/radio/src/targets/tx15/CMakeLists.txt b/radio/src/targets/tx15/CMakeLists.txt index 299fd8bbe5f..49fd5954497 100644 --- a/radio/src/targets/tx15/CMakeLists.txt +++ b/radio/src/targets/tx15/CMakeLists.txt @@ -62,6 +62,7 @@ add_definitions(-DFIRMWARE_QSPI) add_definitions(-DFIRMWARE_FORMAT_UF2) add_definitions(-DUSE_CUSTOM_EXTI_IRQ) add_definitions(-DUSB_CHARGER) +add_definitions(-DUSB_CHARGE_CONTROL) set(FLAVOUR tx15) add_definitions(-DMANUFACTURER_RADIOMASTER) diff --git a/radio/src/targets/tx16smk3/CMakeLists.txt b/radio/src/targets/tx16smk3/CMakeLists.txt index 113a5f8961f..edd0fae08fc 100644 --- a/radio/src/targets/tx16smk3/CMakeLists.txt +++ b/radio/src/targets/tx16smk3/CMakeLists.txt @@ -65,6 +65,7 @@ add_definitions(-DFIRMWARE_QSPI) add_definitions(-DFIRMWARE_FORMAT_UF2) add_definitions(-DUSE_CUSTOM_EXTI_IRQ) add_definitions(-DUSB_CHARGER) +add_definitions(-DUSB_CHARGE_CONTROL) add_definitions(-DLUMINOSITY_SENSOR) set(FLAVOUR tx16smk3) diff --git a/radio/src/translations/i18n/cn.h b/radio/src/translations/i18n/cn.h index db4b73e3e62..87a9a71b29a 100644 --- a/radio/src/translations/i18n/cn.h +++ b/radio/src/translations/i18n/cn.h @@ -989,6 +989,7 @@ #define TR_SENSOR "传感器" #define TR_COUNTRY_CODE "国别码" #define TR_USBMODE "USB模式" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "教练插口模式" #define TR_VOICE_LANGUAGE "播报语言" #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/i18n/cz.h b/radio/src/translations/i18n/cz.h index dc72408116b..98f7396934a 100644 --- a/radio/src/translations/i18n/cz.h +++ b/radio/src/translations/i18n/cz.h @@ -986,6 +986,7 @@ #define TR_SENSOR "SENZOR" #define TR_COUNTRY_CODE "Kód regionu" #define TR_USBMODE "Režim USB" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Režim Jack" #define TR_VOICE_LANGUAGE "Jazyk hlasu" #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/i18n/da.h b/radio/src/translations/i18n/da.h index 776f709c80c..3e716f183d5 100644 --- a/radio/src/translations/i18n/da.h +++ b/radio/src/translations/i18n/da.h @@ -994,6 +994,7 @@ #define TR_SENSOR "SENSOR" #define TR_COUNTRY_CODE "Lande kode" #define TR_USBMODE "USB tilstand" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Jack tilstand" #define TR_VOICE_LANGUAGE "Stemme sprog" #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/i18n/de.h b/radio/src/translations/i18n/de.h index fd52cdc38c5..06c9ede61d1 100644 --- a/radio/src/translations/i18n/de.h +++ b/radio/src/translations/i18n/de.h @@ -988,6 +988,7 @@ #define TR_SENSOR TR_BW_COL("SENSOR", "Sensor") #define TR_COUNTRY_CODE "Landescode" #define TR_USBMODE "USB Modus" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Klinken-Modus" #define TR_VOICE_LANGUAGE "Sprachansagen" #define TR_TEXT_LANGUAGE "Textsprache" diff --git a/radio/src/translations/i18n/en.h b/radio/src/translations/i18n/en.h index 14f4ce32f7c..26a85ddcfdc 100644 --- a/radio/src/translations/i18n/en.h +++ b/radio/src/translations/i18n/en.h @@ -990,6 +990,7 @@ #define TR_SENSOR "SENSOR" #define TR_COUNTRY_CODE "Country code" #define TR_USBMODE "USB mode" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Jack mode" #define TR_VOICE_LANGUAGE "Voice language" #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/i18n/es.h b/radio/src/translations/i18n/es.h index ce94ccd5ba2..b42cb473219 100644 --- a/radio/src/translations/i18n/es.h +++ b/radio/src/translations/i18n/es.h @@ -982,6 +982,7 @@ #define TR_SENSOR "SENSOR" #define TR_COUNTRY_CODE "Código país" #define TR_USBMODE "Modo USB" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Modo Jack" #define TR_VOICE_LANGUAGE "Idioma voces" #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/i18n/fi.h b/radio/src/translations/i18n/fi.h index 3584c47fa25..6fbe0af61b3 100644 --- a/radio/src/translations/i18n/fi.h +++ b/radio/src/translations/i18n/fi.h @@ -982,6 +982,7 @@ #define TR_SENSOR "SENSORI" #define TR_COUNTRY_CODE "Maatunnus" #define TR_USBMODE "USB-tila" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Jack Mode" #define TR_VOICE_LANGUAGE "Äänen kieli" #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/i18n/fr.h b/radio/src/translations/i18n/fr.h index eb3b8d608bf..1475560f4f0 100644 --- a/radio/src/translations/i18n/fr.h +++ b/radio/src/translations/i18n/fr.h @@ -986,6 +986,7 @@ #define TR_SENSOR "CAPTEUR" #define TR_COUNTRY_CODE TR("Zone géo.", "Zone géographique") #define TR_USBMODE "Mode USB" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Mode Jack" #define TR_VOICE_LANGUAGE TR("Langue voix", "Langue annonces vocales") #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/i18n/he.h b/radio/src/translations/i18n/he.h index e5628663db9..e2d0f4940c0 100644 --- a/radio/src/translations/i18n/he.h +++ b/radio/src/translations/i18n/he.h @@ -992,6 +992,7 @@ #define TR_SENSOR "חיישן" #define TR_COUNTRY_CODE "קוד ארץ" #define TR_USBMODE "USB מצב" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Jack mode" #define TR_VOICE_LANGUAGE "שפת שמע" #define TR_TEXT_LANGUAGE "שפת הטקסט" diff --git a/radio/src/translations/i18n/it.h b/radio/src/translations/i18n/it.h index 9e6fb85707d..734cf4a323a 100644 --- a/radio/src/translations/i18n/it.h +++ b/radio/src/translations/i18n/it.h @@ -989,6 +989,7 @@ #define TR_SENSOR "SENSORE" #define TR_COUNTRY_CODE TR("Cod. Paese", "Codice del Paese") #define TR_USBMODE "Modo USB" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Modo JACK" #define TR_VOICE_LANGUAGE "Lingua vocale" #define TR_TEXT_LANGUAGE "Lingua testo" diff --git a/radio/src/translations/i18n/jp.h b/radio/src/translations/i18n/jp.h index c86038997d1..409575fc07d 100644 --- a/radio/src/translations/i18n/jp.h +++ b/radio/src/translations/i18n/jp.h @@ -988,6 +988,7 @@ #define TR_SENSOR "センサー" #define TR_COUNTRY_CODE "カントリーコード" #define TR_USBMODE "USBモード" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Jackモード" #define TR_VOICE_LANGUAGE "音声言語" #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/i18n/ko.h b/radio/src/translations/i18n/ko.h index 690de444804..31ed2f1d4f2 100644 --- a/radio/src/translations/i18n/ko.h +++ b/radio/src/translations/i18n/ko.h @@ -1032,6 +1032,7 @@ #define TR_SENSOR "센서" #define TR_COUNTRY_CODE "국가 코드" #define TR_USBMODE "USB 모드" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "잭 모드" #define TR_VOICE_LANGUAGE "음성 언어" #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/i18n/nl.h b/radio/src/translations/i18n/nl.h index dddac376a38..f1fda36119e 100644 --- a/radio/src/translations/i18n/nl.h +++ b/radio/src/translations/i18n/nl.h @@ -984,6 +984,7 @@ #define TR_SENSOR "SENSOR" #define TR_COUNTRY_CODE "Landcode" #define TR_USBMODE "USB Mode" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Jack Mode" #define TR_VOICE_LANGUAGE "Taal" #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/i18n/pl.h b/radio/src/translations/i18n/pl.h index 9dab627e43a..2f956d69797 100644 --- a/radio/src/translations/i18n/pl.h +++ b/radio/src/translations/i18n/pl.h @@ -981,6 +981,7 @@ #define TR_SENSOR "SENSOR" #define TR_COUNTRY_CODE "Kod regionu" #define TR_USBMODE "Tryb USB" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Tryb Jack" #define TR_VOICE_LANGUAGE "Język głosu" #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/i18n/pt.h b/radio/src/translations/i18n/pt.h index 352cb13c89a..4132d25c95c 100644 --- a/radio/src/translations/i18n/pt.h +++ b/radio/src/translations/i18n/pt.h @@ -990,6 +990,7 @@ #define TR_SENSOR "SENSOR" #define TR_COUNTRY_CODE "Código pais" #define TR_USBMODE "Modo USB" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Jack mode" #define TR_VOICE_LANGUAGE "Idoma da Voz" #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/i18n/ru.h b/radio/src/translations/i18n/ru.h index 727b5caffff..635bcc2a85d 100644 --- a/radio/src/translations/i18n/ru.h +++ b/radio/src/translations/i18n/ru.h @@ -991,6 +991,7 @@ #define TR_SENSOR "СЕНСОР" #define TR_COUNTRY_CODE "Код страны" #define TR_USBMODE "Режим USB" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Режим разъема" #define TR_VOICE_LANGUAGE "Язык озвучки" #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/i18n/se.h b/radio/src/translations/i18n/se.h index a8097dcc4e1..9252a645849 100644 --- a/radio/src/translations/i18n/se.h +++ b/radio/src/translations/i18n/se.h @@ -989,6 +989,7 @@ #define TR_SENSOR "SENSOR" #define TR_COUNTRY_CODE "Landskod" #define TR_USBMODE "USB-läge" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Uttagsläge" #define TR_VOICE_LANGUAGE "Röstspråk" #define TR_TEXT_LANGUAGE "Textspråk" diff --git a/radio/src/translations/i18n/tw.h b/radio/src/translations/i18n/tw.h index fe90f0094dc..18c254b1347 100644 --- a/radio/src/translations/i18n/tw.h +++ b/radio/src/translations/i18n/tw.h @@ -986,6 +986,7 @@ #define TR_SENSOR "傳感器" #define TR_COUNTRY_CODE "國別碼" #define TR_USBMODE "USB模式" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "教練插口模式" #define TR_VOICE_LANGUAGE "播報語言" #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/i18n/ua.h b/radio/src/translations/i18n/ua.h index f0621b8effc..a6fe99db8f6 100644 --- a/radio/src/translations/i18n/ua.h +++ b/radio/src/translations/i18n/ua.h @@ -990,6 +990,7 @@ #define TR_SENSOR "СЕНСОР" #define TR_COUNTRY_CODE "Код країни" #define TR_USBMODE "Режим USB" +#define TR_USB_CHARGE "USB SD/Joystick/VCP charge" #define TR_JACK_MODE "Режим коннектора" #define TR_VOICE_LANGUAGE "Мова голосу" #define TR_TEXT_LANGUAGE "Text language" diff --git a/radio/src/translations/sim_string_list.h b/radio/src/translations/sim_string_list.h index f3a9c7cd477..1895489cb22 100644 --- a/radio/src/translations/sim_string_list.h +++ b/radio/src/translations/sim_string_list.h @@ -1044,6 +1044,7 @@ #define STR_UPDATE_RX_OPTIONS currentLangStrings->STR_UPDATE_RX_OPTIONS #define STR_UPDATE_TX_OPTIONS currentLangStrings->STR_UPDATE_TX_OPTIONS #define STR_US currentLangStrings->STR_US +#define STR_USB_CHARGE currentLangStrings->STR_USB_CHARGE #define STR_USB_JOYSTICK currentLangStrings->STR_USB_JOYSTICK #define STR_USB_MASS_STORAGE currentLangStrings->STR_USB_MASS_STORAGE #define STR_USB_SERIAL currentLangStrings->STR_USB_SERIAL diff --git a/radio/src/translations/string_list.h b/radio/src/translations/string_list.h index 641b077df19..0a84c1a65fc 100644 --- a/radio/src/translations/string_list.h +++ b/radio/src/translations/string_list.h @@ -1048,6 +1048,7 @@ STR(UNSUPPORTED_RX) STR(UPDATE_RX_OPTIONS) STR(UPDATE_TX_OPTIONS) STR(US) +STR(USB_CHARGE) STR(USB_JOYSTICK) STR(USB_MASS_STORAGE) STR(USB_SERIAL) From 01b2e4999304cc0a299f998335f75ed5f8abd8ff Mon Sep 17 00:00:00 2001 From: 3djc <3djc@gh.com> Date: Thu, 16 Jul 2026 13:21:29 +0200 Subject: [PATCH 2/3] fix: native compilation --- radio/src/boards/rm-h750/board.h | 4 ++++ radio/src/boards/rm-h750/usb_charger_driver.cpp | 10 +++++++++- radio/src/main.cpp | 16 ++-------------- radio/src/targets/simu/led_driver.cpp | 3 +++ 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/radio/src/boards/rm-h750/board.h b/radio/src/boards/rm-h750/board.h index 46f4ef02f46..a987c59600c 100644 --- a/radio/src/boards/rm-h750/board.h +++ b/radio/src/boards/rm-h750/board.h @@ -241,4 +241,8 @@ void usbChargerInit(); bool usbChargerLed(); #endif +#if defined(USB_CHARGE_CONTROL) +void usbChargerEnableCharge(bool enable); +#endif + #endif // _BOARD_H_ diff --git a/radio/src/boards/rm-h750/usb_charger_driver.cpp b/radio/src/boards/rm-h750/usb_charger_driver.cpp index b00677abc2d..426e0f5373c 100644 --- a/radio/src/boards/rm-h750/usb_charger_driver.cpp +++ b/radio/src/boards/rm-h750/usb_charger_driver.cpp @@ -25,7 +25,15 @@ #include "board.h" #include "hal/usb_driver.h" -//TODO: charger enable control + #if defined(USB_CHARGE_CONTROL) +void usbChargerEnableCharge(bool enable) +{ + if (enable) + gpio_clear(UCHARGER_EN_GPIO); + else + gpio_set(UCHARGER_EN_GPIO); +} +#endif void usbChargerInit() { diff --git a/radio/src/main.cpp b/radio/src/main.cpp index 9c68dbfed88..f3af6529a0f 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -28,11 +28,6 @@ #include "edgetx.h" #include "lua/lua_states.h" -#if defined(USB_CHARGE_CONTROL) -#include "hal/gpio.h" -#include "stm32_gpio.h" -#endif - #if defined(COLORLCD) #include "view_main.h" #include "startup_shutdown.h" @@ -210,13 +205,7 @@ void handleUsbConnection() TRACE("USB started"); #if defined(USB_CHARGE_CONTROL) - // When "USB SD/Joystick/VCP charge" is set to OFF, disable charging by - // driving the charger-enable pin high while USB is active. - if (g_eeGeneral.usbChargeDisabled) { - gpio_set(UCHARGER_EN_GPIO); - } else { - gpio_clear(UCHARGER_EN_GPIO); - } + usbChargerEnableCharge(!g_eeGeneral.usbChargeDisabled); #endif } } @@ -225,8 +214,7 @@ void handleUsbConnection() usbStop(); TRACE("USB stopped"); #if defined(USB_CHARGE_CONTROL) - // Restore default charger-enable state on unplug - gpio_clear(UCHARGER_EN_GPIO); + usbChargerEnableCharge(true); #endif if (getSelectedUsbMode() == USB_MASS_STORAGE_MODE) { #if defined(COLORLCD) diff --git a/radio/src/targets/simu/led_driver.cpp b/radio/src/targets/simu/led_driver.cpp index 8c921375b07..7433c0829ba 100644 --- a/radio/src/targets/simu/led_driver.cpp +++ b/radio/src/targets/simu/led_driver.cpp @@ -24,6 +24,9 @@ #include "definitions.h" bool usbChargerLed() { return true; } +#if defined(USB_CHARGE_CONTROL) +void usbChargerEnableCharge(bool enable) {} +#endif void ledRed() {} void ledGreen() {} void ledBlue() {} From d246a9ded64a51902e9818502a82d4b355a38591 Mon Sep 17 00:00:00 2001 From: 3djc <3djc@gh.com> Date: Thu, 6 Aug 2026 09:24:08 +0200 Subject: [PATCH 3/3] fix: apply USB charge setting on plug, not on mode selection The charger was left enabled while the USB mode popup was open, so the radio charged until a mode was picked. The unplug restore had the mirror problem: it sat in the usbStarted() branch, so unplugging from the popup never re-enabled charging. Co-Authored-By: Claude Opus 5 --- radio/src/main.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/radio/src/main.cpp b/radio/src/main.cpp index f3af6529a0f..57f1279182a 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -171,10 +171,18 @@ void handleUsbConnection() TRACE("USB unplugged"); closeUsbMenu(); _pluggedUsb = false; +#if defined(USB_CHARGE_CONTROL) + usbChargerEnableCharge(true); +#endif } else if (!_pluggedUsb && usbPlugged()) { TRACE("USB plugged"); _pluggedUsb = true; _usbDisabled = false; +#if defined(USB_CHARGE_CONTROL) + // Apply on plug, not on usbStart(): the mode popup can sit open for a long + // time and the radio would charge until a mode is picked + usbChargerEnableCharge(!g_eeGeneral.usbChargeDisabled); +#endif } if (!_usbDisabled && !usbStarted() && usbPlugged()) { @@ -203,19 +211,12 @@ void handleUsbConnection() usbStart(); TRACE("USB started"); - -#if defined(USB_CHARGE_CONTROL) - usbChargerEnableCharge(!g_eeGeneral.usbChargeDisabled); -#endif } } if (usbStarted() && !usbPlugged()) { usbStop(); TRACE("USB stopped"); -#if defined(USB_CHARGE_CONTROL) - usbChargerEnableCharge(true); -#endif if (getSelectedUsbMode() == USB_MASS_STORAGE_MODE) { #if defined(COLORLCD) usbConnectedWindow->deleteLater();