From 6f95884d477c63c0b5c50bece623bcb88c9c99e4 Mon Sep 17 00:00:00 2001 From: pelgraine <140762863+pelgraine@users.noreply.github.com> Date: Tue, 2 Jun 2026 22:15:15 +1000 Subject: [PATCH] STUPID BACKLIGHT IS WORKING FINALLY AAAH --- examples/companion_radio/main.cpp | 21 ++---- .../lilygo_tdeck_max/TDeckProMaxBoard.cpp | 74 ++++++++++++++++--- variants/lilygo_tdeck_max/platformio.ini | 2 +- variants/lilygo_tdeck_pro/platformio.ini | 2 +- variants/lilygo_tdeck_pro/variant.h | 2 +- 5 files changed, 71 insertions(+), 30 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 88db4a51..99519288 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -2546,17 +2546,6 @@ void setup() { if (p4) free(p4); if (p10) free(p10); if (p25) free(p25); } MESH_DEBUG_PRINTLN("=== setup() - COMPLETE ==="); - - // DIAGNOSTIC: assert the frontlight at the very end of setup(), after ALL - // init has run. The factory firmware proves analogWrite(41,50) lights this - // panel. If the home screen is lit now (but the early step-12 assert was - // not), the pin was being reconfigured during init and this late assert wins. - // If it lights now and stays until a specific screen is opened, that screen's - // pinMode(41) is the thief. Watch this marker vs the screen you open. -#ifdef PIN_EINK_BL - analogWrite(PIN_EINK_BL, 50); - Serial.println(">>> BL DIAG: analogWrite(41,50) asserted at end of setup()"); -#endif } // --------------------------------------------------------------------------- @@ -2834,7 +2823,7 @@ void loop() { audio->setVolume(0); audio->stopSong(); delay(50); - digitalWrite(41, LOW); + // digitalWrite(41, LOW); notifTonePlaying = false; notifFadingOut = false; notifMuted = false; @@ -2887,9 +2876,9 @@ void loop() { audio->connecttoFS(SD, file); // Enable DAC amplifier and let it stabilise with silence flowing - pinMode(41, OUTPUT); - digitalWrite(41, HIGH); - delay(80); + // pinMode(41, OUTPUT); + // digitalWrite(41, HIGH); + // delay(80); // Fill audio buffer with silence at volume 0 (prevents power-on pop) for (int i = 0; i < 30; i++) { @@ -4129,7 +4118,7 @@ void handleKeyboardInput() { if (key == KB_KEY_KBD_BACKLIGHT) { static bool kbdBacklightOn = false; kbdBacklightOn = !kbdBacklightOn; - analogWrite(KB_BL_PIN, kbdBacklightOn ? 255 : 0); + digitalWrite(KB_BL_PIN, kbdBacklightOn ? 255 : 0); Serial.printf("Keyboard backlight %s\n", kbdBacklightOn ? "ON" : "OFF"); return; } diff --git a/variants/lilygo_tdeck_max/TDeckProMaxBoard.cpp b/variants/lilygo_tdeck_max/TDeckProMaxBoard.cpp index 96abbdde..826371bb 100644 --- a/variants/lilygo_tdeck_max/TDeckProMaxBoard.cpp +++ b/variants/lilygo_tdeck_max/TDeckProMaxBoard.cpp @@ -2,6 +2,8 @@ #include "variant.h" #include "TDeckProMaxBoard.h" #include // For MESH_DEBUG_PRINTLN +#include "soc/gpio_reg.h" // GPIO_ENABLE1_REG/OUT1/IN1/FUNC0_OUT_SEL_CFG (diagnostic) +#include "soc/io_mux_reg.h" // IO_MUX_GPIO41_REG / IO_MUX_GPIO42_REG (diagnostic) // LEDC channel for e-ink backlight PWM (Arduino ESP32 core 2.x channel-based API) #ifdef PIN_EINK_BL @@ -27,6 +29,39 @@ // to handle XL9555-routed pins. BQ27220 methods are inherited unchanged. // ============================================================================= +#ifdef PIN_EINK_BL +// DIAGNOSTIC helper: dump the low-level state of one GPIO so the frontlight pin +// (GPIO41 / MTDI) and the keyboard-backlight pin (GPIO42 / MTMS) can be compared +// directly. Per the V0.1 schematic both are identical S8050 low-side LED switches +// with VDD3V3 anodes, yet IO42 lights and IO41 does not. This prints the output +// enable, output/input level, the IO_MUX function select, and the GPIO-matrix +// output signal so we can see what differs about GPIO41. +// ESP32-S3 note: GPIO 41/42 live in the *1 register banks (bit = gpio - 32). +static void dumpGpioState(const char* label, int gpio, uint32_t muxReg) { + uint32_t en1 = REG_READ(GPIO_ENABLE1_REG); + uint32_t out1 = REG_READ(GPIO_OUT1_REG); + uint32_t in1 = REG_READ(GPIO_IN1_REG); + uint32_t mux = REG_READ(muxReg); + uint32_t fcfg = REG_READ(GPIO_FUNC0_OUT_SEL_CFG_REG + (uint32_t)gpio * 4); + int bit = gpio - 32; // 41 -> bit 9, 42 -> bit 10 + Serial.printf( + " %s GPIO%d: OEN=%d OUT=%d IN=%d | IO_MUX=0x%08X MCU_SEL=%d FUN_IE=%d FUN_DRV=%d WPU=%d WPD=%d | FUNC_OUT_SEL=0x%08X sig=%d\n", + label, gpio, + (int)((en1 >> bit) & 1), + (int)((out1 >> bit) & 1), + (int)((in1 >> bit) & 1), + mux, + (int)((mux >> 12) & 0x7), // MCU_SEL : IO_MUX function select + (int)((mux >> 9) & 0x1), // FUN_IE : input enable + (int)((mux >> 10) & 0x3), // FUN_DRV : drive strength + (int)((mux >> 8) & 0x1), // FUN_WPU : pull-up + (int)((mux >> 7) & 0x1), // FUN_WPD : pull-down + fcfg, + (int)(fcfg & 0x1FF) // func_sel: output signal index (256 = direct GPIO_OUT) + ); +} +#endif + void TDeckProMaxBoard::begin() { MESH_DEBUG_PRINTLN("TDeckProMaxBoard::begin() - T-Deck Pro MAX V0.1"); @@ -53,13 +88,23 @@ for (uint8_t a = 0x6A; a <= 0x6B; a++) { // without XL9555, but LoRa/GPS/modem will be dead. } - // Frontlight on, factory-style: a single analogWrite right after XL9555 init, - // exactly as LilyGo's factory firmware does (analogWrite(BOARD_EPD_BL, 50)). - // No rail-forcing, no explicit channel -- this is the clean test of whether - // the core (2.0.14 vs 2.0.17) was the difference. + // DIAGNOSTIC: GPIO41 (frontlight) vs GPIO42 (keyboard backlight) register + // comparison. Per the V0.1 schematic both are identical S8050 low-side LED + // switches with VDD3V3 anodes, differing only in the GPIO -- IO42 lights, + // IO41 does not. Dump each pin's register state at boot to establish the + // baseline that the post-boot backlightOn() dump can be compared against. #ifdef PIN_EINK_BL - analogWrite(PIN_EINK_BL, 50); - Serial.println(">>> BL: analogWrite(41,50) after XL9555 init"); + Serial.println(">>> BL DIAG: GPIO41 (frontlight) vs GPIO42 (keyboard) register compare"); + Serial.println(" [baseline -- after XL9555 init, before driving either pin]"); + dumpGpioState("FRONTLIGHT", 41, IO_MUX_GPIO41_REG); + dumpGpioState("KEYBOARD ", 42, IO_MUX_GPIO42_REG); + + pinMode(42, OUTPUT); digitalWrite(42, HIGH); // keyboard backlight -- known-good reference + pinMode(41, OUTPUT); digitalWrite(41, LOW); // frontlight -- held LOW so only backlightOn() can light it + delay(5); + Serial.println(" [after: IO42 HIGH (reference), IO41 output held LOW]"); + dumpGpioState("FRONTLIGHT", 41, IO_MUX_GPIO41_REG); + dumpGpioState("KEYBOARD ", 42, IO_MUX_GPIO42_REG); #endif // ------ Step 3: Touch reset pulse ------ @@ -125,9 +170,9 @@ for (uint8_t a = 0x6A; a <= 0x6B; a++) { #endif // ------ Step 12: E-ink backlight ------ - // Left as no-op during this diagnostic: the early factory-order assert above - // (right after XL9555 init) is what we are testing. Do NOT pull IO41 low here, - // or it would undo that test. + // No-op: the diagnostic block above already configured IO41 as an output and + // left it LOW at boot. The frontlight is now lit only by backlightOn() (Alt+B), + // so we can capture the post-boot register state from inside that call. MESH_DEBUG_PRINTLN("TDeckProMaxBoard::begin() - complete"); } @@ -340,14 +385,21 @@ void TDeckProMaxBoard::loraPowerOff() { void TDeckProMaxBoard::backlightOn() { #ifdef PIN_EINK_BL - analogWrite(PIN_EINK_BL, 50); + pinMode(PIN_EINK_BL, OUTPUT); + digitalWrite(PIN_EINK_BL, HIGH); + // TEMP diagnostic -- dump GPIO41 state right after driving it HIGH, post-boot. + // Compare against the begin() baseline: if OEN=1 OUT=1 sig=256 here too but + // the panel stays dark, something post-boot is overriding the pad. + dumpGpioState("FRONTLIGHT", PIN_EINK_BL, IO_MUX_GPIO41_REG); #endif _backlightOn = true; } void TDeckProMaxBoard::backlightOff() { #ifdef PIN_EINK_BL - analogWrite(PIN_EINK_BL, 0); + pinMode(PIN_EINK_BL, OUTPUT); + digitalWrite(PIN_EINK_BL, LOW); + dumpGpioState("FRONTLIGHT", PIN_EINK_BL, IO_MUX_GPIO41_REG); // TEMP diagnostic #endif _backlightOn = false; } diff --git a/variants/lilygo_tdeck_max/platformio.ini b/variants/lilygo_tdeck_max/platformio.ini index bb99f142..0caa3530 100644 --- a/variants/lilygo_tdeck_max/platformio.ini +++ b/variants/lilygo_tdeck_max/platformio.ini @@ -125,7 +125,7 @@ build_flags = -D PIN_DISPLAY_SCLK=36 -D PIN_DISPLAY_MISO=-1 -D PIN_DISPLAY_MOSI=33 - -D PIN_DISPLAY_BL=41 + ; -D PIN_DISPLAY_BL=41 -D PIN_USER_BTN=0 ; Touch (INT is direct GPIO; RST is XL9555, handled by board class) -D HAS_TOUCHSCREEN=1 diff --git a/variants/lilygo_tdeck_pro/platformio.ini b/variants/lilygo_tdeck_pro/platformio.ini index 132e2989..13bbcf84 100644 --- a/variants/lilygo_tdeck_pro/platformio.ini +++ b/variants/lilygo_tdeck_pro/platformio.ini @@ -62,7 +62,7 @@ build_flags = -D EINK_BUSY=37 -D EINK_SCLK=36 -D EINK_MOSI=33 - -D EINK_BL=45 + -D EINK_BL=41 -D EINK_NOT_HIBERNATE=1 -D HAS_BQ27220=1 -D AUTO_SHUTDOWN_MILLIVOLTS=2800 diff --git a/variants/lilygo_tdeck_pro/variant.h b/variants/lilygo_tdeck_pro/variant.h index 78531711..c423cf97 100644 --- a/variants/lilygo_tdeck_pro/variant.h +++ b/variants/lilygo_tdeck_pro/variant.h @@ -19,7 +19,7 @@ #define PIN_EINK_BUSY 37 #define PIN_EINK_SCLK 36 // Shared with LoRa #define PIN_EINK_MOSI 33 // Shared with LoRa -#define PIN_EINK_BL 45 // Backlight PWM (optional, V1.1 feature) +#define PIN_EINK_BL 41 // Backlight PWM (optional, V1.1 feature) // Legacy aliases for MeshCore compatibility #define PIN_DISPLAY_CS PIN_EINK_CS