fix(uart): la Pi puede hablar por serie con la placa de al lado
Dos piezas que faltaban para que pi-to-arduino-led-control fuera algo
mas que un guion imprimiendo lo que "habria enviado".
1) classifyPin no reconocia los pads del header por su nombre. Se llaman
GPIO14 / GPIO15 en el dibujo de la placa y en todos los cables de los
ejemplos, pero solo se aceptaban numeros fisicos: parseInt('GPIO14')
daba NaN, el pin no clasificaba como nada y el Interconnect nunca
construia la ruta. Ahora se acepta el prefijo GPIO/BCM y la numeracion
fisica sigue funcionando.
2) Seam de serie para placas que no tienen ni simulador ni bridge: el
motor de navegador corre el Python de la Pi en la propia pestana.
registerSerialSink(placa, fn) recibe los bytes que le llegan y
feedBoardSerialOut(placa, ch) anuncia los que envia, que es lo que el
enrutado por cables ya sabia repartir.
This commit is contained in:
parent
8e1001740a
commit
9160624da4
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* A Raspberry Pi header pad wired to an Arduino serial pin must be seen
|
||||
* as a UART link.
|
||||
*
|
||||
* The pads are LABELLED 'GPIO14' / 'GPIO15' — that is what the board art
|
||||
* shows and what every example wire uses. `normalizePinName` only accepted
|
||||
* physical pin numbers for the Pi, so parseInt('GPIO14') was NaN, the pin
|
||||
* classified as nothing, and Interconnect never built the route: a Pi
|
||||
* sending commands to an Arduino was talking into the void.
|
||||
*/
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { classifyPin, isUartWire } from '../utils/boardProtocols';
|
||||
|
||||
describe('Raspberry Pi UART pins', () => {
|
||||
it('classifies the BCM-named header pads', () => {
|
||||
expect(classifyPin('raspberry-pi-3', 'GPIO14')).toEqual({ kind: 'uart-tx', uart: 0 });
|
||||
expect(classifyPin('raspberry-pi-3', 'GPIO15')).toEqual({ kind: 'uart-rx', uart: 0 });
|
||||
// Physical numbering keeps working (pin 8 = BCM14, pin 10 = BCM15).
|
||||
expect(classifyPin('raspberry-pi-3', '8')).toEqual({ kind: 'uart-tx', uart: 0 });
|
||||
expect(classifyPin('raspberry-pi-3', '10')).toEqual({ kind: 'uart-rx', uart: 0 });
|
||||
});
|
||||
|
||||
it('recognises the Pi <-> Arduino cross-board wires', () => {
|
||||
expect(isUartWire('raspberry-pi-3', 'GPIO14', 'arduino-uno', '0')).toBeTruthy();
|
||||
expect(isUartWire('arduino-uno', '1', 'raspberry-pi-3', 'GPIO15')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -182,12 +182,44 @@ function pushPinState(boardId: string, pin: number, state: boolean): void {
|
|||
}
|
||||
}
|
||||
|
||||
// ── Serial seam for boards driven from outside the sim/bridge pair ───────
|
||||
//
|
||||
// A QEMU-Linux board can also run its Python in the tab (no WebSocket, no
|
||||
// bridge object). Such a board still has UART wires on the canvas, so it
|
||||
// needs both directions of the routing: a sink to receive bytes, and a way
|
||||
// to announce the ones it sends. Both are plain callbacks — nothing here
|
||||
// knows what is on the other end.
|
||||
const serialSinks = new Map<string, (ch: string, uart: number) => void>();
|
||||
|
||||
/** Receive UART bytes addressed to this board. Returns an unregister fn. */
|
||||
export function registerSerialSink(
|
||||
boardId: string,
|
||||
sink: (ch: string, uart: number) => void,
|
||||
): () => void {
|
||||
serialSinks.set(boardId, sink);
|
||||
return () => {
|
||||
if (serialSinks.get(boardId) === sink) serialSinks.delete(boardId);
|
||||
};
|
||||
}
|
||||
|
||||
/** Announce a UART byte this board just transmitted, so the wires route it. */
|
||||
export function feedBoardSerialOut(boardId: string, ch: string, uart = 0): void {
|
||||
const subs = boards.get(boardId)?.serialFanout.get(uart);
|
||||
if (subs) for (const cb of subs) cb(ch);
|
||||
}
|
||||
|
||||
/** Push a UART byte into the receiving board's UART RX. */
|
||||
function pushSerialByte(boardId: string, ch: string, uart: number): void {
|
||||
if (!runtime) return;
|
||||
const entry = boards.get(boardId);
|
||||
if (!entry) return;
|
||||
|
||||
const sink = serialSinks.get(boardId);
|
||||
if (sink) {
|
||||
sink(ch, uart);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBrowserSim(entry.kind)) {
|
||||
const sim = runtime.getBoardSimulator(boardId);
|
||||
// RP2040Simulator doesn't yet expose feedUart per-UART — fall back
|
||||
|
|
|
|||
|
|
@ -191,6 +191,13 @@ function normalizePinName(boardKind: string, pinName: string): string | null {
|
|||
boardKind.startsWith('raspberry-pi-4') ||
|
||||
boardKind.startsWith('raspberry-pi-5')
|
||||
) {
|
||||
// The header pads are LABELLED 'GPIO14' (that is what the board art
|
||||
// and every example wire use); only physical numbers were accepted
|
||||
// here, so parseInt('GPIO14') was NaN and the pin classified as
|
||||
// nothing at all — a Pi TX wired to an Arduino RX was never seen as a
|
||||
// UART link, and the two boards could not talk.
|
||||
const bcm = trimmed.match(/^(?:GPIO|BCM)(\d+)$/);
|
||||
if (bcm) return bcm[1];
|
||||
const phys = parseInt(trimmed, 10);
|
||||
if (!isNaN(phys)) {
|
||||
const bcm = PI3_PHYSICAL_TO_BCM[phys];
|
||||
|
|
|
|||
Loading…
Reference in New Issue