Nur geaenderte Zellen schreiben -- gegen das Flackern im Sekundentakt

Seit der Einzelpositionierung blitzten bei jeder Aktualisierung willkuerliche
Pixel auf, in beiden Zeilen. Ursache ist die Telegrammlaenge: Eine volle Zeile
kostet mit einzeln gesetzten Zeichen rund 100 Bytes statt 20, bei 19200 Baud
und 8E1 (11 Bit je Byte) dauerte ein kompletter Bildwechsel damit rund 300 ms.
Die Anzeige stellt schon waehrend des Empfangs dar, also war der Aufbau zu
sehen -- im Sekundentakt ein Drittel der Zeit.

Von einer Sekunde zur naechsten aendert sich aber fast nichts: "18h36m56s" ->
"18h36m57s" ist eine einzige Ziffer, die Deklination steht meist still.
show_lines vergleicht deshalb gegen den zuletzt dargestellten Inhalt und
schreibt nur die betroffenen Zellen; eine unveraenderte Zeile erzeugt gar kein
Telegramm mehr. Am Geraet gemessen: 306 ms -> 66 ms je Bildwechsel.

Dabei am Geraet aufgefallen und mitbehoben: Dem "s" hinter den Sekunden fehlten
die linken Pixel, dem "m" hinter den Minuten ebenso -- beides Zeichen direkt
rechts von einer Stelle, die sich gerade geaendert hatte. Die Anzeige malt je
Zeichen 7 px breit (daher auch der 7-px-Auto-Vorschub), gesetzt wird aber auf
6-px-Raster: Ein neu geschriebenes Zeichen loescht die erste Pixelspalte seines
rechten Nachbarn. Beim vollstaendigen Neuaufbau fiel das nie auf, weil der
Nachbar gleich danach ohnehin neu gemalt wurde. _zelle_faellig zieht ihn jetzt
mit.

Weitere Details:
- clear() verwirft den gemerkten Inhalt, sonst haelt der Vergleich Zellen
  faelschlich fuer vorhanden und die Anzeige bliebe teilweise leer.
- Schlaegt ein Telegramm fehl, wird der gemerkte Inhalt der Zeile verworfen --
  was angekommen ist, ist dann ungewiss.
- Der Zeichensatz wird nur noch bei der ersten Ausgabe einer Zeile gesetzt. Das
  spart nicht nur Bytes: Jeder Wechsel beschaedigt die Home-Zelle. Findet doch
  einer statt (neues Gradzeichen), wird die oberste Zeile vollstaendig
  nachgezogen.

Zu beiden Befunden gibt es Tests mit Gegenprobe (mit der alten Fassung schlagen
sie fehl). 155 Tests gruen, am Geraet bestaetigt: ruhig, keine fehlenden Pixel.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-27 17:18:11 +02:00
parent 41f5eb1821
commit dae7694a07
4 changed files with 306 additions and 58 deletions
+5 -3
View File
@@ -157,14 +157,16 @@ class TestDisplay(unittest.TestCase):
t = FakeTransport(echo=False)
Display(t, response=True).show_lines("12:34:56", "+45:12:30", clear=True)
self.assertEqual(len(t.frames), 2)
# clear=True ist ein eigenes, sehr kurzes Telegramm, danach je Zeile eins.
self.assertEqual(len(t.frames), 3)
for frame in t.frames:
self.assertEqual(frame[:4], bytes([0x02, 0x81, 0x80, 0x81]))
self.assertEqual(frame[-1], 0x03)
self.assertLessEqual(len(frame), migra.MAX_DATA_UNIT)
unten, oben = t.frames # untere Zeile zuerst
self.assertIn(b"\x1bF0", unten) # mit clear=True: einmal loeschen
loeschen, unten, oben = t.frames # untere Zeile zuerst
self.assertIn(b"\x1bF0", loeschen)
self.assertNotIn(b"\x1bF0", unten)
self.assertNotIn(b"\x1bF0", oben)
# Jedes Zeichen sitzt auf seiner eigenen Zelle: x = LINE_X + i*CELL_WIDTH.