docs: module catalog, 3D model, touchscreen concept, and PCB preview

This commit is contained in:
2026-06-09 00:28:16 -04:00
parent c8d7541065
commit dbb3b9d84f
4 changed files with 1327 additions and 0 deletions
+510
View File
@@ -0,0 +1,510 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pi Multi-FX Pedal — 3D Model</title>
<style>
* { margin: 0; padding: 0; }
body {
background: #0d0d0d;
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
color: #e0e0e0;
}
#info {
position: absolute;
bottom: 24px;
left: 50%;
transform: translateX(-50%);
text-align: center;
pointer-events: none;
z-index: 10;
background: rgba(13,13,13,0.7);
padding: 8px 20px;
border-radius: 20px;
border: 1px solid #333;
font-size: 0.8rem;
backdrop-filter: blur(4px);
}
#info span { color: #666; }
#key {
position: absolute;
top: 20px;
right: 20px;
z-index: 10;
background: rgba(13,13,13,0.8);
border: 1px solid #333;
border-radius: 8px;
padding: 12px;
font-size: 0.7rem;
backdrop-filter: blur(4px);
min-width: 120px;
}
#key div { display: flex; align-items: center; gap: 8px; padding: 2px 0; }
.swatch { width: 12px; height: 12px; border-radius: 2px; display: inline-block; }
.swatch.lcd { background: #2a3a3a; }
.swatch.glass { background: rgba(79,195,247,0.3); }
.swatch.disp { background: #1a5a0a; }
.swatch.rpi { background: #66bb6a; }
.swatch.hat { background: #a78bfa; }
.swatch.box { background: #888; }
.swatch.jack { background: #fbbf24; }
</style>
</head>
<body>
<div id="key">
<div><span class="swatch glass"></span> Touch Glass</div>
<div><span class="swatch disp"></span> Display PCB</div>
<div><span class="swatch rpi"></span> Raspberry Pi 4B</div>
<div><span class="swatch hat"></span> I2S HAT</div>
<div><span class="swatch box"></span> 1590BB Enclosure</div>
<div><span class="swatch jack"></span> Audio Jacks</div>
<div style="margin-top:6px; color:#888;">🖱 Drag to orbit</div>
<div style="color:#888;">🔄 Scroll to zoom</div>
</div>
<div id="info">🎸 Pi Multi-FX Pedal · <span>1590BB + 5" DSI Touch + I2S HAT</span></div>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
// ── Scene Setup ──────────────────────────────────────────────────
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x0d0d0d);
const camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 500);
camera.position.set(150, 100, 200);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.2;
document.body.appendChild(renderer.domElement);
const labelRenderer = new CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = '0';
labelRenderer.domElement.style.left = '0';
labelRenderer.domElement.style.pointerEvents = 'none';
document.body.appendChild(labelRenderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.08;
controls.autoRotate = true;
controls.autoRotateSpeed = 1.0;
controls.target.set(0, 5, 0);
// ── Lighting ─────────────────────────────────────────────────────
const ambient = new THREE.AmbientLight(0x404060, 0.6);
scene.add(ambient);
const keyLight = new THREE.DirectionalLight(0xffffff, 2.5);
keyLight.position.set(100, 150, 80);
keyLight.castShadow = true;
keyLight.shadow.mapSize.width = 1024;
keyLight.shadow.mapSize.height = 1024;
scene.add(keyLight);
const fillLight = new THREE.DirectionalLight(0x8888ff, 0.6);
fillLight.position.set(-80, 40, -60);
scene.add(fillLight);
const rimLight = new THREE.DirectionalLight(0xffffff, 0.8);
rimLight.position.set(-50, 100, -100);
scene.add(rimLight);
const underLight = new THREE.DirectionalLight(0x4488ff, 0.25);
underLight.position.set(0, -100, 0);
scene.add(underLight);
// Ground grid
const gridHelper = new THREE.GridHelper(300, 40, 0x333, 0x222);
gridHelper.position.y = -15;
scene.add(gridHelper);
// ── Helper: make a box with rounded edges ────────────────────────
function roundedBox(w, h, d, r, color, emissive, roughness, metalness, opacity) {
const shape = new THREE.Shape();
const w2 = w/2 - r;
const h2 = h/2 - r;
shape.moveTo(-w2, h2);
shape.quadraticCurveTo(w/2, h2, w/2, 0);
shape.quadraticCurveTo(w/2, -h2, w2, -h2);
shape.lineTo(-w2, -h2);
shape.quadraticCurveTo(-w/2, -h2, -w/2, 0);
shape.quadraticCurveTo(-w/2, h2, -w2, h2);
const extrudeSettings = { depth: d, bevelEnabled: true, bevelThickness: r*0.5, bevelSize: r*0.3, bevelSegments: 6 };
const geo = new THREE.ExtrudeGeometry(shape, extrudeSettings);
geo.translate(0, 0, -d/2);
const mat = new THREE.MeshStandardMaterial({
color, emissive, roughness, metalness,
transparent: opacity !== undefined,
opacity: opacity || 1.0,
emissiveIntensity: 0.1,
});
const mesh = new THREE.Mesh(geo, mat);
mesh.castShadow = true;
mesh.receiveShadow = true;
return mesh;
}
function makeLabel(text, color = '#4fc3f7', size = '14px') {
const div = document.createElement('div');
div.textContent = text;
div.style.color = color;
div.style.fontFamily = 'Courier New, monospace';
div.style.fontSize = size;
div.style.fontWeight = '600';
div.style.textShadow = '0 1px 4px rgba(0,0,0,0.8)';
div.style.background = 'rgba(0,0,0,0.5)';
div.style.padding = '2px 8px';
div.style.borderRadius = '4px';
div.style.border = '1px solid ' + color;
return new CSS2DObject(div);
}
// ── Colors ───────────────────────────────────────────────────────
const C = {
glass: 0x88ccdd,
glassEdge: 0x446688,
pcb: 0x1a5a0a,
rpi: 0x66bb6a,
rpiDark: 0x338833,
hat: 0x8855cc,
hatDark: 0x553388,
box: 0x888888,
boxDark: 0x555555,
jack: 0xfbbf24,
jackDark: 0xcc9900,
accent: 0x4fc3f7,
gold: 0xccaaff,
};
// ── Build the pedal ──────────────────────────────────────────────
const pedal = new THREE.Group();
// 1. ENCLOSURE — 1590BB (140×78×48mm external)
// Bottom box
const boxGeo = new THREE.BoxGeometry(140, 48, 78);
const boxMat = new THREE.MeshStandardMaterial({
color: 0x666666,
roughness: 0.7,
metalness: 0.3,
emissive: 0x222222,
emissiveIntensity: 0.05,
});
const boxMesh = new THREE.Mesh(boxGeo, boxMat);
boxMesh.position.y = -24;
boxMesh.castShadow = true;
boxMesh.receiveShadow = true;
pedal.add(boxMesh);
// Top face (panel) — slightly recessed
const panelMat = new THREE.MeshStandardMaterial({
color: 0x555555,
roughness: 0.6,
metalness: 0.4,
emissive: 0x111111,
emissiveIntensity: 0.05,
});
const panelGeo = new THREE.BoxGeometry(136, 2, 74);
const panelMesh = new THREE.Mesh(panelGeo, panelMat);
panelMesh.position.y = 0;
panelMesh.castShadow = true;
panelMesh.receiveShadow = true;
pedal.add(panelMesh);
// Enclosure edge bevels (visual)
const edgeMat = new THREE.MeshStandardMaterial({
color: 0x444444,
roughness: 0.8,
metalness: 0.2,
});
// 2. I2S HAT (bottom layer) — 65×56mm, sits inside enclosure
const hatMat = new THREE.MeshStandardMaterial({
color: C.hat,
roughness: 0.4,
metalness: 0.3,
emissive: C.hat,
emissiveIntensity: 0.05,
});
const hatGeo = new THREE.BoxGeometry(65, 1.6, 56);
const hatMesh = new THREE.Mesh(hatGeo, hatMat);
hatMesh.position.set(0, 2.5, 0);
hatMesh.castShadow = true;
hatMesh.receiveShadow = true;
pedal.add(hatMesh);
// HAT silkscreen marks
const hatchf = new THREE.Mesh(
new THREE.BoxGeometry(0.5, 0.15, 0.5),
new THREE.MeshStandardMaterial({ color: 0xffaa00, emissive: 0xffaa00, emissiveIntensity: 0.3 })
);
[-20, -10, 0, 10, 20].forEach(x => {
[-15, 0, 15].forEach(z => {
const dot = hatchf.clone();
dot.position.set(x, 3.3, z);
pedal.add(dot);
});
});
// HAT components (IC blocks)
function addIC(x, z, w, d, h, color, label) {
const mat = new THREE.MeshStandardMaterial({
color, roughness: 0.3, metalness: 0.5,
emissive: color, emissiveIntensity: 0.08,
});
const body = new THREE.Mesh(new THREE.BoxGeometry(w, h, d), mat);
body.position.set(x, 3.3 + h/2, z);
body.castShadow = true;
pedal.add(body);
const lbl = makeLabel(label, '#a78bfa', '10px');
lbl.position.set(x, 6, z);
pedal.add(lbl);
}
addIC(-15, -8, 8, 6, 1.5, 0xaa66ee, 'U3 ADC');
addIC(15, -8, 8, 6, 1.5, 0x66aaff, 'U4 DAC');
addIC(-15, 8, 10, 10, 2.0, 0x66bb66, 'U2 Pre');
addIC(10, 8, 7, 6, 1.8, 0xee5555, 'U1 LDO');
// Jacks on I2S HAT — side mounted cylinders
function addJack(x, z, angle, label) {
const mat = new THREE.MeshStandardMaterial({
color: C.jack,
roughness: 0.3,
metalness: 0.6,
emissive: C.jack,
emissiveIntensity: 0.05,
});
const cylinder = new THREE.Mesh(new THREE.CylinderGeometry(4, 4, 12, 16), mat);
cylinder.rotation.z = Math.PI/2;
cylinder.position.set(x, 5, z);
cylinder.castShadow = true;
pedal.add(cylinder);
// Nut
const nutMat = new THREE.MeshStandardMaterial({ color: 0x888888, roughness: 0.4, metalness: 0.7 });
const nut = new THREE.Mesh(new THREE.CylinderGeometry(5, 5, 2, 6), nutMat);
nut.rotation.z = Math.PI/2;
nut.position.set(x, 5, z);
pedal.add(nut);
const lbl = makeLabel(label, '#fbbf24', '10px');
lbl.position.set(x + (x < 0 ? -10 : 10), 8, z);
pedal.add(lbl);
}
addJack(-68, -10, 0, 'J IN');
addJack(-68, 10, 0, 'J SEND');
addJack(68, -10, 0, 'J RETURN');
addJack(68, 10, 0, 'J OUT');
// 3. RPi 4B (middle layer) — 85×56mm
const rpiMat = new THREE.MeshStandardMaterial({
color: C.rpi,
roughness: 0.5,
metalness: 0.2,
emissive: C.rpi,
emissiveIntensity: 0.03,
});
const rpiGeo = new THREE.BoxGeometry(85, 1.6, 56);
const rpiMesh = new THREE.Mesh(rpiGeo, rpiMat);
rpiMesh.position.set(0, 7, 0);
rpiMesh.castShadow = true;
rpiMesh.receiveShadow = true;
pedal.add(rpiMesh);
// RPi standoffs (4x)
const standoffMat = new THREE.MeshStandardMaterial({
color: 0x888888, roughness: 0.3, metalness: 0.6,
});
for (let x of [-28, 28]) {
for (let z of [-20, 20]) {
const standoff = new THREE.Mesh(new THREE.CylinderGeometry(2.5, 2.5, 5, 8), standoffMat);
standoff.position.set(x, 5.5, z);
pedal.add(standoff);
}
}
// GPIO stacking header
const hdrMat = new THREE.MeshStandardMaterial({
color: 0x222222, roughness: 0.3, metalness: 0.2,
});
const hdr = new THREE.Mesh(new THREE.BoxGeometry(4, 6, 50), hdrMat);
hdr.position.set(22, 10, 0);
pedal.add(hdr);
const hdr2 = new THREE.Mesh(new THREE.BoxGeometry(4, 6, 50), hdrMat);
hdr2.position.set(-22, 10, 0);
pedal.add(hdr2);
// DSI port indicator
const dsiMat = new THREE.MeshStandardMaterial({
color: 0x4488ff, roughness: 0.3, metalness: 0.1,
});
const dsiPort = new THREE.Mesh(new THREE.BoxGeometry(4, 1, 10), dsiMat);
dsiPort.position.set(-38, 8, 5);
pedal.add(dsiPort);
const rpiLbl = makeLabel('RPi 4B', '#66bb6a', '12px');
rpiLbl.position.set(0, 12, 0);
pedal.add(rpiLbl);
// 4. Display PCB (Waveshare 5" — 102×76mm)
const dispMat = new THREE.MeshStandardMaterial({
color: C.pcb,
roughness: 0.4,
metalness: 0.2,
emissive: C.pcb,
emissiveIntensity: 0.03,
});
const dispGeo = new THREE.BoxGeometry(102, 1.6, 76);
const dispMesh = new THREE.Mesh(dispGeo, dispMat);
dispMesh.position.set(0, 13, 0);
dispMesh.castShadow = true;
dispMesh.receiveShadow = true;
pedal.add(dispMesh);
// Display standoffs
for (let x of [-40, 40]) {
for (let z of [-30, 30]) {
const standoff = new THREE.Mesh(new THREE.CylinderGeometry(2, 2, 5, 8), standoffMat);
standoff.position.set(x, 11, z);
pedal.add(standoff);
}
}
// DSI ribbon cable (visual)
const ribbonMat = new THREE.MeshStandardMaterial({
color: 0x8855cc, roughness: 0.5, metalness: 0.1,
transparent: true, opacity: 0.7,
});
const ribbon = new THREE.Mesh(new THREE.BoxGeometry(3, 1, 40), ribbonMat);
ribbon.position.set(-40, 12.5, -20);
ribbon.rotation.x = 0.3;
pedal.add(ribbon);
const ribbon2 = new THREE.Mesh(new THREE.BoxGeometry(3, 1, 30), ribbonMat);
ribbon2.position.set(-40, 10, -35);
ribbon2.rotation.x = 0.6;
pedal.add(ribbon2);
const dispLbl = makeLabel('5" DSI Display', '#33aa33', '12px');
dispLbl.position.set(0, 16, 0);
pedal.add(dispLbl);
// 5. Touch Glass (front face — fills enclosure top)
const glassMat = new THREE.MeshStandardMaterial({
color: C.glass,
roughness: 0.1,
metalness: 0.0,
transparent: true,
opacity: 0.15,
emissive: C.glass,
emissiveIntensity: 0.05,
});
const glassGeo = new THREE.BoxGeometry(120, 1.5, 65);
const glassMesh = new THREE.Mesh(glassGeo, glassMat);
glassMesh.position.set(0, 15.5, 0);
glassMesh.castShadow = true;
glassMesh.receiveShadow = true;
pedal.add(glassMesh);
// Glass edge bezel
const bezelMat = new THREE.MeshStandardMaterial({
color: 0x222233, roughness: 0.4, metalness: 0.3,
});
const bezel = new THREE.Mesh(new THREE.BoxGeometry(122, 0.5, 67), bezelMat);
bezel.position.set(0, 15, 0);
pedal.add(bezel);
// Simulated UI on glass — floating colored rectangles
function addUIPixel(x, z, w, h, color) {
const m = new THREE.MeshStandardMaterial({
color, roughness: 0.3, metalness: 0.0,
emissive: color, emissiveIntensity: 0.3,
transparent: true, opacity: 0.6,
});
const r = new THREE.Mesh(new THREE.BoxGeometry(w, 0.1, h), m);
r.position.set(x, 16.3, z);
pedal.add(r);
}
// Simulated preset name bar
addUIPixel(-30, 18, 60, 8, 0x4fc3f7);
// Bypass button glow
addUIPixel(-45, -5, 20, 10, 0x66bb6a);
// Volume slider
addUIPixel(5, -5, 40, 4, 0x4fc3f7);
// Volume knob
addUIPixel(30, -5, 6, 6, 0x4fc3f7);
// FX chain pills
addUIPixel(-30, -18, 25, 6, 0xa78bfa);
addUIPixel(-5, -18, 18, 6, 0x66bb6a);
addUIPixel(15, -18, 22, 6, 0x4fc3f7);
// Bottom bar
addUIPixel(-30, -28, 70, 6, 0x4488cc);
const glassLbl = makeLabel('Touch Glass', '#88ccdd', '12px');
glassLbl.position.set(60, 20, -30);
pedal.add(glassLbl);
// ── Position the whole pedal ───────────────────────────────────
pedal.position.set(0, 10, 0);
scene.add(pedal);
// ── Label: overall product name ────────────────────────────────
const titleLbl = makeLabel('Pi Multi-FX Pedal · 1590BB', '#4fc3f7', '18px');
titleLbl.position.set(0, 45, 80);
scene.add(titleLbl);
const subtitleLbl = makeLabel('5" DSI Touch · PCM1808+PCM5102 I2S HAT · 32 FX', '#888', '12px');
subtitleLbl.position.set(0, 40, 80);
scene.add(subtitleLbl);
// ── Responsive ──────────────────────────────────────────────────
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.setSize(window.innerWidth, window.innerHeight);
});
// Toggle auto-rotate on click
renderer.domElement.addEventListener('click', () => {
controls.autoRotate = !controls.autoRotate;
});
// ── Animate ──────────────────────────────────────────────────────
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
labelRenderer.render(scene, camera);
}
animate();
</script>
</body>
</html>
+224
View File
@@ -0,0 +1,224 @@
# Ourpad Modular Band System — Module Catalog
> **Vision:** A family of stackable DSP modules, one per band member, sharing a common platform. Each module is a self-contained RPi-powered effects unit in a compact enclosure. Modules sync over the network for sample-accurate multi-channel mixing.
>
> **Status:** Planning phase. Guitar module prototype is furthest along.
---
## Platform Spec (All Modules)
| Spec | Standard | Premium Option |
|------|----------|----------------|
| **CPU** | RPi 4B (2GB+) | RPi 5 (for drums/keys) |
| **OS** | DietPi (minimized) | Same |
| **Audio I/O** | I2S HAT per module type | USB Audio Class 2 (for high channel count) |
| **Sample Rate** | 48kHz / 24-bit | 96kHz (keys/synth) |
| **Latency Target** | < 10ms round-trip | < 5ms (drums) |
| **Display** | 5" DSI touch (800×480) | None (drums — rack UI only) |
| **Network** | WiFi + Ethernet | AES50 for drums |
| **Sync** | NTP / manual | AES50 embedded clock |
| **Enclosure** | 1590BB (140×78mm) | 1U rackmount (drums) |
| **Power** | USB-C PD (5V/3A) | PoE (drums in stage box) |
| **Control** | Touch, Web UI, MIDI DIN/BT | All of the above |
---
## 🎸 Module 1: Guitar
**Status: Prototype — Phase 1 (I2S HAT + DSP) complete. Phase 2 (touch + XLR) pending.**
| Spec | Value |
|------|-------|
| **Inputs** | Combo XLR/1/4" with hi-Z switch, 1/4" Return (4CM) |
| **Outputs** | 1/4" Send (4CM), XLR balanced DI |
| **Preamp** | TL072-based (existing) + hi-Z buffer for piezo |
| **Line Driver** | DRV134 or THAT1646 for balanced XLR |
| **Phantom** | Not needed (instrument level) |
| **Patching** | Front: Combo in, XLR out. Side: Send/Return |
| **FX** | 32 total: Gate, Comp, Boost, OD, Dist, Fuzz, NAM Amp, IR Cab, EQ, Parametric EQ, HPF, LPF, Mod, Delay, Reverb, Pitch, Looper + all modulation |
| **HAT** | PCM1808+PCM5102 (existing Rev 1.0 — mono 1ch in/out) |
| **HAT Rev 2** | Add combo jack footprint, XLR driver, 4CM Send/Return |
| **Edge** | NAM A2 neural amp modeling |
**Current state:** All DSP and 4CM routing done. I2S HAT designed (needs Gerber export). Touch integration pending 1590BB enclosure.
---
## 🎸 Module 2: Bass
**Status: Concept. Shares guitar HAT with different preamp.**
| Spec | Value |
|------|-------|
| **Inputs** | Combo XLR/1/4" with hi-Z, pad switch |
| **Outputs** | XLR balanced DI, 1/4" thru |
| **Preamp** | FET Neve-style (SansAmp character) — dedicated op-amp stage |
| **Tone Shaping** | 3-band active EQ (bass/mid/treble sweepable), blend control |
| **FX Priority** | Compressor (always-on), Octaver, Envelope Filter, Chorus, EQ |
| **RPi** | Zero 2W sufficient (lighter DSP load) |
| **Enclosure** | 1590BB or smaller (125B) — fewer controls needed |
| **Display** | 3.5" DSI or small OLED + knobs |
| **HAT** | Same PCM1808+PCM5102 as guitar (mono instrument) |
**Edge:** Analog blend — mix dry bass tone with processed signal (critical for bassists).
---
## 🎤 Module 3: Vocal
**Status: Concept. Needs different analog front-end.**
| Spec | Value |
|------|-------|
| **Inputs** | XLR with 48V phantom power |
| **Outputs** | XLR balanced |
| **Preamp** | INA163 or SSM2019 instrumentation amp (low noise, 20-60dB gain) |
| **Phantom** | MAX1771 or similar DC-DC converter for 48V |
| **Pad** | -20dB pad for hot sources |
| **FX Priority** | Gate, Comp, De-esser, EQ, Reverb, Delay, Harmonizer, Pitch Correction |
| **RPi** | 4B (pitch detection is CPU-heavy) |
| **Enclosure** | 1590BB with touch |
| **HAT** | Custom — mic pre + phantom + balanced driver |
**Edge:** Real-time pitch correction (auto-tune style), harmony generation from MIDI input.
**Cost impact:** Phantom power adds ~$8-12 in components (DC-DC converter, filtering).
---
## 🎹 Module 4: Keys / Synth
**Status: Concept. Simplest analog stage — line level only.**
| Spec | Value |
|------|-------|
| **Inputs** | 2× TRS (stereo line in) |
| **Outputs** | 2× TRS or XLR (stereo out) |
| **Preamp** | None needed (line level) — just buffer + protection |
| **FX Priority** | Reverbs, Delays, Chorus, Phaser, Rotary, Tremolo, Ring Mod |
| **RPi** | Zero 2W sufficient |
| **Enclosure** | 1590BB or rackmount half-width |
| **Display** | 5" touch or headless (MIDI CC control) |
| **HAT** | PCM1808 stereo ADC (already stereo-capable) + PCM5102 stereo DAC |
**Edge:** Uses the existing HAT's full stereo capability (PCM1808 has 2 ADC channels, PCM5102 has 2 DAC channels — the guitar module only uses half).
---
## 🎺 Module 5: Horns / Misc
**Status: Concept. Vocal variant with simpler FX.**
| Spec | Value |
|------|-------|
| **Inputs** | XLR (mic) |
| **Outputs** | XLR balanced |
| **Preamp** | Same INA163 as vocal |
| **Phantom** | Yes (condenser mics) |
| **FX Priority** | Comp, EQ, Reverb (minimal — horns sound great dry) |
| **RPi** | Zero 2W |
| **Enclosure** | 125B (small, simple) |
| **Display** | None — web UI only |
**Edge:** Minimalist. Three knobs: Reverb, Compression, EQ. Designed to not get in the way.
---
## 🥁 Module 6: Drums
**Status: Concept. Different architecture — network audio + stage box.**
| Spec | Value |
|------|-------|
| **Inputs** | Ethernet (AES50) from stage box |
| **Outputs** | Ethernet (AES50) to FOH, stereo monitor out |
| **Stage Box** | 8× XLR input → AES50 transmitter (dedicated hardware, not a Pi) |
| **RPi Job** | Mixer + FX per channel + routing to stereo out |
| **FX Per Channel** | Gate, Comp, EQ per drum — summed into stereo mix |
| **RPi** | RPi 5 (8-16 channel real-time processing) |
| **Enclosure** | 1U rackmount |
| **Display** | 7" HDMI or headless (iPad control) |
| **HAT** | AES50 XMOS board → I2S bridge, or USB Audio interface |
### Stage Box Details
```
Front: 8× Combo XLR/TRS input
Back: Ethercon (AES50 out), Power in
Size: Half-rack or floor box (aluminum, rugged)
RX: XMOS AES50 receiver module → I2S → RPi
OR: Behringer S16-style design with custom PCB
```
**AES50 Hardware Options:**
- **XMOS XU208 dev board** (~$25) — programmable AES50 transceiver
- **Off-the-shelf AES50 <-> ADAT converter** (~$60) — simpler but less flexible
- **DIY PCB** with XMOS chip — for production
**Edge:** Uses AES50 (open protocol, proven in live sound), sub-1ms latency, standard CAT5e cabling, 100m+ range.
---
## 🌐 Module 7: Sync / Mix Bridge (Optional)
**Status: Concept. Only needed for multi-module setups.**
| Spec | Value |
|------|-------|
| **Role** | Master clock + mix bus for multi-module band setups |
| **Inputs** | Ethernet from each module |
| **Outputs** | Stereo XLR (FOH), headphone monitor |
| **Sync** | AES50-derived word clock, distributed to all modules via network |
| **Mix** | Web UI mixer — each module's stereo output blended + headphone sends |
| **RPi** | RPi 5 |
| **Enclosure** | Rackmount 1U |
**Edge:** Without this, modules run independently (each with its own output to the mixer). The bridge lets you control the entire band mix from one device and gives the drummer a click track.
---
## Module Comparison Matrix
| Module | I/O | Preamp | Phantom | RPi | Enclosure | Complexity | Est. BOM | Status |
|:-------|:---:|:------:|:-------:|:---:|:---------:|:----------:|:--------:|:------:|
| **Guitar** | Combo + 4CM | TL072 | No | 4B | 1590BB | Medium | ~$175 | **Prototype** |
| **Bass** | Combo + DI | FET Neve | No | Z2W | 125B | Medium | ~$150 | Concept |
| **Vocal** | XLR in/out | INA163 | Yes | 4B | 1590BB | High | ~$200 | Concept |
| **Keys** | Stereo TRS | None | No | Z2W | 125B | Low | ~$120 | Concept |
| **Horns** | XLR in/out | INA163 | Yes | Z2W | 125B | Medium | ~$160 | Concept |
| **Drums** | AES50 + stage | Varies | Yes (box) | 5 | 1U | **Very High** | ~$400+ | Concept |
| **Bridge** | Ethernet | — | No | 5 | 1U | High | ~$200 | Concept |
---
## Next Steps
**Immediate (guitar prototype):**
1. Revise I2S HAT for 1590BB + combo jacks + XLR driver
2. Order boards (Gerber export → JLCPCB)
3. Assemble + test with Focusrite 2i2 in 4CM
4. Wire touchscreen display
5. Full prototype test: guitar → pedal → amp + FOH
**Short-term (bass + keys):**
- Bass uses same HAT as guitar (just different preamp circuit)
- Keys uses existing HAT's stereo capability — zero PCB changes
- Both can be validated with the Focusrite before ordering HAT PCBs
**Medium-term (vocal + horns):**
- Need new HAT design (mic pre + phantom power)
- Major analog design effort
**Long-term (drums + bridge):**
- AES50 research and prototyping
- Stage box PCB design (8-channel preamp + phantom + AES50 encoder)
- Mix bridge software design
---
Want me to save this as a reference doc and task up the **guitar prototype completion** plan from here? That'd cover:
1. I2S HAT Rev 2 (combo jacks + XLR driver + 1590BB fit)
2. Touch display integration
3. Full assembly + test with Focusrite 4CM
4. Then order real boards
+296
View File
@@ -0,0 +1,296 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PCM1808+PCM5102 I2S HAT — PCB Preview</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: #0d0d0d;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
padding: 40px 20px;
color: #e0e0e0;
}
h1 { font-size: 1.4rem; margin-bottom: 8px; }
.subtitle { color: #999; font-size: 0.85rem; margin-bottom: 30px; }
.container {
display: flex;
flex-wrap: wrap;
gap: 40px;
justify-content: center;
max-width: 1100px;
}
.board-card {
background: #1a1a1a;
border: 1px solid #333;
border-radius: 12px;
padding: 24px;
}
.board-card h2 {
font-size: 0.85rem;
color: #999;
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 16px;
}
svg text { font-family: 'Courier New', monospace; }
.specs {
background: #1a1a1a;
border: 1px solid #333;
border-radius: 12px;
padding: 24px;
min-width: 280px;
align-self: flex-start;
}
.specs h2 {
font-size: 0.85rem;
color: #999;
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 16px;
}
.spec-table { width: 100%; font-size: 0.82rem; }
.spec-table td { padding: 6px 4px; border-bottom: 1px solid #222; }
.spec-table td:first-child { color: #666; white-space: nowrap; padding-right: 16px; }
.spec-table td:last-child { color: #e0e0e0; }
.label { color: #4fc3f7; }
.footnote { color: #666; font-size: 0.75rem; margin-top: 16px; }
.accent { color: #66bb6a; }
.cost { color: #ffa726; }
</style>
</head>
<body>
<h1>🎸 PCM1808+PCM5102 I2S HAT</h1>
<div class="subtitle">65×56mm 2-layer PCB — 1590B Compatible — Rev 1.0</div>
<div class="container">
<div class="board-card">
<h2>Top View (Component Side)</h2>
<svg width="460" height="396" viewBox="0 0 460 396">
<!-- Board outline -->
<rect x="10" y="10" width="440" height="376" rx="4" fill="#0a1a0a" stroke="#2a5a2a" stroke-width="2"/>
<!-- Board edge highlight -->
<rect x="11" y="11" width="438" height="374" rx="3" fill="none" stroke="#1a3a1a" stroke-width="0.5"/>
<!-- Mounting holes -->
<circle cx="31" cy="31" r="11" fill="#0d0d0d" stroke="#444" stroke-width="1.5"/>
<circle cx="31" cy="31" r="8" fill="none" stroke="#333" stroke-width="0.5"/>
<circle cx="429" cy="31" r="11" fill="#0d0d0d" stroke="#444" stroke-width="1.5"/>
<circle cx="429" cy="31" r="8" fill="none" stroke="#333" stroke-width="0.5"/>
<circle cx="31" cy="365" r="11" fill="#0d0d0d" stroke="#444" stroke-width="1.5"/>
<circle cx="31" cy="365" r="8" fill="none" stroke="#333" stroke-width="0.5"/>
<circle cx="429" cy="365" r="11" fill="#0d0d0d" stroke="#444" stroke-width="1.5"/>
<circle cx="429" cy="365" r="8" fill="none" stroke="#333" stroke-width="0.5"/>
<!-- RPi 40-pin header J1 -->
<rect x="170" y="14" width="120" height="40" rx="3" fill="rgba(79,195,247,0.15)" stroke="#4fc3f7" stroke-width="1.5"/>
<text x="230" y="38" text-anchor="middle" fill="#4fc3f7" font-size="9">J1 — RPi 40-Pin Header</text>
<!-- Pin 1 marker -->
<circle cx="176" cy="20" r="3" fill="#4fc3f7" opacity="0.5"/>
<!-- I2S bus label -->
<rect x="50" y="70" width="80" height="18" rx="3" fill="rgba(251,191,36,0.15)" stroke="#fbbf24" stroke-width="1" stroke-dasharray="3,2"/>
<text x="90" y="83" text-anchor="middle" fill="#fbbf24" font-size="8">I2S Bus (BCLK/LRCLK/DIN/DOUT)</text>
<!-- AMS1117-3.3 LDO U1 -->
<rect x="40" y="100" width="70" height="30" rx="3" fill="rgba(239,83,80,0.15)" stroke="#ef5350" stroke-width="1.5"/>
<text x="75" y="115" text-anchor="middle" fill="#ef5350" font-size="9">U1</text>
<text x="75" y="125" text-anchor="middle" fill="#ef5350" font-size="7">AMS1117-3.3</text>
<!-- Decoupling caps near LDO -->
<rect x="115" y="105" width="14" height="10" rx="2" fill="rgba(255,255,255,0.1)" stroke="#666" stroke-width="1"/>
<text x="122" y="119" text-anchor="middle" fill="#888" font-size="6">C1</text>
<rect x="115" y="120" width="14" height="10" rx="2" fill="rgba(255,255,255,0.1)" stroke="#666" stroke-width="1"/>
<text x="122" y="134" text-anchor="middle" fill="#888" font-size="6">C2</text>
<!-- TL072 Preamp U2 -->
<rect x="40" y="155" width="90" height="45" rx="4" fill="rgba(102,187,106,0.15)" stroke="#66bb6a" stroke-width="1.5"/>
<text x="85" y="172" text-anchor="middle" fill="#66bb6a" font-size="9">U2 — TL072</text>
<text x="85" y="184" text-anchor="middle" fill="#66bb6a" font-size="7">Dual JFET Op-Amp</text>
<text x="85" y="195" text-anchor="middle" fill="#888" font-size="6">Half 1: Preamp · Half 2: Buffer</text>
<!-- Feedback resistors R3 R4 -->
<rect x="135" y="165" width="14" height="10" rx="2" fill="rgba(255,255,255,0.1)" stroke="#666" stroke-width="1"/>
<text x="142" y="179" text-anchor="middle" fill="#888" font-size="6">R3</text>
<rect x="135" y="180" width="14" height="10" rx="2" fill="rgba(255,255,255,0.1)" stroke="#666" stroke-width="1"/>
<text x="142" y="194" text-anchor="middle" fill="#888" font-size="6">R4</text>
<!-- Input jack J2 -->
<rect x="10" y="145" width="26" height="55" rx="4" fill="rgba(251,191,36,0.12)" stroke="#fbbf24" stroke-width="1.5"/>
<text x="23" y="168" text-anchor="middle" fill="#fbbf24" font-size="7">J2</text>
<text x="23" y="180" text-anchor="middle" fill="#fbbf24" font-size="6">Input</text>
<!-- Arrow from jack to preamp -->
<line x1="36" y1="172" x2="40" y2="177" stroke="#666" stroke-width="1"/>
<polygon points="38,172 40,170 44,177 40,178" fill="#666"/>
<!-- Caps near preamp -->
<rect x="135" y="155" width="14" height="10" rx="2" fill="rgba(255,255,255,0.1)" stroke="#666" stroke-width="1"/>
<rect x="155" y="155" width="14" height="10" rx="2" fill="rgba(255,255,255,0.1)" stroke="#666" stroke-width="1"/>
<text x="162" y="169" text-anchor="middle" fill="#888" font-size="6">R1,R2</text>
<!-- PCM1808 ADC U3 -->
<rect x="40" y="220" width="85" height="40" rx="4" fill="rgba(167,139,250,0.15)" stroke="#a78bfa" stroke-width="1.5"/>
<text x="82" y="240" text-anchor="middle" fill="#a78bfa" font-size="9">U3 — PCM1808</text>
<text x="82" y="252" text-anchor="middle" fill="#a78bfa" font-size="7">24-bit Stereo ADC</text>
<!-- PCM5102 DAC U4 -->
<rect x="200" y="220" width="85" height="40" rx="4" fill="rgba(79,195,247,0.15)" stroke="#4fc3f7" stroke-width="1.5"/>
<text x="242" y="240" text-anchor="middle" fill="#4fc3f7" font-size="9">U4 — PCM5102</text>
<text x="242" y="252" text-anchor="middle" fill="#4fc3f7" font-size="7">32-bit Stereo DAC</text>
<!-- ADC decoupling caps -->
<rect x="155" y="215" width="14" height="10" rx="2" fill="rgba(255,255,255,0.1)" stroke="#666" stroke-width="1"/>
<text x="162" y="229" text-anchor="middle" fill="#888" font-size="6">C6</text>
<rect x="155" y="230" width="14" height="10" rx="2" fill="rgba(255,255,255,0.1)" stroke="#666" stroke-width="1"/>
<text x="162" y="244" text-anchor="middle" fill="#888" font-size="6">C7</text>
<!-- DAC decoupling caps -->
<rect x="175" y="215" width="14" height="10" rx="2" fill="rgba(255,255,255,0.1)" stroke="#666" stroke-width="1"/>
<text x="182" y="229" text-anchor="middle" fill="#888" font-size="6">C8</text>
<rect x="175" y="230" width="14" height="10" rx="2" fill="rgba(255,255,255,0.1)" stroke="#666" stroke-width="1"/>
<text x="182" y="244" text-anchor="middle" fill="#888" font-size="6">C9</text>
<!-- I2S connection lines between ADC and DAC -->
<line x1="125" y1="230" x2="200" y2="230" stroke="#fbbf24" stroke-width="1" stroke-dasharray="3,2"/>
<line x1="125" y1="240" x2="200" y2="240" stroke="#fbbf24" stroke-width="1" stroke-dasharray="3,2"/>
<line x1="125" y1="250" x2="200" y2="250" stroke="#fbbf24" stroke-width="1" stroke-dasharray="3,2"/>
<text x="162" y="262" text-anchor="middle" fill="#fbbf24" font-size="6">BCLK · LRCLK · DIN</text>
<!-- DC-blocking cap C5 -->
<rect x="155" y="195" width="14" height="10" rx="2" fill="rgba(255,255,255,0.1)" stroke="#666" stroke-width="1"/>
<text x="162" y="209" text-anchor="middle" fill="#888" font-size="6">C5</text>
<!-- Output RC filter -->
<rect x="290" y="225" width="40" height="20" rx="3" fill="rgba(255,255,255,0.08)" stroke="#666" stroke-width="1"/>
<text x="310" y="235" text-anchor="middle" fill="#888" font-size="7">R5+C10</text>
<text x="310" y="242" text-anchor="middle" fill="#666" font-size="6">330Ω+10µF</text>
<!-- Output jack J3 -->
<rect x="335" y="145" width="26" height="55" rx="4" fill="rgba(251,191,36,0.12)" stroke="#fbbf24" stroke-width="1.5"/>
<text x="348" y="168" text-anchor="middle" fill="#fbbf24" font-size="7">J3</text>
<text x="348" y="180" text-anchor="middle" fill="#fbbf24" font-size="6">Output</text>
<!-- DAC to output path -->
<line x1="285" y1="240" x2="335" y2="172" stroke="#888" stroke-width="1" stroke-dasharray="4,2"/>
<!-- Output buffer resistor R6 -->
<rect x="290" y="195" width="20" height="12" rx="2" fill="rgba(255,255,255,0.1)" stroke="#666" stroke-width="1"/>
<text x="300" y="203" text-anchor="middle" fill="#888" font-size="6">R6</text>
<!-- 3.3V rail indicator -->
<rect x="50" y="275" width="100" height="16" rx="3" fill="rgba(239,83,80,0.08)" stroke="#ef5350" stroke-width="1" stroke-dasharray="2,2"/>
<text x="100" y="287" text-anchor="middle" fill="#ef5350" font-size="7">⎇ 3.3V Rail (5V → AMS1117)</text>
<!-- GND flood fill text -->
<text x="230" y="320" text-anchor="middle" fill="#444" font-size="8">GND Flood Fill (both layers)</text>
<text x="230" y="330" text-anchor="middle" fill="#444" font-size="8">Star Ground at RPi GND pin</text>
<!-- Power section label -->
<rect x="40" y="95" width="80" height="18" rx="3" fill="rgba(239,83,80,0.08)" stroke="#ef5350" stroke-width="0.5"/>
<text x="80" y="107" text-anchor="middle" fill="#ef5350" font-size="7">Power Regulation</text>
<!-- Dimension arrows -->
<line x1="10" y1="390" x2="450" y2="390" stroke="#555" stroke-width="0.5" marker-start="url(#arrow)" marker-end="url(#arrow)"/>
<text x="230" y="384" text-anchor="middle" fill="#666" font-size="8">65mm</text>
<line x1="458" y1="10" x2="458" y2="386" stroke="#555" stroke-width="0.5" marker-start="url(#arrow)" marker-end="url(#arrow)"/>
<text x="454" y="200" text-anchor="middle" fill="#666" font-size="8" transform="rotate(90,454,200)">56mm</text>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M 0 0 L 10 5 L 0 10" fill="none" stroke="#555" stroke-width="1"/>
</marker>
</defs>
</svg>
</div>
<div class="specs">
<h2>Board Specifications</h2>
<table class="spec-table">
<tr><td>Dimensions</td><td>65 × 56mm (1590B)</td></tr>
<tr><td>Layers</td><td>2-layer FR4, 1.6mm</td></tr>
<tr><td>Surface Finish</td><td>ENIG (gold) preferred</td></tr>
<tr><td>Min Trace</td><td>0.254mm (10mil)</td></tr>
<tr><td>Min Hole</td><td>0.3mm</td></tr>
<tr><td>Mounting</td><td>4× M2.5, 3.2mm holes</td></tr>
<tr><td colspan="2" style="padding-top:16px; border:none;"></td></tr>
<tr><td colspan="2" style="font-weight:600; border-bottom:1px solid #444;">Signal Chain</td></tr>
<tr><td>Input</td><td>Guitar → <span class="label">J2</span> (6.35mm TS)</td></tr>
<tr><td>Preamp</td><td><span class="label">U2</span> TL072 — 20dB gain</td></tr>
<tr><td>ADC</td><td><span class="label">U3</span> PCM1808 — 24-bit/48kHz I2S</td></tr>
<tr><td>DAC</td><td><span class="label">U4</span> PCM5102A — 32-bit I2S</td></tr>
<tr><td>Output</td><td><span class="label">J3</span> (6.35mm TS) via RC filter</td></tr>
<tr><td colspan="2" style="padding-top:16px; border:none;"></td></tr>
<tr><td colspan="2" style="font-weight:600; border-bottom:1px solid #444;">Power</td></tr>
<tr><td>Regulator</td><td><span class="label">U1</span> AMS1117-3.3 (5V→3.3V)</td></tr>
<tr><td>Decoupling</td><td>100nF + 10µF per IC</td></tr>
<tr><td>Ground</td><td>Star ground, GND flood fill</td></tr>
<tr><td colspan="2" style="padding-top:16px; border:none;"></td></tr>
<tr><td colspan="2" style="font-weight:600; border-bottom:1px solid #444;">I2S Bus (GPIO)</td></tr>
<tr><td>BCLK</td><td>GPIO18 (Pin 12)</td></tr>
<tr><td>LRCLK</td><td>GPIO19 (Pin 35)</td></tr>
<tr><td>DIN (to RPi)</td><td>GPIO20 (Pin 38) ← PCM1808</td></tr>
<tr><td>DOUT (from RPi)</td><td>GPIO21 (Pin 40) → PCM5102</td></tr>
<tr><td colspan="2" style="padding-top:16px; border:none;"></td></tr>
<tr><td colspan="2" style="font-weight:600; border-bottom:1px solid #444;">Cost</td></tr>
<tr><td>Board + Components</td><td class="cost"><strong>~$29.25</strong></td></tr>
<tr><td>+ Enclosure (1590B)</td><td class="cost"><strong>~$41.75</strong></td></tr>
<tr><td>Qty 5 @ JLCPCB</td><td class="cost"><strong>~$146.25</strong></td></tr>
</table>
<div class="footnote">
⚠️ PCB layout shown is a schematic-derived approximation — the KiCad PCB file (commit 0ae2ca6) has the board outline and mounting holes. Component footprints need human placement review before Gerber export. Open in KiCad to see the actual routed layout.
</div>
</div>
</div>
<div style="margin-top: 30px; max-width: 860px; width: 100%;">
<div style="background: #1a1a1a; border: 1px solid #333; border-radius: 12px; padding: 20px;">
<h2 style="color: #999; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 12px;">Schematic Preview (from KiCad .sch file)</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; font-size: 0.8rem;">
<div style="background: #111; border: 1px solid #222; border-radius: 6px; padding: 12px;">
<div style="color: #4fc3f7; font-weight: 600; margin-bottom: 6px;">Page 1 — Power</div>
<div>5V rail → <span style="color:#ef5350;">U1 AMS1117</span> → 3.3V</div>
<div>C1 (10µF) + C2 (100nF) input decoupling</div>
<div>C3 (10µF) + C4 (100nF) output decoupling</div>
</div>
<div style="background: #111; border: 1px solid #222; border-radius: 6px; padding: 12px;">
<div style="color: #66bb6a; font-weight: 600; margin-bottom: 6px;">Page 2 — RPi Header</div>
<div><span style="color:#4fc3f7;">J1</span> 2×20 stacking header</div>
<div>All 40 GPIO pins pass through</div>
<div>I2S: BCLK(18) LRCLK(19) DIN(20) DOUT(21)</div>
</div>
<div style="background: #111; border: 1px solid #222; border-radius: 6px; padding: 12px;">
<div style="color: #66bb6a; font-weight: 600; margin-bottom: 6px;">Page 3 — Preamp</div>
<div><span style="color:#fbbf24;">J2</span> Guitar in → R1(1MΩ) pulldown</div>
<div>→ R2(10k) → <span style="color:#66bb6a;">U2 TL072</span> non-inv (+) input</div>
<div>Gain = 1 + R3(100k)/R4(10k) = <strong>~20dB</strong></div>
<div>→ C5(10µF) DC-block → PCM1808</div>
</div>
<div style="background: #111; border: 1px solid #222; border-radius: 6px; padding: 12px;">
<div style="color: #a78bfa; font-weight: 600; margin-bottom: 6px;">Page 4 — ADC + DAC</div>
<div><span style="color:#a78bfa;">U3 PCM1808</span>: I2S, 48kHz, always active</div>
<div>C6(100nF) + C7(10µF) decoupling</div>
<div><span style="color:#4fc3f7;">U4 PCM5102</span>: low-latency filter, unmuted</div>
<div>C8(100nF) + C9(10µF) decoupling</div>
<div>Output → R5(330Ω) + C10(10µF) → <span style="color:#fbbf24;">J3</span></div>
</div>
<div style="background: #111; border: 1px solid #222; border-radius: 6px; padding: 12px;">
<div style="color: #888; font-weight: 600; margin-bottom: 6px;">Page 5 — Output Buffer</div>
<div>U2 TL072 (half 2): output buffer stage</div>
<div>R6(10k) feedback resistor</div>
</div>
<div style="background: #111; border: 1px solid #222; border-radius: 6px; padding: 12px;">
<div style="color: #888; font-weight: 600; margin-bottom: 6px;">I2S Bus Labels</div>
<div>Global net labels: <span style="color:#fbbf24;">I2S_BCLK</span>, <span style="color:#fbbf24;">I2S_LRCLK</span></div>
<div><span style="color:#fbbf24;">I2S_DIN</span> (RPi←ADC), <span style="color:#fbbf24;">I2S_DOUT</span> (RPi→DAC)</div>
</div>
</div>
</div>
</div>
</body>
</html>
+297
View File
@@ -0,0 +1,297 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pi Multi-FX — Boss-Size Touchscreen Pedal</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: #0d0d0d;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
padding: 40px 20px;
color: #e0e0e0;
}
h1 { font-size: 1.4rem; margin-bottom: 4px; }
h2 { font-size: 1rem; margin-bottom: 4px; color: #ccc; }
.subtitle { color: #999; font-size: 0.85rem; margin-bottom: 20px; }
.container { display: flex; flex-wrap: wrap; gap: 30px; justify-content: center; max-width: 1100px; }
.panel {
background: #1a1a1a;
border: 1px solid #333;
border-radius: 12px;
padding: 20px;
}
.panel h3 {
font-size: 0.8rem;
color: #999;
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 12px;
}
.comp-table { width: 100%; font-size: 0.82rem; border-collapse: collapse; }
.comp-table td { padding: 8px 6px; border-bottom: 1px solid #222; }
.comp-table td:first-child { color: #888; white-space: nowrap; padding-right: 12px; }
.comp-table td:last-child { color: #e0e0e0; }
.cost-row td { border-bottom: none !important; padding-top: 12px !important; }
.cost-row td:last-child { color: #ffa726; font-weight: 600; font-size: 1rem; }
.label { color: #4fc3f7; }
.accent { color: #66bb6a; }
.warn { color: #ffa726; }
.check { color: #66bb6a; }
svg text { font-family: 'Courier New', monospace; }
.ruler-label { fill: #666; font-size: 7px; text-anchor: middle; }
</style>
</head>
<body>
<h1>🎸 Pi Multi-FX — Boss-Size Touchscreen Concept</h1>
<div class="subtitle">1590BB Enclosure · 5" DSI Touch · I2S HAT Stack</div>
<div class="container">
<!-- Main concept image -->
<div class="panel">
<h3>Exploded View — Stackup</h3>
<svg width="480" height="520" viewBox="0 0 480 520">
<!-- Background grid -->
<pattern id="g" width="20" height="20" patternUnits="userSpaceOnUse">
<path d="M 20 0 L 0 0 0 20" fill="none" stroke="#1a1a1a" stroke-width="0.3"/>
</pattern>
<rect x="0" y="0" width="480" height="520" fill="url(#g)"/>
<!-- 1. Top: Touchscreen Layer -->
<g transform="translate(80, 10)">
<!-- Screen glass -->
<rect x="0" y="0" width="280" height="168" rx="8" fill="rgba(79,195,247,0.08)" stroke="#4fc3f7" stroke-width="1.5"/>
<rect x="6" y="6" width="268" height="156" rx="5" fill="rgba(0,0,0,0.3)" stroke="rgba(79,195,247,0.2)" stroke-width="0.5"/>
<!-- Simulated UI -->
<rect x="20" y="16" width="100" height="18" rx="3" fill="rgba(79,195,247,0.2)"/>
<text x="70" y="29" text-anchor="middle" fill="#4fc3f7" font-size="7">Preset: Crunch Lead</text>
<rect x="10" y="40" width="80" height="30" rx="4" fill="rgba(102,187,106,0.15)" stroke="rgba(102,187,106,0.3)" stroke-width="0.5"/>
<text x="50" y="51" text-anchor="middle" fill="#66bb6a" font-size="6">BYPASS</text>
<text x="50" y="62" text-anchor="middle" fill="#66bb6a" font-size="6">ACTIVE</text>
<!-- Slider mockups -->
<rect x="100" y="40" width="80" height="8" rx="2" fill="#333"/>
<circle cx="130" cy="44" r="5" fill="#4fc3f7"/>
<text x="140" y="60" text-anchor="start" fill="#888" font-size="6">Volume</text>
<!-- FX chain pills -->
<rect x="10" y="78" width="50" height="16" rx="8" fill="rgba(167,139,250,0.2)" stroke="#a78bfa" stroke-width="0.5"/>
<text x="35" y="89" text-anchor="middle" fill="#a78bfa" font-size="6">NAM Amp</text>
<rect x="65" y="78" width="36" height="16" rx="8" fill="rgba(102,187,106,0.2)" stroke="#66bb6a" stroke-width="0.5"/>
<text x="83" y="89" text-anchor="middle" fill="#66bb6a" font-size="6">Delay</text>
<rect x="105" y="78" width="44" height="16" rx="8" fill="rgba(79,195,247,0.2)" stroke="#4fc3f7" stroke-width="0.5"/>
<text x="127" y="89" text-anchor="middle" fill="#4fc3f7" font-size="6">Reverb</text>
<!-- Bottom bar -->
<rect x="10" y="105" width="240" height="20" rx="4" fill="rgba(79,195,247,0.08)" stroke="rgba(79,195,247,0.15)" stroke-width="0.5"/>
<text x="130" y="118" text-anchor="middle" fill="#888" font-size="6">4CM · Send→Pre · Post→Return</text>
<text x="10" y="150" fill="#666" font-size="7">5" DSI Capacitive Touch</text>
</g>
<!-- Spacer arrow 1 -->
<g transform="translate(220, 185)">
<line x1="0" y1="0" x2="0" y2="15" stroke="#555" stroke-width="0.8" stroke-dasharray="2,2"/>
<polygon points="-3,15 0,19 3,15" fill="#555"/>
</g>
<!-- 2. Middle: Display Driver PCB (Waveshare 5" DSI board) -->
<g transform="translate(75, 205)">
<rect x="0" y="0" width="290" height="40" rx="3" fill="rgba(79,195,247,0.1)" stroke="#4fc3f7" stroke-width="1"/>
<text x="145" y="18" text-anchor="middle" fill="#4fc3f7" font-size="9">Waveshare 5" DSI Display Board</text>
<text x="145" y="30" text-anchor="middle" fill="#888" font-size="7">102×76mm — Ribbon to RPi DSI port</text>
</g>
<!-- Spacer arrow 2 -->
<g transform="translate(220, 250)">
<line x1="0" y1="0" x2="0" y2="20" stroke="#555" stroke-width="0.8" stroke-dasharray="2,2"/>
<polygon points="-3,20 0,24 3,20" fill="#555"/>
<text x="-30" y="12" fill="#666" font-size="6">Standoffs</text>
</g>
<!-- 3. RPi 4B -->
<g transform="translate(60, 280)">
<rect x="0" y="0" width="320" height="60" rx="4" fill="rgba(102,187,106,0.12)" stroke="#66bb6a" stroke-width="1.5"/>
<text x="160" y="22" text-anchor="middle" fill="#66bb6a" font-size="10">Raspberry Pi 4B</text>
<text x="160" y="36" text-anchor="middle" fill="#888" font-size="7">85×56mm · USB-C · HDMI · DSI · GPIO 40-pin</text>
<!-- DSI port indicator -->
<rect x="5" y="42" width="40" height="12" rx="2" fill="rgba(79,195,247,0.15)" stroke="#4fc3f7" stroke-width="0.5"/>
<text x="25" y="51" text-anchor="middle" fill="#4fc3f7" font-size="6">DSI→</text>
<!-- Stacking GPIO header -->
<rect x="120" y="42" width="80" height="12" rx="2" fill="rgba(79,195,247,0.15)" stroke="#4fc3f7" stroke-width="0.5"/>
<text x="160" y="51" text-anchor="middle" fill="#4fc3f7" font-size="6">GPIO 40-pin ↓</text>
</g>
<!-- Spacer arrow 3 — GPIO passthrough -->
<g transform="translate(220, 345)">
<line x1="0" y1="0" x2="0" y2="20" stroke="#555" stroke-width="0.8" stroke-dasharray="2,2"/>
<polygon points="-3,20 0,24 3,20" fill="#555"/>
<text x="16" y="12" fill="#4fc3f7" font-size="6">Stacking Hdr</text>
</g>
<!-- 4. I2S HAT (65×56mm) -->
<g transform="translate(97, 380)">
<rect x="0" y="0" width="240" height="48" rx="4" fill="rgba(167,139,250,0.12)" stroke="#a78bfa" stroke-width="1.5"/>
<text x="120" y="18" text-anchor="middle" fill="#a78bfa" font-size="10">PCM1808+PCM5102 I2S HAT</text>
<text x="120" y="32" text-anchor="middle" fill="#888" font-size="7">65×56mm · Preamp → ADC → DSP → DAC</text>
<!-- I2S bus indicator -->
<rect x="85" y="36" width="70" height="10" rx="2" fill="rgba(251,191,36,0.12)" stroke="#fbbf24" stroke-width="0.5"/>
<text x="120" y="44" text-anchor="middle" fill="#fbbf24" font-size="6">I2S ↔ RPi</text>
</g>
<!-- Audio jacks — side mounted -->
<g transform="translate(50, 385)">
<rect x="-12" y="-8" width="14" height="55" rx="3" fill="rgba(251,191,36,0.12)" stroke="#fbbf24" stroke-width="1"/>
<text x="-5" y="0" text-anchor="middle" fill="#fbbf24" font-size="6">J</text>
<text x="-5" y="10" text-anchor="middle" fill="#fbbf24" font-size="5">I</text>
<text x="-5" y="20" text-anchor="middle" fill="#fbbf24" font-size="5">N</text>
<line x1="-12" y1="25" x2="0" y2="25" stroke="#fbbf24" stroke-width="0.5"/>
<line x1="-12" y1="30" x2="0" y2="30" stroke="#fbbf24" stroke-width="0.5"/>
</g>
<g transform="translate(375, 385)">
<rect x="0" y="-8" width="14" height="55" rx="3" fill="rgba(251,191,36,0.12)" stroke="#fbbf24" stroke-width="1"/>
<text x="7" y="0" text-anchor="middle" fill="#fbbf24" font-size="6">J</text>
<text x="7" y="10" text-anchor="middle" fill="#fbbf24" font-size="5">O</text>
<text x="7" y="20" text-anchor="middle" fill="#fbbf24" font-size="5">U</text>
<text x="7" y="30" text-anchor="middle" fill="#fbbf24" font-size="5">T</text>
</g>
<!-- 5. 1590BB Enclosure Outline -->
<rect x="38" y="375" width="364" height="130" rx="10" fill="none" stroke="#fbbf24" stroke-width="1.5" stroke-dasharray="8,4"/>
<text x="220" y="520" text-anchor="middle" fill="#fbbf24" font-size="8">1590BB Enclosure (140×78mm face · ~48mm deep)</text>
<!-- Dimension arrows on enclosure -->
<line x1="38" y1="525" x2="402" y2="525" stroke="#555" stroke-width="0.5"/>
<polygon points="38,523 38,527" fill="#555" stroke="#555" stroke-width="0.5"/>
<polygon points="402,523 402,527" fill="#555" stroke="#555" stroke-width="0.5"/>
<text x="220" y="522" text-anchor="middle" fill="#555" font-size="7">~140mm (Boss-compatible)</text>
<!-- Stackup depth -->
<line x1="420" y1="10" x2="420" y2="505" stroke="#555" stroke-width="0.5"/>
<text x="424" y="260" text-anchor="start" fill="#555" font-size="7" transform="rotate(90,424,260)">~38mm total stack (w/ standoffs)</text>
<!-- Labels -->
<text x="10" y="180" fill="#4fc3f7" font-size="7">① Touch</text>
<text x="10" y="220" fill="#4fc3f7" font-size="7">② Display PCB</text>
<text x="10" y="305" fill="#66bb6a" font-size="7">③ RPi 4B</text>
<text x="10" y="405" fill="#a78bfa" font-size="7">④ I2S HAT</text>
<text x="10" y="470" fill="#fbbf24" font-size="7">⑤ 1590BB Box</text>
</svg>
</div>
<!-- Specs & BOM side panel -->
<div class="panel" style="min-width: 300px;">
<h3>Component Stack — 1590BB Build</h3>
<table class="comp-table">
<tr><td>Enclosure</td><td>1590BB diecast aluminum</td></tr>
<tr><td></td><td><span class="warn">140×78×48mm</span> — Boss compact size</td></tr>
<tr><td colspan="2" style="padding-top:8px; border-bottom:1px solid #444;"></td></tr>
<tr><td>Touchscreen</td><td><span class="label">Waveshare 5" DSI</span></td></tr>
<tr><td></td><td>800×480, capacitive multi-touch</td></tr>
<tr><td></td><td><span class="check"></span> Native RPi DSI — no HDMI needed</td></tr>
<tr><td></td><td><span class="check"></span> Fits 1590BB face with border</td></tr>
<tr><td colspan="2" style="padding-top:8px; border-bottom:1px solid #444;"></td></tr>
<tr><td>Brain</td><td><span class="label">RPi 4B</span> (2GB+)</td></tr>
<tr><td></td><td>DietPi, headless, JACK + Python DSP</td></tr>
<tr><td colspan="2" style="padding-top:8px; border-bottom:1px solid #444;"></td></tr>
<tr><td>Audio</td><td><span class="label">PCM1808+PCM5102 I2S HAT</span></td></tr>
<tr><td></td><td>Custom 65×56mm PCB (already designed)</td></tr>
<tr><td></td><td>Stacking header passes GPIO to display</td></tr>
<tr><td></td><td><span class="check"></span> < 10ms round-trip</td></tr>
<tr><td colspan="2" style="padding-top:8px; border-bottom:1px solid #444;"></td></tr>
<tr><td>Connectivity</td><td>USB-C (power only)</td></tr>
<tr><td></td><td>WiFi for `pedal.local` web UI</td></tr>
<tr><td></td><td>Bluetooth for wireless MIDI</td></tr>
<tr><td colspan="2" style="padding-top:8px; border-bottom:1px solid #444;"></td></tr>
<tr><td>I/O Panel</td><td>Side-mounted: Input, Send, Return, Output</td></tr>
<tr><td></td><td>USB-C power, MIDI DIN (optional)</td></tr>
<tr><td colspan="2" style="padding-top:12px; border-bottom:none;" class="cost-row"></td></tr>
<tr class="cost-row"><td>Est. BOM (5 pcs)</td><td><strong>~$175-200</strong> per unit</td></tr>
</table>
</div>
</div>
<!-- Detail sections -->
<div style="margin-top: 30px; max-width: 1100px; width: 100%; display: flex; flex-wrap: wrap; gap: 20px;">
<!-- Mechanical -->
<div class="panel" style="flex: 1; min-width: 280px;">
<h3>📐 Mechanical Stack</h3>
<div style="display: grid; grid-template-columns: 1fr; gap: 4px; font-size: 0.85rem;">
<div style="display: flex; justify-content: space-between; padding: 4px 0; border-bottom: 1px solid #222;">
<span style="color:#888;">Touch layer</span>
<span>5" glass + front bezel</span>
</div>
<div style="display: flex; justify-content: space-between; padding: 4px 0; border-bottom: 1px solid #222;">
<span style="color:#888;">Display PCB</span>
<span>8mm standoff</span>
</div>
<div style="display: flex; justify-content: space-between; padding: 4px 0; border-bottom: 1px solid #222;">
<span style="color:#888;">RPi 4B</span>
<span>10mm standoff (above HAT)</span>
</div>
<div style="display: flex; justify-content: space-between; padding: 4px 0; border-bottom: 1px solid #222;">
<span style="color:#888;">Stacking header</span>
<span>GPIO pass-through</span>
</div>
<div style="display: flex; justify-content: space-between; padding: 4px 0; border-bottom: 1px solid #222;">
<span style="color:#888;">I2S HAT</span>
<span>6mm standoff → enclosure base</span>
</div>
<div style="display: flex; justify-content: space-between; padding: 4px 0;">
<span style="color:#888;">Total depth</span>
<span style="color:#4fc3f7;"><strong>~38-42mm</strong> (fits 48mm 1590BB)</span>
</div>
</div>
</div>
<!-- Wiring -->
<div class="panel" style="flex: 1; min-width: 280px;">
<h3>🔌 Internal Wiring</h3>
<div style="font-size: 0.82rem; display: flex; flex-direction: column; gap: 6px;">
<div><span style="color:#4fc3f7;">Display</span> → DSI ribbon (15-pin) → RPi DSI port</div>
<div><span style="color:#a78bfa;">I2S HAT</span> → mounts on RPi GPIO via stacking header</div>
<div><span style="color:#fbbf24;">Audio jacks</span> → flying leads to HAT I/O pads</div>
<div><span style="color:#66bb6a;">Power</span> → USB-C → RPi → 5V rail → I2S HAT</div>
<div><span style="color:#888;">Footswitches</span> (optional) → GPIO via HAT passthrough</div>
</div>
</div>
<!-- Caveats -->
<div class="panel" style="flex: 1; min-width: 280px;">
<h3>⚠️ Things to Sort</h3>
<div style="font-size: 0.82rem; display: flex; flex-direction: column; gap: 6px;">
<div><span class="warn"></span> <span style="color:#ccc;">Jacks:</span> Need right-angle PCB-mount jacks for side fit — or wire to chassis-mount jacks on enclosure walls</div>
<div><span class="warn"></span> <span style="color:#ccc;">DSI ribbon:</span> Needs careful routing past the stacking header. 15-pin flat flex cable, keep away from I2S traces</div>
<div><span class="warn"></span> <span style="color:#ccc;">I2S HAT Rev:</span> The current PCB is 65×56mm (1590B). For 1590BB you could make it slightly wider to match — but it works as-is</div>
<div><span class="warn"></span> <span style="color:#ccc;">Heat:</span> RPi 4B in an enclosed box gets warm. Consider a vent slot or small fan on the side</div>
</div>
</div>
</div>
<!-- Boss comparison -->
<div style="margin-top: 20px; max-width: 1100px; width: 100%;">
<div class="panel">
<h3>📏 Size Comparison vs Boss Pedal</h3>
<svg width="860" height="100" viewBox="0 0 860 100">
<!-- Boss pedal -->
<rect x="20" y="20" width="260" height="56" rx="8" fill="rgba(239,83,80,0.1)" stroke="#ef5350" stroke-width="1.5"/>
<text x="150" y="53" text-anchor="middle" fill="#ef5350" font-size="11">Boss DS-1 / BD-2 (129×73mm)</text>
<text x="150" y="67" text-anchor="middle" fill="#666" font-size="8">Baseline compact pedal</text>
<!-- 1590B (current) -->
<rect x="310" y="25" width="220" height="46" rx="6" fill="rgba(251,191,36,0.1)" stroke="#fbbf24" stroke-width="1.5"/>
<text x="420" y="53" text-anchor="middle" fill="#fbbf24" font-size="11">1590B (112×60mm)</text>
<text x="420" y="67" text-anchor="middle" fill="#666" font-size="8">Current HAT size</text>
<!-- 1590BB (proposed) -->
<rect x="560" y="18" width="280" height="60" rx="8" fill="rgba(102,187,106,0.12)" stroke="#66bb6a" stroke-width="2"/>
<text x="700" y="53" text-anchor="middle" fill="#66bb6a" font-size="11">1590BB (140×78mm)</text>
<text x="700" y="67" text-anchor="middle" fill="#66bb6a" font-size="8"><strong>Boss-compatible + touchscreen</strong></text>
<!-- Arrow showing fit -->
<line x1="580" y1="84" x2="820" y2="84" stroke="#66bb6a" stroke-width="0.5" stroke-dasharray="3,2"/>
<text x="700" y="96" text-anchor="middle" fill="#66bb6a" font-size="7">✅ 5" display fits inside with 15mm border all round</text>
</svg>
</div>
</div>
</body>
</html>