Keyboard_Class & KeysState
Header: utility/Keyboard/Keyboard.h
Access: M5Cardputer.Keyboard
Handles all keyboard input: physical key scanning, character mapping, modifier tracking, Caps Lock, and USB HID key code generation.
KeysState
A snapshot of currently pressed keys, populated by updateKeysState().
Fields
| Field | Type | Description |
|---|---|---|
tab |
bool |
Tab key is pressed |
fn |
bool |
Fn modifier is active |
shift |
bool |
Shift modifier is active |
ctrl |
bool |
Ctrl modifier is active |
opt |
bool |
Opt modifier is active |
alt |
bool |
Alt modifier is active |
del |
bool |
Backspace key is pressed |
enter |
bool |
Enter key is pressed |
space |
bool |
Space key is pressed |
modifiers |
uint8_t |
USB HID modifier bitmask |
word |
std::vector<char> |
Printable characters (respects Shift/Ctrl/Caps) |
hid_keys |
std::vector<uint8_t> |
USB HID key codes for all non-modifier keys |
modifier_keys |
std::vector<uint8_t> |
USB HID key codes for modifier keys |
reset()
Clears all fields: booleans → false, vectors cleared.
KeysState state = M5Cardputer.Keyboard.keysState();
// ... use state ...
state.reset(); // Ready for next frame
Keyboard_Class Methods
begin()
Auto-detects the board type and creates the appropriate KeyboardReader:
- board_M5Cardputer → IOMatrixKeyboardReader (GPIO matrix)
- board_M5CardputerADV → TCA8418KeyboardReader (I2C/TCA8418)
This is called automatically by M5Cardputer.begin() — you normally don't need to call it yourself.
begin(reader)
Injects a custom KeyboardReader implementation. Use this for testing or custom keyboard hardware.
auto customReader = std::make_unique<IOMatrixKeyboardReader>();
M5Cardputer.Keyboard.begin(std::move(customReader));
updateKeyList()
Delegates to the active KeyboardReader to scan the physical matrix and refresh the pressed-key list. Called automatically by M5Cardputer.update().
keyList()
Returns all currently pressed key coordinates as Point2D_t {x, y}.
| Return | Description |
|---|---|
const std::vector<Point2D_t>& |
List of pressed key positions |
void loop() {
M5Cardputer.update();
auto& keys = M5Cardputer.Keyboard.keyList();
M5Cardputer.Display.setCursor(0, 0);
M5Cardputer.Display.printf("Keys held: %d\n", keys.size());
}
isPressed()
Returns the number of keys currently held down. Returns 0 when no keys are pressed.
| Return | Description |
|---|---|
uint8_t |
Count of pressed keys |
void loop() {
M5Cardputer.update();
if (M5Cardputer.Keyboard.isPressed()) {
// At least one key is held
M5Cardputer.Display.drawString("Typing...", 10, 10);
}
}
isChange()
Returns true if the number of pressed keys has changed since the last call. Use this to detect new input without processing every frame.
| Return | Description |
|---|---|
true |
Key count changed (press or release) |
false |
No change since last check |
void loop() {
M5Cardputer.update();
if (M5Cardputer.Keyboard.isChange()) {
if (M5Cardputer.Keyboard.isPressed()) {
M5Cardputer.Keyboard.updateKeysState();
auto& state = M5Cardputer.Keyboard.keysState();
// Process new input
for (char c : state.word) {
M5Cardputer.Display.print(c);
}
if (state.enter) M5Cardputer.Display.println();
} else {
// All keys released
M5Cardputer.Display.println("Keys released");
}
}
}
isKeyPressed(c)
Returns true if the ASCII character c is currently being pressed.
| Parameter | Type | Description |
|---|---|---|
c |
char |
ASCII character to check |
void loop() {
M5Cardputer.update();
// WASD movement
int x = 100, y = 100;
if (M5Cardputer.Keyboard.isKeyPressed('w')) y--;
if (M5Cardputer.Keyboard.isKeyPressed('s')) y++;
if (M5Cardputer.Keyboard.isKeyPressed('a')) x--;
if (M5Cardputer.Keyboard.isKeyPressed('d')) x++;
M5Cardputer.Display.fillRect(x, y, 8, 8, TFT_GREEN);
// Quit shortcut
if (M5Cardputer.Keyboard.isKeyPressed('q')) {
M5Cardputer.Display.println("Quitting...");
}
}
getKey(keyCoor)
Returns the ASCII character for a given physical key position, applying current Shift/Ctrl/Caps Lock state.
| Parameter | Type | Description |
|---|---|---|
keyCoor |
Point2D_t |
Key coordinate {x, y} |
| Return | Description |
|---|---|
uint8_t |
ASCII character, or 0 if invalid/missing |
void loop() {
M5Cardputer.update();
// Read what character is at position (5, 1)
Point2D_t keyPos = {5, 1}; // 't' key
uint8_t ch = M5Cardputer.Keyboard.getKey(keyPos);
M5Cardputer.Display.printf("Key(5,1) = '%c'\n", ch);
}
getKeyValue(keyCoor)
Returns the raw KeyValue_t {value_first, value_second} for a coordinate, without applying modifiers.
Point2D_t keyPos = {1, 0}; // '1' key
KeyValue_t kv = M5Cardputer.Keyboard.getKeyValue(keyPos);
// kv.value_first = '1'
// kv.value_second = '!'
M5Cardputer.Display.printf("'%c' / '%c'\n", kv.value_first, kv.value_second);
updateKeysState()
Scans all pressed keys and populates the KeysState buffer. This is a two-pass algorithm:
- Pass 1: Identify modifier keys (Fn, Opt, Ctrl, Shift, Alt)
- Pass 2: Process all other keys (printable chars, Tab, Enter, Backspace, Space) with correct modifier state
Populates word, hid_keys, modifier_keys, and all boolean flags. Call this before reading keysState().
keysState()
Returns a reference to the current KeysState buffer. The buffer is populated by updateKeysState().
void loop() {
M5Cardputer.update();
if (M5Cardputer.Keyboard.isChange() && M5Cardputer.Keyboard.isPressed()) {
M5Cardputer.Keyboard.updateKeysState();
auto& state = M5Cardputer.Keyboard.keysState();
// Show pressed characters
M5Cardputer.Display.setCursor(0, 0);
M5Cardputer.Display.print("Input: ");
for (char c : state.word) {
M5Cardputer.Display.print(c);
}
// Show active modifiers
M5Cardputer.Display.setCursor(0, 20);
if (state.shift) M5Cardputer.Display.print("SHIFT ");
if (state.ctrl) M5Cardputer.Display.print("CTRL ");
if (state.alt) M5Cardputer.Display.print("ALT ");
if (state.fn) M5Cardputer.Display.print("FN ");
}
}
capslocked() / setCapsLocked()
Software-managed Caps Lock state. When enabled, getKey() returns uppercase characters. This is not a hardware LED — your application must manage the visual indicator.
// Toggle Caps Lock on Tab press
void loop() {
M5Cardputer.update();
if (M5Cardputer.Keyboard.isChange() && M5Cardputer.Keyboard.isPressed()) {
M5Cardputer.Keyboard.updateKeysState();
auto& state = M5Cardputer.Keyboard.keysState();
if (state.tab) {
bool caps = M5Cardputer.Keyboard.capslocked();
M5Cardputer.Keyboard.setCapsLocked(!caps);
M5Cardputer.Display.print(caps ? "Caps: OFF\n" : "Caps: ON\n");
}
}
}
Key Layout
The physical keyboard is a 4-row × 14-column matrix stored in _key_value_map[4][14]. Each position has value_first (normal) and value_second (shifted).
Row 0: ` 1 2 3 4 5 6 7 8 9 0 - = BKSP
Row 1: TAB q w e r t y u i o p [ ] \
Row 2: FN SHIFT a s d f g h j k l ; ' ENTER
Row 3: CTRL OPT ALT z x c v b n m , . / SPACE
Coordinates: Point2D_t {column, row}. Example: the a key is at {2, 2}, the ENTER key is at {13, 2}.
Key Code Constants
Defined in utility/Keyboard/Keyboard_def.h. Useful for USB HID keyboard emulation.
Modifier Keys
| Constant | Value | USB HID | Description |
|---|---|---|---|
KEY_LEFT_CTRL |
0x80 |
0xE0 |
Left Control |
KEY_LEFT_SHIFT |
0x81 |
0xE1 |
Left Shift |
KEY_LEFT_ALT |
0x82 |
0xE2 |
Left Alt |
KEY_FN |
0xFF |
— | Fn (M5Cardputer-specific) |
KEY_OPT |
0x00 |
— | Opt (M5Cardputer-specific) |
Special Keys
| Constant | Value | USB HID | Description |
|---|---|---|---|
KEY_BACKSPACE |
0x2A |
0x2A |
Backspace |
KEY_TAB |
0x2B |
0x2B |
Tab |
KEY_ENTER |
0x28 |
0x28 |
Enter |
SHIFT Flag
When set on a key code in _kb_asciimap[], the key requires Shift.
_kb_asciimap[128]
Maps ASCII characters to USB HID key codes. Used internally to populate KeysState.hid_keys. See src/utility/Keyboard/Keyboard_def.h for the full table.
Complete Usage Pattern
#include <M5Cardputer.h>
void setup() {
auto cfg = M5.config();
M5Cardputer.begin(cfg, true);
M5Cardputer.Display.setRotation(1);
}
void loop() {
M5Cardputer.update();
// Debounced: only process on state change
if (M5Cardputer.Keyboard.isChange()) {
if (M5Cardputer.Keyboard.isPressed()) {
M5Cardputer.Keyboard.updateKeysState();
auto& state = M5Cardputer.Keyboard.keysState();
// Print characters
for (char c : state.word) {
M5Cardputer.Display.print(c);
}
if (state.enter) M5Cardputer.Display.println();
if (state.del) {
// Implement backspace logic here
}
}
}
// Polling: continuous while held
if (M5Cardputer.Keyboard.isKeyPressed('r')) {
M5Cardputer.Display.fillScreen(TFT_RED);
}
}