Display flush callback and convertsion v8.4.0 to v9.5.0

I am a struggling LVGL newbie, trying to convert code I didn’t write. The source is v8.4.0, and the target is v9.5.0. After jumping a few minor hurdles, I’m now stuck with how to write a flush buffer callback. Again, bearing in mind that this is not my code (and I don’t claim to understand it), this is what I see in the v8.4.0-based code:

// Display flushing 
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
  uint32_t w = (area->x2 - area->x1 + 1);
  uint32_t h = (area->y2 - area->y1 + 1);
  
#if (LV_COLOR_16_SWAP != 0)
  gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#else
  gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#endif

  lv_disp_flush_ready(disp);
}

The migration docs at Changelog — LVGL documentation mention the flush callback, and Display interface — LVGL documentation talks about writing a (slow) callback, but mentions that the part that does the actual work has to be our own code.

I have no idea how to begin with this, as I neither understand the source nor what needs to be done to write that subcode (nor why I would want to, just to get a slow result) … let alone what might be done to improve it. This seems a pretty big gap for a migration document. Is there any hope, or should I continue on with 8.4, which kina-sorta works for me?

Start with understanding what LVGL is. Primary function is render in memory = no display result. This last step is move data to display and based on display interfaces here exist many ways. Manage this isnt part of LVGL.
In your code this manage gfx-> driver…
LVGL any version only declares callback prototype for do this . For some type of MCU and displays display flush callback is empty func. But default in LVGL is partial flush = area is transfered to display.

Migrating between v8 v9 is only change prototype and some little in driver definition.

void my_disp_flush( lv_display_t *disp, const lv_area_t *area, unsigned char *color_p )

as you see v9 change type for first param …

Hi

Regarding the flush callback, the equivalent should be something like this:

//In V9
static void my_disp_flush(lv_disp_t *disp, const lv_area_t *area, uint8_t *pxmap)
{
    uint32_t w = (area->x2 - area->x1 + 1);
    uint32_t h = (area->y2 - area->x1 + 1);

#if (LV_COLOR_16_SWAP != 0)
    gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)pxmap, w, h);
#else
    gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)pxmap, w, h);
#endif

    lv_disp_flush_ready(disp);
}

The main difference, is that instead of the function receives a pointer to array of lv_color_t it receives a pointer to array of uint8_t.

Regarding the slowmentioned in the documentation, is related to the fact that this function gfx->draw16bitRGBBitmap is blocking, and not using “DMA” that could release the CPU to process “stuff” instead of waiting to send the data.

1 Like

implement the function as below, note that you need to call the appropriate draw function depending on your color format

void my_disp_flush(lv_display_t *display, const lv_area_t *area, uint8_t *data)
{

  uint32_t w = lv_area_get_width(area);
  uint32_t h = lv_area_get_height(area);

  gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)data, w, h);
  lv_display_flush_ready(display);

}
lv_display_set_color_format(lv_display, LV_COLOR_FORMAT_RGB565);

LV_COLOR_FORMAT_RGB565_SWAPPED is supported as another color format instead of using the LV_COLOR_16_SWAP flag

void my_disp_flush(lv_display_t *display, const lv_area_t *area, uint8_t *data)
{

  uint32_t w = lv_area_get_width(area);
  uint32_t h = lv_area_get_height(area);

  gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)data, w, h);
  lv_display_flush_ready(display);
}
lv_display_set_color_format(lv_display, LV_COLOR_FORMAT_RGB565_SWAPPED);
1 Like

Thank you very much for your answer. Diving deeper into this, I decided to abandon the idea since there is SO MUCH more to this conversion than originally obvious, and SO MUCH left out of the migration document (probably because a certain level of knowledge is assumed).

I ran into problems with code like the following, that is simply not addressed (or not so that I’d recognize it anyway) in any migration or upgrade documentation or tech help site that I’ve located. I get lost in the confusion.


  lv_disp_draw_buf_init(&draw_buf, buf, NULL, LCD_WIDTH * LCD_HEIGHT / 10);

  // Initialize the display
  static lv_disp_drv_t disp_drv;
  static lv_indev_drv_t indev_drv;
  lv_disp_drv_init(&disp_drv);
  disp_drv.hor_res = LCD_WIDTH;
  disp_drv.ver_res = LCD_HEIGHT;
  disp_drv.flush_cb = my_disp_flush;
  disp_drv.rounder_cb = example_lvgl_rounder_cb;
  disp_drv.draw_buf = &draw_buf;
  disp_drv.sw_rotate = 1 ;
  disp_drv.rotated = LV_DISP_ROT_270 ;
  lv_disp_drv_register(&disp_drv);
  lv_indev_drv_init(&indev_drv); // DBG moved up 1
  indev_drv.type = LV_INDEV_TYPE_POINTER; // DBG moved up 1
  lv_indev_drv_register(&indev_drv); // DBG moved up 1

EACH_LINE!!! above seems to be an exercise in futility for anyone at my level. A shame, but I get it. I guess.

By the way, it was that 270-degree rotation that made me want to upgrade. With it, my display is distorted. Without it, the display is clean (but of course oriented incorrectly). I expect that’s a bug, possibly resolved in v9. But alas!

And if you’re even more curious, the hardware is Waveshare’s ESP32-S3-Touch-AMOLED-1.75 display. Unfortunately, all their example code uses LVGL 8.4 and really-backlevel on most everything else.

I am assuming you are using Arduino framework, unfortunately they have examples for LVGL V9 but it’s only for ESP-IDF.

You can check, the source code they have for the 2.41" Amoled display, the controller seems to be the same, but the example for Arduino seems to be done with LVGL V9. ( ESP32-S3-Touch-AMOLED-2.41 - Waveshare Wiki)

Hmmm… great tip! I’ve been avoiding the (probably inevitable) excursion into ESP-IDF-land. Thanks.

@delovelady Here is an implementation of the Waveshare S3 1.75 466x466 AMOLED board with LVGL v9, perhaps this could help. Also, reach out if you need more help

Thanks, @fbiego , but I don’t know how to read this… was the link you sent, the one you meant to send? I rattled around on the linked github site (especially in that src directory) but didn’t see anything applicable.

I realize I’m missing a lot lately, so it’s probably me.

@delovelady

If you can you really want to learn how to use the ESP-IDF directly. The Arduino IDE uses a hacked up version of the ESP-IDF and it adds a lot of overhead and you will also be limited in a lot of advanced features that are seen with using the ESP-IDF.

It’s actually easier than you think to use the ESP-IDF to compile unless you are running under Windows and in that case you need to set up and use WSL (comes with Windows 10+).