feat(driver): add ST7735, ST7789, ST7796, ILI9341 display drivers (#5020)

Co-authored-by: Zoltan Janosy <zjanosy@fishman.com>
Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
Zoltan Janosy
2024-01-12 10:25:07 +01:00
committed by GitHub
parent ff9e63a393
commit a61e51f579
20 changed files with 2074 additions and 4 deletions

View File

@@ -0,0 +1,212 @@
=================================================
Generic MIPI DCS compatible LCD Controller driver
=================================================
Overview
-------------
From the `Wikipedia <https://en.wikipedia.org/wiki/MIPI_Alliance>`__:
`MIPI Allience <https://www.mipi.org/>`__ is a global business alliance that develops technical specifications
for the mobile ecosystem, particularly smart phones but including mobile-influenced industries. MIPI was founded in 2003 by Arm, Intel, Nokia, Samsung,
STMicroelectronics and Texas Instruments.
MIPI Allience published a series of specifications related to display devices, including DBI (Display Bus Interface), DSI (Display Serial Interface) and DCS
Display Command Set). Usually when one talks about a MIPI-compatible display, one thinks of a device with a DSI serial interface. However, the DBI specification
includes a number of other, legacy interfaces, like SPI and a 8080-compatible parallel interface, which are often used to interface LCD displays to microcontrollers.
Furthermore, the DCS specification contains a standard command set, which is supported by a large number of legacy TFT LCD controllers, including the popular Sitronix
(ST7735, ST7789, ST7796) and Ilitek (ILI9341) SOCs.
The DCS command set provides a common interface to configure display orientation, color resolution, various power modes, and provide generic video memory access. On top
of that standard command set each LCD controller chip has a number of vendor-specific commands to configure voltage generator levels, timings, or gamma curves.
It is important to understand that this generic MIPI LCD driver is not a hardware driver for displays with DSI interface. Instead, it implements the MIPI DCS command
set, and provides a common framework for chip-specific display controllers.
.. tip::
Although this is a generic driver, it can be used to support compatible chips which do not have a specific driver.
Prerequisites
-------------
There are no prerequisites.
Configuring the driver
----------------------
Enable the generic MIPI LCD driver support in lv_conf.h, by cmake compiler define or by KConfig
.. code:: c
#define LV_USE_GENERIC_MIPI 1
.. note::
:c:macro:`LV_USE_GENERIC_MIPI` is automatically enabled when a compatible driver is enabled.
Usage
-----
You need to implement two platform-dependent functions:
.. code:: c
/* Send short command to the LCD. This function shall wait until the transaction finishes. */
int32_t my_lcd_send_cmd(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, const uint8_t *param, size_t param_size)
{
...
}
/* Send large array of pixel data to the LCD. If necessary, this function has to do the byte-swapping. This function can do the transfer in the background. */
int32_t my_lcd_send_color(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, uint8_t *param, size_t param_size)
{
...
}
The only difference between the :cpp:func:`my_lcd_send_cmd()` and :cpp:func:`my_lcd_send_color()` functions is that :cpp:func:`my_lcd_send_cmd()` is used to send short commands and it is expected
complete the transaction when it returns (in other words, it should be blocking), while :cpp:func:`my_lcd_send_color()` is only used to send pixel data, and it is recommended to use
DMA to transmit data in the background. More sophisticated methods can be also implemented, like queing transfers and scheduling them in the background.
Please note that while display flushing is handled by the driver, it is the user's responsibility to call :cpp:func:`lv_display_flush_ready()`
when the color transfer completes. In case of a DMA transfer this is usually done in a transfer ready callback.
.. note::
While it is acceptable to use a blocking implementation for the pixel transfer as well, performance will suffer.
.. tip::
Care must be taken to avoid sending a command while there is an active transfer going on in the background. It is the user's responsibility to implement this either
by polling the hardware, polling a global variable (which is reset at the end of the transfer), or by using a semaphore or other locking mechanism.
Please also note that the driver does not handle the draw buffer allocation, because this may be platform-dependent, too. Thus you need to allocate the buffers and assign them
to the display object as usual by calling :cpp:func:`lv_display_set_draw_buffers()`.
The driver can be used to create multiple displays. In such a configuration the callbacks must be able to distinguish between the displays. Usually one would
implement a separate set of callbacks for each display. Also note that the user must take care of arbitrating the bus when multiple devices are connected to it.
Example
-------
.. note::
You can find the actual implementation of the callbacks on an STM32F746 using STM32CubeIDE and the ST HAL libraries
`here <https://github.com/lvgl/lvgl/doc/integration/drivers/display/lcd_stm32_hal.rst>`__.
.. code:: c
#include "src/dev/display/st7789/lv_st7789.h"
#define LCD_H_RES 240
#define LCD_V_RES 320
#define LCD_BUF_LINES 60
lv_display_t *my_disp;
...
/* Initialize LCD I/O bus, reset LCD */
static int32_t my_lcd_io_init(void)
{
...
return HAL_OK;
}
/* Send command to the LCD controller */
static void my_lcd_send_cmd(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, const uint8_t *param, size_t param_size)
{
...
}
/* Send pixel data to the LCD controller */
static void my_lcd_send_color(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, uint8_t *param, size_t param_size)
{
...
}
int main(int argc, char ** argv)
{
...
/* Initialize LVGL */
lv_init();
/* Initialize LCD bus I/O */
if (my_lcd_io_init() != 0)
return;
/* Create the LVGL display object and the LCD display driver */
my_disp = lv_lcd_generic_mipi_create(LCD_H_RES, LCD_V_RES, LV_LCD_FLAG_NONE, my_lcd_send_cmd, my_lcd_send_color);
/* Set display orientation to landscape */
lv_display_set_rotation(my_disp, LV_DISPLAY_ROTATION_90);
/* Configure draw buffers, etc. */
lv_color_t * buf1 = NULL;
lv_color_t * buf2 = NULL;
uint32_t buf_size = LCD_H_RES * LCD_BUF_LINES * lv_color_format_get_size(lv_disp_get_color_format(my_disp));
buf1 = lv_malloc(buf_size);
if(buf1 == NULL) {
LV_LOG_ERROR("display draw buffer malloc failed");
return;
}
/* Allocate secondary buffer if needed */
...
lv_display_set_buffers(my_disp, buf1, buf2, buf_size, LV_DISPLAY_RENDER_MODE_PARTIAL);
ui_init(my_disp);
while(true) {
...
/* Periodically call the lv_timer handler */
lv_timer_handler();
}
}
Advanced topics
---------------
Create flags
^^^^^^^^^^^^
The third argument of the :cpp:func:`lv_lcd_generic_mipi_create()` function is a flag array. This can be used to configure the orientation and RGB ordering of the panel if the
default settings do not work for you. In particular, the generic MIPI driver accepts the following flags:
.. code:: c
LV_LCD_FLAG_NONE
LV_LCD_FLAG_MIRROR_X
LV_LCD_FLAG_MIRROR_Y
LV_LCD_FLAG_BGR
You can pass multiple flags by ORing them together, e.g., :c:macro:`LV_LCD_FLAG_MIRROR_X | LV_LCD_FLAG_BGR`.
Custom command lists
^^^^^^^^^^^^^^^^^^^^
While the chip-specific drivers do their best to initialize the LCD controller correctly, it is possible, that different TFT panels need different configurations.
In particular a correct gamma setup is crucial for good color reproduction. Unfortunately, finding a good set of parameters is not easy. Usually the manufacturer
of the panel provides some example code with recommended register settings.
You can use the ``my_lcd_send_cmd()`` function to send an arbitrary command to the LCD controller. However, to make it easier to send a large number of parameters
the generic MIPI driver supports sending a custom command list to the controller. The commands must be put into a 'uint8_t' array:
.. code:: c
static const uint8_t init_cmd_list[] = {
<command 1>, <number of parameters>, <parameter 1>, ... <parameter N>,
<command 2>, <number of parameters>, <parameter 1>, ... <parameter N>,
...
LV_LCD_CMD_DELAY_MS, LV_LCD_CMD_EOF /* terminate list: this is required! */
};
...
lv_lcd_generic_mipi_send_cmd_list(my_disp, init_cmd_list);
You can add a delay between the commands by using the pseudo-command ``LV_LCD_CMD_DELAY_MS``, which must be followed by the delay given in 10ms units.
To terminate the command list you must use a delay with a value of ``LV_LCD_CMD_EOF``, as shown above.
See an actual example of sending a command list `here <https://github.com/lvgl/lvgl/src/dev/display/st7789/lv_st7789.c>`__.

View File

@@ -1,5 +1,68 @@
=======
ILI9341
=======
=============================
ILI9341 LCD Controller driver
=============================
TODO
Overview
-------------
The `ILI9341 <https://www.buydisplay.com/download/ic/ILI9341.pdf>`__ is a 262,144-color single-chip SOC driver for a-TFT liquid crystal display with resolution of 240RGBx320
dots, comprising a 720-channel source driver, a 320-channel gate driver, 172,800 bytes GRAM for graphic
display data of 240RGBx320 dots, and power supply circuit.
ILI9341 supports parallel 8-/9-/16-/18-bit data bus MCU interface, 6-/16-/18-bit data bus RGB interface and
3-/4-line serial peripheral interface (SPI).
The ILI9341 LCD controller `driver <https://github.com/lvgl/lvgl/src/dev/display/ili9341>`__ is a platform-agnostic driver, based on the `generic MIPI driver <https://github.com/lvgl/lvgl/doc/integration/drivers/display/gen_mipi.rst>`__.
It implements display initialization, supports display rotation and implements the display flush callback. The user needs to implement only two platform-specific functions to send
a command or pixel data to the controller via SPI or parallel bus. Typically these are implemented by calling the appropriate SDK library functions on the given platform.
Prerequisites
-------------
There are no prerequisites.
Configuring the driver
----------------------
Enable the ILI9341 driver support in lv_conf.h, by cmake compiler define or by KConfig
.. code:: c
#define LV_USE_ILI9341 1
Usage
-----
You need to implement two platform-dependent functions:
.. code:: c
/* Send short command to the LCD. This function shall wait until the transaction finishes. */
int32_t my_lcd_send_cmd(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, const uint8_t *param, size_t param_size)
{
...
}
/* Send large array of pixel data to the LCD. If necessary, this function has to do the byte-swapping. This function can do the transfer in the background. */
int32_t my_lcd_send_color(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, uint8_t *param, size_t param_size)
{
...
}
To create an ILI9341-based display use the function
.. code:: c
/**
* Create an LCD display with ILI9341 driver
* @param hor_res horizontal resolution
* @param ver_res vertical resolution
* @param flags default configuration settings (mirror, RGB ordering, etc.)
* @param send_cmd platform-dependent function to send a command to the LCD controller (usually uses polling transfer)
* @param send_color platform-dependent function to send pixel data to the LCD controller (usually uses DMA transfer: must implement a 'ready' callback)
* @return pointer to the created display
*/
lv_display_t * lv_ili9341_create(uint32_t hor_res, uint32_t ver_res, lv_lcd_flag_t flags,
lv_ili9341_send_cmd_cb_t send_cmd_cb, lv_ili9341_send_color_cb_t send_color_cb);
For additional details and a working example see the `generic MIPI driver documentation <https://github.com/lvgl/lvgl/doc/integration/drivers/display/gen_mipi.rst>`__.

View File

@@ -6,3 +6,6 @@ Display
:maxdepth: 2
ili9341
st7735
st7789
st7796

View File

@@ -0,0 +1,109 @@
==================================================================================================
LCD driver SPI bus I/O implementation example for STM32 devices using the STM32Cube HAL SPI driver
==================================================================================================
This is an example implementation of an SPI bus driver using STM32CubeIDE and the ST HAL libraries, tested on a Nucleo-F746ZG board. This code example only implements
the LCD driver specific parts, so you still have to configure the hardware using STM32CubeMX or STM32CubeIDE. It is not meant as the best possible implementation,
but since it uses DMA for the pixel transfer, it has a good performance.
To use this code without change you need to name the appropriate GPIO pins as follows:
.. code:: c
LCD_RESET /* Reset */
LCD_CS /* Chip Select */
LCD_DCX /* Data/Command Select */
The example code uses the SPI1 port. The SPI controller of the STM32F746 is capable of 16-bit transfers, and it can swap the 16-bit pixel data bytes on the fly, so
there is no need to do this in software. This improves the performance considerably.
This code implements a rather simple locking mechanism using a global variable :cpp:var:`my_disp_bus_busy` to prevent accessing the controller while there is a DMA transfer
going on in the background. In a more sophisticated implementation this could be replaced with a semaphore or a transaction queue.
.. code:: c
#include "stm32f7xx_hal.h"
#include "lvgl.h"
...
lv_display_t *my_disp;
volatile int my_disp_bus_busy = 0;
...
/* DMA transfer ready callback */
static void my_lcd_color_transfer_ready_cb(SPI_HandleTypeDef *hspi)
{
/* CS high */
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET);
my_disp_bus_busy = 0;
lv_display_flush_ready(my_disp);
}
/* Initialize LCD I/O bus, reset LCD */
static int32_t my_lcd_io_init(void)
{
/* Register SPI Tx Complete Callback */
HAL_SPI_RegisterCallback(&hspi1, HAL_SPI_TX_COMPLETE_CB_ID, stm32_lcd_color_transfer_ready_cb);
/* reset LCD */
HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_SET);
return HAL_OK;
}
/* Send short command to the LCD. This function shall wait until the transaction finishes. */
static void my_lcd_send_cmd(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, const uint8_t *param, size_t param_size)
{
LV_UNUSED(disp);
/* Set the SPI in 8-bit mode */
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
HAL_SPI_Init(&hspi1);
/* DCX low (command) */
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_RESET);
/* CS low */
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET);
/* send command */
if (HAL_SPI_Transmit(&hspi1, cmd, cmd_size, BUS_SPI1_POLL_TIMEOUT) == HAL_OK) {
/* DCX high (data) */
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_SET);
/* for short data blocks we use polling transfer */
HAL_SPI_Transmit(&hspi1, (uint8_t *)param, (uint16_t)param_size, BUS_SPI1_POLL_TIMEOUT);
/* CS high */
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET);
}
}
/* Send large array of pixel data to the LCD. If necessary, this function has to do the byte-swapping. This function can do the transfer in the background. */
static void my_lcd_send_color(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, uint8_t *param, size_t param_size)
{
LV_UNUSED(disp);
while (my_disp_bus_busy); /* wait until previous transfer is finished */
/* Set the SPI in 8-bit mode */
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
HAL_SPI_Init(&hspi1);
/* DCX low (command) */
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_RESET);
/* CS low */
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET);
/* send command */
if (HAL_SPI_Transmit(&hspi1, cmd, cmd_size, BUS_SPI1_POLL_TIMEOUT) == HAL_OK) {
/* DCX high (data) */
HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_SET);
/* for color data use DMA transfer */
/* Set the SPI in 16-bit mode to match endianess */
hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
HAL_SPI_Init(&hspi1);
my_disp_bus_busy = 1;
HAL_SPI_Transmit_DMA(&hspi1, param, (uint16_t)param_size / 2);
/* NOTE: CS will be reset in the transfer ready callback */
}
}

View File

@@ -0,0 +1,70 @@
=============================
ST7735 LCD Controller driver
=============================
Overview
-------------
The `ST7735S <https://www.buydisplay.com/download/ic/ST7735S.pdf>`__ is a single-chip controller/driver for 262K-color, graphic type TFT-LCD. It consists of 396
source line and 162 gate line driving circuits. This chip is capable of connecting directly to an external
microprocessor, and accepts Serial Peripheral Interface (SPI), 8-bit/9-bit/16-bit/18-bit parallel interface.
Display data can be stored in the on-chip display data RAM of 132 x 162 x 18 bits. It can perform display data
RAM read/write operation with no external operation clock to minimize power consumption. In addition,
because of the integrated power supply circuits necessary to drive liquid crystal, it is possible to make a
display system with fewer components.
The ST7735 LCD controller `driver <https://github.com/lvgl/lvgl/src/dev/display/st7735>`__ is a platform-agnostic driver, based on the `generic MIPI driver <https://github.com/lvgl/lvgl/doc/integration/drivers/display/gen_mipi.rst>`__.
It implements display initialization, supports display rotation and implements the display flush callback. The user needs to implement only two platform-specific functions to send
a command or pixel data to the controller via SPI or parallel bus. Typically these are implemented by calling the appropriate SDK library functions on the given platform.
Prerequisites
-------------
There are no prerequisites.
Configuring the driver
----------------------
Enable the ST7735 driver support in lv_conf.h, by cmake compiler define or by KConfig
.. code:: c
#define LV_USE_ST7735 1
Usage
-----
You need to implement two platform-dependent functions:
.. code:: c
/* Send short command to the LCD. This function shall wait until the transaction finishes. */
int32_t my_lcd_send_cmd(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, const uint8_t *param, size_t param_size)
{
...
}
/* Send large array of pixel data to the LCD. If necessary, this function has to do the byte-swapping. This function can do the transfer in the background. */
int32_t my_lcd_send_color(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, uint8_t *param, size_t param_size)
{
...
}
To create an ST7735-based display use the function
.. code:: c
/**
* Create an LCD display with ST7735 driver
* @param hor_res horizontal resolution
* @param ver_res vertical resolution
* @param flags default configuration settings (mirror, RGB ordering, etc.)
* @param send_cmd platform-dependent function to send a command to the LCD controller (usually uses polling transfer)
* @param send_color platform-dependent function to send pixel data to the LCD controller (usually uses DMA transfer: must implement a 'ready' callback)
* @return pointer to the created display
*/
lv_display_t * lv_st7735_create(uint32_t hor_res, uint32_t ver_res, lv_lcd_flag_t flags,
lv_st7735_send_cmd_cb_t send_cmd_cb, lv_st7735_send_color_cb_t send_color_cb);
For additional details and a working example see the `generic MIPI driver documentation <https://github.com/lvgl/lvgl/doc/integration/drivers/display/gen_mipi.rst>`__.

View File

@@ -0,0 +1,69 @@
=============================
ST7789 LCD Controller driver
=============================
Overview
-------------
The `ST7789 <https://www.buydisplay.com/download/ic/ST7789.pdf>`__ is a single-chip controller/driver for 262K-color, graphic type TFT-LCD. It consists of 720
source line and 320 gate line driving circuits. This chip is capable of connecting directly to an external
microprocessor, and accepts, 8-bits/9-bits/16-bits/18-bits parallel interface. Display data can be stored in the
on-chip display data RAM of 240x320x18 bits. It can perform display data RAM read/write operation with no
external operation clock to minimize power consumption. In addition, because of the integrated power supply
circuit necessary to drive liquid crystal; it is possible to make a display system with the fewest components.
The ST7789 LCD controller `driver <https://github.com/lvgl/lvgl/src/dev/display/st7789>`__ is a platform-agnostic driver, based on the `generic MIPI driver <https://github.com/lvgl/lvgl/doc/integration/drivers/display/gen_mipi.rst>`__.
It implements display initialization, supports display rotation and implements the display flush callback. The user needs to implement only two platform-specific functions to send
a command or pixel data to the controller via SPI or parallel bus. Typically these are implemented by calling the appropriate SDK library functions on the given platform.
Prerequisites
-------------
There are no prerequisites.
Configuring the driver
----------------------
Enable the ST7789 driver support in lv_conf.h, by cmake compiler define or by KConfig
.. code:: c
#define LV_USE_ST7789 1
Usage
-----
You need to implement two platform-dependent functions:
.. code:: c
/* Send short command to the LCD. This function shall wait until the transaction finishes. */
int32_t my_lcd_send_cmd(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, const uint8_t *param, size_t param_size)
{
...
}
/* Send large array of pixel data to the LCD. If necessary, this function has to do the byte-swapping. This function can do the transfer in the background. */
int32_t my_lcd_send_color(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, uint8_t *param, size_t param_size)
{
...
}
To create an ST7789-based display use the function
.. code:: c
/**
* Create an LCD display with ST7789 driver
* @param hor_res horizontal resolution
* @param ver_res vertical resolution
* @param flags default configuration settings (mirror, RGB ordering, etc.)
* @param send_cmd platform-dependent function to send a command to the LCD controller (usually uses polling transfer)
* @param send_color platform-dependent function to send pixel data to the LCD controller (usually uses DMA transfer: must implement a 'ready' callback)
* @return pointer to the created display
*/
lv_display_t * lv_st7789_create(uint32_t hor_res, uint32_t ver_res, lv_lcd_flag_t flags,
lv_st7789_send_cmd_cb_t send_cmd_cb, lv_st7789_send_color_cb_t send_color_cb);
For additional details and a working example see the `generic MIPI driver documentation <https://github.com/lvgl/lvgl/doc/integration/drivers/display/gen_mipi.rst>`__.

View File

@@ -0,0 +1,70 @@
=============================
ST7796 LCD Controller driver
=============================
Overview
-------------
The `ST7796S <https://www.buydisplay.com/download/ic/ST7796S.pdf>`__ is a single-chip controller/driver for 262K-color, graphic type TFT-LCD. It consists of 960
source lines and 480 gate lines driving circuits. The ST7796S is capable of connecting directly to an external
microprocessor, and accepts 8-bit/9-bit/16-bit/18-bit parallel interface, SPI, and the ST7796S also provides
MIPI interface. Display data can be stored in the on-chip display data RAM of 320x480x18 bits. It can perform
display data RAM read-/write-operation with no external clock to minimize power consumption. In addition,
because of the integrated power supply circuit necessary to drive liquid crystal; it is possible to make a display
system with fewest components.
The ST7796 LCD controller `driver <https://github.com/lvgl/lvgl/src/dev/display/st7796>`__ is a platform-agnostic driver, based on the `generic MIPI driver <https://github.com/lvgl/lvgl/doc/integration/drivers/display/gen_mipi.rst>`__.
It implements display initialization, supports display rotation and implements the display flush callback. The user needs to implement only two platform-specific functions to send
a command or pixel data to the controller via SPI or parallel bus. Typically these are implemented by calling the appropriate SDK library functions on the given platform.
Prerequisites
-------------
There are no prerequisites.
Configuring the driver
----------------------
Enable the ST7796 driver support in lv_conf.h, by cmake compiler define or by KConfig
.. code:: c
#define LV_USE_ST7796 1
Usage
-----
You need to implement two platform-dependent functions:
.. code:: c
/* Send short command to the LCD. This function shall wait until the transaction finishes. */
int32_t my_lcd_send_cmd(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, const uint8_t *param, size_t param_size)
{
...
}
/* Send large array of pixel data to the LCD. If necessary, this function has to do the byte-swapping. This function can do the transfer in the background. */
int32_t my_lcd_send_color(lv_display_t *disp, const uint8_t *cmd, size_t cmd_size, uint8_t *param, size_t param_size)
{
...
}
To create an ST7796-based display use the function
.. code:: c
/**
* Create an LCD display with ST7796 driver
* @param hor_res horizontal resolution
* @param ver_res vertical resolution
* @param flags default configuration settings (mirror, RGB ordering, etc.)
* @param send_cmd platform-dependent function to send a command to the LCD controller (usually uses polling transfer)
* @param send_color platform-dependent function to send pixel data to the LCD controller (usually uses DMA transfer: must implement a 'ready' callback)
* @return pointer to the created display
*/
lv_display_t * lv_st7796_create(uint32_t hor_res, uint32_t ver_res, lv_lcd_flag_t flags,
lv_st7796_send_cmd_cb_t send_cmd_cb, lv_st7796_send_color_cb_t send_color_cb);
For additional details and a working example see the `generic MIPI driver documentation <https://github.com/lvgl/lvgl/doc/integration/drivers/display/gen_mipi.rst>`__.