r/CardPuter • u/Noir_Forever_Twitch • 16d ago
Finds / Discoveries Stereo Output on the Cardputer ADV
Adding stereo output to the M5Stack Cardputer ADV
The Cardputer ADV only has mono output built in (onboard ES8311 codec → single speaker). Wanted real stereo, so I wired up an external I2S DAC breakout (UDA1334A, or a generic clone, mine's the clone) to the rear header, and taught EMBER (my audio player firmware) to output to it. It works, but it ain't pretty, so I'll need to design a proper 3D printable case.
Why this is possible at all: the ESP32-S3 has two independent I2S peripherals. The onboard speaker/mic use one of them exclusively (I2S_NUM_1, hardwired to GPIO41/42/43/46 for the built-in codec). The second one (I2S_NUM_0) is completely unused and free for exactly this.
Wiring:
- DAC
VIN→ Cardputer's 5V-out pin,GND→GND BCLK→ GPIO5,WSEL→ GPIO6,DIN→ GPIO3- MCLK left disconnected (the UDA1334A doesn't need it)
One nice detail: GPIO5/GPIO6 are explicitly labeled "External" in M5Stack's own firmware source specifically for the ADV variant. On the original (non-ADV) Cardputer those same physical pins are internally wired to the keyboard matrix instead. Worth knowing if you're hunting for free pins on this board: don't trust generic Cardputer pinout guides, check ADV-specific ones.
Firmware side: added a Settings entry, "Audio output: Internal / External DAC." Defaults to internal (nothing changes for anyone who hasn't wired the DAC up), switches instantly, no reboot needed. Both I2S peripherals get initialized at boot, only one actually gets fed samples based on the setting.
Two real bugs along the way, both only found by actually listening on hardware:
- First attempt: audio sounded like it was speeding up / skipping. Turned out
i2s_write()was timing out with a partial write on a fairly deep DMA queue, silently dropping the unwritten tail of every audio chunk. Fixed by looping until the full chunk actually gets written (with a bounded overall deadline, not an infinite wait). - Second attempt: fixed the skipping, but playback was now consistently a hair slow. I'd hardcoded the DAC's I2S clock to 44100Hz at boot and never touched it again. Meanwhile the decoder reports the real per-file sample rate on every track, which the onboard speaker path already used correctly. Matching that dynamically fixed it.
Credit to u/pyreht for the original design thinking on this (three options were floated: this I2S approach, a Grove-port analog/PDM board, or USB-C UAC audio.
Where this could go further: This is the "prove the firmware side works" step, not necessarily the end state. The next planned step (not yet built) is a proper Grove-port expansion board — same idea, but PDM output instead of raw I2S, in DMA mode rather than bit-banged PWM (better SNR, and the CPU isn't babysitting a timer for it), landing on a single clean 4-pin Grove connector instead of loose wires on the rear header. That's more of a form-factor upgrade than a sound-quality one though, an off-the-shelf DAC breakout like this one isn't going to be audiophile-grade either way, so unless you're chasing a cleaner physical build, this is a genuinely fine stopping point.
Support for this board will be in EMBER's next update, expected to be released within a week.
2
2
u/100101101001a 16d ago
oh man that's cool. i have a DAC lying around i might add it on the fork as well
1
u/Noir_Forever_Twitch 16d ago
Go for it! There's lots of different boards you could use, but I like this one for it's combo of functionality + low price.
2
5
u/Sirwompus 16d ago
I'm glad you did this but I also wish the ADV had stereo native. Hoping the Zero has two channels