Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ jobs:
target: esp32
- path: 'components/lsm6dso/example'
target: esp32s3
- path: 'components/m5stack-cardputer/example'
target: esp32s3
- path: 'components/m5stack-tab5/example'
target: esp32p4
- path: 'components/math/example'
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/upload_components.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ jobs:
components/logger
components/lp5817
components/lsm6dso
components/m5stack-cardputer
components/m5stack-tab5
components/math
components/matouch-rotary-display
Expand Down
7 changes: 7 additions & 0 deletions components/m5stack-cardputer/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# only register the component if the target is esp32s3
idf_component_register(
INCLUDE_DIRS "include"
SRC_DIRS "src"
REQUIRES driver esp_adc esp_driver_i2s fatfs base_component adc bmi270 display display_drivers i2c interrupt led math neopixel spi task
REQUIRED_IDF_TARGETS "esp32s3"
)
91 changes: 91 additions & 0 deletions components/m5stack-cardputer/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
menu "M5Stack Cardputer Configuration"

config M5STACK_CARDPUTER_INTERRUPT_STACK_SIZE
int "Interrupt stack size"
default 4096
help
Size of the stack allocated for the interrupt task.

config M5STACK_CARDPUTER_INTERRUPT_PRIORITY
int "Interrupt task priority"
default 20
range 0 25
help
Priority of the interrupt task.

config M5STACK_CARDPUTER_INTERRUPT_CORE_ID
int "Interrupt task core ID"
default -1
range -1 1
help
Core ID of the interrupt task. -1 means it is not pinned to any core.

config M5STACK_CARDPUTER_KEYBOARD_TASK_STACK_SIZE
int "Keyboard task stack size"
default 8192
help
Size of the stack allocated for the keyboard scanner task. Note
that the keypress callback runs in this task's context, so the
stack must be large enough for whatever the callback calls into
(e.g. LVGL).

config M5STACK_CARDPUTER_KEYBOARD_TASK_PRIORITY
int "Keyboard task priority"
default 0
range 0 25
help
Priority of the keyboard scanner task.

config M5STACK_CARDPUTER_KEYBOARD_TASK_CORE_ID
int "Keyboard task core ID"
default -1
range -1 1
help
Core ID of the keyboard scanner task. -1 means it is not pinned to
any core.

config M5STACK_CARDPUTER_AUDIO_TASK_STACK_SIZE
int "Audio task stack size"
default 4096
help
Size of the stack allocated for the audio (speaker) task.

config M5STACK_CARDPUTER_AUDIO_TASK_PRIORITY
int "Audio task priority"
default 19
range 0 25
help
Priority of the audio (speaker) task.

config M5STACK_CARDPUTER_AUDIO_TASK_CORE_ID
int "Audio task core ID"
default 1
range -1 1
help
Core ID of the audio (speaker) task. -1 means it is not pinned to
any core.

config M5STACK_CARDPUTER_MICROPHONE_TASK_STACK_SIZE
int "Microphone task stack size"
default 4096
help
Size of the stack allocated for the microphone task. Note that the
microphone callback runs in this task's context, so the stack must
be large enough for whatever the callback does with the audio data.

config M5STACK_CARDPUTER_MICROPHONE_TASK_PRIORITY
int "Microphone task priority"
default 19
range 0 25
help
Priority of the microphone task.

config M5STACK_CARDPUTER_MICROPHONE_TASK_CORE_ID
int "Microphone task core ID"
default 1
range -1 1
help
Core ID of the microphone task. -1 means it is not pinned to any
core.

endmenu
53 changes: 53 additions & 0 deletions components/m5stack-cardputer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# M5Stack Cardputer Board Support Package (BSP) Component

[![Badge](https://components.espressif.com/components/espp/m5stack-cardputer/badge.svg)](https://components.espressif.com/components/espp/m5stack-cardputer)

The M5Stack Cardputer (K132) and Cardputer ADV are card-sized computers based
on the ESP32-S3 StampS3 module, with a 56-key QWERTY keyboard, a 1.14" 240x135
IPS display, a mono speaker, a microphone, a micro-SD card slot, an IR
transmitter, a Grove port, and a WS2812 RGB LED.

The `espp::M5StackCardputer` component supports **both variants with the same
API**, detecting the board at runtime (see `variant()`), and provides a
singleton hardware abstraction for initializing and using the subsystems:

- **Display**: 1.14" 240x135 IPS TFT (ST7789V2) over SPI @ 40 MHz, with LVGL
integration via `espp::Display` and PWM backlight brightness control.
- **Keyboard**: on the original, the 56-key matrix (scanned through a 74HC138
3-to-8 demultiplexer) is polled by a scanner task; on the ADV the same 56
keys are read from the TCA8418 I2C keyboard controller's event FIFO. Either
way, a callback is invoked once per key state change with the key's matrix
position, resolved character (shift-aware), fn-layer special key (F1-F12,
arrows, esc, delete), and modifier state (fn / shift / ctrl / opt / alt).
- **Audio output**: mono speaker with `play_audio()`, runtime sample-rate
control, and software volume / mute. On the original the I2S stream drives
an NS4168 amplifier directly; on the ADV it goes through an ES8311 codec
(initialized automatically) into an NS4150B amplifier.
- **Microphone**: a recording task delivers 16-bit mono samples to a
callback. Original: SPM1423 PDM microphone; ADV: analog MEMS microphone via
the ES8311 codec's ADC.
- **uSD card**: SPI-mode micro-SD mounted at `/sdcard`.
- **RGB LED**: the StampS3's WS2812 via `espp::Neopixel`.
- **Battery**: battery voltage measurement (2:1 divider into ADC1) and an
estimated state of charge from a 1S lithium-ion discharge curve.
- **G0 (BOOT) button**: via `espp::Interrupt` with a callback.
- **IR transmitter / Grove port**: pin accessors for use with your own RMT /
I2C drivers.
- **IMU** (ADV only): the BMI270 on the internal I2C bus via
`initialize_imu()` / `imu()` (espp `bmi270` driver, with optional
orientation filter).
- **Internal I2C bus** (ADV only): accessor for the bus hosting the TCA8418
(0x34), ES8311 (0x18), and BMI270 (0x68).

> [!NOTE]
> The speaker and the microphone share I2S pins (GPIO 43 word-select / PDM
> clock on the original; the BCK/WS pair on the ADV), so they cannot be used
> at the same time; initializing one while the other is active will fail.
> This matches the boards' hardware design.

## Example

The [example](./example) shows how to use the `espp::M5StackCardputer` hardware
abstraction component to initialize the display (with a `Gui` class built on
LVGL), type text with the keyboard, play key-click sounds on the speaker, cycle
the RGB LED color, and monitor the battery voltage.
22 changes: 22 additions & 0 deletions components/m5stack-cardputer/example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.20)

set(ENV{IDF_COMPONENT_MANAGER} "0")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)

# add the component directories that we want to use
set(EXTRA_COMPONENT_DIRS
"../../../components/"
)

set(
COMPONENTS
"main esptool_py m5stack-cardputer"
CACHE STRING
"List of components to include"
)

project(m5stack_cardputer_example)

set(CMAKE_CXX_STANDARD 20)
62 changes: 62 additions & 0 deletions components/m5stack-cardputer/example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# M5Stack Cardputer Example

This example shows how to use the `espp::M5StackCardputer` hardware abstraction
component to initialize and use the components on the M5Stack Cardputer:

- The display (with LVGL, via a small `Gui` class that implements a
keyboard-driven text editor)
- The 56-key QWERTY keyboard (typing, shift layer, and the fn layer's arrow /
delete / esc keys)
- The speaker (a key-click beep for every keypress)
- The RGB LED (the G0 / BOOT button cycles its color)
- The uSD card (mounted at startup if inserted)
- The battery voltage / state-of-charge measurement (shown in the status bar)
- The IMU on the Cardputer ADV (live accelerometer / gyroscope readings shown
in the top-right corner)

## How to use example

### Controls

| Input | Action |
|-------|--------|
| Printable keys (with shift layer) | Type into the text area |
| Backspace / Enter / Tab | Edit the text area |
| Fn + `;` / `,` / `.` / `/` | Move the cursor (up / left / down / right) |
| Fn + backspace | Delete forward |
| Fn + `` ` `` | Clear the text area |
| Fn + 1 (F1) | Show / hide the controls help popup |
| Fn + 2 (F2) | Show / hide the IMU overlay (ADV) |
| Fn + number row | Show F1-F12 in the status bar |
| G0 (BOOT) button | Cycle the RGB LED color |

The controls are also printed to the log at startup.

The status bar at the bottom of the screen shows the most recent key /
modifier activity and is updated with the battery voltage every few seconds.

### Hardware Required

This example is designed to run on the M5Stack Cardputer (K132), with an
optional uSD card inserted.

### Build and Flash

Build the project and flash it to the board, then run monitor tool to view
serial output:

```
idf.py -p PORT flash monitor
```

(Replace PORT with the name of the serial port to use.)

(To exit the serial monitor, type ``Ctrl-]``.)

See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.

## Example Output

Serial output showing initialization of the subsystems, followed by log lines
for keyboard / button activity. The display shows the text editor with the
status bar along the bottom.
2 changes: 2 additions & 0 deletions components/m5stack-cardputer/example/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRC_DIRS "."
INCLUDE_DIRS ".")
Loading
Loading