feat: remove unnecessary logging and diagnostic dumps in ESP32 worker; update WS2812 event handling in simulator store

pull/64/head
David Montero Crespo 2026-03-24 14:38:08 -03:00
parent 01f75cf313
commit 0290b24a47
4 changed files with 10 additions and 64 deletions

View File

@ -232,8 +232,6 @@ def main() -> None: # noqa: C901 (complexity OK for inline worker)
# ESP32 signal indices: 72-79 = LEDC HS ch 0-7, 80-87 = LEDC LS ch 0-7 # ESP32 signal indices: 72-79 = LEDC HS ch 0-7, 80-87 = LEDC LS ch 0-7
_ledc_gpio_map: dict[int, int] = {} _ledc_gpio_map: dict[int, int] = {}
_out_sel_dumped = [False] # one-time diagnostic dump flag
def _refresh_ledc_gpio_map() -> None: def _refresh_ledc_gpio_map() -> None:
"""Scan gpio_out_sel[40] registers and update _ledc_gpio_map. """Scan gpio_out_sel[40] registers and update _ledc_gpio_map.
@ -243,25 +241,16 @@ def main() -> None: # noqa: C901 (complexity OK for inline worker)
try: try:
out_sel_ptr = lib.qemu_picsimlab_get_internals(2) out_sel_ptr = lib.qemu_picsimlab_get_internals(2)
if not out_sel_ptr: if not out_sel_ptr:
_log('LEDC gpio_out_sel: internals(2) returned NULL')
return return
out_sel = (ctypes.c_uint32 * 40).from_address(out_sel_ptr) out_sel = (ctypes.c_uint32 * 40).from_address(out_sel_ptr)
# One-time dump of ALL gpio_out_sel values for diagnostics
if not _out_sel_dumped[0]:
_out_sel_dumped[0] = True
non_default = {pin: int(out_sel[pin]) for pin in range(40)
if int(out_sel[pin]) != 256 and int(out_sel[pin]) != 0}
_log(f'LEDC gpio_out_sel dump (non-default): {non_default}')
_log(f'LEDC gpio_out_sel ALL: {[int(out_sel[i]) for i in range(40)]}')
for gpio_pin in range(40): for gpio_pin in range(40):
signal = int(out_sel[gpio_pin]) & 0xFF signal = int(out_sel[gpio_pin]) & 0xFF
if 72 <= signal <= 87: if 72 <= signal <= 87:
ledc_ch = signal - 72 ledc_ch = signal - 72
if _ledc_gpio_map.get(ledc_ch) != gpio_pin: if _ledc_gpio_map.get(ledc_ch) != gpio_pin:
_ledc_gpio_map[ledc_ch] = gpio_pin _ledc_gpio_map[ledc_ch] = gpio_pin
_log(f'LEDC map: ch{ledc_ch} -> GPIO{gpio_pin} (signal={signal})') except Exception:
except Exception as e: pass
_log(f'LEDC gpio_out_sel scan error: {e}')
# Sensor state: gpio_pin → {type, properties..., saw_low, responding} # Sensor state: gpio_pin → {type, properties..., saw_low, responding}
_sensors: dict[int, dict] = {} _sensors: dict[int, dict] = {}
@ -456,7 +445,6 @@ def main() -> None: # noqa: C901 (complexity OK for inline worker)
if marker == 0x5000: # LEDC duty change (from esp32_ledc.c) if marker == 0x5000: # LEDC duty change (from esp32_ledc.c)
ledc_ch = (direction >> 8) & 0x0F ledc_ch = (direction >> 8) & 0x0F
intensity = direction & 0xFF # 0-100 percentage intensity = direction & 0xFF # 0-100 percentage
_log(f'0x5000 callback: direction=0x{direction:04X} ch={ledc_ch} intensity={intensity} map={dict(_ledc_gpio_map)}')
gpio = _ledc_gpio_map.get(ledc_ch, -1) gpio = _ledc_gpio_map.get(ledc_ch, -1)
if gpio == -1: if gpio == -1:
_refresh_ledc_gpio_map() _refresh_ledc_gpio_map()
@ -622,52 +610,13 @@ def main() -> None: # noqa: C901 (complexity OK for inline worker)
def _ledc_poll_thread() -> None: def _ledc_poll_thread() -> None:
# Track last-emitted duty to avoid flooding identical updates # Track last-emitted duty to avoid flooding identical updates
_last_duty = [0.0] * 16 _last_duty = [0.0] * 16
_diag_count = [0]
_first_nonzero_logged = [False]
_log('LEDC poll thread started')
while not _stopped.wait(0.1): while not _stopped.wait(0.1):
try: try:
ptr = lib.qemu_picsimlab_get_internals(6) # LEDC_CHANNEL_DUTY ptr = lib.qemu_picsimlab_get_internals(6) # LEDC_CHANNEL_DUTY
_diag_count[0] += 1
if ptr is None or ptr == 0: if ptr is None or ptr == 0:
continue continue
# duty[] is float[16] in QEMU (percentage 0-100)
arr = (ctypes.c_float * 16).from_address(ptr) arr = (ctypes.c_float * 16).from_address(ptr)
# Refresh LEDC→GPIO mapping from gpio_out_sel[40] registers
_refresh_ledc_gpio_map() _refresh_ledc_gpio_map()
# Log once when nonzero duties first appear
if not _first_nonzero_logged[0]:
nonzero = {ch: round(float(arr[ch]), 2) for ch in range(16)
if float(arr[ch]) != 0.0}
if nonzero:
_log(f'LEDC first nonzero at poll #{_diag_count[0]}: '
f'duties={nonzero} gpio_map={dict(_ledc_gpio_map)}')
_first_nonzero_logged[0] = True
# Periodic diagnostic dump every 50 polls (~5s)
if _diag_count[0] % 50 == 0:
all_duties = {ch: round(float(arr[ch]), 4) for ch in range(16)
if float(arr[ch]) != 0.0}
# Also read LEDC channel conf (internals(4)) and timer freq (internals(5))
diag_parts = [f'duties={all_duties}', f'gpio_map={dict(_ledc_gpio_map)}']
try:
conf_ptr = lib.qemu_picsimlab_get_internals(4)
if conf_ptr:
conf_arr = (ctypes.c_uint32 * 16).from_address(conf_ptr)
nonzero_conf = {ch: hex(int(conf_arr[ch])) for ch in range(16)
if int(conf_arr[ch]) != 0}
diag_parts.append(f'ch_conf={nonzero_conf}')
except Exception:
pass
try:
freq_ptr = lib.qemu_picsimlab_get_internals(5)
if freq_ptr:
freq_arr = (ctypes.c_uint32 * 8).from_address(freq_ptr)
nonzero_freq = {t: int(freq_arr[t]) for t in range(8)
if int(freq_arr[t]) != 0}
diag_parts.append(f'timer_freq={nonzero_freq}')
except Exception:
pass
_log(f'LEDC poll #{_diag_count[0]}: {" | ".join(diag_parts)}')
for ch in range(16): for ch in range(16):
duty_pct = float(arr[ch]) duty_pct = float(arr[ch])
if abs(duty_pct - _last_duty[ch]) < 0.01: if abs(duty_pct - _last_duty[ch]) < 0.01:
@ -679,9 +628,8 @@ def main() -> None: # noqa: C901 (complexity OK for inline worker)
'duty': round(duty_pct, 2), 'duty': round(duty_pct, 2),
'duty_pct': round(duty_pct, 2), 'duty_pct': round(duty_pct, 2),
'gpio': gpio}) 'gpio': gpio})
except Exception as e: except Exception:
import traceback pass
_log(f'LEDC poll error: {e}\n{traceback.format_exc()}')
threading.Thread(target=_ledc_poll_thread, daemon=True, name='ledc-poll').start() threading.Thread(target=_ledc_poll_thread, daemon=True, name='ledc-poll').start()
@ -706,7 +654,6 @@ def main() -> None: # noqa: C901 (complexity OK for inline worker)
raw_v = int(int(cmd['millivolts']) * 4095 / 3300) raw_v = int(int(cmd['millivolts']) * 4095 / 3300)
ch = int(cmd['channel']) ch = int(cmd['channel'])
clamped = max(0, min(4095, raw_v)) clamped = max(0, min(4095, raw_v))
_log(f'set_adc: ch={ch} mv={cmd["millivolts"]} raw={clamped}')
lib.qemu_picsimlab_set_apin(ch, clamped) lib.qemu_picsimlab_set_apin(ch, clamped)
elif c == 'set_adc_raw': elif c == 'set_adc_raw':

View File

@ -71,12 +71,9 @@ PartSimulationRegistry.register('potentiometer', {
const isESP32 = typeof (simulator as any).setAdcVoltage === 'function'; const isESP32 = typeof (simulator as any).setAdcVoltage === 'function';
const refVoltage = (isRP2040 || isESP32) ? 3.3 : 5.0; const refVoltage = (isRP2040 || isESP32) ? 3.3 : 5.0;
console.log(`[Pot] attached: pin=${pin} isESP32=${isESP32} refV=${refVoltage}`);
const onInput = () => { const onInput = () => {
const raw = parseInt((element as any).value || '0', 10); const raw = parseInt((element as any).value || '0', 10);
const volts = (raw / 1023.0) * refVoltage; const volts = (raw / 1023.0) * refVoltage;
console.log(`[Pot] onInput: raw=${raw} volts=${volts.toFixed(3)} pin=${pin}`);
setAdcVoltage(simulator, pin, volts); setAdcVoltage(simulator, pin, volts);
}; };
@ -338,14 +335,11 @@ PartSimulationRegistry.register('servo', {
// 544µs = 2.72%, 2400µs = 12.0% // 544µs = 2.72%, 2400µs = 12.0%
const MIN_DC = MIN_PULSE_US / 20000; // 0.0272 const MIN_DC = MIN_PULSE_US / 20000; // 0.0272
const MAX_DC = MAX_PULSE_US / 20000; // 0.12 const MAX_DC = MAX_PULSE_US / 20000; // 0.12
console.log(`[Servo:ESP32] registering onPwmChange on pin=${pinSIG}`);
const unsubscribe = pinManager.onPwmChange(pinSIG, (_pin, dutyCycle) => { const unsubscribe = pinManager.onPwmChange(pinSIG, (_pin, dutyCycle) => {
console.log(`[Servo:ESP32] onPwmChange pin=${_pin} dutyCycle=${dutyCycle.toFixed(4)}`);
if (dutyCycle < 0.01 || dutyCycle > 0.20) return; // ignore out-of-range if (dutyCycle < 0.01 || dutyCycle > 0.20) return; // ignore out-of-range
const angle = Math.round( const angle = Math.round(
((dutyCycle - MIN_DC) / (MAX_DC - MIN_DC)) * 180 ((dutyCycle - MIN_DC) / (MAX_DC - MIN_DC)) * 180
); );
console.log(`[Servo:ESP32] angle=${angle}`);
el.angle = Math.max(0, Math.min(180, angle)); el.angle = Math.max(0, Math.min(180, angle));
}); });
return () => { unsubscribe(); }; return () => { unsubscribe(); };

View File

@ -33,7 +33,6 @@ export function setAdcVoltage(simulator: AnySimulator, pin: number, voltage: num
const channel = pin - 26; const channel = pin - 26;
// RP2040 ADC: 12-bit, 3.3V reference // RP2040 ADC: 12-bit, 3.3V reference
const adcValue = Math.round((voltage / 3.3) * 4095); const adcValue = Math.round((voltage / 3.3) * 4095);
console.log(`[setAdcVoltage] RP2040 ch${channel} = ${adcValue} (${voltage.toFixed(3)}V)`);
simulator.setADCValue(channel, adcValue); simulator.setADCValue(channel, adcValue);
return true; return true;
} }

View File

@ -862,6 +862,12 @@ export const useSimulatorStore = create<SimulatorState>((set, get) => {
}); });
}; };
bridge.onLedcUpdate = makeLedcUpdateHandler(boardId); bridge.onLedcUpdate = makeLedcUpdateHandler(boardId);
bridge.onWs2812Update = (channel, pixels) => {
const eventTarget = document.getElementById(`ws2812-${boardId}-${channel}`);
if (eventTarget) {
eventTarget.dispatchEvent(new CustomEvent('ws2812-pixels', { detail: { pixels } }));
}
};
esp32BridgeMap.set(boardId, bridge); esp32BridgeMap.set(boardId, bridge);
const shim = new Esp32BridgeShim(bridge, pm); const shim = new Esp32BridgeShim(bridge, pm);
shim.onSerialData = serialCallback; shim.onSerialData = serialCallback;