From 441a8e4fd42f99d0b99aac646b08f3a4b945fe57 Mon Sep 17 00:00:00 2001 From: GOB Date: Tue, 19 May 2026 17:08:23 +0900 Subject: [PATCH 1/4] fix(uart): consume caps one-shot in UART/ESP-NOW alphabetic key path The caps one-shot indicator (green LED) never cleared after the next alphabetic key press in UART or ESP-NOW modes, because app_clear_caps_one_time() was only called from the I2C/BLE HID ASCII output branch. Add a mode-independent caps consumer that fires when a Latin letter is pressed (excluding modifier keys and Fn-combined presses). --- src/main/app/app_factory.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/app/app_factory.c b/src/main/app/app_factory.c index 0065bba..e72717d 100644 --- a/src/main/app/app_factory.c +++ b/src/main/app/app_factory.c @@ -607,6 +607,17 @@ static void app_process_key_event(key_event_t *key_event) } } + // Fix: consume caps one-shot in UART/ESP-NOW modes when an alphabetic key is pressed + // (originally only handled in I2C/BLEHID ASCII paths — see app_clear_caps_one_time call below) + if (is_press && !key_event->is_repeat && !fn_pressed && + (g_mode == MODE_UART || g_mode == MODE_ESPNOW)) { + char c = 0; + if (app_get_key_char(key_event->button_index, &c) && + ((c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A))) { + app_clear_caps_one_time(); + } + } + // 产测模式:通过 UART 上报按键事件 if (g_mode == MODE_PRODTEST && (is_press || is_release)) { bsp_uart_printf("+KEY:%d,%d\r\n", key_event->button_index, key_event->event); From 79417c5f51b0056d1fc4648bfbd0c2aba9a1fad8 Mon Sep 17 00:00:00 2001 From: GOB Date: Tue, 19 May 2026 17:08:39 +0900 Subject: [PATCH 2/4] fix(uart): send framed ESC for Fn+1 instead of raw byte The Fn+1 ESC branch for UART sent a bare 0x1B via bsp_uart_send, which hosts parsing the 5-byte {0xAA, 0x03, key_id, state, checksum} frame format drop. Replace with app_send_uart_frame(KEY_ESC, true) so ESC presses are delivered as regular framed key events, matching the host UART protocol used by the rest of the keys. --- src/main/app/app_factory.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/app/app_factory.c b/src/main/app/app_factory.c index e72717d..ed4c738 100644 --- a/src/main/app/app_factory.c +++ b/src/main/app/app_factory.c @@ -593,7 +593,8 @@ static void app_process_key_event(key_event_t *key_event) bsp_blehid_send_keycode(0, USB_HID_KEY_ESC); } } else if (g_mode == MODE_UART) { - bsp_uart_send(&esc_char, 1); + // Fix: send framed ESC (host parser expects 5-byte KEY_ID + KEY_STATE frame) + app_send_uart_frame(KEY_ESC, true); } return; } From 905879055b1fb945c2ceaaf3445df339e97b465c Mon Sep 17 00:00:00 2001 From: GOB Date: Tue, 19 May 2026 17:08:53 +0900 Subject: [PATCH 3/4] fix(mode-switch): reset modifier state and LED on mode change app_mode_apply() re-initialised the comms peripherals but left the modifier flags untouched. Combined with app_led_blink_white() then restoring the previous current_r/g/b, the new mode would boot with Sym/Caps/Fn flags still engaged and the LED in the pre-switch colour (e.g. cyan when both Sym and Caps were active). Clear the modifier flags and refresh the LED at the end of app_mode_apply() so each new mode starts clean. --- src/main/app/app_factory.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/app/app_factory.c b/src/main/app/app_factory.c index ed4c738..1e8a233 100644 --- a/src/main/app/app_factory.c +++ b/src/main/app/app_factory.c @@ -495,6 +495,15 @@ static void app_mode_apply(app_mode_t new_mode, bool save_nvs) break; } + // Fix: reset modifier state and refresh LED on mode switch (avoids leaking Sym/Fn into new mode) + sym_mode = false; + sym_pressed = false; + fn_pressed = false; + caps_one_time = false; + caps_locked = false; + caps_hold = false; + app_update_led_state(); + if (save_nvs) { app_save_mode_to_nvs(g_mode); } From cdbf0c9b6aae6ea920409df2cf51e5479763792c Mon Sep 17 00:00:00 2001 From: GOB Date: Tue, 19 May 2026 17:09:02 +0900 Subject: [PATCH 4/4] chore: bump FIRMWARE_VERSION to 0x02 Mark this build as containing the fixes applied in the preceding three commits so host-side libraries can distinguish the patched firmware from the original (0x01) via the I2C version register and the AT+VERSION? production-test command. --- src/main/app/app_factory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/app/app_factory.h b/src/main/app/app_factory.h index 92f432c..6f9cc83 100644 --- a/src/main/app/app_factory.h +++ b/src/main/app/app_factory.h @@ -26,7 +26,7 @@ extern "C" { #endif // 固件版本定义 -#define FIRMWARE_VERSION 0x01 +#define FIRMWARE_VERSION 0x02 // 键盘状态定义 typedef struct {