0ae2ca6e8e
Custom I2S HAT for Pi Multi-FX Pedal — full hardware package: - KiCad project: schematic (kicad_sch), PCB layout (kicad_pcb), project file - Custom DT overlay: pcm1808-pcm5102-overlay.dts (no upstream overlay exists for PCM1808) - docs/hardware-bom.md: BOM (9.25 HAT + 1.75 with enclosure), wiring diagram, PCB design notes - docs/config-audio.md: DT overlay build, ALSA config, JACK integration, troubleshooting - scripts/install_hat.sh: One-command install + test suite (6 tests) - hardware/gerber/: JLCPCB fab instructions and assembly notes Circuit: Guitar input → TL072 preamp (gain ~20dB) → PCM1808 ADC → RPi I2S → PCM5102 DAC → RC filter → output jack I2S: BCLK/GPIO18, LRCLK/GPIO19, DIN/GPIO20, DOUT/GPIO21 Stacking header passes all 40 GPIO pins for footswitches/LEDs/display
294 lines
7.0 KiB
Markdown
294 lines
7.0 KiB
Markdown
# Audio Configuration — PCM1808+PCM5102 I2S HAT
|
||
|
||
> **HAT:** Custom PCM1808 ADC + PCM5102 DAC I2S audio HAT
|
||
> **RPi:** 4B, Raspberry Pi OS (Bookworm, 64-bit)
|
||
> **Kernel:** rpi-6.6.y (upstream Raspberry Pi kernel)
|
||
> **Last updated:** 2026-06-07
|
||
|
||
---
|
||
|
||
## Device Tree Overlay
|
||
|
||
The PCM1808 ADC has **no upstream overlay** in the rpi-6.6.y kernel tree. A custom overlay is provided at:
|
||
|
||
```
|
||
hardware/pcm1808-pcm5102-overlay.dts
|
||
```
|
||
|
||
### Build & Install
|
||
|
||
```bash
|
||
# Install device-tree-compiler if not present
|
||
sudo apt-get install device-tree-compiler
|
||
|
||
# Compile overlay
|
||
dtc -@ -I dts -O dtb -o pcm1808-pcm5102-overlay.dtbo \
|
||
hardware/pcm1808-pcm5102-overlay.dts
|
||
|
||
# Copy to boot overlays directory
|
||
sudo cp pcm1808-pcm5102-overlay.dtbo /boot/firmware/overlays/
|
||
# On older Pi OS: /boot/overlays/
|
||
```
|
||
|
||
This compiles to `/boot/firmware/overlays/pcm1808-pcm5102-overlay.dtbo`.
|
||
|
||
### Enable Overlay
|
||
|
||
Edit `/boot/firmware/config.txt` (or `/boot/config.txt` on older installs):
|
||
|
||
```ini
|
||
# ── Custom I2S HAT: PCM1808 ADC + PCM5102 DAC ─────────
|
||
dtoverlay=pcm1808-pcm5102-overlay
|
||
|
||
# Disable onboard audio to free I2S pins
|
||
dtparam=audio=off
|
||
|
||
# Optional: force I2S pins if overlay doesn't set them
|
||
# dtparam=i2s=on
|
||
```
|
||
|
||
### Verify Overlay Loads
|
||
|
||
```bash
|
||
# Check overlay is loaded
|
||
dmesg | grep -i "pcm1808\|pcm5102\|i2s"
|
||
|
||
# Check ALSA sees both devices
|
||
aplay -l
|
||
arecord -l
|
||
|
||
# Expected output for playback:
|
||
# card 0: pcm1808pcm5102hat [pcm1808-pcm5102-hat], device 0: ... []
|
||
# Subdevices: 1/1
|
||
|
||
# Expected output for capture:
|
||
# card 0: pcm1808pcm5102hat [pcm1808-pcm5102-hat], device 0: ... []
|
||
# Subdevices: 1/1
|
||
|
||
# Check /proc device tree
|
||
cat /proc/device-tree/sound/name # should show "pcm1808-pcm5102-hat"
|
||
```
|
||
|
||
---
|
||
|
||
## ALSA Configuration
|
||
|
||
### Default Card Setup
|
||
|
||
Create `/etc/asound.conf` (system-wide) or `~/.asoundrc` (per-user):
|
||
|
||
```conf
|
||
# ── PCM1808+PCM5102 I2S HAT ─────────────────────────
|
||
|
||
# Default playback device
|
||
pcm.!default {
|
||
type asym
|
||
playback.pcm {
|
||
type hw
|
||
card 0
|
||
device 0
|
||
}
|
||
capture.pcm {
|
||
type hw
|
||
card 0
|
||
device 0
|
||
}
|
||
}
|
||
|
||
# Hardware device aliases
|
||
pcm.i2s_playback {
|
||
type hw
|
||
card 0
|
||
device 0
|
||
}
|
||
|
||
pcm.i2s_capture {
|
||
type hw
|
||
card 0
|
||
device 0
|
||
}
|
||
|
||
# Software volume control (PCM1808/PCM5102 have no HW volume)
|
||
pcm.softvol_playback {
|
||
type softvol
|
||
slave.pcm "i2s_playback"
|
||
control {
|
||
name "Master Playback Volume"
|
||
card 0
|
||
}
|
||
min_dB -50.0
|
||
max_dB 0.0
|
||
}
|
||
|
||
# 48kHz upsampler for 44.1kHz sources (like YouTube/Spotify)
|
||
pcm.rate_convert {
|
||
type plug
|
||
slave {
|
||
pcm "softvol_playback"
|
||
rate 48000
|
||
format S24_3LE
|
||
channels 2
|
||
}
|
||
}
|
||
|
||
# Default: use rate conversion + softvol
|
||
pcm.!default {
|
||
type plug
|
||
slave.pcm "rate_convert"
|
||
}
|
||
|
||
# Control device
|
||
ctl.!default {
|
||
type hw
|
||
card 0
|
||
}
|
||
```
|
||
|
||
### Test Audio
|
||
|
||
```bash
|
||
# --- Playback test ---
|
||
# Sine wave at 440Hz (A4)
|
||
speaker-test -t sine -f 440 -l 1 -c 2
|
||
|
||
# Play a WAV file
|
||
aplay /usr/share/sounds/alsa/Front_Center.wav
|
||
|
||
# --- Capture test ---
|
||
# Record 3 seconds from ADC
|
||
arecord -d 3 -f cd -t wav test_record.wav
|
||
|
||
# Play back the recording
|
||
aplay test_record.wav
|
||
|
||
# --- Full loopback test ---
|
||
# Play tone while recording (connect DAC output to ADC input)
|
||
# Check latency: <10ms at 48kHz/128 frames
|
||
arecord -d 5 -f S24_3LE -r 48000 -c 2 loopback_test.wav &
|
||
speaker-test -t sine -f 440 -l 2
|
||
wait
|
||
aplay loopback_test.wav
|
||
```
|
||
|
||
---
|
||
|
||
## JACK Audio Configuration
|
||
|
||
The pedal DSP runs under JACK. The existing JACK config in `main.py` uses `hw:1,0` (USB). Swap to `hw:0,0` for I2S:
|
||
|
||
### JACK Start
|
||
|
||
```bash
|
||
# Kill PulseAudio (conflicts with JACK on RPi)
|
||
pulseaudio --kill
|
||
|
||
# Start JACK at 48kHz/128 frames (recommended target: ~5.3ms buffer)
|
||
jackd -R -d alsa \
|
||
-d hw:0,0 \
|
||
-r 48000 \
|
||
-p 128 \
|
||
-n 3
|
||
|
||
# For low-latency mode (risky, check xruns):
|
||
jackd -R -d alsa -d hw:0,0 -r 48000 -p 64 -n 2
|
||
```
|
||
|
||
### Update main.py Config
|
||
|
||
In `/home/oplabs/projects/pi-multifx-pedal/main.py`, change:
|
||
|
||
```python
|
||
# FROM (USB Audio):
|
||
# config = {
|
||
# "input_device": "hw:1,0",
|
||
# "output_device": "hw:1,0",
|
||
# }
|
||
|
||
# TO (I2S HAT):
|
||
config = {
|
||
"input_device": "hw:0,0", # PCM1808 ADC
|
||
"output_device": "hw:0,0", # PCM5102 DAC
|
||
"sample_rate": 48000,
|
||
"period_size": 128, # 2.6ms buffer
|
||
"num_periods": 3, # triple-buffered
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Integration with NAM DSP
|
||
|
||
The I2S HAT uses the **same block size** as the NAM DSP engine (256 samples):
|
||
|
||
| Parameter | Value | Note |
|
||
|-----------|-------|------|
|
||
| Sample rate | 48,000 Hz | Both JACK and NAM |
|
||
| Block size | 256 frames | NAM internal block |
|
||
| JACK period | 128 frames | 2 × periods per block |
|
||
| Round-trip (target) | <8ms | 128fr × 2 + codec delay + DSP |
|
||
|
||
At 48kHz/128 frames × 3 periods = ~8ms round-trip, well within the 10ms target for NAM DSP. The 256-sample NAM block fits exactly into 2 JACK periods.
|
||
|
||
---
|
||
|
||
## Troubleshooting
|
||
|
||
### No card 0 detected
|
||
|
||
```bash
|
||
# Check if I2S is enabled in pin controller
|
||
dmesg | grep -i i2s
|
||
|
||
# Check loaded overlays
|
||
vcgencmd get_config dtov
|
||
# Should show: pcm1808-pcm5102-overlay
|
||
|
||
# Rebuild overlay if kernel was updated
|
||
sudo dtc -@ -I dts -O dtb -o /boot/firmware/overlays/pcm1808-pcm5102-overlay.dtbo \
|
||
/home/oplabs/projects/pi-multifx-pedal/hardware/pcm1808-pcm5102-overlay.dts
|
||
```
|
||
|
||
### No capture device
|
||
|
||
PCM1808 has no upstream overlay — the custom overlay provides the `pcm1808` codec binding. If capture isn't showing:
|
||
|
||
```bash
|
||
# Verify the overlay node compiled
|
||
dtc -I dtb -O dts /boot/firmware/overlays/pcm1808-pcm5102-overlay.dtbo | grep -i pcm1808
|
||
|
||
# Check I2S pin muxing is correct
|
||
raspi-gpio get 18 19 20 21
|
||
# Expect: GPIO 18: level=0 func=ALT5 (I2S BCLK)
|
||
# GPIO 19: level=0 func=ALT5 (I2S LRCLK)
|
||
# GPIO 20: level=0 func=ALT5 (I2S DIN)
|
||
# GPIO 21: level=0 func=ALT5 (I2S DOUT)
|
||
```
|
||
|
||
### PCM5102 hiss
|
||
|
||
- Add 330Ω + 10µF RC filter on DAC output (R5, C10 in BOM)
|
||
- Ensure XSMT (pin 17) is pulled to 3.3V, not floating
|
||
- Check 3.3V rail noise with oscilloscope (<50mV ripple at audio frequencies)
|
||
|
||
### JACK xruns
|
||
|
||
- Increase period size: `-p 256` (5.3ms, safer)
|
||
- Increase num periods: `-n 3` (triple buffer)
|
||
- Isolate RPi 4B from USB power noise
|
||
- Check `cat /proc/asound/card0/pcm0p/sub0/status` for xrun count
|
||
|
||
---
|
||
|
||
## Pinout Reference
|
||
|
||
| Signal | BCM GPIO | Physical Pin | ALT Function | Direction |
|
||
|--------|----------|:------------:|:------------:|:---------:|
|
||
| BCLK | GPIO18 | Pin 12 | ALT5 (I2S) | RPi → HAT |
|
||
| LRCLK | GPIO19 | Pin 35 | ALT5 (I2S) | RPi → HAT |
|
||
| DIN | GPIO20 | Pin 38 | ALT5 (I2S) | HAT → RPi |
|
||
| DOUT | GPIO21 | Pin 40 | ALT5 (I2S) | RPi → HAT |
|
||
| 3.3V | — | Pins 1, 17 | Power | RPi → HAT |
|
||
| 5V | — | Pins 2, 4 | Power | RPi → HAT |
|
||
| GND | — | Pins 6, 9, 14, 25, 30, 34, 39 | Ground | — |
|
||
|
||
The I2S HAT uses a **stacking header** (2×20 female socket) to pass through all 40 GPIO pins so footswitches, LEDs, and display are accessible from the top of the HAT. |