velxio/frontend/src/components/velxio-components/pi40PinHeader.ts

72 lines
2.0 KiB
TypeScript
Raw Normal View History

feat(boards): expose Raspberry Pi 4 and Pi 5 in the picker (UI + pin wiring) The BoardKind type and the QEMU backend already supported raspberry-pi-4 (Cortex-A72) and raspberry-pi-5 (Cortex-A76) by reusing the Pi 3 arm64 image set, but the frontend had no way to actually select either: the board picker, the canvas renderer, the serial monitor, the oscilloscope channel list, and the editor toolbar all hard-coded "raspberry-pi-3" as the only Pi entry. ComponentRegistry even registered Pi 4 / Pi 5 metadata pointing at the velxio-raspberry-pi-3 custom-element tag — a placeholder that meant both boards rendered as a Pi 3 in the picker thumbnail and on the canvas. Add dedicated boards top-to-bottom: * `RaspberryPi4Element.ts` / `RaspberryPi5Element.ts` — Velxio-style schematic SVG (authored from scratch, not traced). Pi 4 is the green PCB with BCM2711 SoC, 4× USB-A, USB-C power, dual µHDMI; Pi 5 is the darker green PCB with BCM2712 + RP1 southbridge, 2.5 GbE, USB-C 5V/5A, PCIe FFC connector, dedicated power button. Both carry a small "velxio" mark in the corner. * `pi40PinHeader.ts` — shared `buildPi40PinHeader()` helper that returns the 40-pin BCM layout. Every Pi from the 1B+ onwards uses the same physical pin positions and same BCM GPIO assignment, so Pi 3 / Pi 4 / Pi 5 elements all consume this helper and example wires drawn against one model transfer to the others without re-routing. * React wrappers `RaspberryPi4.tsx` / `RaspberryPi5.tsx` render the custom elements at absolute positions (mirrors how RaspberryPi3.tsx handles the Pi 3 illustration). * Wire-up across the editor surface: - BoardOnCanvas: BOARD_SIZE entry + switch case. - BoardPickerModal: description, icon, kinds list. - ComponentPickerModal: thumbnails now instantiate the dedicated custom element (was velxio-raspberry-pi-3 fallback). - SerialMonitor / EditorToolbar: pill labels, icons, colours. - Oscilloscope: GPIO channel list (28 BCM pins). - SimulatorCanvas: remote-boards filter for run/stop sync. - SPICE boardPinGroups: same 5V / 3V3 / GND as Pi 3. - boardPinToNumber: accepts physical pin numbers ("1"-"40"), BCM names ("GPIO14") and power labels for any Pi 3/4/5 id. - ComponentRegistry: dedicated tagNames + per-board thumbnails (green for Pi 4, darker green for Pi 5). * EditorToolbar's Pi 3 special cases (Linux/Python compile path, Run/Stop routing) now use `isPiBoardKind()` so Pi 4 and Pi 5 inherit the same behaviour automatically, and any future Pi family member (Zero / 1 / 2) lands in the right code paths the moment its backend boots. QEMU backend was already wired (qemu_manager.py:71/82 + manifest entry 'raspberry-pi-3-virt' shared across arm64 Pis), so this commit makes both boards selectable end-to-end without any backend follow-up.
2026-05-23 09:46:59 +07:00
/**
* Shared 40-pin GPIO header layout used by every Raspberry Pi from the
* 1B+ onwards (Zero W, 1B+, 2, 3, 4, 5). Same physical positions, same
* BCM GPIO assignment, same naming convention — so wires drawn against
* a Pi 3 example transfer to a Pi 4 or Pi 5 board without re-routing.
*
* Coordinates are in CSS pixels relative to the board element's top-left,
* sized to fit the 250×160 footprint shared by every Velxio Pi element.
* Pin "1" sits top-left; odd pins on the top row, even on the bottom.
*
* Names follow the Pi 3 wrapper convention (BCM GPIO numbers like
* "GPIO14" plus power/ground labels) so example wires using those names
* resolve to the same physical position on every Pi model.
*/
export interface PinInfo {
name: string;
x: number;
y: number;
signals: string[];
}
const PIN_X_START = 20;
const PIN_X_STEP = 10;
const PIN_Y_TOP = 10;
const PIN_Y_BOT = 20;
const PI_PIN_NAMES: Record<number, string> = {
1: '3V3', 2: '5V',
3: 'GPIO2', 4: '5V',
5: 'GPIO3', 6: 'GND',
7: 'GPIO4', 8: 'GPIO14',
9: 'GND', 10: 'GPIO15',
11: 'GPIO17', 12: 'GPIO18',
13: 'GPIO27', 14: 'GND',
15: 'GPIO22', 16: 'GPIO23',
17: '3V3', 18: 'GPIO24',
19: 'GPIO10', 20: 'GND',
21: 'GPIO9', 22: 'GPIO25',
23: 'GPIO11', 24: 'GPIO8',
25: 'GND', 26: 'GPIO7',
27: 'ID_SD', 28: 'ID_SC',
29: 'GPIO5', 30: 'GND',
31: 'GPIO6', 32: 'GPIO12',
33: 'GPIO13', 34: 'GND',
35: 'GPIO19', 36: 'GPIO16',
37: 'GPIO26', 38: 'GPIO20',
39: 'GND', 40: 'GPIO21',
};
export function buildPi40PinHeader(): PinInfo[] {
const pins: PinInfo[] = [];
for (let col = 0; col < 20; col++) {
const oddPin = col * 2 + 1; // top row
const evenPin = col * 2 + 2; // bottom row
const px = PIN_X_START + col * PIN_X_STEP;
pins.push({
name: PI_PIN_NAMES[oddPin] ?? `P${oddPin}`,
x: px,
y: PIN_Y_TOP,
signals: [],
});
pins.push({
name: PI_PIN_NAMES[evenPin] ?? `P${evenPin}`,
x: px,
y: PIN_Y_BOT,
signals: [],
});
}
return pins;
}