viniciusdias.tech

research

Assistive AAC device — technical documentation

Reference for building, maintaining and extending the device. The prototype records three phrases and plays each one back from its own button. It has no network stack: nothing leaves the board.

Behaviour

A short press on any button plays the phrase stored in that slot. Holding SW1 for one second or more starts recording, which continues while the button is held and stops at twenty seconds. After recording, the LED blinks for ten seconds while the firmware waits for a button to identify the destination slot; if no button is pressed, the recording is discarded.

SW1 curto ──→ toca o slot 1
SW1 ≥ 1s  ──→ grava enquanto segurar
                └─→ LED pisca, 10 s para escolher onde salvar
                      ├─ SW1 → slot 1
                      ├─ SW2 → slot 2
                      ├─ SW3 → slot 3
                      └─ nada → descarta
SW2       ──→ toca o slot 2
SW3       ──→ toca o slot 3

Block diagram

MIC1 MIC2 ESP32-S3 N16R8 PSRAM 8 MB 3 slots × 20 s 16 kHz · 16 bit ES8388 codec MCLK 8 · BCLK 3 LRCLK 9 I2S DIN · 10 I2S DOUT · 46 I2C · 14/47 LOUT1 / ROUT1 HT6872 bridged amp SPEAKER SW1 12 · SW2 11 · SW3 13 LED 21
Audio crosses the I2S bus in both directions on separate pins. I2C carries only the codec configuration, written once at boot. The microphones and the speaker are on the codec side.

Functions

The firmware is a single file, play_tone/main/main.c, 486 lines. There are no tasks beyond app_main and no interrupt handlers.

Function Role
es8388_write_reg writes one codec register over I2C
es8388_read_reg reads one codec register; used once to detect the codec
i2c_scan scans addresses 0x08–0x77 and logs the ones that answer
i2c_init configures I2C master at 100 kHz
es8388_init detects the codec and applies the register sequence
i2s_init creates the TX and RX channels, sets pins and format
any_btn_pressed true if any button reads low
wait_all_released blocks until all buttons are released
wait_any_btn waits for a button up to a timeout, blinking the LED; returns 0–2 or −1
playback_slot writes a slot to I2S and flushes the DMA buffer
do_record reads I2S into rec_buf while SW1 is held
assign_recording transfers rec_buf to a slot
app_main initialises GPIO, I2C, codec and I2S, then runs the polling loop

Memory

Audio buffers are allocated in PSRAM with MALLOC_CAP_SPIRAM. The figures below follow from SAMPLE_RATE 16000, two bytes per sample and RECORD_MAX_SEC 20.

Item Size Note
MAX_SLOT_BYTES 640 000 B one slot at maximum length: 16000 × 2 × 20
slot_data[0..2] 1 920 000 B three slots, allocated on first use
rec_buf 640 000 B temporary recording buffer, freed or transferred after each take
PSRAM 2 560 000 B / 8 MiB peak PSRAM use against the module’s capacity
chunk + silence 8 192 B two static 4 KB transfer buffers, in BSS rather than on the stack

Other pages

hardware
Boards, pin map, button wiring, amplifier output.
esp-idf
Framework choice, APIs used, build configuration, compiling and flashing.
codec
ES8388 driver: I2C access, register sequence, I2S configuration.
recording
Buffers, recording, slot assignment, playback, main loop, extension points.

Source

Firmware and the manufacturer’s original files: the project repository.