Sync object display

Description

The main() variable declaration and later while(1) task handling is not synchronised.

MCU in use

STM32F405RGT in a custom board.

What LVGL version are you using?

7.11.0

What do you want to achieve?

I want to call a system function HAL_SPI_Transmit(3) after a image object is drawn to the display.

The goal is to fade (with contrast control) an image.

What have you tried so far?

In main() I tried calling HAL_SPI_Transmit(3) after lv_img_create(3). Because lv_task_handler(3) has not run yet, the lvgl image is not displayed when the SPI command happens. This is the wrong order.

I also tried using a one shot task as well as an asynchronous function, but both of these are called immediately after the variable declarations (before the image is displayed.) Wrong order.

Code to reproduce

int main(void)
{
  lv_obj_t *pScrnsplash = lv_scr_act();
  lv_obj_t *pImage1 = lv_img_create(pScrnsplash, NULL);
  LV_IMG_DECLARE(mylogo);
  lv_img_set_src(pImage1, &mylogo);
  lv_scr_load(pScrnsplash);

  HAL_SPI_Transmit(&hspi1, ...);  // Send the display a SPI command

  while(1) {
    lv_task_handler();
    HAL_Delay(5);
  }
}

What might work?

If I can catch LV_EVENT_DISPLAYED in a callback that would work, but there is no event for objects that are being created or displayed.

monitor_cb in your display driver will be called after the display is finished being drawn.

Good idea @embeddedt , but if I want to sync to image2 below, then how would I use monitor_cb? It appears that the display doesn’t know which object has just been drawn. Can I use display->user_data for this?

lv_img_create(image1);
delay(1000ms);
lv_img_create(image2);
delay(1000ms);
// Do non LVGL work here
lv_img_create(image3);

You would have to use a global flag that tracks which image has been drawn. LVGL doesn’t provide facilities for this, because the assumption is that you are not manipulating the hardware to produce effects on the screen.

By the way, delays won’t usually work how you expect, as LVGL uses an event loop to do things like redrawing the screen. All redraws are performed within lv_task_handler, so the image will not get displayed until that gets called. Normally, the expectation is that lv_task_handler is running continuously in a loop (aside from the 16ms delay between frames).

Why not just use opacity to fade the image in?

Why not just use opacity to fade the image in?

I’m using a monochrome OLED, so there is no way to use opacity (I think.)

I may give up on the fade idea, because it seems the LVGL designers imply there should be no synchronisation between LVGL and the underlying system.

It’s not a big deal, I guess.

LVGL is designed to control most aspects of rendering itself, with the user just having to provide the necessary glue to flush buffers to the display, so yes, it’s not really architected in a manner that makes this simple.

It seems to be the combination of a LVGL core design choice and probably lack of resources to extend features allowing an approach resembling Qt Quick (declarative QML.)

Seems okay to me, so I’ve abandoned the goal of mixing in my own graphic manipulations from SPI calls to the display IC (SSD1306 in my case.)