Fixes and improvements (#620)
- Standardized keyboard input using Unicode-based key codes across supported devices and the simulator. Keyboards don't emit `LV_KEY_*` anymore. - Refactored lilygo encoder driver into a reusable GPIO rotary encoder driver (see `Drivers/gpio-encoder-module/`). Added more features to the config file. - Improved LVGL keyboard device management, including duplicate prevention and reliable reconnects. - LVGL file mutex now registers with lvgl start/stop - Improved LVGL startup/shutdown stability and memory allocation reliability. - Increased simulator LVGL memory capacity and improved USB device-class handling.
This commit is contained in:
committed by
GitHub
parent
4fea48f433
commit
db48dfe812
@@ -44,31 +44,31 @@
|
||||
37 49 50 51 52 53 54 55 56 0 // % 1 2 3 4 5 6 7 8
|
||||
57 48 8 91 93 43 34 39 27 0 // 9 0 BKSP [ ] + " ' EXIT
|
||||
9 113 119 101 114 116 121 117 105 0 // TAB q w e r t y u i
|
||||
111 112 10 40 41 45 59 58 3 0 // o p ENTER ( ) - ; : STOP
|
||||
111 112 13 40 41 45 59 58 3 0 // o p ENTER ( ) - ; : STOP
|
||||
0 97 115 100 102 103 104 106 107 0 // a s d f g h j k
|
||||
108 17 35 123 125 42 44 46 2 0 // l UP # { } * , . MENU
|
||||
122 120 99 118 98 32 32 110 109 0 // z x c v b n m
|
||||
20 18 19 60 62 47 92 61 10 0 // LEFT DOWN RIGHT < > / \ = RUN
|
||||
20 18 19 60 62 47 92 61 13 0 // LEFT DOWN RIGHT < > / \ = RUN
|
||||
];
|
||||
keymap-uc = [
|
||||
37 49 50 51 52 53 54 55 56 0 // % 1 2 3 4 5 6 7 8
|
||||
57 48 8 91 93 43 34 39 27 0 // 9 0 BKSP [ ] + " ' EXIT
|
||||
9 81 87 69 82 84 89 85 73 0 // TAB Q W E R T Y U I
|
||||
79 80 10 40 41 45 59 58 3 0 // O P ENTER ( ) - ; : STOP
|
||||
79 80 13 40 41 45 59 58 3 0 // O P ENTER ( ) - ; : STOP
|
||||
0 65 83 68 70 71 72 74 75 0 // A S D F G H J K
|
||||
76 17 35 123 125 42 44 46 2 0 // L UP # { } * , . MENU
|
||||
90 88 67 86 66 32 32 78 77 0 // Z X C V B N M
|
||||
20 18 19 60 62 47 92 61 10 0 // LEFT DOWN RIGHT < > / \ = RUN
|
||||
20 18 19 60 62 47 92 61 13 0 // LEFT DOWN RIGHT < > / \ = RUN
|
||||
];
|
||||
keymap-sy = [
|
||||
37 49 50 51 52 53 54 55 56 0 // % 1 2 3 4 5 6 7 8
|
||||
57 48 8 91 93 43 34 39 27 0 // 9 0 BKSP [ ] + " ' EXIT
|
||||
9 113 119 101 114 116 121 117 105 0 // TAB q w e r t y u i
|
||||
111 112 10 40 41 45 59 58 3 0 // o p ENTER ( ) - ; : STOP
|
||||
111 112 13 40 41 45 59 58 3 0 // o p ENTER ( ) - ; : STOP
|
||||
0 97 115 100 102 103 104 106 107 0 // a s d f g h j k
|
||||
108 17 35 123 125 42 44 46 2 0 // l UP # { } * , . MENU
|
||||
122 120 99 118 98 32 32 110 109 0 // z x c v b n m
|
||||
20 18 19 60 62 47 92 61 10 0 // LEFT DOWN RIGHT < > / \ = RUN
|
||||
20 18 19 60 62 47 92 61 13 0 // LEFT DOWN RIGHT < > / \ = RUN
|
||||
];
|
||||
shift-row = <4>;
|
||||
shift-col = <0>;
|
||||
|
||||
@@ -74,19 +74,19 @@
|
||||
keymap-lc = [
|
||||
113 119 101 114 116 121 117 105 111 112 // q w e r t y u i o p
|
||||
97 115 100 102 103 104 106 107 108 8 // a s d f g h j k l BACKSPACE
|
||||
0 122 120 99 118 98 110 109 36 10 // z x c v b n m $ ENTER
|
||||
0 122 120 99 118 98 110 109 36 13 // z x c v b n m $ ENTER
|
||||
0 0 0 0 0 11 48 32 0 9 // PREV 0 SPC NEXT
|
||||
];
|
||||
keymap-uc = [
|
||||
81 87 69 82 84 89 85 73 79 80 // Q W E R T Y U I O P
|
||||
65 83 68 70 71 72 74 75 76 8 // A S D F G H J K L BACKSPACE
|
||||
0 90 88 67 86 66 78 77 36 10 // Z X C V B N M $ ENTER
|
||||
0 90 88 67 86 66 78 77 36 13 // Z X C V B N M $ ENTER
|
||||
0 0 0 0 0 11 48 32 0 9 // PREV 0 SPC NEXT
|
||||
];
|
||||
keymap-sy = [
|
||||
49 50 51 52 53 54 55 56 57 48 // 1 2 3 4 5 6 7 8 9 0
|
||||
64 35 43 45 42 47 40 41 95 8 // @ # + - * / ( ) _ BACKSPACE
|
||||
0 33 63 59 58 39 34 44 46 10 // ! ? ; : ' " , . ENTER
|
||||
0 33 63 59 58 39 34 44 46 13 // ! ? ; : ' " , . ENTER
|
||||
0 0 0 0 0 11 48 32 0 9 // PREV 0 SPC NEXT
|
||||
];
|
||||
shift-row = <2>;
|
||||
|
||||
@@ -61,19 +61,19 @@
|
||||
keymap-lc = [
|
||||
113 119 101 114 116 121 117 105 111 112 // q w e r t y u i o p
|
||||
97 115 100 102 103 104 106 107 108 8 // a s d f g h j k l BACKSPACE
|
||||
0 122 120 99 118 98 110 109 36 10 // z x c v b n m $ ENTER
|
||||
0 122 120 99 118 98 110 109 36 13 // z x c v b n m $ ENTER
|
||||
0 0 0 0 0 11 48 32 0 9 // PREV 0 SPC NEXT
|
||||
];
|
||||
keymap-uc = [
|
||||
81 87 69 82 84 89 85 73 79 80 // Q W E R T Y U I O P
|
||||
65 83 68 70 71 72 74 75 76 8 // A S D F G H J K L BACKSPACE
|
||||
0 90 88 67 86 66 78 77 36 10 // Z X C V B N M $ ENTER
|
||||
0 90 88 67 86 66 78 77 36 13 // Z X C V B N M $ ENTER
|
||||
0 0 0 0 0 11 48 32 0 9 // PREV 0 SPC NEXT
|
||||
];
|
||||
keymap-sy = [
|
||||
49 50 51 52 53 54 55 56 57 48 // 1 2 3 4 5 6 7 8 9 0
|
||||
64 35 43 45 42 47 40 41 95 8 // @ # + - * / ( ) _ BACKSPACE
|
||||
0 33 63 59 58 39 34 44 46 10 // ! ? ; : ' " , . ENTER
|
||||
0 33 63 59 58 39 34 44 46 13 // ! ? ; : ' " , . ENTER
|
||||
0 0 0 0 0 11 48 32 0 9 // PREV 0 SPC NEXT
|
||||
];
|
||||
shift-row = <2>;
|
||||
|
||||
@@ -3,5 +3,5 @@ file(GLOB_RECURSE SOURCE_FILES source/*.c*)
|
||||
idf_component_register(
|
||||
SRCS ${SOURCE_FILES}
|
||||
INCLUDE_DIRS "source"
|
||||
REQUIRES TactilityKernel lvgl-module lilygo-module
|
||||
REQUIRES TactilityKernel lvgl-module gpio-encoder-module
|
||||
)
|
||||
|
||||
@@ -6,5 +6,5 @@ dependencies:
|
||||
- Drivers/tca8418-module
|
||||
- Drivers/bq25896-module
|
||||
- Drivers/drv2605-module
|
||||
- Drivers/lilygo-module
|
||||
- Drivers/gpio-encoder-module
|
||||
dts: lilygo,tlora-pager.dts
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <bindings/tca8418.h>
|
||||
#include <bindings/bq25896.h>
|
||||
#include <bindings/drv2605.h>
|
||||
#include <lilygo/bindings/tpager_encoder.h>
|
||||
#include <bindings/gpio_encoder.h>
|
||||
|
||||
// Reference: https://wiki.lilygo.cc/get_started/en/LoRa_GPS/T-LoraPager/T-LoraPager.html
|
||||
/ {
|
||||
@@ -60,13 +60,13 @@
|
||||
columns = <10>;
|
||||
keymap-lc = [
|
||||
113 119 101 114 116 121 117 105 111 112 // q w e r t y u i o p
|
||||
97 115 100 102 103 104 106 107 108 10 // a s d f g h j k l ENTER
|
||||
97 115 100 102 103 104 106 107 108 13 // a s d f g h j k l ENTER
|
||||
0 122 120 99 118 98 110 109 0 8 // z x c v b n m BACKSPACE
|
||||
32 0 0 0 0 0 0 0 0 0 // SPC
|
||||
];
|
||||
keymap-uc = [
|
||||
81 87 69 82 84 89 85 73 79 80 // Q W E R T Y U I O P
|
||||
65 83 68 70 71 72 74 75 76 10 // A S D F G H J K L ENTER
|
||||
65 83 68 70 71 72 74 75 76 13 // A S D F G H J K L ENTER
|
||||
0 90 88 67 86 66 78 77 0 8 // Z X C V B N M BACKSPACE
|
||||
32 0 0 0 0 0 0 0 0 0 // SPC
|
||||
];
|
||||
@@ -201,7 +201,7 @@
|
||||
|
||||
// Encoder wheel next to the display.
|
||||
encoder {
|
||||
compatible = "lilygo,tpager-encoder";
|
||||
compatible = "tactility,gpio-encoder";
|
||||
pin-a = <&gpio0 40 GPIO_FLAG_NONE>;
|
||||
pin-b = <&gpio0 41 GPIO_FLAG_NONE>;
|
||||
pin-enter = <&gpio0 7 GPIO_FLAG_NONE>;
|
||||
|
||||
@@ -2,17 +2,14 @@
|
||||
#include <tactility/module.h>
|
||||
#include <tactility/system_event.h>
|
||||
|
||||
#include <lilygo/drivers/tpager_encoder_input.h>
|
||||
|
||||
constexpr auto* TAG = "T-Lora Pager";
|
||||
|
||||
extern "C" {
|
||||
|
||||
static void on_boot_completed(struct SystemEvent* /*event*/, void* /*context*/) {
|
||||
// The kernel tpager_encoder device is already started by kernel_init(); this just
|
||||
// The kernel gpio_encoder device is already started by kernel_init(); this just
|
||||
// registers it as an LVGL input device, which requires LVGL to be up first.
|
||||
lvgl_lock();
|
||||
tpager_encoder::init();
|
||||
lvgl_unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/queue.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
@@ -119,36 +117,38 @@ static constexpr HidMapping KEY_MATRIX_HID_SYM[70] = {
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// HID usage code + modifier → LVGL key
|
||||
// Covers all codes present in the Tab5 matrix tables above. LV_KEY_* are plain uint32_t
|
||||
// constants - matching KeyboardKeyData::key's driver-defined contract and the same convention
|
||||
// m5stack-module's cardputer_keyboard.cpp kernel driver already uses.
|
||||
// HID usage code + modifier → key (Unicode codepoint)
|
||||
// Covers all codes present in the Tab5 matrix tables above. Every key returns a real Unicode
|
||||
// codepoint per KeyboardKeyData::key's contract - never an LV_KEY_* constant. Keys with no
|
||||
// ordinary character of their own (arrows, Tab/Shift+Tab and Ctrl+arrow as focus nav) use the
|
||||
// CodePoint enum's standard Unicode symbols for the concept (CODEPOINT_FOCUS_PREV/NEXT reused for
|
||||
// Ctrl+arrow's focus-move aliases). lvgl-module's keyboard.cpp translates all of these back to
|
||||
// LVGL's own sentinels (CODEPOINT_ESCAPE/BACKSPACE/DELETE already equal their LV_KEY_* counterpart
|
||||
// numerically, so no translation is needed for those).
|
||||
//
|
||||
// `ctrl` only selects the LVGL focus-navigation aliases for the arrow keys. Ctrl chords on
|
||||
// ordinary keys are NOT folded into the returned value - the C0 control codes a terminal wants
|
||||
// (Ctrl+C = 0x03, Ctrl+K = 0x0B, ...) collide with the LVGL constants returned here (LV_KEY_END = 3,
|
||||
// LV_KEY_PREV = 11, ...), so Ctrl is reported out-of-band via KeyboardKeyData::ctrl instead and
|
||||
// consumers that want control codes derive them themselves.
|
||||
// Ctrl chords on ordinary keys are NOT folded into the returned value - the C0 control codes a
|
||||
// terminal wants (Ctrl+C = 0x03, Ctrl+K = 0x0B, ...) would collide with a codepoint-based scheme,
|
||||
// so Ctrl is reported out-of-band via KeyboardKeyData::ctrl instead and consumers that want
|
||||
// control codes derive them themselves.
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint32_t tab5_translate_key(uint8_t keycode, uint8_t modifier, bool ctrl) {
|
||||
const bool shift = (modifier & 0x22U) != 0U;
|
||||
|
||||
// Navigation → LVGL key constants
|
||||
// Navigation → key (Unicode codepoint)
|
||||
switch (keycode) {
|
||||
case 0x29: return LV_KEY_ESC;
|
||||
case 0x28: return LV_KEY_ENTER;
|
||||
case 0x2A: return LV_KEY_BACKSPACE;
|
||||
case 0x4C: return LV_KEY_DEL;
|
||||
case 0x2B: return '\t';
|
||||
// Arrows: Ctrl+arrow = focus navigation, plain arrow = raw cursor movement
|
||||
case 0x52: return ctrl ? (uint32_t)LV_KEY_PREV : (uint32_t)LV_KEY_UP;
|
||||
case 0x51: return ctrl ? (uint32_t)LV_KEY_NEXT : (uint32_t)LV_KEY_DOWN;
|
||||
case 0x50: return ctrl ? (uint32_t)LV_KEY_PREV : (uint32_t)LV_KEY_LEFT;
|
||||
case 0x4F: return ctrl ? (uint32_t)LV_KEY_NEXT : (uint32_t)LV_KEY_RIGHT;
|
||||
case 0x29: return CODEPOINT_ESCAPE;
|
||||
case 0x28: return CODEPOINT_ENTER;
|
||||
case 0x2A: return CODEPOINT_BACKSPACE;
|
||||
case 0x4C: return CODEPOINT_DELETE;
|
||||
case 0x2B: return CODEPOINT_TAB;
|
||||
case 0x52: return CODEPOINT_ARROW_UP;
|
||||
case 0x51: return CODEPOINT_ARROW_DOWN;
|
||||
case 0x50: return CODEPOINT_ARROW_LEFT;
|
||||
case 0x4F: return CODEPOINT_ARROW_RIGHT;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// F1-F12 (Sym layer over the number row) have no LVGL/ASCII representation - callers that
|
||||
// F1-F12 (Sym layer over the number row) have no Unicode/LVGL representation - callers that
|
||||
// want them read KeyboardKeyData::hid_keycode instead (see drain_events()), which is
|
||||
// populated for every key regardless of whether `key` itself has a meaningful value.
|
||||
|
||||
@@ -378,9 +378,9 @@ static void drain_events(Device* device, Tab5KeyboardInternal* internal) {
|
||||
if (internal->ctrl_held) modifier |= 0x01U; // HID LeftCtrl
|
||||
if (internal->alt_held) modifier |= 0x04U; // HID LeftAlt
|
||||
const uint32_t lv_key = tab5_translate_key(m.keycode, modifier, internal->ctrl_held);
|
||||
// Queue whenever there's a HID keycode, even if this key has no LVGL/ASCII
|
||||
// Queue whenever there's a HID keycode, even if this key has no Unicode/LVGL
|
||||
// representation (e.g. F1-F12) - lv_key stays 0 for those, callers that only
|
||||
// care about LVGL/ASCII text ignore a 0 key the same way they always have.
|
||||
// care about the codepoint ignore a 0 key the same way they always have.
|
||||
if (pressed) {
|
||||
// A real key was pressed — this hold is a chord, not a tap
|
||||
internal->aa_tapped = false;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include "sdl_input.h"
|
||||
|
||||
#include <lvgl.h>
|
||||
#include <tactility/drivers/keyboard.h>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
@@ -27,22 +27,27 @@ void push_key(uint32_t key) {
|
||||
key_queue_count++;
|
||||
}
|
||||
|
||||
// Mirrors LVGL's own lv_sdl_keyboard.c keycode_to_ctrl_key(): maps navigation/control keys to
|
||||
// LV_KEY_* constants. Printable characters arrive separately via SDL_TEXTINPUT.
|
||||
uint32_t keycode_to_key(SDL_Keycode sdl_key) {
|
||||
// Mirrors LVGL's own lv_sdl_keyboard.c keycode_to_ctrl_key(): every key returns a real Unicode
|
||||
// codepoint per KeyboardKeyData::key's contract - never an LV_KEY_* constant, even for keys with
|
||||
// no ordinary character of their own (arrows, Tab/Shift+Tab as focus nav, Home/End), which use the
|
||||
// CodePoint enum's standard Unicode symbols for the concept. lvgl-module's keyboard.cpp translates
|
||||
// all of these back to LVGL's own sentinels (CODEPOINT_ESCAPE/BACKSPACE/DELETE already equal their
|
||||
// LV_KEY_* counterpart numerically, so no translation is needed for those). Printable characters
|
||||
// arrive separately via SDL_TEXTINPUT.
|
||||
uint32_t keycode_to_key(SDL_Keycode sdl_key, bool shift) {
|
||||
switch (sdl_key) {
|
||||
case SDLK_RIGHT: return LV_KEY_RIGHT;
|
||||
case SDLK_LEFT: return LV_KEY_LEFT;
|
||||
case SDLK_UP: return LV_KEY_UP;
|
||||
case SDLK_DOWN: return LV_KEY_DOWN;
|
||||
case SDLK_ESCAPE: return LV_KEY_ESC;
|
||||
case SDLK_BACKSPACE: return LV_KEY_BACKSPACE;
|
||||
case SDLK_DELETE: return LV_KEY_DEL;
|
||||
case SDLK_RIGHT: return CODEPOINT_ARROW_RIGHT;
|
||||
case SDLK_LEFT: return CODEPOINT_ARROW_LEFT;
|
||||
case SDLK_UP: return CODEPOINT_ARROW_UP;
|
||||
case SDLK_DOWN: return CODEPOINT_ARROW_DOWN;
|
||||
case SDLK_ESCAPE: return CODEPOINT_ESCAPE;
|
||||
case SDLK_BACKSPACE: return CODEPOINT_BACKSPACE;
|
||||
case SDLK_DELETE: return CODEPOINT_DELETE;
|
||||
case SDLK_RETURN:
|
||||
case SDLK_KP_ENTER: return LV_KEY_ENTER;
|
||||
case SDLK_TAB: return LV_KEY_NEXT;
|
||||
case SDLK_HOME: return LV_KEY_HOME;
|
||||
case SDLK_END: return LV_KEY_END;
|
||||
case SDLK_KP_ENTER: return CODEPOINT_ENTER;
|
||||
case SDLK_TAB: return CODEPOINT_TAB;
|
||||
case SDLK_HOME: return CODEPOINT_HOME;
|
||||
case SDLK_END: return CODEPOINT_END;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
@@ -75,7 +80,7 @@ void sdl_input_pump() {
|
||||
}
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
push_key(keycode_to_key(event.key.keysym.sym));
|
||||
push_key(keycode_to_key(event.key.keysym.sym, (event.key.keysym.mod & KMOD_SHIFT) != 0));
|
||||
break;
|
||||
case SDL_TEXTINPUT:
|
||||
// ASCII only (first byte of event.text.text) - sufficient for a simulator keyboard.
|
||||
|
||||
Reference in New Issue
Block a user