Hardware
One development board and one expansion board, used as a pair. No additional modules and no soldering are required.
What is on the board
- ESP32-S3 N16R8: 16 MB of flash and 8 MB of octal PSRAM. The audio slots are allocated in PSRAM.
- ES8388: an audio codec with both an ADC and a DAC, configured over I2C and carrying samples over I2S.
- HT6872: a class-D amplifier wired bridge-tied, powered from 5 V, its CTRL pin enabled through a voltage divider.
- Two GMI6027P-56DB electret microphones, on the codec’s LIN1 and RIN1 inputs.
- A speaker on connector J1, driven by the amplifier.
Pin map
Taken from the firmware. The manufacturer’s schematic names the same signals from the codec’s point of view, so the data pins read reversed there; see the codec page.
| Signal | GPIO | Function |
|---|---|---|
| SW1 | 12 | button 1; hold to record |
| SW2 | 11 | button 2 |
| SW3 | 13 | button 3 |
| LED | 21 | blinks while a slot is chosen |
| I2C SDA | 14 | ES8388 control |
| I2C SCL | 47 | ES8388 control |
| I2S MCLK | 8 | codec master clock |
| I2S BCLK | 3 | bit clock |
| I2S LRCLK | 9 | word clock |
| I2S DOUT | 46 | ESP32 → ES8388 DSDIN (DAC) |
| I2S DIN | 10 | ES8388 ASDOUT → ESP32 (ADC) |
#define I2C_SDA_PIN 14 #define I2C_SCL_PIN 47 #define I2S_MCLK_PIN 8 #define I2S_BCLK_PIN 3 #define I2S_LRCLK_PIN 9 #define I2S_DOUT_PIN 46 #define I2S_DIN_PIN 10
Buttons and LED
Each button sits between its GPIO and ground, pulled up on the board through 100 kΩ, with a 100 nF capacitor across it. A pressed button therefore reads low. The firmware also enables the ESP32’s internal pull-up, so the input is defined on boards populated without the external resistor.
All three buttons are configured at once from a bit mask:
/* GPIOs */
gpio_config_t out_cfg = {
.pin_bit_mask = (1ULL << LED_PIN),
.mode = GPIO_MODE_OUTPUT,
};
gpio_config(&out_cfg);
gpio_set_level(LED_PIN, 0);
uint64_t btn_mask = 0;
for (int i = 0; i < NUM_SLOTS; i++)
btn_mask |= (1ULL << BTN_PIN[i]);
gpio_config_t btn_cfg = {
.pin_bit_mask = btn_mask,
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
};
gpio_config(&btn_cfg);Why the amplifier output is bridged
The HT6872 amplifies the difference between the codec’s two outputs rather than one output against ground, which doubles the voltage swing available from a 5 V supply. If both channels carry the same signal the difference is zero and the output is silent. The firmware sets I2S to mono on the left slot, which leaves ROUT1 at zero.
Audio parameters
16 kHz, 16-bit, mono. Three slots of up to 20 seconds each: 16000 × 2 bytes × 20 s = 640 000 B per slot. With the temporary recording buffer, peak allocation is 2 560 000 B against 8 MiB of PSRAM.
#define NUM_SLOTS 3
static const int BTN_PIN[NUM_SLOTS] = { 12, 11, 13 }; /* SW1, SW2, SW3 */
#define LONG_PRESS_MS 1000 /* tempo para ativar gravação */
/* =====================================================================
* Áudio
* ===================================================================== */
#define SAMPLE_RATE 16000
#define RECORD_MAX_SEC 20
#define MAX_SLOT_BYTES (SAMPLE_RATE * 2 * RECORD_MAX_SEC) /* ~640 KB */
#define CHUNK_BYTES 4096PSRAM is volatile: the three slots are lost when the board loses power. The firmware does not write audio to flash.