Brendan Ang

Search

Search IconIcon to open search

endianess goddammit

Last updated Feb 3, 2025 Edit Source

# endianess goddammit

Let’s say we want to transmit RGB-565 data over the wire using SPI with the ESP32. How does that look like?

Let’s assume your target is the ST7796, to make that pixel beautifully pastel pink 0xF435, it expects the data to arrive like this:

1
2
3
4
5
Data: 0xF 0x4 0x3 0x5

in bits: R(11110) G(100 001) (10101)

Time: 1st -----------...last

We use tiny jpeg, to decode a jpeg file into its raw bytes. Crucially, this section:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
/* Convert RGB888 to RGB565 if needed */
if (JD_FORMAT == 1) {
    uint8_t *s = (uint8_t *)jd->workbuf;
    uint16_t w, *d = (uint16_t *)s;
    unsigned int n = rx * ry;

    do {
        w = (*s++ & 0xF8) << 8;     /* RRRRR----------- */
        w |= (*s++ & 0xFC) << 3;    /* -----GGGGGG----- */
        w |= *s++ >> 3;             /* -----------BBBBB */
        *d++ = w;
    } while (--n);
}

The pixel data is set into a uint16_t variable as you would expect, in RGB order, with R as the MSB. ESP32 is little endian (least significant byte is at a lower address), so here are the bytes when placed in a contiguous array of memory uint16_t arr[]

1
2
3
4
5
6
LO 
| bit[7:0]
| 0x35 (GB)
| 0xF4 (RG)
...
HI

The SPI master transmit order is most significant bit first, transmitting 1 byte at a time in a for loop through arr, we send:

1
2
3
4
5
Data: 0x3 0x5 0xF 0x4

in bits: R(00110) G(101 111) (10100)

Time: 1st -----------...last

To fix this, tiny jpeg has a flag swap_color_bytes which turns our data into:

1
2
3
4
5
6
LO 
| bit[7:0]
| 0xF4 (GB)
| 0x35 (RG)
...
HI

Note: I found that my display would be set in RGB mode (according to the datasheet, there’s a register named MADCTL where bit 3 would configure it as RGB/BGR), but display colors in BGR instead. This made me rethink the underlying chain of events leading to the image transfer, culminating in this post.