feat(sim): board-agnostic microphone seam + reSpeaker gallery glyph

setMicrophoneSource on the simulator shim mirrors addI2CDevice: a part
that produces audio hands one 16-bit sample per call to whatever bridge
implements the method (the in-browser JS-engine bridges); everywhere
else the optional chain makes it a silent mic. No board-kind checks in
components. Plus the flat reSpeaker Lite glyph for gallery cards.
This commit is contained in:
David Montero Crespo 2026-07-31 03:30:13 +02:00
parent e9053f73fe
commit 08c5626b79
2 changed files with 32 additions and 0 deletions

View File

@ -447,7 +447,26 @@ const EPaperGlyph: React.FC<InlineSVGProps> = ({ w, h }) => {
);
};
// ── reSpeaker Lite (dual-mic array board) — flat glyph for gallery cards ────
const RespeakerLite = () => (
<svg viewBox="0 0 240 100" xmlns="http://www.w3.org/2000/svg">
<rect x="4" y="10" width="232" height="86" rx="10" fill="#14161a" stroke="#2c2e34" strokeWidth="2" />
<circle cx="34" cy="52" r="7" fill="#0c0d10" stroke="#4a4f59" />
<circle cx="206" cy="52" r="7" fill="#0c0d10" stroke="#4a4f59" />
<rect x="96" y="32" width="48" height="32" rx="3" fill="#b9bec7" stroke="#8a8f99" />
<rect x="103" y="38" width="34" height="20" fill="#3a3f49" />
<text x="120" y="51" fontSize="7" fontFamily="monospace" fill="#e8e8ec" textAnchor="middle">
XU316
</text>
<text x="120" y="90" fontSize="7" fontFamily="monospace" fill="#cfd3da" textAnchor="middle">
ReSpeaker Lite
</text>
</svg>
);
export const INLINE_SVGS: Record<string, InlineEntry> = {
// Audio front-ends
'respeaker-lite': { component: RespeakerLite, w: 240, h: 100 },
// BJTs
'wokwi-bjt-2n2222': { component: BjtNpn, w: 72, h: 72 },
'wokwi-bjt-2n3904': { component: BjtNpn, w: 72, h: 72 },

View File

@ -395,6 +395,19 @@ class Esp32BridgeShim {
(this.bridge as { attachSyncI2cDevice?: (d: I2CDevice) => void }).attachSyncI2cDevice?.(device);
}
/**
* Attach (or clear, with null) the microphone sample source feeding the
* board's I2S RX path: one signed 16-bit sample per call. Same forwarding
* pattern as addI2CDevice the in-browser JS-engine bridges implement
* setMicrophoneSource (velxio-prod overlay); everywhere else it's a no-op,
* which reads as a silent mic.
*/
setMicrophoneSource(source: (() => number) | null): void {
(
this.bridge as { setMicrophoneSource?: (s: (() => number) | null) => void }
).setMicrophoneSource?.(source);
}
/** Remove a previously-registered virtual device. */
removeI2CDevice(addr: number, _bus: 0 | 1 = 0): void {
this.i2cBusInstance.removeDevice(addr);