From 6a7b72138f5c8c0cf08f32e7d09cf57813a47c8f Mon Sep 17 00:00:00 2001 From: David Montero Crespo Date: Fri, 15 May 2026 00:23:36 -0300 Subject: [PATCH] fix(rp2040): route SPI0 through the adapter in initMCU too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Long-standing latent bug: SPI parts (ILI9341, custom chips, etc.) register a handler on simulator.spi.onByte via the lazy adapter, but the actual rp2040.spi[0].onTransmit assignment in initMCU was a pure loopback that never consulted the adapter. The MicroPython init path (initMicroPython) had the adapter-aware version since day one; the Arduino path (initMCU) didn't. Symptom: Pico Doom + every other Arduino sketch driving an ILI9341 on the RP2040 saw an empty SPI bus. The ILI9341 emulator's onByte handler was wired up correctly — it just never received a single byte. Pantalla negra. Fix: copy the adapter-aware handler from initMicroPython (line 219) into initMCU (line 441). Each byte the firmware writes to SPI0 now checks `_spiAdapter.onByte` first; if a part is registered, it gets the byte; otherwise we keep the original loopback as the fallback so plain "echo MOSI back as MISO" sketches still work. Combined with the earlier MADCTL fix (commit 6edc715) and the power+MISO wiring fix (8440836), Pico Doom should now render its title screen + the raycaster. Build verified (vite OSS+pro, 285 SEO pages). Co-Authored-By: Claude Opus 4.7 (1M context) --- frontend/src/simulation/RP2040Simulator.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/frontend/src/simulation/RP2040Simulator.ts b/frontend/src/simulation/RP2040Simulator.ts index 9f6de79a..04adf228 100644 --- a/frontend/src/simulation/RP2040Simulator.ts +++ b/frontend/src/simulation/RP2040Simulator.ts @@ -437,9 +437,21 @@ export class RP2040Simulator { this.wireI2C(0); this.wireI2C(1); - // ── Wire SPI0 and SPI1 — default loopback ──────────────────────── - this.rp2040.spi[0].onTransmit = (value: number) => { - this.rp2040!.spi[0].completeTransmit(value); // loopback + // ── Wire SPI0 and SPI1 ──────────────────────────────────────────── + // SPI0 must check for a registered .spi adapter on every byte. If a + // part on the canvas (ILI9341, custom chip, …) accessed simulator.spi + // BEFORE this initMCU runs, the adapter is already staged but + // _adapter.onByte points at the part's handler — we have to route + // the byte through it. Without this, SPI parts see nothing and the + // canvas stays black (real regression — Pico Doom shipped with this + // bug for months because the same wiring in initMicroPython was + // adapter-aware but this Arduino path wasn't). + this.rp2040.spi[0].onTransmit = (v: number) => { + if (this._spiAdapter && this._spiAdapter.onByte) { + this._spiAdapter.onByte(v); + } else { + this.rp2040!.spi[0].completeTransmit(v); + } }; this.rp2040.spi[1].onTransmit = (value: number) => { this.rp2040!.spi[1].completeTransmit(value); // loopback