feat: enhance simulator interfaces and add ESP32 bridge shim for improved component interaction
parent
ee7281383c
commit
84370e6f8d
|
|
@ -1,7 +1,14 @@
|
||||||
import { AVRSimulator } from '../AVRSimulator';
|
import { AVRSimulator } from '../AVRSimulator';
|
||||||
import { RP2040Simulator } from '../RP2040Simulator';
|
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
|
* Interface for simulation logic mapped to a specific wokwi-element
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,41 @@ export const BOARD_LABELS: Record<BoardType, string> = {
|
||||||
export const DEFAULT_BOARD_POSITION = { x: 50, y: 50 };
|
export const DEFAULT_BOARD_POSITION = { x: 50, y: 50 };
|
||||||
export const ARDUINO_POSITION = DEFAULT_BOARD_POSITION;
|
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) ─────────────────────
|
// ── 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 pinManagerMap = new Map<string, PinManager>();
|
||||||
const bridgeMap = new Map<string, RaspberryPi3Bridge>();
|
const bridgeMap = new Map<string, RaspberryPi3Bridge>();
|
||||||
const esp32BridgeMap = new Map<string, Esp32Bridge>();
|
const esp32BridgeMap = new Map<string, Esp32Bridge>();
|
||||||
|
|
@ -97,7 +130,7 @@ interface SimulatorState {
|
||||||
/** @deprecated use boards[x].x/y */
|
/** @deprecated use boards[x].x/y */
|
||||||
boardPosition: { x: number; y: number };
|
boardPosition: { x: number; y: number };
|
||||||
/** @deprecated use getBoardSimulator(activeBoardId) */
|
/** @deprecated use getBoardSimulator(activeBoardId) */
|
||||||
simulator: AVRSimulator | RP2040Simulator | RiscVSimulator | Esp32C3Simulator | null;
|
simulator: AVRSimulator | RP2040Simulator | RiscVSimulator | Esp32C3Simulator | Esp32BridgeShim | null;
|
||||||
/** @deprecated use getBoardPinManager(activeBoardId) */
|
/** @deprecated use getBoardPinManager(activeBoardId) */
|
||||||
pinManager: PinManager;
|
pinManager: PinManager;
|
||||||
running: boolean;
|
running: boolean;
|
||||||
|
|
@ -337,6 +370,11 @@ export const useSimulatorStore = create<SimulatorState>((set, get) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
esp32BridgeMap.set(id, bridge);
|
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 {
|
} else {
|
||||||
const sim = createSimulator(
|
const sim = createSimulator(
|
||||||
boardKind,
|
boardKind,
|
||||||
|
|
@ -645,10 +683,13 @@ export const useSimulatorStore = create<SimulatorState>((set, get) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
esp32BridgeMap.set(boardId, bridge);
|
esp32BridgeMap.set(boardId, bridge);
|
||||||
|
const shim = new Esp32BridgeShim(bridge, pm);
|
||||||
|
shim.onSerialData = serialCallback;
|
||||||
|
simulatorMap.set(boardId, shim);
|
||||||
|
|
||||||
set((s) => ({
|
set((s) => ({
|
||||||
boardType: type,
|
boardType: type,
|
||||||
simulator: null,
|
simulator: shim as any,
|
||||||
compiledHex: null,
|
compiledHex: null,
|
||||||
serialOutput: '',
|
serialOutput: '',
|
||||||
serialBaudRate: 0,
|
serialBaudRate: 0,
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,13 @@ const ESP32_PIN_MAP: Record<string, number> = {
|
||||||
'GPIO25': 25, 'GPIO26': 26, 'GPIO27': 27,
|
'GPIO25': 25, 'GPIO26': 26, 'GPIO27': 27,
|
||||||
'GPIO32': 32, 'GPIO33': 33, 'GPIO34': 34, 'GPIO35': 35,
|
'GPIO32': 32, 'GPIO33': 33, 'GPIO34': 34, 'GPIO35': 35,
|
||||||
'GPIO36': 36, 'GPIO39': 39,
|
'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
|
// ADC aliases
|
||||||
'VP': 36, 'VN': 39,
|
'VP': 36, 'VN': 39,
|
||||||
// Power / GND — not real GPIOs; mapped to -1 so WirePin skips silently
|
// Power / GND — not real GPIOs; mapped to -1 so WirePin skips silently
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue