diff --git a/versapad_serial.py b/versapad_serial.py index 2c795a1..d3eb978 100644 --- a/versapad_serial.py +++ b/versapad_serial.py @@ -37,6 +37,7 @@ CONFIG_SIZE = 740 MACRO_SIZE = 512 ACTIVE_PROFILE_OFFSET = 7 +CMD_READ_STATUS = 0x06 CMD_CONFIG_BEGIN = 0x10 CMD_CONFIG_DATA = 0x11 CMD_CONFIG_COMMIT = 0x12 @@ -46,6 +47,7 @@ CMD_MACRO_DATA = 0x21 CMD_MACRO_COMMIT = 0x22 CMD_MACRO_READ = 0x23 +EVT_STATUS = 0x86 EVT_CONFIG_ACK = 0x90 EVT_CONFIG_NACK = 0x91 EVT_CONFIG_BEGIN = 0x92 @@ -187,16 +189,39 @@ class VersaPadLink: # ── Oeffentliche API ──────────────────────────────────────── - def read_active_profile(self): - """0-2 bei Erfolg, None bei Timeout/Fehler/kein Board.""" - buf = self._read_dump(CMD_CONFIG_READ, EVT_CONFIG_BEGIN, EVT_CONFIG_DATA, EVT_CONFIG_END, CONFIG_SIZE) - if buf is None: + def read_active_profile(self, deadline_s=1.0): + """0-2 bei Erfolg, None bei Timeout/Fehler/kein Board. + + Nutzt CMD_READ_STATUS (1 Antwortpaket) statt eines vollen CONFIG_READ- + Dumps (124 Pakete) -- der volle Dump blockiert die Firmware lange genug, + dass laufende LED-Pulse-Animationen beim Live-Sync-Polling sichtbar + stottern (siehe VersaMCU doc/07_serial_protocol.md, "READ_STATUS vs. + CONFIG_READ fuer Polling"). Für ältere Firmware ohne CMD_READ_STATUS + faellt das Board auf keine Antwort zurueck -> Timeout, kein Absturz.""" + if not self._ensure_open(): return None - profile = buf[ACTIVE_PROFILE_OFFSET] - if profile not in (0, 1, 2): + try: + self.ser.reset_input_buffer() + self.ser.write(bytes([CMD_READ_STATUS, 0, 0, 0, 0, 0, 0, 0])) + + deadline = time.time() + deadline_s + while time.time() < deadline: + raw = self.ser.read(PACKET_SIZE) + if len(raw) < PACKET_SIZE: + continue + if raw[0] == EVT_STATUS: + profile = raw[1] + if profile not in (0, 1, 2): + self.last_error = "timeout" + return None + self.last_error = None + return profile self.last_error = "timeout" return None - return profile + except serial.SerialException: + self.close() + self.last_error = "busy" + return None def read_full_config(self): """740B Rohdaten (alle 3 Profile) oder None."""