Skip to content
Merged
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
85 changes: 85 additions & 0 deletions tasks/ESP-045.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
id: ESP-045
title: "Mini: one physical transport button on the Super Mini — press=play/stop, hold=realign"
status: todo
assignee: null
priority: high
tags:
- kitchensynctouch
- hardware
- transport
- product-v1
depends_on:
- ESP-043
- ESP-042
created_at: 2026-07-16
updated_at: 2026-07-16
---

## Why (the Mini's one live action needs to be physical)

The v1 product is the cheap MIDI-only "Mini" (headless S3 Super Mini, 1 DIN out, app for config).
The office-hours design locks **one physical button** as its live-performance surface: everything
else is the app, but *play/stop and realign must be a real button you can hit mid-set* without
reaching for a phone. Today the Super Mini has **no button** — transport comes only over
`/transport` + `/live` from the app. That's fine for config, not for performance.

The firmware is most of the way there and it is NOT new logic:

- `KitchenSyncTouch.ino` already has a `#ifdef HAS_BUTTONS` block (the ESP-025 bench rig): debounced
`Button` inputs post the SAME `TransportLaunchIntent` into the SAME `ktouch_transport` mailbox the
touch UI uses, so the 1 ms writer is identical — what the bench proved is what the Mini runs.
- `buttons.c` gives `button_reset` / `button_update` (debounce).
- Intents exist: `TL_INTENT_PLAY`, `TL_INTENT_STOP`, `TL_INTENT_REALIGN`.
- Status feedback already exists: **ESP-043** drives the onboard WS2812 (GPIO48) via
`ktouch_status_rgb` (dark stopped / amber armed / green running / cyan Link-locked). So the box
can already *show* armed — this ticket only adds the *input*.

So this is a **wiring + config-flag + one-button-gesture** job, not a new transport path.

## The gap vs. what exists

The bench `HAS_BUTTONS` block is **two** buttons (transport + realign) on **GPIO32/33** — a
classic-ESP32 DevKit pinout. The Mini is different in two ways:

1. **One button, two gestures.** Product decision: a single button. **Short press = play/stop**
(quantized, arms on the bar line), **hold (~600 ms) = realign**. Needs hold-detection on top of
`button_update` (short vs long press), which the bench two-button block does not have.
2. **S3 GPIOs, not classic-ESP32.** GPIO32/33 don't exist the same way; pick a **safe exposed S3
input**. Avoid: 0/3/45/46 (strapping), 19/20 (USB), 43/44 (UART0), **48 (onboard RGB — ESP-043)**,
**11 (DIN MIDI TX — `din_midi_out.h`)**. Use an exposed non-strapping pin with a real internal
pull-up, wired button→GND, `INPUT_PULLUP` (pressed = LOW), matching the bench convention.

## Scope

- Define `HAS_BUTTONS` (or a narrower `HAS_TRANSPORT_BUTTON`) for the **Super Mini** build in
`tools/build-supermini.sh` / `config.h`, without dragging in the two-button/LED-pin bench rig.
- Add a **single-button transport gesture**: debounce → short-press posts PLAY/STOP (toggle on
`ktouch_transport_state()`), long-press posts `TL_INTENT_REALIGN`. Keep the mailbox post exactly
as the bench does — never touch the wire from `loop()`; the writer fires on the grid.
- Status stays on the **onboard RGB (ESP-043)** — no new LED wiring for the plain-button build.
(If a ChromaTek 19mm WS2812 button is used instead, its LED can chain as pixel #2 off the WS2812
line and mirror the same `ktouch_status_rgb` — an enclosure-dependent option, not required here.)

## Acceptance criteria

- [ ] Short press on the Super Mini arms/stops transport (quantized), identical to an app
`/transport` PLAY/STOP — verified by the armed→running transition being the device's, not
client-predicted.
- [ ] Hold (~600 ms) posts a realign (`0xFC`+`0xFA` on the bar line), distinct from a short press.
- [ ] The chosen GPIO is a safe S3 input (not strapping/USB/UART0/48/11); button→GND + `INPUT_PULLUP`.
- [ ] Onboard RGB (ESP-043) reflects the resulting state (armed blink → running).
- [ ] Product build (Touch) unaffected: `HAS_BUTTONS`-for-Mini does not pull LED pins or the
two-button block into the Touch.
- [ ] A pure test for the short-vs-long gesture decision (mirror `test_status_rgb`) — the timing
threshold is logic, not glue.

## Notes

- Pairs with **ESP-021** (enclosure + panel-mount button + TRS out) — this is the firmware half of
the same "make the Mini a real box" story.
- Gesture grammar comes from the office-hours doc: press = play/stop, hold = realign. Keep it to
one button; more controls belong in the app or a later "Performance" tier (arcade buttons).
- The quantized-press blink is load-bearing (a press does nothing for up to a bar; without the
armed blink it reads as a dead button) — ESP-043 already provides it, which is why this ticket
is input-only.
Loading