Skip to content

Fix uDisplay case 'T' union corruption for I80 parallel displays + WT32-SC01 Plus descriptor#24506

Open
lz64 wants to merge 1 commit intoarendst:developmentfrom
lz64:fix/udisplay-case-t-union-corruption
Open

Fix uDisplay case 'T' union corruption for I80 parallel displays + WT32-SC01 Plus descriptor#24506
lz64 wants to merge 1 commit intoarendst:developmentfrom
lz64:fix/udisplay-case-t-union-corruption

Conversation

@lz64
Copy link

@lz64 lz64 commented Feb 27, 2026

Description:

Fix: case 'T' in uDisplay descriptor parser corrupts I80 parallel display pin config

The descriptor parser's case 'T' (EPD timing) unconditionally writes to panel_config->epd.lut_full_time, lut_partial_time, and update_time regardless of interface type. In the PanelConfigUnion, these EPD fields overlap with I80 panel bus pin config (cs_pin, dc_pin, wr_pin, rd_pin, data_pins_low[]).

Any non-EPD display with a :T prefixed line in its descriptor (e.g., :TI for old-style touch init) hits case 'T' and corrupts the I80 pin configuration. The display initializes without error but sends data to wrong GPIO pins, resulting in a blank screen.

Root cause: The :TI1,38,5,6,7,4 touch descriptor line is parsed by case 'T', which writes the touch I2C address (38) and SDA pin (5) over the I80 bus WR and D0 pin values in the union.

Fix: Guard the EPD timing writes with if (ep_mode) so they only execute for EPD displays.

Debug evidence (added temporary AddLog after PAR pin parsing):

UDisplay: PAR PARSED cs:-1 dc:0 wr:47 rd:-1 d0:9 d1:46    ← correct at parse time
UDisplay: par mode:3 cs:0 rs:0 wr:38 rd:0 d0:5 d1:0        ← corrupted after case 'T'

Fix: Remove dead berry.lvgl_panel_loaded reference

Commit e4c2cf5 (Berry Extension Manager) removed lvgl_panel_loaded from the BerrySupport class but left a reference in xdrv_54_lvgl.ino line 488 inside #ifdef USE_BERRY_LVGL_PANEL. This causes a compile error when USE_BERRY_LVGL_PANEL is defined.

New: WT32-SC01 Plus (ST7796 parallel 8-bit) display descriptor

Verified working display descriptor for the Wireless Tag WT32-SC01 Plus development board:

  • ESP32-S3 with ST7796U 480x320 16-bit color
  • 8-bit parallel (I80) interface
  • FT5206 capacitive touch controller
  • Includes :B,40,2 for correct color byte order on I80 bus

Tested on Tasmota v15.3.0.1 with LVGL 9.5.0.

Checklist:

  • The pull request is done against the latest development branch
  • Only relevant files were touched
  • Only one feature/fix was added per PR and the code change compiles without warnings
  • The code change is tested and works with Tasmota core ESP8266 V.2.7.8
  • The code change is tested and works with Tasmota core ESP32 V.3.1.9
  • I accept the CLA.

NOTE: ESP8266 checkbox left unchecked — this fix is ESP32-only (I80 parallel displays and LVGL are ESP32 features).

Copilot AI review requested due to automatic review settings February 27, 2026 15:40
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a long-standing Universal Display descriptor parsing issue where :T... lines could corrupt non-EPD panel configurations (notably I80 parallel pin mappings), fixes a compile break in the LVGL driver when USE_BERRY_LVGL_PANEL is enabled, and adds a verified display descriptor for the WT32-SC01 Plus (ST7796, I80 8-bit, FT5206 touch).

Changes:

  • Guard :T (EPD timing) parsing in the uDisplay descriptor parser to prevent config-union corruption on non-EPD displays.
  • Remove a dead berry.lvgl_panel_loaded reference that causes compilation failures under USE_BERRY_LVGL_PANEL.
  • Add a new WT32-SC01 Plus ST7796 PAR8 display descriptor (including I80 byte order and FT5206 touch line).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino Removes obsolete Berry LVGL panel flag reference that no longer exists.
tasmota/displaydesc/WT32-SC01-Plus_ST7796_p8_display.ini Adds a descriptor for WT32-SC01 Plus (ST7796, PAR8) including color byte order and touch line.
lib/lib_display/UDisplay/src/uDisplay.cpp Changes :T parsing behavior to avoid union corruption from non-EPD :TI/:TS descriptor lines.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…WT32-SC01 Plus descriptor

- Skip :TI (touch I2C) and :TS (touch SPI) lines in case 'T' of the uDisplay
  descriptor parser. These touch config lines are handled separately by
  xdsp_17_universal.ino via strstr(), but case 'T' was matching on the first
  character and unconditionally writing the subsequent values into
  panel_config->epd.lut_full_time/lut_partial_time/update_time. In the
  PanelConfigUnion, these EPD fields overlap with I80 panel bus pin config
  (cs_pin, dc_pin, wr_pin, rd_pin, data_pins), causing parallel displays to
  silently receive corrupted GPIO pin assignments and fail to render.

  The fix checks if the character after 'T' is 'I' or 'S' and skips EPD timing
  parsing for those lines. EPD descriptors using :T,<timing> continue to work
  as before.

- Remove dead reference to berry.lvgl_panel_loaded in xdrv_54_lvgl.ino.
  The member was removed from BerrySupport in commit e4c2cf5 (Berry Extension
  Manager) but the reference in start_lvgl() was left behind, causing a compile
  error when USE_BERRY_LVGL_PANEL is defined.

- Add verified display descriptor for WT32-SC01 Plus (ESP32-S3, ST7796U 480x320,
  8-bit parallel I80, FT5206 capacitive touch). Tested on Tasmota v15.3.0.1 with
  LVGL 9.5.0.
@lz64 lz64 force-pushed the fix/udisplay-case-t-union-corruption branch from f22f4c4 to 6cb82e0 Compare February 27, 2026 16:09
@lz64
Copy link
Author

lz64 commented Feb 27, 2026

Good catch — you're absolutely right that ep_mode is computed after the parsing loop completes, so the guard would always be false and break EPD timing.

Updated the fix to check the character after T instead:

case 'T':
    // :TI and :TS are touch config lines handled by xdsp_17_universal.ino
    // Only parse EPD timing when the line is :T,<number> (EPD timing values)
    if (*lp1 != 'I' && *lp1 != 'S') {
        panel_config->epd.lut_full_time = next_val(&lp1);
        panel_config->epd.lut_partial_time = next_val(&lp1);
        panel_config->epd.update_time = next_val(&lp1);
    }
    break;

At the point case 'T' executes, lp1 points to the character right after T (since section = *lp1++ already consumed it). So:

  • :TI1,38,5,6,7,4*lp1 == 'I' → skip (touch I2C, handled by xdsp_17)
  • :TS,16*lp1 == 'S' → skip (touch SPI, handled by xdsp_17)
  • :T,450,10,450*lp1 == ',' → parse EPD timing as before

Force-pushed the corrected commit.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@lz64 lz64 closed this Mar 9, 2026
@lz64 lz64 reopened this Mar 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants