feat: enhance simulator interfaces and add ESP32 bridge shim for improved component interaction

pull/47/head
David Montero Crespo 2026-03-22 02:25:58 -03:00
parent ee7281383c
commit 84370e6f8d
3 changed files with 59 additions and 4 deletions

View File

@ -1,7 +1,14 @@
import { AVRSimulator } from '../AVRSimulator';
import { RP2040Simulator } from '../RP2040Simulator';
export type AnySimulator = AVRSimulator | RP2040Simulator;
/** Any simulator that components can interact with (AVR, RP2040, or ESP32 bridge shim). */
export type AnySimulator = {
setPinState(pin: number, state: boolean): void;
isRunning(): boolean;
pinManager: import('../PinManager').PinManager;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
} | AVRSimulator | RP2040Simulator;
/**
* Interface for simulation logic mapped to a specific wokwi-element

View File

@ -35,8 +35,41 @@ export const BOARD_LABELS: Record<BoardType, string> = {
export const DEFAULT_BOARD_POSITION = { x: 50, y: 50 };
export const ARDUINO_POSITION = DEFAULT_BOARD_POSITION;
// ── Lightweight shim wrapping Esp32Bridge so component simulations (DHT22, etc.)
// can call setPinState / pinManager just like they would on a local simulator. ──
class Esp32BridgeShim {
pinManager: PinManager;
onSerialData: ((ch: string) => void) | null = null;
onPinChangeWithTime: ((pin: number, state: boolean, timeMs: number) => void) | null = null;
onBaudRateChange: ((baud: number) => void) | null = null;
private bridge: Esp32Bridge;
constructor(bridge: Esp32Bridge, pm: PinManager) {
this.bridge = bridge;
this.pinManager = pm;
}
setPinState(pin: number, state: boolean): void { this.bridge.sendPinEvent(pin, state); }
getCurrentCycles(): number { return -1; }
getClockHz(): number { return 240_000_000; }
isRunning(): boolean { return this.bridge.connected; }
serialWrite(text: string): void {
this.bridge.sendSerialBytes(Array.from(new TextEncoder().encode(text)));
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getADC(): any { return null; }
getMCU(): null { return null; }
start(): void { /* managed by bridge */ }
stop(): void { /* managed by bridge */ }
reset(): void { /* managed by bridge */ }
setSpeed(_s: number): void { /* no-op */ }
getSpeed(): number { return 1; }
loadHex(_hex: string): void { /* no-op */ }
loadBinary(_b64: string): void { /* no-op */ }
}
// ── Runtime Maps (outside Zustand — not serialisable) ─────────────────────
const simulatorMap = new Map<string, AVRSimulator | RP2040Simulator | RiscVSimulator | Esp32C3Simulator>();
const simulatorMap = new Map<string, AVRSimulator | RP2040Simulator | RiscVSimulator | Esp32C3Simulator | Esp32BridgeShim>();
const pinManagerMap = new Map<string, PinManager>();
const bridgeMap = new Map<string, RaspberryPi3Bridge>();
const esp32BridgeMap = new Map<string, Esp32Bridge>();
@ -97,7 +130,7 @@ interface SimulatorState {
/** @deprecated use boards[x].x/y */
boardPosition: { x: number; y: number };
/** @deprecated use getBoardSimulator(activeBoardId) */
simulator: AVRSimulator | RP2040Simulator | RiscVSimulator | Esp32C3Simulator | null;
simulator: AVRSimulator | RP2040Simulator | RiscVSimulator | Esp32C3Simulator | Esp32BridgeShim | null;
/** @deprecated use getBoardPinManager(activeBoardId) */
pinManager: PinManager;
running: boolean;
@ -337,6 +370,11 @@ export const useSimulatorStore = create<SimulatorState>((set, get) => {
}
};
esp32BridgeMap.set(id, bridge);
// Provide a shim so PartSimulationRegistry components (DHT22, etc.)
// can call setPinState / access pinManager on ESP32 boards.
const shim = new Esp32BridgeShim(bridge, pm);
shim.onSerialData = serialCallback;
simulatorMap.set(id, shim);
} else {
const sim = createSimulator(
boardKind,
@ -645,10 +683,13 @@ export const useSimulatorStore = create<SimulatorState>((set, get) => {
}
};
esp32BridgeMap.set(boardId, bridge);
const shim = new Esp32BridgeShim(bridge, pm);
shim.onSerialData = serialCallback;
simulatorMap.set(boardId, shim);
set((s) => ({
boardType: type,
simulator: null,
simulator: shim as any,
compiledHex: null,
serialOutput: '',
serialBaudRate: 0,

View File

@ -132,6 +132,13 @@ const ESP32_PIN_MAP: Record<string, number> = {
'GPIO25': 25, 'GPIO26': 26, 'GPIO27': 27,
'GPIO32': 32, 'GPIO33': 33, 'GPIO34': 34, 'GPIO35': 35,
'GPIO36': 36, 'GPIO39': 39,
// Wokwi element "D" prefix aliases (esp32-devkit-v1-element pin names)
'D2': 2, 'D4': 4, 'D5': 5,
'D12': 12, 'D13': 13, 'D14': 14, 'D15': 15,
'D16': 16, 'D17': 17, 'D18': 18, 'D19': 19,
'D21': 21, 'D22': 22, 'D23': 23,
'D25': 25, 'D26': 26, 'D27': 27,
'D32': 32, 'D33': 33, 'D34': 34, 'D35': 35,
// ADC aliases
'VP': 36, 'VN': 39,
// Power / GND — not real GPIOs; mapped to -1 so WirePin skips silently