# LVGL ESP Portation [![Component Registry](https://components.espressif.com/components/espressif/esp_lvgl_port/badge.svg)](https://components.espressif.com/components/espressif/esp_lvgl_port) This component helps with using LVGL with Espressif's LCD and touch drivers. It can be used with any project with LCD display. ## Features * Initialization of the LVGL * Create task and timer * Handle rotating * Add/remove display (using [`esp_lcd`](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/lcd.html)) * Add/remove touch input (using [`esp_lcd_touch`](https://github.com/espressif/esp-bsp/tree/master/components/lcd_touch)) ## Usage ### Initialization ``` c const lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG(); esp_err_t err = lvgl_port_init(&lvgl_cfg); ``` ### Add screen Add an LCD screen to the LVGL. It can be called multiple times for adding multiple LCD screens. This part is necessary only in IDF 5.0 and older: ``` c static lv_disp_t * disp; /* The component calls esp_lcd_panel_draw_bitmap API for send data to the screen. There must be called lvgl_port_flush_ready(disp) after each transaction to display. The best way is to use on_color_trans_done callback from esp_lcd IO config structure. */ static bool notify_lvgl_flush_ready(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx) { lv_disp_t ** disp = (lv_disp_t **)user_ctx; lvgl_port_flush_ready(*disp); return false; } /* LCD IO */ esp_lcd_panel_io_spi_config_t io_config = { ... .on_color_trans_done = notify_lvgl_flush_ready, .user_ctx = &disp }; esp_lcd_panel_io_handle_t io_handle = NULL; ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t) 1, &io_config, &io_handle)); /* LCD driver initialization */ ... esp_lcd_panel_handle_t lcd_panel_handle; esp_err_t err = esp_lcd_new_panel_st7789(io_handle, &panel_config, &lcd_panel_handle); ``` Main part of the code (IDF version independent): ``` c /* Add LCD screen */ const lvgl_port_display_cfg_t disp_cfg = { .io_handle = io_handle, .panel_handle = lcd_panel_handle, .buffer_size = DISP_WIDTH*DISP_HEIGHT, .double_buffer = true, .hres = DISP_WIDTH, .vres = DISP_HEIGHT, .monochrome = false, /* Rotation values must be same as used in esp_lcd for initial settings of the screen */ .rotation = { .swap_xy = false, .mirror_x = false, .mirror_y = false, }, .flags = { .buff_dma = true, } }; disp = lvgl_port_add_disp(&disp_cfg); ``` **Note:** The screens added in this function are not removed in `lvgl_port_deinit`. They must be removed by `lvgl_port_remove_disp` before deinitialization. Otherwise, there can be memory leaks! ### Add touch input Add touch input to the LVGL. It can be called more times for adding more touch inputs. ``` c /* Touch driver initialization */ ... esp_lcd_touch_handle_t tp; esp_err_t err = esp_lcd_touch_new_i2c_gt911(io_handle, &tp_cfg, &tp); /* Add touch input (for selected screen) */ const lvgl_port_touch_cfg_t touch_cfg = { .disp = disp_spi, .handle = tp, }; lvgl_port_add_touch(&touch_cfg); ``` **Note:** The inputs added in this function are not removed in `lvgl_port_deinit`. They must be removed by `lvgl_port_remove_touch` before deinitialization. Otherwise, there can be memory leaks! ### LVGL API usage Every LVGL calls must be protected with these lock/unlock commands: ``` c /* Wait for the other task done the screen operation */ lvgl_port_lock(0); ... lv_obj_t * screen = lv_disp_get_scr_act(disp); lv_obj_t * obj = lv_label_create(screen); ... /* Screen operation done -> release for the other task */ lvgl_port_unlock(); ``` ### Rotating screen ``` c lv_disp_set_rotation(disp, LV_DISP_ROT_90); ``` **Note:** During the rotating, the component call [`esp_lcd`](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/lcd.html) API.
idf.py add-dependency "espressif/esp_lvgl_port^1.0.3"