Skip to content

Add GC9A01 round TFT display usermod#4989

Open
srg74 wants to merge 142 commits into
wled:mainfrom
srg74:feature/gc9a01-display-usermod
Open

Add GC9A01 round TFT display usermod#4989
srg74 wants to merge 142 commits into
wled:mainfrom
srg74:feature/gc9a01-display-usermod

Conversation

@srg74
Copy link
Copy Markdown
Contributor

@srg74 srg74 commented Oct 6, 2025

Overview

Adds comprehensive support for GC9A01 240x240 round TFT displays with a circular UI layout optimized for round displays.

Features

  • Circular UI design optimized for 240x240 round displays
  • Real-time status display: WiFi signal, power state, brightness, current effect
  • Clock mode with 12/24-hour format options
  • Configurable sleep/clock modes (5-300s timeout)
  • Color preview buttons (FX/BG/CS) with automatic synchronization from web UI
  • Effect and palette names with automatic display
  • Custom startup logo
  • Full web UI configuration for all settings
  • Compatible with rotary encoder usermod for visual feedback

Hardware Requirements

  • ESP32 microcontroller
  • GC9A01 240x240 round TFT display
  • TFT_eSPI library (v2.5.43+)

Additional Changes

This PR also includes a bug fix for the rotary encoder ALT usermod that prevents palette navigation wraparound when decrementing from index 0.

Testing

Thoroughly tested on ESP32-D0WDQ6 with GC9A01 display. All features verified including power management, color synchronization, and rotary encoder integration.

Files Changed

  • New usermod: usermods/usermod_v2_gc9a01_display/ (5 files)
  • Bug fix: usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.cpp (line 895)

Summary by CodeRabbit

  • New Features

    • GC9A01 240x240 round TFT support with full on-device UI: clock, WiFi/power indicators, brightness arc, effect/palette labels, overlays, encoder-driven controls, sleep/wake and backlight/timeout handling; integrates with rotary-encoder UI.
  • Documentation

    • Comprehensive GC9A01 display usermod guide: wiring, setup, usage, build flags, configuration examples, and changelog.
  • Chores

    • Added library manifest for the new usermod and updated ignore rules for development artifacts.

@softhack007 softhack007 added the usermod usermod related label Mar 24, 2026
@softhack007 softhack007 added this to the 16.1 milestone Mar 24, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@usermods/usermod_v2_gc9a01_display/usermod_v2_gc9a01_display.cpp`:
- Around line 817-821: The code always sets overlayUntil to millis() +
overlayInactivityTimeout, ignoring the requested showHowLong and breaking
overlays like displayNetworkInfo() and short rotary overlays; change the
assignment in the overlay activation path so overlayUntil = millis() +
(showHowLong > 0 ? showHowLong : overlayInactivityTimeout) (keeping the existing
activeOverlayMode, overlayText and lastRedraw updates) so explicit durations
passed in (e.g., from displayNetworkInfo()) are honored while still falling back
to overlayInactivityTimeout when no duration is supplied; updateRedrawTime() can
remain as-is to extend on user input.
- Around line 749-764: wakeDisplayFromSleep currently restores the backlight
even when the display/usermod is disabled; modify
UsermodGC9A01Display::wakeDisplayFromSleep to first check the displayEnabled (or
gc9a01.on) flag and return false if the display is disabled, so it does not call
setBacklight, flip displayTurnedOff, or force known* updates when the usermod is
off; locate the checks and variables displayTurnedOff, displayEnabled (or
gc9a01.on), setBacklight(), knownBrightness/knownMode/knownPowerState and gate
the wake logic behind that enabled flag.

In `@usermods/usermod_v2_gc9a01_display/usermod_v2_gc9a01_display.h`:
- Around line 52-53: The displayTimeout field uses uint16_t which overflows for
millisecond values >65,535; change its type to uint32_t (keeping the same
variable name displayTimeout and default 60000) so it can hold up to 300000 ms
(300s); update any places that read/write/serialize displayTimeout
(constructors, parsers, EEPROM/save/load, or RPCs) to use the 32-bit type to
avoid truncation, and run a quick grep for "displayTimeout" to update all
references and casts accordingly while leaving backlight untouched.

In
`@usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.cpp`:
- Around line 642-669: The GC9A01-specific branch that calls
gc9a01Display->wakeDisplay() and gc9a01Display->redraw() must be wrapped with
`#ifdef` USERMOD_GC9A01_DISPLAY so those member calls are only compiled when the
GC9A01 display type is enabled; locate the block that checks if (newState == 0
&& gc9a01Display != nullptr && display == nullptr) and surround its body (the
wakeDisplay()/redraw() calls and the changedState assignments) with the
USERMOD_GC9A01_DISPLAY preprocessor guard to prevent dereferencing the void*
stub when the feature is disabled.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5106a826-f52e-427b-b070-b9ae2914d1fb

📥 Commits

Reviewing files that changed from the base of the PR and between 84866b4 and f9e1182.

📒 Files selected for processing (7)
  • .gitignore
  • usermods/usermod_v2_gc9a01_display/library.json
  • usermods/usermod_v2_gc9a01_display/logo_data.h
  • usermods/usermod_v2_gc9a01_display/readme.md
  • usermods/usermod_v2_gc9a01_display/usermod_v2_gc9a01_display.cpp
  • usermods/usermod_v2_gc9a01_display/usermod_v2_gc9a01_display.h
  • usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.cpp
✅ Files skipped from review due to trivial changes (3)
  • .gitignore
  • usermods/usermod_v2_gc9a01_display/library.json
  • usermods/usermod_v2_gc9a01_display/readme.md

Comment thread usermods/usermod_v2_gc9a01_display/usermod_v2_gc9a01_display.cpp
Comment thread usermods/usermod_v2_gc9a01_display/usermod_v2_gc9a01_display.cpp
Comment thread usermods/usermod_v2_gc9a01_display/usermod_v2_gc9a01_display.h Outdated
srg74 added 21 commits April 6, 2026 12:57
- Honor showHowLong in overlay(): overlayUntil now uses the caller-supplied
  duration when > 0, falling back to overlayInactivityTimeout — fixes short
  rotary overlays and displayNetworkInfo() being held too long
- Guard wakeDisplayFromSleep() with displayEnabled check so backlight/state
  are not restored when the usermod is disabled
- Change displayTimeout from uint16_t to uint32_t to hold values up to
  300 000 ms without overflow
- Wrap GC9A01-specific wakeDisplay()/redraw() calls in rotary encoder ALT
  with #ifdef USERMOD_GC9A01_DISPLAY to prevent void* dereference when
  the display type is not compiled in
## Bug Fixes (PR review follow-up)
- `overlay()`: honor `showHowLong` parameter — overlayUntil now respects explicit durations (e.g. from `displayNetworkInfo()`) instead of always using `overlayInactivityTimeout`
- `wakeDisplayFromSleep()`: skip backlight restore and state reset when `displayEnabled` is false
- `displayTimeout`: widened from `uint16_t` to `uint32_t` to safely hold values up to 300 000 ms
- Rotary encoder ALT: GC9A01 `wakeDisplay()`/`redraw()` calls now guarded by `#ifdef USERMOD_GC9A01_DISPLAY`
@softhack007
Copy link
Copy Markdown
Member

In file included from .pio/libdeps/usermods_esp32/TFT_eSPI/TFT_eSPI.h:101,
from .pio/libdeps/usermods_esp32/TFT_eSPI/TFT_eSPI.cpp:16:
.pio/libdeps/usermods_esp32/TFT_eSPI/Processors/TFT_eSPI_ESP32.h:139:12: fatal error: SPIFFS.h: No such file or directory

I think the reason for the build failure is crazy simple: tasmota has removed SPIFFS 😢 , so the display driver lib fails to compile (even when SPIFFs is not used, the lib needs SPIFFS.h)

You can still build this usermod with the original arduino-esp32 framework from espressif.

WLED/platformio.ini

Lines 305 to 308 in bf948fa

;; espressif platform (optional - needs 300KB extra flash)
;;; arduino-esp32 2.0.17 + esp-idf 4.4.7
;; platform = espressif32@ ~6.13.0
;; platform_packages =

I hope @willmmiles can find a solution in #5479

🤔 in worst case, we could place a fake "spiffs.h" into the usermod folder, so the compiler finds something.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

usermod usermod related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants