Skip to content

Commit

Permalink
feat(lvgl_port): Initial support for ppa rendering in lvgl
Browse files Browse the repository at this point in the history
      Mainly supports the following features:
       - color blend (simple fill)
       - color blend with opa
       - blend normal (blend with argb8888)
       - blend normal to color (color convert / memcpy)
  • Loading branch information
ThunderDai committed Oct 28, 2024
1 parent c90025b commit 461a0f8
Show file tree
Hide file tree
Showing 21 changed files with 1,995 additions and 22 deletions.
21 changes: 16 additions & 5 deletions components/esp_lvgl_port/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ if("usb_host_hid" IN_LIST build_components)
endif()

# Include SIMD assembly source code for rendering, only for (9.1.0 <= LVG_version < 9.2.0) and only for esp32 and esp32s3
if((lvgl_ver VERSION_GREATER_EQUAL "9.1.0") AND (lvgl_ver VERSION_LESS "9.2.0"))
if(CONFIG_IDF_TARGET_ESP32 OR CONFIG_IDF_TARGET_ESP32S3)
if((lvgl_ver VERSION_GREATER_EQUAL "9.1.0") AND (lvgl_ver VERSION_LESS_EQUAL "9.2.0"))
if(CONFIG_IDF_TARGET_ESP32 OR CONFIG_IDF_TARGET_ESP32S3 OR CONFIG_IDF_TARGET_ESP32P4)
message(VERBOSE "Compiling SIMD")
if(CONFIG_IDF_TARGET_ESP32S3)
file(GLOB_RECURSE ASM_SRCS ${PORT_PATH}/simd/*_esp32s3.S) # Select only esp32s3 related files
else()
elseif(CONFIG_IDF_TARGET_ESP32)
file(GLOB_RECURSE ASM_SRCS ${PORT_PATH}/simd/*_esp32.S) # Select only esp32 related files
endif()
list(APPEND ADD_SRCS ${ASM_SRCS})
Expand All @@ -91,9 +91,16 @@ if((lvgl_ver VERSION_GREATER_EQUAL "9.1.0") AND (lvgl_ver VERSION_LESS "9.2.0"))
idf_component_get_property(lvgl_lib ${lvgl_name} COMPONENT_LIB)
target_include_directories(${lvgl_lib} PRIVATE "include")

if(CONFIG_IDF_TARGET_ESP32P4)
file(GLOB_RECURSE PPA_SRCS ${PORT_PATH}/ppa/*)
list(APPEND ADD_SRCS ${PPA_SRCS})
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u lv_malloc_core")
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u esp_ppa_fill_for_lvgl")
else()
# Force link .S files
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u lv_color_blend_to_argb8888_esp")
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u lv_color_blend_to_rgb565_esp")
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u lv_color_blend_to_argb8888_esp")
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u lv_color_blend_to_rgb565_esp")
endif()
endif()
endif()

Expand All @@ -114,5 +121,9 @@ target_link_libraries(lvgl_port_lib PRIVATE
${ADD_LIBS}
)

if(CONFIG_IDF_TARGET_ESP32P4)
target_link_libraries(lvgl_port_lib PRIVATE idf::esp_driver_ppa idf::esp_mm)
endif()

# Finally, link the lvgl_port_lib its esp-idf interface library
target_link_libraries(${COMPONENT_LIB} INTERFACE lvgl_port_lib)
4 changes: 4 additions & 0 deletions components/esp_lvgl_port/examples/mipi_dsi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(mipi_dsi_panel)
86 changes: 86 additions & 0 deletions components/esp_lvgl_port/examples/mipi_dsi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
| Supported Targets | ESP32-P4 |
| ----------------- | -------- |

# MIPI DSI LCD Panel Example

[esp_lcd](https://docs.espressif.com/projects/esp-idf/en/latest/esp32p4/api-reference/peripherals/lcd/dsi_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 support [ILI9881C](https://components.espressif.com/components/espressif/esp_lcd_ili9881c) and [EK79007](https://components.espressif.com/components/espressif/esp_lcd_ek79007)
* 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.

### Configure

Run `idf.py menuconfig` and go to `Example Configuration`:

* Choose the LCD model in `Select MIPI LCD model` according to your board.
* Choose whether to `Use DMA2D to copy draw buffer to frame buffer` asynchronously. If you choose `No`, the draw buffer will be copied to the frame buffer synchronously by CPU.
* Choose if you want to `Monitor Refresh Rate by GPIO`. If you choose `Yes`, then you can attach an oscilloscope or logic analyzer to the GPIO pin to monitor the Refresh Rate of the display.
Please note, the actual Refresh Rate should be **double** the square wave frequency.

### 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 the ESP Component 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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRCS "mipi_dsi_lcd_main.c"
INCLUDE_DIRS ".")
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
menu "Example Configuration"
config EXAMPLE_AVOID_BLUE_SCREEN
bool "Avoid blue screen caused for PSRAM bandwidth"
default y
help
Enable this option, DMA2D peak will be limted, then GDMA will run normal.
endmenu
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
dependencies:
espressif/esp32_p4_function_ev_board:
version: "*"
override_path: "../../../../../bsp/esp32_p4_function_ev_board"
lvgl/lvgl: "~9.2.0"
esp_lcd_ili9881c: "^1.0.0"
esp_lcd_ek79007: "^1.0.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"

#include "hal/axi_dma_ll.h"
#include "hal/axi_icm_ll.h"
#include "soc/mipi_dsi_bridge_struct.h"

#include "lv_demos.h"
#include "bsp/esp-bsp.h"

static char *TAG = "app_main";

#define LOG_MEM_INFO (0)

static void esp_dsi_avoid_blue_screen(void)
{
axi_icm_ll_set_dw_gdma_qos_arbiter_prio(0, 9, 10);
axi_icm_ll_set_dw_gdma_qos_arbiter_prio(1, 9, 10);
axi_icm_ll_set_h264_dma_qos_arbiter_prio(1, 5, 5);
axi_icm_ll_set_h264_dma_qos_arbiter_prio(0, 5, 5);
axi_icm_ll_set_dma2d_qos_arbiter_prio(4, 4);
axi_icm_ll_set_cache_qos_arbiter_prio(4, 4);

int peak_level = 5; // 4: 800MB/s, 5: 400MB, 6: 200MB
axi_icm_ll_set_qos_burstiness(AXI_ICM_MASTER_DMA2D, 256);
axi_icm_ll_set_qos_peak_transaction_rate(AXI_ICM_MASTER_DMA2D, peak_level, peak_level + 1);
}

void app_main(void)
{
#if CONFIG_EXAMPLE_AVOID_BLUE_SCREEN
esp_dsi_avoid_blue_screen();
#endif

/* Initialize display and LVGL */
bsp_display_start();

#if CONFIG_BSP_DISPLAY_LVGL_AVOID_TEAR
ESP_LOGI(TAG, "Avoid lcd tearing effect");
#if CONFIG_BSP_DISPLAY_LVGL_FULL_REFRESH
ESP_LOGI(TAG, "LVGL full-refresh");
#elif CONFIG_BSP_DISPLAY_LVGL_DIRECT_MODE
ESP_LOGI(TAG, "LVGL direct-mode");
#endif
#endif

/* Set display brightness to 100% */
bsp_display_backlight_on();

ESP_LOGI(TAG, "Display LVGL demo");
bsp_display_lock(0);
// lv_demo_widgets(); /* A widgets example */
// lv_demo_music(); /* A modern, smartphone-like music player demo. */
// lv_demo_stress(); /* A stress test for LVGL. */
lv_demo_benchmark(); /* A demo to measure the performance of LVGL or to compare different settings. */
bsp_display_unlock();

#if LOG_MEM_INFO
static char buffer[128]; /* Make sure buffer is enough for `sprintf` */
while (1) {
sprintf(buffer, " Biggest / Free / Total\n"
"\t SRAM : [%8d / %8d / %8d]\n"
"\t PSRAM : [%8d / %8d / %8d]",
heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL),
heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
heap_caps_get_total_size(MALLOC_CAP_INTERNAL),
heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM),
heap_caps_get_free_size(MALLOC_CAP_SPIRAM),
heap_caps_get_total_size(MALLOC_CAP_SPIRAM));
ESP_LOGI("MEM", "%s", buffer);

vTaskDelay(pdMS_TO_TICKS(500));
}
#endif
}
5 changes: 5 additions & 0 deletions components/esp_lvgl_port/examples/mipi_dsi/partitions.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 10M,
Original file line number Diff line number Diff line change
@@ -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')
97 changes: 97 additions & 0 deletions components/esp_lvgl_port/examples/mipi_dsi/sdkconfig.defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@

#
# Serial flasher config
#
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y

#
# Compiler options
#
CONFIG_COMPILER_OPTIMIZATION_PERF=y

#
# Kernel
#
CONFIG_FREERTOS_HZ=1000

#
# LVGL configuration
#
CONFIG_LV_CONF_SKIP=y

#
# Enable built-in fonts
#
CONFIG_LV_FONT_MONTSERRAT_14=y
CONFIG_LV_FONT_MONTSERRAT_16=y
CONFIG_LV_FONT_MONTSERRAT_18=y
CONFIG_LV_FONT_MONTSERRAT_22=y
CONFIG_LV_FONT_MONTSERRAT_24=y
CONFIG_LV_FONT_MONTSERRAT_32=y

#
# Color Settings
#
CONFIG_LV_COLOR_DEPTH_24=y

#
# Compiler Settings
#
CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM=y

#
# Logging
#
CONFIG_LV_USE_LOG=n
CONFIG_LV_LOG_LEVEL_ERROR=y
CONFIG_LV_LOG_PRINTF=n

#
# Display
#
CONFIG_BSP_LCD_DPI_BUFFER_NUMS=2
CONFIG_BSP_DISPLAY_LVGL_AVOID_TEAR=y
CONFIG_BSP_DISPLAY_LVGL_DIRECT_MODE=y
CONFIG_BSP_LCD_COLOR_FORMAT_RGB888=y
CONFIG_BSP_LCD_TYPE_1280_800=y
# end of Display
# end of Board Support Package(ESP32-P4)

#
# Partition Table
#
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

#
# Demos
#
CONFIG_LV_USE_DEMO_WIDGETS=y
CONFIG_LV_DEMO_WIDGETS_SLIDESHOW=y
CONFIG_LV_USE_DEMO_KEYPAD_AND_ENCODER=y
CONFIG_LV_USE_DEMO_BENCHMARK=y
CONFIG_LV_USE_DEMO_RENDER=y
CONFIG_LV_USE_DEMO_SCROLL=y
CONFIG_LV_USE_DEMO_STRESS=y
CONFIG_LV_USE_DEMO_TRANSFORM=y
CONFIG_LV_USE_DEMO_MUSIC=y
CONFIG_LV_DEMO_MUSIC_SQUARE=y
CONFIG_LV_DEMO_MUSIC_LANDSCAPE=y
CONFIG_LV_DEMO_MUSIC_ROUND=y
CONFIG_LV_DEMO_MUSIC_LARGE=y
CONFIG_LV_DEMO_MUSIC_AUTO_PLAY=y
CONFIG_LV_USE_DEMO_FLEX_LAYOUT=y
CONFIG_LV_USE_DEMO_MULTILANG=n
# end of Demos
# end of LVGL configuration
# end of Component config

#
# Others
#
CONFIG_LV_USE_OBSERVER=y
CONFIG_LV_USE_SYSMON=y
CONFIG_LV_USE_PERF_MONITOR=y
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_HEX=y
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
CONFIG_SPIRAM_SPEED_200M=y
CONFIG_SPIRAM_MEMTEST=n
CONFIG_CACHE_L2_CACHE_LINE_128B=y

CONFIG_LV_COLOR_DEPTH_16=n
CONFIG_BSP_LCD_COLOR_FORMAT_RGB565=n

#
# ESP-MM: Memory Management Configurations
#
CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS=y
CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS_MAX_LEN=0x4000
# end of ESP-MM: Memory Management Configurations

#
# Example Configuration
#
CONFIG_EXAMPLE_AVOID_BLUE_SCREEN=y
# end of Example Configuration

#
# Rendering Configuration
#
# Set custom ASM render and provide a header file with function prototypes
CONFIG_LV_DRAW_SW_ASM_CUSTOM=y
CONFIG_LV_DRAW_SW_ASM_CUSTOM_INCLUDE="esp_lvgl_port_lv_blend_ppa.h"

#
# Memory Settings
#
CONFIG_LV_USE_CUSTOM_MALLOC=y
CONFIG_LV_USE_CLIB_SPRINTF=y
CONFIG_LV_USE_CLIB_STRING=y
Loading

0 comments on commit 461a0f8

Please sign in to comment.