From 34247465c34113bb26f6c9582ea31f31b0ea0d1b Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Sat, 15 Jul 2017 15:53:47 +0200 Subject: [PATCH] extmod/modframebuf: Add 2-bit color format (GS2_HMSB). This format is used in 2-color LED matrices and in e-ink displays like SSD1606. --- docs/library/framebuf.rst | 4 +++ extmod/modframebuf.c | 30 +++++++++++++++++ tests/extmod/framebuf2.py | 62 +++++++++++++++++++++++++++++++++++ tests/extmod/framebuf2.py.exp | 57 ++++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+) create mode 100644 tests/extmod/framebuf2.py create mode 100644 tests/extmod/framebuf2.py.exp diff --git a/docs/library/framebuf.rst b/docs/library/framebuf.rst index 74c9f85649..4f0026e380 100644 --- a/docs/library/framebuf.rst +++ b/docs/library/framebuf.rst @@ -148,6 +148,10 @@ Constants Red Green Blue (16-bit, 5+6+5) color format +.. data:: framebuf.GS2_HMSB + + Grayscale (2-bit) color format + .. data:: framebuf.GS4_HMSB Grayscale (4-bit) color format diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index 20e40d5791..f2dc4e858e 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -54,6 +54,7 @@ typedef struct _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_MHLSB (3) #define FRAMEBUF_MHMSB (4) @@ -130,6 +131,30 @@ STATIC void rgb565_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, i } } +// Functions for GS2_HMSB format + +STATIC void gs2_hmsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { + uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride) >> 2]; + uint8_t shift = (x & 0x3) << 1; + uint8_t mask = 0x3 << shift; + uint8_t color = (col & 0x3) << shift; + *pixel = color | (*pixel & (~mask)); +} + +STATIC uint32_t gs2_hmsb_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { + uint8_t pixel = ((uint8_t*)fb->buf)[(x + y * fb->stride) >> 2]; + uint8_t shift = (x & 0x3) << 1; + return (pixel >> shift) & 0x3; +} + +STATIC void gs2_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { + for (int xx=x; xx < x+w; xx++) { + for (int yy=y; yy < y+h; yy++) { + gs2_hmsb_setpixel(fb, xx, yy, col); + } + } +} + // Functions for GS4_HMSB format STATIC void gs4_hmsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { @@ -184,6 +209,7 @@ STATIC void gs4_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, 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_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_MHLSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, [FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, @@ -240,6 +266,9 @@ STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size case FRAMEBUF_MHMSB: o->stride = (o->stride + 7) & ~7; break; + case FRAMEBUF_GS2_HMSB: + o->stride = (o->stride + 3) & ~3; + break; case FRAMEBUF_GS4_HMSB: o->stride = (o->stride + 1) & ~1; break; @@ -579,6 +608,7 @@ 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) }, + { 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_MONO_HLSB), MP_ROM_INT(FRAMEBUF_MHLSB) }, { MP_ROM_QSTR(MP_QSTR_MONO_HMSB), MP_ROM_INT(FRAMEBUF_MHMSB) }, diff --git a/tests/extmod/framebuf2.py b/tests/extmod/framebuf2.py new file mode 100644 index 0000000000..a313170eb5 --- /dev/null +++ b/tests/extmod/framebuf2.py @@ -0,0 +1,62 @@ +try: + import framebuf +except ImportError: + print("SKIP") + raise SystemExit + +def printbuf(): + print("--8<--") + for y in range(h): + for x in range(w): + print('%u' % ((buf[(x + y * w) // 4] >> ((x & 3) << 1)) & 3), end='') + print() + print("-->8--") + +w = 8 +h = 5 +buf = bytearray(w * h // 4) +fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS2_HMSB) + +# fill +fbuf.fill(3) +printbuf() +fbuf.fill(0) +printbuf() + +# put pixel +fbuf.pixel(0, 0, 1) +fbuf.pixel(3, 0, 2) +fbuf.pixel(0, 4, 3) +fbuf.pixel(3, 4, 2) +printbuf() + +# get pixel +print(fbuf.pixel(0, 4), fbuf.pixel(1, 1)) + +# scroll +fbuf.fill(0) +fbuf.pixel(2, 2, 3) +printbuf() +fbuf.scroll(0, 1) +printbuf() +fbuf.scroll(1, 0) +printbuf() +fbuf.scroll(-1, -2) +printbuf() + +w2 = 2 +h2 = 3 +buf2 = bytearray(w2 * h2 // 4) +fbuf2 = framebuf.FrameBuffer(buf2, w2, h2, framebuf.GS2_HMSB) + +# blit +fbuf2.fill(0) +fbuf2.pixel(0, 0, 1) +fbuf2.pixel(0, 2, 2) +fbuf2.pixel(1, 0, 1) +fbuf2.pixel(1, 2, 2) +fbuf.fill(3) +fbuf.blit(fbuf2, 3, 3, 0) +fbuf.blit(fbuf2, -1, -1, 0) +fbuf.blit(fbuf2, 16, 16, 0) +printbuf() diff --git a/tests/extmod/framebuf2.py.exp b/tests/extmod/framebuf2.py.exp new file mode 100644 index 0000000000..c53e518a6e --- /dev/null +++ b/tests/extmod/framebuf2.py.exp @@ -0,0 +1,57 @@ +--8<-- +33333333 +33333333 +33333333 +33333333 +33333333 +-->8-- +--8<-- +00000000 +00000000 +00000000 +00000000 +00000000 +-->8-- +--8<-- +10020000 +00000000 +00000000 +00000000 +30020000 +-->8-- +3 0 +--8<-- +00000000 +00000000 +00300000 +00000000 +00000000 +-->8-- +--8<-- +00000000 +00000000 +00000000 +00300000 +00000000 +-->8-- +--8<-- +00000000 +00000000 +00000000 +00030000 +00000000 +-->8-- +--8<-- +00000000 +00300000 +00000000 +00030000 +00000000 +-->8-- +--8<-- +33333333 +23333333 +33333333 +33311333 +33333333 +-->8--