268 lines
7.3 KiB
C
268 lines
7.3 KiB
C
/******************************************************************************
|
|
* @file key.c
|
|
* @brief 按键状态机实现
|
|
* @author cyWu <1917507415@qq.com>
|
|
* @date 2026.08.25
|
|
* @version V1.0.0
|
|
* @history
|
|
* - V1.0.0, 2026.08.25, cyWu, 从天誉 MJ-1.0 充电板移植到杰理 BR28
|
|
******************************************************************************/
|
|
|
|
#include "key.h"
|
|
#include <stddef.h>
|
|
|
|
static uint32_t s_key_count_time;
|
|
static uint8_t s_key_num = USR_KEY_COUNT;
|
|
keyCategory_t keyTable[USR_KEY_COUNT];
|
|
|
|
/**
|
|
* @brief 读按键电平到 fsm
|
|
* @param key 状态机
|
|
* @return 1=已读,0=被屏蔽
|
|
*/
|
|
static uint8_t get_key_level(keyFSM_t *key)
|
|
{
|
|
if (key->keyShield == KEY_DISABLE) {
|
|
return 0;
|
|
}
|
|
if (key->keyReadValue == NULL) {
|
|
return 0;
|
|
}
|
|
key->keyLevel = (key->keyReadValue() == key->keyDownLevel) ? Bit_SET : Bit_RESET;
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @brief 单击 / 双击间隔判定
|
|
* @param click 状态机
|
|
* @return 1=可以出事件
|
|
*/
|
|
static uint8_t key_click_frequency(keyFSM_t *click)
|
|
{
|
|
click->keyInterval++;
|
|
switch (click->keyFrequency) {
|
|
case CLICK:
|
|
if (click->keyInterval >= (KEY_INTERVAL / (DEBOUNCE_TIME * KEY_TIMER_MS))) {
|
|
click->eventType = SHORT_Event;
|
|
return 1;
|
|
}
|
|
break;
|
|
case DbLCLICK:
|
|
if (click->keyInterval >= (KEY_INTERVAL / (DEBOUNCE_TIME * KEY_TIMER_MS))) {
|
|
click->eventType = DBCL_Event;
|
|
return 1;
|
|
}
|
|
break;
|
|
default:
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief 按键状态机步进
|
|
* @param key_buf 状态机
|
|
* @return 1=已处理
|
|
*/
|
|
static uint8_t read_key_status(keyFSM_t *key_buf)
|
|
{
|
|
if (!get_key_level(key_buf)) {
|
|
return 0;
|
|
}
|
|
|
|
switch (key_buf->keyStatus) {
|
|
case KEY_ST_NULL:
|
|
if (key_buf->keyLevel == Bit_SET) {
|
|
key_buf->keyStatus = KEY_ST_SURE;
|
|
}
|
|
break;
|
|
case KEY_ST_SURE:
|
|
if (key_buf->keyLevel == Bit_SET) {
|
|
key_buf->eventType = DOWN_Event;
|
|
key_buf->keyStatus = KEY_ST_DOWN;
|
|
key_buf->keyCount = 0;
|
|
key_buf->keyLongFlag = 1;
|
|
} else {
|
|
key_buf->keyStatus = KEY_ST_NULL;
|
|
}
|
|
break;
|
|
case KEY_ST_DOWN:
|
|
if (key_buf->keyLevel != Bit_SET) {
|
|
if (key_buf->keyShortFlag == 0) {
|
|
key_buf->keyShortFlag = 1;
|
|
key_buf->keyFrequency++;
|
|
key_buf->keyInterval = 0;
|
|
}
|
|
if (key_click_frequency(key_buf)) {
|
|
key_buf->keyFrequency = 0;
|
|
key_buf->keyStatus = KEY_ST_NULL;
|
|
}
|
|
if ((key_buf->keyCount >= key_buf->keyLongTime / DEBOUNCE_TIME)
|
|
&& (key_buf->keyCount < key_buf->keyLastTime / DEBOUNCE_TIME)) {
|
|
key_buf->keyFrequency = 0;
|
|
key_buf->keyStatus = KEY_ST_NULL;
|
|
key_buf->eventType = RELEASE_Event;
|
|
}
|
|
key_buf->keyCount = 0;
|
|
key_buf->keyLongFlag = 1;
|
|
} else {
|
|
if ((++key_buf->keyCount >= key_buf->keyLastTime / DEBOUNCE_TIME)) {
|
|
key_buf->keyCount = 0;
|
|
key_buf->keyFrequency = 0;
|
|
key_buf->keyStatus = KEY_ST_LONG;
|
|
key_buf->eventType = LAST_Event;
|
|
key_buf->keyLongFlag = 1;
|
|
}
|
|
if ((key_buf->keyCount >= key_buf->keyLongTime / DEBOUNCE_TIME)
|
|
&& (key_buf->keyCount < key_buf->keyLastTime / DEBOUNCE_TIME)) {
|
|
key_buf->keyFrequency = 0;
|
|
if (key_buf->keyLongFlag == 1) {
|
|
key_buf->eventType = LONG_Event;
|
|
key_buf->keyLongFlag = 0;
|
|
}
|
|
}
|
|
key_buf->keyShortFlag = 0;
|
|
}
|
|
break;
|
|
case KEY_ST_LONG:
|
|
if (key_buf->keyLevel != Bit_SET) {
|
|
key_buf->keyStatus = KEY_ST_NULL;
|
|
key_buf->eventType = RELEASE_Event;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @brief 扫描全部按键状态机
|
|
* @return 无
|
|
*/
|
|
static void key_event_process(void)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < s_key_num; i++) {
|
|
(void)read_key_status(&keyTable[i].fsm);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief 1ms 调用一次;满 DEBOUNCE_TIME 才真正采样
|
|
* @return 无
|
|
*/
|
|
void keyCheckProcess(void)
|
|
{
|
|
s_key_count_time++;
|
|
if (s_key_count_time >= (DEBOUNCE_TIME / KEY_TIMER_MS)) {
|
|
s_key_count_time = 0;
|
|
key_event_process();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief 拷贝产品按键表
|
|
* @param keys 按键数组,长度 USR_KEY_COUNT
|
|
* @return 无
|
|
*/
|
|
void keyParaInit(keyCategory_t *keys)
|
|
{
|
|
if (keys == NULL) {
|
|
return;
|
|
}
|
|
if (USR_KEY_COUNT >= KEY_MAX_NUMBER) {
|
|
s_key_num = KEY_MAX_NUMBER;
|
|
}
|
|
memcpy(keyTable, keys, sizeof(keyCategory_t) * s_key_num);
|
|
}
|
|
|
|
/**
|
|
* @brief 运行中改长按/连按时长并复位状态
|
|
* @param key_event 按键索引
|
|
* @param key_param 新参数
|
|
* @return 无
|
|
*/
|
|
void setKeyEventParams(uint8_t key_event, keyCategory_t key_param)
|
|
{
|
|
if (key_event >= s_key_num) {
|
|
return;
|
|
}
|
|
keyTable[key_event].fsm.keyShield = key_param.fsm.keyShield;
|
|
keyTable[key_event].fsm.keyLongTime = key_param.fsm.keyLongTime;
|
|
keyTable[key_event].fsm.keyLastTime = key_param.fsm.keyLastTime;
|
|
keyTable[key_event].fsm.keyStatus = KEY_ST_NULL;
|
|
keyTable[key_event].fsm.eventType = NULL_Event;
|
|
keyTable[key_event].fsm.keyCount = 0;
|
|
}
|
|
|
|
/**
|
|
* @brief 派发按键事件回调
|
|
* @return 无
|
|
*/
|
|
void keyHandle(void)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < s_key_num; i++) {
|
|
if (keyTable[i].fsm.eventType == NULL_Event) {
|
|
continue;
|
|
}
|
|
switch (keyTable[i].fsm.eventType) {
|
|
case RELEASE_Event:
|
|
if (keyTable[i].func.releasePressCb != NULL) {
|
|
keyTable[i].func.releasePressCb();
|
|
}
|
|
keyTable[i].fsm.eventType = NULL_Event;
|
|
break;
|
|
case SHORT_Event:
|
|
if (keyTable[i].func.ShortPressCb != NULL) {
|
|
keyTable[i].func.ShortPressCb();
|
|
}
|
|
keyTable[i].fsm.eventType = NULL_Event;
|
|
break;
|
|
case DOWN_Event:
|
|
if (keyTable[i].func.downPressCb != NULL) {
|
|
keyTable[i].func.downPressCb();
|
|
}
|
|
keyTable[i].fsm.eventType = NULL_Event;
|
|
break;
|
|
case LONG_Event:
|
|
if (keyTable[i].func.longPressCb != NULL) {
|
|
keyTable[i].func.longPressCb();
|
|
}
|
|
keyTable[i].fsm.eventType = NULL_Event;
|
|
break;
|
|
case LAST_Event:
|
|
if (keyTable[i].func.lastPressCb != NULL) {
|
|
keyTable[i].func.lastPressCb();
|
|
}
|
|
break;
|
|
case DBCL_Event:
|
|
if (keyTable[i].func.dbclPressCb != NULL) {
|
|
keyTable[i].func.dbclPressCb();
|
|
}
|
|
keyTable[i].fsm.eventType = NULL_Event;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief 复位指定按键状态机
|
|
* @param key_index 按键索引
|
|
* @return 无
|
|
*/
|
|
void reset_key_Status(keyList key_index)
|
|
{
|
|
if (key_index >= USR_KEY_COUNT) {
|
|
return;
|
|
}
|
|
keyTable[key_index].fsm.keyStatus = KEY_ST_NULL;
|
|
keyTable[key_index].fsm.eventType = NULL_Event;
|
|
keyTable[key_index].fsm.keyCount = 0;
|
|
}
|