From 3147fc2f52cdaa1899bf175433e168ad8cee8343 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 26 Aug 2024 12:30:40 +0200 Subject: [PATCH] fix(i1): fix compiler and runtime issues with I1 rendering (#6714) Co-authored-by: Liam <30486941+liamHowatt@users.noreply.github.com> --- docs/porting/display.rst | 37 +++++++++++++++++++++++++++++++++++-- lv_conf_template.h | 2 +- src/core/lv_refr.c | 14 +++++++++++--- src/draw/lv_draw_buf.c | 4 ++-- src/lv_conf_internal.h | 2 +- src/misc/lv_color.h | 8 +++++++- 6 files changed, 57 insertions(+), 10 deletions(-) diff --git a/docs/porting/display.rst b/docs/porting/display.rst index 2541ae239..4053d7fb7 100644 --- a/docs/porting/display.rst +++ b/docs/porting/display.rst @@ -136,7 +136,6 @@ or anything else to optimize while the waiting for flush. If ``flush_wait_cb`` is not set, LVGL assume that `lv_display_flush_ready` is used. - Rotation -------- @@ -173,7 +172,7 @@ The default color format of the display is set according to :c:macro:`LV_COLOR_D - :c:macro:`LV_COLOR_DEPTH` ``24``: RGB888 (3 bytes/pixel) - :c:macro:`LV_COLOR_DEPTH` ``16``: RGB565 (2 bytes/pixel) - :c:macro:`LV_COLOR_DEPTH` ``8``: L8 (1 bytes/pixel) -- :c:macro:`LV_COLOR_DEPTH` ``1``: I1 (1 bit/pixel) Only support for horizontal mapped buffers. +- :c:macro:`LV_COLOR_DEPTH` ``1``: I1 (1 bit/pixel) Only support for horizontal mapped buffers. See :refr:`monochrome` for more details: The ``color_format`` can be changed with :cpp:expr:`lv_display_set_color_depth(display, LV_COLOR_FORMAT_...)`. @@ -205,6 +204,40 @@ to ``GGG BBBBB | RRRRR GGG``. +.. _monochrome: + +Monochrome Displays +------------------- + +LVGL supports rendering directly in a 1-bit format for monochrome displays. +To enable it, set ``LV_COLOR_DEPTH 1`` or use :cpp:expr:`lv_display_set_color_format(display, LV_COLOR_FORMAT_I1)`. + +The :cpp:expr:`LV_COLOR_FORMAT_I1` format assumes that bytes are mapped to rows (i.e., the bits of a byte are written next to each other). +The order of bits is MSB first, which means: + +.. code:: + + MSB LSB + bits 7 6 5 4 3 2 1 0 + pixels 0 1 2 3 4 5 6 7 + Left Right + +Ensure that the LCD controller is configured accordingly. + +Internally, LVGL rounds the redrawn areas to byte boundaries. Therefore, updated areas will: + +- Start on an ``Nx8`` coordinate. +- End on an ``Nx8 - 1`` coordinate. + +When setting up the buffers for rendering (:cpp:func:`lv_display_set_buffers`), make the buffer 8 bytes larger. +This is necessary because LVGL reserves 2 x 4 bytes in the buffer, as these are assumed to be used as a palette. + +To skip the palette, include the following line in your ``flush_cb`` function: ``px_map += 8``. + +As usual, monochrome displays support partial, full, and direct rendering modes as well. +In full and direct modes, the buffer size should be large enough for the whole screen, meaning ``(horizontal_resolution x vertical_resolution / 8) + 8`` bytes. +As LVGL can not handle fractional width make sure to round the horizontal resolution to 8- +(For example 90 to 96) User data --------- diff --git a/lv_conf_template.h b/lv_conf_template.h index 1086abc83..ddf71cd13 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -26,7 +26,7 @@ COLOR SETTINGS *====================*/ -/*Color depth: 8 (A8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/ +/*Color depth: 1 (I1), 8 (L8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/ #define LV_COLOR_DEPTH 16 /*========================= diff --git a/src/core/lv_refr.c b/src/core/lv_refr.c index 736938636..13a2608e6 100644 --- a/src/core/lv_refr.c +++ b/src/core/lv_refr.c @@ -291,6 +291,13 @@ void lv_inv_area(lv_display_t * disp, const lv_area_t * area_p) suc = lv_area_intersect(&com_area, area_p, &scr_area); if(suc == false) return; /*Out of the screen*/ + if(disp->color_format == LV_COLOR_FORMAT_I1) { + /*Make sure that the X coordinates start and end on byte boundary. + *E.g. convert 11;27 to 8;31*/ + com_area.x1 &= ~0x7; /*Round down: Nx8*/ + com_area.x2 |= 0x7; /*Round up: Nx8 - 1*/ + } + /*If there were at least 1 invalid area in full refresh mode, redraw the whole screen*/ if(disp->render_mode == LV_DISPLAY_RENDER_MODE_FULL) { disp->inv_areas[0] = scr_area; @@ -1101,10 +1108,11 @@ static void refr_obj(lv_layer_t * layer, lv_obj_t * obj) static uint32_t get_max_row(lv_display_t * disp, int32_t area_w, int32_t area_h) { - bool has_alpha = lv_color_format_has_alpha(disp->color_format); - lv_color_format_t cf = has_alpha ? LV_COLOR_FORMAT_ARGB8888 : disp->color_format; + lv_color_format_t cf = disp->color_format; uint32_t stride = lv_draw_buf_width_to_stride(area_w, cf); - int32_t max_row = (uint32_t)disp->buf_act->data_size / stride; + uint32_t overhead = LV_COLOR_INDEXED_PALETTE_SIZE(cf) * sizeof(lv_color32_t); + + int32_t max_row = (uint32_t)(disp->buf_act->data_size - overhead) / stride; if(max_row > area_h) max_row = area_h; diff --git a/src/draw/lv_draw_buf.c b/src/draw/lv_draw_buf.c index 9050f355e..daebe9543 100644 --- a/src/draw/lv_draw_buf.c +++ b/src/draw/lv_draw_buf.c @@ -168,9 +168,9 @@ void lv_draw_buf_clear(lv_draw_buf_t * draw_buf, const lv_area_t * a) if(lv_area_get_width(&a_clipped) <= 0) return; if(lv_area_get_height(&a_clipped) <= 0) return; - uint8_t px_size = lv_color_format_get_size(header->cf); uint8_t * buf = lv_draw_buf_goto_xy(draw_buf, a_clipped.x1, a_clipped.y1); - uint32_t line_length = lv_area_get_width(&a_clipped) * px_size; + uint8_t bpp = lv_color_format_get_bpp(header->cf); + uint32_t line_length = (lv_area_get_width(&a_clipped) * bpp + 7) >> 3; int32_t y; for(y = a_clipped.y1; y <= a_clipped.y2; y++) { lv_memzero(buf, line_length); diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 4268d97c4..f8002f678 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -83,7 +83,7 @@ COLOR SETTINGS *====================*/ -/*Color depth: 8 (A8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/ +/*Color depth: 1 (I1), 8 (L8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/ #ifndef LV_COLOR_DEPTH #ifdef CONFIG_LV_COLOR_DEPTH #define LV_COLOR_DEPTH CONFIG_LV_COLOR_DEPTH diff --git a/src/misc/lv_color.h b/src/misc/lv_color.h index 13b948710..6328c0d2c 100644 --- a/src/misc/lv_color.h +++ b/src/misc/lv_color.h @@ -171,7 +171,10 @@ typedef enum { LV_COLOR_FORMAT_YUV_END = LV_COLOR_FORMAT_UYVY, /*Color formats in which LVGL can render*/ -#if LV_COLOR_DEPTH == 8 +#if LV_COLOR_DEPTH == 1 + LV_COLOR_FORMAT_NATIVE = LV_COLOR_FORMAT_I1, + LV_COLOR_FORMAT_NATIVE_WITH_ALPHA = LV_COLOR_FORMAT_I1, +#elif LV_COLOR_DEPTH == 8 LV_COLOR_FORMAT_NATIVE = LV_COLOR_FORMAT_L8, LV_COLOR_FORMAT_NATIVE_WITH_ALPHA = LV_COLOR_FORMAT_AL88, #elif LV_COLOR_DEPTH == 16 @@ -183,7 +186,10 @@ typedef enum { #elif LV_COLOR_DEPTH == 32 LV_COLOR_FORMAT_NATIVE = LV_COLOR_FORMAT_XRGB8888, LV_COLOR_FORMAT_NATIVE_WITH_ALPHA = LV_COLOR_FORMAT_ARGB8888, +#else +#error "LV_COLOR_DEPTH should be 1, 8, 16, 24 or 32" #endif + } lv_color_format_t; #define LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf) ((cf) >= LV_COLOR_FORMAT_A1 && (cf) <= LV_COLOR_FORMAT_A8)