/****************************************************************************** * @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(); }