Skip to content

KeyboardReader & Implementations

Header: utility/Keyboard/KeyboardReader/KeyboardReader.h

The KeyboardReader is an abstract interface for reading physical key matrices. Two concrete implementations exist, selected automatically based on board type.


Point2D_t

struct Point2D_t {
    int x = 0;
    int y = 0;

    bool operator==(const Point2D_t& other) const;
};

Represents a physical key position on the keyboard matrix: - x — column index (0–13) - y — row index (0–3)


KeyboardReader (Abstract Base)

class KeyboardReader {
public:
    virtual ~KeyboardReader() = default;
    virtual void begin();
    virtual void update();
    const std::vector<Point2D_t>& keyList() const;
protected:
    std::vector<Point2D_t> _key_list;
};
Method Description
begin() Initialize hardware. Override in subclasses to configure GPIO / I2C.
update() Scan the key matrix and populate _key_list. Override in subclasses.
keyList() Returns the current list of pressed key coordinates.

IOMatrixKeyboardReader

Header: utility/Keyboard/KeyboardReader/IOMatrix.h
Used by: M5Cardputer (standard version)

GPIO matrix scanning implementation. Uses 3 output pins and 7 input pins to scan a 4-row × 7-column × 2 matrix (effectively 4×14 by time-division multiplexing).

Pin Assignments

Role Pins
Output (row select) 8, 9, 11
Input (column read) 13, 15, 3, 4, 5, 6, 7

How it works

  1. begin() — configures output pins as OUTPUT, input pins as INPUT_PULLUP.
  2. update() — iterates 8 steps (0–7), setting the 3-bit row address on the output pins, then reading 7 input pins. The first 4 steps map to columns x_1, the last 4 to columns x_2 (see X_map_chart). Detected key-downs are pushed into _key_list as Point2D_t.
class IOMatrixKeyboardReader : public KeyboardReader {
public:
    void begin() override;
    void update() override;
private:
    const std::vector<int> output_list = {8, 9, 11};
    const std::vector<int> input_list  = {13, 15, 3, 4, 5, 6, 7};
    const Chart_t X_map_chart[7];
    void set_output(const std::vector<int>& pinList, uint8_t output);
    uint8_t get_input(const std::vector<int>& pinList);
};

TCA8418KeyboardReader

Header: utility/Keyboard/KeyboardReader/TCA8418.h
Used by: M5Cardputer-ADV

I2C-based keyboard reader using the TCA8418 keypad matrix controller chip. Interrupt-driven: a GPIO ISR sets a flag when key events are available.

Hardware

Item Value
I2C Bus Internal (m5::In_I2C)
I2C Address 0x34
Interrupt Pin GPIO 11
Matrix Size 7 rows × 8 columns

How it works

  1. begin() — initializes the TCA8418 via I2C, configures a 7×8 matrix, attaches a CHANGE interrupt on GPIO 11.
  2. update() — called from the main loop. If the ISR flag is set, reads the key event from TCA8418's FIFO, remaps the row/column to match the M5Cardputer coordinate system, and updates _key_list (adds new presses, removes releases).
class TCA8418KeyboardReader : public KeyboardReader {
public:
    TCA8418KeyboardReader(int interrupt_pin = -1);
    void begin() override;
    void update() override;
private:
    struct KeyEventRaw_t { bool state; uint8_t row; uint8_t col; };
    std::unique_ptr<Adafruit_TCA8418> _tca8418;
    volatile bool _isr_flag;
    int _interrupt_pin;
    static void IRAM_ATTR gpio_isr_handler(void* arg);
};
Constructor Parameter Default Description
interrupt_pin -1 (auto → GPIO 11) Interrupt pin for key events

Adafruit_TCA8418 (Internal Driver)

Header: utility/Adafruit_TCA8418/Adafruit_TCA8418.h

Internal I2C driver for the TCA8418 chip, inherited from m5::I2C_Device. Adapted from Adafruit's library to use M5Unified's I2C abstraction. Typically only used internally by TCA8418KeyboardReader.

class Adafruit_TCA8418 : public m5::I2C_Device {
public:
    Adafruit_TCA8418(uint8_t i2c_addr = 0x34, uint32_t freq = 400000,
                     m5::I2C_Class* i2c = &m5::In_I2C);
    bool begin();
    bool matrix(uint8_t rows, uint8_t columns);
    uint8_t getEvent();
    uint8_t flush();
    void enableInterrupts();
    void disableInterrupts();
    // ... GPIO, debounce, and other control methods ...
};