Pinout Reference
All assignments live in main/app_config.h; this table is generated from it by eyeball and kept in sync by review. Wiring order and pull-up guidance: wiring and assembly.
By function
| Function | Signal | GPIO | Notes |
|---|---|---|---|
| Audio (I2S) | BCLK | 38 | |
| LRC / WS | 39 | ||
| DIN | 40 | ||
| Amp SD / gain | 41 | Driven high to enable the MAX98357A | |
| SPI2 shared bus | MOSI | 13 | Display and SD share; silk SDA on both display modules |
| MISO | 11 | SD only; both supported displays are write-only | |
| SCLK | 12 | Display and SD share; silk CLK (ST7735S) or SCL (ST7789) | |
| Display (ST7735S or ST7789) | CS | 2 | Same pins for both panel options |
| DC | 16 | Data/command select; silk RS on the ST7735S red board, DC on the ST7789 | |
| RST | 21 | Silk RST (ST7735S) or RES (ST7789) | |
| Backlight | 18 | LEDC PWM, 5 kHz; BL on the ST7789. The ST7735S red board has no backlight pin (always on from VCC), so GPIO 18 is unused there | |
| SD card | CS | 5 | External 10 kΩ pull-up required |
| NFC + RTC (I2C) | SDA | 8 | Shared by PN532 and DS3231; 4.7 to 10 kΩ pull-ups |
| SCL | 9 | Shared bus, same pull-ups | |
| RTC (DS3231) | INT | 10 | Open drain, active low, pull-up required; deep sleep wake (ext1) |
| Encoder | A / CLK | 1 | Internal pull-up |
| B / DT | 7 | Internal pull-up | |
| Switch | 15 | Internal pull-up; deep sleep wake (ext1) | |
| Touch | Pad | 4 | Native touch channel TOUCH4 |
| Battery | Sense | 6 | ADC1 channel 5, behind the 100k/27k divider |
| Charge status | 17 | TP4056 CHRG, open drain, 10 kΩ pull-up, low = charging |
Free and RTC-capable: GPIO 14 (spare). Free but not wake-capable: 42, 47, 48.
Constraints that shaped the map
- GPIO19/20 are untouchable: they carry the native USB used for flashing and the serial console; this is why the classic VSPI pins were not an option and everything sits on SPI2.
- GPIO15 and GPIO10 form the wake mask: ext1 deep-sleep wake requires RTC-capable GPIOs (0 to 21 on the S3); the encoder switch and the DS3231 alarm are combined in one ANY_LOW mask (power). With the encoder unwired during bench work, GPIO15 floats and can wake the chip immediately; that is a loose-wire artifact, not a firmware bug.
- GPIO6 for battery sense: ADC1 rather than ADC2 because ADC2 conflicts with WiFi usage on ESP32-family chips.
- Strapping pins (0, 3, 45, 46) are left unconnected by this design on purpose; repurposing them invites boot-mode surprises.
- The touch pad wants GPIO with a native touch channel; 4 is one, and keeping it analog-quiet means routing it away from the SPI bus.