feat(kbd): 添加CAF按钮模块支持
- 在CMakeLists.txt中添加button_map_module.c源文件和头文件目录 - 创建inc/buttons_def.h定义按钮矩阵引脚配置 - 配置prj.conf启用CAF按钮相关功能和参数 - 实现src/modules/button_map_module.c按钮映射逻辑 - 支持6x4键盘矩阵的按键事件处理和Linux输入键码转换
This commit is contained in:
@@ -3,4 +3,9 @@ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
|
||||
project(new_kbd)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
zephyr_include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)
|
||||
|
||||
target_sources(app PRIVATE
|
||||
src/main.c
|
||||
src/modules/button_map_module.c
|
||||
)
|
||||
|
||||
34
inc/buttons_def.h
Normal file
34
inc/buttons_def.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* CAF buttons 矩阵引脚定义
|
||||
*
|
||||
* 设计说明:
|
||||
* - 本文件被 CAF buttons 模块通过 CONFIG_CAF_BUTTONS_DEF_PATH 直接包含;
|
||||
* - 行列引脚顺序必须与板级 DTS 中 my_keyboard 的 row-gpios/col-gpios 保持一致;
|
||||
* - key_id 的行列编号完全基于这里的数组下标,不依赖 input-keymap 节点。
|
||||
*/
|
||||
|
||||
#include <caf/gpio_pins.h>
|
||||
|
||||
/*
|
||||
* 该符号用于保证配置文件只被链接一次:
|
||||
* 若被重复包含到多个编译单元,会在链接阶段报重复定义,避免静默错配。
|
||||
*/
|
||||
const struct {} buttons_def_include_once;
|
||||
|
||||
/* 列引脚:对应 atguigu_mini_keyboard.dts 中 my_keyboard/col-gpios 顺序。 */
|
||||
static const struct gpio_pin col[] = {
|
||||
{ .port = 0, .pin = 5 },
|
||||
{ .port = 0, .pin = 6 },
|
||||
{ .port = 0, .pin = 26 },
|
||||
{ .port = 0, .pin = 30 },
|
||||
};
|
||||
|
||||
/* 行引脚:对应 atguigu_mini_keyboard.dts 中 my_keyboard/row-gpios 顺序。 */
|
||||
static const struct gpio_pin row[] = {
|
||||
{ .port = 0, .pin = 15 },
|
||||
{ .port = 0, .pin = 7 },
|
||||
{ .port = 0, .pin = 12 },
|
||||
{ .port = 0, .pin = 4 },
|
||||
{ .port = 1, .pin = 9 },
|
||||
{ .port = 0, .pin = 8 },
|
||||
};
|
||||
5
prj.conf
5
prj.conf
@@ -12,3 +12,8 @@ CONFIG_CAF_POWER_MANAGER=y
|
||||
CONFIG_CAF_POWER_MANAGER_TIMEOUT=20
|
||||
CONFIG_CAF_POWER_MANAGER_ERROR_TIMEOUT=10
|
||||
CONFIG_REBOOT=y
|
||||
|
||||
CONFIG_CAF_BUTTONS=y
|
||||
CONFIG_CAF_BUTTONS_DEF_PATH="buttons_def.h"
|
||||
CONFIG_CAF_BUTTONS_SCAN_INTERVAL=5
|
||||
CONFIG_CAF_BUTTONS_DEBOUNCE_INTERVAL=10
|
||||
|
||||
69
src/modules/button_map_module.c
Normal file
69
src/modules/button_map_module.c
Normal file
@@ -0,0 +1,69 @@
|
||||
#include <app_event_manager.h>
|
||||
|
||||
#define MODULE button_map
|
||||
#include <caf/events/module_state_event.h>
|
||||
|
||||
#include <caf/events/button_event.h>
|
||||
#include <caf/key_id.h>
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_REGISTER(MODULE);
|
||||
|
||||
/*
|
||||
* keymap[row][col] 直接对齐板级 DTS 里的 MATRIX_KEY(row, col, key) 定义。
|
||||
* 值为 Linux input key code;-1 表示该矩阵位置未映射功能键。
|
||||
*/
|
||||
static const int16_t keymap[6][4] = {
|
||||
/* row 0 */ { -1, -1, -1, INPUT_KEY_MUTE },
|
||||
/* row 1 */ { INPUT_KEY_NUMLOCK, INPUT_KEY_KPSLASH, INPUT_KEY_KPASTERISK, INPUT_KEY_KPMINUS },
|
||||
/* row 2 */ { INPUT_KEY_KP7, INPUT_KEY_KP8, INPUT_KEY_KP9, -1 },
|
||||
/* row 3 */ { INPUT_KEY_KP4, INPUT_KEY_KP5, INPUT_KEY_KP6, INPUT_KEY_KPPLUS },
|
||||
/* row 4 */ { INPUT_KEY_KP1, INPUT_KEY_KP2, INPUT_KEY_KP3, -1 },
|
||||
/* row 5 */ { INPUT_KEY_KP0, INPUT_KEY_KPDOT, -1, INPUT_KEY_KPENTER },
|
||||
};
|
||||
|
||||
static bool app_event_handler(const struct app_event_header *aeh)
|
||||
{
|
||||
if (is_button_event(aeh)) {
|
||||
const struct button_event *event = cast_button_event(aeh);
|
||||
uint8_t row = KEY_ROW(event->key_id);
|
||||
uint8_t col = KEY_COL(event->key_id);
|
||||
|
||||
/*
|
||||
* 防御性检查:若行列越界,说明 buttons_def 与实际扫描结果不一致,
|
||||
* 记录错误以便尽快发现硬件矩阵定义或固件配置问题。
|
||||
*/
|
||||
if ((row >= ARRAY_SIZE(keymap)) || (col >= ARRAY_SIZE(keymap[0]))) {
|
||||
LOG_ERR("Unknown key_id=0x%04x (row=%u, col=%u)", event->key_id, row, col);
|
||||
return false;
|
||||
}
|
||||
|
||||
int16_t code = keymap[row][col];
|
||||
if (code < 0) {
|
||||
LOG_INF("Button %s row=%u col=%u unmapped", event->pressed ? "down" : "up", row, col);
|
||||
} else {
|
||||
LOG_INF("Button %s row=%u col=%u keycode=%d", event->pressed ? "down" : "up", row, col, code);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_module_state_event(aeh)) {
|
||||
const struct module_state_event *event = cast_module_state_event(aeh);
|
||||
|
||||
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
|
||||
module_set_state(MODULE_STATE_READY);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 未处理但已订阅的事件类型不应进入这里。 */
|
||||
__ASSERT_NO_MSG(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
APP_EVENT_LISTENER(MODULE, app_event_handler);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, button_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
|
||||
Reference in New Issue
Block a user