esp32: map S3-family GPIO pins to ADC channels in setAdcVoltage/setAdcWaveform

The GPIO->channel map only covered the classic ESP32 (GPIO 36-39/32-35),
so on esp32-s3 / xiao-esp32-s3 / arduino-nano-esp32 every SPICE-driven
analog value was dropped and analogRead saw 0 (when it didn't hang —
fixed machine-side in libqemu 1.2.5's SENS stub). S3 family: ADC1 =
GPIO 1-10 -> CH0-9, ADC2 = GPIO 11-20 -> channel index 10-19, matching
the machine's channel layout.
This commit is contained in:
David Montero 2026-07-31 18:38:04 +02:00
parent 0c69c847ad
commit cd5cbb14f3
1 changed files with 20 additions and 7 deletions

View File

@ -212,11 +212,26 @@ class Esp32BridgeShim {
* ESP32 ADC1: GPIO 36-39 CH0-3, GPIO 32-35 CH4-7
* Returns true if the pin is a valid ADC pin.
*/
/** GPIO -> ADC channel for the bridge's board family. Classic ESP32:
* ADC1 on GPIO 36-39 (CH0-3) + 32-35 (CH4-7). ESP32-S3 family (incl.
* xiao-esp32-s3 and the S3-based arduino-nano-esp32): ADC1 = GPIO 1-10
* (CH0-9), ADC2 = GPIO 11-20 (stored at channel index 10-19, matching
* the machine's SENS stub). Without the S3 branch analogRead always saw
* 0 there (2026-07 emulation-gaps audit, F1). */
private adcChannelForPin(pin: number): number {
const kind = this.bridge.boardKind as string;
if (kind === 'esp32-s3' || kind === 'xiao-esp32-s3' || kind === 'arduino-nano-esp32') {
if (pin >= 1 && pin <= 10) return pin - 1;
if (pin >= 11 && pin <= 20) return 10 + (pin - 11);
return -1;
}
if (pin >= 36 && pin <= 39) return pin - 36; // GPIO 36→CH0 … 39→CH3
if (pin >= 32 && pin <= 35) return pin - 28; // GPIO 32→CH4 … 35→CH7
return -1;
}
setAdcVoltage(pin: number, voltage: number): boolean {
let channel = -1;
if (pin >= 36 && pin <= 39)
channel = pin - 36; // GPIO 36→CH0, 37→CH1, 38→CH2, 39→CH3
else if (pin >= 32 && pin <= 35) channel = pin - 28; // GPIO 32→CH4, 33→CH5, 34→CH6, 35→CH7
const channel = this.adcChannelForPin(pin);
if (channel < 0) return false;
const millivolts = Math.round(voltage * 1000);
this.bridge.setAdc(channel, millivolts);
@ -232,9 +247,7 @@ class Esp32BridgeShim {
* `samples` are 12-bit raw values (0-4095) aligned on a uniform grid.
*/
setAdcWaveform(pin: number, samples: Uint16Array, periodNs: number): boolean {
let channel = -1;
if (pin >= 36 && pin <= 39) channel = pin - 36;
else if (pin >= 32 && pin <= 35) channel = pin - 28;
const channel = this.adcChannelForPin(pin);
if (channel < 0) return false;
this.bridge.setAdcWaveform(channel, samples, periodNs);
return true;