I’m using the 9.1.1-dev version of LVGL to display UI in a gc9a01 display using a ESP-32-S3 N8R8. I’m using ESP-IDF framework. So far I could display a label and a circle. I want to display lottie files. I saw it’s a new feature implemented in the last months. The thing is I only see a white screen. I set up the variables LV_USE_LOTTIE
, LV_USE_CANVAS
, LV_USE_VECTOR_GRAPHIC
, LV_USE_THORVG_INTERNAL
to 1
I’m trying to display this example: examples/widgets/lottie/lv_example_lottie_1.c
The content of lv_example_lottie_approve.c is being loaded
There is anything I’m mising?
/* INCLUDES ------------------------------------------------------------------*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "gc9a01.h"
#include "unity.h"
#include "unity_test_runner.h"
#include "lvgl.h"
#include "esp_log.h"
/* PRIVATE STRUCTURES --------------------------------------------------------*/
/* VARIABLES -----------------------------------------------------------------*/
lv_display_t *disp;
static char *TAG = "gc9a01";
esp_lcd_panel_handle_t panel_handle = NULL;
/* DEFINITIONS ---------------------------------------------------------------*/
#define BYTE_PER_PIXEL 2
/* MACROS --------------------------------------------------------------------*/
/* PRIVATE FUNCTIONS DECLARATION ---------------------------------------------*/
static void flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map)
{
esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)lv_display_get_user_data(disp);
esp_lcd_panel_draw_bitmap(panel_handle, area->x1, area->y1, area->x2 + 1, area->y2 + 1, px_map);
lv_display_flush_ready(disp);
}
static void increase_lvgl_tick(void *arg)
{
// Tell LVGL how many milliseconds has elapsed
lv_tick_inc(LVGL_TICK_PERIOD_MS);
}
static void display_config(esp_lcd_panel_handle_t panel_handle)
{
lv_init();
static uint8_t buf1[LCD_H_RES * 10 * BYTE_PER_PIXEL]; /*A buffer for 10 rows*/
static uint8_t buf2[LCD_H_RES * 10 * BYTE_PER_PIXEL];
// Allocate the draw buffer
lv_display_t *display = lv_display_create(LCD_H_RES, LCD_V_RES);
if (display == NULL)
{
ESP_LOGE(TAG, "Failed to create display");
return;
}
lv_display_set_user_data(display, panel_handle);
lv_display_set_flush_cb(display, flush_cb);
lv_display_set_buffers(display, buf1, buf2, sizeof(buf1), LV_DISPLAY_RENDER_MODE_PARTIAL);
ESP_LOGI(TAG, "Install LVGL tick timer");
// Tick interface for LVGL (using esp_timer to generate 2ms periodic event)
const esp_timer_create_args_t lvgl_tick_timer_args = {
.callback = &increase_lvgl_tick,
.name = "lvgl_tick"};
esp_timer_handle_t lvgl_tick_timer = NULL;
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, LVGL_TICK_PERIOD_MS * 1000));
// Test lottie animation
extern const uint8_t lv_example_lottie_approve[];
extern const size_t lv_example_lottie_approve_size;
lv_obj_t *lottie = lv_lottie_create(lv_screen_active());
lv_lottie_set_src_data(lottie, lv_example_lottie_approve, lv_example_lottie_approve_size);
#if LV_DRAW_BUF_ALIGN == 4 && LV_DRAW_BUF_STRIDE_ALIGN == 1
/*If there are no special requirements, just declare a buffer
x4 because the Lottie is rendered in ARGB8888 format*/
static uint8_t buf[64 * 64 * 4];
lv_lottie_set_buffer(lottie, 64, 64, buf);
#else
/*For GPUs and special alignment/strid setting use a draw_buf instead*/
LV_DRAW_BUF_DEFINE(draw_buf, 64, 64, LV_COLOR_FORMAT_ARGB8888);
lv_lottie_set_draw_buf(lottie, &draw_buf);
#endif
lv_obj_center(lottie);
}
/* FUNCTION PROTOTYPES -------------------------------------------------------*/
void gc9a01_displayInit(void)
{
ESP_LOGI(TAG, "Initialize SPI bus");
const spi_bus_config_t bus_config = GC9A01_PANEL_BUS_SPI_CONFIG(PIN_NUM_SCLK, PIN_NUM_MOSI,
LCD_H_RES * 80 * sizeof(uint16_t));
ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &bus_config, SPI_DMA_CH_AUTO));
ESP_LOGI(TAG, "Install panel IO");
esp_lcd_panel_io_handle_t io_handle = NULL;
const esp_lcd_panel_io_spi_config_t io_config = GC9A01_PANEL_IO_SPI_CONFIG(PIN_NUM_LCD_CS, PIN_NUM_LCD_DC,
NULL, NULL);
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &io_handle));
ESP_LOGI(TAG, "Install GC9A01 panel driver");
esp_lcd_panel_handle_t panel_handle = NULL;
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = PIN_NUM_LCD_RST,
.rgb_endian = LCD_RGB_ENDIAN_RGB,
.bits_per_pixel = 16, // Implemented by LCD command `3Ah` (16/18)
// .vendor_config = &vendor_config, // Uncomment this line if use custom initialization commands
};
ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(io_handle, &panel_config, &panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true));
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, true, false));
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
ESP_LOGI(TAG, "Configure LCD backlight pin");
gpio_config_t bk_gpio_config = {
.pin_bit_mask = 1ULL << PIN_NUM_BK_LIGHT,
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE};
gpio_config(&bk_gpio_config);
ESP_LOGI(TAG, "Turn on LCD backlight");
gpio_set_level(PIN_NUM_BK_LIGHT, LCD_BK_LIGHT_ON_LEVEL);
ESP_LOGI(TAG, "Backlight level set to %d", LCD_BK_LIGHT_ON_LEVEL);
vTaskDelay(pdMS_TO_TICKS(100)); // Add a delay to ensure the signal is set
display_config(panel_handle);
}