171 lines
4.5 KiB
C
171 lines
4.5 KiB
C
/******************************************************************************
|
|
* @file key_manager.c
|
|
* @brief 按键:短按切加热;按住 5s 配对 / 12s OTA
|
|
* @author cyWu <1917507415@qq.com>
|
|
* @date 2026.09.04
|
|
* @version V3.1.0
|
|
* @history
|
|
* - V3.1.0, 2026.09.04, cyWu, 精简注释
|
|
* - V3.0.0, 2026.08.31, cyWu, 复用 key.c 长按分级
|
|
******************************************************************************/
|
|
|
|
#include "system/includes.h"
|
|
#include "key_manager.h"
|
|
#include "bsp_hw.h"
|
|
#include "board_pin.h"
|
|
|
|
#define LOG_TAG_CONST APP
|
|
#define LOG_TAG "[KEY]"
|
|
#define LOG_INFO_ENABLE
|
|
#include "debug.h"
|
|
|
|
/** 模块状态 */
|
|
typedef struct {
|
|
uint8_t initialized;
|
|
uint8_t boot_key_lock; /**< 1=上电时键还按着,等松开才认短按(不挡长按分级) */
|
|
uint8_t ota_fired; /**< 1=已到点触发 OTA,本次按住松手不再提交配对 */
|
|
} KeyManagerCtx_t;
|
|
|
|
static KeyManagerCtx_t s_km;
|
|
|
|
/**
|
|
* @brief 读按键:1=按下
|
|
* @return 1=按下,0=松开
|
|
*/
|
|
static uint8_t key_user_read(void)
|
|
{
|
|
return bsp_key_is_pressed();
|
|
}
|
|
|
|
/**
|
|
* @brief 短按(SHORT_Event,松手时刻 <5s):上电未松手前忽略,否则切加热
|
|
* @return 无
|
|
*/
|
|
static void key_user_short(void)
|
|
{
|
|
if (s_km.boot_key_lock) {
|
|
s_km.boot_key_lock = 0; /* 上电松手当成释放,不当短按切加热 */
|
|
log_info("boot key released\n");
|
|
return;
|
|
}
|
|
usr_on_key_short();
|
|
}
|
|
|
|
/**
|
|
* @brief 长按到点(LONG_Event,满 5s 仍按住):挂配对提示灯
|
|
* @note ⚠ 跑在 usr_timer 20ms(硬件定时器中断上下文):只准打标志 + 切灯效
|
|
* 事件(纯 RAM)。清绑定(写 VM)留给 app_function_loop(任务上下文)。
|
|
* @return 无
|
|
*/
|
|
static void key_user_pair_hint(void)
|
|
{
|
|
usr_on_key_pair_hint();
|
|
}
|
|
|
|
/**
|
|
* @brief 连按到点(LAST_Event,满 12s 仍按住,到点即触发不等松手):进 OTA
|
|
* @note ⚠ 同上,只置标志;usr_app_ota_init 由 app_function_loop 执行。
|
|
* key.c 的 keyHandle 对 LAST_Event 不清 eventType,松手前每 20ms 都会
|
|
* 再派发一次,这里用 ota_fired 挡住重复调用。
|
|
* @return 无
|
|
*/
|
|
static void key_user_ota_start(void)
|
|
{
|
|
if (s_km.ota_fired) {
|
|
return;
|
|
}
|
|
s_km.ota_fired = 1;
|
|
usr_on_key_ota_start();
|
|
}
|
|
|
|
/**
|
|
* @brief 释放(RELEASE_Event,只有按满 ≥5s 才会触发):未进 OTA 则提交配对
|
|
* @note 按满 12s 已触发 OTA 的这次按住,松手不再提交配对(ota_fired 拦住)。
|
|
* @return 无
|
|
*/
|
|
static void key_user_release(void)
|
|
{
|
|
s_km.boot_key_lock = 0;
|
|
if (!s_km.ota_fired) {
|
|
usr_on_key_pair_start();
|
|
}
|
|
s_km.ota_fired = 0;
|
|
}
|
|
|
|
static keyCategory_t s_keys[USR_KEY_COUNT] = {
|
|
[USR_KEY_USER] = {
|
|
.fsm.keyShield = KEY_ENABLE,
|
|
.fsm.keyDownLevel = Bit_SET,
|
|
.fsm.eventType = NULL_Event,
|
|
.fsm.keyLongTime = BOARD_KEY_PAIR_MS, /* 满 5s 仍按住 -> longPressCb */
|
|
.fsm.keyLastTime = BOARD_KEY_OTA_MS, /* 满 12s 仍按住 -> lastPressCb */
|
|
.fsm.keyReadValue = key_user_read,
|
|
.func.ShortPressCb = key_user_short,
|
|
.func.releasePressCb = key_user_release,
|
|
.func.longPressCb = key_user_pair_hint,
|
|
.func.lastPressCb = key_user_ota_start,
|
|
},
|
|
};
|
|
|
|
/**
|
|
* @brief 装载按键表
|
|
* @return 无
|
|
*/
|
|
void user_key_init(void)
|
|
{
|
|
if (s_km.initialized) {
|
|
return;
|
|
}
|
|
keyParaInit(s_keys);
|
|
s_km.boot_key_lock = 0;
|
|
s_km.ota_fired = 0;
|
|
s_km.initialized = 1;
|
|
}
|
|
|
|
/**
|
|
* @brief 上电后:键还按着则锁住短按,松开才认短按
|
|
* @note 只锁短按,**不锁长按分级**:上电就按住 5s 进配对是受支持的用法。
|
|
* @return 无
|
|
*/
|
|
void user_key_lock_if_held(void)
|
|
{
|
|
reset_key_Status(USR_KEY_USER);
|
|
if (bsp_key_is_pressed()) {
|
|
s_km.boot_key_lock = 1; /* 上电手还按着,等松开才认短按,避免一上电就切加热 */
|
|
log_info("boot key held, wait release\n");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief 按真实毫秒推进状态机
|
|
* @param dt 距上次调用的毫秒数
|
|
* @return 无
|
|
*/
|
|
void user_key_scan(uint16_t dt)
|
|
{
|
|
uint16_t i;
|
|
|
|
if (!s_km.initialized) {
|
|
return;
|
|
}
|
|
if (dt == 0) {
|
|
dt = 1;
|
|
}
|
|
/* 按键库按 1ms 步进,业务节拍是 20ms,这里循环 dt 次对齐真实时间 */
|
|
for (i = 0; i < dt; i++) {
|
|
keyCheckProcess();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief 派发按键回调
|
|
* @return 无
|
|
*/
|
|
void user_key_handle(void)
|
|
{
|
|
if (!s_km.initialized) {
|
|
return;
|
|
}
|
|
keyHandle();
|
|
}
|