From fd390ea34fc72203cbe2a72ae9f4bba7ebc95806 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Wed, 21 Oct 2026 20:45:37 +0200 Subject: [PATCH] LVGL touch more responsive (#25172) --- CHANGELOG.md | 1 + tasmota/displaydesc/M5stack_core2_display.ini | 9 +++--- tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino | 3 +- tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino | 32 ++++++++++++++++--- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bf67761c..311c259c3 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file. - ESP32 `PWMFrequency` < 8 result in WDT exception after restart (#25155) - LVGL Panel extension crash (#25165) - LVGL Panel improved click handling +- LVGL touch more responsive ### Removed diff --git a/tasmota/displaydesc/M5stack_core2_display.ini b/tasmota/displaydesc/M5stack_core2_display.ini index b0b0b82d2..ec5d3e1c8 100644 --- a/tasmota/displaydesc/M5stack_core2_display.ini +++ b/tasmota/displaydesc/M5stack_core2_display.ini @@ -40,13 +40,14 @@ CP 02 RTF RT :UTT -RDM 00 16 -MV 2 1 +RD 02 +CP 01 RT :UTX -MV 3 2 +RDM 03 4 +MV 0 2 RT :UTY -MV 5 2 +MV 2 2 RT # diff --git a/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino b/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino index 2acd5c716..e245c8afe 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_54_lvgl.ino @@ -438,13 +438,14 @@ static void lv_tick_handler(void) { lv_tick_inc(lv_tick_interval_ms); } // TOUCHSCREEN STUFF ------------------------------------------------------- uint32_t Touch_Status(int32_t sel); +bool Touch_PressedLatched(void); //typedef void (*lv_indev_read_cb_t)(lv_indev_t * indev, lv_indev_data_t * data); void lvgl_touchscreen_read(lv_indev_t *indev_drv, lv_indev_data_t *data); void lvgl_touchscreen_read(lv_indev_t *indev_drv, lv_indev_data_t *data) { data->point.x = Touch_Status(1); // Last-pressed coordinates data->point.y = Touch_Status(2); - data->state = Touch_Status(0) ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; + data->state = Touch_PressedLatched() ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; // don't lose a tap shorter than the read period data->continue_reading = false; /*No buffering now so no more data read*/ // keep data for TS calibration lv_ts_calibration.state = data->state; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino index f16c4a0e0..747de9343 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino @@ -64,9 +64,15 @@ typedef struct TSGlobal_t { bool touched; bool external_ts; bool ext_pressed; // press injected by display.touch_update(), ex: LVGL Panel in the browser + bool press_latch; // new press not yet reported by Touch_PressedLatched() uint32_t ext_last; // millis() of the last injected update } TSGlobal_t; +// Touch controller polling period. Short taps last 15-30 ms, so 50 ms missed many of them +#ifndef TOUCH_POLL_MS +#define TOUCH_POLL_MS 20 +#endif + // An injected press overrides the touch controller until it is released or not refreshed for this time #ifndef TOUCH_EXT_TIMEOUT_MS #define TOUCH_EXT_TIMEOUT_MS 1000 @@ -90,6 +96,7 @@ VButton *buttons[MAX_TOUCH_BUTTONS]; #endif void Touch_SetStatus(uint8_t touches, uint16_t raw_x, uint16_t raw_y, uint8_t gesture, bool force_no_convert) { + bool was_touched = TSGlobal.touched; TSGlobal.external_ts = true; TSGlobal.gesture = gesture; TSGlobal.touches = touches; @@ -100,9 +107,19 @@ void Touch_SetStatus(uint8_t touches, uint16_t raw_x, uint16_t raw_y, uint8_t ge TS_RotConvert(&TSGlobal.touch_xp, &TSGlobal.touch_yp); } TSGlobal.ext_pressed = TSGlobal.touched; + if (TSGlobal.touched && !was_touched) { TSGlobal.press_latch = true; } TSGlobal.ext_last = millis(); } +// For LVGL: true if pressed now, or if a press started since the last call. +// LVGL may not read the input between two polls while it renders, and would lose a short tap. +// Only the start of a press is latched, so a release is not delayed +bool Touch_PressedLatched(void) { + bool pressed = TSGlobal.touched || TSGlobal.press_latch; + TSGlobal.press_latch = false; + return pressed; +} + // return true if succesful, false if not configured bool Touch_GetStatus(uint8_t* touches, uint16_t* x, uint16_t* y, uint8_t* gesture, uint16_t* raw_x, uint16_t* raw_y) { @@ -396,7 +413,7 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) { static bool was_touched = false; // flag used to log the data sent when the screen was just released // An injected press (display.touch_update) is kept until released, otherwise - // polling the controller would release it within 50 ms + // polling the controller would release it at the next poll if (TSGlobal.ext_pressed) { if (!TimeReached(TSGlobal.ext_last + TOUCH_EXT_TIMEOUT_MS)) { return; } TSGlobal.ext_pressed = false; // no refresh from the source, release it @@ -456,6 +473,7 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) { #endif // USE_XPT2046 if (TSGlobal.touched) { + if (!was_touched) { TSGlobal.press_latch = true; } was_touched = true; TSGlobal.touch_xp = TSGlobal.raw_touch_xp; TSGlobal.touch_yp = TSGlobal.raw_touch_yp; @@ -614,10 +632,13 @@ bool Xdrv55(uint32_t function) { switch (function) { case FUNC_INIT: break; - case FUNC_EVERY_50_MSECOND: - // 50 ms matches LVGL input reads and Berry touch drivers; 100 ms felt laggy + case FUNC_LOOP: if (CST816S_found || FT5206_found || XPT2046_found || GT911_found || utouch_found || SRES_found) { - Touch_Check(TS_RotConvert); + static uint32_t touch_next_poll = 0; + if (TimeReached(touch_next_poll)) { + SetNextTimeInterval(touch_next_poll, TOUCH_POLL_MS); + Touch_Check(TS_RotConvert); + } } break; case FUNC_ACTIVE: @@ -633,5 +654,8 @@ bool Xdrv55(uint32_t function) { uint32_t Touch_Status(int32_t sel) { return 0; } +bool Touch_PressedLatched(void) { + return false; +} #endif // #if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_TOUCH_BUTTONS)