MIPI DSI Interfaced LCD
Create a DSI bus, and it will initialize the D-PHY as well.
esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL; esp_lcd_dsi_bus_config_t bus_config = { .bus_id = 0, // index from 0, specify the DSI host to use .num_data_lanes = 2, // Number of data lanes to use, can't set a value that exceeds the chip's capability .phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT, // Clock source for the DPHY .lane_bit_rate_mbps = EXAMPLE_MIPI_DSI_LANE_BITRATE_MBPS, // Bit rate of the data lanes, in Mbps }; ESP_ERROR_CHECK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus));
Derive the DBI interface from the DSI bus. The DBI interface mostly is used as the control IO layer in the esp_lcd component. This interface provides the functions to read or write the configuration registers inside the LCD device. In this step, you need to provide the following information:
esp_lcd_dbi_io_config_t::virtual_channel
sets the virtual channel number to use. The virtual channel is a logical channel that is used to multiplex the data from different sources. If you only have one LCD connected, you can set this to0
.esp_lcd_dbi_io_config_t::lcd_cmd_bits
andesp_lcd_dbi_io_config_t::lcd_param_bits
set the bit width of the command and parameter that recognized by the LCD controller chip. This is chip specific, you should refer to your LCD spec in advance.
esp_lcd_panel_io_handle_t mipi_dbi_io = NULL; esp_lcd_dbi_io_config_t dbi_config = { .virtual_channel = 0, .lcd_cmd_bits = 8, // according to the LCD spec .lcd_param_bits = 8, // according to the LCD spec }; ESP_ERROR_CHECK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io));
Install the LCD controller driver. The LCD controller driver is responsible for sending the commands and parameters to the LCD controller chip. In this step, you need to specify the MIPI DBI IO handle that allocated in the last step, and some panel specific configurations:
esp_lcd_panel_dev_config_t::bits_per_pixel
sets the bit width of each pixel. The LCD driver uses this value to calculate the number of bytes to send to the LCD controller chip.esp_lcd_panel_dev_config_t::reset_gpio_num
sets the GPIO number of the reset pin. If the LCD controller chip does not have a reset pin, you can set this value to-1
.esp_lcd_panel_dev_config_t::rgb_ele_order
sets the RGB element order of the pixel data, it can be RGB or BGR.
esp_lcd_panel_handle_t ili9881c_ctrl_panel = NULL; esp_lcd_panel_dev_config_t lcd_dev_config = { .bits_per_pixel = 24, // MIPI LCD usually uses 24 bit (i.e., RGB888) per pixel .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));
With the LCD control panel that returned in the last step, you can reset the LCD device followed by a basic initialization. After that, you can turn on the display.
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));
However, you still can't send pixel data to the MIPI LCD with the control panel, because MIPI LCD has a high resolution and there's no GRAM in the LCD controller. We need to maintain the LCD frame buffer and flush it to the LCD via the MIPI DSI DPI interface. To allocate a DPI data panel, you need to provide many essential parameters, including the DPI clock frequency, the pixel format, the video timing, and so on.
esp_lcd_dpi_panel_config_t::virtual_channel
sets the virtual channel number to use. Like the DBI interface, we also need to set the virtual channel for the DPI interface. If you only have one LCD connected, you can set this to0
.esp_lcd_dpi_panel_config_t::dpi_clk_src
sets the clock source for the DPI interface. The available clock sources are listed inmipi_dsi_dpi_clock_source_t
.esp_lcd_dpi_panel_config_t::dpi_clock_freq_mhz
sets the DPI clock frequency in MHz. Higher pixel clock frequency results in higher refresh rate, but may cause flickering if the DMA bandwidth is not sufficient or the LCD controller chip does not support high pixel clock frequency.esp_lcd_dpi_panel_config_t::pixel_format
sets the pixel format of the pixel data. The available pixel formats are listed inlcd_color_rgb_pixel_format_t
. We usually use RGB888 for MIPI LCD to get the best color depth.esp_lcd_dpi_panel_config_t::video_timing
sets the LCD panel specific timing parameters. All required parameters are listed in theesp_lcd_video_timing_t
, including the LCD resolution and blanking porches. Please fill them according to the datasheet of your LCD.esp_lcd_dpi_panel_config_t::extra_dpi_panel_flags::use_dma2d
sets whether to use the 2D DMA peripheral to copy the user data to the frame buffer, asynchronously.
esp_lcd_panel_handle_t mipi_dpi_panel = NULL; esp_lcd_dpi_panel_config_t dpi_config = { .virtual_channel = 0, .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, .dpi_clock_freq_mhz = 1 * 1000, .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, .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, }, .flags.use_dma2d = true, }; 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));
API Reference
Header File
This header file can be included with:
#include "esp_lcd_mipi_dsi.h"
This header file is a part of the API provided by the
esp_lcd
component. To declare that your component depends onesp_lcd
, add the following to your CMakeLists.txt:REQUIRES esp_lcd
or
PRIV_REQUIRES esp_lcd
Functions
-
esp_err_t esp_lcd_new_dsi_bus(const esp_lcd_dsi_bus_config_t *bus_config, esp_lcd_dsi_bus_handle_t *ret_bus)
Create MIPI DSI bus handle.
- Parameters
bus_config -- [in] Bus configuration
ret_bus -- [out] Returned bus handle
- Returns
ESP_OK: Create MIPI DSI bus successfully
ESP_ERR_INVALID_ARG: Create MIPI DSI bus failed because of invalid argument
ESP_ERR_NO_MEM: Create MIPI DSI bus failed because of out of memory
ESP_ERR_NOT_FOUND: Create MIPI DSI bus failed because no more free DSI hardware instance
ESP_FAIL: Create MIPI DSI bus failed because of other error
-
esp_err_t esp_lcd_del_dsi_bus(esp_lcd_dsi_bus_handle_t bus)
Destroy MIPI DSI bus handle.
- Parameters
bus -- [in] MIPI DSI bus handle, returned from
esp_lcd_new_dsi_bus
- Returns
ESP_OK: Destroy MIPI DSI bus successfully
ESP_ERR_INVALID_ARG: Destroy MIPI DSI bus failed because of invalid argument
ESP_FAIL: Destroy MIPI DSI bus failed because of other error
-
esp_err_t esp_lcd_new_panel_io_dbi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dbi_io_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io)
Create LCD panel IO, for MIPI DSI DBI interface.
Note
Although we call it "DBI", internally the driver is using a co-called "generic" interface for transmitting/receiving LCD commands and parameters.
- Parameters
bus -- [in] MIPI DSI bus handle, returned from
esp_lcd_new_dsi_bus
io_config -- [in] IO configuration
ret_io -- [out] Returned panel IO handle
- Returns
ESP_OK: Create MIPI DSI command IO successfully
ESP_ERR_INVALID_ARG: Create MIPI DSI command IO failed because of invalid argument
ESP_ERR_NO_MEM: Create MIPI DSI command IO failed because of out of memory
ESP_FAIL: Create MIPI DSI command IO failed because of other error
-
esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_panel_config_t *panel_config, esp_lcd_panel_handle_t *ret_panel)
Create LCD panel for MIPI DSI DPI interface.
- Parameters
bus -- [in] MIPI DSI bus handle, returned from
esp_lcd_new_dsi_bus
panel_config -- [in] DSI data panel configuration
ret_panel -- [out] Returned LCD panel handle
- Returns
ESP_OK: Create MIPI DSI data panel successfully
ESP_ERR_INVALID_ARG: Create MIPI DSI data panel failed because of invalid argument
ESP_ERR_NO_MEM: Create MIPI DSI data panel failed because of out of memory
ESP_ERR_NOT_SUPPORTED: Create MIPI DSI data panel failed because of unsupported feature
ESP_FAIL: Create MIPI DSI data panel failed because of other error
-
esp_err_t esp_lcd_dpi_panel_get_frame_buffer(esp_lcd_panel_handle_t dpi_panel, uint32_t fb_num, void **fb0, ...)
Get the address of the frame buffer(s) that allocated by the driver.
- Parameters
dpi_panel -- [in] MIPI DPI panel handle, returned from esp_lcd_new_panel_dpi()
fb_num -- [in] Number of frame buffer(s) to get. This value must be the same as the number of the followed parameters.
fb0 -- [out] Address of the frame buffer 0 (first frame buffer)
... -- [out] List of other frame buffers if any
- Returns
ESP_ERR_INVALID_ARG: Get frame buffer address failed because of invalid argument
ESP_OK: Get frame buffer address successfully
-
esp_err_t esp_lcd_dpi_panel_set_pattern(esp_lcd_panel_handle_t dpi_panel, mipi_dsi_pattern_type_t pattern)
Set pre-defined pattern to the screen for testing or debugging purpose.
- Parameters
dpi_panel -- [in] MIPI DPI panel handle, returned from esp_lcd_new_panel_dpi()
pattern -- [in] Pattern type
- Returns
ESP_OK: Set pattern successfully
ESP_ERR_INVALID_ARG: Set pattern failed because of invalid argument
ESP_FAIL: Set pattern failed because of other error
-
esp_err_t esp_lcd_dpi_panel_register_event_callbacks(esp_lcd_panel_handle_t dpi_panel, const esp_lcd_dpi_panel_event_callbacks_t *cbs, void *user_ctx)
Register LCD DPI panel callbacks.
- Parameters
dpi_panel -- [in] LCD DPI panel handle, which is returned from esp_lcd_new_panel_dpi()
cbs -- [in] structure with all LCD panel callbacks
user_ctx -- [in] User private data, passed directly to callback's user_ctx
- Returns
ESP_ERR_INVALID_ARG: Register callbacks failed because of invalid argument
ESP_OK: Register callbacks successfully
Structures
-
struct esp_lcd_dsi_bus_config_t
MIPI DSI bus configuration structure.
Public Members
-
int bus_id
Select which DSI controller, index from 0
-
uint8_t num_data_lanes
Number of data lanes, if set to 0, the driver will fallback to use maximum number of lanes
-
mipi_dsi_phy_clock_source_t phy_clk_src
MIPI DSI PHY clock source
-
uint32_t lane_bit_rate_mbps
Lane bit rate in Mbps
-
int bus_id
-
struct esp_lcd_dbi_io_config_t
Panel IO configuration structure, for MIPI DSI command interface.
-
struct esp_lcd_dpi_panel_config_t
MIPI DSI DPI panel configuration structure.
Public Members
-
uint8_t virtual_channel
Virtual channel ID, index from 0
-
mipi_dsi_dpi_clock_source_t dpi_clk_src
MIPI DSI DPI clock source
-
uint32_t dpi_clock_freq_mhz
DPI clock frequency in MHz
-
lcd_color_rgb_pixel_format_t pixel_format
Pixel format that used by the MIPI LCD device
-
uint8_t num_fbs
Number of screen-sized frame buffers that allocated by the driver By default (set to either 0 or 1) only one frame buffer will be created
-
esp_lcd_video_timing_t video_timing
Video timing
-
struct esp_lcd_dpi_panel_config_t::extra_dpi_panel_flags flags
Extra configuration flags
-
struct extra_dpi_panel_flags
Extra configuration flags for MIPI DSI DPI panel.
-
uint8_t virtual_channel
-
struct esp_lcd_dpi_panel_event_data_t
Type of LCD DPI panel event data.
-
struct esp_lcd_dpi_panel_event_callbacks_t
Type of LCD DPI panel callbacks.
Public Members
-
esp_lcd_dpi_panel_color_trans_done_cb_t on_color_trans_done
Invoked when user's color buffer copied to the internal frame buffer. This is an indicator that the draw buffer can be recycled safely. But doesn't mean the draw buffer finishes the refreshing to the screen.
-
esp_lcd_dpi_panel_refresh_done_cb_t on_refresh_done
Invoked when the internal frame buffer finishes refreshing to the screen
-
esp_lcd_dpi_panel_color_trans_done_cb_t on_color_trans_done
Type Definitions
-
typedef struct esp_lcd_dsi_bus_t *esp_lcd_dsi_bus_handle_t
Type of MIPI DSI bus handle
-
typedef bool (*esp_lcd_dpi_panel_general_cb_t)(esp_lcd_panel_handle_t panel, esp_lcd_dpi_panel_event_data_t *edata, void *user_ctx)
A general function callback prototype for DPI panel driver.
- Param panel
[in] LCD panel handle, which is created by factory API like esp_lcd_new_panel_dpi()
- Param edata
[in] DPI panel event data, fed by driver
- Param user_ctx
[in] User data
- Return
Whether a high priority task has been waken up by this function
-
typedef esp_lcd_dpi_panel_general_cb_t esp_lcd_dpi_panel_color_trans_done_cb_t
Declare the prototype of the function that will be invoked when driver finishes coping user's color buffer to frame buffer.
-
typedef esp_lcd_dpi_panel_general_cb_t esp_lcd_dpi_panel_refresh_done_cb_t
Declare the prototype of the function that will be invoked when driver finishes refreshing the frame buffer to the screen.