2026-03-06 07:07:03 +07:00
|
|
|
|
/**
|
|
|
|
|
|
* Board Pin Mapping Utility
|
|
|
|
|
|
*
|
|
|
|
|
|
* Maps wokwi-element pin names to simulator GPIO/pin numbers
|
|
|
|
|
|
* for both Arduino Uno (AVR) and Nano RP2040 Connect (RP2040).
|
|
|
|
|
|
*
|
|
|
|
|
|
* The wokwi board elements expose pin names like 'D2', 'A0', 'TX', etc.
|
|
|
|
|
|
* The simulators need numeric GPIO/pin numbers.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Nano RP2040 Connect element pin names → RP2040 GPIO numbers.
|
|
|
|
|
|
* Derived from wokwi-nano-rp2040-connect-element.ts pinInfo descriptions.
|
|
|
|
|
|
*/
|
|
|
|
|
|
const NANO_RP2040_PIN_MAP: Record<string, number> = {
|
2026-04-22 02:45:45 +07:00
|
|
|
|
D2: 25, // GPIO25 — LED_BUILTIN
|
|
|
|
|
|
D3: 15, // GPIO15
|
|
|
|
|
|
D4: 16, // GPIO16 — SPI0 MISO
|
|
|
|
|
|
D5: 17, // GPIO17 — SPI0 CS
|
|
|
|
|
|
D6: 18, // GPIO18 — SPI0 SCK
|
|
|
|
|
|
D7: 19, // GPIO19 — SPI0 MOSI
|
|
|
|
|
|
D8: 20, // GPIO20
|
|
|
|
|
|
D9: 21, // GPIO21
|
|
|
|
|
|
D10: 5, // GPIO05
|
|
|
|
|
|
D11: 7, // GPIO07
|
|
|
|
|
|
D12: 4, // GPIO04 — I2C0 SDA
|
|
|
|
|
|
D13: 6, // GPIO06 — SPI0 SCK (alternate)
|
|
|
|
|
|
TX: 0, // GPIO0 — UART0 TX
|
|
|
|
|
|
RX: 1, // GPIO1 — UART0 RX
|
|
|
|
|
|
A0: 26, // GPIO26 — ADC channel 0
|
|
|
|
|
|
A1: 27, // GPIO27 — ADC channel 1
|
|
|
|
|
|
A2: 28, // GPIO28 — ADC channel 2
|
|
|
|
|
|
A3: 29, // GPIO29 — ADC channel 3
|
|
|
|
|
|
A4: 12, // GPIO12
|
|
|
|
|
|
A5: 13, // GPIO13
|
2026-03-06 07:07:03 +07:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Arduino Uno analog pin names → AVR pin numbers.
|
|
|
|
|
|
* Digital pins D0-D13 are parsed numerically; only analog names need mapping.
|
|
|
|
|
|
*/
|
|
|
|
|
|
const ARDUINO_UNO_ANALOG_MAP: Record<string, number> = {
|
2026-04-22 02:45:45 +07:00
|
|
|
|
A0: 14,
|
|
|
|
|
|
A1: 15,
|
|
|
|
|
|
A2: 16,
|
|
|
|
|
|
A3: 17,
|
|
|
|
|
|
A4: 18,
|
|
|
|
|
|
A5: 19,
|
|
|
|
|
|
A6: 20,
|
|
|
|
|
|
A7: 21,
|
2026-03-06 07:07:03 +07:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-03-09 20:08:14 +07:00
|
|
|
|
/**
|
|
|
|
|
|
* Arduino Mega analog pin names → AVR pin numbers.
|
|
|
|
|
|
* A0–A15 map to physical pins 54–69 on the ATmega2560.
|
|
|
|
|
|
*/
|
|
|
|
|
|
const ARDUINO_MEGA_ANALOG_MAP: Record<string, number> = {
|
2026-04-22 02:45:45 +07:00
|
|
|
|
A0: 54,
|
|
|
|
|
|
A1: 55,
|
|
|
|
|
|
A2: 56,
|
|
|
|
|
|
A3: 57,
|
|
|
|
|
|
A4: 58,
|
|
|
|
|
|
A5: 59,
|
|
|
|
|
|
A6: 60,
|
|
|
|
|
|
A7: 61,
|
|
|
|
|
|
A8: 62,
|
|
|
|
|
|
A9: 63,
|
|
|
|
|
|
A10: 64,
|
|
|
|
|
|
A11: 65,
|
|
|
|
|
|
A12: 66,
|
|
|
|
|
|
A13: 67,
|
|
|
|
|
|
A14: 68,
|
|
|
|
|
|
A15: 69,
|
2026-03-09 20:08:14 +07:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-03-13 09:39:04 +07:00
|
|
|
|
/**
|
|
|
|
|
|
* Raspberry Pi 3B physical pin number → BCM GPIO number.
|
|
|
|
|
|
* Power / GND / special-function pins are mapped to -1 (not a GPIO).
|
|
|
|
|
|
* Source: https://pinout.xyz
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const PI3_PHYSICAL_TO_BCM: Record<number, number> = {
|
2026-04-22 02:45:45 +07:00
|
|
|
|
1: -1, // 3.3V
|
|
|
|
|
|
2: -1, // 5V
|
|
|
|
|
|
3: 2, // BCM2 (SDA1)
|
|
|
|
|
|
4: -1, // 5V
|
|
|
|
|
|
5: 3, // BCM3 (SCL1)
|
|
|
|
|
|
6: -1, // GND
|
|
|
|
|
|
7: 4, // BCM4 (GPCLK0)
|
|
|
|
|
|
8: 14, // BCM14 (TXD0 / ttyAMA0)
|
|
|
|
|
|
9: -1, // GND
|
|
|
|
|
|
10: 15, // BCM15 (RXD0 / ttyAMA0)
|
|
|
|
|
|
11: 17, // BCM17
|
|
|
|
|
|
12: 18, // BCM18 (PWM0)
|
|
|
|
|
|
13: 27, // BCM27
|
|
|
|
|
|
14: -1, // GND
|
|
|
|
|
|
15: 22, // BCM22
|
|
|
|
|
|
16: 23, // BCM23
|
|
|
|
|
|
17: -1, // 3.3V
|
|
|
|
|
|
18: 24, // BCM24
|
|
|
|
|
|
19: 10, // BCM10 (MOSI)
|
|
|
|
|
|
20: -1, // GND
|
|
|
|
|
|
21: 9, // BCM9 (MISO)
|
|
|
|
|
|
22: 25, // BCM25
|
|
|
|
|
|
23: 11, // BCM11 (SCLK)
|
|
|
|
|
|
24: 8, // BCM8 (CE0)
|
|
|
|
|
|
25: -1, // GND
|
|
|
|
|
|
26: 7, // BCM7 (CE1)
|
|
|
|
|
|
27: -1, // ID_SD (reserved)
|
|
|
|
|
|
28: -1, // ID_SC (reserved)
|
|
|
|
|
|
29: 5, // BCM5
|
|
|
|
|
|
30: -1, // GND
|
|
|
|
|
|
31: 6, // BCM6
|
|
|
|
|
|
32: 12, // BCM12 (PWM0)
|
|
|
|
|
|
33: 13, // BCM13 (PWM1)
|
|
|
|
|
|
34: -1, // GND
|
|
|
|
|
|
35: 19, // BCM19 (MISO1)
|
|
|
|
|
|
36: 16, // BCM16 (CE2)
|
|
|
|
|
|
37: 26, // BCM26
|
|
|
|
|
|
38: 20, // BCM20 (MOSI1)
|
|
|
|
|
|
39: -1, // GND
|
|
|
|
|
|
40: 21, // BCM21 (SCLK1)
|
2026-03-13 09:39:04 +07:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/** BCM GPIO number → physical pin number (reverse map) */
|
|
|
|
|
|
export const PI3_BCM_TO_PHYSICAL: Record<number, number> = Object.fromEntries(
|
|
|
|
|
|
Object.entries(PI3_PHYSICAL_TO_BCM)
|
|
|
|
|
|
.filter(([, bcm]) => bcm >= 0)
|
2026-04-22 02:45:45 +07:00
|
|
|
|
.map(([physical, bcm]) => [bcm, Number(physical)]),
|
2026-03-13 09:39:04 +07:00
|
|
|
|
);
|
|
|
|
|
|
|
2026-03-14 06:35:48 +07:00
|
|
|
|
/**
|
|
|
|
|
|
* ESP32 DevKit-C GPIO pin names → GPIO numbers.
|
|
|
|
|
|
* Pin names are GPIO numbers directly (GPIO0–GPIO39).
|
|
|
|
|
|
* Special aliases: TX=1, RX=3.
|
|
|
|
|
|
*/
|
|
|
|
|
|
const ESP32_PIN_MAP: Record<string, number> = {
|
2026-04-22 02:45:45 +07:00
|
|
|
|
TX: 1,
|
|
|
|
|
|
RX: 3,
|
|
|
|
|
|
GPIO0: 0,
|
|
|
|
|
|
GPIO1: 1,
|
|
|
|
|
|
GPIO2: 2,
|
|
|
|
|
|
GPIO3: 3,
|
|
|
|
|
|
GPIO4: 4,
|
|
|
|
|
|
GPIO5: 5,
|
|
|
|
|
|
GPIO6: 6,
|
|
|
|
|
|
GPIO7: 7,
|
|
|
|
|
|
GPIO8: 8,
|
|
|
|
|
|
GPIO9: 9,
|
|
|
|
|
|
GPIO10: 10,
|
|
|
|
|
|
GPIO11: 11,
|
|
|
|
|
|
GPIO12: 12,
|
|
|
|
|
|
GPIO13: 13,
|
|
|
|
|
|
GPIO14: 14,
|
|
|
|
|
|
GPIO15: 15,
|
|
|
|
|
|
GPIO16: 16,
|
|
|
|
|
|
GPIO17: 17,
|
|
|
|
|
|
GPIO18: 18,
|
|
|
|
|
|
GPIO19: 19,
|
|
|
|
|
|
GPIO20: 20,
|
|
|
|
|
|
GPIO21: 21,
|
|
|
|
|
|
GPIO22: 22,
|
|
|
|
|
|
GPIO23: 23,
|
|
|
|
|
|
GPIO25: 25,
|
|
|
|
|
|
GPIO26: 26,
|
|
|
|
|
|
GPIO27: 27,
|
|
|
|
|
|
GPIO32: 32,
|
|
|
|
|
|
GPIO33: 33,
|
|
|
|
|
|
GPIO34: 34,
|
|
|
|
|
|
GPIO35: 35,
|
|
|
|
|
|
GPIO36: 36,
|
|
|
|
|
|
GPIO39: 39,
|
2026-03-22 12:25:58 +07:00
|
|
|
|
// Wokwi element "D" prefix aliases (esp32-devkit-v1-element pin names)
|
2026-04-22 02:45:45 +07:00
|
|
|
|
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,
|
2026-03-14 06:35:48 +07:00
|
|
|
|
// ADC aliases
|
2026-04-22 02:45:45 +07:00
|
|
|
|
VP: 36,
|
|
|
|
|
|
VN: 39,
|
2026-03-17 20:08:06 +07:00
|
|
|
|
// Power / GND — not real GPIOs; mapped to -1 so WirePin skips silently
|
2026-04-22 02:45:45 +07:00
|
|
|
|
GND: -1,
|
|
|
|
|
|
GND1: -1,
|
|
|
|
|
|
GND2: -1,
|
|
|
|
|
|
VCC: -1,
|
|
|
|
|
|
'3V3': -1,
|
|
|
|
|
|
'3V3_OUT': -1,
|
|
|
|
|
|
'5V': -1,
|
|
|
|
|
|
VIN: -1,
|
|
|
|
|
|
EN: -1,
|
2026-03-14 06:35:48 +07:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-03-06 07:07:03 +07:00
|
|
|
|
/** All known board component IDs in the simulator */
|
2026-03-13 09:39:04 +07:00
|
|
|
|
export const BOARD_COMPONENT_IDS = [
|
2026-04-22 02:45:45 +07:00
|
|
|
|
'arduino-uno',
|
|
|
|
|
|
'arduino-nano',
|
|
|
|
|
|
'arduino-mega',
|
|
|
|
|
|
'nano-rp2040',
|
|
|
|
|
|
'raspberry-pi-3',
|
|
|
|
|
|
'raspberry-pi-pico',
|
|
|
|
|
|
'pi-pico-w',
|
|
|
|
|
|
'esp32',
|
|
|
|
|
|
'esp32-devkit-c-v4',
|
|
|
|
|
|
'esp32-cam',
|
|
|
|
|
|
'wemos-lolin32-lite',
|
|
|
|
|
|
'esp32-s3',
|
|
|
|
|
|
'xiao-esp32-s3',
|
|
|
|
|
|
'arduino-nano-esp32',
|
|
|
|
|
|
'esp32-c3',
|
|
|
|
|
|
'xiao-esp32-c3',
|
|
|
|
|
|
'aitewinrobot-esp32c3-supermini',
|
2026-03-19 09:33:20 +07:00
|
|
|
|
'attiny85',
|
2026-03-13 09:39:04 +07:00
|
|
|
|
];
|
2026-03-06 07:07:03 +07:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Check whether a componentId represents a board (not an external component).
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function isBoardComponent(componentId: string): boolean {
|
2026-03-13 09:39:04 +07:00
|
|
|
|
return BOARD_COMPONENT_IDS.some((id) => componentId === id || componentId.startsWith(id));
|
2026-03-06 07:07:03 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Convert a board element pin name to a simulator-usable pin/GPIO number.
|
|
|
|
|
|
*
|
|
|
|
|
|
* For Arduino Uno: 'D0'-'D13' / '0'-'13' → 0-13, 'A0'-'A7' → 14-21
|
|
|
|
|
|
* For Nano RP2040: 'D2'-'D13' / 'A0'-'A5' / 'TX' / 'RX' → GPIO number
|
|
|
|
|
|
*
|
|
|
|
|
|
* @returns Numeric pin/GPIO number, or null if unmapped
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function boardPinToNumber(boardId: string, pinName: string): number | null {
|
2026-03-08 09:14:33 +07:00
|
|
|
|
if (boardId === 'arduino-uno' || boardId === 'arduino-nano') {
|
2026-03-21 03:11:12 +07:00
|
|
|
|
// Power / GND pins — not real GPIOs, skip silently
|
|
|
|
|
|
if (/^(GND|VCC|VIN|IOREF|AREF|RESET|3\.3V|3V3|5V|3V)/.test(pinName)) return -1;
|
2026-03-06 07:07:03 +07:00
|
|
|
|
// Try numeric (covers '0' through '13', also legacy examples using just numbers)
|
|
|
|
|
|
const num = parseInt(pinName, 10);
|
|
|
|
|
|
if (!isNaN(num) && num >= 0 && num <= 21) return num;
|
|
|
|
|
|
// Try 'Dx' style
|
|
|
|
|
|
if (pinName.startsWith('D')) {
|
|
|
|
|
|
const d = parseInt(pinName.substring(1), 10);
|
|
|
|
|
|
if (!isNaN(d)) return d;
|
|
|
|
|
|
}
|
|
|
|
|
|
// Analog naming
|
|
|
|
|
|
return ARDUINO_UNO_ANALOG_MAP[pinName] ?? null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-09 20:08:14 +07:00
|
|
|
|
if (boardId === 'arduino-mega') {
|
|
|
|
|
|
// Digital pins D0–D53 parsed numerically
|
|
|
|
|
|
const num = parseInt(pinName, 10);
|
|
|
|
|
|
if (!isNaN(num) && num >= 0 && num <= 53) return num;
|
|
|
|
|
|
if (pinName.startsWith('D')) {
|
|
|
|
|
|
const d = parseInt(pinName.substring(1), 10);
|
|
|
|
|
|
if (!isNaN(d) && d <= 53) return d;
|
|
|
|
|
|
}
|
|
|
|
|
|
return ARDUINO_MEGA_ANALOG_MAP[pinName] ?? null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-16 10:12:33 +07:00
|
|
|
|
if (boardId === 'nano-rp2040' || boardId === 'raspberry-pi-pico') {
|
2026-03-21 03:11:12 +07:00
|
|
|
|
// Power / GND pins — return -1 so callers skip silently
|
2026-04-22 02:45:45 +07:00
|
|
|
|
if (
|
|
|
|
|
|
pinName.startsWith('GND') ||
|
|
|
|
|
|
pinName.startsWith('3.3V') ||
|
|
|
|
|
|
pinName.startsWith('3V3') ||
|
|
|
|
|
|
pinName.startsWith('5V') ||
|
|
|
|
|
|
pinName.startsWith('VBUS') ||
|
|
|
|
|
|
pinName.startsWith('VSYS')
|
|
|
|
|
|
) {
|
2026-03-21 03:11:12 +07:00
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
2026-03-16 10:12:33 +07:00
|
|
|
|
// Try D-prefix map first (D2 → GPIO25 = LED_BUILTIN, etc.)
|
|
|
|
|
|
const mapped = NANO_RP2040_PIN_MAP[pinName];
|
|
|
|
|
|
if (mapped !== undefined) return mapped;
|
|
|
|
|
|
// Also accept GP-prefix (GP0–GP29) and bare numbers
|
|
|
|
|
|
if (pinName.startsWith('GP')) {
|
|
|
|
|
|
const n = parseInt(pinName.substring(2), 10);
|
|
|
|
|
|
if (!isNaN(n) && n <= 29) return n;
|
|
|
|
|
|
}
|
|
|
|
|
|
const num = parseInt(pinName, 10);
|
|
|
|
|
|
if (!isNaN(num) && num <= 29) return num;
|
|
|
|
|
|
return null;
|
2026-03-06 07:07:03 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-13 09:39:04 +07:00
|
|
|
|
// Raspberry Pi 3B — pinName is the physical pin number ("1" … "40")
|
|
|
|
|
|
// We return the BCM GPIO number, or -1 for power/GND pins.
|
|
|
|
|
|
if (boardId === 'raspberry-pi-3' || boardId.startsWith('raspberry-pi-3')) {
|
|
|
|
|
|
const physical = parseInt(pinName, 10);
|
|
|
|
|
|
if (!isNaN(physical)) return PI3_PHYSICAL_TO_BCM[physical] ?? null;
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-16 01:39:26 +07:00
|
|
|
|
// Pi Pico W — same GPIO mapping as Raspberry Pi Pico (GP0-GP28 → 0-28)
|
|
|
|
|
|
if (boardId === 'pi-pico-w') {
|
|
|
|
|
|
if (pinName.startsWith('GP')) {
|
|
|
|
|
|
const n = parseInt(pinName.substring(2), 10);
|
|
|
|
|
|
if (!isNaN(n)) return n;
|
|
|
|
|
|
}
|
|
|
|
|
|
const num = parseInt(pinName, 10);
|
|
|
|
|
|
if (!isNaN(num)) return num;
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-14 06:35:48 +07:00
|
|
|
|
// ESP32 / ESP32-S3 / ESP32-C3 — GPIO numbers used directly
|
|
|
|
|
|
if (boardId === 'esp32' || boardId.startsWith('esp32')) {
|
2026-03-18 09:06:36 +07:00
|
|
|
|
// Power / GND pins (GND, GND.1, 3V3, 3V3.1, 5V, 5V.1, etc.)
|
2026-04-22 02:45:45 +07:00
|
|
|
|
if (pinName.startsWith('GND') || pinName.startsWith('3V3') || pinName.startsWith('5V'))
|
|
|
|
|
|
return -1;
|
2026-03-14 06:35:48 +07:00
|
|
|
|
// Try bare number first ("13" → 13)
|
|
|
|
|
|
const num = parseInt(pinName, 10);
|
|
|
|
|
|
if (!isNaN(num) && num >= 0 && num <= 39) return num;
|
|
|
|
|
|
return ESP32_PIN_MAP[pinName] ?? null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-16 01:39:26 +07:00
|
|
|
|
// ESP32 variants not starting with 'esp32'
|
|
|
|
|
|
if (boardId === 'wemos-lolin32-lite') {
|
|
|
|
|
|
// Pins named "GPIO34", "GPIO32" etc → strip prefix
|
|
|
|
|
|
if (pinName.startsWith('GPIO')) return parseInt(pinName.substring(4), 10);
|
|
|
|
|
|
const num = parseInt(pinName, 10);
|
|
|
|
|
|
if (!isNaN(num)) return num;
|
|
|
|
|
|
return ESP32_PIN_MAP[pinName] ?? null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (boardId === 'xiao-esp32-s3' || boardId === 'arduino-nano-esp32') {
|
|
|
|
|
|
// D0-D13, A0-A7 → ESP32-S3 GPIO numbers
|
|
|
|
|
|
const XIAO_S3_MAP: Record<string, number> = {
|
2026-04-22 02:45:45 +07:00
|
|
|
|
D0: 1,
|
|
|
|
|
|
D1: 2,
|
|
|
|
|
|
D2: 3,
|
|
|
|
|
|
D3: 4,
|
|
|
|
|
|
D4: 5,
|
|
|
|
|
|
D5: 6,
|
|
|
|
|
|
D6: 43,
|
|
|
|
|
|
D7: 44,
|
|
|
|
|
|
D8: 7,
|
|
|
|
|
|
D9: 8,
|
|
|
|
|
|
D10: 9,
|
2026-03-16 01:39:26 +07:00
|
|
|
|
};
|
|
|
|
|
|
const NANO_ESP32_MAP: Record<string, number> = {
|
2026-04-22 02:45:45 +07:00
|
|
|
|
D0: 44,
|
|
|
|
|
|
D1: 43,
|
|
|
|
|
|
D2: 5,
|
|
|
|
|
|
D3: 6,
|
|
|
|
|
|
D4: 7,
|
|
|
|
|
|
D5: 8,
|
|
|
|
|
|
D6: 9,
|
|
|
|
|
|
D7: 10,
|
|
|
|
|
|
D8: 17,
|
|
|
|
|
|
D9: 18,
|
|
|
|
|
|
D10: 21,
|
|
|
|
|
|
D11: 38,
|
|
|
|
|
|
D12: 47,
|
|
|
|
|
|
D13: 48,
|
|
|
|
|
|
A0: 1,
|
|
|
|
|
|
A1: 2,
|
|
|
|
|
|
A2: 3,
|
|
|
|
|
|
A3: 4,
|
|
|
|
|
|
A4: 11,
|
|
|
|
|
|
A5: 12,
|
|
|
|
|
|
A6: 13,
|
|
|
|
|
|
A7: 14,
|
2026-03-16 01:39:26 +07:00
|
|
|
|
};
|
|
|
|
|
|
const map = boardId === 'arduino-nano-esp32' ? NANO_ESP32_MAP : XIAO_S3_MAP;
|
|
|
|
|
|
if (pinName in map) return map[pinName];
|
|
|
|
|
|
const num = parseInt(pinName, 10);
|
|
|
|
|
|
if (!isNaN(num)) return num;
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (boardId === 'xiao-esp32-c3') {
|
|
|
|
|
|
const XIAO_C3_MAP: Record<string, number> = {
|
2026-04-22 02:45:45 +07:00
|
|
|
|
D0: 2,
|
|
|
|
|
|
D1: 3,
|
|
|
|
|
|
D2: 4,
|
|
|
|
|
|
D3: 5,
|
|
|
|
|
|
D4: 6,
|
|
|
|
|
|
D5: 7,
|
|
|
|
|
|
D6: 21,
|
|
|
|
|
|
D7: 20,
|
|
|
|
|
|
D8: 8,
|
|
|
|
|
|
D9: 9,
|
|
|
|
|
|
D10: 10,
|
2026-03-16 01:39:26 +07:00
|
|
|
|
};
|
|
|
|
|
|
if (pinName in XIAO_C3_MAP) return XIAO_C3_MAP[pinName];
|
|
|
|
|
|
const num = parseInt(pinName, 10);
|
|
|
|
|
|
if (!isNaN(num)) return num;
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (boardId === 'aitewinrobot-esp32c3-supermini') {
|
|
|
|
|
|
const num = parseInt(pinName, 10);
|
|
|
|
|
|
if (!isNaN(num)) return num;
|
|
|
|
|
|
return ESP32_PIN_MAP[pinName] ?? null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ATtiny85 — PORTB only: PB0-PB5 → pins 0-5
|
|
|
|
|
|
if (boardId === 'attiny85' || boardId.startsWith('attiny85')) {
|
2026-04-15 12:46:33 +07:00
|
|
|
|
// Power / GND pins — not real GPIOs, skip silently
|
|
|
|
|
|
if (pinName === 'GND' || pinName === 'VCC') return -1;
|
|
|
|
|
|
if (/^PB(\d+)$/.test(pinName)) {
|
|
|
|
|
|
const n = parseInt(pinName.substring(2), 10);
|
|
|
|
|
|
return n >= 0 && n <= 5 ? n : null; // PB6/PB7 don't exist on ATtiny85
|
|
|
|
|
|
}
|
2026-03-16 01:39:26 +07:00
|
|
|
|
// Numeric fallback
|
|
|
|
|
|
const num = parseInt(pinName, 10);
|
|
|
|
|
|
if (!isNaN(num) && num >= 0 && num <= 5) return num;
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// RISC-V generic (CH32V003 target) — PA0-PA7=0-7, PC0-PC7=8-15, PD0-PD7=16-23
|
|
|
|
|
|
if (boardId === 'riscv-generic' || boardId.startsWith('riscv-generic')) {
|
|
|
|
|
|
if (/^PA(\d+)$/.test(pinName)) return parseInt(pinName.substring(2), 10);
|
|
|
|
|
|
if (/^PC(\d+)$/.test(pinName)) return 8 + parseInt(pinName.substring(2), 10);
|
|
|
|
|
|
if (/^PD(\d+)$/.test(pinName)) return 16 + parseInt(pinName.substring(2), 10);
|
|
|
|
|
|
// Numeric fallback
|
|
|
|
|
|
const num = parseInt(pinName, 10);
|
|
|
|
|
|
if (!isNaN(num) && num >= 0 && num <= 23) return num;
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-06 07:07:03 +07:00
|
|
|
|
return null;
|
|
|
|
|
|
}
|