velxio/CLAUDE.md

323 lines
10 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
This is a local Arduino emulator (Wokwi clone) that provides a full development environment for Arduino projects:
- Frontend: React + Vite + TypeScript with Monaco Editor and visual simulation canvas
- Backend: FastAPI + Python for Arduino code compilation via arduino-cli
- Simulation: Real AVR8 emulation using avr8js with full GPIO/timer/USART support
- Components: Visual electronic components from wokwi-elements (LEDs, resistors, buttons, etc.)
The project uses **local clones of official Wokwi repositories** instead of npm packages for maximum compatibility and ease of updates.
## Development Commands
### Backend (FastAPI + Python)
**Setup:**
```bash
cd backend
python -m venv venv
venv\Scripts\activate # Windows
pip install -r requirements.txt
```
**Run development server:**
```bash
cd backend
venv\Scripts\activate
uvicorn app.main:app --reload --port 8001
```
**Access:**
- API: http://localhost:8001
- Docs: http://localhost:8001/docs
### Frontend (React + Vite)
**Setup:**
```bash
cd frontend
npm install
```
**Run development server:**
```bash
cd frontend
npm run dev
```
**Build for production:**
```bash
cd frontend
npm run build
```
**Lint:**
```bash
cd frontend
npm run lint
```
**Access:**
- App: http://localhost:5173
### Wokwi Libraries (Local Repositories)
The project uses local clones of Wokwi repositories in `wokwi-libs/`:
- `wokwi-elements/` - Web Components for electronic parts
- `avr8js/` - AVR8 CPU emulator
- `rp2040js/` - RP2040 emulator (future use)
**Update libraries:**
```bash
update-wokwi-libs.bat
```
Or manually:
```bash
cd wokwi-libs/wokwi-elements
git pull origin main
npm install
npm run build
```
### External Dependencies
**arduino-cli** must be installed on your system:
```bash
# Verify installation
arduino-cli version
# Initialize (first time)
arduino-cli core update-index
arduino-cli core install arduino:avr
```
## Architecture
### High-Level Data Flow
1. **Code Editing**: User writes Arduino code → Monaco Editor → Zustand store (`useEditorStore`)
2. **Compilation**: Code → Frontend API call → Backend FastAPI → arduino-cli subprocess → Returns .hex file
3. **Simulation**: .hex file → AVRSimulator.loadHex() → Parsed into Uint16Array → CPU execution loop
4. **Pin Updates**: CPU writes to PORTB/C/D → Port listeners → PinManager → Component state updates
5. **Visual Updates**: Component state changes → React re-renders → wokwi-elements update visually
### Critical Architecture Patterns
**1. Vite Aliases for Local Wokwi Libs**
The `frontend/vite.config.ts` uses path aliases to import from local repositories:
```typescript
resolve: {
alias: {
'avr8js': path.resolve(__dirname, '../wokwi-libs/avr8js/dist/esm'),
'@wokwi/elements': path.resolve(__dirname, '../wokwi-libs/wokwi-elements/dist/esm'),
},
}
```
This allows importing as if they were npm packages while using local clones.
**2. AVR Simulation Loop**
The simulation runs at ~60 FPS using `requestAnimationFrame`:
- Each frame executes ~267,000 CPU cycles (16MHz / 60fps)
- Port listeners fire when PORTB/C/D registers change
- PinManager maps Arduino pins to components (e.g., pin 13 → LED_BUILTIN)
**3. State Management with Zustand**
Two main stores:
- `useEditorStore`: Code content, theme
- `useSimulatorStore`: Simulation state, components, wires, compiled hex
**4. Component-Pin Mapping**
Components are connected to Arduino pins via the PinManager:
- PORTB maps to digital pins 8-13 (pin 13 = built-in LED)
- PORTC maps to analog pins A0-A5
- PORTD maps to digital pins 0-7
When a port value changes, PinManager calls registered callbacks for affected components.
**5. Wire System (Phase 1 - Visual Only)**
Wires are stored as objects with start/end endpoints:
```typescript
{
id: string
start: { componentId, pinName, x, y }
end: { componentId, pinName, x, y }
color: string
signalType: 'digital' | 'analog' | 'power-vcc' | 'power-gnd'
}
```
Wire positions auto-update when components move via `updateWirePositions()`.
## Key File Locations
### Backend
- [backend/app/main.py](backend/app/main.py) - FastAPI app entry point, CORS config
- [backend/app/api/routes/compile.py](backend/app/api/routes/compile.py) - Compilation endpoints
- [backend/app/services/arduino_cli.py](backend/app/services/arduino_cli.py) - arduino-cli wrapper, handles compilation subprocess
### Frontend - Core
- [frontend/src/App.tsx](frontend/src/App.tsx) - Main app component
- [frontend/src/store/useEditorStore.ts](frontend/src/store/useEditorStore.ts) - Code editor state
- [frontend/src/store/useSimulatorStore.ts](frontend/src/store/useSimulatorStore.ts) - Simulation state, components, wires
### Frontend - Simulation
- [frontend/src/simulation/AVRSimulator.ts](frontend/src/simulation/AVRSimulator.ts) - AVR8 CPU emulator wrapper, execution loop
- [frontend/src/simulation/PinManager.ts](frontend/src/simulation/PinManager.ts) - Maps Arduino pins to components
- [frontend/src/utils/hexParser.ts](frontend/src/utils/hexParser.ts) - Intel HEX format parser
### Frontend - UI Components
- [frontend/src/components/editor/CodeEditor.tsx](frontend/src/components/editor/CodeEditor.tsx) - Monaco editor wrapper
- [frontend/src/components/editor/EditorToolbar.tsx](frontend/src/components/editor/EditorToolbar.tsx) - Compile/Run/Stop buttons
- [frontend/src/components/simulator/SimulatorCanvas.tsx](frontend/src/components/simulator/SimulatorCanvas.tsx) - Main simulation canvas
- [frontend/src/components/simulator/WireLayer.tsx](frontend/src/components/simulator/WireLayer.tsx) - Wire rendering layer
- [frontend/src/components/components-wokwi/](frontend/src/components/components-wokwi/) - React wrappers for wokwi-elements
## Important Implementation Notes
### 1. AVR Instruction Execution
The simulation **must call both** `avrInstruction()` and `cpu.tick()` in the execution loop:
```typescript
avrInstruction(this.cpu); // Execute the AVR instruction
this.cpu.tick(); // Update peripheral timers and cycles
```
Missing `avrInstruction()` will cause the CPU to appear "stuck" even though cycles increment.
### 2. Port Listeners
Port listeners in AVRSimulator.ts are attached to AVRIOPort instances, NOT directly to CPU registers:
```typescript
this.portB!.addListener((value, oldValue) => {
// value is the PORTB register value (0-255)
// Check individual pins: this.portB!.pinState(5) for pin 13
});
```
### 3. HEX File Format
Arduino compilation produces Intel HEX format. The parser in `hexParser.ts`:
- Parses lines starting with `:`
- Extracts address, record type, and data bytes
- Returns a `Uint8Array` of program bytes
- AVRSimulator converts this to `Uint16Array` (16-bit words, little-endian)
### 4. Component Registration
To add a component to the simulation:
1. Add it to the canvas in SimulatorCanvas.tsx
2. Register a pin change callback in PinManager
3. Update component state when pin changes
Example:
```typescript
pinManager.registerCallback(13, (state) => {
// Update LED when pin 13 changes
useSimulatorStore.getState().updateComponentState('led-builtin', state);
});
```
### 5. CORS Configuration
Backend allows specific Vite dev ports (5173-5175). Update `backend/app/main.py` if using different ports.
### 6. Wokwi Elements Integration
Wokwi elements are Web Components. React wrappers declare custom elements:
```typescript
declare global {
namespace JSX {
interface IntrinsicElements {
'wokwi-led': any;
}
}
}
```
## Testing
### Backend Testing
Test compilation directly:
```bash
cd backend
python test_compilation.py
```
### Frontend Testing
No test suite currently implemented. Manual testing via dev server.
## Common Development Scenarios
### Adding a New Electronic Component
1. Check if wokwi-elements has the component (see `wokwi-libs/wokwi-elements/src/`)
2. Create React wrapper in `frontend/src/components/components-wokwi/`
3. Add component type to `useSimulatorStore` interface
4. Update SimulatorCanvas to render the component
5. Register pin callbacks in PinManager if interactive
### Adding a New API Endpoint
1. Create route in `backend/app/api/routes/`
2. Include router in `backend/app/main.py`
3. Add corresponding service in `backend/app/services/` if needed
4. Create API client function in `frontend/src/services/`
### Debugging Simulation Issues
Common issues:
- **LED doesn't blink**: Check port listeners are firing (console logs), verify pin mapping
- **Compilation fails**: Check arduino-cli is in PATH, verify `arduino:avr` core is installed
- **CPU stuck at PC=0**: Ensure `avrInstruction()` is being called in execution loop
- **Wire positions wrong**: Check `calculatePinPosition()` uses correct component coordinates
Enable verbose logging:
- AVRSimulator logs port changes and CPU state every 60 frames
- Backend logs all compilation steps and arduino-cli output
## Project Status
**Implemented:**
- Full Arduino code editing with Monaco Editor
- Compilation via arduino-cli to .hex files
- Real AVR8 emulation with avr8js
- Pin state tracking and component updates
- Dynamic component system with 48+ wokwi-elements components
- Component picker modal with search and categories
- Component property dialog (single-click interaction)
- Component rotation (90° increments)
- Wire creation and rendering (orthogonal routing)
- Segment-based wire editing (drag segments perpendicular to orientation)
- Real-time wire preview with grid snapping (20px)
- Pin overlay system for wire connections
**In Progress:**
- Functional wire connections (electrical signal routing)
- Wire validation and error handling
**Planned:**
- Serial monitor
- Project persistence (SQLite)
- Multi-board support (Mega, Nano, ESP32)
- Undo/redo functionality
## Additional Resources
- Main README: [README.md](README.md)
- Architecture Details: [ARCHITECTURE.md](ARCHITECTURE.md)
- Wokwi Integration: [WOKWI_LIBS.md](WOKWI_LIBS.md)
- Wokwi Elements Repo: https://github.com/wokwi/wokwi-elements
- AVR8js Repo: https://github.com/wokwi/avr8js
- Arduino CLI Docs: https://arduino.github.io/arduino-cli/