Skip to content

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

struct Keyboard_Class::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()

void 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()

void begin();

Auto-detects the board type and creates the appropriate KeyboardReader: - board_M5CardputerIOMatrixKeyboardReader (GPIO matrix) - board_M5CardputerADVTCA8418KeyboardReader (I2C/TCA8418)

This is called automatically by M5Cardputer.begin() — you normally don't need to call it yourself.


begin(reader)

void begin(std::unique_ptr<KeyboardReader> 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()

void updateKeyList();

Delegates to the active KeyboardReader to scan the physical matrix and refresh the pressed-key list. Called automatically by M5Cardputer.update().


keyList()

const std::vector<Point2D_t>& 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()

uint8_t 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()

bool 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)

bool isKeyPressed(char 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)

uint8_t getKey(Point2D_t 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)

KeyValue_t getKeyValue(const Point2D_t& 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()

void updateKeysState();

Scans all pressed keys and populates the KeysState buffer. This is a two-pass algorithm:

  1. Pass 1: Identify modifier keys (Fn, Opt, Ctrl, Shift, Alt)
  2. 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()

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()

bool capslocked(void);
void setCapsLocked(bool isLocked);

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

#define SHIFT 0x80

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);
    }
}