Hardware
The firmware runs on any ESP32-S3 board with at least 4 MB of Octal PSRAM. The reference build targets the ESP32-S3-WROOM-1-N16R8 dev kit.
Bill of materials
The full, ordered-by-part-number list (with prices, retailers, and
required-vs-optional guidance) lives in
hardware/HARDWARE.md §3.
The table below is the one-page summary.
| # | Component | Part | Required? | Qty | ~Cost (USD) |
|---|---|---|---|---|---|
| 1 | MCU dev board | ESP32-S3-WROOM-1-N16R8 | Required | 1 | $5–$10 |
| 2 | Audio DAC (I²S out) | PCM5102A | Required | 1 | $2–$4 |
| 3 | I²S MEMS microphone | INMP441 | Required | 1 | $2–$5 |
| 4 | 2.4″ TFT display | ILI9341 (240×320, SPI) | Required | 1 | $4–$8 |
| 5 | 4×4 button matrix | 16 tactile switches | Required | 16 | $2–$4 |
| 5b | Modifier buttons | 7× 6 mm tactile switches | Required | 7 | < $1 |
| 7c | Rotary encoder | Alps EC11E (24 detents, click) | Required | 1 | $0.50–$1 |
| 7b | Analog knobs (10 kΩ lin.) | 2× panel-mount pots + knobs | Recommended | 2 | $1–$3 |
| 6 | Speaker | 4 Ω or 8 Ω, 0.5–3 W | Optional | 1 | $2–$5 |
| 7 | Class-D amp | MAX98357A (I²S) | Optional | 1 | $6–$10 |
| 8 | Battery | Li-ion 18650 3.7 V 2800 mAh | Recommended | 1 | $5–$12 |
| 9 | Battery charger | TP4056 module | Optional (only w/ battery) | 1 | $1 |
| 10 | Status LEDs | 2× 3 mm LED (REC + PLAY) | Recommended | 2 | < $1 |
| 11 | Jumper wires | Dupont F-F, 10 cm, 40-pin ribbon | Required | 1 strip | $1–$2 |
| 12 | Breadboard | 830 tie points | Optional (helpful) | 1 | $2–$5 |
Total cost: minimal build (1–5, 5b, 7c, 11) ≈ $16–$26;
with speaker + amp ≈ $25–$40; with battery ≈ $30–$45;
everything ≈ $35–$60.
See hardware/HARDWARE.md §3.1.
Pin map
All pins below are configured in
main/config.h. Edit there if your
board differs. Total in-use: 17 GPIOs + 2 ADC channels
(matrix 8 + modifiers 7 + encoder 3 + knobs 2 + I²S 6 + TFT 6 +
sync 2 + LEDs 2 − shared I²S bus). The full GPIO-budget
analysis lives in hardware/HARDWARE.md §8.4.
Two pins are reserved for future USB-MIDI: GPIO 20 (was Knob A; moved to GPIO 2) and GPIO 19 (was Sync IN; moved to GPIO 25). GPIO 2 is a strapping pin: it must be floating or HIGH at boot, otherwise the ESP32-S3 enters download-boot mode. Keep Knob A turned away from its minimum stop before power-cycling if you suspect a stuck bootloader.
Audio (PCM5102A + INMP441)
| DAC BCLK | GPIO9 |
| DAC LRCK | GPIO10 |
| DAC DIN | GPIO8 |
| Mic BCLK | GPIO15 |
| Mic LRCK | GPIO16 |
| Mic DOUT | GPIO17 |
2.4″ TFT (ILI9341 SPI)
| MOSI | GPIO6 |
| SCK | GPIO7 |
| CS | GPIO5 |
| DC | GPIO4 |
| RST | GPIO48 |
| BL (PWM) | GPIO47 |
Buttons — matrix + modifiers
23 buttons: 16 step buttons on a 4×4 scan matrix
(btn_id = BTN_STEP1 + row × 4 + col) plus 7 PO-33
modifier keys on their own GPIOs. Internal pull-ups everywhere.
| Matrix rows | GPIO35, 36, 37, 38 |
| Matrix cols | GPIO33, 34, 39, 40 |
| SOUND | GPIO11 |
| PATTERN | GPIO44 |
| BPM | GPIO13 |
| REC | GPIO41 |
| FX | GPIO12 |
| PLAY | GPIO42 |
| WRITE | GPIO43 |
Knobs (ADC)
Two 10 kΩ linear pots, read on ADC1 and debounced in software.
| Knob A | GPIO2 / ADC1_CH1 (was GPIO20; reserved GPIO20 for USB-MIDI) |
| Knob B | GPIO46 / ADC1_CH5 |
Sync + LEDs
| Sync OUT | GPIO18 |
| Sync IN | GPIO25 (was GPIO19; reserved GPIO19 for USB-MIDI) |
| LED REC | GPIO21 |
| LED PLAY | GPIO14 |
Rotary encoder (Alps EC11E)
24-detent vertical-mount encoder with click-switch. Phase A/B are consumed by ESP32-S3 PCNT unit 0; the click-switch is polled and debounced. Used by the sketch picker.
| Phase A | GPIO22 |
| Phase B | GPIO23 |
| Click-switch | GPIO24 |
Class-D amp (MAX98357A) + battery monitor
The MAX98357A shares the PCM5102A’s I²S bus (BCLK/LRCK/DIN = GPIO 9/10/8) — only one is driven at a time. Battery voltage is read via ADC1_CH3 on GPIO 4 (a 2:1 resistor divider halves the cell voltage into the ADC’s 3.3 V range).
| MAX98357A BCLK | GPIO9 (shared w/ DAC) |
| MAX98357A LRCK | GPIO10 (shared w/ DAC) |
| MAX98357A DIN | GPIO8 (shared w/ DAC) |
| Battery ADC | GPIO4 / ADC1_CH3 |
In v1 firmware the amp is not driven (F-031 ❌ missing); the battery monitor is optional and the ADC field is reserved.
Power
The firmware draws ~10 µA in deep sleep, so a 1500 mAh LiPo will last ~6 months on standby. Active power depends on which voice engine is running; expect 60–120 mA at moderate polyphony.
The 5-minute idle timer drops the chip into deep sleep automatically. Any button press wakes it back up — via a GPIO interrupt on the matrix column pins or on any of the seven modifier GPIOs.