#include "key_board/key_board.h"
#if ((KEY_LONG_SUPPORT != KEY_ENABLE) && (KEY_LONG_SUPPORT != KEY_DISABLE))
#error "KEY_LONG_SUPPORT can be only set to KEY_ENABLE or KEY_DISABLE."
#endif
#if ((KEY_MULTI_SUPPORT != KEY_ENABLE) && (KEY_MULTI_SUPPORT != KEY_DISABLE))
#error "KEY_MULTI_SUPPORT can be only set to KEY_ENABLE or KEY_DISABLE."
#endif
#if ((KEY_CONTINUOUS_SUPPORT != KEY_ENABLE) && (KEY_CONTINUOUS_SUPPORT != KEY_DISABLE))
#error "KEY_CONTINUOUS_SUPPORT can be only set to KEY_ENABLE or KEY_DISABLE."
#endif
#if ((KEY_COMBINE_SUPPORT != KEY_ENABLE) && (KEY_COMBINE_SUPPORT != KEY_DISABLE))
#error "KEY_COMBINE_SUPPORT can be only set to KEY_ENABLE or KEY_DISABLE."
#endif
#if (KEY_BOARD_MAX_NUM <= 0)
#error "The value of KEY_BOARD_MAX_NUM must be greater than 0."
#endif
#if (KEY_MAX_NUM <= 0)
#error "The value of KEY_MAX_NUM must be greater than 0."
#endif
#if (KEY_LONG_SUPPORT == KEY_ENABLE)
#if (KEY_DEFAULT_LONG_TRRIGER_TIME <= 0)
#error "The value of KEY_DEFAULT_LONG_TRRIGER_TIME must be greater than 0."
#endif
#endif
#if (KEY_MULTI_SUPPORT == KEY_ENABLE)
#if (KEY_DEFAULT_MULTI_INTERVAL_TIME <= 0)
#error "The value of KEY_DEFAULT_MULTI_INTERVAL_TIME must be greater than 0."
#elif (KEY_DEFAULT_MULTI_INTERVAL_TIME <= KEY_DEFAULT_DEBOUNCE_TIME)
#warning "It is strongly recommended that the value of KEY_DEFAULT_MULTI_INTERVAL_TIME is greater than the value of KEY_DEFAULT_DEBOUNCE_TIME."
#endif
#endif
#if (KEY_CONTINUOUS_SUPPORT == KEY_ENABLE)
#if (KEY_DEFAULT_CONTINUOUS_INIT_TRRIGER_TIME <= 0)
#error "The value of KEY_DEFAULT_CONTINUOUS_INIT_TRRIGER_TIME must be greater than 0."
#endif
#if (KEY_DEFAULT_CONTINUOUS_PERIOD_TRRIGER_TIME <= 0)
#error "The value of KEY_DEFAULT_CONTINUOUS_PERIOD_TRRIGER_TIME must be greater than 0."
#endif
#endif
#if (KEY_COMBINE_SUPPORT == KEY_ENABLE)
#if (KEY_DEFAULT_COMBINE_INTERVAL_TIME <= 0)
#error "The value of KEY_DEFAULT_COMBINE_INTERVAL_TIME must be greater than 0."
#elif (KEY_DEFAULT_COMBINE_INTERVAL_TIME <= KEY_DEFAULT_DEBOUNCE_TIME)
#warning "It is strongly recommended that the value of KEY_DEFAULT_COMBINE_INTERVAL_TIME is greater than the value of KEY_DEFAULT_DEBOUNCE_TIME."
#endif
#endif
#if (KEY_DEFAULT_DEBOUNCE_TIME < 0)
#error "The value of KEY_DEFAULT_DEBOUNCE_TIME must be greater than or equal to 0."
#endif
#define KEY_MAX_TIME ((1u << ((sizeof(unsigned int) << 3) - 1)) - 1)
#define KEY_TIME_CHECK(x) ((x) < KEY_MAX_TIME ? (x) : KEY_MAX_TIME - 1)
struct event_cnt_t {
unsigned int rd_cnt : 16,
wr_cnt : 16;
};
struct key_private_t {
struct key_public_sig_t *property;
enum key_state_t state; //按键状态
bool last_level; //按键上次电平(有效/无效)
bool this_level; //按键本次电平(有效/无效)
struct event_cnt_t release_event; //弹起事件计数
struct event_cnt_t press_event; //按下事件计数
struct event_cnt_t pressing_event; //任然按下事件计数
unsigned int init_debounce_time; //初始消抖时间
unsigned int debounce_time; //消抖计时
#if (KEY_LONG_SUPPORT == KEY_ENABLE)
struct {
unsigned int trriger_time; //触发时间
unsigned int press_time; //已按下时间
bool trriger_flag; //触发标志
}long_press, long_release;
struct event_cnt_t press_long_event; //按下长按事件计数
struct event_cnt_t release_long_event; //弹起长按事件计数
#endif
#if (KEY_MULTI_SUPPORT == KEY_ENABLE)
struct {
unsigned int count; //多击次数
unsigned int timecnt; //记录距上次点击的时间
unsigned int interval; //连续两次点击的最大允许间隔时间
}multi_click_press, multi_click_release;
struct event_cnt_t press_multi_event; //按下多击事件计数
struct event_cnt_t release_multi_event; //弹起多击事件计数
#endif
#if (KEY_CONTINUOUS_SUPPORT == KEY_ENABLE)
struct {
unsigned int trriger_time; //触发时间
unsigned int trriger_period; //触发周期
unsigned int press_time; //已按下时间
}continuous;
struct event_cnt_t press_continuous_event; //连按事件计数
#endif
};
#if (KEY_COMBINE_SUPPORT == KEY_ENABLE)
struct {
unsigned int timecnt; //记录距上次触发的时间
unsigned int interval; //连续两次触发的最大允许间隔时间
struct match_list_t {
const struct key_combine_t *match; //需要匹配的组合状态
unsigned int n; //记录组合状态的位数
unsigned int match_count; //已匹配成功计数
struct match_list_t *next; //用于链接下一个注册的组合状态
struct event_cnt_t combine_event; //组合事件计数
}head; //注册的组合状态的链表头
}static combine;
#endif
struct key_board_t {
enum key_board_type_t type; //键盘类型
unsigned int sig_num; //信号线的数量
struct key_private_t *sig; //信号线的相关信息
//仅用于矩阵键盘
unsigned int ctrl_num; //控制线的数量
unsigned int sig_per_ctrl; //每根控制线上信号线的数量
struct key_public_ctrl_t *ctrl; //控制线的相关信息
};
static struct key_board_t *key_board[KEY_BOARD_MAX_NUM];
static unsigned int key_hash_map[KEY_MAX_NUM]; //用于根据id快速查找按键的对象(线性探测法)
static unsigned int key_press_count; //用于记录当前按下键的计数
static print_debug_callback internal_print_debug; //调试信息输出
static unsigned int key_tick_ms; //tick
static inline void debug(const char *func, int line, const char *message)
{
#include <stdio.h>
static char buff[128];
sprintf(buff, "func:%s, line:%u, %s\n", func, line, message);
if(internal_print_debug)
{
internal_print_debug(buff);
}
}
int key_board_init(void)
{
memset(key_board, 0, sizeof(key_board));
for(unsigned int i= 0;i < GET_ARRAY_SIZE(key_hash_map);i++)
{
key_hash_map[i] = (unsigned int)-1;
}
key_press_count = 0;
#if (KEY_COMBINE_SUPPORT == KEY_ENABLE)
memset(&combine, 0, sizeof(combine));
combine.head.next = NULL;
#endif
key_tick_ms = 0;
return 0;
}
struct key_board_t *key_board_register(enum key_board_type_t type, const struct key_public_sig_t sig[], unsigned int key_sig_n, const struct key_public_ctrl_t ctrl[], unsigned int key_ctrl_n)
{
struct key_board_t *obj;
unsigned int handle_no_use;
unsigned int i;
for(handle_no_use = 0;handle_no_use < GET_ARRAY_SIZE(key_board) && key_board[handle_no_use];handle_no_use++);
if(handle_no_use >= GET_ARRAY_SIZE(key_board))
{
debug(__FUNCTION__, __LINE__, "exceed the max configure value [KEY_BOARD_MAX_NUM]");
return NULL;
}
obj = malloc(sizeof(struct key_board_t));
if(!obj)
{
debug(__FUNCTION__, __LINE__, "malloc failed");
return NULL;
}
memset(obj, 0, sizeof(struct key_board_t));
key_board[handle_no_use] = obj;
obj->type = type;
obj->sig_num = key_sig_n;
obj->sig = malloc(key_sig_n * sizeof(struct key_private_t));
if(!obj->sig)
{
debug(__FUNCTION__, __LINE__, "malloc failed");
return NULL;
}
memset(obj->sig, 0, key_sig_n * sizeof(struct key_private_t));
for(i = 0;i < key_sig_n;i++)
{
obj->sig[i].property = (struct key_public