mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(lcd): update mipi dsi example with lvgl v9
This commit is contained in:
parent
293f529cd7
commit
49c43a7ff7
@ -1,3 +1,3 @@
|
||||
dependencies:
|
||||
lvgl/lvgl: "~8.3.0"
|
||||
lvgl/lvgl: "~9.0.0"
|
||||
esp_lcd_ili9881c: "*"
|
||||
|
@ -4,65 +4,153 @@
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
// This demo UI is adapted from LVGL official example: https://docs.lvgl.io/8.3/widgets/extra/meter.html#a-meter-with-multiple-arcs
|
||||
|
||||
#include "lvgl.h"
|
||||
|
||||
static lv_obj_t * meter;
|
||||
static lv_style_t style_bullet;
|
||||
static lv_obj_t *scale1;
|
||||
static const lv_font_t *font_normal = &lv_font_montserrat_16;
|
||||
|
||||
static void set_value(void *indic, int32_t v)
|
||||
static lv_obj_t *create_scale_box(lv_obj_t *parent, const char *text1, const char *text2, const char *text3)
|
||||
{
|
||||
lv_meter_set_indicator_end_value(meter, indic, v);
|
||||
lv_obj_t *scale = lv_scale_create(parent);
|
||||
lv_obj_center(scale);
|
||||
lv_obj_set_size(scale, 600, 600);
|
||||
lv_scale_set_mode(scale, LV_SCALE_MODE_ROUND_OUTER);
|
||||
lv_scale_set_label_show(scale, false);
|
||||
lv_scale_set_post_draw(scale, true);
|
||||
lv_obj_set_width(scale, LV_PCT(100));
|
||||
lv_obj_set_style_pad_all(scale, 30, 0);
|
||||
|
||||
lv_obj_t *bullet1 = lv_obj_create(parent);
|
||||
lv_obj_set_size(bullet1, 13, 13);
|
||||
lv_obj_remove_style(bullet1, NULL, LV_PART_SCROLLBAR);
|
||||
lv_obj_add_style(bullet1, &style_bullet, 0);
|
||||
lv_obj_set_style_bg_color(bullet1, lv_palette_main(LV_PALETTE_RED), 0);
|
||||
lv_obj_t *label1 = lv_label_create(parent);
|
||||
lv_label_set_text(label1, text1);
|
||||
|
||||
lv_obj_t *bullet2 = lv_obj_create(parent);
|
||||
lv_obj_set_size(bullet2, 13, 13);
|
||||
lv_obj_remove_style(bullet2, NULL, LV_PART_SCROLLBAR);
|
||||
lv_obj_add_style(bullet2, &style_bullet, 0);
|
||||
lv_obj_set_style_bg_color(bullet2, lv_palette_main(LV_PALETTE_BLUE), 0);
|
||||
lv_obj_t *label2 = lv_label_create(parent);
|
||||
lv_label_set_text(label2, text2);
|
||||
|
||||
lv_obj_t *bullet3 = lv_obj_create(parent);
|
||||
lv_obj_set_size(bullet3, 13, 13);
|
||||
lv_obj_remove_style(bullet3, NULL, LV_PART_SCROLLBAR);
|
||||
lv_obj_add_style(bullet3, &style_bullet, 0);
|
||||
lv_obj_set_style_bg_color(bullet3, lv_palette_main(LV_PALETTE_GREEN), 0);
|
||||
lv_obj_t *label3 = lv_label_create(parent);
|
||||
lv_label_set_text(label3, text3);
|
||||
|
||||
static int32_t grid_col_dsc[] = {LV_GRID_CONTENT, LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
||||
static int32_t grid_row_dsc[] = {LV_GRID_CONTENT, LV_GRID_CONTENT, LV_GRID_CONTENT, LV_GRID_CONTENT, LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
|
||||
lv_obj_set_grid_dsc_array(parent, grid_col_dsc, grid_row_dsc);
|
||||
lv_obj_set_grid_cell(scale, LV_GRID_ALIGN_START, 0, 2, LV_GRID_ALIGN_START, 1, 1);
|
||||
lv_obj_set_grid_cell(bullet1, LV_GRID_ALIGN_START, 0, 1, LV_GRID_ALIGN_START, 2, 1);
|
||||
lv_obj_set_grid_cell(bullet2, LV_GRID_ALIGN_START, 0, 1, LV_GRID_ALIGN_START, 3, 1);
|
||||
lv_obj_set_grid_cell(bullet3, LV_GRID_ALIGN_START, 0, 1, LV_GRID_ALIGN_START, 4, 1);
|
||||
lv_obj_set_grid_cell(label1, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_START, 2, 1);
|
||||
lv_obj_set_grid_cell(label2, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_START, 3, 1);
|
||||
lv_obj_set_grid_cell(label3, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_START, 4, 1);
|
||||
return scale;
|
||||
}
|
||||
|
||||
void example_lvgl_demo_ui(lv_disp_t *disp)
|
||||
static void scale1_indic1_anim_cb(void *var, int32_t v)
|
||||
{
|
||||
lv_obj_t *scr = lv_disp_get_scr_act(disp);
|
||||
meter = lv_meter_create(scr);
|
||||
lv_obj_center(meter);
|
||||
lv_obj_set_size(meter, 600, 600);
|
||||
lv_arc_set_value(var, v);
|
||||
|
||||
/*Remove the circle from the middle*/
|
||||
lv_obj_remove_style(meter, NULL, LV_PART_INDICATOR);
|
||||
lv_obj_t *card = lv_obj_get_parent(scale1);
|
||||
lv_obj_t *label = lv_obj_get_child(card, -5);
|
||||
lv_label_set_text_fmt(label, "Revenue: %"LV_PRId32" %%", v);
|
||||
}
|
||||
|
||||
/*Add a scale first*/
|
||||
lv_meter_scale_t * scale = lv_meter_add_scale(meter);
|
||||
lv_meter_set_scale_ticks(meter, scale, 11, 2, 10, lv_palette_main(LV_PALETTE_GREY));
|
||||
lv_meter_set_scale_major_ticks(meter, scale, 1, 2, 30, lv_color_hex3(0xeee), 15);
|
||||
lv_meter_set_scale_range(meter, scale, 0, 100, 270, 90);
|
||||
static void scale1_indic2_anim_cb(void *var, int32_t v)
|
||||
{
|
||||
lv_arc_set_value(var, v);
|
||||
|
||||
/*Add a four arc indicator*/
|
||||
lv_meter_indicator_t * indic1 = lv_meter_add_arc(meter, scale, 30, lv_palette_main(LV_PALETTE_RED), 0);
|
||||
lv_meter_indicator_t * indic2 = lv_meter_add_arc(meter, scale, 30, lv_palette_main(LV_PALETTE_GREEN), -30);
|
||||
lv_meter_indicator_t * indic3 = lv_meter_add_arc(meter, scale, 30, lv_palette_main(LV_PALETTE_BLUE), -60);
|
||||
lv_meter_indicator_t * indic4 = lv_meter_add_arc(meter, scale, 30, lv_palette_main(LV_PALETTE_YELLOW), -90);
|
||||
lv_obj_t *card = lv_obj_get_parent(scale1);
|
||||
lv_obj_t *label = lv_obj_get_child(card, -3);
|
||||
lv_label_set_text_fmt(label, "Sales: %"LV_PRId32" %%", v);
|
||||
}
|
||||
|
||||
/*Create an animation to set the value*/
|
||||
static void scale1_indic3_anim_cb(void *var, int32_t v)
|
||||
{
|
||||
lv_arc_set_value(var, v);
|
||||
|
||||
lv_obj_t *card = lv_obj_get_parent(scale1);
|
||||
lv_obj_t *label = lv_obj_get_child(card, -1);
|
||||
lv_label_set_text_fmt(label, "Costs: %"LV_PRId32" %%", v);
|
||||
}
|
||||
|
||||
void example_lvgl_demo_ui(lv_display_t *disp)
|
||||
{
|
||||
// init default theme
|
||||
lv_theme_default_init(disp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), LV_THEME_DEFAULT_DARK,
|
||||
font_normal);
|
||||
// bullet style
|
||||
lv_style_init(&style_bullet);
|
||||
lv_style_set_border_width(&style_bullet, 0);
|
||||
lv_style_set_radius(&style_bullet, LV_RADIUS_CIRCLE);
|
||||
|
||||
lv_obj_t *parent = lv_display_get_screen_active(disp);
|
||||
|
||||
// create scale widget
|
||||
scale1 = create_scale_box(parent, "Revenue", "Sales", "Costs");
|
||||
|
||||
// create arc indicators
|
||||
lv_obj_t *arc;
|
||||
arc = lv_arc_create(scale1);
|
||||
lv_obj_remove_style(arc, NULL, LV_PART_KNOB);
|
||||
lv_obj_remove_style(arc, NULL, LV_PART_MAIN);
|
||||
lv_obj_set_size(arc, lv_pct(100), lv_pct(100));
|
||||
lv_obj_set_style_arc_opa(arc, 0, 0);
|
||||
lv_obj_set_style_arc_width(arc, 15, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_arc_color(arc, lv_palette_main(LV_PALETTE_BLUE), LV_PART_INDICATOR);
|
||||
lv_obj_remove_flag(arc, LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
// animation
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_exec_cb(&a, set_value);
|
||||
lv_anim_set_values(&a, 0, 100);
|
||||
lv_anim_set_repeat_delay(&a, 100);
|
||||
lv_anim_set_playback_delay(&a, 100);
|
||||
lv_anim_set_values(&a, 20, 100);
|
||||
lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
|
||||
|
||||
lv_anim_set_time(&a, 2000);
|
||||
lv_anim_set_playback_time(&a, 500);
|
||||
lv_anim_set_var(&a, indic1);
|
||||
lv_anim_set_exec_cb(&a, scale1_indic1_anim_cb);
|
||||
lv_anim_set_var(&a, arc);
|
||||
lv_anim_set_duration(&a, 4100);
|
||||
lv_anim_set_playback_duration(&a, 2700);
|
||||
lv_anim_start(&a);
|
||||
|
||||
lv_anim_set_time(&a, 1000);
|
||||
lv_anim_set_playback_time(&a, 1000);
|
||||
lv_anim_set_var(&a, indic2);
|
||||
arc = lv_arc_create(scale1);
|
||||
lv_obj_remove_style(arc, NULL, LV_PART_KNOB);
|
||||
lv_obj_set_size(arc, lv_pct(100), lv_pct(100));
|
||||
lv_obj_set_style_margin_all(arc, 20, 0);
|
||||
lv_obj_set_style_arc_opa(arc, 0, 0);
|
||||
lv_obj_set_style_arc_width(arc, 15, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_arc_color(arc, lv_palette_main(LV_PALETTE_RED), LV_PART_INDICATOR);
|
||||
lv_obj_remove_flag(arc, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_center(arc);
|
||||
|
||||
lv_anim_set_exec_cb(&a, scale1_indic2_anim_cb);
|
||||
lv_anim_set_var(&a, arc);
|
||||
lv_anim_set_duration(&a, 2600);
|
||||
lv_anim_set_playback_duration(&a, 3200);
|
||||
lv_anim_start(&a);
|
||||
|
||||
lv_anim_set_time(&a, 1000);
|
||||
lv_anim_set_playback_time(&a, 2000);
|
||||
lv_anim_set_var(&a, indic3);
|
||||
lv_anim_start(&a);
|
||||
arc = lv_arc_create(scale1);
|
||||
lv_obj_remove_style(arc, NULL, LV_PART_KNOB);
|
||||
lv_obj_set_size(arc, lv_pct(100), lv_pct(100));
|
||||
lv_obj_set_style_margin_all(arc, 40, 0);
|
||||
lv_obj_set_style_arc_opa(arc, 0, 0);
|
||||
lv_obj_set_style_arc_width(arc, 15, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_arc_color(arc, lv_palette_main(LV_PALETTE_GREEN), LV_PART_INDICATOR);
|
||||
lv_obj_remove_flag(arc, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_center(arc);
|
||||
|
||||
lv_anim_set_time(&a, 3000);
|
||||
lv_anim_set_playback_time(&a, 2000);
|
||||
lv_anim_set_var(&a, indic4);
|
||||
lv_anim_set_exec_cb(&a, scale1_indic3_anim_cb);
|
||||
lv_anim_set_var(&a, arc);
|
||||
lv_anim_set_duration(&a, 2800);
|
||||
lv_anim_set_playback_duration(&a, 1800);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
@ -64,17 +64,17 @@ static const char *TAG = "example";
|
||||
|
||||
static SemaphoreHandle_t lvgl_api_mux = NULL;
|
||||
|
||||
extern void example_lvgl_demo_ui(lv_disp_t *disp);
|
||||
extern void example_lvgl_demo_ui(lv_display_t *disp);
|
||||
|
||||
static void example_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
|
||||
static void example_lvgl_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) drv->user_data;
|
||||
esp_lcd_panel_handle_t panel_handle = lv_display_get_user_data(disp);
|
||||
int offsetx1 = area->x1;
|
||||
int offsetx2 = area->x2;
|
||||
int offsety1 = area->y1;
|
||||
int offsety2 = area->y2;
|
||||
// pass the draw buffer to the driver
|
||||
esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map);
|
||||
esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, px_map);
|
||||
}
|
||||
|
||||
static void example_increase_lvgl_tick(void *arg)
|
||||
@ -118,8 +118,8 @@ static void example_lvgl_port_task(void *arg)
|
||||
|
||||
static bool example_notify_lvgl_flush_ready(esp_lcd_panel_handle_t panel, esp_lcd_dpi_panel_event_data_t *edata, void *user_ctx)
|
||||
{
|
||||
lv_disp_drv_t *disp_driver = (lv_disp_drv_t *)user_ctx;
|
||||
lv_disp_flush_ready(disp_driver);
|
||||
lv_display_t *disp = (lv_display_t *)user_ctx;
|
||||
lv_display_flush_ready(disp);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -161,9 +161,6 @@ static void example_bsp_set_lcd_backlight(uint32_t level)
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s)
|
||||
static lv_disp_drv_t disp_drv; // contains callback functions
|
||||
|
||||
example_bsp_enable_dsi_phy_power();
|
||||
example_bsp_init_lcd_backlight();
|
||||
example_bsp_set_lcd_backlight(EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL);
|
||||
@ -190,7 +187,7 @@ void app_main(void)
|
||||
// create ILI9881C control panel
|
||||
esp_lcd_panel_handle_t ili9881c_ctrl_panel;
|
||||
esp_lcd_panel_dev_config_t lcd_dev_config = {
|
||||
.bits_per_pixel = 16,
|
||||
.bits_per_pixel = 24,
|
||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.reset_gpio_num = EXAMPLE_PIN_NUM_LCD_RST,
|
||||
};
|
||||
@ -205,7 +202,7 @@ void app_main(void)
|
||||
.virtual_channel = 0,
|
||||
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
|
||||
.dpi_clock_freq_mhz = EXAMPLE_MIPI_DSI_DPI_CLK_MHZ,
|
||||
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
|
||||
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB888,
|
||||
.video_timing = {
|
||||
.h_size = EXAMPLE_MIPI_DSI_LCD_H_RES,
|
||||
.v_size = EXAMPLE_MIPI_DSI_LCD_V_RES,
|
||||
@ -221,36 +218,40 @@ void app_main(void)
|
||||
#endif
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &mipi_dpi_panel));
|
||||
// register event callbacks
|
||||
esp_lcd_dpi_panel_event_callbacks_t cbs = {
|
||||
.on_color_trans_done = example_notify_lvgl_flush_ready,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_lcd_dpi_panel_register_event_callbacks(mipi_dpi_panel, &cbs, &disp_drv));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_init(mipi_dpi_panel));
|
||||
|
||||
// turn on backlight
|
||||
example_bsp_set_lcd_backlight(EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
|
||||
|
||||
ESP_LOGI(TAG, "Initialize LVGL library");
|
||||
lv_init();
|
||||
// create a lvgl display
|
||||
lv_display_t *display = lv_display_create(EXAMPLE_MIPI_DSI_LCD_H_RES, EXAMPLE_MIPI_DSI_LCD_V_RES);
|
||||
// associate the mipi panel handle to the display
|
||||
lv_display_set_user_data(display, mipi_dpi_panel);
|
||||
// create draw buffer
|
||||
void *buf1 = NULL;
|
||||
void *buf2 = NULL;
|
||||
ESP_LOGI(TAG, "Allocate separate LVGL draw buffers from PSRAM");
|
||||
buf1 = heap_caps_malloc(EXAMPLE_MIPI_DSI_LCD_H_RES * EXAMPLE_LVGL_DRAW_BUF_LINES * sizeof(lv_color_t), MALLOC_CAP_SPIRAM);
|
||||
ESP_LOGI(TAG, "Allocate separate LVGL draw buffers");
|
||||
// Note:
|
||||
// Keep the display buffer in **internal** RAM can speed up the UI because LVGL uses it a lot and it should have a fast access time
|
||||
// This example allocate the buffer from PSRAM mainly because we want to save the internal RAM
|
||||
size_t draw_buffer_sz = EXAMPLE_MIPI_DSI_LCD_H_RES * EXAMPLE_LVGL_DRAW_BUF_LINES * sizeof(lv_color_t);
|
||||
buf1 = heap_caps_malloc(draw_buffer_sz, MALLOC_CAP_SPIRAM);
|
||||
assert(buf1);
|
||||
buf2 = heap_caps_malloc(EXAMPLE_MIPI_DSI_LCD_H_RES * EXAMPLE_LVGL_DRAW_BUF_LINES * sizeof(lv_color_t), MALLOC_CAP_SPIRAM);
|
||||
buf2 = heap_caps_malloc(draw_buffer_sz, MALLOC_CAP_SPIRAM);
|
||||
assert(buf2);
|
||||
// initialize LVGL draw buffers
|
||||
lv_disp_draw_buf_init(&disp_buf, buf1, buf2, EXAMPLE_MIPI_DSI_LCD_H_RES * EXAMPLE_LVGL_DRAW_BUF_LINES);
|
||||
lv_display_set_buffers(display, buf1, buf2, draw_buffer_sz, LV_DISPLAY_RENDER_MODE_PARTIAL);
|
||||
// set color depth
|
||||
lv_display_set_color_format(display, LV_COLOR_FORMAT_RGB888);
|
||||
// set the callback which can copy the rendered image to an area of the display
|
||||
lv_display_set_flush_cb(display, example_lvgl_flush_cb);
|
||||
|
||||
// register display driver to LVGL library
|
||||
lv_disp_drv_init(&disp_drv);
|
||||
disp_drv.hor_res = EXAMPLE_MIPI_DSI_LCD_H_RES;
|
||||
disp_drv.ver_res = EXAMPLE_MIPI_DSI_LCD_V_RES;
|
||||
disp_drv.flush_cb = example_lvgl_flush_cb;
|
||||
disp_drv.draw_buf = &disp_buf;
|
||||
disp_drv.user_data = mipi_dpi_panel;
|
||||
lv_disp_t *disp = lv_disp_drv_register(&disp_drv);
|
||||
ESP_LOGI(TAG, "Register DPI panel event callback for LVGL flush ready notification");
|
||||
esp_lcd_dpi_panel_event_callbacks_t cbs = {
|
||||
.on_color_trans_done = example_notify_lvgl_flush_ready,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_lcd_dpi_panel_register_event_callbacks(mipi_dpi_panel, &cbs, display));
|
||||
|
||||
ESP_LOGI(TAG, "Use esp_timer as LVGL tick timer");
|
||||
const esp_timer_create_args_t lvgl_tick_timer_args = {
|
||||
@ -271,7 +272,7 @@ void app_main(void)
|
||||
ESP_LOGI(TAG, "Display LVGL Meter Widget");
|
||||
// Lock the mutex due to the LVGL APIs are not thread-safe
|
||||
if (example_lvgl_lock(-1)) {
|
||||
example_lvgl_demo_ui(disp);
|
||||
example_lvgl_demo_ui(display);
|
||||
// Release the mutex
|
||||
example_lvgl_unlock();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
CONFIG_LV_MEM_CUSTOM=y
|
||||
CONFIG_LV_MEMCPY_MEMSET_STD=y
|
||||
CONFIG_LV_USE_USER_DATA=y
|
||||
CONFIG_LV_USE_CHART=y
|
||||
CONFIG_LV_CONF_SKIP=y
|
||||
CONFIG_LV_COLOR_DEPTH_24=y
|
||||
CONFIG_LV_FONT_MONTSERRAT_16=y
|
||||
CONFIG_LV_USE_OBSERVER=y
|
||||
CONFIG_LV_USE_SYSMON=y
|
||||
CONFIG_LV_USE_PERF_MONITOR=y
|
||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||
|
Loading…
Reference in New Issue
Block a user