Cardputer Hub is an extensible firmware platform for the M5Stack Cardputer-Adv.
The project is designed as a small personal device platform built around reusable Services and independent Mini Apps.
The long-term goal is to support functionality such as:
- Bluetooth host control
- multiple paired devices
- Wi-Fi connectivity
- weather information
- VPS monitoring
- media controls
- RGB status indication
- microSD-backed file storage
- Telegram integration
- remote control through a Web UI
- additional Mini Apps and hardware extensions
The project is intentionally not designed as a single-purpose MacBook remote.
The primary dependency direction is:
Mini Apps
↓
Services
↓
Connectivity
↓
Hardware Adapters
The System Core provides shared infrastructure such as:
Application lifecycle
Launcher
App Registry
Navigation
Input routing
Action Bus
Configuration interfaces
Record and file-storage primitives
Logging
Capabilities
WeatherApp
↓
WeatherService
↓
WiFiService
↓
ESP32 Wi-Fi
Mini Apps should remain thin.
Reusable logic, state, integrations, and background behavior belong in Services.
Project documentation is the source of truth for architecture and engineering decisions.
Read:
docs/ARCHITECTURE.md— system architecture, Services, Mini Apps, connectivity, host management, remote control, and planned development phasesdocs/ENGINEERING.md— testing, CI/CD, build system, versioning, releases, and development requirementsdocs/UI_REQUIREMENTS.md— planned visual, motion, sound, display-power, and HID interaction rules for future UIdocs/manuals/— installation, supported features, device controls, and user-facing proceduresAGENTS.md— instructions for Codex and other coding agents working in this repository
Architectural changes should update the relevant documentation in the same pull request.
src/
├── core/
├── connectivity/
├── services/
├── apps/
├── hardware/
└── main.cpp
test/
docs/
├── ARCHITECTURE.md
├── ENGINEERING.md
├── UI_REQUIREMENTS.md
└── plans/
.github/
└── workflows/
scripts/
The empty apps, connectivity, and services directories reserve the
documented boundaries. No product behavior is implemented in the bootstrap.
The locked development environment uses:
- Python 3.12.14;
- uv 0.12.7;
- ESP-IDF 5.5.5 with its recommended compiler, CMake, and Ninja tools;
- PlatformIO Core 6.1.19 only for native host tests and static analysis;
- clang-format 23.1.0;
- a C++17 host compiler for native tests and C++17 project-owned firmware components;
- exact managed-component and Git-submodule dependency locks.
On macOS, install Git and the host compiler with Xcode Command Line Tools:
xcode-select --installOn Ubuntu or Debian Linux, install the native build prerequisites:
sudo apt-get update
sudo apt-get install --yes build-essential git curl wget flex bison gperf \
python3 python3-pip python3-venv ccache libffi-dev libssl-dev dfu-util \
libusb-1.0-0Install the repository's exact uv version using its versioned installer, then let uv install Python and the locked tools. Review downloaded installation scripts before running them when required by your environment's security policy.
curl -LsSf https://astral.sh/uv/0.12.7/install.sh | sh
uv python install 3.12.14
bash scripts/install_esp_idf.sh \
"$HOME/.espressif/frameworks/esp-idf-v5.5.5"
source "$HOME/.espressif/frameworks/esp-idf-v5.5.5/export.sh"
make setupThe locked virtual environment is local to the checkout; these commands do not replace the macOS system Python. Verify the resolved versions with:
uv --version
uv run --frozen python --version
uv run --frozen pio --version
uv run --frozen clang-format --version
idf.py --versionDo not install project-specific ESP32 or M5Stack libraries globally. The
ESP-IDF component manager resolves the exact production graph from
main/idf_component.yml and dependencies.lock; Git submodules retain the
exact pinned hardware-support sources. Re-source ESP-IDF's export.sh in each
new terminal before running firmware commands.
Follow the maintained
docs/manuals/installing-firmware.md
guide for prerequisites, USB installation, verification, and troubleshooting.
make buildThe production application and matching partition-table images are written to
build/cardputer_hub.bin and
build/partition_table/partition-table.bin. The version-controlled flash layout
keeps the framework's default NVS separate from the dedicated hub_config NVS
partition reserved for authoritative configuration records. On startup, the
firmware enters through native ESP-IDF, initializes M5Unified directly, writes
structured informational records for the product name, version, commit, and
build type to serial, and renders the product name and version as a minimal boot screen. Its update loop
refreshes the hardware and polls semantic keyboard input events. Those events
are intentionally not routed to product behavior yet, and no connectivity or
Mini Apps are started.
System Core also provides standalone navigation history, capability, and application-metadata registries plus record- and file-storage boundaries for later phases. The Cardputer microSD adapter compiles against the pinned board framework but is not constructed or mounted by the firmware runtime. These foundations do not provide Launcher, Mini App, file-browser, backup, or configuration import/export behavior.
The first Phase 2 foundation adds a hardware-independent Wi-Fi connection state machine and a compiled ESP32 station adapter. Neither is constructed by the firmware runtime yet: no credentials are compiled or persisted, no connection starts automatically, and the supported device behavior remains unchanged.
The Bluetooth lifecycle foundation similarly adds a hardware-independent single-peer state machine and a compiled direct ESP-NimBLE peripheral adapter. The same boundary now supports explicit authenticated pairing, stable opaque bond references, a 16-bond registry, selected-bond reconnection, explicit bond removal, and a shared hardware-neutral HID report contract. The direct ESP-NimBLE adapter exposes a secured keyboard and consumer-control HID service, accepts reports only for the selected authenticated and subscribed peer, and releases active reports before controlled disconnects. Bluetooth remains unconstructed at runtime and there is no pairing UI or Action-to-HID routing, so normal device behavior is unchanged.
Native tests run on the host and require no Cardputer hardware:
make testBehavior changes follow red-green-refactor TDD and should test observable behavior. The native suites cover stable firmware build metadata, log-level filtering, keyboard event translation and deduplication, opaque record-storage validation and forwarding, owned navigation history and Back traversal, dynamic capability registration and enumeration, owned application metadata validation and lookup, bounded logical file-storage operations, and System Core boot and update orchestration. They also cover Wi-Fi configuration validation, connection state, timeout and capped retry timing, connected-only and link-loss-safe RSSI access, disconnect-error propagation, and credential-free diagnostics. The Bluetooth suite covers side-effect-free construction, explicit lifecycle results, callback-event isolation, bonded single-peer policy, unbonded-peer rejection, pairing-window timing, all authenticated challenge modes, strict security completion, stable-reference finalization, capacity, target selection, bond deletion, reconnect timing, capped advertising backoff, fatal cleanup, stale event isolation, retained cleanup retries, and identity-free diagnostics. Peer-rejection coverage verifies that advertising cannot resume until all asynchronous disconnects for rejected peers have completed. The HID suites additionally cover neutral and six-key keyboard reports, consumer usages, invalid and duplicate usage rejection, selected-peer and dual subscription readiness, report ownership, retryable backpressure, neutral release, stale callbacks, controlled target changes, and clean re-enable.
Run formatting and static analysis separately with:
make format
make format-check
make lintBefore opening a pull request, run the complete CI-equivalent suite:
make checkmake check verifies the lock, formatting, Cppcheck analysis, native tests,
strict compiler warnings, and the Cardputer-Adv firmware build. make clean
removes ESP-IDF production build output. PlatformIO remains scoped to host-side
tests and analysis.
Connect the Cardputer-Adv with a USB-C cable that supports data, then run:
make uploadFor the first installation, or a one-time upgrade from the earlier flash
layout, use make migrate-storage-layout UPLOAD_PORT=<device> instead. The
explicit port ensures the upload and targeted erase reach the same Cardputer.
It provisions the new configuration range; routine upgrades must continue to
use make upload so stored configuration is preserved. See the
installation guide for the exact
migration and release-asset flashing procedure.
ESP-IDF's flash command normally resets the device automatically. If it cannot enter
download mode, hold the G0 button, press and release reset, release G0, and
retry the upload. You may need to grant access to the serial device on Linux.
make monitorThe configured baud rate is 115200. Exit the monitor with Ctrl+].
Pull requests targeting any branch, pushes to main, and manual CI runs execute
the make host-check and make firmware-check portions of make check in
parallel on Ubuntu 24.04. This includes stacked pull requests whose base is
another feature branch. A final required status succeeds only when both paths
pass. CI also uploads the compiled application and partition-table images as an
artifact retained for seven days. All third-party Actions use full commit SHA
pins, and Dependabot proposes reviewed updates.
After CI validates a merged pull request on main, the protected
Release firmware workflow uses the source branch prefix to assign the next
semantic version: major/ or breaking/ bumps major, feat/ or minor/ bumps
minor, and fix/, perf/, or patch/ bumps patch. Other branch types do not
release firmware. The first eligible release is v0.1.0. The workflow repeats
full validation, embeds release metadata, creates the version tag, and
publishes the application image, its matching partition-table image, and
SHA256SUMS covering both files.
Only the two newest GitHub Release records and their assets are retained. All
official Git tags are preserved. To rebuild an older version, manually run
Rebuild tagged firmware with its existing vMAJOR.MINOR.PATCH tag. That
read-only workflow checks out the tag and provides the application image,
partition table, and checksums as a temporary seven-day artifact; it does not
recreate or delete Releases or tags.
The primary local commands are:
make setup resolve locked repository and ESP-IDF dependencies
make build compile Cardputer-Adv firmware
make test run native tests
make format format owned C/C++ sources
make format-check verify formatting
make lint run static analysis
make host-check run lock, format, lint, and native test checks
make firmware-check
build and verify the production firmware
make check run all required validation
make upload compile and flash firmware
make migrate-storage-layout UPLOAD_PORT=<device>
one-time migration from the earlier flash layout
make monitor open the 115200-baud serial monitor
make clean remove ESP-IDF production build output
See docs/ENGINEERING.md for the complete workflow.
The Phase 1 System Core foundations are complete, and Phase 2 Connectivity is in progress with its Wi-Fi, Bluetooth lifecycle, authenticated pairing, and bond-management foundations plus the BLE keyboard/consumer HID transport delivered. These milestones establish testable contracts and hardware adapters; they do not make Wi-Fi, Bluetooth, or other planned product features user-visible. Native USB HID transport is the next Phase 2 foundation in the documented architecture order.
The authoritative development order is defined in
docs/ARCHITECTURE.md:
1. System Core
2. Connectivity
3. Core Services
4. Application Shell
5. Mini App Infrastructure
6. Device Manager
7. Host Control
8. Weather
9. RGB Indicator
10. Remote Boundary
11. Extensions
Product features should follow this order and the documented dependency direction.
Target device:
- M5Stack Cardputer-Adv
Planned external hardware:
- M5Stack Unit Puzzle 8×8 WS2812E RGB LED matrix
Additional sensors and modules may be added later.
License has not been selected yet.