# RLCD Audio Apps — Mp3Player & VoiceRecorder Fixes (2026-07-12) ## Context Waveshare RLCD 4.2" uses ES8311 DAC @0x18 + ES7210 mic ADC @0x40, MCLK=12.288MHz GPIO16, BCLK=9 WS=45 TX=8 RX=10 AMP=46 HIGH. Working reference: `MicroPython/test1/Screen/lib/audio_util.py` + `board_config.py` WAVESHARE_RLCD profile. ## Mp3Player Pitfalls ### 1. Task Stack & Priority - Default `xTaskCreate(..., 4096, 5)` → stack overflow under minimp3 + SD + I2S + LVGL. - Log: `i2s_alloc_dma_desc failed` sometimes masked as OOM, but also task crashes. - Fix: `6144, prio 6`. ### 2. taskYIELD Causing Repetition ```c // Before: decode one MP3 frame (1152 samples @16k = 72ms) then: taskYIELD(); // gives CPU to LVGL but DMA empties → repeats last buffer // After: remove YIELD, loop tight, let I2S write block (250ms timeout) drive pacing ``` - DMA 4x120 = 30ms total, smaller than frame time → underrun → repetition. Increased driver DMA to 6x160 (~60ms) + removed YIELD. ### 3. Sample Rate Assumptions - RLCD files in repo are 16k mono (faith-mysterious-garden/page001.mp3 31652 bytes, 16k 1ch). - `I2S configured: 16000 Hz, 1 channels` — must match ES8311 boot init that already programs 16k exact. - Reclock hook that rewrites ES8311 0x06/0x07/0x08 during I2S start causes pop. For 16k, skip entirely. - MCLK multiple: 16k*768=12.288MHz exact, 32k*384, 48k*256. Default SDK 256 gives 4.096MHz for 16k → robot sound. See `tactility-firmware/references/rlcd-audio-fix.md`. ## VoiceRecorder Pitfalls ### Mono vs Stereo for ES7210 Working MP: ```python i2s = I2S(1, sck=9, ws=45, sd=10, mode=I2S.RX, rate=16000, bits=16, format=I2S.STEREO) # then mono extract: for i in 0..n step 4: mono[j]=buf[i:i+2] ``` - ES7210 outputs stereo (2 mics) even if you want mono file. - VoiceRecorder previously requested `channel_right = NONE` (mono slot mode) → driver expects 1 slot but codec sends 2 → low pitch mic-like. - Fix: Request `channel_right=1` (STEREO), read `AUDIO_BUF_SIZE` (4096) stereo, downmix left channel in-place backward to avoid overwrite: ```c size_t mono_bytes = bytes_read/2; for(int src=bytes_read-4, dst=mono_bytes-2; src>=0; src-=4, dst-=2){ buf[dst]=buf[src]; buf[dst+1]=buf[src+1]; } fwrite(buf,1,mono_bytes,f); ``` - WAV header stays mono (1 ch, byterate 32000) – data correctly pitched. ### TDM vs STD - Other boards (m5stack-stackchan, tab5) use TDM 4-slot for ES7210 via `i2s_controller_set_rx_tdm_config`. - RLCD working MP uses STD stereo, not TDM. Keep STD for RLCD. TDM path DMA also needs reduction (was 8x512 → 4x120) or OOM. ## Firmware / Logging Interaction ### File Lock Flood `File.cpp:getLock()` logged `WARN File lock function not set!` on every `listDirectory()` – Tactility scans `/sdcard` every sec → 1Hz UART spam. - UART ISR at 115200 contends with I2S GDMA ISR → jitter → small noises. - Fix: once-only warning + listDir INFO→DEBUG. ### I2S Pin Logs `esp32_i2s: Configuring I2S pins...` logged INFO on every play → same jitter. - Fix: LOG_D. ### Verification Checklist - Play 16k mono MP3: no pop at start, no robot, no repetition. - Log after fix: no `File lock flood`, no `i2s_alloc_dma_desc failed`. - Record WAV, download, play on PC: 16k mono correct pitch, not low/mic-like. - Serial for voice: `I2S configured: 16000 Hz, 1 channels` for play, stereo read for record is internal. ## References - `tactility-firmware/references/rlcd-audio-fix.md` – GPIO5 conflict, correct pins, DMA OOM, MCLK, ES8311 reclock - MicroPython working code: `~/Projects/MicroPython/test1/Screen/lib/board_config.py` WAVESHARE_RLCD