diff --git a/frontend/src/simulation/spice/boardPinGroups.ts b/frontend/src/simulation/spice/boardPinGroups.ts index ffad82a0..abdab436 100644 --- a/frontend/src/simulation/spice/boardPinGroups.ts +++ b/frontend/src/simulation/spice/boardPinGroups.ts @@ -17,6 +17,12 @@ export interface BoardPinGroup { type AllBoardKinds = BoardKind | 'default'; +const STM32_GROUP: BoardPinGroup = { + vcc: 3.3, + gnd: ['GND', 'GND.1', 'GND.2', 'GND.3', 'GND.4'], + vcc_pins: ['3V3', '3V3.1', '3V3.2', '5V', 'VBAT', 'VB'], +}; + export const BOARD_PIN_GROUPS: Record = { default: { vcc: 5, gnd: ['GND', 'GND.1', 'GND.2'], vcc_pins: ['5V', 'VCC'] }, @@ -37,6 +43,16 @@ export const BOARD_PIN_GROUPS: Record = { }, attiny85: { vcc: 5, gnd: ['GND'], vcc_pins: ['VCC'] }, + // STM32 family — 3.3 V logic. Bluepill silkscreens repeat bare GND/3V3. + 'stm32-bluepill': STM32_GROUP, + 'stm32-bluepill-f103cb': STM32_GROUP, + 'stm32-blackpill': STM32_GROUP, + 'stm32-blackpill-f401': STM32_GROUP, + 'stm32-f4-discovery': STM32_GROUP, + 'stm32-olimex-h405': STM32_GROUP, + 'stm32-netduino-plus2': STM32_GROUP, + 'stm32-netduino2': STM32_GROUP, + 'raspberry-pi-pico': { vcc: 3.3, gnd: ['GND.1', 'GND.2', 'GND.3', 'GND'], diff --git a/frontend/src/simulation/spice/collectPinStates.ts b/frontend/src/simulation/spice/collectPinStates.ts index 1524e40c..40c2775a 100644 --- a/frontend/src/simulation/spice/collectPinStates.ts +++ b/frontend/src/simulation/spice/collectPinStates.ts @@ -92,20 +92,27 @@ export function collectPinStates( const outputPins = pm.getOutputPins(); // STM32 names pins PA0/PC13 and keys its PinManager on the linear pin - // (port*16+pin). It runs in backend QEMU, where its OUTPUT pins are surfaced - // to the canvas via the part layer (not SPICE), so here we only contribute - // the INPUT internal pull (reported by the worker's gpio_pull) — enough for - // NetlistBuilder to stamp the weak resistor so an INPUT_PULLUP button-to-GND - // solves to idle-HIGH / pressed-LOW. connectDigitalInputsToMcu then drives - // the guest IDR from the solve. Leaving outputs out keeps STM32 LED rendering - // exactly as before. + // (port*16+pin). It runs in backend QEMU; the worker streams gpio_change + // for outputs and gpio_pull for inputs. Outputs were historically LEFT OUT + // of the netlist ("the part layer will render them") — but the part layer + // never drove wired parts, so a correctly-wired LED sat at ~0 A forever + // (lianqi 07-23, emulation-gaps F3). Now that the name mapping is right, + // stamp outputs as V sources exactly like every other board; inputs still + // contribute only their internal pull. const isStm32 = isStm32BoardKind(boardKind); if (isStm32) { for (const pinName of pinNames) { const linear = stm32PinNameToLinear(pinName); - if (linear < 0 || outputPins.has(linear)) continue; - const pull = pm.getPinPull(linear); - if (pull !== 0) result[pinName] = { type: 'input', pull }; + if (linear < 0) continue; + if (outputPins.has(linear)) { + result[pinName] = { + type: 'digital', + v: pm.getPinState(linear) ? vcc : 0, + }; + } else { + const pull = pm.getPinPull(linear); + if (pull !== 0) result[pinName] = { type: 'input', pull }; + } } return result; }