Demo
Real screen captures, shown on the device. The firmware draws the same 135 × 240 screen in the desktop simulator and on hardware, so what you see here is exactly what ships.
Configuration
A brand is one config.yaml under brands/<id>/, in two groups: brand (identity) and device (what ships in firmware, the agent, and mood and alert rules). Anything left out is off. A brand only bakes in the packs, games, and rules it lists, keeping the image small.
config builderwrites the file for you, pick identity, packs and rules, then flash or download→
config referenceevery section explained in depth, with live examples to poke at→
Mascots don't have to come from the built-in packs. Any transparent PNG works as a custom mascot, and the mixer builds one from parts.
Build & flash
The config gets onto a device two ways. Flash it in the browser, or self-host the console with Docker. Same firmware, same result.
The config builder is one page with the whole flow. Build the config, plug the device in over USB, and flash it in one go. Nothing to install.
- Live yaml. Every pick updates the
config.yamlnext to the form. - Flash over USB. The
gooshiimage plus your selections as a config partition, custom theme palettes included. Chrome or Edge on desktop. - Or download. Drop the file into
brands/<id>/for the other paths.
The hub pairs over BLE and manages brands, rules, and flashing.
pip install -e hub/backend # once, Python 3.10+ make hub # pairs with your device over BLE
Or skip the bare install. The Docker tab runs the same hub and serves the full console in the browser.
One command runs the hub and serves the console. Devices, brand, rules, and flashing over USB.
make up # hub, console on http://localhost:8000 TAMA_PORT=9090 make up # port 8000 taken? serve it elsewhere
Development
For working on the project itself. Nothing here is needed for the two setups above.
System overview
The desktop simulator draws the same screen as hardware, so most work needs no board at all. It builds and runs locally from the PlatformIO project under firmware/.
make sim # build and run the simulator, offline
The firmware is a PlatformIO project under firmware/. Set the brand, then build and flash over USB. The build regenerates that brand's headers on its own. A brand id is a folder under brands/, and its config.yaml defines what the build includes.
Build and flash locally
A build carries only what the brand config lists. Optional device.persona bakes a name into the status bar. Long-press A on home opens its about screen.
cd firmware && TAMA_BRAND=<id> pio run -e m5sticks3 -t upload # build and flash that brand make brand TAMA_BRAND=<id> # optional: just generate headers into firmware/.gen/current
Build-time environment
| Variable | Purpose |
|---|---|
TAMA_BRAND | Which brand config to build (default gooshi). |
TAMA_TRANSPORTS | The set of link:protocol channels compiled into the firmware, e.g. ble:gatt. Overrides the brand's device.transports. |
MUSE_SDK_TOKEN | Muse SDK token, from the environment or the repo .env. Baked into builds with device.agent: muse. |
The hub is a Python package under hub/backend, with the console it serves in hub/console. The wire format is defined once per side, in hub/backend/src/wire and firmware/lib/wire.
The hub runs a brand too, so match it to what the device is flashed with. Set TAMA_BRAND=<id>, the same variable used everywhere else. It defaults to gooshi.
pip install -e hub/backend # once, Python 3.10+ make hub TAMA_BRAND=<id> # run it bare, pairs over BLE (defaults to gooshi) make logs # tail the Docker stack's hub logs make hub-test # hub unit tests
Runtime environment
| Variable | Purpose |
|---|---|
TAMA_BRAND | Which brand the hub runs (default gooshi). Match it to the device's flashed brand. |
TAMA_TRANSPORT | The single link:protocol channel the hub uses to reach the device, ble:gatt. |
TAMA_DEVICE_ID | Device identity. |
TAMA_BLE_NAME / TAMA_BLE_ADDRESS | Device to pair with. Defaults to the saved connection. |
TAMA_HUB_PORT | Console port (default 8000). |
Apps & games
Apps and games that can run on the device. Configuration: device.apps and device.games. Some games use IMU/mic for inputs.
HID mode
HID (Human Interface Device) apps (controller, media, clicker, jiggler, volume) require a matching HID mode on the device: gamepad, desk (media + keyboard + mouse), or off. Apps whose capability is not in the active mode are locked. Set the mode in the hub. After it saves, reboot the device, forget it on the host, and re-pair so the new HID descriptors apply.
On macOS, if Keyboard Setup Assistant appears for desk mode, dismiss it.
Gamepad
Separate from the games that run on-device in firmware. Enable the controller app in the config and the stick pairs as a Bluetooth gamepad.
- The stick is the gamepad. IMU tilt and buttons map to moves.
- IMU tester. Wireframe grid to verify the Bluetooth link before shipping a game.
- Anywhere a gamepad works. Browser games are one example. Anything that reads a BLE gamepad can drive off the stick.
Mascot Mixer
In-browser mascot generator. Outputs a six-frame image of expressions for mascot.custom.
- Six expressions. One pick per slot, recolored live, previewed in every device mood.
- Avatar or mascot. Download one frame or all six as one image.
- Config. Save the image next to
config.yaml, list it undermascot.custom.