K1Guitar/APP/app_touch.c

164 lines
5.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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; /* 无手势 */
}