321 lines
11 KiB
C
321 lines
11 KiB
C
#include "event.h"
|
||
#include "app_manager.h"
|
||
#include "database.h"
|
||
#include "system.h"
|
||
#include "clock.h"
|
||
#include "xtell.h"
|
||
#include "../Drivers/adc.h"
|
||
|
||
// 定义事件çŽå½¢é˜Ÿåˆ—çš„æœå¤§æ·±åº¦ä¸º 8
|
||
#define EVENT_QUEUE_DEPTH 8
|
||
|
||
// çŽå½¢é˜Ÿåˆ—å˜å‚¨æ•°ç» (å˜æ”¾åœ¨å<C2A8>•片机 xdata 拓展 RAM区ä¸)
|
||
static SystemEvent xdata event_queue[EVENT_QUEUE_DEPTH];
|
||
static u8 queue_head = 0; // 队é–è»æŒ‡é’
|
||
static u8 queue_tail = 0; // 队尾写指é’
|
||
static u8 queue_count = 0; // 当å‰<C3A5>é˜Ÿåˆ—å†…æœ‰æ•ˆäº‹ä»¶æ»æ•°
|
||
|
||
/**
|
||
* @brief åˆ<C3A5>å‹åŒ–/清空事件队列
|
||
*/
|
||
void EventQueue_Init(void)
|
||
{
|
||
queue_head = 0;
|
||
queue_tail = 0;
|
||
queue_count = 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 将普通事件压入队å°
|
||
* @param evt 输入的系统事ä»
|
||
* @return bit 1-æˆ<C3A6>功ï¼0-失败
|
||
*/
|
||
bit EventQueue_Push(SystemEvent evt)
|
||
{
|
||
if (queue_count >= EVENT_QUEUE_DEPTH) return 0; // 队列满,丢弃事件
|
||
EA = 0; // å…³é—免局䏿–,ä¿<C3A4>护临界区æ“<C3A6>作的原å<C3A5>æ
|
||
event_queue[queue_tail] = evt; // å˜å…¥é˜Ÿå°¾
|
||
queue_tail = (queue_tail + 1) % EVENT_QUEUE_DEPTH; // 尾指针å<CB86>‘å<E28098>Žç§»åŠï¼Œå›žçŽ
|
||
queue_count++; // æœ‰æ•ˆè®¡æ•°åŠ 1
|
||
EA = 1; // æ<>¢å<C2A2>å…¨å±ä¸æ–
|
||
return 1;
|
||
}
|
||
|
||
/**
|
||
* @brief 将高优先çº/ç´§æ¥äº‹ä»¶å¼ºè¡Œæ<C592>’到队é¦
|
||
* @param evt 输入的系统事ä»
|
||
* @return bit 1-æˆ<C3A6>功ï¼0-失败
|
||
*/
|
||
bit EventQueue_InsertFront(SystemEvent evt)
|
||
{
|
||
if (queue_count >= EVENT_QUEUE_DEPTH) return 0; // 队列满,æ<C592>’队失败
|
||
EA = 0; // å±<C3A5>è”½ä¸æ–
|
||
// 头指针å<CB86>‘å‰<C3A5>移动一ä½<C3A4>(带回çŽé˜²æº¢å‡ºï¼‰
|
||
queue_head = (queue_head - 1 + EVENT_QUEUE_DEPTH) % EVENT_QUEUE_DEPTH;
|
||
event_queue[queue_head] = evt; // å˜å…¥è…¾å‡ºçš„队首ä½<C3A4>ç½
|
||
queue_count++; // è®¡æ•°åŠ 1
|
||
EA = 1; // æ<>¢å<C2A2>䏿–
|
||
return 1;
|
||
}
|
||
|
||
/**
|
||
* @brief 从队首弹出一ä¸ç¼“冲事件
|
||
* @return SystemEvent 返回弹出的事件ã‚若空返回空闲事ä»
|
||
*/
|
||
SystemEvent EventQueue_Pop(void)
|
||
{
|
||
SystemEvent evt;
|
||
// 默è¤ç©ºäº‹ä»¶å±žæ
|
||
evt.key_event = KEY_EVENT_NONE;
|
||
evt.priority = EVENT_PRIORITY_NORMAL;
|
||
evt.extra_data = 0;
|
||
evt.extra_size = 0;
|
||
|
||
if (queue_count == 0) return evt; // 队空,直接返回空闲事ä»
|
||
|
||
EA = 0; // å±<C3A5>è”½ä¸æ–
|
||
evt = event_queue[queue_head]; // 读å<C2BB>–é˜Ÿé–æ•°æ<C2B0>
|
||
queue_head = (queue_head + 1) % EVENT_QUEUE_DEPTH; // 头指针å<CB86>‘å<E28098>Žç§»åŠï¼Œå›žçŽ
|
||
queue_count--; // æœ‰æ•ˆè®¡æ•°å‡ 1
|
||
EA = 1; // æ<>¢å<C2A2>䏿–
|
||
return evt;
|
||
}
|
||
|
||
/**
|
||
* @brief 判æ–队列æ˜å<CB9C>¦ä¸ºç©
|
||
*/
|
||
bit EventQueue_IsEmpty(void)
|
||
{
|
||
return (queue_count == 0) ? 1 : 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 判æ–队列æ˜å<CB9C>¦å·²æ»
|
||
*/
|
||
bit EventQueue_IsFull(void)
|
||
{
|
||
return (queue_count >= EVENT_QUEUE_DEPTH) ? 1 : 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 获å<C2B7>–当å‰<C3A5>队列ä¸çš„äº‹ä»¶æ»æ•°
|
||
*/
|
||
u8 EventQueue_GetCount(void)
|
||
{
|
||
return queue_count;
|
||
}
|
||
|
||
/**
|
||
* @brief 事件分å<E280A0>‘å™¨æ ¸å¿ƒè½®è¯¢é»è¾‘
|
||
* @details é€<C3A9>一处ç<E2809E>†é˜Ÿåˆ—ä¸çš„äº‹ä»¶ï¼Œå¹¶æ ¹æ<C2B9>系统当å‰<C3A5>çš„è¿<C3A8>行模å¼<C3A5>进行拦æˆã€<C3A3>è·³è½æˆ–下å<E280B9>‘æ´¾å<C2BE>‘ã
|
||
*/
|
||
void Event_Dispatcher_Loop(void)
|
||
{
|
||
SystemEvent evt = EventQueue_Pop(); // 弹出ä¸ä¸äº‹ä»¶
|
||
|
||
// å¦‚æžœæ˜æ— 事å<E280B9>‘生的空事件,直接éå‡
|
||
if (evt.key_event == KEY_EVENT_NONE && evt.extra_size == 0) {
|
||
return;
|
||
}
|
||
|
||
inactivity_timer = 0; // æ<>•èŽ·åˆ°æœ‰æ•ˆäº‹ä»¶ï¼Œæ¸…é›¶ä¼‘çœ è®¡æ—¶å™ï¼Œé‡<C3A9>ç½é—²ç½®è¶…æ—¶
|
||
|
||
// 串å<C2B2>£æ‰“å<E2809C>°è°ƒè¯•ä¿¡æ<C2A1>¯
|
||
XTELL_LOG("[EVENT] key=");
|
||
XTELL_LOG_HEX8((u8)evt.key_event);
|
||
XTELL_LOG("\r\n");
|
||
|
||
// SOS 按键紧æ¥å„ç<E2809E>†ï¼šè‹¥å½“å‰<C3A5>å‰<C3A5>å<EFBFBD>°ä¸<C3A4>为 SOS 应用,接收到 SOS é”动作,立å<E280B9>³å¼ºè¡Œåˆ‡å…¥åˆ° SOS_APP 并执行求æ•
|
||
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;
|
||
}
|
||
|
||
// 关机事件处ç<E2809E>†ï¼šæ<C5A1>•èŽ·åˆ°é•¿æŒ‰å…³æœºæŒ‡ä»¤ï¼Œç›´æŽ¥è°ƒç” Power_Off å…³æ–电æº<C3A6>
|
||
if (evt.key_event == KEY_EVENT_POWER_OFF) {
|
||
Power_Off();
|
||
return;
|
||
}
|
||
|
||
// 常è„事件(如普通的按键点击)直接é<C2A5>ä¼ åˆ†å<E280A0>‘给当å‰<C3A5>å„于å‰<C3A5>å<EFBFBD>°æ´»è·ƒçš„应ç”
|
||
AppManager_DispatchEvent(evt);
|
||
}
|
||
|
||
/**
|
||
* @brief å®šæ—¶å™ 1 åˆ<C3A5>å‹åŒ–,è¾å®š 1ms 䏿–周期
|
||
*/
|
||
void Timer1_Init(void)
|
||
{
|
||
AUXR |= 0x40; // è®¾å®šå®šæ—¶å™ 1 ä¸ 1T 模å¼<C3A5> (æ— åˆ†é¢‘ï¼Œä¸»é‘直接输å…)
|
||
TMOD &= 0x0F; // è®¾ç½®å®šæ—¶å™ 1 模å¼<C3A5>寄å˜å™ï¼Œä¿<C3A4>留低四ä½<C3A4> (定时å™0é…<C3A9>ç½®)
|
||
{
|
||
// 按照系统主é (MAIN_Fosc) 计算 1ms 对应的é‡<C3A9>装载å€
|
||
u16 reload = (u16)(65536UL - (MAIN_Fosc / 1000UL));
|
||
TL1 = (u8)reload; // è½½å…¥ä½ 8 ä½
|
||
TH1 = (u8)(reload >> 8);// è½½å…¥é« 8 ä½
|
||
}
|
||
ET1 = 1; // å¼å<C2BC>å®šæ—¶å™ 1 䏿–å…<C3A5>è
|
||
TR1 = 1; // å<>动定时器 1 计数
|
||
EA = 1; // å¼å<C2BC>免局䏿–å…<C3A5>è
|
||
}
|
||
|
||
// å…¨å±€æŒ‰é”®æ‰æ<E280B0><C3A6>触å<C2A6>‘æ ‡å¿
|
||
volatile bit key_scan_flag = 0;
|
||
|
||
/**
|
||
* @brief å®šæ—¶å™ 1 䏿–æœ<C3A6>务程åº<C3A5> (æ¯ 1ms 触å<C2A6>‘䏿¬)
|
||
* @details æ‰¿æ‹…ç³»ç»Ÿè½æ—¶é’Ÿè®¡ç®—ï¼Œå¹¶æ¯ 10ms ç½ä½<C3A4>主å¾çŽæŒ‰é”®æ‰æ<E280B0><C3A6>æ ‡å¿—ï¼Œä¸<C3A4>ç›´æŽ¥åœ¨ä¸æ–ä¸è¿›è ADC 多æ¡é‡‡æ ·ã
|
||
*/
|
||
void Timer1_Isr(void) interrupt 3
|
||
{
|
||
// 1ms å®šæ—¶æ›´æ–°è½æ—¶é’Ÿ
|
||
Clock_IncMS();
|
||
|
||
// 报è¦å±<C3A5>幕红边æ†ä»¥ 100ms 周期äºç<C2BA>,进行éœè‰²çˆ†é—ªæŒ‡ç¤º
|
||
alarm_flash_flag = (ms_tick / 100) % 2;
|
||
|
||
/* 物ç<C2A9>†æŒ‰é”®å®šæ—¶è®¡æ•° (æ¯ 10ms ç½ä½<C3A4>ä¸€æ¬¡æ ‡å¿—ä½<C3A4>) */
|
||
key_scan_timer++;
|
||
if (key_scan_timer >= 10) {
|
||
key_scan_timer = 0; // é‡<C3A9>ç½®æ‰æ<E280B0><C3A6>åˆ†é¢‘è¡æ•°å™
|
||
key_scan_flag = 1; // ä»…åœ¨ä¸æ–é‡Œç½®èµ·æ ‡å¿—ä½<C3A4>,留待主å¾çŽä¸æ‰§èŒå®žé™…è»å<C2BB>–与消æŠ
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief ä¸»å¾ªçŽæŒ‰é”®æ‰æ<E280B0><C3A6>与消抖处ç<E2809E>†å‡½æ•°
|
||
* @details 由主å¾çŽæ¯ 10ms æ£æŸ¥å¹¶æ‰§èŒï¼Œå®Œå…¨åœ¨ä¸»çº¿ç¨‹ä¸è¿<C3A8>èŒï¼Œç»<C3A7>æ— ä¸æ–é‡<C3A9>入冲çª<C3A7>ã€
|
||
*/
|
||
void Event_KeyScan_Poll(void)
|
||
{
|
||
SystemEvent evt;
|
||
// 读å<C2BB>–按键的电平信å<C2A1> (KEY_UP, KEY_CONFIRM 为低电平有效)
|
||
u8 raw_up = !KEY_UP;
|
||
u8 raw_down = ADC_IsKeyDown(); // KEY_DOWN 通过 P0.3 ADC 通é<C5A1>“判定 (常æ 2.0V, 按下 3.7V)
|
||
u8 raw_confirm = !KEY_CONFIRM;
|
||
u8 raw_sos = !KEY_SOS; // æ<>¢å SOS 物ç<C2A9>†æŒ‰é”®ç”µå¹³æ£æµ
|
||
key_scan_timer = 0; // é‡<C3A9>ç½®æ‰æ<E280B0><C3A6>åˆ†é¢‘è¡æ•°å™
|
||
|
||
// ã€<C3A3>SOS 按键电平实时诊æ–ã€
|
||
{
|
||
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");
|
||
}
|
||
}
|
||
|
||
// 按键调试诊æ–:若按键 ADC 值有å<E280B0>˜åŒ–或å„于高电平,串å<C2B2>£è¾“出真实 ADC å€
|
||
{
|
||
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");
|
||
}
|
||
}
|
||
|
||
// æ£æµ‹åˆ°æœ‰ä»»æ„<C3A6>按é”处于下压状æ<C2B6>,立å<E280B9>³å°†æ— æ“<C3A6>ä½œé—²ç½®ä¼‘çœ è®¡æ—¶å™¨å½’é›
|
||
if (raw_up || raw_down || raw_confirm || raw_sos) {
|
||
inactivity_timer = 0;
|
||
} else {
|
||
// 如果在常æ€<C3A6>下(é<CB86>žä¼‘çœ ã€<C3A3>é<EFBFBD>žæŠ¥è¦ã<C2A6>é<EFBFBD>žç´§æ¥æ±‚æ•‘ï¼‰ï¼Œç´¯åŠ é—²ç½æ—¶é—´
|
||
if (current_state != STATE_SLEEP && current_state != STATE_ALARM && current_state != STATE_SOS_EMITTED) {
|
||
inactivity_timer++;
|
||
}
|
||
}
|
||
|
||
// 默è¤å°†æ´¾å<C2BE>‘事件é‡<C3A9>置为空
|
||
evt.key_event = KEY_EVENT_NONE;
|
||
evt.priority = EVENT_PRIORITY_NORMAL;
|
||
evt.extra_data = 0;
|
||
evt.extra_size = 0;
|
||
|
||
// å<>Œé”®ç»„å<E2809E>ˆåˆ¤å®šï¼šâ–² é” and â– é”å<E2809D>Œæ—¶æŒ‰ä¸‹çš„æ¶ˆæŠ–与生æˆ<C3A6>
|
||
if (raw_up && raw_down) {
|
||
comb_hold++;
|
||
if (comb_hold == 300) { // æŒ<C3A6>ç»æŒ‰ä¸‹è¾ 3 ç§ (300 * 10ms = 3s)
|
||
evt.key_event = KEY_EVENT_UP_DOWN_COMB;
|
||
EventQueue_Push(evt); // 压入队列
|
||
}
|
||
key_up_hold = 0; // 清零å<C2B6>•个按键计数,防æ¢å<C2A2>Œå‡»äº‹ä»¶å¹²æ‰
|
||
key_down_hold = 0;
|
||
} else {
|
||
comb_hold = 0; // 组å<E2809E>ˆé”æ<E2809D>¾å¼€å½’é›¶
|
||
|
||
// â– (KEY_UP) 按键状æ<C2B6>机
|
||
if (raw_up) {
|
||
key_up_hold++;
|
||
if (key_up_hold == 300) { // 达到 3 秒判定为长按
|
||
evt.key_event = KEY_EVENT_UP_LONG;
|
||
EventQueue_Push(evt);
|
||
}
|
||
} else {
|
||
// 如果æ<C593>¾å¼€æ—¶æŒ‰ä¸‹è¡æ•°åœ¨æ¶ˆæŠ–阈值(20ms)至长按阈å¼ï¼ˆ3sï¼‰ä¹‹é—´ï¼Œåˆ™åˆ¤å®šä¸ºä¸æ¬¡çŸæŒ
|
||
if (key_up_hold >= 2 && key_up_hold < 300) {
|
||
evt.key_event = KEY_EVENT_UP_CLICK;
|
||
EventQueue_Push(evt);
|
||
}
|
||
key_up_hold = 0; // 释放归零
|
||
}
|
||
|
||
// â– (KEY_DOWN / å¼å…³æœº) 按键状æ<C2B6>机
|
||
if (raw_down) {
|
||
key_down_hold++;
|
||
if (key_down_hold == 100) { // 长按 1 ç§ (100 * 10ms = 1000ms = 1s) 触å<C2A6>‘关机事件
|
||
evt.key_event = KEY_EVENT_POWER_OFF;
|
||
EventQueue_Push(evt);
|
||
}
|
||
} else {
|
||
// 如果æ<C593>¾å¼€æ—¶æŒ‰ä¸‹æ—¶é•¿åœ¨ 20ms è‡ 1s 之间,触å<C2A6>‘çŸæŒ‰ä¸‹ç¿/选择事件
|
||
if (key_down_hold >= 2 && key_down_hold < 100) {
|
||
evt.key_event = KEY_EVENT_DOWN_CLICK;
|
||
EventQueue_Push(evt);
|
||
}
|
||
key_down_hold = 0; // 释放归零
|
||
}
|
||
|
||
// â– (KEY_CONFIRM) ç¡è®¤æŒ‰é”状æ<C2B6>机
|
||
if (raw_confirm) {
|
||
key_confirm_hold++;
|
||
if (key_confirm_hold == 300) { // 长按 3 秒打å¼ä¸»è<C2BB>œå<C593>
|
||
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);
|
||
}
|
||
key_confirm_hold = 0; // 释放归零
|
||
}
|
||
|
||
// SOS ÎïÀíÇó¾È°´¼ü״̬»ú (ÒѽâËø)
|
||
if (raw_sos) {
|
||
key_sos_hold++;
|
||
if (key_sos_hold == 300) { // ³¤°´ 3 Ã룬·¢³öÇó¾È£¬²åÈë¶ÓÊ×
|
||
evt.key_event = KEY_EVENT_SOS_LONG;
|
||
evt.priority = EVENT_PRIORITY_URGENT;
|
||
EventQueue_InsertFront(evt);
|
||
Uart_SendString("[KEY-DIAG] SOS Long Press Dispatched!\r\n");
|
||
}
|
||
} else {
|
||
if (key_sos_hold >= 2 && key_sos_hold < 300) { // ¶Ì°´¼´ºô¾È£¬²åÈë¶ÓÊ×
|
||
evt.key_event = KEY_EVENT_SOS_CLICK;
|
||
evt.priority = EVENT_PRIORITY_URGENT;
|
||
EventQueue_InsertFront(evt);
|
||
Uart_SendString("[KEY-DIAG] SOS Click Dispatched!\r\n");
|
||
}
|
||
key_sos_hold = 0; // ÊͷŹéÁã
|
||
}
|
||
}
|
||
}
|