diff --git a/CMakeLists.txt b/CMakeLists.txt index a0fb22b..8c2db34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 +) diff --git a/inc/buttons_def.h b/inc/buttons_def.h new file mode 100644 index 0000000..f6f8122 --- /dev/null +++ b/inc/buttons_def.h @@ -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 + +/* + * 该符号用于保证配置文件只被链接一次: + * 若被重复包含到多个编译单元,会在链接阶段报重复定义,避免静默错配。 + */ +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 }, +}; diff --git a/prj.conf b/prj.conf index 09fa7b0..d52a2d3 100644 --- a/prj.conf +++ b/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 diff --git a/src/modules/button_map_module.c b/src/modules/button_map_module.c new file mode 100644 index 0000000..853b910 --- /dev/null +++ b/src/modules/button_map_module.c @@ -0,0 +1,69 @@ +#include + +#define MODULE button_map +#include + +#include +#include +#include +#include + +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);