Skip to content

Commit 54158eb

Browse files
committed
feat(multi-touch): Multi-touch gesture detection in LVGL port
1 parent f63a083 commit 54158eb

File tree

4 files changed

+54
-5
lines changed

4 files changed

+54
-5
lines changed

components/esp_lvgl_port/Kconfig

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,10 @@ menu "ESP LVGL PORT"
66
default n
77
help
88
Enables using PPA for screen rotation.
9-
9+
config LVGL_PORT_ENABLE_GESTURES
10+
depends on LV_USE_GESTURE_RECOGNITION
11+
bool "Enable gesture detection"
12+
default n
13+
help
14+
Enables gesture detection.
1015
endmenu

components/esp_lvgl_port/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,22 @@ Display rotation can be changed at runtime.
275275
> [!NOTE]
276276
> 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.
277277
278+
### Detecting gestures
279+
280+
LVGL includes support for software detection of multi-touch gestures.
281+
This detection can be enabled by setting the `LVGL_PORT_ENABLE_GESTURES` config and having `ESP_LCD_TOUCH_MAX_POINTS` > 1.
282+
Example usage of the gesture callback can be found in LVGL [documentation](https://docs.lvgl.io/master/details/main-modules/indev/gestures.html).
283+
284+
The LVGL port task is responsible for passing the touch coordinates to the gesture recognizers and calling the registered callback when a gesture is detected.
285+
286+
To correctly distinguish two finger swipe from rotation, we recommend changing the default value (which is 0) for the rotation threshold.
287+
From our testing we recommend starting with 0.15 radians.
288+
289+
```
290+
lv_indev_t indev = bsp_display_get_input_dev();
291+
lv_indev_set_rotation_rad_threshold(indev, 0.15f);
292+
```
293+
278294
### Using PSRAM canvas
279295

280296
If the SRAM is insufficient, you can use the PSRAM as a canvas and use a small trans_buffer to carry it, this makes drawing more efficient.

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.6.3"
1+
version: "2.6.4"
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/src/lvgl9/esp_lvgl_port_touch.c

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "esp_check.h"
1010
#include "esp_lcd_touch.h"
1111
#include "esp_lvgl_port.h"
12+
#include "esp_timer.h"
1213

1314
static const char *TAG = "LVGL";
1415

@@ -117,15 +118,42 @@ static void lvgl_port_touchpad_read(lv_indev_t *indev_drv, lv_indev_data_t *data
117118
assert(touch_ctx);
118119
assert(touch_ctx->handle);
119120

120-
uint16_t touchpad_x[1] = {0};
121-
uint16_t touchpad_y[1] = {0};
121+
uint16_t touchpad_x[CONFIG_ESP_LCD_TOUCH_MAX_POINTS] = {0};
122+
uint16_t touchpad_y[CONFIG_ESP_LCD_TOUCH_MAX_POINTS] = {0};
122123
uint8_t touchpad_cnt = 0;
123124

124125
/* Read data from touch controller into memory */
125126
esp_lcd_touch_read_data(touch_ctx->handle);
126127

127128
/* Read data from touch controller */
128-
bool touchpad_pressed = esp_lcd_touch_get_coordinates(touch_ctx->handle, touchpad_x, touchpad_y, NULL, &touchpad_cnt, 1);
129+
bool touchpad_pressed = esp_lcd_touch_get_coordinates(touch_ctx->handle, touchpad_x, touchpad_y, NULL, &touchpad_cnt, CONFIG_ESP_LCD_TOUCH_MAX_POINTS);
130+
131+
#if (CONFIG_ESP_LCD_TOUCH_MAX_POINTS > 1 && CONFIG_LVGL_PORT_ENABLE_GESTURES)
132+
// Number of touch points which need to be constantly updated inside gesture recognizers
133+
#define GESTURE_TOUCH_POINTS 2
134+
135+
uint8_t touchpad_track_id[CONFIG_ESP_LCD_TOUCH_MAX_POINTS] = {0};
136+
137+
/* Read track IDs for TODO number of touch points*/
138+
esp_err_t err = esp_lcd_touch_get_track_id(touch_ctx->handle, touchpad_track_id, GESTURE_TOUCH_POINTS);
139+
140+
/* Initialize LVGL touch data for each activated touch point */
141+
/* static */ lv_indev_touch_data_t touches[CONFIG_ESP_LCD_TOUCH_MAX_POINTS] = {0};
142+
if (err != ESP_ERR_NOT_SUPPORTED) {
143+
for (int i = 0; i < touchpad_cnt; i++) {
144+
touches[i].state = LV_INDEV_STATE_PRESSED;
145+
touches[i].point.x = touchpad_x[i];
146+
touches[i].point.y = touchpad_y[i];
147+
touches[i].id = touchpad_track_id[i];
148+
touches[i].timestamp = esp_timer_get_time() / 1000;
149+
}
150+
}
151+
152+
/* Pass touch data to LVGL gesture recognizers */
153+
lv_indev_gesture_recognizers_update(indev_drv, touches, GESTURE_TOUCH_POINTS);
154+
lv_indev_gesture_recognizers_set_data(indev_drv, data);
155+
156+
#endif
129157

130158
if (touchpad_pressed && touchpad_cnt > 0) {
131159
data->point.x = touch_ctx->scale.x * touchpad_x[0];

0 commit comments

Comments
 (0)