ST7796 SPI display: correct RGB565 data on MCU side, but color channel mis-mapping and smearing with esp_lcd

Karlheinz
Posts: 8
Joined: Sat Sep 07, 2024 1:24 pm

ST7796 SPI display: correct RGB565 data on MCU side, but color channel mis-mapping and smearing with esp_lcd

Postby Karlheinz » Mon Jan 19, 2026 7:54 pm

Hi all,

I am currently debugging a very specific ST7796 display behavior and would like to get some feedback from people who have experience with esp_lcd and ST77xx panel variants.

Hardware / Software setup:
- ST7796-based 320x480 SPI display (common China modules, e.g. from vendors like QDtech, etc.)
- Interface: 4-wire SPI
- MCU: ESP32-S3
- ESP-IDF: 5.5.x
- Stack: esp_lcd + esp_lvgl_port + LVGL v8

Important reference:
- The SAME display works perfectly with TFT_eSPI (Arduino) using the same hardware.
- I extracted and integrated the TFT_eSPI ST7796 init sequence into our esp_lcd setup.
- On the MCU side, color values are verified to be correct.

Verification on MCU side:
- LVGL color generation is correct:
- lv_color_make(255,0,0) logs as 0xF800
- lv_color_make(0,255,0) logs as 0x07E0
- lv_color_make(0,0,255) logs as 0x001F
- First by before MCU write operation ist correct
- Flush callback is correct (area handling with +1, correct buffer type, no repacking).
- SPI mode (0–3), SPI frequency, and endianness changes do NOT resolve the issue.

Observed problem (key point):
1) There is a clear COLOR CHANNEL MIS-MAPPING at full color values:
- Full GREEN and full BLUE are swapped or mixed.
- Full RED is not isolated cleanly either.
- This is NOT a simple RGB/BGR or a byte swap.
- The mapping error is reproducible and systematic.

2) In addition to the channel swap, colors are NOT mapped cleanly:
- Pure colors are “smeared” into other channels.
- Example: green appears yellowish, blue appears washed out or cyan-like.
- This happens even with full-scale RGB565 values.

This strongly suggests:
- The panel internally interprets color data differently than expected.
- Possibly an internal RGB565 → RGB666 / RGB888 mapping issue.
- Or undocumented ST7796 register bits required for certain panel variants.
- Or a column/row or internal color pipeline difference not covered by standard COLMOD/MADCTL settings.

What I already tried:
- Using the TFT_eSPI init sequence in esp_lcd (no improvement)
- MADCTL RGB/BGR toggling (changes colors but never results in correct mapping)
- COLMOD = 0x55 (RGB565)
- SPI mode and clock changes
- DC polarity experiments (affects colors, but unstable and never correct)

Key question:
- Are there known ST7796 panel variants that internally expect 18-bit color or use a non-standard RGB565 mapping, even when COLMOD=0x55?
- Is anyone aware of undocumented ST7796 register settings needed for such panels?
- Has anyone successfully driven similar ST7796 SPI panels with esp_lcd and can share init details?

Any hints, documentation gaps, or real-world experience would be highly appreciated.
We can provide init sequences, photos of test patterns, and full esp_lcd configuration if needed.

Thanks in advance!

Karlheinz
Posts: 8
Joined: Sat Sep 07, 2024 1:24 pm

Re: ST7796 SPI display: correct RGB565 data on MCU side, but color channel mis-mapping and smearing with esp_lcd

Postby Karlheinz » Wed Feb 18, 2026 12:10 pm

Hi everyone,

I wanted to provide an update because I finally found the "ghost in the machine." The issue was not the ST7796 registers or the panel hardware itself, but a conflict in the ESP-IDF build system configuration.

The Root Cause:
In projects using esp_lvgl_port, the settings in sdkconfig (or sdkconfig.defaults) can silently override the defines in your lv_conf.h.

In my case, the missing parameters were being forced by the SDK configuration, leading to the systematic channel swapping and "smeared" colors I described:

CONFIG_LV_COLOR_DEPTH_16=y
CONFIG_LV_COLOR_16_SWAP=y

Because CONFIG_LV_COLOR_16_SWAP was not active in the background, the bytes were being swapped incorrectly, which explained why simple RGB/BGR toggling in MADCTL never yielded a clean result.

Working Setup for ST7796 (SPI) on ESP32-S3:
For anyone struggling with similar my modules MSP3525/MSP3526 (320x480), here are the settings that now produce pixel-perfect colors:

Color Format: RGB565 (COLMOD 0x55).

Color Order: BGR (configured via esp_lcd_panel_dev_config_t).

Inversion: Color inversion must be Enabled (esp_lcd_panel_invert_color(panel_handle, true)).

LVGL Swap: Ensure byte swapping is handled in one place only. If your SPI host handles DMA correctly, you usually want LV_COLOR_16_SWAP to be 0 in lv_conf.h (and n in sdkconfig).

Key takeaway: If you are using the esp_lvgl_port component, always double-check your sdkconfig for CONFIG_LV_... entries. They will win every fight against your manual header definitions!

I hope this saves someone else a few days of debugging.

Best regards,
Karlheinz

Who is online

Users browsing this forum: Baidu [Spider], ChatGPT-User, coccocbot, trendictionbot and 12 guests