#include "includes.h" /* ?????????????????????????????? */ typedef enum { TOUCH_IDLE, TOUCH_PRESS_WAIT_STABLE, TOUCH_PRESS_STABLE, TOUCH_SLIDING } touch_state_t; #define TOUCH_STABLE_TIME 8 #define TOUCH_SLIDE_THRESH 12 #define TOUCH_SLIDE_STEP 5 #define TOUCH_LONG_PRESS_TIME 800 #define TOUCH_REPEAT_INTERVAL 120 static touch_state_t touch_state = TOUCH_IDLE; static uint16_t down_x = 0; static uint16_t down_y = 0; static uint32_t touch_tick = 0; static uint32_t repeat_tick = 0; static uint8_t long_press_fired = 0; static uint8_t click_sent = 0; static uint16_t last_slide_x = 0; static uint16_t last_slide_y = 0; static uint32_t suppress_until = 0; static inline uint16_t abs_diff(int16_t a, int16_t b) { int16_t d = a - b; return (d < 0) ? (uint16_t)(-d) : (uint16_t)d; } void app_touch_reset(void) { touch_state = TOUCH_IDLE; down_x = down_y = 0; touch_tick = repeat_tick = 0; long_press_fired = 0; click_sent = 0; last_slide_x = last_slide_y = 0; } void app_touch_suppress(uint32_t ms) { uint32_t now = rt_tick_get(); uint32_t ticks = (ms * RT_TICK_PER_SECOND + 999U) / 1000U; suppress_until = now + ticks; app_touch_reset(); } app_touch_result_t app_touch_process(uint16_t x, uint16_t y, uint8_t pressed) { app_touch_result_t r; r.gesture = GESTURE_NONE; r.x = x; r.y = y; r.down_x = down_x; r.down_y = down_y; uint32_t now = rt_tick_get(); /* 切页抑制窗口内丢弃按下,避免误触底栏设置 */ if ((int32_t)(now - suppress_until) < 0) { if (!pressed) { app_touch_reset(); } return r; } if (!pressed) { if (!long_press_fired && !click_sent && (touch_state == TOUCH_PRESS_WAIT_STABLE || touch_state == TOUCH_PRESS_STABLE || touch_state == TOUCH_SLIDING)) { /* 导航页:抬起时发一次点击(坐标更稳,避免按下瞬间误触底栏) */ if (CurrUIProcress != UI_Mixer_Process) { r.gesture = GESTURE_RELEASE; r.x = down_x; r.y = down_y; LOG_TPI("release x=%u y=%u -> MSG", (unsigned)down_x, (unsigned)down_y); MainTask_Sendmsg(MSG_ID_TOUCH, 1, down_x, down_y); } } touch_state = TOUCH_IDLE; down_x = down_y = 0; last_slide_x = last_slide_y = 0; touch_tick = repeat_tick = 0; long_press_fired = 0; click_sent = 0; return r; } switch (touch_state) { case TOUCH_IDLE: down_x = x; down_y = y; touch_tick = now; long_press_fired = 0; click_sent = 0; repeat_tick = 0; touch_state = TOUCH_PRESS_WAIT_STABLE; /* Mixer 推子:按下即报;其它页等抬起再报,防止进页后残留按下误触设置 */ if (CurrUIProcress == UI_Mixer_Process) { click_sent = 1; LOG_TPI("press x=%u y=%u -> MSG", (unsigned)down_x, (unsigned)down_y); MainTask_Sendmsg(MSG_ID_TOUCH, 1, down_x, down_y); } else { LOG_TPI("press down x=%u y=%u (wait release)", (unsigned)down_x, (unsigned)down_y); } break; case TOUCH_PRESS_WAIT_STABLE: if ((now - touch_tick) >= TOUCH_STABLE_TIME) { if (abs_diff(x, down_x) < 24 && abs_diff(y, down_y) < 24) { /* 用稳定后的坐标替换首采样噪声 */ down_x = x; down_y = y; touch_state = TOUCH_PRESS_STABLE; } else { down_x = x; down_y = y; touch_tick = now; } } break; case TOUCH_PRESS_STABLE: if (!long_press_fired && (now - touch_tick) >= TOUCH_LONG_PRESS_TIME) { long_press_fired = 1; repeat_tick = now; r.gesture = GESTURE_LONG_PRESS; LOG_TPI("long_press x=%u y=%u", (unsigned)down_x, (unsigned)down_y); MainTask_Sendmsg(MSG_ID_TOUCH_LONG_REPEAT, 1, down_x, down_y); return r; } if (long_press_fired && (now - repeat_tick) >= TOUCH_REPEAT_INTERVAL) { repeat_tick = now; r.gesture = GESTURE_REPEAT; MainTask_Sendmsg(MSG_ID_TOUCH_LONG_REPEAT, 1, down_x, down_y); return r; } if (abs_diff(x, down_x) >= TOUCH_SLIDE_THRESH || abs_diff(y, down_y) >= TOUCH_SLIDE_THRESH) { touch_state = TOUCH_SLIDING; last_slide_x = x; last_slide_y = y; } break; case TOUCH_SLIDING: /* 仅 Mixer 需要拖动连续坐标;其它页拖动会误触底栏设置 Tab */ if (CurrUIProcress == UI_Mixer_Process && (abs_diff(x, last_slide_x) >= TOUCH_SLIDE_STEP || abs_diff(y, last_slide_y) >= TOUCH_SLIDE_STEP)) { r.gesture = GESTURE_DRAG; r.down_x = last_slide_x; r.down_y = last_slide_y; LOG_TPI("drag x=%u y=%u", (unsigned)x, (unsigned)y); MainTask_Sendmsg(MSG_ID_TOUCH, 1, x, y); last_slide_x = x; last_slide_y = y; return r; } break; default: touch_state = TOUCH_IDLE; break; } return r; }