LVGL Partial Buffer Problem


I want to use partial Updates with an Epaper Display and LVGL on an STM32. I´ve implemented so far the full refresh with counting up a number in the middle of the Display. Now i want to use the partial Refresh. The Problem is, that when i use the partial update, its just updating with white (but in the right spot). I think its wrong how i use the partial frame buffer.

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

I use a STM32 Nucleo Board.

What do you want to achieve?

I want to have a functional partial refresh.

What have you tried so far?

Ive tried various implementation and debugging.

Code to reproduce

Add the relevant code snippets here.

This is what the driver is doing with the lv_color_t *color_p from my flush function.

#if 1

#if 0
			   unsigned int y =0;

			   if(partial_counter > 2){
					for (y = 0; y < y_difference; y++) {
						for (i = 0; i < x_difference; i++) {
							Epaper_Write_Data(Image[i + (y * (HORIZONTAL_RESOLUTION - 1))]);

Screenshot and/or video

The first zero is in the middle. And after that its just overwriting the area with white. When i do the full update from the epaper Display it´s on the left top corner from the display. How can i achieve to put give the framebuffer from only the part i want to sent so that it is working? Maybe someone has demo code for an epaper display? Mine is from

Does anyone implemented this? It would be very good to have help. Thank you so much in advance. When I´m on my other PC i will add some pictures as well.

your examples is out of lvgl and i dont understand your partial idea.
LVGL normal work is partial flush…

Hello, I will try to make this a little more precise. For me it is related to LVGL, because I am trying to use the framebuffer of LVGL. When I update now the area is only overwritten with white pixels.

I think this is because the framebuffer passed by the static void disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { is read incorrectly.

How does the framebuffer of LVGL work? Can I set the framebuffer so that it only covers the area to be updated? If the complete framebuffer is printed, the number that should appear in the center is at the top left. This means that I can’t just send it pixel by pixel, but only the area relevant for the update, right?

Framebuffer is bad word used here. LVGL render area and flush it.
Then callback must set display to area XYWH and send data to this rectangle from color_p.

Okay, thanks for making that clear. So when i do it like this EPD_Update_Partial((uint8_t *) color_p,area->x1, area->y1,(area->x2), (area->y2)); it should work, right? Than it seems like it is a driver problem. I thought maybe someone has a snippet, how to implement some function like that. In the display driver, after all the initial functions, its increments the color_p and is putting it to the display (see my first post). So normally it should work like that and not only overwrite the area with white instead of the number that should be displayed?

Next you need understand LV_COLOR_DEPTH. This is format of color_p in flush area. When display not equal to this format, you need call convert before update.
Some peaple here show epapers technique, try search epaper…

Thanks for the suggestion. I have read through it again. With the pixel_cb I can adjust the data so that it is one bit per pixel. That also seems to work, because in full refresh everything is displayed correctly.

I have also found the option of activating direct_mode. Now everything is always in the right place and the updates work correctly. The only strange thing now is that the transferred coordinates always cover the entire display area and not just the required area as before. Without the directmode, the area worked fine. Am I missing something?

Here are the settings of the display driver I am using:

	disp_drv.hor_res = MY_DISP_HOR_RES;
	disp_drv.ver_res = MY_DISP_VER_RES;

	disp_drv.flush_cb = disp_flush;
	disp_drv.draw_buf = &draw_buf_dsc_1;
	disp_drv.set_px_cb = my_set_px_cb;

	disp_drv.full_refresh = 0;
	disp_drv.direct_mode = 1;


I didnt change the full_refresh Mode and the area worked fine without setting direct_mode.

Maybe im missunderstant, but i mean direct mode dont use flush_cb… and buffer isnt partial but full screen

Thank you for your effort, your quick answers and your patience. Unfortunately, I don’t understand exactly what you mean.
In the LVGL Doc it`s explained like this

… draw buffer(s) needs to be screen sized. It this case flush_cb will be called only once when all dirty areas are redrawn.

So I assumed that the dirty; redrawn areas are given in the flush_cb. Is there another way to get the area that is refreshed?

Because the direct mode is fitting very well to do the full and the partial refresh in my case. If its not working like i thought I have to switch to the normal mode again.

Thanks :slight_smile:

Yes in direct mode is once called … but this mode is for MCU with for example hw based flush and your callback is empty or as writed in docu for double buffer you need copy buffers and other jobs.

For example STM LTDC.

But im not expert for this mode, then maybe can handle epaper, but i mean full buffer is waste of spece , specialy for displays with internal memory.