velxio/frontend/src/simulation/esp32-signals.ts

54 lines
2.2 KiB
TypeScript

/**
* ESP32 GPIO Matrix output signal source IDs.
*
* Mirror of `backend/app/services/esp32_signals.py`. Keep both
* files in sync — the worker emits the numeric ids defined in the
* Python module via WebSocket and the frontend interprets them
* here. The constants come from the ESP32 Technical Reference
* Manual section 4.11 ("IO_MUX and GPIO Matrix").
*/
// ── LEDC (PWM peripheral) ─────────────────────────────────────────────────
// Per ESP32 TRM section 4.11, Table 4-3 (GPIO Matrix output signals):
// 71-78 → LEDC_HS_SIG_OUT[0..7] (high-speed channels 0-7)
// 79-86 → LEDC_LS_SIG_OUT[0..7] (low-speed channels 0-7)
// The legacy worker code used 72-87 (off by one). That bug rerouted
// every multi-servo project's channels — see
// backend/app/services/esp32_signals.py for the full explanation.
export const SIG_LEDC_HS_CH0_OUT_IDX = 71;
export const SIG_LEDC_HS_CH_LAST = 78;
export const SIG_LEDC_LS_CH0_OUT_IDX = 79;
export const SIG_LEDC_LS_CH_LAST = 86;
/**
* Map a velxio-style unified LEDC channel index (0..15) to its GPIO
* Matrix signal source id. velxio unifies HS + LS into 0..15 where
* 0-7 = HS, 8-15 = LS — matches the encoding the QEMU plugin emits
* on the 0x5000 duty callback.
*/
export function ledcSignalForChannel(channel: number): number {
if (channel < 0 || channel >= 16 || !Number.isInteger(channel)) {
throw new Error(`ledc channel out of range: ${channel}`);
}
return channel < 8
? SIG_LEDC_HS_CH0_OUT_IDX + channel
: SIG_LEDC_LS_CH0_OUT_IDX + (channel - 8);
}
/**
* Inverse of {@link ledcSignalForChannel}. Returns null when the
* signal id is not an LEDC channel.
*/
export function channelForLedcSignal(signalId: number): number | null {
if (signalId >= SIG_LEDC_HS_CH0_OUT_IDX && signalId <= SIG_LEDC_HS_CH_LAST) {
return signalId - SIG_LEDC_HS_CH0_OUT_IDX;
}
if (signalId >= SIG_LEDC_LS_CH0_OUT_IDX && signalId <= SIG_LEDC_LS_CH_LAST) {
return 8 + (signalId - SIG_LEDC_LS_CH0_OUT_IDX);
}
return null;
}
// ── Sentinel: GPIO not routed (driven by GPIO_OUT_REG bit directly) ──────
export const SIG_GPIO_DIRECT_OUT_IDX = 256;