From 65e05085a447c4007ffee131223a6ffa04713f7e Mon Sep 17 00:00:00 2001 From: philmoz Date: Thu, 6 Jun 2024 07:52:45 +1000 Subject: [PATCH] feat(bw128): add option to invert LCD/OLED display (#4933) --- .../firmwares/edgetx/yaml_generalsettings.cpp | 3 + companion/src/firmwares/generalsettings.h | 2 + companion/src/generaledit/generalsetup.cpp | 13 + companion/src/generaledit/generalsetup.h | 1 + companion/src/generaledit/generalsetup.ui | 372 +++++++++--------- radio/src/datastructs_private.h | 5 +- .../src/gui/common/stdlcd/radio_hardware.cpp | 24 ++ radio/src/storage/sdcard_yaml.cpp | 6 +- .../storage/yaml/yaml_datastructs_128x64.cpp | 3 +- .../src/storage/yaml/yaml_datastructs_t20.cpp | 3 +- .../storage/yaml/yaml_datastructs_tpro.cpp | 3 +- .../storage/yaml/yaml_datastructs_xlites.cpp | 3 +- radio/src/targets/simu/simpgmspace.cpp | 6 + radio/src/targets/taranis/board.h | 3 + radio/src/targets/taranis/lcd_driver_spi.cpp | 7 + 15 files changed, 269 insertions(+), 185 deletions(-) diff --git a/companion/src/firmwares/edgetx/yaml_generalsettings.cpp b/companion/src/firmwares/edgetx/yaml_generalsettings.cpp index bd8b61fde3a..edc4112e0c5 100644 --- a/companion/src/firmwares/edgetx/yaml_generalsettings.cpp +++ b/companion/src/firmwares/edgetx/yaml_generalsettings.cpp @@ -261,6 +261,8 @@ Node convert::encode(const GeneralSettings& rhs) node["labelSingleSelect"] = rhs.labelSingleSelect; node["labelMultiMode"] = rhs.labelMultiMode; node["favMultiMode"] = rhs.favMultiMode; + } else if (fw->getCapability(LcdWidth) == 128) { + node["invertLCD"] = (int)rhs.invertLCD; } Node serialPort; @@ -513,6 +515,7 @@ bool convert::decode(const Node& node, GeneralSettings& rhs) node["backgroundVolume"] >> ioffset_int(rhs.backgroundVolume, 2); node["modelQuickSelect"] >> rhs.modelQuickSelect; node["dontPlayHello"] >> rhs.dontPlayHello; + node["invertLCD"] >> rhs.invertLCD; // depreciated v2.7 replaced by serialPort if (node["auxSerialMode"]) { diff --git a/companion/src/firmwares/generalsettings.h b/companion/src/firmwares/generalsettings.h index f217f0488e5..80243652dd2 100644 --- a/companion/src/firmwares/generalsettings.h +++ b/companion/src/firmwares/generalsettings.h @@ -318,6 +318,8 @@ class GeneralSettings { int labelMultiMode; int favMultiMode; + bool invertLCD; + // v 2.10 ADC refactor // earlier version data is read into legacy structs to maintain older version compatibility // post reading the legacy structs are manipulated into the new structs diff --git a/companion/src/generaledit/generalsetup.cpp b/companion/src/generaledit/generalsetup.cpp index 9e44a6d2b2e..7845d655f01 100644 --- a/companion/src/generaledit/generalsetup.cpp +++ b/companion/src/generaledit/generalsetup.cpp @@ -533,6 +533,13 @@ void GeneralSetupPanel::setValues() ui->label_favMultiMode->hide(); ui->favMultiMode_CB->hide(); } + + if (firmware->getCapability(LcdWidth) == 128) { + ui->invertLCD_CB->setChecked(generalSettings.invertLCD); + } else { + ui->invertLCD_label->hide(); + ui->invertLCD_CB->hide(); + } } void GeneralSetupPanel::showLabelSelectOptions() @@ -928,3 +935,9 @@ void GeneralSetupPanel::on_startSoundCB_stateChanged(int) generalSettings.dontPlayHello = !ui->startSoundCB->isChecked(); emit modified(); } + +void GeneralSetupPanel::on_invertLCD_CB_stateChanged(int) +{ + generalSettings.invertLCD = ui->invertLCD_CB->isChecked(); + emit modified(); +} diff --git a/companion/src/generaledit/generalsetup.h b/companion/src/generaledit/generalsetup.h index cd0a84c9051..80078afd069 100644 --- a/companion/src/generaledit/generalsetup.h +++ b/companion/src/generaledit/generalsetup.h @@ -100,6 +100,7 @@ class GeneralSetupPanel : public GeneralPanel void on_labelSingleSelect_CB_currentIndexChanged(int); void on_labelMultiMode_CB_currentIndexChanged(int); void on_favMultiMode_CB_currentIndexChanged(int); + void on_invertLCD_CB_stateChanged(int); private: Ui::GeneralSetup *ui; diff --git a/companion/src/generaledit/generalsetup.ui b/companion/src/generaledit/generalsetup.ui index a94331848e2..573b10ce8b2 100644 --- a/companion/src/generaledit/generalsetup.ui +++ b/companion/src/generaledit/generalsetup.ui @@ -7,7 +7,7 @@ 0 0 858 - 992 + 1018 @@ -554,105 +554,13 @@ - - - - Label selection mode - - - - - - - Label matching - - - - - - - Backlight OFF Brightness - - - - - - - - 0 - 0 - - - - 23 - - - - - - - - Large image (2 columns) - - - - - Small image (3 columns) - - - - - Name only (2 columns) - - - - - Name only (1 column) - - - - - - - - - Beeper - - - - - Speaker - - - - - BeeperVoice - - - - - SpeakerVoice - - - + + - - - - - 0 - 0 - - + + - Stick reverse - - - - - - - 8 + Voice Language @@ -752,37 +660,129 @@ - - + + - Timeshift from UTC + Label selection mode - - + + - Voice Language + Label matching - - + + + + Backlight OFF Brightness + + - - + + + + + 0 + 0 + + + + 23 + + + + + + + + Large image (2 columns) + + + + + Small image (3 columns) + + + + + Name only (2 columns) + + + + + Name only (1 column) + + + + + + + + + Beeper + + + + + Speaker + + + + + BeeperVoice + + + + + SpeakerVoice + + + + + + + + + 0 + 0 + + - Backlight flash on alarm + Stick reverse - + + + + 8 + + + + + + + Timeshift from UTC + + + + + + + + Backlight flash on alarm + + + @@ -790,6 +790,13 @@ + + + + Vario pitch at max + + + @@ -797,17 +804,44 @@ - - + + - Vario pitch at max + Manage Models layout + + + + + + + + + + Speaker Volume + + + + + + + Owner Registration ID - + - Manage Models layout + Rotary Encoder Mode + + + + + + + + + + Model quick select @@ -838,41 +872,7 @@ p, li { white-space: pre-wrap; } - - - - Speaker Volume - - - - - - - Owner Registration ID - - - - - - - - - - Rotary Encoder Mode - - - - - - - - - - Model quick select - - - - + Enable this to quickly change model on the model select page (a long press can then be used to open the model edit menu). @@ -882,7 +882,7 @@ p, li { white-space: pre-wrap; } - + Qt::Vertical @@ -895,7 +895,7 @@ p, li { white-space: pre-wrap; } - + @@ -933,20 +933,6 @@ p, li { white-space: pre-wrap; } - - - - Vario pitch at zero - - - - - - - RotEnc Navigation - - - @@ -966,7 +952,21 @@ p, li { white-space: pre-wrap; } - + + + + Vario pitch at zero + + + + + + + RotEnc Navigation + + + + @@ -1016,7 +1016,7 @@ p, li { white-space: pre-wrap; } - + Country Code @@ -1058,7 +1058,7 @@ p, li { white-space: pre-wrap; } - + @@ -1092,7 +1092,7 @@ p, li { white-space: pre-wrap; } - + FAI Mode @@ -1118,7 +1118,7 @@ p, li { white-space: pre-wrap; } - + If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio. @@ -1128,14 +1128,14 @@ p, li { white-space: pre-wrap; } - + Backlight color - + @@ -1187,14 +1187,14 @@ p, li { white-space: pre-wrap; } - + Keys Backlight - + 5 @@ -1204,14 +1204,14 @@ p, li { white-space: pre-wrap; } - + Favorites matching - + @@ -1225,7 +1225,7 @@ p, li { white-space: pre-wrap; } - + @@ -1239,7 +1239,7 @@ p, li { white-space: pre-wrap; } - + @@ -1253,6 +1253,20 @@ p, li { white-space: pre-wrap; } + + + + Invert LCD + + + + + + + + + + diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index 4f7d92f1ee8..3c968f8f190 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -979,8 +979,11 @@ PACK(struct RadioData { #if defined(COLORLCD) NOBACKUP(uint8_t space:7 SKIP); +#elif LCD_W == 128 + uint8_t invertLCD:1; // Invert B&W LCD display + NOBACKUP(uint8_t spare:4 SKIP); #else - NOBACKUP(uint8_t space:5 SKIP); + NOBACKUP(uint8_t spare:5 SKIP); #endif NOBACKUP(uint8_t getBrightness() const diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index 61ffec98229..719baf23936 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -80,6 +80,10 @@ enum { ITEM_RADIO_HARDWARE_JITTER_FILTER, ITEM_RADIO_HARDWARE_RAS, ITEM_RADIO_HARDWARE_SPORT_UPDATE_POWER, +#if (defined(BACKLIGHT_GPIO) || defined(OLED_SCREEN)) && (LCD_W == 128) + ITEM_RADIO_HARDWARE_SCREEN_LABEL, + ITEM_RADIO_HARDWARE_SCREEN_INVERT, +#endif ITEM_RADIO_HARDWARE_DEBUG, #if defined(FUNCTION_SWITCHES) ITEM_RADIO_HARDWARE_DEBUG_FS, @@ -211,6 +215,11 @@ static void _init_menu_tab_array(uint8_t* tab, size_t len) tab[ITEM_RADIO_HARDWARE_SPORT_UPDATE_POWER] = HIDDEN_ROW; } +#if (defined(BACKLIGHT_GPIO) || defined(OLED_SCREEN)) && (LCD_W == 128) + tab[ITEM_RADIO_HARDWARE_SCREEN_LABEL] = READONLY_ROW; + tab[ITEM_RADIO_HARDWARE_SCREEN_INVERT] = 0; +#endif + tab[ITEM_RADIO_HARDWARE_DEBUG] = 1; #if defined(FUNCTION_SWITCHES) tab[ITEM_RADIO_HARDWARE_DEBUG_FS] = 0; @@ -425,6 +434,21 @@ void menuRadioHardware(event_t event) } break; +#if (defined(BACKLIGHT_GPIO) || defined(OLED_SCREEN)) && (LCD_W == 128) + case ITEM_RADIO_HARDWARE_SCREEN_LABEL: + lcdDrawTextAlignedLeft(y, STR_SCREEN); + break; + case ITEM_RADIO_HARDWARE_SCREEN_INVERT: + { + lcdDrawText(INDENT_WIDTH, y, STR_MENU_INVERT); + bool inv = g_eeGeneral.invertLCD; + g_eeGeneral.invertLCD = editCheckBox(g_eeGeneral.invertLCD, HW_SETTINGS_COLUMN2, y, nullptr, attr, event); + if (inv != g_eeGeneral.invertLCD) + lcdSetInvert(g_eeGeneral.invertLCD); + } + break; +#endif + case ITEM_RADIO_HARDWARE_DEBUG: lcdDrawTextAlignedLeft(y, STR_DEBUG); lcdDrawText(HW_SETTINGS_COLUMN2, y, STR_ANALOGS_BTN, menuHorizontalPosition == 0 ? attr : 0); diff --git a/radio/src/storage/sdcard_yaml.cpp b/radio/src/storage/sdcard_yaml.cpp index 85c186295c1..6620dcd2906 100644 --- a/radio/src/storage/sdcard_yaml.cpp +++ b/radio/src/storage/sdcard_yaml.cpp @@ -611,5 +611,9 @@ const char * restoreModel(uint8_t idx, char *model_name) bool storageReadRadioSettings(bool checks) { if (!sdMounted()) sdInit(); - return loadRadioSettingsYaml(checks) == nullptr; + bool rv = loadRadioSettingsYaml(checks) == nullptr; +#if LCD_W == 128 + lcdSetInvert(g_eeGeneral.invertLCD); +#endif + return rv; } diff --git a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp index 0e0f9f8101f..15a4a5c5417 100644 --- a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp @@ -358,7 +358,8 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "modelCustomScriptsDisabled", 1 ), YAML_UNSIGNED( "modelTelemetryDisabled", 1 ), YAML_UNSIGNED( "disableTrainerPoweroffAlarm", 1 ), - YAML_PADDING( 5 ), + YAML_UNSIGNED( "invertLCD", 1 ), + YAML_PADDING( 4 ), YAML_END }; static const struct YamlNode struct_unsigned_8[] = { diff --git a/radio/src/storage/yaml/yaml_datastructs_t20.cpp b/radio/src/storage/yaml/yaml_datastructs_t20.cpp index 8cc4a71803d..a6d48807f46 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t20.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t20.cpp @@ -358,7 +358,8 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "modelCustomScriptsDisabled", 1 ), YAML_UNSIGNED( "modelTelemetryDisabled", 1 ), YAML_UNSIGNED( "disableTrainerPoweroffAlarm", 1 ), - YAML_PADDING( 5 ), + YAML_UNSIGNED( "invertLCD", 1 ), + YAML_PADDING( 4 ), YAML_END }; static const struct YamlNode struct_unsigned_8[] = { diff --git a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp index 265d1df37c5..37e6148216a 100644 --- a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp @@ -358,7 +358,8 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "modelCustomScriptsDisabled", 1 ), YAML_UNSIGNED( "modelTelemetryDisabled", 1 ), YAML_UNSIGNED( "disableTrainerPoweroffAlarm", 1 ), - YAML_PADDING( 5 ), + YAML_UNSIGNED( "invertLCD", 1 ), + YAML_PADDING( 4 ), YAML_END }; static const struct YamlNode struct_unsigned_8[] = { diff --git a/radio/src/storage/yaml/yaml_datastructs_xlites.cpp b/radio/src/storage/yaml/yaml_datastructs_xlites.cpp index 3885bbbfec9..fd662b74690 100644 --- a/radio/src/storage/yaml/yaml_datastructs_xlites.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_xlites.cpp @@ -361,7 +361,8 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "modelCustomScriptsDisabled", 1 ), YAML_UNSIGNED( "modelTelemetryDisabled", 1 ), YAML_UNSIGNED( "disableTrainerPoweroffAlarm", 1 ), - YAML_PADDING( 5 ), + YAML_UNSIGNED( "invertLCD", 1 ), + YAML_PADDING( 4 ), YAML_END }; static const struct YamlNode struct_unsigned_8[] = { diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index 6c081e48d54..31ce381d276 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -426,6 +426,12 @@ void lcdSetRefVolt(uint8_t val) } #endif +#if LCD_W == 128 +void lcdSetInvert(bool invert) +{ +} +#endif + void boardInit() { } diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 6a6cd88b82d..0be92e2bc4b 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -371,6 +371,9 @@ void lcdRefresh(); void lcdRefresh(bool wait=true); // TODO uint8_t wait to simplify this #endif void lcdSetRefVolt(unsigned char val); +#if LCD_W == 128 +void lcdSetInvert(bool invert); +#endif #ifdef __cplusplus void lcdSetContrast(bool useDefault = false); #endif diff --git a/radio/src/targets/taranis/lcd_driver_spi.cpp b/radio/src/targets/taranis/lcd_driver_spi.cpp index 4b16796f25d..153307bf8e9 100644 --- a/radio/src/targets/taranis/lcd_driver_spi.cpp +++ b/radio/src/targets/taranis/lcd_driver_spi.cpp @@ -411,3 +411,10 @@ void lcdSetRefVolt(uint8_t val) lcdWriteCommand(0x81); // Set Vop lcdWriteCommand(val+LCD_CONTRAST_OFFSET); // 0-255 } + +#if LCD_W == 128 +void lcdSetInvert(bool invert) +{ + lcdWriteCommand(invert ? 0xA7 : 0xA6); +} +#endif