Skip to content

Commit 645f085

Browse files
committed
feat(lvgl_port): Used PPA for rotation on ESP32-P4 and added SW rotation
1 parent 7f12e73 commit 645f085

File tree

14 files changed

+660
-36
lines changed

14 files changed

+660
-36
lines changed

bsp/esp32_p4_function_ev_board/esp32_p4_function_ev_board.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ static lv_indev_t *disp_indev = NULL;
3030
#endif // (BSP_CONFIG_NO_GRAPHIC_LIB == 0)
3131

3232
sdmmc_card_t *bsp_sdcard = NULL; // Global uSD card handler
33-
static esp_lcd_touch_handle_t tp; // LCD touch handle
3433
static bool i2c_initialized = false;
3534
static TaskHandle_t usb_host_task; // USB Host Library task
3635

@@ -357,15 +356,14 @@ static lv_display_t *bsp_display_lcd_init(const bsp_display_cfg_t *cfg)
357356
.mirror_x = true,
358357
.mirror_y = true,
359358
},
359+
.color_format = LV_COLOR_FORMAT_RGB565,
360360
.flags = {
361361
.buff_dma = cfg->flags.buff_dma,
362362
.buff_spiram = cfg->flags.buff_spiram,
363363
#if LVGL_VERSION_MAJOR >= 9
364364
.swap_bytes = (BSP_LCD_BIGENDIAN ? true : false),
365365
#endif
366-
#if LVGL_VERSION_MAJOR == 8
367366
.sw_rotate = cfg->flags.sw_rotate, /* Only SW rotation is supported for 90° and 270° */
368-
#endif
369367
}
370368
};
371369

@@ -374,6 +372,7 @@ static lv_display_t *bsp_display_lcd_init(const bsp_display_cfg_t *cfg)
374372

375373
static lv_indev_t *bsp_display_indev_init(lv_display_t *disp)
376374
{
375+
esp_lcd_touch_handle_t tp;
377376
BSP_ERROR_CHECK_RETURN_NULL(bsp_touch_new(NULL, &tp));
378377
assert(tp);
379378

@@ -395,6 +394,7 @@ lv_display_t *bsp_display_start(void)
395394
.flags = {
396395
.buff_dma = true,
397396
.buff_spiram = false,
397+
.sw_rotate = true,
398398
}
399399
};
400400
return bsp_display_start_with_config(&cfg);

bsp/esp32_p4_function_ev_board/include/bsp/esp32_p4_function_ev_board.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ esp_err_t bsp_sdcard_unmount(void);
184184

185185
#if (BSP_CONFIG_NO_GRAPHIC_LIB == 0)
186186

187-
#define BSP_LCD_DRAW_BUFF_SIZE (BSP_LCD_H_RES * 100) // Frame buffer size in pixels
187+
#define BSP_LCD_DRAW_BUFF_SIZE (BSP_LCD_H_RES * 50) // Frame buffer size in pixels
188188
#define BSP_LCD_DRAW_BUFF_DOUBLE (0)
189189

190190
/**

components/esp_lvgl_port/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 2.3.0
4+
- Fixed LVGL port for using with LVGL9 OS FreeRTOS enabled
5+
- Added support for SW rotation in LVGL9
6+
- Added support for PPA rotation in LVGL9 (available for ESP32P4)
7+
38
## 2.2.2
49

510
### Fixes

components/esp_lvgl_port/CMakeLists.txt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,20 @@ endif()
2222

2323
set(PORT_PATH "src/${PORT_FOLDER}")
2424

25+
26+
set(PRIV_REQUIRES "esp_timer")
27+
set(PPA_PATH "")
28+
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.3")
29+
list(APPEND PRIV_REQUIRES "esp_driver_ppa")
30+
list(APPEND PPA_PATH "src/common/ppa/lcd_ppa.c")
31+
endif()
32+
2533
idf_component_register(
26-
SRCS "${PORT_PATH}/esp_lvgl_port.c" "${PORT_PATH}/esp_lvgl_port_disp.c"
34+
SRCS "${PORT_PATH}/esp_lvgl_port.c" "${PORT_PATH}/esp_lvgl_port_disp.c" "${PPA_PATH}"
2735
INCLUDE_DIRS "include"
2836
PRIV_INCLUDE_DIRS "priv_include"
2937
REQUIRES "esp_lcd"
30-
PRIV_REQUIRES "esp_timer")
38+
PRIV_REQUIRES "${PRIV_REQUIRES}")
3139

3240
set(ADD_SRCS "")
3341
set(ADD_LIBS "")

components/esp_lvgl_port/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,8 @@ Display rotation can be changed at runtime.
265265
lv_disp_set_rotation(disp_handle, LV_DISP_ROT_90);
266266
```
267267

268-
> [!WARNING]
269-
> Software rotation is available only in LVGL 8.
268+
> [!NOTE]
269+
> This feature consume more RAM.
270270
271271
> [!NOTE]
272272
> During the hardware rotating, the component call [`esp_lcd`](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/lcd.html) API. When using software rotation, you cannot use neither `direct_mode` nor `full_refresh` in the driver. See [LVGL documentation](https://docs.lvgl.io/8.3/porting/display.html?highlight=sw_rotate) for more info.

components/esp_lvgl_port/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: "2.2.2"
1+
version: "2.3.0"
22
description: ESP LVGL port
33
url: https://github.com/espressif/esp-bsp/tree/master/components/esp_lvgl_port
44
dependencies:

components/esp_lvgl_port/include/esp_lvgl_port_disp.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,7 @@ typedef struct {
5757
struct {
5858
unsigned int buff_dma: 1; /*!< Allocated LVGL buffer will be DMA capable */
5959
unsigned int buff_spiram: 1; /*!< Allocated LVGL buffer will be in PSRAM */
60-
#if LVGL_VERSION_MAJOR == 8
61-
unsigned int sw_rotate: 1; /*!< Use software rotation (slower) */
62-
#endif
60+
unsigned int sw_rotate: 1; /*!< Use software rotation (slower) or PPA if available */
6361
#if LVGL_VERSION_MAJOR >= 9
6462
unsigned int swap_bytes: 1; /*!< Swap bytes in RGB656 (16-bit) color format before send to LCD driver */
6563
#endif
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
8+
#include <string.h>
9+
#include "esp_err.h"
10+
#include "esp_check.h"
11+
#include "esp_heap_caps.h"
12+
#include "soc/soc_caps.h"
13+
#include "lcd_ppa.h"
14+
15+
#define PPA_LCD_ENABLE_CB 0
16+
17+
#if SOC_PPA_SUPPORTED
18+
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
19+
20+
struct lcd_ppa_t {
21+
uint8_t *buffer;
22+
uint32_t buffer_size;
23+
ppa_client_handle_t srm_handle;
24+
uint32_t color_type_id;
25+
};
26+
27+
static const char *TAG = "PPA";
28+
/*******************************************************************************
29+
* Function definitions
30+
*******************************************************************************/
31+
#if PPA_LCD_ENABLE_CB
32+
static bool _lcd_ppa_callback(ppa_client_handle_t ppa_client, ppa_event_data_t *event_data, void *user_data);
33+
#endif
34+
/*******************************************************************************
35+
* Public API functions
36+
*******************************************************************************/
37+
38+
lcd_ppa_handle_t esp_lcd_ppa_create(const lcd_ppa_cfg_t *cfg)
39+
{
40+
esp_err_t ret = ESP_OK;
41+
assert(cfg != NULL);
42+
43+
lcd_ppa_t *ppa_ctx = malloc(sizeof(lcd_ppa_t));
44+
ESP_GOTO_ON_FALSE(ppa_ctx, ESP_ERR_NO_MEM, err, TAG, "Not enough memory for PPA context allocation!");
45+
memset(ppa_ctx, 0, sizeof(lcd_ppa_t));
46+
47+
uint32_t buffer_caps = 0;
48+
if (cfg->flags.buff_dma) {
49+
buffer_caps |= MALLOC_CAP_DMA;
50+
}
51+
if (cfg->flags.buff_spiram) {
52+
buffer_caps |= MALLOC_CAP_SPIRAM;
53+
}
54+
if (buffer_caps == 0) {
55+
buffer_caps |= MALLOC_CAP_DEFAULT;
56+
}
57+
58+
ppa_ctx->buffer_size = ALIGN_UP(cfg->buffer_size, 64);
59+
ppa_ctx->buffer = heap_caps_aligned_calloc(64, ppa_ctx->buffer_size, sizeof(uint8_t), buffer_caps);
60+
assert(ppa_ctx->buffer != NULL);
61+
62+
ppa_client_config_t ppa_client_config = {
63+
.oper_type = PPA_OPERATION_SRM,
64+
};
65+
ESP_GOTO_ON_ERROR(ppa_register_client(&ppa_client_config, &ppa_ctx->srm_handle), err, TAG, "Error when registering PPA client!");
66+
67+
#if PPA_LCD_ENABLE_CB
68+
ppa_event_callbacks_t ppa_cbs = {
69+
.on_trans_done = _lcd_ppa_callback,
70+
};
71+
ESP_GOTO_ON_ERROR(ppa_client_register_event_callbacks(ppa_ctx->srm_handle, &ppa_cbs), err, TAG, "Error when registering PPA callbacks!");
72+
#endif
73+
74+
ppa_ctx->color_type_id = COLOR_TYPE_ID(cfg->color_space, cfg->pixel_format);
75+
76+
err:
77+
if (ret != ESP_OK) {
78+
if (ppa_ctx->buffer) {
79+
free(ppa_ctx->buffer);
80+
}
81+
if (ppa_ctx) {
82+
free(ppa_ctx);
83+
}
84+
}
85+
86+
return ppa_ctx;
87+
}
88+
89+
void esp_lcd_ppa_delete(lcd_ppa_handle_t handle)
90+
{
91+
lcd_ppa_t *ppa_ctx = (lcd_ppa_t *)handle;
92+
assert(ppa_ctx != NULL);
93+
94+
if (ppa_ctx->buffer) {
95+
free(ppa_ctx->buffer);
96+
}
97+
98+
ppa_unregister_client(ppa_ctx->srm_handle);
99+
100+
free(ppa_ctx);
101+
}
102+
103+
uint8_t *esp_lcd_ppa_get_output_buffer(lcd_ppa_handle_t handle)
104+
{
105+
lcd_ppa_t *ppa_ctx = (lcd_ppa_t *)handle;
106+
assert(ppa_ctx != NULL);
107+
return ppa_ctx->buffer;
108+
}
109+
110+
esp_err_t esp_lcd_ppa_rotate(lcd_ppa_handle_t handle, lcd_ppa_disp_rotate_t *rotate_cfg)
111+
{
112+
lcd_ppa_t *ppa_ctx = (lcd_ppa_t *)handle;
113+
assert(ppa_ctx != NULL);
114+
assert(rotate_cfg != NULL);
115+
const int w = rotate_cfg->area.x2 - rotate_cfg->area.x1 + 1;
116+
const int h = rotate_cfg->area.y2 - rotate_cfg->area.y1 + 1;
117+
118+
/* Set dimension by screen size and rotation */
119+
int out_w = w;
120+
int out_h = h;
121+
122+
int x1 = rotate_cfg->area.x1;
123+
int x2 = rotate_cfg->area.x2;
124+
int y1 = rotate_cfg->area.y1;
125+
int y2 = rotate_cfg->area.y2;
126+
127+
/* Rotate coordinates */
128+
switch (rotate_cfg->rotation) {
129+
case PPA_SRM_ROTATION_ANGLE_0:
130+
break;
131+
case PPA_SRM_ROTATION_ANGLE_90:
132+
out_w = h;
133+
out_h = w;
134+
x1 = rotate_cfg->area.y1;
135+
x2 = rotate_cfg->area.y2;
136+
y1 = rotate_cfg->disp_size.hres - rotate_cfg->area.x2;
137+
y2 = rotate_cfg->disp_size.hres - rotate_cfg->area.x1;
138+
break;
139+
case PPA_SRM_ROTATION_ANGLE_180:
140+
x1 = rotate_cfg->disp_size.hres - rotate_cfg->area.x2 - 1;
141+
x2 = rotate_cfg->disp_size.hres - rotate_cfg->area.x1 - 1;
142+
y1 = rotate_cfg->disp_size.vres - rotate_cfg->area.y2;
143+
y2 = rotate_cfg->disp_size.vres - rotate_cfg->area.y1;
144+
break;
145+
case PPA_SRM_ROTATION_ANGLE_270:
146+
out_w = h;
147+
out_h = w;
148+
x1 = rotate_cfg->disp_size.vres - rotate_cfg->area.y2 - 1;
149+
x2 = rotate_cfg->disp_size.vres - rotate_cfg->area.y1 - 1;
150+
y1 = rotate_cfg->area.x1;
151+
y2 = rotate_cfg->area.x2;
152+
break;
153+
}
154+
/* Return new coordinates */
155+
rotate_cfg->area.x1 = x1;
156+
rotate_cfg->area.x2 = x2;
157+
rotate_cfg->area.y1 = y1;
158+
rotate_cfg->area.y2 = y2;
159+
160+
/* Prepare Operation */
161+
ppa_srm_oper_config_t srm_oper_config = {
162+
.in.buffer = rotate_cfg->in_buff,
163+
.in.pic_w = w,
164+
.in.pic_h = h,
165+
.in.block_w = w,
166+
.in.block_h = h,
167+
.in.block_offset_x = 0,
168+
.in.block_offset_y = 0,
169+
.in.srm_cm = ppa_ctx->color_type_id,
170+
171+
.out.buffer = ppa_ctx->buffer,
172+
.out.buffer_size = ppa_ctx->buffer_size,
173+
.out.pic_w = out_w,
174+
.out.pic_h = out_h,
175+
.out.block_offset_x = 0,
176+
.out.block_offset_y = 0,
177+
.out.srm_cm = ppa_ctx->color_type_id,
178+
179+
.rotation_angle = rotate_cfg->rotation,
180+
.scale_x = 1.0,
181+
.scale_y = 1.0,
182+
183+
.byte_swap = rotate_cfg->swap_bytes,
184+
185+
.mode = rotate_cfg->ppa_mode,
186+
.user_data = rotate_cfg->user_data,
187+
};
188+
189+
return ppa_do_scale_rotate_mirror(ppa_ctx->srm_handle, &srm_oper_config);
190+
}
191+
192+
#if PPA_LCD_ENABLE_CB
193+
static bool _lcd_ppa_callback(ppa_client_handle_t ppa_client, ppa_event_data_t *event_data, void *user_data)
194+
{
195+
return false;
196+
}
197+
#endif
198+
199+
#endif

0 commit comments

Comments
 (0)