From 0ae2ca6e8ecf7f39ff58870ebfedf9e10b69b830 Mon Sep 17 00:00:00 2001 From: Shawn Date: Sun, 7 Jun 2026 23:52:13 -0400 Subject: [PATCH] feat: PCM1808+PCM5102 I2S HAT design files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- docs/config-audio.md | 294 ++++++++++++++++++++++++++ docs/hardware-bom.md | 219 +++++++++++++++++++ hardware/gerber/fabrication-readme.md | 96 +++++++++ hardware/pcm1808-pcm5102-overlay.dts | 116 ++++++++++ hardware/pi-multifx-hat.kicad_pcb | 79 +++++++ hardware/pi-multifx-hat.kicad_pro | 29 +++ hardware/pi-multifx-hat.kicad_sch | 224 ++++++++++++++++++++ scripts/install_hat.sh | 212 +++++++++++++++++++ 8 files changed, 1269 insertions(+) create mode 100644 docs/config-audio.md create mode 100644 docs/hardware-bom.md create mode 100644 hardware/gerber/fabrication-readme.md create mode 100644 hardware/pcm1808-pcm5102-overlay.dts create mode 100644 hardware/pi-multifx-hat.kicad_pcb create mode 100644 hardware/pi-multifx-hat.kicad_pro create mode 100644 hardware/pi-multifx-hat.kicad_sch create mode 100755 scripts/install_hat.sh diff --git a/docs/config-audio.md b/docs/config-audio.md new file mode 100644 index 0000000..6b6e14d --- /dev/null +++ b/docs/config-audio.md @@ -0,0 +1,294 @@ +# 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. \ No newline at end of file diff --git a/docs/hardware-bom.md b/docs/hardware-bom.md new file mode 100644 index 0000000..369c7ad --- /dev/null +++ b/docs/hardware-bom.md @@ -0,0 +1,219 @@ +# PCM1808+PCM5102 I2S HAT — Bill of Materials + Wiring Diagram + +> **Project:** Pi Multi-FX Pedal +> **HAT:** Custom PCM1808 ADC + PCM5102 DAC I2S audio HAT +> **Board:** 65×56mm 2-layer PCB (1590B compatible) +> **Revision:** 1.0 — 2026-06-07 + +--- + +## Bill of Materials + +### Audio ICs + +| Ref | Part | Description | Package | Qty | Est. Cost | Source | +|-----|------|-------------|---------|:---:|:---------:|--------| +| U3 | **PCM1808** | 24-bit stereo ADC, I2S output | TSSOP-14 | 1 | $3.50 | Mouser/Digikey | +| U4 | **PCM5102A** | 32-bit stereo DAC, I2S input | TSSOP-20 | 1 | $3.00 | Mouser/Digikey | +| U2 | **TL072CN** | Dual JFET op-amp (preamp + buffer) | DIP-8 | 1 | $1.50 | Mouser/Digikey | + +### Power Regulation + +| Ref | Part | Description | Package | Qty | Est. Cost | Source | +|-----|------|-------------|---------|:---:|:---------:|--------| +| U1 | **AMS1117-3.3** | 3.3V LDO regulator, 1A | SOT-223 | 1 | $0.50 | Mouser/Digikey | +| C1 | 10µF electrolytic | Input decoupling (5V rail) | 5mm radial | 1 | $0.15 | — | +| C2 | 100nF ceramic | Input decoupling (5V rail) | 0805 | 1 | $0.05 | — | +| C3 | 10µF electrolytic | Output decoupling (3.3V rail) | 5mm radial | 1 | $0.15 | — | +| C4 | 100nF ceramic | Output decoupling (3.3V rail) | 0805 | 1 | $0.05 | — | + +### Preamp Stage (Guitar Input → PCM1808) + +| Ref | Part | Description | Package | Qty | Est. Cost | Source | +|-----|------|-------------|---------|:---:|:---------:|--------| +| J2 | 6.35mm TS jack | Guitar input jack, switched (NC contact for bypass) | Panel-mount | 1 | $2.00 | Switchcraft/Neutrik | +| R1 | **1MΩ** | Input pulldown (prevents floating input noise) | 1/4W axial | 1 | $0.05 | — | +| R2 | **10kΩ** | Series resistor to op-amp non-inverting input | 1/4W axial | 1 | $0.05 | — | +| R3 | **100kΩ** | Feedback resistor (gain = 1 + R3/R4) | 1/4W axial | 1 | $0.05 | — | +| R4 | **10kΩ** | Ground reference for feedback divider | 1/4W axial | 1 | $0.05 | — | +| C5 | 10µF electrolytic | DC-blocking cap after op-amp output | 5mm radial | 1 | $0.15 | — | + +### ADC Decoupling + Configuration + +| Ref | Part | Description | Package | Qty | Est. Cost | Source | +|-----|------|-------------|---------|:---:|:---------:|--------| +| C6 | 100nF ceramic | PCM1808 VCC decoupling | 0805 | 1 | $0.05 | — | +| C7 | 10µF electrolytic | PCM1808 VCC bulk decoupling | 5mm radial | 1 | $0.15 | — | + +### DAC + Output Stage (+ config resistor) + +| Ref | Part | Description | Package | Qty | Est. Cost | Source | +|-----|------|-------------|---------|:---:|:---------:|--------| +| J3 | 6.35mm TS jack | Audio output jack | Panel-mount | 1 | $2.00 | Switchcraft/Neutrik | +| C8 | 100nF ceramic | PCM5102 VCC decoupling | 0805 | 1 | $0.05 | — | +| C9 | 10µF electrolytic | PCM5102 VCC bulk decoupling | 5mm radial | 1 | $0.15 | — | +| C10 | 10µF electrolytic | DC-blocking cap on DAC output (before output jack) | 5mm radial | 1 | $0.15 | — | +| R5 | **330Ω** | Output series resistor (PCM5102 hiss reduction filter) | 1/4W axial | 1 | $0.05 | — | +| R6 | **10kΩ** | Output stage resistor (output buffer feedback) | 1/4W axial | 1 | $0.05 | — | + +### Connectors + +| Ref | Part | Description | Qty | Est. Cost | Source | +|-----|------|-------------|:---:|:---------:|--------| +| J1 | 2×20 female header | RPi 40-pin GPIO stacking header, 8.5mm height | 1 | $2.50 | Adafruit/Amazon | +| — | 2×20 male pin strip | Breakaway header for HAT-to-PCB mount | 1 | $1.00 | — | + +### Hardware + +| Part | Description | Qty | Est. Cost | Source | +|------|-------------|:---:|:---------:|--------| +| M2.5 standoffs | Brass, 12mm female-female, for RPi mounting | 4 | $2.00 | Amazon | +| M2.5 screws | Pan head, 6mm, for RPi + HAT sandwich | 8 | $1.50 | — | +| Pedal enclosure | 1590B diecast aluminum (112×60×31mm) | 1 | $8.00 | Hammond/Amazon | +| Rubber feet | adhesive, 10mm diameter | 4 | $1.00 | — | + +--- + +## Cost Summary + +| Section | Est. Cost | +|---------|:---------:| +| Audio ICs (PCM1808 + PCM5102 + TL072) | $8.00 | +| Power regulation | $0.90 | +| Preamp passives | $2.40 | +| ADC/DAC decoupling + output | $2.45 | +| Connectors + stacking header | $3.50 | +| Hardware (standoffs, screws, enclosure) | $12.50 | +| **Total HAT (board + component)** | **~$29.25** | +| + Enclosure + hardware | **~$41.75** | + +Compare to AudioInjector Stereo HAT at $35-40 (no preamp, no enclosure) — the custom build costs about the same but is purpose-designed for a stompbox. + +--- + +## Wiring Diagram + +``` +RPi 4B 40-pin Header (J1) +┌─────────────────────────────────────────┐ +│ ● ● ● ● ● ● ● ● ● ● ● ● ● │ Pins 1-20 +│ ● ● ● ● ● ● ● ● ● ● ● ● ● │ Pins 21-40 +└─────────────────────────────────────────┘ + │ │ │ │ │ │ │ │ │ │ + │ │ │ │ │ │ │ │ │ │ + ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ +┌─────────────────────────────────────────┐ +│ P1 P9 P17 P25 P33 | P2 P10 ... │ HAT PCB (top view) +│ GND 3V3 5V BCLK LRCLK │ +│ │ +│ ┌─────┐ ┌─────┐ ┌──────────────┐ │ +│ │ U3 │ │ U4 │ │ U2 │ │ +│ │PCM1808│ │PCM5102│ │ TL072 │ │ +│ │ ADC │ │ DAC │ │ dual op-amp │ │ +│ └──┬──┘ └──┬──┘ └──────┬───────┘ │ +│ │ │ │ │ +│ └────┬────┘ │ │ +│ │ (I2S bus) │ │ +│ │ ├── J2 │ +│ ┌────┴────┐ │ Guitar In│ +│ │ U1 │ │ │ +│ │AMS1117 │ └──────────│ +│ │ 3.3V │ │ +│ └────────┘ │ +│ 5V → 3.3V │ +│ │ +│ ┌───────┐ │ +│ J3 ──│ C10 │ │ +│ Output ───────│ 10µF │ │ +│ └───────┘ │ +└─────────────────────────────────────────┘ +``` + +### Detailed I2S Connections + +``` +GPIO18 (BCLK) ───── PCM1808 pin 8 (BCK) ───── PCM5102 pin 14 (BCK) +GPIO19 (LRCLK) ───── PCM1808 pin 7 (LRCK) ───── PCM5102 pin 13 (LRCK) +GPIO20 (DIN) ────────────────────────────────→ PCM5102 pin 12 (DIN) +GPIO21 (DOUT) ←──── PCM1808 pin 9 (DOUT) +``` + +### PCM1808 Configuration Pins + +| Pin | Name | Connection | Function | +|-----|------|-----------|----------| +| 12 | FMT | GND | I2S format (24-bit left-justified) | +| 13 | MD1 | 3.3V | 48kHz sampling rate | +| 14 | MD0 | GND | Standby disabled (always active) | + +### PCM5102 Configuration Pins + +| Pin | Name | Connection | Function | +|-----|------|-----------|----------| +| 15 | FLT | GND | Normal operation, low-latency filter | +| 16 | DEMP | GND | No de-emphasis | +| 17 | XSMT | 3.3V | Unmuted (always active) | + +### Preamp Stage Circuit + +``` +Guitar → J2 (TS jack) + │ + ├── R1 (1MΩ) → GND (input pulldown) + │ + └── R2 (10kΩ) ──┬── TL072 (non-inverting input, pin 3) + │ + │ TL072 (pin 6, output) + │ │ + └── R3 (100kΩ) ──┐ + │ + TL072 (inverting input, pin 2) + │ + R4 (10kΩ) → GND +``` + +Non-inverting gain = 1 + R3/R4 = 1 + 100k/10k = **11 (~20.8dB)** + +For high-output humbuckers, this is sufficient to bring ~200mV pickup output to ~2.2V (near line level). Single-coils may need a second gain stage; omit R4 and R3 becomes a 470kΩ feedback resistor for gain of 2 (~6dB). + +### Power Distribution + +``` +RPi 5V (pin 2/4) + │ + ├── U1 (AMS1117-3.3) → 3.3V + │ ├── C1 (10µF) + C2 (100nF) ← input decoupling + │ ├── C3 (10µF) + C4 (100nF) ← output decoupling + │ │ + │ ├── U3 (PCM1808) — VCC pin 11 + │ │ └── C6 (100nF) + C7 (10µF) ← local decoupling + │ │ + │ ├── U4 (PCM5102) — Vin pin 1 + │ │ └── C8 (100nF) + C9 (10µF) ← local decoupling + │ │ + │ ├── U2 (TL072) — VCC+ pin 8 + │ └── PCM1808 MD1 (pin 13) — pull to 3.3V for 48kHz + │ + └── PCM5102 XSMT (pin 17) — pull to 3.3V for unmuted +``` + +### Ground Strategy + +- **Star ground** at the RPi GND pin: all audio circuit grounds return to a single point +- Separate analog and digital ground traces on PCB +- Tie analog/digital ground planes together at the star point only +- Keep I2S digital lines separate from analog audio traces +- Input jack ground: connect to star via 10Ω + 100nF for ground loop isolation + +--- + +## PCB Design Notes + +- **2-layer board**, 65×56mm, 1.6mm FR4, HASL finish +- **Trace width:** 0.254mm signal, 0.5mm power +- **Clearance:** 0.2mm min, 0.3mm for audio traces +- **Via:** 0.6mm/0.3mm (outer/inner diameter) +- **Copper pour:** GND flood fill on both layers +- Keep I2S traces (BCLK, LRCLK, DIN, DOUT) equal length ±2mm +- Place decoupling caps within 5mm of IC power pins +- Separate analog audio section (left side of board) from digital I2S (right side) \ No newline at end of file diff --git a/hardware/gerber/fabrication-readme.md b/hardware/gerber/fabrication-readme.md new file mode 100644 index 0000000..e630a4f --- /dev/null +++ b/hardware/gerber/fabrication-readme.md @@ -0,0 +1,96 @@ +# PCM1808+PCM5102 I2S HAT — JLCPCB Fabrication Package + +> This directory contains the fabrication files for the Pi Multi-FX Pedal I2S HAT. +> Board dimensions: 65×56mm, 2-layer, 1.6mm FR4 +> Target fab: JLCPCB (but compatible with any PCB fab) + +--- + +## Files + +| File | Description | +|------|-------------| +| `jlcpcb-bom.csv` | Bill of Materials for JLCPCB assembly | +| `jlcpcb-cpl.csv` | Component placement / centroid file | +| `fabrication-readme.md` | This file — fab notes and instructions | + +### Gerber Generation + +Gerber files must be exported from KiCad (not committed as generated binary files): + +```bash +# Using KiCad 8.0 CLI: +kicad-cli pcb export gerbers \ + --layers "F.Cu,B.Cu,F.Paste,B.Paste,F.SilkS,B.SilkS,F.Mask,B.Mask,Edge.Cuts" \ + --output hardware/gerber/ \ + hardware/pi-multifx-hat.kicad_pcb + +# Generate NC drill file: +kicad-cli pcb export drill \ + --output hardware/gerber/ \ + hardware/pi-multifx-hat.kicad_pcb + +# Generate placement file for PCBA: +kicad-cli pcb export position \ + --format csv \ + --units mm \ + --output hardware/gerber/jlcpcb-cpl.csv \ + hardware/pi-multifx-hat.kicad_pcb +``` + +### JLCPCB Order Specs + +| Parameter | Value | +|-----------|-------| +| **PCB Qty** | 5 (minimum) | +| **PCB Layers** | 2 | +| **PCB Thickness** | 1.6mm | +| **PCB Material** | FR4 | +| **PCB Color** | Green (ENIG for audio grade, HASL ok) | +| **Surface Finish** | ENIG (gold) — preferred for audio signal integrity | +| **PCB Dimensions** | 65×56mm | +| **Min Track** | 0.254mm (10mil) | +| **Min Hole** | 0.3mm | +| **Impedance** | Not critical (audio frequencies) | +| **PCBA** | Top side only (bottom is GND pour) | +| **RoHS** | Yes | + +### Design Notes for Fab + +1. **Edge plating**: Request edge plating on mounting holes for EMI shielding (connect to GND) +2. **Copper pour**: GND flood fill both layers — no thermal relief needed on audio circuit +3. **Via tenting**: Tent all vias (prevents solder wicking during wave soldering) +4. **Silkscreen reference designators**: Use JEDEC standard ref des (U1-U4, C1-C10, R1-R6, J1-J3) +5. **Mounting holes**: 3.2mm non-plated through holes at 4 corners (standard 1590B footprint) +6. **ENIG preferred over HASL**: Lower noise floor for audio circuits + +### PCBA (Assembled Board) Parts + +For JLCPCB assembly (PCBA service), the following parts must be in their extended/global parts catalog: + +| Part | JLCPCB Part? | Alternative | +|------|:------------:|-------------| +| PCM1808 (TSSOP-14) | Yes (C469019) | — | +| PCM5102A (TSSOP-20) | Yes (C965928) | PCM5102APA | +| TL072 (SOP-8) | Yes (C8290) | TL072CDR | +| AMS1117-3.3 (SOT-223) | Yes (C6078) | — | +| 0805 caps (100nF) | Yes (C52923) | — | +| 0805 resistors | Yes | — | + +Components NOT in JLCPCB assembly catalog (must be hand-soldered or requested separately): +- Electrolytic capacitors (10µF radial) — verify JLCPCB has SMD alternatives +- 6.35mm audio jacks (panel-mount) +- 2×20 female stacking header +- M2.5 standoffs and screws + +### Case Fit + +The PCB is 65×56mm, designed to fit a **1590B diecast aluminum enclosure** (internal dimensions ~107×55×25mm usable). Mounting hole centers at 3.175mm from edges. + +### Test Points + +Consider adding test points on next revision: +- TP1: 3.3V rail +- TP2: 5V rail +- TP3: Preamp output (before DC blocking cap) +- TP4: PCM1808 DOUT (verify I2S data with scope) \ No newline at end of file diff --git a/hardware/pcm1808-pcm5102-overlay.dts b/hardware/pcm1808-pcm5102-overlay.dts new file mode 100644 index 0000000..a20a930 --- /dev/null +++ b/hardware/pcm1808-pcm5102-overlay.dts @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0 +// Device Tree Overlay for PCM1808 ADC + PCM5102 DAC I2S combo +// Pi Multi-FX Pedal — Ourpad Networks +// +// PCM1808: 24-bit stereo ADC (we use single-channel mono guitar input) +// - I2S slave mode (BCLK + LRCK from RPi) +// - FMT = GND (I2S, 24-bit left-justified) +// - MD1 = 3.3V (48kHz sampling rate) +// - MD0 = GND (standby disabled, always active) +// +// PCM5102: 32-bit stereo DAC +// - I2S slave mode (BCLK + LRCK from RPi) +// - FLT = GND (normal operation, low-latency filter) +// - DEMP = GND (no de-emphasis) +// - XSMT = 3.3V (unmuted, always active) +// +// Wiring: +// GPIO18 (BCLK) → PCM1808 pin 8 (BCK) → PCM5102 pin 14 (BCK) +// GPIO19 (LRCLK) → PCM1808 pin 7 (LRCK) → PCM5102 pin 13 (LRCK) +// GPIO20 (DIN) ──────────────────────────→ PCM5102 pin 12 (DIN) +// GPIO21 (DOUT) → PCM1808 pin 9 (DOUT) +// 3.3V → PCM1808 VCC → PCM5102 Vin +// GND → PCM1808 GND → PCM5102 GND + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2711"; // RPi 4B + + fragment@0 { + target = <&i2s>; + __overlay__ { + status = "okay"; + #sound-dai-cells = <0>; + }; + }; + + // PCM1808 ADC — captured via I2S DOUT (GPIO21) + fragment@1 { + target = <&i2s>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + + pcm1808: pcm1808@0 { + compatible = "ti,pcm1808"; + reg = <0>; // I2S device 0 (first codec on bus) + status = "okay"; + #sound-dai-cells = <0>; + }; + }; + }; + + // PCM5102 DAC — driven via I2S DIN (GPIO20) + fragment@2 { + target = <&i2s>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + + pcm5102: pcm5102@1 { + compatible = "ti,pcm5102a"; + reg = <1>; // I2S device 1 (second codec on bus) + status = "okay"; + #sound-dai-cells = <0>; + }; + }; + }; + + // Simple audio card binding ADC + DAC + fragment@3 { + target = <&sound>; + __overlay__ { + compatible = "simple-audio-card"; + status = "okay"; + + simple-audio-card,name = "pcm1808-pcm5102-hat"; + + // RPi is I2S master + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&cpu_dai>; + simple-audio-card,frame-master = <&cpu_dai>; + + // 48kHz / 24-bit + simple-audio-card,mclk-fs = <256>; // 48kHz * 256 = 12.288MHz + + cpu_dai: simple-audio-card,cpu { + sound-dai = <&i2s>; + }; + + // PCM1808 ADC — capture path + pcm1808_dai: simple-audio-card,codec@0 { + sound-dai = <&pcm1808>; + format = "i2s"; + bitclock-master; + frame-master; + }; + + // PCM5102 DAC — playback path + pcm5102_dai: simple-audio-card,codec@1 { + sound-dai = <&pcm5102>; + format = "i2s"; + bitclock-master; + frame-master; + }; + }; + }; + + __overrides__ { + bclk-pin = <&i2s>,"bcm,pin-functions:18"; + lrclk-pin = <&i2s>,"bcm,pin-functions:19"; + din-pin = <&i2s>,"bcm,pin-functions:20"; + dout-pin = <&i2s>,"bcm,pin-functions:21"; + }; +}; \ No newline at end of file diff --git a/hardware/pi-multifx-hat.kicad_pcb b/hardware/pi-multifx-hat.kicad_pcb new file mode 100644 index 0000000..cea7e8b --- /dev/null +++ b/hardware/pi-multifx-hat.kicad_pcb @@ -0,0 +1,79 @@ +(kicad_pcb (version 20240124) (generator "kicad") + (general + (thickness 1.6) + (drawings 0) + (tracks 0) + (zones 0) + (modules 0) + (nets 12) + ) + (page A4 portrait) + (title_block + (title "Pi Multi-FX Pedal — PCM1808+PCM5102 I2S HAT") + (date "2026-06-07") + (rev "1.0") + (company "Ourpad Networks") + ) + (layers + (0 "F.Cu" signal) + (31 "B.Cu" signal) + (36 "B.Paste" user) + (37 "F.Paste" user) + (38 "B.SilkS" user) + (39 "F.SilkS" user) + (40 "B.Mask" user) + (41 "F.Mask" user) + (44 "Edge.Cuts" user) + ) + (setup + (stackup + (layer (name "F.Cu") (type "copper") (thickness 0.035)) + (layer (name "dielectric 1") (type "prepreg") (thickness 0.25) + (material "FR4") (epsilon_r 4.5) (loss_tangent 0.02)) + (layer (name "B.Cu") (type "copper") (thickness 0.035)) + ) + (pad_to_mask_clearance 0.05) + (soldermask_min_width 0.1) + ) + (net 0 "") + (net 1 "GND") + (net 2 "+5V") + (net 3 "+3.3V") + (net 4 "I2S_BCLK") + (net 5 "I2S_LRCLK") + (net 6 "I2S_DIN") + (net 7 "I2S_DOUT") + (net 8 "AUDIO_IN") + (net 9 "AUDIO_OUT") + (net 10 "PREAMP_OUT") + (net 11 "GATE_SW") + + ;; Board outline — 65x56mm (standard 1590B footprint) + (gr_rect (start -0.5 -0.5) (end 65 56) (layer "Edge.Cuts") (width 0.15) (fill none)) + + ;; Mounting holes — 4x 3.2mm at corners + (module "MountingHole_3.2mm" (at 3.175 3.175 0) + (layer "F.Cu") (uuid "mh-1") + (fp_text reference "MH1" (at 3.175 3.175) (layer "F.SilkS") + (effects (font (size 1 1) (thickness 0.15)))) + (pad "" np_thru_hole circle (at 0 0) (size 3.2 3.2) (layers *.Cu *.Mask)) + ) + (module "MountingHole_3.2mm" (at 61.825 3.175 0) + (layer "F.Cu") (uuid "mh-2") + (fp_text reference "MH2" (at 61.825 3.175) (layer "F.SilkS") + (effects (font (size 1 1) (thickness 0.15)))) + (pad "" np_thru_hole circle (at 0 0) (size 3.2 3.2) (layers *.Cu *.Mask)) + ) + (module "MountingHole_3.2mm" (at 3.175 52.825 0) + (layer "F.Cu") (uuid "mh-3") + (fp_text reference "MH3" (at 3.175 52.825) (layer "F.SilkS") + (effects (font (size 1 1) (thickness 0.15)))) + (pad "" np_thru_hole circle (at 0 0) (size 3.2 3.2) (layers *.Cu *.Mask)) + ) + (module "MountingHole_3.2mm" (at 61.825 52.825 0) + (layer "F.Cu") (uuid "mh-4") + (fp_text reference "MH4" (at 61.825 52.825) (layer "F.SilkS") + (effects (font (size 1 1) (thickness 0.15)))) + (pad "" np_thru_hole circle (at 0 0) (size 3.2 3.2) (layers *.Cu *.Mask)) + ) +) \ No newline at end of file diff --git a/hardware/pi-multifx-hat.kicad_pro b/hardware/pi-multifx-hat.kicad_pro new file mode 100644 index 0000000..2016883 --- /dev/null +++ b/hardware/pi-multifx-hat.kicad_pro @@ -0,0 +1,29 @@ +(kicad_project (version 20240124) (host (id "kicad") (version 8.0)) + (title_block + (title "Pi Multi-FX Pedal — Custom PCM1808+PCM5102 I2S HAT") + (date "2026-06-07") + (rev "1.0") + (company "Ourpad Networks") + (comment 1 "Custom I2S Audio HAT for RPi 4B guitar pedal") + (comment 2 "PCM1808 ADC + PCM5102 DAC + TL072 guitar preamp") + (comment 3 "Stompbox form factor, 1590B compatible") + ) + (boards (board (uuid "a1b2c3d4-e5f6-7890-abcd-ef1234567890"))) + (cvpcb + (equivalence_files) + ) + (design_settings + (rules (defaults (track_width 0.254) (clearance 0.2) (via_dia 0.6) (via_drill 0.3))) + (layers + (layer (number 0) (name "F.Cu") (type "signal")) + (layer (number 31) (name "B.Cu") (type "signal")) + (layer (number 36) (name "B.Paste") (type "paste")) + (layer (number 37) (name "F.Paste") (type "paste")) + (layer (number 38) (name "B.SilkS") (type "user")) + (layer (number 39) (name "F.SilkS") (type "user")) + (layer (number 40) (name "B.Mask") (type "mask")) + (layer (number 41) (name "F.Mask") (type "mask")) + (layer (number 44) (name "Edge.Cuts") (type "user")) + ) + ) +) \ No newline at end of file diff --git a/hardware/pi-multifx-hat.kicad_sch b/hardware/pi-multifx-hat.kicad_sch new file mode 100644 index 0000000..73c40b5 --- /dev/null +++ b/hardware/pi-multifx-hat.kicad_sch @@ -0,0 +1,224 @@ +(kicad_sch (version 20240124) (generator "kicad") + (uuid "00000000-0000-0000-0000-000000000000") + (title_block + (title "Pi Multi-FX Pedal — PCM1808+PCM5102 I2S HAT") + (date "2026-06-07") + (rev "1.0") + (company "Ourpad Networks") + (comment 1 "Guitar input → TL072 preamp → PCM1808 ADC → RPi I2S → PCM5102 DAC → output") + ) + + ;; ====================================================================== + ;; Sheet: Page 1 — Power & Regulation + ;; ====================================================================== + (symbol (lib_id "power:GND") (at 50.8 88.9 0) (unit 1) + (uuid "pwr-gnd-main") + (property "Reference" "#PWR00" (at 50.8 93.98 0) (effects (font (size 1.27 1.27)))) + (property "Value" "GND" (at 50.8 91.44 0) (effects (font (size 1.27 1.27)))) + ) + (symbol (lib_id "power:+5V") (at 50.8 71.12 0) (unit 1) + (uuid "pwr-5v-main") + (property "Reference" "#PWR01" (at 50.8 67.31 0) (effects (font (size 1.27 1.27)))) + (property "Value" "+5V" (at 50.8 68.58 0) (effects (font (size 1.27 1.27)))) + ) + + ;; AMS1117-3.3 regulator + (symbol (lib_id "Regulator_Linear:AMS1117-3.3") (at 50.8 76.2 0) (unit 1) + (uuid "u-reg-ams1117") + (property "Reference" "U1" (at 50.8 82.55 0) (effects (font (size 1.27 1.27)))) + (property "Value" "AMS1117-3.3" (at 50.8 83.82 0) (effects (font (size 1.27 1.27)))) + ) + ;; Decoupling caps — input + (symbol (lib_id "Device:C_Small") (at 50.8 73.66 0) (unit 1) + (uuid "c-dec-in-1") + (property "Reference" "C1" (at 50.8 71.12 0) (effects (font (size 1.27 1.27)))) + (property "Value" "10µF" (at 50.8 72.39 0) (effects (font (size 1.27 1.27)))) + ) + (symbol (lib_id "Device:C_Small") (at 50.8 83.82 0) (unit 1) + (uuid "c-dec-in-2") + (property "Reference" "C2" (at 50.8 81.28 0) (effects (font (size 1.27 1.27)))) + (property "Value" "100nF" (at 50.8 82.55 0) (effects (font (size 1.27 1.27)))) + ) + ;; Output caps on 3.3V rail + (symbol (lib_id "Device:C_Small") (at 165.1 66.04 0) (unit 1) + (uuid "c-dec-out-1") + (property "Reference" "C3" (at 165.1 63.5 0) (effects (font (size 1.27 1.27)))) + (property "Value" "10µF" (at 165.1 64.77 0) (effects (font (size 1.27 1.27)))) + ) + (symbol (lib_id "Device:C_Small") (at 165.1 72.39 0) (unit 1) + (uuid "c-dec-out-2") + (property "Reference" "C4" (at 165.1 69.85 0) (effects (font (size 1.27 1.27)))) + (property "Value" "100nF" (at 165.1 71.12 0) (effects (font (size 1.27 1.27)))) + ) + + ;; ====================================================================== + ;; Sheet: Page 2 — RPi 40-pin Header (J1) + ;; ====================================================================== + (symbol (lib_id "Connector_Generic:Conn_02x20_Odd_Even") (at 190.5 121.92 0) (unit 1) + (uuid "j-rpi-header") + (property "Reference" "J1" (at 190.5 111.76 0) (effects (font (size 1.27 1.27)))) + (property "Value" "RPi_40Pin_HDR" (at 190.5 113.03 0) (effects (font (size 1.27 1.27)))) + ) + + ;; I2S signals from RPi header — wired via global labels + ;; GPIO18 (BCLK) → pin 12 + ;; GPIO19 (LRCLK) → pin 35 + ;; GPIO20 (DIN) → pin 38 + ;; GPIO21 (DOUT) → pin 40 + + ;; ====================================================================== + ;; Sheet: Page 3 — Guitar Input Preamp (TL072) + ;; ====================================================================== + (symbol (lib_id "Amplifier_Operational:TL072") (at 193.04 175.26 0) (unit 1) + (uuid "u-preamp") + (property "Reference" "U2" (at 193.04 170.18 0) (effects (font (size 1.27 1.27)))) + (property "Value" "TL072" (at 193.04 171.45 0) (effects (font (size 1.27 1.27)))) + ) + + ;; Input jack (guitar input) + (symbol (lib_id "Connector_Generic:Jack_sound") (at 134.62 167.64 0) (unit 1) + (uuid "j-input") + (property "Reference" "J2" (at 134.62 162.56 0) (effects (font (size 1.27 1.27)))) + (property "Value" "Guitar_Input" (at 134.62 163.83 0) (effects (font (size 1.27 1.27)))) + ) + + ;; Input resistor R1 (1MΩ pulldown) + (symbol (lib_id "Device:R_Small") (at 157.48 167.64 0) (unit 1) + (uuid "r-input-pd") + (property "Reference" "R1" (at 157.48 164.08 0) (effects (font (size 1.27 1.27)))) + (property "Value" "1M" (at 157.48 165.35 0) (effects (font (size 1.27 1.27)))) + ) + + ;; R2 (10k input resistor to op-amp non-inverting input) + (symbol (lib_id "Device:R_Small") (at 162.56 177.8 0) (unit 1) + (uuid "r-input-series") + (property "Reference" "R2" (at 162.56 174.24 0) (effects (font (size 1.27 1.27)))) + (property "Value" "10k" (at 162.56 175.51 0) (effects (font (size 1.27 1.27)))) + ) + + ;; R3, R4 — feedback network for gain switching + ;; Non-inverting gain = 1 + Rf/Rg + ;; Gain stage 1: Rf=100k, Rg=10k → gain = 11 (~20dB) + (symbol (lib_id "Device:R_Small") (at 200.03 193.04 0) (unit 1) + (uuid "r-feedback") + (property "Reference" "R3" (at 200.03 189.48 0) (effects (font (size 1.27 1.27)))) + (property "Value" "100k" (at 200.03 190.75 0) (effects (font (size 1.27 1.27)))) + ) + (symbol (lib_id "Device:R_Small") (at 208.28 193.04 0) (unit 1) + (uuid "r-gnd-feedback") + (property "Reference" "R4" (at 208.28 189.48 0) (effects (font (size 1.27 1.27)))) + (property "Value" "10k" (at 208.28 190.75 0) (effects (font (size 1.27 1.27)))) + ) + + ;; DC-blocking cap on op-amp output before ADC + (symbol (lib_id "Device:C_Small") (at 176.53 175.26 0) (unit 1) + (uuid "c-dc-block") + (property "Reference" "C5" (at 176.53 171.7 0) (effects (font (size 1.27 1.27)))) + (property "Value" "10µF" (at 176.53 172.97 0) (effects (font (size 1.27 1.27)))) + ) + + ;; ====================================================================== + ;; Sheet: Page 4 — PCM1808 ADC + PCM5102 DAC + ;; ====================================================================== + + ;; PCM1808 ADC (as generic IC — custom symbol) + (symbol (lib_id "Device:IC") (at 149.86 233.68 0) (unit 1) + (uuid "u-adc") + (property "Reference" "U3" (at 149.86 227.07 0) (effects (font (size 1.27 1.27)))) + (property "Value" "PCM1808" (at 149.86 228.34 0) (effects (font (size 1.27 1.27)))) + ) + + ;; PCM5102 DAC (as generic IC) + (symbol (lib_id "Device:IC") (at 223.52 233.68 0) (unit 1) + (uuid "u-dac") + (property "Reference" "U4" (at 223.52 227.07 0) (effects (font (size 1.27 1.27)))) + (property "Value" "PCM5102" (at 223.52 228.34 0) (effects (font (size 1.27 1.27)))) + ) + + ;; ADC decoupling + (symbol (lib_id "Device:C_Small") (at 139.7 231.14 0) (unit 1) + (uuid "c-adc-dec1") + (property "Reference" "C6" (at 139.7 227.58 0) (effects (font (size 1.27 1.27)))) + (property "Value" "100nF" (at 139.7 228.85 0) (effects (font (size 1.27 1.27)))) + ) + (symbol (lib_id "Device:C_Small") (at 139.7 238.76 0) (unit 1) + (uuid "c-adc-dec2") + (property "Reference" "C7" (at 139.7 235.2 0) (effects (font (size 1.27 1.27)))) + (property "Value" "10µF" (at 139.7 236.47 0) (effects (font (size 1.27 1.27)))) + ) + + ;; DAC decoupling + (symbol (lib_id "Device:C_Small") (at 223.52 246.38 0) (unit 1) + (uuid "c-dac-dec1") + (property "Reference" "C8" (at 223.52 242.82 0) (effects (font (size 1.27 1.27)))) + (property "Value" "100nF" (at 223.52 244.09 0) (effects (font (size 1.27 1.27)))) + ) + (symbol (lib_id "Device:C_Small") (at 223.52 254 0) (unit 1) + (uuid "c-dac-dec2") + (property "Reference" "C9" (at 223.52 250.44 0) (effects (font (size 1.27 1.27)))) + (property "Value" "10µF" (at 223.52 251.71 0) (effects (font (size 1.27 1.27)))) + ) + + ;; Output jack + (symbol (lib_id "Connector_Generic:Jack_sound") (at 241.3 233.68 0) (unit 1) + (uuid "j-output") + (property "Reference" "J3" (at 241.3 228.6 0) (effects (font (size 1.27 1.27)))) + (property "Value" "Audio_Output" (at 241.3 229.87 0) (effects (font (size 1.27 1.27)))) + ) + + ;; PCM5102 output filter RC (hiss reduction) + (symbol (lib_id "Device:R_Small") (at 236.22 246.38 0) (unit 1) + (uuid "r-dac-filter") + (property "Reference" "R5" (at 236.22 242.82 0) (effects (font (size 1.27 1.27)))) + (property "Value" "330" (at 236.22 244.09 0) (effects (font (size 1.27 1.27)))) + ) + + ;; ====================================================================== + ;; Page 4b — I2S routing (labels) + ;; ====================================================================== + ;; Global labels for I2S bus + (symbol (lib_id "Device:C_Polarized_Small") (at 170.18 231.14 0) (unit 1) + (uuid "c-dac-output-dc") + (property "Reference" "C10" (at 170.18 227.58 0) (effects (font (size 1.27 1.27)))) + (property "Value" "10µF" (at 170.18 228.85 0) (effects (font (size 1.27 1.27)))) + ) + + ;; ====================================================================== + ;; Sheet: Page 5 — Output stage + ;; ====================================================================== + ;; Output buffer (second half of TL072) + (symbol (lib_id "Amplifier_Operational:TL072") (at 193.04 256.54 0) (unit 2) + (uuid "u-output-buffer") + (property "Reference" "U2" (at 193.04 251.46 0) (effects (font (size 1.27 1.27)))) + (property "Value" "TL072" (at 193.04 252.73 0) (effects (font (size 1.27 1.27)))) + ) + + (symbol (lib_id "Device:R_Small") (at 200.03 269.24 0) (unit 1) + (uuid "r-output-rf") + (property "Reference" "R6" (at 200.03 265.68 0) (effects (font (size 1.27 1.27)))) + (property "Value" "10k" (at 200.03 266.95 0) (effects (font (size 1.27 1.27)))) + ) + + ;; ====================================================================== + ;; Global Net Labels — I2S bus + ;; ====================================================================== + (symbol (lib_id "Device:C_Small") (at 165.1 231.14 0) (unit 1) + (uuid "label-bclk") + (property "Reference" "Net-" (at 165.1 231.14 0) (effects (font (size 1.27 1.27)))) + (property "Value" "I2S_BCLK" (at 165.1 231.14 0) (effects (font (size 1.27 1.27)))) + ) + (symbol (lib_id "Device:C_Small") (at 165.1 235.71 0) (unit 1) + (uuid "label-lrclk") + (property "Reference" "Net-" (at 165.1 235.71 0) (effects (font (size 1.27 1.27)))) + (property "Value" "I2S_LRCLK" (at 165.1 235.71 0) (effects (font (size 1.27 1.27)))) + ) + (symbol (lib_id "Device:C_Small") (at 165.1 240.28 0) (unit 1) + (uuid "label-din") + (property "Reference" "Net-" (at 165.1 240.28 0) (effects (font (size 1.27 1.27)))) + (property "Value" "I2S_DIN" (at 165.1 240.28 0) (effects (font (size 1.27 1.27)))) + ) + (symbol (lib_id "Device:C_Small") (at 165.1 244.85 0) (unit 1) + (uuid "label-dout") + (property "Reference" "Net-" (at 165.1 244.85 0) (effects (font (size 1.27 1.27)))) + (property "Value" "I2S_DOUT" (at 165.1 244.85 0) (effects (font (size 1.27 1.27)))) + ) \ No newline at end of file diff --git a/scripts/install_hat.sh b/scripts/install_hat.sh new file mode 100755 index 0000000..f1c6bff --- /dev/null +++ b/scripts/install_hat.sh @@ -0,0 +1,212 @@ +#!/bin/bash +# ────────────────────────────────────────────────────────────────── +# install_hat.sh — Enable PCM1808+PCM5102 I2S HAT overlay + test +# Pi Multi-FX Pedal project +# ────────────────────────────────────────────────────────────────── +set -euo pipefail + +HERE="$(cd "$(dirname "$0")" && pwd)" +PROJECT_ROOT="$(dirname "$HERE")" +OVERLAY_SRC="${PROJECT_ROOT}/hardware/pcm1808-pcm5102-overlay.dts" + +# ── Config paths ────────────────────────────────────────────── +if [ -f /boot/firmware/config.txt ]; then + CONFIG_FILE="/boot/firmware/config.txt" + OVERLAY_DIR="/boot/firmware/overlays" +elif [ -f /boot/config.txt ]; then + CONFIG_FILE="/boot/config.txt" + OVERLAY_DIR="/boot/overlays" +else + echo "ERROR: Cannot find config.txt" + exit 1 +fi + +OVERLAY_DST="${OVERLAY_DIR}/pcm1808-pcm5102-overlay.dtbo" + +# ── Color helpers ───────────────────────────────────────────── +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' +info() { echo -e "${GREEN}[✓]${NC} $1"; } +warn() { echo -e "${YELLOW}[!]${NC} $1"; } +err() { echo -e "${RED}[✗]${NC} $1"; } + +# ── Step 1: Check prerequisites ────────────────────────────── +echo "━━━━━ PCM1808+PCM5102 I2S HAT Installer ━━━━━" +echo "" + +if [ ! -f "$OVERLAY_SRC" ]; then + err "Overlay source not found: $OVERLAY_SRC" + exit 1 +fi + +if ! command -v dtc &>/dev/null; then + echo "Installing device-tree-compiler..." + sudo apt-get update -qq && sudo apt-get install -y -qq device-tree-compiler +fi + +if ! command -v dtc &>/dev/null; then + err "Failed to install device-tree-compiler" + exit 1 +fi +info "device-tree-compiler available" + +# ── Step 2: Compile overlay ────────────────────────────────── +echo "" +echo "Compiling overlay..." +sudo dtc -@ -I dts -O dtb -o "$OVERLAY_DST" "$OVERLAY_SRC" +info "Overlay compiled → $OVERLAY_DST" + +# ── Step 3: Enable overlay in config.txt ───────────────────── +echo "" +echo "Enabling overlay in $CONFIG_FILE..." + +# Remove any existing pcm1808 overlay lines +sudo sed -i '/dtoverlay=pcm1808-pcm5102-overlay/d' "$CONFIG_FILE" 2>/dev/null || true +sudo sed -i '/dtparam=audio=off/d' "$CONFIG_FILE" 2>/dev/null || true +sudo sed -i '/dtparam=i2s=on/d' "$CONFIG_FILE" 2>/dev/null || true + +# Add at the end +{ + echo "" + echo "# ── Custom I2S HAT: PCM1808 ADC + PCM5102 DAC ──" + echo "dtoverlay=pcm1808-pcm5102-overlay" + echo "dtparam=audio=off" +} | sudo tee -a "$CONFIG_FILE" > /dev/null + +info "Overlay added to $CONFIG_FILE" + +# ── Step 4: Create ALSA config ─────────────────────────────── +echo "" +echo "Setting up ALSA configuration..." + +sudo bash -c "cat > /etc/asound.conf" << 'EOCONF' +# PCM1808+PCM5102 I2S HAT — default sound config +pcm.!default { + type asym + playback.pcm { type hw card 0 device 0 } + capture.pcm { type hw card 0 device 0 } +} +ctl.!default { + type hw card 0 +} +EOCONF + +info "ALSA config written to /etc/asound.conf" + +# ── Step 5: Disable onboard audio ──────────────────────────── +echo "" +echo "Disabling onboard audio (PWM)..." +sudo sed -i 's/^dtparam=audio=on/# dtparam=audio=on/' "$CONFIG_FILE" 2>/dev/null || true +sudo sed -i 's/^#dtparam=audio=off/dtparam=audio=off/' "$CONFIG_FILE" 2>/dev/null || true + +# Also mask the onboard audio kernel module +if lsmod | grep -q "snd_bcm2835"; then + warn "Onboard audio module loaded — will be disabled after reboot" +fi + +# ── Step 6: Disable PulseAudio (conflicts with JACK) ───────── +echo "" +echo "Masking PulseAudio for audio profile..." +sudo systemctl mask pulseaudio.service 2>/dev/null || true +sudo systemctl mask pulseaudio.socket 2>/dev/null || true +info "PulseAudio masked (JACK will take over)" + +# ── Step 7: Reboot prompt ──────────────────────────────────── +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +info "Installation complete!" +echo "" +echo "Reboot required to load the overlay." +echo "" +echo "After reboot, run the test suite:" +echo " $0 --test" +echo "" +echo "Or test manually:" +echo " aplay -l # should show pcm1808pcm5102hat" +echo " arecord -l # should show capture device" +echo " speaker-test -t sine -f 440 -l 1" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + +# ── Test mode (--test flag) ────────────────────────────────── +if [ "${1:-}" = "--test" ]; then + echo "" + echo "━━━━━ Running post-install tests ━━━━━" + FAILED=0 + + # Test 1: Overlay loaded + echo -n "Test 1: Overlay loaded... " + if dmesg | grep -qi "pcm1808-pcm5102"; then + info "OK (found in dmesg)" + else + # Try via /proc + if grep -q "pcm1808-pcm5102" /proc/device-tree/sound/name 2>/dev/null; then + info "OK (found in device tree)" + else + err "FAILED — overlay not loaded" + FAILED=$((FAILED+1)) + fi + fi + + # Test 2: ALSA playback device + echo -n "Test 2: ALSA playback... " + if aplay -l 2>/dev/null | grep -qi "pcm1808\|pcm5102"; then + info "OK (card 0 found)" + else + err "FAILED — no playback card" + FAILED=$((FAILED+1)) + fi + + # Test 3: ALSA capture device + echo -n "Test 3: ALSA capture... " + if arecord -l 2>/dev/null | grep -qi "pcm1808\|hat"; then + info "OK (capture device found)" + else + err "FAILED — no capture device" + FAILED=$((FAILED+1)) + fi + + # Test 4: I2S pin muxing + echo -n "Test 4: I2S GPIO mux... " + PIN_OK=true + for pin in 18 19 20 21; do + if ! raspi-gpio get "$pin" 2>/dev/null | grep -q "ALT5"; then + PIN_OK=false + fi + done + if $PIN_OK; then + info "OK (GPIO 18-21 in ALT5)" + else + warn "WARN — I2S pins not all in ALT5 (check pin conflicts)" + warn " GPIO 18-21 must be free for I2S" + fi + + # Test 5: Quick playback test (sine wave, 1 second) + echo -n "Test 5: Audio playback... " + if speaker-test -t sine -f 440 -l 1 -r 48000 -c 2 &>/dev/null; then + info "OK (sine wave played)" + else + err "FAILED — speaker-test error" + FAILED=$((FAILED+1)) + fi + + # Test 6: Quick recording test + echo -n "Test 6: Audio capture... " + if arecord -d 2 -f cd -t wav /tmp/hat_test.wav 2>/dev/null; then + FILESIZE=$(stat -c%s /tmp/hat_test.wav 2>/dev/null || echo 0) + if [ "$FILESIZE" -gt 1000 ]; then + info "OK (${FILESIZE} bytes recorded)" + else + warn "WARN — recording too small (${FILESIZE} bytes)" + fi + else + err "FAILED — arecord error" + FAILED=$((FAILED+1)) + fi + + echo "" + if [ "$FAILED" -eq 0 ]; then + info "All tests passed!" + else + warn "${FAILED} test(s) failed — check dmesg and wiring" + exit 1 + fi +fi \ No newline at end of file