From a4a1aacdd8ec8f9895132a857f74d254304cc735 Mon Sep 17 00:00:00 2001 From: torlando-tech Date: Wed, 4 Mar 2026 11:16:24 -0500 Subject: [PATCH 01/10] Show boot splash within 1s of power-on instead of after 20s+ init Move Display::init_hardware_only() and POWER_EN to right after serial banner, before GPS/WiFi/SD/Reticulum init. Add 150ms delay after POWER_EN HIGH so ST7789V power rail stabilizes before SPI commands (without this, SWRESET is sent to an unpowered chip and silently lost). Splash now visible for entire boot period (~18s) until LVGL takes over. Co-Authored-By: Claude Opus 4.6 --- lib/tdeck_ui/Hardware/TDeck/Display.cpp | 56 ++++++++++++++++++++++--- lib/tdeck_ui/Hardware/TDeck/Display.h | 10 ++++- src/main.cpp | 22 ++++++++-- 3 files changed, 77 insertions(+), 11 deletions(-) diff --git a/lib/tdeck_ui/Hardware/TDeck/Display.cpp b/lib/tdeck_ui/Hardware/TDeck/Display.cpp index a2f058f..bd4e908 100644 --- a/lib/tdeck_ui/Hardware/TDeck/Display.cpp +++ b/lib/tdeck_ui/Hardware/TDeck/Display.cpp @@ -8,6 +8,10 @@ #include "Log.h" #include +#if __has_include("SplashImage.h") +#include "SplashImage.h" +#endif + using namespace RNS; namespace Hardware { @@ -16,6 +20,7 @@ namespace TDeck { SPIClass* Display::_spi = nullptr; uint8_t Display::_brightness = Disp::BACKLIGHT_DEFAULT; bool Display::_initialized = false; +bool Display::_hw_initialized = false; volatile uint32_t Display::_flush_count = 0; volatile uint32_t Display::_last_flush_ms = 0; uint32_t Display::_last_health_log_ms = 0; @@ -70,16 +75,17 @@ bool Display::init() { } bool Display::init_hardware_only() { - if (_initialized) { + if (_hw_initialized) { return true; } INFO("Initializing display hardware"); - // Configure backlight PWM + // Configure backlight PWM — keep OFF until splash is rendered + // Use ledcWrite directly so _brightness retains the default value for show_splash() ledcSetup(Disp::BACKLIGHT_CHANNEL, Disp::BACKLIGHT_FREQ, Disp::BACKLIGHT_RESOLUTION); ledcAttachPin(Pin::DISPLAY_BACKLIGHT, Disp::BACKLIGHT_CHANNEL); - set_brightness(_brightness); + ledcWrite(Disp::BACKLIGHT_CHANNEL, 0); // Initialize SPI _spi = new SPIClass(HSPI); @@ -94,7 +100,7 @@ bool Display::init_hardware_only() { // Initialize ST7789V registers init_registers(); - _initialized = true; + _hw_initialized = true; INFO(" Display hardware ready"); return true; } @@ -141,8 +147,8 @@ void Display::init_registers() { // DELAY RATIONALE: SPI command settling - allow display controller to process command before next delay(10); - // Clear screen to black - fill_screen(0x0000); + // Show splash image (or black screen if SplashImage.h not generated) + show_splash(); INFO(" ST7789V initialized"); } @@ -166,6 +172,44 @@ void Display::set_power(bool on) { } } +void Display::show_splash() { + // Background color: #1D1A1E -> RGB565 0x18C3 + static const uint16_t BG_COLOR = 0x18C3; + + // Fill entire screen with background color + fill_screen(BG_COLOR); + +#ifdef HAS_SPLASH_IMAGE + // Center 160x160 image on 320x240 screen + static const uint16_t X_OFFSET = (Disp::WIDTH - SPLASH_WIDTH) / 2; // 80 + static const uint16_t Y_OFFSET = (Disp::HEIGHT - SPLASH_HEIGHT) / 2; // 40 + + set_addr_window(X_OFFSET, Y_OFFSET, + X_OFFSET + SPLASH_WIDTH - 1, + Y_OFFSET + SPLASH_HEIGHT - 1); + + begin_write(); + write_command(Command::RAMWR); + + // Stream PROGMEM data in 512-byte chunks to avoid large stack allocation + static const size_t CHUNK_SIZE = 512; + uint8_t buf[CHUNK_SIZE]; + size_t total = SPLASH_WIDTH * SPLASH_HEIGHT * 2; + + for (size_t offset = 0; offset < total; offset += CHUNK_SIZE) { + size_t len = (offset + CHUNK_SIZE <= total) ? CHUNK_SIZE : (total - offset); + memcpy_P(buf, splash_image + offset, len); + write_data(buf, len); + } + + end_write(); + INFO(" Splash image rendered"); +#endif + + // Backlight on now that screen content is ready + set_brightness(_brightness); +} + void Display::fill_screen(uint16_t color) { set_addr_window(0, 0, Disp::WIDTH - 1, Disp::HEIGHT - 1); diff --git a/lib/tdeck_ui/Hardware/TDeck/Display.h b/lib/tdeck_ui/Hardware/TDeck/Display.h index 0f866b5..5bab54e 100644 --- a/lib/tdeck_ui/Hardware/TDeck/Display.h +++ b/lib/tdeck_ui/Hardware/TDeck/Display.h @@ -68,6 +68,13 @@ public: */ static void draw_rect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); + /** + * Show boot splash image (centered Pyxis logo) + * Called during init_registers() before backlight turns on. + * Falls back to black screen if SplashImage.h not generated. + */ + static void show_splash(); + /** * LVGL flush callback - called by LVGL to update display * Do not call directly - used internally by LVGL @@ -132,7 +139,8 @@ private: static SPIClass* _spi; static uint8_t _brightness; - static bool _initialized; + static bool _initialized; // Full init (hardware + LVGL) + static bool _hw_initialized; // Hardware-only init (SPI + registers) // Display health monitoring static volatile uint32_t _flush_count; diff --git a/src/main.cpp b/src/main.cpp index a8e108e..d7d0e33 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -637,10 +637,8 @@ void setup_hardware() { Wire.setClock(I2C::FREQUENCY); INFO("I2C initialized"); - // Initialize power - pinMode(Pin::POWER_EN, OUTPUT); - digitalWrite(Pin::POWER_EN, HIGH); - INFO("Power enabled"); + // Note: POWER_EN already set HIGH in setup() before display splash + INFO("Power enabled (early init)"); } void setup_lvgl_and_ui() { @@ -652,6 +650,11 @@ void setup_lvgl_and_ui() { while (1) delay(1000); } + // Match LVGL default screen background to splash color (#1D1A1E) + // so LVGL's first render doesn't flash over the boot splash + lv_obj_set_style_bg_color(lv_scr_act(), lv_color_hex(0x1D1A1E), 0); + lv_obj_set_style_bg_opa(lv_scr_act(), LV_OPA_COVER, 0); + INFO("LVGL initialized"); // Start LVGL on its own FreeRTOS task for responsive UI @@ -1196,6 +1199,17 @@ void setup() { INFO("╚══════════════════════════════════════╝"); INFO(""); + // Enable peripheral power rail before display init. + // Display needs ~120ms after power-on before accepting SPI commands + // (ST7789V power-on reset time). Without this delay, SWRESET is sent + // to an unpowered chip and silently lost. + pinMode(Pin::POWER_EN, OUTPUT); + digitalWrite(Pin::POWER_EN, HIGH); + delay(150); + + // Show boot splash ASAP — before any slow init (GPS, WiFi, SD, Reticulum). + Hardware::TDeck::Display::init_hardware_only(); + // Capture ESP reset reason early (before WiFi) — logged after WiFi init for UDP visibility esp_reset_reason_t _boot_reset_reason = esp_reset_reason(); From 30dc48086ce95229eeb17bcb72a138b43d090387 Mon Sep 17 00:00:00 2001 From: torlando-tech Date: Wed, 4 Mar 2026 13:50:20 -0500 Subject: [PATCH 02/10] Add splash screen icon and build-time SVG-to-RGB565 generator - pyxis-icon.svg: Pyxis constellation icon (3 stars with connecting lines) - generate_splash.py: PlatformIO pre-build script that renders the SVG to a 160x160 RGB565 PROGMEM header (SplashImage.h) using cairosvg + Pillow - .gitignore: Exclude generated SplashImage.h - platformio.ini: Add generate_splash.py to both build environments Co-Authored-By: Claude Opus 4.6 --- .gitignore | 1 + generate_splash.py | 98 ++++++++++++++++++++++++++++++++++++++++++++++ platformio.ini | 5 ++- pyxis-icon.svg | 21 ++++++++++ 4 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 generate_splash.py create mode 100644 pyxis-icon.svg diff --git a/.gitignore b/.gitignore index 873aa97..c6c6a74 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .vscode/ *.pyc docs/flasher/firmware/ +lib/tdeck_ui/Hardware/TDeck/SplashImage.h diff --git a/generate_splash.py b/generate_splash.py new file mode 100644 index 0000000..46d5da8 --- /dev/null +++ b/generate_splash.py @@ -0,0 +1,98 @@ +""" +PlatformIO pre-build script: Convert pyxis-icon.svg to RGB565 PROGMEM header. + +Generates lib/tdeck_ui/Hardware/TDeck/SplashImage.h containing a 160x160 +pixel splash image as a PROGMEM byte array. Skips regeneration if the +header is already newer than the source SVG. + +Requires: cairosvg, Pillow (gracefully skips if not installed) +""" + +Import("env") + +import os +import struct + +ICON_SIZE = 160 +SVG_FILE = "pyxis-icon.svg" +HEADER_FILE = os.path.join("lib", "tdeck_ui", "Hardware", "TDeck", "SplashImage.h") +BG_COLOR = (0x1D, 0x1A, 0x1E) # #1D1A1E — matches fill_screen in show_splash() + + +def rgb888_to_rgb565(r, g, b): + """Convert 8-bit RGB to 16-bit RGB565 (big-endian bytes).""" + rgb565 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3) + return struct.pack(">H", rgb565) + + +def should_regenerate(svg_path, header_path): + """Return True if the header needs regeneration.""" + if not os.path.exists(header_path): + return True + return os.path.getmtime(svg_path) > os.path.getmtime(header_path) + + +project_dir = env.get("PROJECT_DIR", os.getcwd()) +svg_path = os.path.join(project_dir, SVG_FILE) +header_path = os.path.join(project_dir, HEADER_FILE) + +if not os.path.exists(svg_path): + print(f"[generate_splash] {SVG_FILE} not found, skipping splash generation") +elif not should_regenerate(svg_path, header_path): + print(f"[generate_splash] {HEADER_FILE} is up-to-date, skipping") +else: + try: + import cairosvg + from PIL import Image + import io + except ImportError as e: + print(f"[generate_splash] Missing dependency ({e}), skipping splash generation") + print(f"[generate_splash] Install with: pip install cairosvg Pillow") + else: + print(f"[generate_splash] Rendering {SVG_FILE} -> {HEADER_FILE} ({ICON_SIZE}x{ICON_SIZE} RGB565)") + + # Render SVG to PNG at target size + png_data = cairosvg.svg2png( + url=svg_path, + output_width=ICON_SIZE, + output_height=ICON_SIZE, + ) + + img = Image.open(io.BytesIO(png_data)).convert("RGBA") + + # Composite onto background color (handles transparency) + bg = Image.new("RGBA", (ICON_SIZE, ICON_SIZE), BG_COLOR + (255,)) + bg.paste(img, (0, 0), img) + img = bg.convert("RGB") + + # Convert to RGB565 big-endian byte array + pixels = list(img.getdata()) + rgb565_bytes = bytearray() + for r, g, b in pixels: + rgb565_bytes.extend(rgb888_to_rgb565(r, g, b)) + + # Write C header + os.makedirs(os.path.dirname(header_path), exist_ok=True) + + with open(header_path, "w") as f: + f.write("// AUTO-GENERATED by generate_splash.py — do not edit\n") + f.write("#ifndef SPLASH_IMAGE_H\n") + f.write("#define SPLASH_IMAGE_H\n\n") + f.write("#include \n\n") + f.write(f"#define SPLASH_WIDTH {ICON_SIZE}\n") + f.write(f"#define SPLASH_HEIGHT {ICON_SIZE}\n") + f.write(f"#define HAS_SPLASH_IMAGE 1\n\n") + f.write(f"// {ICON_SIZE}x{ICON_SIZE} RGB565 big-endian ({len(rgb565_bytes)} bytes)\n") + f.write("static const uint8_t PROGMEM splash_image[] = {\n") + + # Write bytes, 16 per line + for i in range(0, len(rgb565_bytes), 16): + chunk = rgb565_bytes[i:i+16] + hex_str = ", ".join(f"0x{b:02X}" for b in chunk) + trailing = "," if i + 16 < len(rgb565_bytes) else "" + f.write(f" {hex_str}{trailing}\n") + + f.write("};\n\n") + f.write("#endif // SPLASH_IMAGE_H\n") + + print(f"[generate_splash] Generated {len(rgb565_bytes)} bytes ({ICON_SIZE}x{ICON_SIZE} RGB565)") diff --git a/platformio.ini b/platformio.ini index bce445e..a7f8778 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,6 +1,8 @@ ; T-Deck environment using Bluedroid BLE stack (fallback, uses more RAM) [env:tdeck-bluedroid] -extra_scripts = pre:version.py +extra_scripts = + pre:version.py + pre:generate_splash.py platform = espressif32 board = esp32-s3-devkitc-1 framework = arduino @@ -79,6 +81,7 @@ build_flags = [env:tdeck] extra_scripts = pre:version.py + pre:generate_splash.py pre:patch_nimble.py platform = espressif32 board = esp32-s3-devkitc-1 diff --git a/pyxis-icon.svg b/pyxis-icon.svg new file mode 100644 index 0000000..87e9d51 --- /dev/null +++ b/pyxis-icon.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 27668a75158bd1f737f285155e91ef3b6ca950cb Mon Sep 17 00:00:00 2001 From: torlando-tech Date: Wed, 4 Mar 2026 14:10:37 -0500 Subject: [PATCH 03/10] Add PYXIS text to splash and render full-screen 320x240 Scale constellation to 80% and shift down to make room for title text. Generate splash at full display resolution instead of 160x160 centered. Co-Authored-By: Claude Opus 4.6 --- generate_splash.py | 28 +++++++++++++++------------- pyxis-icon.svg | 3 +++ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/generate_splash.py b/generate_splash.py index 46d5da8..7256a13 100644 --- a/generate_splash.py +++ b/generate_splash.py @@ -13,7 +13,8 @@ Import("env") import os import struct -ICON_SIZE = 160 +SPLASH_WIDTH = 320 +SPLASH_HEIGHT = 240 SVG_FILE = "pyxis-icon.svg" HEADER_FILE = os.path.join("lib", "tdeck_ui", "Hardware", "TDeck", "SplashImage.h") BG_COLOR = (0x1D, 0x1A, 0x1E) # #1D1A1E — matches fill_screen in show_splash() @@ -49,20 +50,21 @@ else: print(f"[generate_splash] Missing dependency ({e}), skipping splash generation") print(f"[generate_splash] Install with: pip install cairosvg Pillow") else: - print(f"[generate_splash] Rendering {SVG_FILE} -> {HEADER_FILE} ({ICON_SIZE}x{ICON_SIZE} RGB565)") + print(f"[generate_splash] Rendering {SVG_FILE} -> {HEADER_FILE} ({SPLASH_WIDTH}x{SPLASH_HEIGHT} RGB565)") - # Render SVG to PNG at target size + # Render SVG to PNG — scale to fit height, center horizontally png_data = cairosvg.svg2png( url=svg_path, - output_width=ICON_SIZE, - output_height=ICON_SIZE, + output_width=SPLASH_HEIGHT, # Square SVG scaled to screen height + output_height=SPLASH_HEIGHT, ) - img = Image.open(io.BytesIO(png_data)).convert("RGBA") + icon = Image.open(io.BytesIO(png_data)).convert("RGBA") - # Composite onto background color (handles transparency) - bg = Image.new("RGBA", (ICON_SIZE, ICON_SIZE), BG_COLOR + (255,)) - bg.paste(img, (0, 0), img) + # Composite onto full-screen background (handles transparency) + bg = Image.new("RGBA", (SPLASH_WIDTH, SPLASH_HEIGHT), BG_COLOR + (255,)) + x_offset = (SPLASH_WIDTH - icon.width) // 2 + bg.paste(icon, (x_offset, 0), icon) img = bg.convert("RGB") # Convert to RGB565 big-endian byte array @@ -79,10 +81,10 @@ else: f.write("#ifndef SPLASH_IMAGE_H\n") f.write("#define SPLASH_IMAGE_H\n\n") f.write("#include \n\n") - f.write(f"#define SPLASH_WIDTH {ICON_SIZE}\n") - f.write(f"#define SPLASH_HEIGHT {ICON_SIZE}\n") + f.write(f"#define SPLASH_WIDTH {SPLASH_WIDTH}\n") + f.write(f"#define SPLASH_HEIGHT {SPLASH_HEIGHT}\n") f.write(f"#define HAS_SPLASH_IMAGE 1\n\n") - f.write(f"// {ICON_SIZE}x{ICON_SIZE} RGB565 big-endian ({len(rgb565_bytes)} bytes)\n") + f.write(f"// {SPLASH_WIDTH}x{SPLASH_HEIGHT} RGB565 big-endian ({len(rgb565_bytes)} bytes)\n") f.write("static const uint8_t PROGMEM splash_image[] = {\n") # Write bytes, 16 per line @@ -95,4 +97,4 @@ else: f.write("};\n\n") f.write("#endif // SPLASH_IMAGE_H\n") - print(f"[generate_splash] Generated {len(rgb565_bytes)} bytes ({ICON_SIZE}x{ICON_SIZE} RGB565)") + print(f"[generate_splash] Generated {len(rgb565_bytes)} bytes ({SPLASH_WIDTH}x{SPLASH_HEIGHT} RGB565)") diff --git a/pyxis-icon.svg b/pyxis-icon.svg index 87e9d51..af724b7 100644 --- a/pyxis-icon.svg +++ b/pyxis-icon.svg @@ -8,6 +8,8 @@ + PYXIS + @@ -18,4 +20,5 @@ + \ No newline at end of file From 0f85f4dd69de6261ff63e13c628d1c82df2c7016 Mon Sep 17 00:00:00 2001 From: torlando-tech Date: Wed, 4 Mar 2026 14:12:36 -0500 Subject: [PATCH 04/10] Add Pyxis logo to README Co-Authored-By: Claude Opus 4.6 --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 8f0bb68..fadb29d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +

+ Pyxis logo +

+ # Pyxis An LXMF and LXST client firmware for T-Deck, built on a [highly modified fork](https://github.com/torlando-tech/microReticulum/tree/feat/t-deck) of [microReticulum](https://github.com/attermann/microReticulum) From a93f7c258f675503b82a1955f1a7bdf4c1edac72 Mon Sep 17 00:00:00 2001 From: Torlando Date: Wed, 4 Mar 2026 14:19:48 -0500 Subject: [PATCH 05/10] Apply suggestion from @greptile-apps[bot] Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- generate_splash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generate_splash.py b/generate_splash.py index 7256a13..41ecfa2 100644 --- a/generate_splash.py +++ b/generate_splash.py @@ -1,7 +1,7 @@ """ PlatformIO pre-build script: Convert pyxis-icon.svg to RGB565 PROGMEM header. -Generates lib/tdeck_ui/Hardware/TDeck/SplashImage.h containing a 160x160 +Generates lib/tdeck_ui/Hardware/TDeck/SplashImage.h containing a 320x240 pixel splash image as a PROGMEM byte array. Skips regeneration if the header is already newer than the source SVG. From 2f61b80567b601b464a090b585d9d2cdea8c2784 Mon Sep 17 00:00:00 2001 From: Torlando Date: Wed, 4 Mar 2026 14:20:44 -0500 Subject: [PATCH 06/10] Update lib/tdeck_ui/Hardware/TDeck/Display.cpp Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- lib/tdeck_ui/Hardware/TDeck/Display.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/tdeck_ui/Hardware/TDeck/Display.cpp b/lib/tdeck_ui/Hardware/TDeck/Display.cpp index bd4e908..6714032 100644 --- a/lib/tdeck_ui/Hardware/TDeck/Display.cpp +++ b/lib/tdeck_ui/Hardware/TDeck/Display.cpp @@ -180,9 +180,9 @@ void Display::show_splash() { fill_screen(BG_COLOR); #ifdef HAS_SPLASH_IMAGE - // Center 160x160 image on 320x240 screen - static const uint16_t X_OFFSET = (Disp::WIDTH - SPLASH_WIDTH) / 2; // 80 - static const uint16_t Y_OFFSET = (Disp::HEIGHT - SPLASH_HEIGHT) / 2; // 40 + // Splash image is full-screen (320x240), so offsets are 0 + static const uint16_t X_OFFSET = (Disp::WIDTH - SPLASH_WIDTH) / 2; // 0 + static const uint16_t Y_OFFSET = (Disp::HEIGHT - SPLASH_HEIGHT) / 2; // 0 set_addr_window(X_OFFSET, Y_OFFSET, X_OFFSET + SPLASH_WIDTH - 1, From 2a1b98f8f152dcbf91b13494891751abe2f19c18 Mon Sep 17 00:00:00 2001 From: torlando-tech Date: Wed, 4 Mar 2026 14:39:49 -0500 Subject: [PATCH 07/10] Fix _initialized never set in Display::init() Prevents double PSRAM allocation and LVGL driver re-registration if init() were called more than once. Co-Authored-By: Claude Opus 4.6 --- lib/tdeck_ui/Hardware/TDeck/Display.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/tdeck_ui/Hardware/TDeck/Display.cpp b/lib/tdeck_ui/Hardware/TDeck/Display.cpp index 6714032..ca70c8d 100644 --- a/lib/tdeck_ui/Hardware/TDeck/Display.cpp +++ b/lib/tdeck_ui/Hardware/TDeck/Display.cpp @@ -70,6 +70,7 @@ bool Display::init() { return false; } + _initialized = true; INFO("Display initialized successfully"); return true; } From 5b2a1ab53eb3cf54145041ca4a90d60998c3459d Mon Sep 17 00:00:00 2001 From: torlando-tech Date: Wed, 4 Mar 2026 16:09:49 -0500 Subject: [PATCH 08/10] Skip redundant fill_screen when full-screen splash image is available Saves one full 320x240 SPI screen write before the splash renders. Co-Authored-By: Claude Opus 4.6 --- lib/tdeck_ui/Hardware/TDeck/Display.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/tdeck_ui/Hardware/TDeck/Display.cpp b/lib/tdeck_ui/Hardware/TDeck/Display.cpp index ca70c8d..30924e2 100644 --- a/lib/tdeck_ui/Hardware/TDeck/Display.cpp +++ b/lib/tdeck_ui/Hardware/TDeck/Display.cpp @@ -177,8 +177,12 @@ void Display::show_splash() { // Background color: #1D1A1E -> RGB565 0x18C3 static const uint16_t BG_COLOR = 0x18C3; - // Fill entire screen with background color +#ifdef HAS_SPLASH_IMAGE + // Full-screen splash has background baked in — skip redundant fill +#else + // No splash image — fill with background color fill_screen(BG_COLOR); +#endif #ifdef HAS_SPLASH_IMAGE // Splash image is full-screen (320x240), so offsets are 0 From bae59ff42467e9f857bedbad6356e23dddc7f57c Mon Sep 17 00:00:00 2001 From: torlando-tech Date: Wed, 4 Mar 2026 17:48:38 -0500 Subject: [PATCH 09/10] Fix unused BG_COLOR warning and make show_splash() private Move BG_COLOR inline into #ifndef block to avoid unused variable when HAS_SPLASH_IMAGE is defined. Make show_splash() private since it's only called internally from init_hardware_only(). Co-Authored-By: Claude Opus 4.6 --- lib/tdeck_ui/Hardware/TDeck/Display.cpp | 11 +++-------- lib/tdeck_ui/Hardware/TDeck/Display.h | 9 ++------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/lib/tdeck_ui/Hardware/TDeck/Display.cpp b/lib/tdeck_ui/Hardware/TDeck/Display.cpp index 30924e2..49184e6 100644 --- a/lib/tdeck_ui/Hardware/TDeck/Display.cpp +++ b/lib/tdeck_ui/Hardware/TDeck/Display.cpp @@ -174,14 +174,9 @@ void Display::set_power(bool on) { } void Display::show_splash() { - // Background color: #1D1A1E -> RGB565 0x18C3 - static const uint16_t BG_COLOR = 0x18C3; - -#ifdef HAS_SPLASH_IMAGE - // Full-screen splash has background baked in — skip redundant fill -#else - // No splash image — fill with background color - fill_screen(BG_COLOR); +#ifndef HAS_SPLASH_IMAGE + // No splash image — fill with background color (#1D1A1E -> RGB565 0x18C3) + fill_screen(0x18C3); #endif #ifdef HAS_SPLASH_IMAGE diff --git a/lib/tdeck_ui/Hardware/TDeck/Display.h b/lib/tdeck_ui/Hardware/TDeck/Display.h index 5bab54e..fcc5629 100644 --- a/lib/tdeck_ui/Hardware/TDeck/Display.h +++ b/lib/tdeck_ui/Hardware/TDeck/Display.h @@ -68,13 +68,6 @@ public: */ static void draw_rect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); - /** - * Show boot splash image (centered Pyxis logo) - * Called during init_registers() before backlight turns on. - * Falls back to black screen if SplashImage.h not generated. - */ - static void show_splash(); - /** * LVGL flush callback - called by LVGL to update display * Do not call directly - used internally by LVGL @@ -82,6 +75,8 @@ public: static void lvgl_flush_cb(lv_disp_drv_t* drv, const lv_area_t* area, lv_color_t* color_p); private: + // Show boot splash image, called from init_hardware_only() + static void show_splash(); // SPI commands for ST7789V enum Command : uint8_t { NOP = 0x00, From ff00c1d7834e8a81aa02d947d9eef6d425aa0295 Mon Sep 17 00:00:00 2001 From: torlando-tech Date: Wed, 4 Mar 2026 18:19:49 -0500 Subject: [PATCH 10/10] Clean up splash preprocessor structure and add include warning Consolidate #ifndef/#ifdef into single #ifdef/#else/#endif block. Add warning comment to generated header about static linkage. Co-Authored-By: Claude Opus 4.6 --- generate_splash.py | 1 + lib/tdeck_ui/Hardware/TDeck/Display.cpp | 12 +++++------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/generate_splash.py b/generate_splash.py index 41ecfa2..f9899cd 100644 --- a/generate_splash.py +++ b/generate_splash.py @@ -85,6 +85,7 @@ else: f.write(f"#define SPLASH_HEIGHT {SPLASH_HEIGHT}\n") f.write(f"#define HAS_SPLASH_IMAGE 1\n\n") f.write(f"// {SPLASH_WIDTH}x{SPLASH_HEIGHT} RGB565 big-endian ({len(rgb565_bytes)} bytes)\n") + f.write("// WARNING: static linkage — include from exactly ONE translation unit\n") f.write("static const uint8_t PROGMEM splash_image[] = {\n") # Write bytes, 16 per line diff --git a/lib/tdeck_ui/Hardware/TDeck/Display.cpp b/lib/tdeck_ui/Hardware/TDeck/Display.cpp index 49184e6..3bcae5b 100644 --- a/lib/tdeck_ui/Hardware/TDeck/Display.cpp +++ b/lib/tdeck_ui/Hardware/TDeck/Display.cpp @@ -174,15 +174,10 @@ void Display::set_power(bool on) { } void Display::show_splash() { -#ifndef HAS_SPLASH_IMAGE - // No splash image — fill with background color (#1D1A1E -> RGB565 0x18C3) - fill_screen(0x18C3); -#endif - #ifdef HAS_SPLASH_IMAGE // Splash image is full-screen (320x240), so offsets are 0 - static const uint16_t X_OFFSET = (Disp::WIDTH - SPLASH_WIDTH) / 2; // 0 - static const uint16_t Y_OFFSET = (Disp::HEIGHT - SPLASH_HEIGHT) / 2; // 0 + static const uint16_t X_OFFSET = (Disp::WIDTH - SPLASH_WIDTH) / 2; + static const uint16_t Y_OFFSET = (Disp::HEIGHT - SPLASH_HEIGHT) / 2; set_addr_window(X_OFFSET, Y_OFFSET, X_OFFSET + SPLASH_WIDTH - 1, @@ -204,6 +199,9 @@ void Display::show_splash() { end_write(); INFO(" Splash image rendered"); +#else + // No splash image — fill with background color (#1D1A1E -> RGB565 0x18C3) + fill_screen(0x18C3); #endif // Backlight on now that screen content is ready