diff --git a/doc/ARCHITECTURE.md b/doc/ARCHITECTURE.md index 22afff0f..488ecce6 100644 --- a/doc/ARCHITECTURE.md +++ b/doc/ARCHITECTURE.md @@ -1,70 +1,90 @@ -# Project Architecture - Arduino Emulator +# Project Architecture - OpenWokwi Arduino Emulator ## Overview -This project is a fully local Arduino emulator using official Wokwi repositories for maximum compatibility. +This project is a fully local Arduino emulator using official Wokwi repositories for maximum compatibility. It features real AVR8 CPU emulation, 48+ interactive electronic components, a comprehensive wire system, and a build-time component discovery pipeline. ``` -┌─────────────────────────────────────────────────────────────┐ -│ USER (Browser) │ -│ http://localhost:5173 │ -└──────────────────────────┬──────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────────────┐ +│ USER (Browser) │ +│ http://localhost:5173 │ +└──────────────────────────┬──────────────────────────────────────────┘ │ ▼ -┌─────────────────────────────────────────────────────────────┐ -│ FRONTEND (React + Vite) │ -│ │ -│ ┌────────────────┐ ┌──────────────────┐ ┌─────────────┐ │ -│ │ Monaco Editor │ │ Zustand Store │ │ Simulator │ │ -│ │ (Code Edit) │ │ (State Mgmt) │ │ Canvas │ │ -│ └────────────────┘ └──────────────────┘ └─────────────┘ │ -│ │ │ │ │ -│ └───────────────────┴──────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌──────────────────────────────────────────────────────┐ │ -│ │ Wokwi Components Integration │ │ -│ │ (wokwi-elements + avr8js from local repos) │ │ -│ └──────────────────────────────────────────────────────┘ │ -└──────────────────────────┬──────────────────────────────────┘ - │ HTTP (axios) +┌─────────────────────────────────────────────────────────────────────┐ +│ FRONTEND (React 19 + Vite 7) │ +│ │ +│ ┌────────────────┐ ┌──────────────────┐ ┌───────────────────┐ │ +│ │ Monaco Editor │ │ Zustand Stores │ │ SimulatorCanvas │ │ +│ │ (Code Edit) │ │ (Editor+Sim) │ │ (Components+ │ │ +│ │ C++ / Arduino │ │ │ │ Wires+Pins) │ │ +│ └────────┬───────┘ └────────┬─────────┘ └────────┬──────────┘ │ +│ │ │ │ │ +│ ▼ ▼ ▼ │ +│ ┌──────────────────────────────────────────────────────────────┐ │ +│ │ AVRSimulator (avr8js) │ │ +│ │ CPU 16MHz · Timer0/1/2 · USART · ADC · PORTB/C/D │ │ +│ │ ~60fps · 267k cycles/frame · Speed 0.1x-10x │ │ +│ └──────────────────────────────┬───────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────────────────────────────────────────────────────────┐ │ +│ │ PinManager + PartSimulationRegistry │ │ +│ │ Digital/PWM/Analog listeners · 16 registered parts │ │ +│ │ LED · RGB · Button · Pot · LCD · Servo · Buzzer · etc. │ │ +│ └──────────────────────────────┬───────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────────────────────────────────────────────────────────┐ │ +│ │ 48+ wokwi-elements (Lit Web Components) │ │ +│ │ DynamicComponent renderer · ComponentRegistry (metadata) │ │ +│ │ ComponentPickerModal · Property dialog · Pin selector │ │ +│ └──────────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────────────────────────┐ │ +│ │ Wire System │ │ +│ │ Orthogonal routing · Segment editing · 8 signal colors │ │ +│ │ Overlap offset · Pin overlay · Grid snapping (20px) │ │ +│ └──────────────────────────────────────────────────────────────┘ │ +└──────────────────────────┬──────────────────────────────────────────┘ + │ HTTP (Axios) ▼ -┌─────────────────────────────────────────────────────────────┐ -│ BACKEND (FastAPI + Python) │ -│ http://localhost:8000 │ -│ │ -│ ┌─────────────────────────────────────────────────────┐ │ -│ │ POST /api/compile │ │ -│ │ - Receives Arduino code (.ino) │ │ -│ │ - Compiles with arduino-cli │ │ -│ │ - Returns .hex file │ │ -│ └─────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────┐ │ -│ │ Arduino CLI Service │ │ -│ │ (Invokes arduino-cli as subprocess) │ │ -│ └─────────────────────────────────────────────────────┘ │ -└──────────────────────────┬──────────────────────────────────┘ - │ - ▼ - ┌──────────────────────┐ - │ arduino-cli │ - │ (Local system) │ - └──────────────────────┘ +┌─────────────────────────────────────────────────────────────────────┐ +│ BACKEND (FastAPI + Python) │ +│ http://localhost:8001 │ +│ │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ POST /api/compile/ → Compile Arduino code to .hex │ │ +│ │ GET /api/compile/boards → List available boards │ │ +│ │ GET / → API info │ │ +│ │ GET /health → Health check │ │ +│ └──────────────────────────────┬──────────────────────────────┘ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ ArduinoCLIService │ │ +│ │ Auto-installs arduino:avr core │ │ +│ │ Temp directory + subprocess.run via asyncio.to_thread │ │ +│ └──────────────────────────────┬──────────────────────────────┘ │ +└─────────────────────────────────┼──────────────────────────────────┘ + │ + ▼ + ┌──────────────────────┐ + │ arduino-cli │ + │ (Local system) │ + └──────────────────────┘ ``` -## Data Flow: Compilation and Simulation +## Data Flow ### 1. Code Editing ``` -User writes code +User writes Arduino code ↓ -Monaco Editor +Monaco Editor (C++, dark theme, autocomplete) ↓ -Zustand (useEditorStore) +Zustand useEditorStore ↓ -State: code +State: { code, theme, fontSize } ``` ### 2. Compilation @@ -73,57 +93,83 @@ Click "Compile" ↓ EditorToolbar.tsx → compileCode() ↓ -Axios POST → http://localhost:8000/api/compile +Axios POST → http://localhost:8001/api/compile/ ↓ Backend: ArduinoCLIService.compile() ↓ -arduino-cli compile --fqbn arduino:avr:uno +arduino-cli compile --fqbn arduino:avr:uno --output-dir build/ ↓ -Generates .hex file in temp directory +Reads build/sketch.ino.hex → returns hex_content ↓ -Backend reads .hex and returns content +Frontend: useSimulatorStore.setCompiledHex(hex) ↓ -Frontend: useSimulatorStore.setCompiledHex() +Auto-calls loadHex() → CPU + peripherals created ``` -### 3. Simulation (Currently simplified) +### 3. Simulation (Real AVR8 Emulation) ``` Click "Run" ↓ -useSimulatorStore.setRunning(true) +useSimulatorStore.startSimulation() ↓ -SimulatorCanvas: useEffect detects running=true +AVRSimulator.start() ↓ -setInterval every 1000ms +requestAnimationFrame loop @ ~60fps ↓ -updateComponentState('led-builtin', !state) +Each frame: Math.floor(267000 × speed) cycles ↓ -wokwi-led component updates visually +For each cycle: + ├── avrInstruction(cpu) ← Execute AVR instruction + └── cpu.tick() ← Update peripherals/timers + ↓ +Port writes → AVRIOPort listeners + ↓ +PinManager.updatePort(portName, newValue, oldValue) + ↓ +Per-pin callbacks fire for changed pins + ↓ +PartSimulationRegistry.onPinStateChange() + ↓ +wokwi web components update visually + +Additionally per frame: + pollPwmRegisters() → reads OCR0A/B, OCR1AL/BL, OCR2A/B + ↓ + PinManager.updatePwm(pin, dutyCycle) ``` -### 4. Real Simulation (Coming with avr8js) +### 4. Input Components Flow ``` -Compiled .hex file +User presses a pushbutton on canvas ↓ -AVRSimulator.loadHex(hex) +Web component fires 'button-press' event ↓ -hexParser → Uint16Array (program memory) +DynamicComponent catches event ↓ -CPU = new CPU(program) +PartSimulationRegistry.attachEvents() handler ↓ -Click "Run" → AVRSimulator.start() +AVRSimulator.setPinState(arduinoPin, LOW) ↓ -requestAnimationFrame loop +AVRIOPort.setPin(bitIndex) injects external pin state ↓ -CPU.tick() × 267,000 cycles/frame +CPU reads pin value in next instruction +``` + +### 5. Wire Creation Flow +``` +Click pin on component A → startWireCreation(endpoint) ↓ -Writes to PORTB/PORTC/PORTD +Mouse move → updateWireInProgress(x, y) ↓ -Write hooks → PinManager.updatePort() +WireInProgressRenderer shows dashed green L-shape preview ↓ -PinManager notifies callbacks +Click pin on component B → finishWireCreation(endpoint) ↓ -Components update visual state +Wire created with midpoint control point + ↓ +WireLayer renders orthogonal SVG path + ↓ +Components subscribe to Arduino pins via wire lookup ``` ## Key Components @@ -131,81 +177,215 @@ Components update visual state ### Frontend #### 1. Stores (Zustand) -- **[useEditorStore.ts](frontend/src/store/useEditorStore.ts)** - - `code`: Current source code - - `theme`: Editor theme (dark/light) - - `setCode()`: Update code -- **[useSimulatorStore.ts](frontend/src/store/useSimulatorStore.ts)** - - `running`: Simulation state - - `compiledHex`: Compiled hex file - - `components`: List of electronic components - - `setCompiledHex()`: Save hex - - `updateComponentState()`: Update LED/component +**useEditorStore** — Code editor state +| Property | Type | Default | +|----------|------|---------| +| `code` | `string` | Blink example sketch | +| `theme` | `'vs-dark' \| 'light'` | `'vs-dark'` | +| `fontSize` | `number` | `14` | -#### 2. UI Components -- **[CodeEditor.tsx](frontend/src/components/editor/CodeEditor.tsx)** - - Monaco Editor wrapper - - C++ syntax highlighting - - Auto-completion +Methods: `setCode()`, `setTheme()`, `setFontSize()` -- **[EditorToolbar.tsx](frontend/src/components/editor/EditorToolbar.tsx)** - - Buttons: Compile, Run, Stop - - Compilation state handling - - Error/success messages +**useSimulatorStore** — Simulation + components + wires state +| Property | Type | Description | +|----------|------|-------------| +| `simulator` | `AVRSimulator \| null` | CPU emulator instance | +| `pinManager` | `PinManager` | Pin-to-component mapping | +| `running` | `boolean` | Simulation active | +| `compiledHex` | `string \| null` | Compiled hex content | +| `components` | `Component[]` | All electronic components | +| `wires` | `Wire[]` | All wire connections | +| `selectedWireId` | `string \| null` | Currently selected wire | +| `wireInProgress` | `WireInProgress \| null` | Wire being created | -- **[SimulatorCanvas.tsx](frontend/src/components/simulator/SimulatorCanvas.tsx)** - - Renders Arduino Uno - - Renders components (LEDs) - - Simulation loop +Methods (20+): +- **Simulation**: `initSimulator()`, `loadHex()`, `startSimulation()`, `stopSimulation()`, `resetSimulation()`, `setCompiledHex()`, `setRunning()` +- **Components**: `addComponent()`, `removeComponent()`, `updateComponent()`, `updateComponentState()`, `handleComponentEvent()`, `setComponents()` +- **Wires**: `addWire()`, `removeWire()`, `updateWire()`, `setSelectedWire()`, `setWires()` +- **Wire creation**: `startWireCreation()`, `updateWireInProgress()`, `finishWireCreation()`, `cancelWireCreation()` +- **Wire positions**: `updateWirePositions(componentId)`, `recalculateAllWirePositions()` -#### 3. Wokwi Component Wrappers -- **[LED.tsx](frontend/src/components/components-wokwi/LED.tsx)** - - React wrapper for `` - - Props: color, value, x, y +Notable behaviors: +- `removeComponent()` cascades: removes all connected wires +- `updateComponent()` auto-recalculates wire positions when x/y changes +- `setCompiledHex()` auto-calls `loadHex()` -- **[ArduinoUno.tsx](frontend/src/components/components-wokwi/ArduinoUno.tsx)** - - React wrapper for `` - - Internal LED control (pin 13) +#### 2. Simulation Engine -- **[Resistor.tsx](frontend/src/components/components-wokwi/Resistor.tsx)** - - React wrapper for `` - - Props: value (ohms) +**AVRSimulator** — Real ATmega328p emulation +- **CPU**: 16MHz clock, 32KB program memory (16K words) +- **Timers**: Timer0 (`timer0Config`), Timer1 (`timer1Config`), Timer2 (`timer2Config`) +- **Serial**: USART (`usart0Config`) at 16MHz +- **ADC**: Analog-to-digital converter (`adcConfig`) +- **GPIO**: PORTB (pins 8-13), PORTC (A0-A5), PORTD (pins 0-7) +- **Simulation loop**: ~60fps via `requestAnimationFrame`, `267000 × speed` cycles/frame +- **Speed control**: 0.1x – 10x multiplier +- **PWM polling**: Reads OCR0A/B, OCR1AL/BL, OCR2A/B each frame +- **API**: `loadHex()`, `start()`, `stop()`, `reset()`, `step()`, `setSpeed()`, `setPinState()`, `getADC()` -- **[Pushbutton.tsx](frontend/src/components/components-wokwi/Pushbutton.tsx)** - - React wrapper for `` - - Events: onPress, onRelease +**PinManager** — Pin state tracking and listener dispatch +- **Digital**: `onPinChange(pin, callback)`, `updatePort(portName, newValue, oldValue)`, `getPinState(pin)` +- **PWM**: `onPwmChange(pin, callback)`, `updatePwm(pin, dutyCycle)`, `getPwmValue(pin)` +- **Analog**: `onAnalogChange(pin, callback)`, `setAnalogVoltage(pin, voltage)` +- **Utility**: `getListenersCount()`, `clearAllListeners()` + +**PartSimulationRegistry** — Plugin system for component behaviors +- Interface: `onPinStateChange(pinName, state, element)` for outputs, `attachEvents(element, simulator, pinHelper) → cleanup` for inputs +- **16 registered parts**: + +| Part | Type | Key Behavior | +|------|------|--------------| +| `led` | Output | Pin A state → `element.value` | +| `rgb-led` | Output | Digital + PWM on R/G/B → `ledRed/Green/Blue` | +| `led-bar-graph` | Output | 10 LEDs (A1-A10) → `.values` array | +| `7segment` | Output | 8 segments (A-G + DP) → `.values` array | +| `pushbutton` | Input | Press/release → `setPinState(pin, LOW/HIGH)` | +| `pushbutton-6mm` | Input | Same as pushbutton | +| `slide-switch` | Input | Change event → pin state | +| `dip-switch-8` | Input | 8 independent switches | +| `potentiometer` | Input | Value (0-1023) → ADC voltage injection | +| `slide-potentiometer` | Input | Same via SIG/OUT pins | +| `photoresistor-sensor` | Input/Output | Default 2.5V on AO, monitors DO for LED | +| `analog-joystick` | Input | VRX/VRY (ADC) + SW (digital) | +| `servo` | Output | Polls OCR1A/ICR1 → angle 0-180° | +| `buzzer` | Output | Web Audio API, reads Timer2 registers | +| `lcd1602` | Output | Full HD44780 4-bit protocol (16×2) | +| `lcd2004` | Output | Full HD44780 4-bit protocol (20×4) | + +#### 3. Component System + +**ComponentRegistry** — Singleton from `/components-metadata.json` +- **48 components** across 8 categories +- Auto-generated at build time by `scripts/generate-component-metadata.ts` (TypeScript AST parser) +- Methods: `getAllComponents()`, `getByCategory()`, `getById()`, `search()`, `getCategories()` + +| Category | Count | Components | +|----------|-------|------------| +| Boards | 4 | Arduino Uno, Mega, Nano, etc. | +| Sensors | 6 | DHT22, HC-SR04, PIR, photoresistor, etc. | +| Displays | 3 | LCD 1602, LCD 2004, 7-segment | +| Input | 5 | Buttons, switches, potentiometers, joystick | +| Output | 5 | LEDs, RGB LED, LED bar graph, buzzer | +| Motors | 2 | Servo, stepper | +| Passive | 4 | Resistor, capacitor, etc. | +| Other | 19 | Various components | + +**DynamicComponent** — Generic web component renderer +- Creates DOM elements with `document.createElement(metadata.tagName)` +- Syncs React properties to web component properties +- Extracts `pinInfo` from web component DOM (100ms polling, 2s timeout) +- Integrates with PartSimulationRegistry for simulation events +- Resolves Arduino pin from wire connections +- Handles visual state: selection border, rotation, cursor, labels + +**ComponentPickerModal** — Component search and selection UI +- Search bar with real-time filtering +- Category tabs from registry +- Live wokwi-element thumbnails (actual web components at reduced scale) +- Component count, pin count, description badges + +#### 4. UI Components + +**SimulatorCanvas** (~472 lines) — Main simulation canvas +- Arduino Uno board at fixed position +- Dynamic component rendering via DynamicComponent +- Component drag-and-drop with viewport→canvas coordinate conversion +- Click vs. drag detection (time <300ms, distance <5px threshold) +- Single-click: opens ComponentPropertyDialog +- Double-click: opens PinSelector +- Wire creation via pin clicks (crosshair cursor during creation) +- Wire auto-recalculation on component move (retries at 100/300/500ms) +- PinOverlay on all components (hidden during simulation) +- Keyboard shortcuts: Delete/Backspace (remove), Escape (cancel wire) +- PinManager subscriptions for output component state updates +- Status indicator: Running/Stopped + component count +- "+ Add Component" button → opens ComponentPickerModal + +**WireRenderer** (~400 lines) — Interactive wire display and editing +- Orthogonal SVG path rendering +- 10px invisible hitbox for easy clicking +- Segment-based editing: hover highlights, drag perpendicular to orientation +- `requestAnimationFrame` smooth drag with local preview state +- Grid snapping (20px) applied on mouseUp +- Invalid wire styling (red dashed) +- Endpoint markers at start/end + +**WireLayer** — SVG overlay with automatic offset calculation for overlapping wires + +**WireInProgressRenderer** — Dashed green preview during wire creation (L-shaped routing) + +**PinOverlay** — 12px cyan circles at each pin position; green on hover with scale animation + +**ComponentPropertyDialog** — Shows pin roles, Arduino pin assignment, Rotate and Delete buttons + +**PinSelector** — Modal for assigning D0-D13 and A0-A5 to component pins + +**CodeEditor** — Monaco Editor wrapper (C++, dark theme, minimap, word wrap) + +**EditorToolbar** — Compile/Run/Stop/Reset buttons with status messages + +**ExamplesGallery** — Filterable card grid (category + difficulty filters) + +#### 5. Wire Utilities + +| Utility | Purpose | +|---------|---------| +| `wirePathGenerator.ts` | L-shape and multi-segment orthogonal SVG path generation | +| `wireSegments.ts` | Segment computation, hit testing (8px tolerance), drag updates | +| `wireColors.ts` | 8 signal-type colors + `determineSignalType()` | +| `wireOffsetCalculator.ts` | Parallel overlap detection (5px tolerance), symmetric offset (6px spacing) | +| `pinPositionCalculator.ts` | Pin coordinate conversion (element → canvas space), closest pin snap (20px) | +| `hexParser.ts` | Intel HEX parser with checksum verification | +| `captureCanvasPreview.ts` | SVG foreignObject preview image generation | ### Backend -#### 1. API Routes -- **[compile.py](backend/app/api/routes/compile.py)** - - `POST /api/compile`: Compile code - - `GET /api/compile/boards`: List boards +**FastAPI** app (port 8001) with CORS for ports 5173-5175 -#### 2. Services -- **[arduino_cli.py](backend/app/services/arduino_cli.py)** - - `compile()`: Compile sketch with arduino-cli - - `list_boards()`: Get available boards - - Temporary directory management +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/` | GET | API info | +| `/health` | GET | Health check | +| `/api/compile/` | POST | Compile Arduino code → hex content | +| `/api/compile/boards` | GET | List available boards | -### Wokwi Libraries (Cloned Locally) +**ArduinoCLIService**: +- Auto-installs `arduino:avr` core if missing +- Creates temp sketch directory, runs `arduino-cli compile` via `asyncio.to_thread(subprocess.run)` +- Reads `build/sketch.ino.hex` output +- Board listing via `arduino-cli board listall` -#### 1. wokwi-elements -- **Location**: `wokwi-libs/wokwi-elements/` -- **Build**: `dist/esm/` and `dist/cjs/` -- **Components**: 50+ electronic elements -- **Technology**: Lit (Web Components) +### Pages & Routing -#### 2. avr8js -- **Location**: `wokwi-libs/avr8js/` -- **Build**: `dist/esm/` and `dist/cjs/` -- **Functionality**: Complete ATmega328p emulator -- **Supports**: CPU, Timers, USART, GPIO, ADC, etc. +| Route | Page | Layout | +|-------|------|--------| +| `/` | EditorPage | Header + split panels: Editor (left) + Simulator (right) | +| `/examples` | ExamplesPage | Examples gallery with "Back to Editor" link | -#### 3. rp2040js -- **Location**: `wokwi-libs/rp2040js/` -- **Future use**: Raspberry Pi Pico support +### Example Projects (8) + +| ID | Title | Category | Difficulty | +|----|-------|----------|------------| +| `blink-led` | Blink LED | basics | beginner | +| `traffic-light` | Traffic Light | basics | beginner | +| `button-led` | Button Control | basics | beginner | +| `fade-led` | Fade LED | basics | beginner | +| `serial-hello` | Serial Hello World | communication | beginner | +| `rgb-led` | RGB LED Colors | basics | intermediate | +| `simon-says` | Simon Says Game | games | advanced | +| `lcd-hello` | LCD 20x4 Display | displays | intermediate | + +Each example includes full Arduino sketch, component definitions, and wire connections. + +### Wokwi Libraries (Local Clones) + +| Library | Location | Purpose | +|---------|----------|---------| +| wokwi-elements | `wokwi-libs/wokwi-elements/` | 48+ Lit Web Components | +| avr8js | `wokwi-libs/avr8js/` | AVR8 ATmega328p emulator | +| rp2040js | `wokwi-libs/rp2040js/` | RP2040 emulator (future) | +| wokwi-features | `wokwi-libs/wokwi-features/` | Features documentation | ## Vite Integration @@ -217,99 +397,85 @@ resolve: { 'avr8js': path.resolve(__dirname, '../wokwi-libs/avr8js/dist/esm'), '@wokwi/elements': path.resolve(__dirname, '../wokwi-libs/wokwi-elements/dist/esm'), }, +}, +optimizeDeps: { + include: ['avr8js', '@wokwi/elements'], } ``` This allows: -- Use local repos instead of npm +- Import from local repos as if they were npm packages - Easy updates with `git pull` -- Modify source code if needed +- Modify source code if needed for debugging ## Technology Stack ### Frontend | Technology | Version | Purpose | -|------------|---------|-----------| +|------------|---------|---------| | React | 19.2 | UI framework | | Vite | 7.3 | Build tool & dev server | | TypeScript | 5.9 | Static typing | -| Monaco Editor | 4.7 | Code editor (VSCode) | +| Monaco Editor | 4.7 | Code editor (VS Code engine) | | Zustand | 5.0 | State management | +| React Router | 7.13 | Client-side routing | | Axios | 1.13 | HTTP client | -| wokwi-elements | 1.9.2 | Electronic components | -| avr8js | 0.21.0 | AVR8 emulator | +| wokwi-elements | local | 48+ electronic web components | +| avr8js | local | AVR8 CPU emulator | ### Backend | Technology | Version | Purpose | -|------------|---------|-----------| +|------------|---------|---------| | Python | 3.12+ | Runtime | | FastAPI | 0.115 | Web framework | | Uvicorn | 0.32 | ASGI server | -| SQLAlchemy | 2.0 | ORM (future) | -| aiosqlite | 0.20 | Async DB (future) | ### External Tools | Tool | Purpose | |------|---------| -| arduino-cli | Arduino compiler | +| arduino-cli | Arduino compiler (subprocess) | | Git | Version control for Wokwi libs | ## Architecture Advantages +### ✅ Real Emulation +- True AVR8 CPU execution, not simulation mockups +- Same avr8js engine used by Wokwi.com +- Accurate timing with configurable speed + +### ✅ Plugin-Based Component Behaviors +- PartSimulationRegistry decouples simulation logic from rendering +- Easy to add new component behaviors +- Supports both input (event-driven) and output (pin-state-driven) components + +### ✅ Automatic Component Discovery +- Build-time TypeScript AST parser extracts metadata from wokwi-elements source +- No manual component registration needed +- New wokwi-elements components appear automatically after rebuild + ### ✅ Separation of Concerns -- **Frontend**: UI, UX, visualization -- **Backend**: Compilation, business logic -- **Wokwi Libs**: Emulation and components (maintained by Wokwi) +- **Frontend**: UI, visualization, simulation engine +- **Backend**: Compilation via arduino-cli +- **Wokwi Libs**: Emulation and components (maintained by Wokwi community) ### ✅ Wokwi Compatibility -- Official repositories = same functionality +- Official repositories = same functionality as Wokwi.com - Automatic updates with `git pull` -- New components available immediately - -### ✅ Scalability -- Frontend can easily add more components -- Backend can add more endpoints (projects, sensors) -- Wokwi libs update independently +- New components available immediately after rebuild ### ✅ Local Development -- No internet required to work +- No internet required after initial setup - Local compilation with arduino-cli -- Local database (SQLite) +- All simulation runs in the browser -## Upcoming Improvements +## Planned Improvements -### Phase 2: Real Emulation (avr8js) -``` -[ ] Implement AVRSimulator.ts -[ ] Intel HEX file parser -[ ] PinManager with write hooks -[ ] Integrate CPU execution loop -[ ] Map Arduino pins to components -``` - -### Phase 3: More Components -``` -[ ] Integrate more wokwi-elements -[ ] Buttons, potentiometers -[ ] Sensors (DHT22, HC-SR04) -[ ] Displays (LCD, 7-segment) -``` - -### Phase 4: Persistence -``` -[ ] SQLite database -[ ] SQLAlchemy models -[ ] Project CRUD -[ ] Save circuits as JSON -``` - -### Phase 5: Advanced Features -``` -[ ] Serial Monitor -[ ] Visual wiring (drag & drop) -[ ] Multiple boards (Mega, Nano, ESP32) -[ ] Export to Wokwi.com -``` +- 📋 **Serial Monitor** — UI for USART output display +- 📋 **Project Persistence** — SQLite database for save/load +- 📋 **Undo/Redo** — Edit history for code and circuit changes +- 📋 **Multi-board Support** — Runtime board switching (Mega, Nano, ESP32) +- 📋 **Wire Validation** — Electrical validation and error highlighting +- 📋 **Export/Import** — Share projects as files ## References diff --git a/doc/WOKWI_LIBS.md b/doc/WOKWI_LIBS.md index b296ebdd..51385747 100644 --- a/doc/WOKWI_LIBS.md +++ b/doc/WOKWI_LIBS.md @@ -1,29 +1,29 @@ # Wokwi Libraries Integration -Este proyecto utiliza los repositorios oficiales de Wokwi clonados localmente, lo que permite mantenerlos actualizados y compatibles con las últimas versiones. +Este proyecto utiliza los repositorios oficiales de Wokwi clonados localmente, lo que permite mantenerlos actualizados y compatibles con las últimas versiones. Los repositorios locales alimentan tanto la emulación AVR como el sistema dinámico de componentes con 48+ elementos electrónicos. ## Repositorios Clonados ### 📦 wokwi-elements - **Ubicación**: `wokwi-libs/wokwi-elements/` -- **Descripción**: Web Components para elementos electrónicos (LEDs, resistencias, botones, etc.) +- **Descripción**: Web Components (Lit) para 48+ elementos electrónicos (LEDs, resistencias, botones, LCDs, sensores, etc.) - **Repositorio**: https://github.com/wokwi/wokwi-elements - **Licencia**: MIT -- **Versión actual**: 1.9.2 +- **Uso actual**: Renderizado visual de todos los componentes en el canvas de simulación. Un script de generación de metadata (`scripts/generate-component-metadata.ts`) parsea el código fuente TypeScript para descubrir automáticamente todos los componentes, sus propiedades y pines. ### 🎮 avr8js - **Ubicación**: `wokwi-libs/avr8js/` -- **Descripción**: Emulador de microcontroladores AVR8 (Arduino Uno, Mega, etc.) en JavaScript +- **Descripción**: Emulador completo de microcontroladores AVR8 (ATmega328p) en JavaScript - **Repositorio**: https://github.com/wokwi/avr8js - **Licencia**: MIT -- **Versión actual**: 0.21.0 +- **Uso actual**: Emulación real del CPU a 16MHz, con Timer0/1/2, USART, ADC, y puertos GPIO (PORTB/C/D). Ejecuta ~267,000 ciclos por frame a ~60fps. ### 🚀 rp2040js - **Ubicación**: `wokwi-libs/rp2040js/` - **Descripción**: Emulador de Raspberry Pi Pico (RP2040) en JavaScript - **Repositorio**: https://github.com/wokwi/rp2040js - **Licencia**: MIT -- **Uso**: Futuro soporte para Raspberry Pi Pico +- **Uso**: Clonado para futuro soporte de Raspberry Pi Pico ### 📝 wokwi-features - **Ubicación**: `wokwi-libs/wokwi-features/` @@ -34,7 +34,7 @@ Este proyecto utiliza los repositorios oficiales de Wokwi clonados localmente, l ### Frontend (Vite) -El archivo [vite.config.ts](frontend/vite.config.ts) está configurado para usar los repositorios locales: +El archivo `frontend/vite.config.ts` está configurado para usar los repositorios locales mediante aliases: ```typescript resolve: { @@ -42,10 +42,13 @@ resolve: { 'avr8js': path.resolve(__dirname, '../wokwi-libs/avr8js/dist/esm'), '@wokwi/elements': path.resolve(__dirname, '../wokwi-libs/wokwi-elements/dist/esm'), }, +}, +optimizeDeps: { + include: ['avr8js', '@wokwi/elements'], } ``` -El archivo [package.json](frontend/package.json) referencia los paquetes locales: +El archivo `frontend/package.json` referencia los paquetes locales: ```json { @@ -56,6 +59,16 @@ El archivo [package.json](frontend/package.json) referencia los paquetes locales } ``` +### Generación Automática de Metadata + +El script `scripts/generate-component-metadata.ts` parsea el código fuente de wokwi-elements usando AST de TypeScript para extraer: +- Nombre del tag (`@customElement('wokwi-led')` → `wokwi-led`) +- Propiedades (`@property()` decorators → tipo, valor por defecto) +- Cantidad de pines +- Categoría, descripción y tags + +El resultado se almacena en `frontend/public/components-metadata.json` y es consumido por el `ComponentRegistry` en tiempo de ejecución. + ## Actualizar las Librerías de Wokwi Para mantener tu proyecto actualizado con las últimas versiones de Wokwi: @@ -63,16 +76,14 @@ Para mantener tu proyecto actualizado con las últimas versiones de Wokwi: ### Opción 1: Actualizar todas las librerías (Recomendado) ```bash -cd e:\Hardware\wokwi_clon - # Script para actualizar todos los repositorios -./update-wokwi-libs.bat +update-wokwi-libs.bat ``` ### Opción 2: Actualizar manualmente cada repositorio ```bash -cd e:\Hardware\wokwi_clon\wokwi-libs +cd wokwi-libs # Actualizar wokwi-elements cd wokwi-elements @@ -96,7 +107,7 @@ npm run build ### Opción 3: Actualizar a una versión específica ```bash -cd e:\Hardware\wokwi_clon\wokwi-libs\wokwi-elements +cd wokwi-libs/wokwi-elements # Ver versiones disponibles git tag -l @@ -109,16 +120,24 @@ npm install npm run build ``` +### Después de Actualizar wokwi-elements + +Si actualizaste wokwi-elements, regenera la metadata de componentes para que nuevos componentes aparezcan en la UI: + +```bash +cd frontend +npx tsx ../scripts/generate-component-metadata.ts +``` + ## Script de Actualización Automática -Se ha creado un script [update-wokwi-libs.bat](update-wokwi-libs.bat) para facilitar las actualizaciones: +El script `update-wokwi-libs.bat` facilita las actualizaciones: ```batch @echo off echo ======================================== echo Actualizando Wokwi Libraries echo ======================================== -echo. cd wokwi-libs @@ -129,7 +148,6 @@ npm install npm run build cd .. -echo. echo [2/3] Actualizando avr8js... cd avr8js git pull origin main @@ -137,7 +155,6 @@ npm install npm run build cd .. -echo. echo [3/3] Actualizando rp2040js... cd rp2040js git pull origin main @@ -145,109 +162,165 @@ npm install npm run build cd .. -echo. echo ======================================== echo Actualizacion completada! echo ======================================== pause ``` +## Cómo Se Usan las Librerías + +### avr8js — Emulación AVR + +El `AVRSimulator` (`frontend/src/simulation/AVRSimulator.ts`) usa avr8js para crear: + +```typescript +import { CPU, avrInstruction, AVRTimer, AVRUSART, AVRADC, AVRIOPort } from 'avr8js'; + +// CPU ATmega328p a 16MHz +const cpu = new CPU(programMemory); + +// Periféricos +const timer0 = new AVRTimer(cpu, timer0Config); +const timer1 = new AVRTimer(cpu, timer1Config); +const timer2 = new AVRTimer(cpu, timer2Config); +const usart = new AVRUSART(cpu, usart0Config, CLOCK); +const adc = new AVRADC(cpu, adcConfig); +const portB = new AVRIOPort(cpu, portBConfig); // pins 8-13 +const portC = new AVRIOPort(cpu, portCConfig); // A0-A5 +const portD = new AVRIOPort(cpu, portDConfig); // pins 0-7 + +// Loop de simulación (~60fps) +function runFrame() { + const cyclesToRun = Math.floor(267000 * speed); + for (let i = 0; i < cyclesToRun; i++) { + avrInstruction(cpu); // Ejecuta instrucción AVR + cpu.tick(); // Actualiza periféricos + } + requestAnimationFrame(runFrame); +} +``` + +### wokwi-elements — Componentes Visuales + +Los componentes se renderizan de dos formas: + +**1. DynamicComponent (sistema actual — 48 componentes)** + +```typescript +import { ComponentRegistry } from './services/ComponentRegistry'; + +// Carga metadata desde /components-metadata.json +const registry = ComponentRegistry.getInstance(); +const metadata = registry.getById('led'); + +// DynamicComponent crea el web component dinámicamente +// document.createElement(metadata.tagName) → +// Sincroniza propiedades React → web component +// Extrae pinInfo del DOM para wire connections +``` + +**2. React wrappers legacy (5 componentes)** + +```tsx +// ArduinoUno.tsx — sigue en uso activo para el board principal + +``` + +### PartSimulationRegistry — Comportamientos de Simulación + +16 partes tienen lógica de simulación registrada que conecta los web components con el emulador AVR: + +| Parte | Tipo | Comportamiento | +|-------|------|----------------| +| `led` | Output | Pin state → `element.value` | +| `rgb-led` | Output | Digital + PWM en R/G/B | +| `led-bar-graph` | Output | 10 LEDs independientes | +| `7segment` | Output | 8 segmentos (A-G + DP) | +| `pushbutton` | Input | Press/release → `setPinState()` | +| `pushbutton-6mm` | Input | Mismo que pushbutton | +| `slide-switch` | Input | Change event → pin state | +| `dip-switch-8` | Input | 8 switches independientes | +| `potentiometer` | Input | Valor → voltaje ADC | +| `slide-potentiometer` | Input | Misma lógica por SIG/OUT | +| `photoresistor-sensor` | Input/Output | Voltaje analógico + LED digital | +| `analog-joystick` | Input | VRX/VRY (ADC) + SW (digital) | +| `servo` | Output | Registros OCR1A/ICR1 → ángulo 0-180° | +| `buzzer` | Output | Web Audio API + Timer2 | +| `lcd1602` | Output | Protocolo HD44780 4-bit completo (16×2) | +| `lcd2004` | Output | Protocolo HD44780 4-bit completo (20×4) | + +## Componentes Wokwi Disponibles (48) + +### Boards (4) +- `wokwi-arduino-uno` — Arduino Uno R3 +- `wokwi-arduino-mega` — Arduino Mega 2560 +- `wokwi-arduino-nano` — Arduino Nano +- `wokwi-esp32-devkit-v1` — ESP32 DevKit v1 + +### Sensors (6) +- `wokwi-dht22` — Temperatura y humedad +- `wokwi-hc-sr04` — Ultrasónico de distancia +- `wokwi-pir-motion-sensor` — Sensor de movimiento PIR +- `wokwi-photoresistor-sensor` — Fotoresistor (LDR) +- `wokwi-ntc-temperature-sensor` — Sensor NTC +- `wokwi-analog-joystick` — Joystick analógico + +### Displays (3) +- `wokwi-lcd1602` — LCD 16x2 con protocolo HD44780 +- `wokwi-lcd2004` — LCD 20x4 con protocolo HD44780 +- `wokwi-7segment` — Display de 7 segmentos + +### Input (5) +- `wokwi-pushbutton` — Botón pulsador +- `wokwi-pushbutton-6mm` — Botón 6mm +- `wokwi-slide-switch` — Interruptor deslizante +- `wokwi-dip-switch-8` — DIP switch de 8 posiciones +- `wokwi-potentiometer` — Potenciómetro + +### Output (5) +- `wokwi-led` — LED de colores +- `wokwi-rgb-led` — LED RGB +- `wokwi-led-bar-graph` — Barra de LEDs (10) +- `wokwi-buzzer` — Buzzer piezoeléctrico +- `wokwi-neopixel` — LED RGB direccionable (WS2812) + +### Motors (2) +- `wokwi-servo` — Servo motor +- `wokwi-stepper-motor` — Motor paso a paso + +### Passive (4) +- `wokwi-resistor` — Resistencia con código de colores +- `wokwi-slide-potentiometer` — Potenciómetro deslizante +- `wokwi-led-ring` — Anillo de LEDs +- `wokwi-membrane-keypad` — Teclado matricial + +### Other (19) +- Componentes variados incluyendo `wokwi-ir-receiver`, `wokwi-ds1307`, breadboards, etc. + ## Ventajas de Este Enfoque ### ✅ Ventajas -1. **Actualización Fácil**: Un simple `git pull` en cada repo te da las últimas mejoras -2. **Compatible con Wokwi**: Si Wokwi agrega nuevos elementos o mejoras a avr8js, automáticamente estarán disponibles -3. **Control de Versiones**: Puedes hacer checkout a versiones específicas si necesitas estabilidad -4. **Desarrollo**: Puedes modificar el código fuente si necesitas hacer debugging o agregar features -5. **Sin Dependencia de npm**: No dependes de que publiquen en npm +1. **Actualización Fácil**: Un simple `git pull` + rebuild te da las últimas mejoras +2. **Compatible con Wokwi**: Usas exactamente el mismo código que Wokwi.com +3. **Descubrimiento Automático**: Nuevos componentes aparecen automáticamente tras regenerar metadata +4. **Control de Versiones**: Puedes hacer checkout a versiones específicas +5. **Desarrollo Flexible**: Código fuente disponible para debugging y modificaciones +6. **Sin Dependencia de npm**: No dependes de que publiquen actualizaciones en npm +7. **100% Offline**: Funciona completamente sin internet después de la configuración inicial ### ⚠️ Consideraciones 1. **Espacio en Disco**: Los repositorios clonados ocupan más espacio (~200MB) 2. **Compilación**: Debes compilar los repositorios después de actualizarlos -3. **Tiempo de Build**: La primera instalación toma más tiempo - -## Componentes Wokwi Disponibles - -### Elementos Básicos -- `wokwi-led` - LED de colores (red, green, blue, yellow, white, orange) -- `wokwi-resistor` - Resistencia con código de colores -- `wokwi-pushbutton` - Botón pulsador -- `wokwi-slide-switch` - Interruptor deslizante -- `wokwi-potentiometer` - Potenciómetro - -### Placas -- `wokwi-arduino-uno` - Arduino Uno R3 -- `wokwi-arduino-mega` - Arduino Mega 2560 -- `wokwi-arduino-nano` - Arduino Nano -- `wokwi-pi-pico` - Raspberry Pi Pico -- `wokwi-esp32-devkit-v1` - ESP32 DevKit v1 - -### Pantallas -- `wokwi-lcd1602` - LCD 16x2 con I2C -- `wokwi-neopixel` - LED RGB direccionable -- `wokwi-7segment` - Display de 7 segmentos - -### Sensores -- `wokwi-dht22` - Sensor de temperatura y humedad -- `wokwi-hc-sr04` - Sensor ultrasónico de distancia -- `wokwi-pir-motion-sensor` - Sensor de movimiento PIR -- `wokwi-photoresistor-sensor` - Fotoresistor (LDR) - -### Otros -- `wokwi-servo` - Servo motor -- `wokwi-membrane-keypad` - Teclado matricial 4x4 -- `wokwi-ir-receiver` - Receptor infrarrojo -- `wokwi-ds1307` - Reloj de tiempo real (RTC) - -## Uso de los Componentes - -### Ejemplo: LED - -```tsx -import { LED } from './components/components-wokwi/LED'; - - -``` - -### Ejemplo: Arduino Uno - -```tsx -import { ArduinoUno } from './components/components-wokwi/ArduinoUno'; - - -``` - -### Ejemplo: Botón - -```tsx -import { Pushbutton } from './components/components-wokwi/Pushbutton'; - - console.log('Presionado!')} - onRelease={() => console.log('Liberado!')} -/> -``` +3. **Metadata**: Regenerar `components-metadata.json` después de actualizar wokwi-elements ## Troubleshooting ### Error: "Module not found: @wokwi/elements" -Asegúrate de que los repositorios estén compilados: +Asegúrate de que wokwi-elements esté compilado: ```bash cd wokwi-libs/wokwi-elements @@ -257,19 +330,37 @@ npm run build ### Error: "Cannot find module 'avr8js'" -Verifica que el alias en `vite.config.ts` esté correcto y que avr8js esté compilado. +Verifica que el alias en `vite.config.ts` esté correcto y que avr8js esté compilado: -### Los componentes no se muestran - -Asegúrate de importar `@wokwi/elements` en tus componentes: - -```tsx -import '@wokwi/elements'; +```bash +cd wokwi-libs/avr8js +npm install +npm run build ``` +### Los componentes no se muestran en el picker + +Regenera la metadata de componentes: + +```bash +cd frontend +npx tsx ../scripts/generate-component-metadata.ts +``` + +### Nuevo componente de wokwi-elements no aparece + +1. Actualiza wokwi-elements: `cd wokwi-libs/wokwi-elements && git pull && npm run build` +2. Regenera metadata: `cd frontend && npx tsx ../scripts/generate-component-metadata.ts` +3. Si necesita simulación, registra su comportamiento en `frontend/src/simulation/parts/` + +### Los componentes se ven pero no responden a la simulación + +Verifica que el componente tenga lógica de simulación registrada en `PartSimulationRegistry` (archivos `BasicParts.ts` o `ComplexParts.ts`). Solo los 16 componentes registrados tienen comportamiento interactivo. + ## Referencias - [Wokwi Elements Documentation](https://elements.wokwi.com/) -- [AVR8js Documentation](https://github.com/wokwi/avr8js/tree/main/demo) +- [AVR8js Repository](https://github.com/wokwi/avr8js) - [Wokwi Simulator](https://wokwi.com) +- [Lit Documentation](https://lit.dev/) — Framework usado por wokwi-elements - [Web Components Guide](https://developer.mozilla.org/en-US/docs/Web/Web_Components)