fix(wires): stop board-corner wire anchors — alias fallbacks for pin-name spellings
A wire endpoint naming a pin the board element does not expose silently resolved to nothing and rendered anchored at the board corner. A full audit (all gallery examples + every saved project on velxio.dev) found 15 examples and 28 user projects doing it — the same electrical pin spelled differently per surface: GND.1 on the classic ESP32 (element exposes GND/GND2), 3.3V vs 3V3, GND2 vs GND.2, D13 vs 13 vs GP13, A0-A2 vs GP26-28 on the Pico, 36/39 vs VP/VN, bare 5V vs VBUS/VIN. calculatePinPosition now tries those equivalences AFTER the exact match and the two existing fallbacks miss (so no current resolution changes), healing old saves, .vlx imports and agent-authored wires without a data migration. The Pico element gains A0/A1/A2 alias pads on the ADC pins (RX2/16 dual-entry precedent) and a GP25 pad at the onboard LED silk so pico-blink-style wires have an anchor. The two examples that were outright wrong (microsd-card-esp32 GND.1, pico-serial-echo TX) now use the element's real pin names. Netlist snapshots (166) untouched; verifier + builder suites green.
This commit is contained in:
parent
fe8ac7e4e3
commit
aed1796a8f
|
|
@ -39,15 +39,26 @@ const PINS_PI_PICO_W = [
|
|||
{ name: 'GP22', x: 97, y: 157 },
|
||||
{ name: 'RUN', x: 97, y: 144 },
|
||||
{ name: 'GP26', x: 97, y: 131 },
|
||||
// Alias entries: examples and saved projects also reference the ADC pins
|
||||
// as A0/A1/A2 (Arduino-style) — same physical pins, same coordinates.
|
||||
// Without these the wire endpoint anchored at the board corner. Mirrors
|
||||
// the RX2/16 dual-entry precedent in Esp32Element.
|
||||
{ name: 'A0', x: 97, y: 131 },
|
||||
{ name: 'GP27', x: 97, y: 119 },
|
||||
{ name: 'A1', x: 97, y: 119 },
|
||||
{ name: 'GND.7', x: 97, y: 106 },
|
||||
{ name: 'GP28', x: 97, y: 93 },
|
||||
{ name: 'A2', x: 97, y: 93 },
|
||||
{ name: 'ADC_VREF', x: 97, y: 81 },
|
||||
{ name: '3V3', x: 97, y: 68 },
|
||||
{ name: '3V3_EN', x: 97, y: 55 },
|
||||
{ name: 'GND.8', x: 97, y: 42 },
|
||||
{ name: 'VSYS', x: 97, y: 30 },
|
||||
{ name: 'VBUS', x: 97, y: 17 },
|
||||
// GP25 is the onboard LED, not a header pin — but pico-blink-style
|
||||
// examples wire an external LED to it for visibility. Anchor at the LED
|
||||
// silk so those wires stop falling back to the board corner.
|
||||
{ name: 'GP25', x: 40, y: 14 },
|
||||
];
|
||||
|
||||
class PiPicoWElement extends HTMLElement {
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ export const microsdExamples: ExampleProject[] = [
|
|||
{ id: 'w-miso', start: { componentId: 'esp32', pinName: '19' }, end: { componentId: 'sd1', pinName: 'MISO' }, color: '#22cc22' },
|
||||
{ id: 'w-sck', start: { componentId: 'esp32', pinName: '18' }, end: { componentId: 'sd1', pinName: 'SCK' }, color: '#ffdd33' },
|
||||
{ id: 'w-vcc', start: { componentId: 'esp32', pinName: '3V3' }, end: { componentId: 'sd1', pinName: 'VCC' }, color: '#ff4444' },
|
||||
{ id: 'w-gnd', start: { componentId: 'esp32', pinName: 'GND.1' }, end: { componentId: 'sd1', pinName: 'GND' }, color: '#000000' },
|
||||
{ id: 'w-gnd', start: { componentId: 'esp32', pinName: 'GND' }, end: { componentId: 'sd1', pinName: 'GND' }, color: '#000000' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -4484,7 +4484,7 @@ void loop() {
|
|||
wires: [
|
||||
{
|
||||
id: 'w1',
|
||||
start: { componentId: 'arduino-uno', pinName: 'TX' },
|
||||
start: { componentId: 'arduino-uno', pinName: 'GP0' },
|
||||
end: { componentId: 'r-led-rx-a', pinName: '1' },
|
||||
color: '#ff8800',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -71,6 +71,31 @@ export function calculatePinPosition(
|
|||
pin = pinInfo.find((p: any) => p.description === `GPIO${gpioNum}`);
|
||||
}
|
||||
}
|
||||
// Generic alias fallbacks — every unresolved endpoint used to silently
|
||||
// anchor at the board CORNER (0,0 of the element), which users read as a
|
||||
// broken circuit. The names below are electrically identical spellings
|
||||
// that boards/examples/saved projects disagree on (a 2026-08 audit found
|
||||
// 15 gallery examples and 28 saved projects wired to a spelling their
|
||||
// board element doesn't expose). Only consulted after exact + the two
|
||||
// legacy fallbacks above miss, so no existing resolution changes.
|
||||
if (!pin) {
|
||||
const candidates: string[] = [];
|
||||
const dot = pinName.match(/^(.+)\.\d+$/);
|
||||
if (dot) candidates.push(dot[1]); // GND.1 -> GND (esp32 classic)
|
||||
if (pinName === '3.3V') candidates.push('3V3', '3V3.1', '3V');
|
||||
if (pinName === '3V3') candidates.push('3V3.1', '3.3V', '3V');
|
||||
if (pinName === '5V') candidates.push('5V.1', 'VBUS', 'VIN');
|
||||
if (pinName === 'GND2') candidates.push('GND.2');
|
||||
const dNum = pinName.match(/^D(\d+)$/);
|
||||
if (dNum) candidates.push(dNum[1], `GP${dNum[1]}`); // D13 -> 13 (esp32) / GP13 (pico)
|
||||
if (/^\d+$/.test(pinName)) candidates.push(`D${pinName}`, `GP${pinName}`);
|
||||
if (pinName === '36') candidates.push('VP'); // ESP32 devkit silk for GPIO36
|
||||
if (pinName === '39') candidates.push('VN'); // ESP32 devkit silk for GPIO39
|
||||
for (const c of candidates) {
|
||||
pin = pinInfo.find((p: any) => p.name === c);
|
||||
if (pin) break;
|
||||
}
|
||||
}
|
||||
if (!pin) {
|
||||
console.warn(`[pinPositionCalculator] Pin ${pinName} not found on component ${componentId}`);
|
||||
console.warn(
|
||||
|
|
|
|||
Loading…
Reference in New Issue