forked from espressif/esp-idf
feat(dsi): add mipi dsi lcd example with lvgl gui
This commit is contained in:
@@ -149,6 +149,12 @@ examples/peripherals/lcd/i80_controller:
|
||||
- esp_lcd
|
||||
- esp_driver_i2s
|
||||
|
||||
examples/peripherals/lcd/mipi_dsi:
|
||||
disable:
|
||||
- if: SOC_LCD_MIPI_DSI_SUPPORTED != 1
|
||||
depends_components:
|
||||
- esp_lcd
|
||||
|
||||
examples/peripherals/lcd/rgb_panel:
|
||||
disable:
|
||||
- if: SOC_LCD_RGB_SUPPORTED != 1
|
||||
|
4
examples/peripherals/lcd/mipi_dsi/CMakeLists.txt
Normal file
4
examples/peripherals/lcd/mipi_dsi/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(mipi_dsi_panel)
|
77
examples/peripherals/lcd/mipi_dsi/README.md
Normal file
77
examples/peripherals/lcd/mipi_dsi/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
| Supported Targets | ESP32-P4 |
|
||||
| ----------------- | -------- |
|
||||
|
||||
# MIPI DSI LCD Panel Example
|
||||
|
||||
[esp_lcd](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/lcd.html) supports MIPI DSI interfaced LCD panel, with frame buffer(s) managed by the driver itself.
|
||||
|
||||
This example shows the general process of installing a MIPI DSI LCD driver, and displays a LVGL widget on the screen.
|
||||
|
||||
## How to use the example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* An ESP development board, which with MIPI DSI peripheral supported
|
||||
* A general MIPI DSI LCD panel, with 2 data lanes and 1 clock lane, this example will use the [ILI9881C](https://components.espressif.com/components/espressif/esp_lcd_ili9881c) for demonstration
|
||||
* An USB cable for power supply and programming
|
||||
|
||||
### Hardware Connection
|
||||
|
||||
The connection between ESP Board and the LCD is as follows:
|
||||
|
||||
```text
|
||||
ESP Board MIPI DSI LCD Panel
|
||||
+-----------------------+ +-------------------+
|
||||
| GND +--------------+ GND |
|
||||
| | | |
|
||||
| 3V3 +--------------+ VCC |
|
||||
| | | |
|
||||
| DSI_CLK_P +--------------+ DSI_CLK_P |
|
||||
| DSI_CLK_N + + DSI_CLK_N |
|
||||
| | | |
|
||||
| DSI_DAT0_P +--------------+ DSI_DAT0_P |
|
||||
| DAI_DAT0_N + + DAI_DAT0_N |
|
||||
| | | |
|
||||
| DSI_DAT1_P +--------------+ DSI_DAT1_P |
|
||||
| DSI_DAT1_N + + DSI_DAT1_N |
|
||||
| | | |
|
||||
| | | |
|
||||
| BK_LIGHT +--------------+ BLK |
|
||||
| | | |
|
||||
| Reset +--------------+ Reset |
|
||||
| | | |
|
||||
+-----------------------+ +-------------------+
|
||||
```
|
||||
|
||||
Before testing your LCD, you also need to read your LCD spec carefully, and then adjust the values like "resolution" and "blank time" in the [main](./main/mipi_dsi_lcd_example_main.c) file.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Run `idf.py -p PORT build flash monitor` to build, flash and monitor the project. A LVGL widget should show up on the LCD as expected.
|
||||
|
||||
The first time you run `idf.py` for the example will cost extra time as the build system needs to address the component dependencies and downloads the missing components from registry into `managed_components` folder.
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
### Example Output
|
||||
|
||||
```bash
|
||||
...
|
||||
I (1629) example: MIPI DSI PHY Powered on
|
||||
I (1629) example: Install MIPI DSI LCD control panel
|
||||
I (1639) ili9881c: ID1: 0x98, ID2: 0x81, ID3: 0x5c
|
||||
I (1779) example: Install MIPI DSI LCD data panel
|
||||
I (1799) example: Initialize LVGL library
|
||||
I (1799) example: Allocate separate LVGL draw buffers from PSRAM
|
||||
I (1809) example: Use esp_timer as LVGL tick timer
|
||||
I (1809) example: Create LVGL task
|
||||
I (1809) example: Starting LVGL task
|
||||
I (1919) example: Display LVGL Meter Widget
|
||||
...
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
|
2
examples/peripherals/lcd/mipi_dsi/main/CMakeLists.txt
Normal file
2
examples/peripherals/lcd/mipi_dsi/main/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "mipi_dsi_lcd_example_main.c" "lvgl_demo_ui.c"
|
||||
INCLUDE_DIRS ".")
|
3
examples/peripherals/lcd/mipi_dsi/main/idf_component.yml
Normal file
3
examples/peripherals/lcd/mipi_dsi/main/idf_component.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
dependencies:
|
||||
lvgl/lvgl: "~8.3.0"
|
||||
esp_lcd_ili9881c: ">=0.1.0"
|
68
examples/peripherals/lcd/mipi_dsi/main/lvgl_demo_ui.c
Normal file
68
examples/peripherals/lcd/mipi_dsi/main/lvgl_demo_ui.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* 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 void set_value(void *indic, int32_t v)
|
||||
{
|
||||
lv_meter_set_indicator_end_value(meter, indic, v);
|
||||
}
|
||||
|
||||
void example_lvgl_demo_ui(lv_disp_t *disp)
|
||||
{
|
||||
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);
|
||||
|
||||
/*Remove the circle from the middle*/
|
||||
lv_obj_remove_style(meter, NULL, LV_PART_INDICATOR);
|
||||
|
||||
/*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);
|
||||
|
||||
/*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);
|
||||
|
||||
/*Create an animation to set the value*/
|
||||
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_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_start(&a);
|
||||
|
||||
lv_anim_set_time(&a, 1000);
|
||||
lv_anim_set_playback_time(&a, 1000);
|
||||
lv_anim_set_var(&a, indic2);
|
||||
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);
|
||||
|
||||
lv_anim_set_time(&a, 3000);
|
||||
lv_anim_set_playback_time(&a, 2000);
|
||||
lv_anim_set_var(&a, indic4);
|
||||
lv_anim_start(&a);
|
||||
}
|
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_private/esp_ldo.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_mipi_dsi.h"
|
||||
#include "esp_lcd_ili9881c.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "lvgl.h"
|
||||
|
||||
static const char *TAG = "example";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////// Please update the following configuration according to your LCD Spec //////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// FPS = 80000000/(40+140+40+800)/(4+16+16+1280) = 60Hz
|
||||
#define EXAMPLE_MIPI_DSI_DPI_CLK_MHZ 80
|
||||
#define EXAMPLE_MIPI_DSI_LCD_H_RES 800
|
||||
#define EXAMPLE_MIPI_DSI_LCD_V_RES 1280
|
||||
#define EXAMPLE_MIPI_DSI_LCD_HSYNC 40
|
||||
#define EXAMPLE_MIPI_DSI_LCD_HBP 140
|
||||
#define EXAMPLE_MIPI_DSI_LCD_HFP 40
|
||||
#define EXAMPLE_MIPI_DSI_LCD_VSYNC 4
|
||||
#define EXAMPLE_MIPI_DSI_LCD_VBP 16
|
||||
#define EXAMPLE_MIPI_DSI_LCD_VFP 16
|
||||
|
||||
#define EXAMPLE_MIPI_DSI_LANE_NUM 2 // 2 data lanes
|
||||
#define EXAMPLE_MIPI_DSI_LANE_BITRATE_MBPS 1000 // 1Gbps
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////// Please update the following configuration according to your Board Design //////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// The "VDD_MIPI_DPHY" should be supplied with 2.5V, it can source from the integrated LDO unit or from external LDO chip
|
||||
#define EXAMPLE_MIPI_DSI_PHY_PWR_LDO_UNIT 3 // LDO_VO3 is connected to VDD_MIPI_DPHY
|
||||
#define EXAMPLE_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV 2500
|
||||
#define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 1
|
||||
#define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL
|
||||
#define EXAMPLE_PIN_NUM_BK_LIGHT -1
|
||||
#define EXAMPLE_PIN_NUM_LCD_RST -1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////// Please update the following configuration according to your Application ///////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define EXAMPLE_LVGL_DRAW_BUF_LINES 200 // number of display lines in each draw buffer
|
||||
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
|
||||
#define EXAMPLE_LVGL_TASK_MAX_DELAY_MS 500
|
||||
#define EXAMPLE_LVGL_TASK_MIN_DELAY_MS 1
|
||||
#define EXAMPLE_LVGL_TASK_STACK_SIZE (4 * 1024)
|
||||
#define EXAMPLE_LVGL_TASK_PRIORITY 2
|
||||
|
||||
static SemaphoreHandle_t lvgl_api_mux = NULL;
|
||||
|
||||
extern void example_lvgl_demo_ui(lv_disp_t *disp);
|
||||
|
||||
static void example_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
|
||||
{
|
||||
esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t) drv->user_data;
|
||||
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);
|
||||
lv_disp_flush_ready(drv);
|
||||
}
|
||||
|
||||
static void example_increase_lvgl_tick(void *arg)
|
||||
{
|
||||
/* Tell LVGL how many milliseconds has elapsed */
|
||||
lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
static bool example_lvgl_lock(int timeout_ms)
|
||||
{
|
||||
// Convert timeout in milliseconds to FreeRTOS ticks
|
||||
// If `timeout_ms` is set to -1, the program will block until the condition is met
|
||||
const TickType_t timeout_ticks = (timeout_ms == -1) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);
|
||||
return xSemaphoreTakeRecursive(lvgl_api_mux, timeout_ticks) == pdTRUE;
|
||||
}
|
||||
|
||||
static void example_lvgl_unlock(void)
|
||||
{
|
||||
xSemaphoreGiveRecursive(lvgl_api_mux);
|
||||
}
|
||||
|
||||
static void example_lvgl_port_task(void *arg)
|
||||
{
|
||||
ESP_LOGI(TAG, "Starting LVGL task");
|
||||
uint32_t task_delay_ms = EXAMPLE_LVGL_TASK_MAX_DELAY_MS;
|
||||
while (1) {
|
||||
// Lock the mutex due to the LVGL APIs are not thread-safe
|
||||
if (example_lvgl_lock(-1)) {
|
||||
task_delay_ms = lv_timer_handler();
|
||||
// Release the mutex
|
||||
example_lvgl_unlock();
|
||||
}
|
||||
if (task_delay_ms > EXAMPLE_LVGL_TASK_MAX_DELAY_MS) {
|
||||
task_delay_ms = EXAMPLE_LVGL_TASK_MAX_DELAY_MS;
|
||||
} else if (task_delay_ms < EXAMPLE_LVGL_TASK_MIN_DELAY_MS) {
|
||||
task_delay_ms = EXAMPLE_LVGL_TASK_MIN_DELAY_MS;
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(task_delay_ms));
|
||||
}
|
||||
}
|
||||
|
||||
static void example_bsp_enable_dsi_phy_power(void)
|
||||
{
|
||||
// Turn on the power for MIPI DSI PHY, so it can go from "No Power" state to "Shutdown" state
|
||||
esp_ldo_unit_handle_t phy_pwr_unit = NULL;
|
||||
#if EXAMPLE_MIPI_DSI_PHY_PWR_LDO_UNIT > 0
|
||||
esp_ldo_unit_init_cfg_t ldo_cfg = {
|
||||
.unit_id = EXAMPLE_MIPI_DSI_PHY_PWR_LDO_UNIT,
|
||||
.cfg = {
|
||||
.voltage_mv = EXAMPLE_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV,
|
||||
},
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_ldo_init_unit(&ldo_cfg, &phy_pwr_unit));
|
||||
ESP_ERROR_CHECK(esp_ldo_enable_unit(phy_pwr_unit));
|
||||
|
||||
ESP_LOGI(TAG, "MIPI DSI PHY Powered on");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void example_bsp_init_lcd_backlight(void)
|
||||
{
|
||||
#if EXAMPLE_PIN_NUM_BK_LIGHT >= 0
|
||||
gpio_config_t bk_gpio_config = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT
|
||||
};
|
||||
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void example_bsp_set_lcd_backlight(uint32_t level)
|
||||
{
|
||||
#if EXAMPLE_PIN_NUM_BK_LIGHT >= 0
|
||||
gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, level);
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// create MIPI DSI bus first, it will initialize the DSI PHY as well
|
||||
esp_lcd_dsi_bus_handle_t mipi_dsi_bus;
|
||||
esp_lcd_dsi_bus_config_t bus_config = {
|
||||
.bus_id = 0,
|
||||
.num_data_lanes = EXAMPLE_MIPI_DSI_LANE_NUM,
|
||||
.phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT,
|
||||
.lane_bit_rate_mbps = EXAMPLE_MIPI_DSI_LANE_BITRATE_MBPS,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus));
|
||||
|
||||
ESP_LOGI(TAG, "Install MIPI DSI LCD control panel");
|
||||
esp_lcd_panel_io_handle_t mipi_dbi_io;
|
||||
// we use DBI interface to send LCD commands and parameters
|
||||
esp_lcd_dbi_io_config_t dbi_config = {
|
||||
.virtual_channel = 0,
|
||||
.lcd_cmd_bits = 8, // according to the LCD ILI9881C spec
|
||||
.lcd_param_bits = 8, // according to the LCD ILI9881C spec
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io));
|
||||
// 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,
|
||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.reset_gpio_num = EXAMPLE_PIN_NUM_LCD_RST,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_ili9881c(mipi_dbi_io, &lcd_dev_config, &ili9881c_ctrl_panel));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_reset(ili9881c_ctrl_panel));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_init(ili9881c_ctrl_panel));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(ili9881c_ctrl_panel, true));
|
||||
|
||||
ESP_LOGI(TAG, "Install MIPI DSI LCD data panel");
|
||||
esp_lcd_panel_handle_t mipi_dpi_panel;
|
||||
esp_lcd_dpi_panel_config_t dpi_config = {
|
||||
.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,
|
||||
.video_timing = {
|
||||
.h_size = EXAMPLE_MIPI_DSI_LCD_H_RES,
|
||||
.v_size = EXAMPLE_MIPI_DSI_LCD_V_RES,
|
||||
.hsync_back_porch = EXAMPLE_MIPI_DSI_LCD_HBP,
|
||||
.hsync_pulse_width = EXAMPLE_MIPI_DSI_LCD_HSYNC,
|
||||
.hsync_front_porch = EXAMPLE_MIPI_DSI_LCD_HFP,
|
||||
.vsync_back_porch = EXAMPLE_MIPI_DSI_LCD_VBP,
|
||||
.vsync_pulse_width = EXAMPLE_MIPI_DSI_LCD_VSYNC,
|
||||
.vsync_front_porch = EXAMPLE_MIPI_DSI_LCD_VFP,
|
||||
},
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &mipi_dpi_panel));
|
||||
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();
|
||||
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);
|
||||
assert(buf1);
|
||||
buf2 = heap_caps_malloc(EXAMPLE_MIPI_DSI_LCD_H_RES * EXAMPLE_LVGL_DRAW_BUF_LINES * sizeof(lv_color_t), 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);
|
||||
|
||||
// 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, "Use esp_timer as LVGL tick timer");
|
||||
const esp_timer_create_args_t lvgl_tick_timer_args = {
|
||||
.callback = &example_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, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000));
|
||||
|
||||
// LVGL APIs are meant to be called across the threads without protection, so we use a mutex here
|
||||
lvgl_api_mux = xSemaphoreCreateRecursiveMutex();
|
||||
assert(lvgl_api_mux);
|
||||
|
||||
ESP_LOGI(TAG, "Create LVGL task");
|
||||
xTaskCreate(example_lvgl_port_task, "LVGL", EXAMPLE_LVGL_TASK_STACK_SIZE, NULL, EXAMPLE_LVGL_TASK_PRIORITY, NULL);
|
||||
|
||||
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);
|
||||
// Release the mutex
|
||||
example_lvgl_unlock();
|
||||
}
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32p4
|
||||
@pytest.mark.generic
|
||||
def test_rgb_lcd_lvgl(dut: Dut) -> None:
|
||||
dut.expect_exact('example: Install MIPI DSI LCD control panel')
|
6
examples/peripherals/lcd/mipi_dsi/sdkconfig.defaults
Normal file
6
examples/peripherals/lcd/mipi_dsi/sdkconfig.defaults
Normal file
@@ -0,0 +1,6 @@
|
||||
CONFIG_LV_MEM_CUSTOM=y
|
||||
CONFIG_LV_MEMCPY_MEMSET_STD=y
|
||||
CONFIG_LV_USE_USER_DATA=y
|
||||
CONFIG_LV_USE_CHART=y
|
||||
CONFIG_LV_USE_PERF_MONITOR=y
|
||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_MODE_HEX=y
|
||||
CONFIG_SPIRAM_SPEED_200M=y
|
Reference in New Issue
Block a user