Framebuffer Refresh Problem

Description

The display shows several Image buttons. As long a button is pressed or an external input is active, a different symbol for the image button is shown.

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

Custom NXP LPC54618 board with TFT LCD-Display 16 bit RGB Interface, Resolution 800 x 480 Pixel.
MCUExpresso V11.5 with gcc Compiler.
LVGL software (master) from github, the processor interface is used from the NXP LVGL SDK example.

What do you want to achieve?

The update of data at the start of memory from Framebuffer is wrong (adressing / buffer problem)

What have you tried so far?

If lv_disp_drv_init() is called with direct_mode = 1 all works correct.
Because I want to rotate the screen, I can`t use the direct_mode.
I have also used two buffers, the effect was the same (also in direct_mode = 1).

Screenshot

On the picture you can the that the first lines shows garbage.

grafik

Any idea what is going wrong ?

Thanks

Klaus

I have another understandig for this problem. It makes a difference when a object is created.

If I call the following function before any “lv_task_handler();”, the display shows the Imagebutton correct.
If this function ic called after “lv_task_handler();” the Imagebutton is not shown and garbage occurs at the beginning of the framebuffer (see picture above).

static void test(void)
{
objTest = lv_imgbtn_create(lv_scr_act());
lv_obj_set_pos(objTest, 200, 200);
lv_obj_set_size(objTest, 80, 80);
lv_imgbtn_set_src(objTest, LV_IMGBTN_STATE_RELEASED, NULL, &my_img[0], NULL);
}

The Memory for LVGL is allocated with
uint16_t Video_RAM1[LCD_PANEL_HEIGHT][LCD_PANEL_WIDTH];

and initialised
lv_disp_draw_buf_init(&disp_buf, (void*)Video_RAM1, NULL, LCD_PANEL_HEIGHT*LCD_PANEL_WIDTH);

In the Flushdisplay function, this memory area is given to the LCD controller.

static void LV_FlushDisplay(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
(void)xSemaphoreTake(s_frameSema, 1000);
LCDC_SetPanelAddr(LCD, kLCDC_UpperPanel, (uint32_t)color_p);
s_framePending = true;
}

This is the same if I use direct_mode or not. Where resides the additional memory if direct_mode is not active ?

Thanks

Klaus

Now if have tested all combinations of direct_mode and full_refresh.

If not rotate, all combinations with the exeption of (.direct_mode = 0) and (.full_refresh = 0) are working correct.
Rotate in (direct_mode = 1) is not possible.
If rotate and (.direct_mode = 0) and (.full_refresh = 0) there is the same wrong result as without rotate.

If rotate and (.direct_mode = 1) and (.full_refresh = 0) there is a mismatch after pressing a key.

This picture shows the start screen
Pic1

If a key is pressed, this Imagebutton toggles and shows the new image. But the rest of the screen is shown as the start screen without rotate. The following picture shows the screen during pressing the button.
Pic2

After release the button, the start screen is shown correct but the pressed Imagebutton is shown on the old position without rotating.
Pic3

Is this a bug or is there a error on my program ?

Thanks

Klaus

Good news, I have solved the problem. The following settings are working:

MyDisp_drv.rotated = LV_DISP_ROT_180;
MyDisp_drv.sw_rotate = 1;

Two buffers
uint16_t attribute ((section (".VRAM_MEMORY")))Framebuffer[LCD_PANEL_HEIGHT][LCD_PANEL_WIDTH];
uint16_t attribute ((section (".VRAM_MEMORY")))Video_RAM[LCD_PANEL_HEIGHT][LCD_PANEL_WIDTH];

The first buffer is for the LCD-Controller and the second for LVGL Data.

The problem was the FlushDisplay() function. Here is my function for a 180 rotated screen.

static void LV_FlushDisplay(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t color_p)
{
lv_disp_t
disp;
uint16_t a;
uint16_t y;
uint16_t x1, x2, y1, y2;

disp = _lv_refr_get_disp_refreshing();

for(a = 0; a < disp->inv_p; a++)
{
	if(disp->inv_area_joined[a])
	{
		continue;
	}

	x1 = LCD_PANEL_WIDTH - 1 - disp->inv_areas[a].x1;
	x2 = LCD_PANEL_WIDTH - 1 - disp->inv_areas[a].x2;
	y1 = LCD_PANEL_HEIGHT - 1 - disp->inv_areas[a].y1;
	y2 = LCD_PANEL_HEIGHT - 1 - disp->inv_areas[a].y2;

	for(y = y2; y < y1; y++)
	{
		memcpy(&Framebuffer[y][x2], color_p + y * LCD_PANEL_WIDTH + x2, (x1 - x2) * sizeof(lv_color_t));
	}
}

/* IMPORTANT!!! Inform the graphics library that you are ready with the flushing*/
lv_disp_flush_ready(&MyDisp_drv);

}

Klaus

1 Like