# 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. --- ## Focusrite Scarlett 2i2 — 4CM (Four Cable Method) > **Interface:** Focusrite Scarlett 2i2 (3rd gen) USB audio interface > **Mode:** `stereo_4cm` in `audio.mode` > **Device:** `hw:1,0` (USB card index, may vary) ### Wiring ``` Guitar ─────→ Input 1 (ADC channel 0) ─→ hw:1,0 capture_0 ─→ Pipeline input_0 Amp FX Send ─→ Input 2 (ADC channel 1) ─→ hw:1,0 capture_1 ─→ Pipeline input_1 Pipeline output_0 (pre-amp) ─→ Output 1 (DAC channel 0) ─→ hw:1,0 playback_0 ─→ Amp Input (Send) Pipeline output_1 (post-amp) ─→ Output 2 (DAC channel 1) ─→ hw:1,0 playback_1 ─→ Amp FX Return ``` ### JACK Config ```bash # Kill PulseAudio first — it grabs USB audio devices pulseaudio --kill # Start JACK at 48kHz/128 frames, 2 capture + 2 playback channels jackd -R -d alsa -d hw:1,0 -r 48000 -p 128 -n 3 -C 2 -P 2 ``` ### Application Config Set these fields in `~/.pedal/config.yaml`: ```yaml audio: hat_type: "focusrite_2i2_3gen" profile: "standard" mode: "stereo_4cm" input_device: "hw:1,0" output_device: "hw:1,0" jack_enabled: true auto_connect: true ``` ### Port Auto-Connect When `auto_connect: true` and mode is `stereo_4cm`, the system creates these JACK connections: | Source | Destination | Signal | |--------|-------------|--------| | `system:capture_1` | `fx_in:input_0` | Guitar → pre-amp DSP | | `system:capture_2` | `fx_in:input_1` | FX Send → post-amp DSP | | `fx_out:output_0` | `system:playback_1` | Pre-amp DSP → amp input | | `fx_out:output_1` | `system:playback_2` | Post-amp DSP → FX return | ### Channel Mapping Helper At runtime, call `AudioSystem.channel_mapping_help("stereo_4cm")` to get these mappings as structured data. ### Notes - The Focusrite 2i2 registers as ALSA card index **1** when the I2S HAT is card 0 (Linux arranges by driver probe order). If HDMI audio or other USB devices are present, the index may shift — use `aplay -l` / `arecord -l` to confirm. - 2-in/2-out at 24-bit/48kHz. JACK runs at 24-bit by default over ALSA. - At 48kHz/128 frames × 3 periods, round-trip latency is ~6-8ms — well within the 10ms target for real-time guitar DSP.