164 lines
5.3 KiB
C
164 lines
5.3 KiB
C
#include "includes.h"
|
||
|
||
/* ============================================================================
|
||
* app_touch 实现
|
||
*
|
||
* 状态机(与原 Touch_Process 一致):
|
||
* IDLE → PRESS_WAIT_STABLE → PRESS_STABLE → SLIDING
|
||
*
|
||
* 时序参数:
|
||
* 稳定判定 20ms (TOUCH_STABLE_TIME)
|
||
* 滑动阈值 10px (TOUCH_SLIDE_THRESH)
|
||
* 滑动步进 5px (TOUCH_SLIDE_STEP)
|
||
* 长按触发 1000ms (TOUCH_LONG_PRESS_TIME)
|
||
* 长按重复 120ms (TOUCH_REPEAT_INTERVAL)
|
||
* ==========================================================================*/
|
||
|
||
/* ==================== 状态机枚举 ==================== */
|
||
typedef enum {
|
||
TOUCH_IDLE, /* 空闲 */
|
||
TOUCH_PRESS_WAIT_STABLE, /* 按下,等待稳定判定 */
|
||
TOUCH_PRESS_STABLE, /* 稳定按下(可长按) */
|
||
TOUCH_SLIDING /* 滑动中 */
|
||
} touch_state_t;
|
||
|
||
/* ==================== 时序参数 ==================== */
|
||
#define TOUCH_STABLE_TIME 20 /* 按下稳定判定时间 ms */
|
||
#define TOUCH_SLIDE_THRESH 10 /* 进入滑动的最小位移 px */
|
||
#define TOUCH_SLIDE_STEP 5 /* 滑动事件最小步进 px */
|
||
#define TOUCH_LONG_PRESS_TIME 1000 /* 长按触发 ms */
|
||
#define TOUCH_REPEAT_INTERVAL 120 /* 长按重复间隔 ms */
|
||
|
||
/* ==================== 状态变量 ==================== */
|
||
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 uint16_t last_slide_x = 0;
|
||
static uint16_t last_slide_y = 0;
|
||
|
||
/* 取绝对值(避免引入 math.h) */
|
||
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;
|
||
last_slide_x = last_slide_y = 0;
|
||
}
|
||
|
||
/* ==================== 手势识别 ==================== */
|
||
|
||
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 (!pressed) {
|
||
/* 若曾稳定按下且未触发长按 → 释放(可当作 TAP) */
|
||
if (touch_state == TOUCH_PRESS_STABLE && !long_press_fired) {
|
||
r.gesture = GESTURE_RELEASE;
|
||
r.x = down_x; r.y = 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;
|
||
return r;
|
||
}
|
||
|
||
/* ---------- 按下处理 ---------- */
|
||
switch (touch_state)
|
||
{
|
||
case TOUCH_IDLE:
|
||
down_x = x;
|
||
down_y = y;
|
||
touch_tick = now;
|
||
long_press_fired = 0;
|
||
repeat_tick = 0;
|
||
touch_state = TOUCH_PRESS_WAIT_STABLE;
|
||
break;
|
||
|
||
case TOUCH_PRESS_WAIT_STABLE:
|
||
if ((now - touch_tick) >= TOUCH_STABLE_TIME) {
|
||
/* 位移小 → 进入稳定 */
|
||
if (abs_diff(x, down_x) < 8 && abs_diff(y, down_y) < 8) {
|
||
touch_state = TOUCH_PRESS_STABLE;
|
||
last_slide_x = down_x;
|
||
last_slide_y = down_y;
|
||
touch_tick = now;
|
||
MainTask_Sendmsg(MSG_ID_TOUCH, 1, down_x, down_y);
|
||
} else {
|
||
/* 位移大 → 视为误触,回到空闲 */
|
||
touch_state = TOUCH_IDLE;
|
||
}
|
||
}
|
||
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;
|
||
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:
|
||
{
|
||
/* 位移超过步进 → 产生拖动事件 */
|
||
if (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;
|
||
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; /* 无手势 */
|
||
}
|