Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion docs/library/framebuf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,20 @@ Constants

.. data:: framebuf.RGB565

Red Green Blue (16-bit, 5+6+5) color format
Red Green Blue (16-bit, 5+6+5, native) color format in native byte-order.

.. data:: framebuf.RGB565_LE

Red Green Blue (16-bit, 5+6+5, little-endian) color format in little-endian
byte order. This defines a 16-bit format where the bytes are stored in
little-endian order. If the system is little-endian, this is the same as
``RGB565``.

.. data:: framebuf.RGB565_BE

Red Green Blue (16-bit, 5+6+5, big-endian) color format in big-endian byte
order. This defines a 16-bit format where the bytes are stored in
big-endian order. If the system is big-endian, this is the same as ``RGB565``.

.. data:: framebuf.GS2_HMSB

Expand Down
7 changes: 7 additions & 0 deletions examples/natmod/framebuf/framebuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
mp_store_global(MP_QSTR_MVLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB));
mp_store_global(MP_QSTR_MONO_VLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB));
mp_store_global(MP_QSTR_RGB565, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565));
#if MP_ENDIANNESS_LITTLE
mp_store_global(MP_QSTR_RGB565_LE, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565));
mp_store_global(MP_QSTR_RGB565_BE, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565_BS));
#else
mp_store_global(MP_QSTR_RGB565_BE, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565));
mp_store_global(MP_QSTR_RGB565_LE, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565_BS));
#endif
mp_store_global(MP_QSTR_GS2_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS2_HMSB));
mp_store_global(MP_QSTR_GS4_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS4_HMSB));
mp_store_global(MP_QSTR_GS8, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS8));
Expand Down
42 changes: 34 additions & 8 deletions extmod/modframebuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,14 @@ typedef struct _mp_framebuf_p_t {
} mp_framebuf_p_t;

// constants for formats
#define FRAMEBUF_MVLSB (0)
#define FRAMEBUF_RGB565 (1)
#define FRAMEBUF_GS2_HMSB (5)
#define FRAMEBUF_GS4_HMSB (2)
#define FRAMEBUF_GS8 (6)
#define FRAMEBUF_MHLSB (3)
#define FRAMEBUF_MHMSB (4)
#define FRAMEBUF_MVLSB (0)
#define FRAMEBUF_RGB565 (1)
#define FRAMEBUF_RGB565_BS (7)
#define FRAMEBUF_GS2_HMSB (5)
#define FRAMEBUF_GS4_HMSB (2)
#define FRAMEBUF_GS8 (6)
#define FRAMEBUF_MHLSB (3)
#define FRAMEBUF_MHMSB (4)

// Functions for MHLSB and MHMSB

Expand Down Expand Up @@ -117,7 +118,10 @@ static void mvlsb_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigne
}
}

// Functions for RGB565 format
// Functions for RGB565 and RGB565_BS format
//
// Internally we use 'native' and 'byte-swapped' formats, and then expose those as big- or little-
// endian to Python as appropriate.

static void rgb565_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
((uint16_t *)fb->buf)[x + y * fb->stride] = col;
Expand All @@ -127,7 +131,20 @@ static uint32_t rgb565_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, uns
return ((uint16_t *)fb->buf)[x + y * fb->stride];
}

static void rgb565_bs_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
col = __builtin_bswap16(col);
((uint16_t *)fb->buf)[x + y * fb->stride] = col;
}

static uint32_t rgb565_bs_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
uint32_t col = ((uint16_t *)fb->buf)[x + y * fb->stride];
return __builtin_bswap16(col);
}

static void rgb565_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
if (fb->format == FRAMEBUF_RGB565_BS) {
col = __builtin_bswap16(col);
}
uint16_t *b = &((uint16_t *)fb->buf)[x + y * fb->stride];
while (h--) {
for (unsigned int ww = w; ww; --ww) {
Expand Down Expand Up @@ -234,6 +251,7 @@ static void gs8_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned
static mp_framebuf_p_t formats[] = {
[FRAMEBUF_MVLSB] = {mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect},
[FRAMEBUF_RGB565] = {rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect},
[FRAMEBUF_RGB565_BS] = {rgb565_bs_setpixel, rgb565_bs_getpixel, rgb565_fill_rect},
[FRAMEBUF_GS2_HMSB] = {gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect},
[FRAMEBUF_GS4_HMSB] = {gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect},
[FRAMEBUF_GS8] = {gs8_setpixel, gs8_getpixel, gs8_fill_rect},
Expand Down Expand Up @@ -310,6 +328,7 @@ static mp_obj_t framebuf_make_new_helper(size_t n_args, const mp_obj_t *args_in,
bpp = 8;
break;
case FRAMEBUF_RGB565:
case FRAMEBUF_RGB565_BS:
bpp = 16;
break;
default:
Expand Down Expand Up @@ -909,6 +928,13 @@ static const mp_rom_map_elem_t framebuf_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_MVLSB), MP_ROM_INT(FRAMEBUF_MVLSB) },
{ MP_ROM_QSTR(MP_QSTR_MONO_VLSB), MP_ROM_INT(FRAMEBUF_MVLSB) },
{ MP_ROM_QSTR(MP_QSTR_RGB565), MP_ROM_INT(FRAMEBUF_RGB565) },
#if MP_ENDIANNESS_LITTLE
{ MP_ROM_QSTR(MP_QSTR_RGB565_LE), MP_ROM_INT(FRAMEBUF_RGB565) },
{ MP_ROM_QSTR(MP_QSTR_RGB565_BE), MP_ROM_INT(FRAMEBUF_RGB565_BS) },
#elif MP_ENDIANNESS_BIG
{ MP_ROM_QSTR(MP_QSTR_RGB565_BE), MP_ROM_INT(FRAMEBUF_RGB565) },
{ MP_ROM_QSTR(MP_QSTR_RGB565_LE), MP_ROM_INT(FRAMEBUF_RGB565_BS) },
#endif // MP_ENDIANNESS_...
{ MP_ROM_QSTR(MP_QSTR_GS2_HMSB), MP_ROM_INT(FRAMEBUF_GS2_HMSB) },
{ MP_ROM_QSTR(MP_QSTR_GS4_HMSB), MP_ROM_INT(FRAMEBUF_GS4_HMSB) },
{ MP_ROM_QSTR(MP_QSTR_GS8), MP_ROM_INT(FRAMEBUF_GS8) },
Expand Down
93 changes: 48 additions & 45 deletions tests/extmod/framebuf16.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
print("SKIP")
raise SystemExit

# This test and its .exp file is based on a little-endian architecture.
if sys.byteorder != "little":
print("SKIP")
raise SystemExit
if (sys.byteorder == "little" and framebuf.RGB565 == framebuf.RGB565_LE) or (
sys.byteorder == "big" and framebuf.RGB565 == framebuf.RGB565_BE
):
print("Native format matches expected value.")
else:
print("Unexpected native format.")


def printbuf():
Expand All @@ -17,50 +19,51 @@ def printbuf():
print("-->8--")


w = 4
h = 5
buf = bytearray(w * h * 2)
fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.RGB565)
for format in [framebuf.RGB565_LE, framebuf.RGB565_BE]:
w = 4
h = 5
buf = bytearray(w * h * 2)
fbuf = framebuf.FrameBuffer(buf, w, h, format)

# fill
fbuf.fill(0xFFFF)
printbuf()
fbuf.fill(0x0000)
printbuf()
# fill
fbuf.fill(0xFFFF)
printbuf()
fbuf.fill(0x0000)
printbuf()

# put pixel
fbuf.pixel(0, 0, 0xEEEE)
fbuf.pixel(3, 0, 0xEE00)
fbuf.pixel(0, 4, 0x00EE)
fbuf.pixel(3, 4, 0x0EE0)
printbuf()
# put pixel
fbuf.pixel(0, 0, 0xEEEE)
fbuf.pixel(3, 0, 0xEE00)
fbuf.pixel(0, 4, 0x00EE)
fbuf.pixel(3, 4, 0x0EE0)
printbuf()

# get pixel
print(fbuf.pixel(0, 4), fbuf.pixel(1, 1))
# get pixel
print(fbuf.pixel(0, 4), fbuf.pixel(1, 1))

# scroll
fbuf.fill(0x0000)
fbuf.pixel(2, 2, 0xFFFF)
printbuf()
fbuf.scroll(0, 1)
printbuf()
fbuf.scroll(1, 0)
printbuf()
fbuf.scroll(-1, -2)
printbuf()
# scroll
fbuf.fill(0x0000)
fbuf.pixel(2, 2, 0xFFFF)
printbuf()
fbuf.scroll(0, 1)
printbuf()
fbuf.scroll(1, 0)
printbuf()
fbuf.scroll(-1, -2)
printbuf()

w2 = 2
h2 = 3
buf2 = bytearray(w2 * h2 * 2)
fbuf2 = framebuf.FrameBuffer(buf2, w2, h2, framebuf.RGB565)
w2 = 2
h2 = 3
buf2 = bytearray(w2 * h2 * 2)
fbuf2 = framebuf.FrameBuffer(buf2, w2, h2, format)

fbuf2.fill(0x0000)
fbuf2.pixel(0, 0, 0x0EE0)
fbuf2.pixel(0, 2, 0xEE00)
fbuf2.pixel(1, 0, 0x00EE)
fbuf2.pixel(1, 2, 0xE00E)
fbuf.fill(0xFFFF)
fbuf.blit(fbuf2, 3, 3, 0x0000)
fbuf.blit(fbuf2, -1, -1, 0x0000)
fbuf.blit(fbuf2, 16, 16, 0x0000)
printbuf()
fbuf2.fill(0x0000)
fbuf2.pixel(0, 0, 0x0EE0)
fbuf2.pixel(0, 2, 0xEE00)
fbuf2.pixel(1, 0, 0x00EE)
fbuf2.pixel(1, 2, 0xE00E)
fbuf.fill(0xFFFF)
fbuf.blit(fbuf2, 3, 3, 0x0000)
fbuf.blit(fbuf2, -1, -1, 0x0000)
fbuf.blit(fbuf2, 16, 16, 0x0000)
printbuf()
58 changes: 58 additions & 0 deletions tests/extmod/framebuf16.py.exp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Native format matches expected value.
--8<--
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff')
Expand Down Expand Up @@ -55,3 +56,60 @@ bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xe0\x0e')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff')
-->8--
--8<--
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff')
-->8--
--8<--
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
-->8--
--8<--
bytearray(b'\xee\xee\x00\x00\x00\x00\xee\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\xee\x00\x00\x00\x00\x0e\xe0')
-->8--
238 0
--8<--
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\xff\xff\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
-->8--
--8<--
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\xff\xff\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
-->8--
--8<--
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\xff\xff')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
-->8--
--8<--
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\xff\xff\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\xff\xff')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
-->8--
--8<--
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xe0\x0e\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\x0e\xe0')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff')
-->8--
Loading