Skip to content

Commit a5634c6

Browse files
committed
feat(multi-touch): Add multi-touch gestures to LVGL port
1 parent b5f2df0 commit a5634c6

File tree

4 files changed

+53
-9
lines changed

4 files changed

+53
-9
lines changed

components/esp_lvgl_port/CHANGELOG.md

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

3+
## 2.7.0
4+
5+
### Features
6+
7+
- Added support for multi-touch gestures.
8+
39
## 2.6.3
410

511
### Fixes

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 (version 9.4 and higher) 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.7.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/src/lvgl9/esp_lvgl_port_touch.c

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include "esp_check.h"
1010
#include "esp_lcd_touch.h"
1111
#include "esp_lvgl_port.h"
12+
#include "esp_timer.h"
13+
#include "sdkconfig.h"
1214

1315
static const char *TAG = "LVGL";
1416

@@ -117,19 +119,39 @@ static void lvgl_port_touchpad_read(lv_indev_t *indev_drv, lv_indev_data_t *data
117119
assert(touch_ctx);
118120
assert(touch_ctx->handle);
119121

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

124125
/* Read data from touch controller into memory */
125-
esp_lcd_touch_read_data(touch_ctx->handle);
126+
ESP_ERROR_CHECK(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+
ESP_ERROR_CHECK(esp_lcd_touch_get_data(touch_ctx->handle, touch_data, &touch_cnt, CONFIG_ESP_LCD_TOUCH_MAX_POINTS));
129130

130-
if (touchpad_pressed && touchpad_cnt > 0) {
131-
data->point.x = touch_ctx->scale.x * touchpad_x[0];
132-
data->point.y = touch_ctx->scale.y * touchpad_y[0];
131+
#if (CONFIG_ESP_LCD_TOUCH_MAX_POINTS > 1 && CONFIG_LV_USE_GESTURE_RECOGNITION)
132+
// Number of touch points which need to be constantly updated inside gesture recognizers
133+
#define GESTURE_TOUCH_POINTS 2
134+
135+
/* Initialize LVGL touch data for each activated touch point */
136+
lv_indev_touch_data_t touches[GESTURE_TOUCH_POINTS] = {0};
137+
138+
for (int i = 0; i < touch_cnt && i < GESTURE_TOUCH_POINTS; i++) {
139+
touches[i].state = LV_INDEV_STATE_PRESSED;
140+
touches[i].point.x = touch_ctx->scale.x * touch_data[i].x;
141+
touches[i].point.y = touch_ctx->scale.y * touch_data[i].y;
142+
touches[i].id = touch_data[i].track_id;
143+
touches[i].timestamp = esp_timer_get_time() / 1000;
144+
}
145+
146+
/* Pass touch data to LVGL gesture recognizers */
147+
lv_indev_gesture_recognizers_update(indev_drv, touches, GESTURE_TOUCH_POINTS);
148+
lv_indev_gesture_recognizers_set_data(indev_drv, data);
149+
150+
#endif
151+
152+
if (touch_cnt > 0) {
153+
data->point.x = touch_ctx->scale.x * touch_data[0].x;
154+
data->point.y = touch_ctx->scale.y * touch_data[0].y;
133155
data->state = LV_INDEV_STATE_PRESSED;
134156
} else {
135157
data->state = LV_INDEV_STATE_RELEASED;

0 commit comments

Comments
 (0)