2026-07-15 16:14:30 +08:00
|
|
|
|
#include "event.h"
|
|
|
|
|
|
#include "app_manager.h"
|
|
|
|
|
|
#include "database.h"
|
|
|
|
|
|
#include "system.h"
|
2026-07-17 09:08:53 +08:00
|
|
|
|
#include "clock.h"
|
|
|
|
|
|
#include "xtell.h"
|
2026-07-28 18:03:20 +08:00
|
|
|
|
#include "../Drivers/adc.h"
|
2026-07-15 16:14:30 +08:00
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 定义事件<E4BA8B><E4BBB6>形队列的<E58897><E79A84>大深度为 8
|
2026-07-15 16:14:30 +08:00
|
|
|
|
#define EVENT_QUEUE_DEPTH 8
|
|
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// <20><>形队列存储数<E582A8><E695B0> (存放在单片机 xdata 拓展 RAM区中)
|
2026-07-28 18:03:20 +08:00
|
|
|
|
static SystemEvent xdata event_queue[EVENT_QUEUE_DEPTH];
|
2026-07-29 10:09:19 +08:00
|
|
|
|
static u8 queue_head = 0; // 队<><E9989F><EFBFBD><EFBFBD>指<EFBFBD><E68C87>
|
|
|
|
|
|
static u8 queue_tail = 0; // 队尾写指<E58699><E68C87>
|
|
|
|
|
|
static u8 queue_count = 0; // 当前队列内有效事件<E4BA8B><E4BBB6>数
|
2026-07-15 16:14:30 +08:00
|
|
|
|
|
2026-07-16 17:52:52 +08:00
|
|
|
|
/**
|
2026-07-29 10:09:19 +08:00
|
|
|
|
* @brief 初<EFBFBD><EFBFBD>化/清空事件队列
|
2026-07-16 17:52:52 +08:00
|
|
|
|
*/
|
2026-07-15 16:14:30 +08:00
|
|
|
|
void EventQueue_Init(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
queue_head = 0;
|
|
|
|
|
|
queue_tail = 0;
|
|
|
|
|
|
queue_count = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 17:52:52 +08:00
|
|
|
|
/**
|
2026-07-29 10:09:19 +08:00
|
|
|
|
* @brief 将普通事件压入队<EFBFBD><EFBFBD>
|
|
|
|
|
|
* @param evt 输入的系统事<EFBFBD><EFBFBD>
|
|
|
|
|
|
* @return bit 1-成功<EFBFBD><EFBFBD>0-失败
|
2026-07-16 17:52:52 +08:00
|
|
|
|
*/
|
2026-07-15 16:14:30 +08:00
|
|
|
|
bit EventQueue_Push(SystemEvent evt)
|
|
|
|
|
|
{
|
2026-07-16 17:52:52 +08:00
|
|
|
|
if (queue_count >= EVENT_QUEUE_DEPTH) return 0; // 队列满,丢弃事件
|
2026-07-29 10:09:19 +08:00
|
|
|
|
EA = 0; // 关闭全局<E585A8><E5B180><EFBFBD><EFBFBD>,保护临界区操作的原子<E58E9F>
|
2026-07-16 17:52:52 +08:00
|
|
|
|
event_queue[queue_tail] = evt; // 存入队尾
|
2026-07-29 10:09:19 +08:00
|
|
|
|
queue_tail = (queue_tail + 1) % EVENT_QUEUE_DEPTH; // 尾指针向后移<E5908E><E7A7BB>,回<EFBC8C><E59B9E>
|
|
|
|
|
|
queue_count++; // 有效计数<E8AEA1><E695B0> 1
|
|
|
|
|
|
EA = 1; // 恢<><E681A2>全<EFBFBD><E585A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 17:52:52 +08:00
|
|
|
|
/**
|
2026-07-29 10:09:19 +08:00
|
|
|
|
* @brief 将高优先<EFBFBD><EFBFBD>/紧<EFBFBD><EFBFBD>事件强行插到队<EFBFBD><EFBFBD>
|
|
|
|
|
|
* @param evt 输入的系统事<EFBFBD><EFBFBD>
|
|
|
|
|
|
* @return bit 1-成功<EFBFBD><EFBFBD>0-失败
|
2026-07-16 17:52:52 +08:00
|
|
|
|
*/
|
2026-07-15 16:14:30 +08:00
|
|
|
|
bit EventQueue_InsertFront(SystemEvent evt)
|
|
|
|
|
|
{
|
2026-07-16 17:52:52 +08:00
|
|
|
|
if (queue_count >= EVENT_QUEUE_DEPTH) return 0; // 队列满,插队失败
|
2026-07-29 10:09:19 +08:00
|
|
|
|
EA = 0; // 屏蔽<E5B18F><E894BD><EFBFBD><EFBFBD>
|
|
|
|
|
|
// 头指针向前移动一位(带回<E5B8A6><E59B9E>防溢出)
|
2026-07-15 16:14:30 +08:00
|
|
|
|
queue_head = (queue_head - 1 + EVENT_QUEUE_DEPTH) % EVENT_QUEUE_DEPTH;
|
2026-07-29 10:09:19 +08:00
|
|
|
|
event_queue[queue_head] = evt; // 存入腾出的队首位<E9A696><E4BD8D>
|
|
|
|
|
|
queue_count++; // 计数<E8AEA1><E695B0> 1
|
|
|
|
|
|
EA = 1; // 恢<><E681A2>中<EFBFBD><E4B8AD>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 17:52:52 +08:00
|
|
|
|
/**
|
2026-07-29 10:09:19 +08:00
|
|
|
|
* @brief 从队首弹出一<EFBFBD><EFBFBD>缓冲事件
|
|
|
|
|
|
* @return SystemEvent 返回弹出的事件<EFBFBD><EFBFBD>若空返回空闲事<EFBFBD><EFBFBD>
|
2026-07-16 17:52:52 +08:00
|
|
|
|
*/
|
2026-07-15 16:14:30 +08:00
|
|
|
|
SystemEvent EventQueue_Pop(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
SystemEvent evt;
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 默<><E9BB98>空事件属<E4BBB6>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
evt.key_event = KEY_EVENT_NONE;
|
2026-07-29 10:09:19 +08:00
|
|
|
|
evt.priority = EVENT_PRIORITY_NORMAL;
|
2026-07-15 16:14:30 +08:00
|
|
|
|
evt.extra_data = 0;
|
|
|
|
|
|
evt.extra_size = 0;
|
2026-07-16 17:52:52 +08:00
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
if (queue_count == 0) return evt; // 队空,直接返回空闲事<E997B2><E4BA8B>
|
2026-07-16 17:52:52 +08:00
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
EA = 0; // 屏蔽<E5B18F><E894BD><EFBFBD><EFBFBD>
|
|
|
|
|
|
evt = event_queue[queue_head]; // 读取队<E58F96><E9989F>数<EFBFBD><E695B0>
|
|
|
|
|
|
queue_head = (queue_head + 1) % EVENT_QUEUE_DEPTH; // 头指针向后移<E5908E><E7A7BB>,回<EFBC8C><E59B9E>
|
|
|
|
|
|
queue_count--; // 有效计数<E8AEA1><E695B0> 1
|
|
|
|
|
|
EA = 1; // 恢<><E681A2>中<EFBFBD><E4B8AD>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
return evt;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 17:52:52 +08:00
|
|
|
|
/**
|
2026-07-29 10:09:19 +08:00
|
|
|
|
* @brief 判断队列<EFBFBD><EFBFBD>否为<EFBFBD><EFBFBD>
|
2026-07-16 17:52:52 +08:00
|
|
|
|
*/
|
2026-07-15 16:14:30 +08:00
|
|
|
|
bit EventQueue_IsEmpty(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
return (queue_count == 0) ? 1 : 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 17:52:52 +08:00
|
|
|
|
/**
|
2026-07-29 10:09:19 +08:00
|
|
|
|
* @brief 判断队列<EFBFBD><EFBFBD>否已<EFBFBD><EFBFBD>
|
2026-07-16 17:52:52 +08:00
|
|
|
|
*/
|
2026-07-15 16:14:30 +08:00
|
|
|
|
bit EventQueue_IsFull(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
return (queue_count >= EVENT_QUEUE_DEPTH) ? 1 : 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 17:52:52 +08:00
|
|
|
|
/**
|
2026-07-29 10:09:19 +08:00
|
|
|
|
* @brief 获取当前队列<EFBFBD><EFBFBD>的事件<EFBFBD><EFBFBD>数
|
2026-07-16 17:52:52 +08:00
|
|
|
|
*/
|
2026-07-15 16:14:30 +08:00
|
|
|
|
u8 EventQueue_GetCount(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
return queue_count;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 17:52:52 +08:00
|
|
|
|
/**
|
2026-07-29 10:09:19 +08:00
|
|
|
|
* @brief 事件分发器核心轮询<EFBFBD><EFBFBD>辑
|
|
|
|
|
|
* @details 逐一处理队列<EFBFBD><EFBFBD>的事件,并根<EFBFBD><EFBFBD>系统当前的运行模式进行拦<EFBFBD><EFBFBD>、跳<EFBFBD><EFBFBD>或下发派发<EFBFBD>
|
2026-07-16 17:52:52 +08:00
|
|
|
|
*/
|
2026-07-15 16:14:30 +08:00
|
|
|
|
void Event_Dispatcher_Loop(void)
|
|
|
|
|
|
{
|
2026-07-29 10:09:19 +08:00
|
|
|
|
SystemEvent evt = EventQueue_Pop(); // 弹出<E5BCB9><E587BA><EFBFBD><EFBFBD>事件
|
2026-07-16 17:52:52 +08:00
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 如果<E5A682><E69E9C>无事发生的空事件,直接<E79BB4><E68EA5><EFBFBD>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
if (evt.key_event == KEY_EVENT_NONE && evt.extra_size == 0) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-07-16 17:52:52 +08:00
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
inactivity_timer = 0; // 捕获到有效事件,清零休眠计时<E8AEA1><E697B6>,重<EFBC8C><E9878D>闲置超时
|
2026-07-16 17:52:52 +08:00
|
|
|
|
|
|
|
|
|
|
// 串口打印调试信息
|
2026-07-17 09:08:53 +08:00
|
|
|
|
XTELL_LOG("[EVENT] key=");
|
|
|
|
|
|
XTELL_LOG_HEX8((u8)evt.key_event);
|
|
|
|
|
|
XTELL_LOG("\r\n");
|
2026-07-15 16:14:30 +08:00
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// SOS 按键紧<E994AE><E7B4A7><EFBFBD><EFBFBD>理:若当前前台不为 SOS 应用,接收到 SOS <20><>动作,立即强行切入到 SOS_APP 并执行求<E8A18C><E6B182>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
if ((evt.key_event == KEY_EVENT_SOS_CLICK || evt.key_event == KEY_EVENT_SOS_LONG) &&
|
|
|
|
|
|
AppManager_GetActiveAppID() != APP_ID_SOS) {
|
|
|
|
|
|
AppManager_StartApp(APP_ID_SOS);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 关机事件处理:捕获到长按关机指令,直接调<E68EA5><E8B083> Power_Off 关断电源
|
2026-07-28 18:03:20 +08:00
|
|
|
|
if (evt.key_event == KEY_EVENT_POWER_OFF) {
|
|
|
|
|
|
Power_Off();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 常<><E5B8B8>事件(如普通的按键点击)直接<E79BB4><E68EA5>传分发给当前<E5BD93><E5898D>于前台活跃的应<E79A84><E5BA94>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
AppManager_DispatchEvent(evt);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 17:52:52 +08:00
|
|
|
|
/**
|
2026-07-29 10:09:19 +08:00
|
|
|
|
* @brief 定时<EFBFBD><EFBFBD> 1 初<EFBFBD><EFBFBD>化,<EFBFBD><EFBFBD>定 1ms <EFBFBD><EFBFBD><EFBFBD><EFBFBD>周期
|
2026-07-16 17:52:52 +08:00
|
|
|
|
*/
|
2026-07-15 16:14:30 +08:00
|
|
|
|
void Timer1_Init(void)
|
|
|
|
|
|
{
|
2026-07-29 10:09:19 +08:00
|
|
|
|
AUXR |= 0x40; // 设定定时<E5AE9A><E697B6> 1 <20><> 1T 模式 (无分频,主<EFBC8C><E4B8BB>直接输<E68EA5><E8BE93>)
|
|
|
|
|
|
TMOD &= 0x0F; // 设置定时<E5AE9A><E697B6> 1 模式寄存<E5AF84><E5AD98>,保留低四位 (定时<E5AE9A><E697B6>0配置)
|
2026-07-15 16:14:30 +08:00
|
|
|
|
{
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 按照系统主<E7BB9F> (MAIN_Fosc) 计算 1ms 对应的重装载<E8A385><E8BDBD>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
u16 reload = (u16)(65536UL - (MAIN_Fosc / 1000UL));
|
2026-07-29 10:09:19 +08:00
|
|
|
|
TL1 = (u8)reload; // 载入<E8BDBD><E585A5> 8 <20><>
|
|
|
|
|
|
TH1 = (u8)(reload >> 8);// 载入<E8BDBD><E585A5> 8 <20><>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
}
|
2026-07-29 10:09:19 +08:00
|
|
|
|
ET1 = 1; // <20><><EFBFBD><EFBFBD>定时<E5AE9A><E697B6> 1 <20><><EFBFBD><EFBFBD>允<EFBFBD>
|
|
|
|
|
|
TR1 = 1; // <20><>动定时器 1 计数
|
|
|
|
|
|
EA = 1; // <20><><EFBFBD><EFBFBD>全局<E585A8><E5B180><EFBFBD><EFBFBD>允<EFBFBD>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 全局按键<E68C89><E994AE>描触发标<E58F91><E6A087>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
volatile bit key_scan_flag = 0;
|
|
|
|
|
|
|
2026-07-16 17:52:52 +08:00
|
|
|
|
/**
|
2026-07-29 10:09:19 +08:00
|
|
|
|
* @brief 定时<EFBFBD><EFBFBD> 1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>服务程序 (<EFBFBD><EFBFBD> 1ms 触发<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
|
|
|
|
|
* @details 承担系统<EFBFBD><EFBFBD>时钟计算,并<EFBFBD><EFBFBD> 10ms <EFBFBD><EFBFBD>位主<EFBFBD><EFBFBD><EFBFBD><EFBFBD>按键<EFBFBD><EFBFBD>描标志,不直接在<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>进<EFBFBD> ADC 多<EFBFBD><EFBFBD>采样<EFBFBD>
|
2026-07-16 17:52:52 +08:00
|
|
|
|
*/
|
2026-07-15 16:14:30 +08:00
|
|
|
|
void Timer1_Isr(void) interrupt 3
|
|
|
|
|
|
{
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 1ms 定时更新<E69BB4><E696B0>时钟
|
2026-07-17 09:08:53 +08:00
|
|
|
|
Clock_IncMS();
|
2026-07-15 16:14:30 +08:00
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 报<><E68AA5>屏幕红边<E7BAA2><E8BEB9>以 100ms 周期<E591A8><E69C9F><EFBFBD><EFBFBD>,进行<E8BF9B><E8A18C>色爆闪指示
|
2026-07-15 16:14:30 +08:00
|
|
|
|
alarm_flash_flag = (ms_tick / 100) % 2;
|
|
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
/* 物理按键定时计数 (<28><> 10ms <20><>位一次标志位) */
|
2026-07-15 16:14:30 +08:00
|
|
|
|
key_scan_timer++;
|
|
|
|
|
|
if (key_scan_timer >= 10) {
|
2026-07-29 10:09:19 +08:00
|
|
|
|
key_scan_timer = 0; // 重置<E9878D><E7BDAE>描分频<E58886><E9A291>数<EFBFBD><E695B0>
|
|
|
|
|
|
key_scan_flag = 1; // 仅在<E4BB85><E59CA8><EFBFBD><EFBFBD>里置起标志位,留待主<E5BE85><E4B8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>执<EFBFBD><E689A7>实际<E5AE9E><E99985>取与消<E4B88E><E6B688>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-29 10:09:19 +08:00
|
|
|
|
* @brief 主循<EFBFBD><EFBFBD>按键<EFBFBD><EFBFBD>描与消抖处理函数
|
|
|
|
|
|
* @details 由主<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 10ms <EFBFBD><EFBFBD>查并执<EFBFBD><EFBFBD>,完全在主线程<EFBFBD><EFBFBD>运<EFBFBD><EFBFBD>,绝无<EFBFBD><EFBFBD><EFBFBD><EFBFBD>重入冲突<EFBFBD><EFBFBD>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Event_KeyScan_Poll(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
SystemEvent evt;
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 读取按键的电平信<E5B9B3><E4BFA1> (KEY_UP, KEY_CONFIRM 为低电平有效)
|
2026-07-28 18:03:20 +08:00
|
|
|
|
u8 raw_up = !KEY_UP;
|
2026-07-29 10:09:19 +08:00
|
|
|
|
u8 raw_down = ADC_IsKeyDown(); // KEY_DOWN 通过 P0.3 ADC 通道判定 (常<> 2.0V, 按下 3.7V)
|
2026-07-28 18:03:20 +08:00
|
|
|
|
u8 raw_confirm = !KEY_CONFIRM;
|
2026-07-29 10:09:19 +08:00
|
|
|
|
u8 raw_sos = !KEY_SOS; // 恢<> SOS 物理按键电平<E794B5><E5B9B3><EFBFBD><EFBFBD>
|
|
|
|
|
|
key_scan_timer = 0; // 重置<E9878D><E7BDAE>描分频<E58886><E9A291>数<EFBFBD><E695B0>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 【SOS 按键电平实时诊断<E8AF8A><E696AD>
|
2026-07-29 10:04:00 +08:00
|
|
|
|
{
|
|
|
|
|
|
static u8 last_raw_sos = 99;
|
|
|
|
|
|
if (raw_sos != last_raw_sos) {
|
|
|
|
|
|
last_raw_sos = raw_sos;
|
|
|
|
|
|
Uart_SendString("[KEY-DIAG] KEY_SOS (P2.6) logic raw: ");
|
|
|
|
|
|
Uart_SendByte(raw_sos ? '1' : '0');
|
|
|
|
|
|
Uart_SendString(", Physical GPIO Pin: ");
|
|
|
|
|
|
Uart_SendByte(KEY_SOS ? '1' : '0');
|
|
|
|
|
|
Uart_SendString("\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 按键调试诊断:若按键 ADC 值有变化或<E58C96><E68896>于高电平,串口输出真实 ADC <20><>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
{
|
|
|
|
|
|
u16 down_val = ADC_ReadFiltered(ADC_CHANNEL_KEY_DOWN);
|
|
|
|
|
|
if (down_val > 2800) {
|
|
|
|
|
|
Uart_SendString("[KEY-DIAG] KEY_DOWN pressed! ADC Raw: ");
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (down_val / 1000) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (down_val / 100) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (down_val / 10) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (down_val % 10)));
|
|
|
|
|
|
Uart_SendString("\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// <20><>测到有任意按<E6848F><E68C89>处于下压状<E58E8B><E78AB6>,立即将无操作闲置休眠计时器归<E599A8><E5BD92>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
if (raw_up || raw_down || raw_confirm || raw_sos) {
|
|
|
|
|
|
inactivity_timer = 0;
|
|
|
|
|
|
} else {
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 如果在常态下(非休眠、非报<E99D9E><E68AA5><EFBFBD><EFBFBD>非紧<E99D9E><E7B4A7>求救),累加闲<E58AA0><E997B2>时间
|
2026-07-15 16:14:30 +08:00
|
|
|
|
if (current_state != STATE_SLEEP && current_state != STATE_ALARM && current_state != STATE_SOS_EMITTED) {
|
|
|
|
|
|
inactivity_timer++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 默<><E9BB98>将派发事件重置为空
|
2026-07-15 16:14:30 +08:00
|
|
|
|
evt.key_event = KEY_EVENT_NONE;
|
2026-07-29 10:09:19 +08:00
|
|
|
|
evt.priority = EVENT_PRIORITY_NORMAL;
|
2026-07-15 16:14:30 +08:00
|
|
|
|
evt.extra_data = 0;
|
|
|
|
|
|
evt.extra_size = 0;
|
|
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 双键组合判定:▲ <20><> and <20><> <20><>同时按下的消抖与生成
|
2026-07-15 16:14:30 +08:00
|
|
|
|
if (raw_up && raw_down) {
|
|
|
|
|
|
comb_hold++;
|
2026-07-29 10:09:19 +08:00
|
|
|
|
if (comb_hold == 300) { // 持续按下<E68C89><E4B88B> 3 <20><> (300 * 10ms = 3s)
|
2026-07-15 16:14:30 +08:00
|
|
|
|
evt.key_event = KEY_EVENT_UP_DOWN_COMB;
|
2026-07-16 17:52:52 +08:00
|
|
|
|
EventQueue_Push(evt); // 压入队列
|
2026-07-15 16:14:30 +08:00
|
|
|
|
}
|
2026-07-29 10:09:19 +08:00
|
|
|
|
key_up_hold = 0; // 清零单个按键计数,防止双击事件干<E4BBB6><E5B9B2>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
key_down_hold = 0;
|
|
|
|
|
|
} else {
|
2026-07-29 10:09:19 +08:00
|
|
|
|
comb_hold = 0; // 组合<E7BB84><E59088>松开归零
|
2026-07-15 16:14:30 +08:00
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// <20><> (KEY_UP) 按键状<E994AE><E78AB6>机
|
2026-07-15 16:14:30 +08:00
|
|
|
|
if (raw_up) {
|
|
|
|
|
|
key_up_hold++;
|
2026-07-16 17:52:52 +08:00
|
|
|
|
if (key_up_hold == 300) { // 达到 3 秒判定为长按
|
2026-07-15 16:14:30 +08:00
|
|
|
|
evt.key_event = KEY_EVENT_UP_LONG;
|
|
|
|
|
|
EventQueue_Push(evt);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 如果松开时按下<E68C89><E4B88B>数在消抖阈值(20ms)至长按阈<E68C89><E99888>(3s)之间,则判定为<E5AE9A><E4B8BA>次短<E6ACA1><E79FAD>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
if (key_up_hold >= 2 && key_up_hold < 300) {
|
|
|
|
|
|
evt.key_event = KEY_EVENT_UP_CLICK;
|
|
|
|
|
|
EventQueue_Push(evt);
|
|
|
|
|
|
}
|
2026-07-16 17:52:52 +08:00
|
|
|
|
key_up_hold = 0; // 释放归零
|
2026-07-15 16:14:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// <20><> (KEY_DOWN / <20><>关机) 按键状<E994AE><E78AB6>机
|
2026-07-15 16:14:30 +08:00
|
|
|
|
if (raw_down) {
|
|
|
|
|
|
key_down_hold++;
|
2026-07-29 10:09:19 +08:00
|
|
|
|
if (key_down_hold == 100) { // 长按 1 <20><> (100 * 10ms = 1000ms = 1s) 触发关机事件
|
2026-07-28 18:03:20 +08:00
|
|
|
|
evt.key_event = KEY_EVENT_POWER_OFF;
|
2026-07-15 16:14:30 +08:00
|
|
|
|
EventQueue_Push(evt);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// 如果松开时按下时长在 20ms <20><> 1s 之间,触发短按下<E68C89><E4B88B>/选择事件
|
2026-07-28 18:03:20 +08:00
|
|
|
|
if (key_down_hold >= 2 && key_down_hold < 100) {
|
2026-07-15 16:14:30 +08:00
|
|
|
|
evt.key_event = KEY_EVENT_DOWN_CLICK;
|
|
|
|
|
|
EventQueue_Push(evt);
|
|
|
|
|
|
}
|
2026-07-16 17:52:52 +08:00
|
|
|
|
key_down_hold = 0; // 释放归零
|
2026-07-15 16:14:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// <20><> (KEY_CONFIRM) <20><>认按<E8AEA4><E68C89>状<EFBFBD><E78AB6>机
|
2026-07-15 16:14:30 +08:00
|
|
|
|
if (raw_confirm) {
|
|
|
|
|
|
key_confirm_hold++;
|
2026-07-29 10:09:19 +08:00
|
|
|
|
if (key_confirm_hold == 300) { // 长按 3 秒打<E7A792><E68993>主菜<E4B8BB><E88F9C>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
evt.key_event = KEY_EVENT_CONFIRM_LONG;
|
|
|
|
|
|
EventQueue_Push(evt);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (key_confirm_hold >= 2 && key_confirm_hold < 300) {
|
|
|
|
|
|
evt.key_event = KEY_EVENT_CONFIRM_CLICK;
|
|
|
|
|
|
EventQueue_Push(evt);
|
|
|
|
|
|
}
|
2026-07-16 17:52:52 +08:00
|
|
|
|
key_confirm_hold = 0; // 释放归零
|
2026-07-15 16:14:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-29 10:09:19 +08:00
|
|
|
|
// SOS <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȱ<EFBFBD><C8B0><EFBFBD>״̬<D7B4><CCAC> (<28>ѽ<EFBFBD><D1BD><EFBFBD>)
|
2026-07-15 16:14:30 +08:00
|
|
|
|
if (raw_sos) {
|
|
|
|
|
|
key_sos_hold++;
|
2026-07-29 10:09:19 +08:00
|
|
|
|
if (key_sos_hold == 300) { // <20><><EFBFBD><EFBFBD> 3 <20>룬<EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
evt.key_event = KEY_EVENT_SOS_LONG;
|
2026-07-29 10:09:19 +08:00
|
|
|
|
evt.priority = EVENT_PRIORITY_URGENT;
|
2026-07-15 16:14:30 +08:00
|
|
|
|
EventQueue_InsertFront(evt);
|
2026-07-29 10:09:19 +08:00
|
|
|
|
Uart_SendString("[KEY-DIAG] SOS Long Press Dispatched!\r\n");
|
2026-07-15 16:14:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2026-07-29 10:09:19 +08:00
|
|
|
|
if (key_sos_hold >= 2 && key_sos_hold < 300) { // <20>̰<EFBFBD><CCB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
evt.key_event = KEY_EVENT_SOS_CLICK;
|
2026-07-29 10:09:19 +08:00
|
|
|
|
evt.priority = EVENT_PRIORITY_URGENT;
|
2026-07-15 16:14:30 +08:00
|
|
|
|
EventQueue_InsertFront(evt);
|
2026-07-29 10:09:19 +08:00
|
|
|
|
Uart_SendString("[KEY-DIAG] SOS Click Dispatched!\r\n");
|
2026-07-15 16:14:30 +08:00
|
|
|
|
}
|
2026-07-29 10:09:19 +08:00
|
|
|
|
key_sos_hold = 0; // <20>ͷŹ<CDB7><C5B9><EFBFBD>
|
2026-07-15 16:14:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|