Swapping Red and Blue on RGB565 setup


What MCU/Processor/Board and compiler are you using?

A board set that was a laundromat POS terminal in its first life ;-). (MAC-Gray, Corp LPOS BOARD.) Has an AT91SAM9263 MCU, 64MB of DRAM, 256MB of FLASH…and a 320x240 TFT LCD panel. Due to CPU limitations (and hardware setup, haha!), the LCD output is RGB565.

Compiler setup is RT-Thread 5.0.0 with GCC (arm-none-eabi) with a custom BSP to support the '9263 (as the register map is considerably different from the RT-Thread supported '9260.)

What LVGL version are you using?

8.3.1, the latest that comes with RT-Thread 5.0.0

What do you want to achieve?

Trying to get LVGL graphics to display in the right colors on the LCD ;-). Graphics works perfectly on the LCD with one exception: red and blue colors are reversed. Tell LVGL to draw in red, and it draws in blue. Tell LVGL to draw in blue, and it draws in red. (Green is fine.)

What have you tried so far?

Everything I could ;-).

  • tried changing big-endian and little-endian in the AT91SAM9263 LCDC driver–THAT didn’t work, as it actually swapped odd and even pixels. Made anti-aliasing a complete mess!
  • tried LV_COLOR_16_SWAP. THAT didn’t work, because it isn’t a byte-swap issue.
  • tried going through “lv_color.h” and changing every definition near a “LV_COLOR_16_SWAP” to reverse red & blue, but THAT didn’t fully work. (It did work on specified colors, though.)

Is swapping red & blue a major under-the-hood revamp for LVGL? I guess I could implement the change in “lcd_fb_flush” (lv_port_disp.c), but to me it should seem that there would be a lower level adjustment for any and all drawing functions?

This week I had a similar problem with my board based on ESP32 and a SPI TFT.
I dont know if your problem can be the same, but take a look at this

Unfortunately there are several significant differences between that issue and my issue.

  • I’m not using an SPI LCD (or an ESP32)–this is a TFT LCD driver that’s a peripheral on an ARM926 CPU. In other words, LVGL literally blits its framebuffer(s) directly to video memory (which goes directly to the LCD)–there is no SPI protocol involved.
  • Dug around, but I can’t find “color_format” anywhere in the LVGL source code, much less in the “lv_disp_drv_t” struct in “lv_hal_disp.h” (which my main application sets up in the “lv_port_disp_init” function call). I’m suspecting that “color_format” this is part of the SPI LCD driver in your case.

It’s highly possible that this board has the 5 “Red” lines and the 5 “Blue” lines (for an RGB565) to the LCD swapped in hardware. But as it’s at least a 6-layer board…and the CPU is a 324-ball BGA, it’s impossible to confirm this for sure. Still, I would think this would be an easy LVGL “tweak”.

Here’s how it appears with the default LVGL setup.

only solution I’ve yet found (though I’m sure there has to be a better one somewhere!) is to manually swap the Red and Blue channels in the user “lcd_fb_flush” function (which could literally use DMA to copy the framebuffer to the video memory except for this issue!)

			swap = color_p->full & 0x07E0;				// green
			swap |= (color_p->full >> 11) & 0x1F;		// red
			swap |= (color_p->full & 0x1F) << 11;		// blue
			fbp16[location].full = swap;
            //fbp16[location].full = color_p->full;

Result is as follows:

but to me, this is a hack, not a solution ;-).

I wasnt sure if the problem can be the same, but as I had similar behavior and just wanted to comment, who knows…
Even I had a temporally similar bypass solution: a software byte swap in the display callback, not color swap as you, but really similar.