dbf850c434
- M5 Unit Modules library + M5 Unit Test app - Minor fixes for TodoList, TwoEleven, Snake, Brainfuck and Breakout - Fixed SerialConsole to use the uart controller as it was broken in one of the many updates - Fixed keyboard input in TwoEleven, Breakout, Magic8Ball and Snake - Bluetooth Media Keys app, supports pressing physical keys to trigger the corresponding buttonmatrix button - Epub Reader app
341 lines
11 KiB
Markdown
341 lines
11 KiB
Markdown
# M5Unit Module References
|
||
|
||
Quick reference for all M5Stack units supported by the M5UnitModules library.
|
||
Each entry links to the official M5Stack docs and the upstream Arduino library.
|
||
|
||
---
|
||
|
||
## PaHub v2.1 (I2C Hub)
|
||
|
||
| Property | Value |
|
||
|---|---|
|
||
| Interface | I2C |
|
||
| I2C Address | 0x70 (default), configurable |
|
||
| Channels | 6 (CH0-CH5) |
|
||
| Driver class | `UnitPaHub` |
|
||
|
||
PCA9548A-based I2C multiplexer. Allows up to 6 I2C devices with the same
|
||
address to share a single bus. Select a channel before talking to a device
|
||
behind it; deselect (mask = 0) when done.
|
||
|
||
- Docs: https://docs.m5stack.com/en/unit/Unit-PaHub%20v2.1
|
||
- Repo: https://github.com/m5stack/M5Unit-HUB
|
||
|
||
**Register map:**
|
||
|
||
| Addr | Operation | Description |
|
||
|------|-----------|-------------|
|
||
| 0x70 | W: bitmask | Enable channels (bit i = channel i). Write 0x00 to deselect all. |
|
||
|
||
---
|
||
|
||
## CardKB2 (Keyboard)
|
||
|
||
| Property | Value |
|
||
|---|---|
|
||
| Interface | I2C (default) or UART |
|
||
| I2C Address | 0x5F |
|
||
| UART | 115200-8N-1, via GROVE port |
|
||
| MCU | STM32 |
|
||
| Driver class | `UnitCardKB2` |
|
||
|
||
Full QWERTY keyboard in a credit-card form factor. The STM32 firmware
|
||
auto-repeats keys (300 ms initial delay, 50 ms repeat). Mode switching
|
||
(I2C/UART/ESP-NOW/BLE-HID) is done via Fn+Sym+[1-4] and persists across
|
||
reboots.
|
||
|
||
- Docs: https://docs.m5stack.com/en/unit/Unit_CardKB2
|
||
- Repo: https://github.com/m5stack/M5Unit-KEYBOARD
|
||
|
||
**I2C protocol:** single I2C read (no register write) returns current key ASCII
|
||
value. 0x00 = no key or I2C error (indistinguishable by design).
|
||
|
||
**UART protocol:** 5-byte frames: `AA 03 [KEY_ID] [KEY_STATE] [checksum]`
|
||
- `KEY_ID` = row × 11 + col (0–43, rows 0–3, cols 0–10)
|
||
- `KEY_STATE` = 0x01 pressed, 0x02 released
|
||
- `checksum` = (0x03 + KEY_ID + KEY_STATE) & 0xFF
|
||
- The driver tracks Aa/Fn/Sym modifier state internally and translates KEY_ID to ASCII.
|
||
|
||
**Special keys:**
|
||
- `Aa` key: tap = one-shot uppercase, double-tap = caps lock
|
||
- `Sym` key: toggles symbol mode (Aa ineffective while active)
|
||
- `Fn+D/X/Z/C` = cursor up/down/left/right (0x1E/0x1F/0x1D/0x1C), `Fn+1` = Esc (0x1B)
|
||
|
||
**Mode behaviour for Fn combos:**
|
||
- **UART mode:** Fully supported. The firmware sends the raw KEY_ID in the UART frame; our driver translates it via `fnCombo()` to the private ASCII codes above.
|
||
- **I2C mode:** No output. The firmware's I2C slave queue only holds regular ASCII; Fn-combo presses route to the BLE HID path and are not queued for I2C reads.
|
||
- **BLE HID mode:** Standard USB HID keycodes (ESC=0x29, Up=0x52, Down=0x51, Left=0x50, Right=0x4F), mapped to `LV_KEY_*` by `BluetoothHidHost`.
|
||
|
||
---
|
||
|
||
## LCD Unit (Color LCD)
|
||
|
||
| Property | Value |
|
||
|---|---|
|
||
| Interface | I2C |
|
||
| I2C Address | 0x3E |
|
||
| MCU | ESP32-PICO (inside) |
|
||
| Display | ST7789V2, 135x240 IPS |
|
||
| Driver class | `UnitLcd` |
|
||
|
||
Internal ESP32 bridges I2C commands to the ST7789V2. Commands are
|
||
fire-and-forget (the ESP32 processes them asynchronously). For bulk pixel
|
||
writes, poll `bufferRemaining()` (register 0x09) to avoid overflow.
|
||
|
||
- Docs: https://docs.m5stack.com/en/unit/lcd
|
||
- M5GFX repo: https://github.com/m5stack/M5GFX
|
||
|
||
**Key commands:**
|
||
|
||
| Cmd | Bytes | Description |
|
||
|-----|-------|-------------|
|
||
| 0x22 | [brightness] | Set backlight (0=off, 255=max) |
|
||
| 0x36 | [rotation] | Set rotation (0=portrait, 1=landscape, 2=portrait flip, 3=landscape flip) |
|
||
| 0x6A | [x0][y0][x1][y1][hi][lo] | Fill rect with RGB565 inline |
|
||
| 0x62 | [x][y][hi][lo] | Draw pixel RGB565 |
|
||
| 0x42 | [pixels...] | Write raw RGB565 stream |
|
||
| 0x09 | (read 1 byte) | Buffer bytes remaining |
|
||
| 0x68 | [x0][y0][x1][y1] | Fill rect with stored colour |
|
||
|
||
Physical dimensions: 135 wide x 240 tall (portrait). Rotation 1/3 swaps to 240 wide x 135 tall.
|
||
Max I2C clock: 400 kHz.
|
||
|
||
---
|
||
|
||
## Scroll Unit (Encoder + LED)
|
||
|
||
| Property | Value |
|
||
|---|---|
|
||
| Interface | I2C |
|
||
| I2C Address | 0x40 |
|
||
| MCU | STM32 |
|
||
| Driver class | `UnitScroll` |
|
||
|
||
Single rotary encoder with push button and one RGB LED.
|
||
|
||
- Docs: https://docs.m5stack.com/en/unit/UNIT-Scroll
|
||
- Repo: https://github.com/m5stack/M5Unit-Scroll
|
||
|
||
**Register map:**
|
||
|
||
| Addr | R/W | Width | Description |
|
||
|------|-----|-------|-------------|
|
||
| 0x10 | R/W | int16_t | Absolute encoder value |
|
||
| 0x20 | R | uint8_t | Button state (0=pressed, 1=released - inverted!) |
|
||
| 0x30 | R/W | 4 bytes | LED: [index(0), R, G, B] |
|
||
| 0x40 | W | uint8_t | Write 1 to reset encoder to 0 |
|
||
| 0x50 | R | int16_t | Delta since last read (resets after read) |
|
||
| 0xFE | R | uint8_t | Firmware version |
|
||
| 0xFF | R/W | uint8_t | I2C address |
|
||
|
||
---
|
||
|
||
## Joystick 2 Unit
|
||
|
||
| Property | Value |
|
||
|---|---|
|
||
| Interface | I2C |
|
||
| I2C Address | 0x63 |
|
||
| MCU | STM32 |
|
||
| Driver class | `UnitJoystick2` |
|
||
|
||
Dual-axis thumbstick with push button and one RGB LED. 12-bit ADC resolution.
|
||
|
||
- Docs: https://docs.m5stack.com/en/unit/Unit-JoyStick2
|
||
- Repo: https://github.com/m5stack/M5Unit-Joystick2
|
||
|
||
**Register map (key registers):**
|
||
|
||
| Addr | R/W | Width | Description |
|
||
|------|-----|-------|-------------|
|
||
| 0x00 | R | uint8_t | X axis (8-bit, 0-255) |
|
||
| 0x01 | R | uint8_t | Y axis (8-bit, 0-255) |
|
||
| 0x02 | R | uint8_t | Button (0=pressed, 1=released) |
|
||
| 0x10 | R | int16_t | X axis 12-bit signed |
|
||
| 0x12 | R | int16_t | Y axis 12-bit signed |
|
||
| 0x20 | R/W | 3 bytes | LED [R, G, B] |
|
||
| 0xFE | R | uint8_t | Firmware version |
|
||
|
||
---
|
||
|
||
## Dual Button Unit
|
||
|
||
| Property | Value |
|
||
|---|---|
|
||
| Interface | GPIO |
|
||
| Signals | 2x digital input (active LOW) |
|
||
| Colors | Red (Button A), Blue (Button B) |
|
||
| Driver class | `UnitDualButton` |
|
||
|
||
Simple two-button unit. Both buttons are active-LOW (pressed = 0V). The
|
||
default GPIO pins depend on the Grove port used:
|
||
|
||
- Docs: https://docs.m5stack.com/en/unit/dual_button
|
||
- Repo: https://github.com/m5stack/M5Stack/tree/master/examples/Unit/DUAL_BUTTON
|
||
|
||
**Pin assignment (Port B):** GPIO varies by device. The driver takes pin
|
||
numbers at `begin()` - pass the actual GPIO numbers for the target hardware.
|
||
|
||
---
|
||
|
||
## 8Encoder Unit
|
||
|
||
| Property | Value |
|
||
|---|---|
|
||
| Interface | I2C |
|
||
| I2C Address | 0x41 |
|
||
| MCU | STM32 |
|
||
| Driver class | `Unit8Encoder` |
|
||
|
||
8 rotary encoders with push buttons, 8 individual RGB LEDs, one toggle switch,
|
||
and one RGB LED for the switch. Total 9 addressable LEDs.
|
||
|
||
- Docs: https://docs.m5stack.com/en/unit/8Encoder
|
||
- Repo: https://github.com/m5stack/M5Unit-8Encoder
|
||
|
||
**Register map (V1 firmware, 2022-11-08):**
|
||
|
||
| Addr | R/W | Width | Description |
|
||
|------|-----|-------|-------------|
|
||
| 0x00 + i*4 | R/W | int32_t | Absolute counter for encoder i (0-3) |
|
||
| 0x10 + i*4 | R/W | int32_t | Absolute counter for encoder i (4-7) |
|
||
| 0x20 + i*4 | R | int32_t | Delta for encoder i (0-3), resets after read |
|
||
| 0x30 + i*4 | R | int32_t | Delta for encoder i (4-7), resets after read |
|
||
| 0x40 + i | W | uint8_t | Write 1 to reset counter i (i = 0-7) |
|
||
| 0x50 + i | R | uint8_t | Button state for encoder i (0=released, 1=pressed) |
|
||
| 0x60 | R | uint8_t | Toggle switch state (0=off, 1=on) |
|
||
| 0x70 + i*3 | R/W | 3 bytes | LED [R, G, B] for encoder i (i = 0-7) |
|
||
| 0x88 | R/W | 3 bytes | LED [R, G, B] for toggle switch (LED8) |
|
||
| 0xF0 | R | uint8_t | Firmware version |
|
||
| 0xFF | R/W | uint8_t | I2C address |
|
||
|
||
Hardware counts 4 pulses per detent; the driver divides by 4 to give
|
||
detent-level deltas. Counter range: -2,147,483,648 to +2,147,483,647.
|
||
|
||
**LED indices in `Unit8Encoder`:** 0-7 = encoder LEDs, 8 = switch LED.
|
||
|
||
---
|
||
|
||
## ByteButton Unit
|
||
|
||
| Property | Value |
|
||
|---|---|
|
||
| Interface | I2C |
|
||
| I2C Address | 0x47 |
|
||
| MCU | STM32 |
|
||
| Driver class | `UnitByteButton` |
|
||
|
||
8 momentary buttons with individual RGB LEDs, each with independently
|
||
controllable brightness.
|
||
|
||
- Docs: https://docs.m5stack.com/en/unit/Unit%20ByteButton
|
||
- Repo: https://github.com/m5stack/M5Unit-ByteButton
|
||
|
||
**Register map:**
|
||
|
||
| Addr | R/W | Width | Description |
|
||
|------|-----|-------|-------------|
|
||
| 0x00 | R | uint8_t | All 8 buttons as bitmask (bit i = button i, 1=pressed) |
|
||
| 0x10 + i | R/W | uint8_t | LED brightness for button i (0-255) |
|
||
| 0x19 | R/W | uint8_t | LED show mode (0=user-defined, 1=system default) |
|
||
| 0x20 + i*4 | R/W | uint32_t | LED RGB colour (LE: bytes = [B, G, R, 0x00]) |
|
||
| 0x50 + i | R/W | uint8_t | LED colour RGB233 compressed |
|
||
| 0x60 + i | R | uint8_t | Individual button state (0=released, non-zero=pressed) |
|
||
| 0x70 + i*4 | R/W | uint32_t | System "off" colour for button i |
|
||
| 0x90 + i*4 | R/W | uint32_t | System "on" colour for button i |
|
||
| 0xFE | R | uint8_t | Firmware version |
|
||
| 0xFF | R/W | uint8_t | I2C address |
|
||
|
||
**LED colour format:** write `uint32_t 0x00RRGGBB` as little-endian - wire
|
||
sees [BB, GG, RR, 0x00]. Set show mode to 0 (user-defined) before
|
||
`setLed`/`flushLeds` to take effect.
|
||
|
||
---
|
||
|
||
## MIDI Unit / Synth Unit
|
||
|
||
| Property | Value |
|
||
|---|---|
|
||
| Interface | UART |
|
||
| Baud rate | 31250 bps, 8N1 |
|
||
| IC | SAM2695 |
|
||
| Polyphony | 64 voices (38 with effects) |
|
||
| Channels | 16 MIDI channels |
|
||
| Driver class | `UnitMidi` |
|
||
|
||
Both the MIDI Unit and Synth Unit use the SAM2695 connected via UART. Pass a
|
||
pre-opened `Uart` instance to `begin()`. The driver issues a system reset
|
||
(0xFF) on init.
|
||
|
||
- Synth Unit docs: https://docs.m5stack.com/en/unit/Unit-Synth
|
||
- MIDI Unit docs: https://docs.m5stack.com/en/unit/Unit-MIDI
|
||
- Repo: https://github.com/m5stack/M5Unit-Synth
|
||
|
||
**MIDI 1.0 message formats:**
|
||
|
||
| Message | Bytes | Description |
|
||
|---------|-------|-------------|
|
||
| 0x80\|ch | note, 0 | Note Off |
|
||
| 0x90\|ch | note, velocity | Note On (velocity 0 = Note Off) |
|
||
| 0xB0\|ch | controller, value | Control Change |
|
||
| 0xC0\|ch | program | Program Change |
|
||
| 0xE0\|ch | LSB, MSB | Pitch Bend (-8192 to +8191, centre = 0x2000) |
|
||
| 0xFF | - | System Reset |
|
||
| 0xB0\|ch | 123, 0 | All Notes Off (CC 123) |
|
||
|
||
**General MIDI program numbers (partial):**
|
||
|
||
| Range | Category |
|
||
|-------|----------|
|
||
| 0-7 | Piano |
|
||
| 8-15 | Chromatic Percussion |
|
||
| 24-31 | Guitar |
|
||
| 32-39 | Bass |
|
||
| 40-47 | Strings |
|
||
| 56-63 | Brass |
|
||
| 73-79 | Flute/Recorder/Pipe |
|
||
| 80-87 | Synth Lead |
|
||
| 88-95 | Synth Pad |
|
||
|
||
---
|
||
|
||
## RFID 2 Unit
|
||
|
||
| Property | Value |
|
||
|---|---|
|
||
| Interface | I2C |
|
||
| I2C Address | 0x28 |
|
||
| IC | MFRC522 (I2C mode) |
|
||
| Standards | ISO/IEC 14443 A/B, MIFARE |
|
||
| Frequency | 13.56 MHz |
|
||
| Driver class | `UnitRfid2` |
|
||
|
||
MFRC522 contactless card reader in I2C mode. Supports UID reading for MIFARE
|
||
Classic, MIFARE Ultralight, and ISO 14443-A cards.
|
||
|
||
- Docs: https://docs.m5stack.com/en/unit/rfid2
|
||
- MFRC522 I2C lib: https://github.com/kkloesener/MFRC522_I2C
|
||
|
||
**Notes:**
|
||
- The MFRC522 supports SPI, I2C, and UART; this unit hardwires I2C mode.
|
||
- UID length: 4 bytes (single-size) or 7 bytes (double-size) depending on card.
|
||
- Always check `readUID()` return length; 0 = no card present or read error.
|
||
|
||
---
|
||
|
||
## Driver Common Notes
|
||
|
||
All drivers use `UnitCommon.h` helpers:
|
||
|
||
- `unitProbe(dev, addr)` - checks for device ACK at address
|
||
- `unitReadReg(dev, addr, reg, buf, len)` - STM32-style: write reg byte, then read
|
||
- `unitWriteReg(dev, addr, reg, buf, len)` - write reg byte followed by data
|
||
- `UNIT_I2C_TIMEOUT_MS` = 20 ms default timeout
|
||
|
||
The STM32-based units (8Encoder, ByteButton, Scroll, Joystick2, CardKB2)
|
||
require a 2 ms delay between write (reg select) and read in some cases. This
|
||
is handled internally by the I2C controller driver.
|
||
|
||
When using the PaHub, always call `selectIfNeeded()` **before** `isPresent()`
|
||
to ensure the correct channel is active for the ACK check.
|