From 11ad249e4675cec22e924af83feaf0eba31d72e7 Mon Sep 17 00:00:00 2001 From: Luke Hoersten Date: Sun, 14 Jun 2026 18:08:50 -0500 Subject: M5 colors fixed: JPEG byte order + DPI memory layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two channel-swap bugs were stacked, hiding each other on symmetric pixels (white text on black background) and showing up only on saturated colour JPEGs: 1. jpeg_decoder: rgb_order was JPEG_DEC_RGB_ELEMENT_ORDER_RGB which empirically emits the RGB565 word in big-endian byte order (the IDF header comment "color component in big endian" is correct; the enum's "RGB" name is misleading). Our painter reads native LE uint16_t, so the bytes were always swapped. Flipped to _BGR which emits LE — verified by dumping decoded bytes for solid red/green/blue JPEGs. 2. display: rgb565_to_rgb888 wrote bytes [R, G, B], but the ESP32-P4 DSI engine + TC358762 + Pi panel expect [B, G, R] in memory despite the "RGB888" label. (MIPI DSI defines bit order, not byte position in memory.) Verified with an embedded solid-blue test JPEG: with [R, G, B] the panel showed solid red; with [B, G, R] it shows solid blue. Diagnosed by embedding a 480x800 blue test JPEG in firmware, decoding + dumping the buffer at boot, and reading the actual bytes over USB serial (ethernet was disconnected mid-investigation). The temporary self-test + debug dump are removed; the fixes themselves are tiny. --- main/jpeg_decoder.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'main/jpeg_decoder.c') diff --git a/main/jpeg_decoder.c b/main/jpeg_decoder.c index 259af65..f2a7d92 100644 --- a/main/jpeg_decoder.c +++ b/main/jpeg_decoder.c @@ -70,12 +70,11 @@ esp_err_t jpeg_decoder_decode(size_t jpeg_len, jpeg_decode_cfg_t dec_cfg = { .output_format = JPEG_DECODE_OUT_FORMAT_RGB565, - .rgb_order = JPEG_DEC_RGB_ELEMENT_ORDER_RGB, - // TODO: known color bug on M5 — solid red renders correctly but solid - // green renders ~black and solid blue renders green. Likely a JPEG - // colorspace / channel-permutation issue, not a byte-order one - // (swapping to BGR turns red into blue, confirming RGB is the right - // element ordering). Needs follow-up. + // Empirically: _RGB emits the RGB565 word in big-endian byte order + // (red 0xF800 → bytes f8 00) which our LE uint16 painter reads + // swapped. _BGR emits little-endian to match (despite the + // misleading "BGR" name) — verified by the decode-byte dump. + .rgb_order = JPEG_DEC_RGB_ELEMENT_ORDER_BGR, .conv_std = JPEG_YUV_RGB_CONV_STD_BT601, }; -- cgit v1.2.3