OpenDCC Handregler - Erläuterungen zur Software

    Die Display werden per Treiber angesteuert. In den Bildschirmroutinen der einzelnen Menus sind alle Aufrufe an das Display zusammengefaßt und werden per Compile-Switch je nach Display eingebunden.

Displayansteuerung Zeichen-LCD

    Das Display EA204-4 besitzt 4 Zeilen zu je 20 Zeichen. Es wird per SPI angesteuert.
    Innerhalb des Displays ist das Eck oben rechts für die Statusanzeige reserviert.

    Sonderzeichen des Chips KS0073 (wie z.B. Pfeile) sind über defines zugänglich gemacht.

Displayansteuerung Graphik-LCD

    Das Display kann nicht rückgelesen werden, es wird daher intern mit einem Framebuffer gearbeitet. alle Ausgaben erfolgen in diesen Framebuffer, der Update des LCDs wird als Hintergrund-Task vom Betriebssystem erledigt. Damit vermeidet man Flackern bei komplexeren Displayupdates und umgeht die Einschränkungen, die sich aus dem fehlenden Rücklesen ergäben.
  • Ein Menu-Handler schreibt seine Ausgabe entweder mittels der Graphiklibrary Bitmaps, Linien oder Proportionalschrift auf das Display. Oder er benutzt die in Treiber als default implementierte 7x5-Schrift - diese besitzt konstante Laufweite und ist auf Zeilen limitiert (Textmode). Beides darf beliebig gemischt werden.
  • Ein Editcursor wird nicht in den Framebuffer eingetragen, sondern erst beim Update des Framebuffers mit in das Display eingerechnet. Der Cursor hat zwei Zustände (on-off), ein blinkender Cursor wird durch einen weiteren Thread erzeugt, welcher den Zustand umschaltet und einen Update der Cursorregion veranlaßt.
  • Wenn der Menu-Handler an den Navigator zurückgibt, wird mittels 'display_update_enable()' die Hintergrundtask für den Refresh des LCD freigegeben. Diese zerlegt den Bildspeicher in 8 Teile (pages) und arbeitet diese nacheinander ab. Ein kompletter Update braucht also 8 Ticks - ca. 12ms.
  • Durch die Ausgabe wird automatisch der Updateprozess gestoppt - es werden also keine Zwischenzustände des framebuffers auf das Display kopiert. Die Ausgabe setzt außerdem die jeweiligen Update-Semaphore der einzelnen pages - wenn nur in einer Zeile geschrieben wird, so muß auch nur diese Zeile später refreshed werden.

Einbindung von Graphiken und Bildern

    Bilder (BMP-files) müssen vor der Verwendung im Handregler auf ein für den Controller leicht handhabbares Format gebracht werden. Hierzu wird der Konverter bmp2glcd verwendet.

    Das Bild wird in senkrechte Teilstriche zu 8 Bit zerlegt, LSB oben. Innerhalb einer Datei wird mit der ersten Zeile aus Teilstrichen begonnen, es folgt die zweite Zeile (also die vertikalen Pixel 8..15), usw. Eine solche Zeile aus Teilstrichen paßt gut zur Pixelorganisation des LCDs. (Zeile = page).

    Der Konverter erzeugt eine header-Datei, welche dann einfach im Sourcecode eingebunden wird. Der Bildinhalt wird mit der Funktion LCD_drawBMP einkopiert. Dies erfolgt pixelweise. Bedeutend schneller geht es, wenn das Bild an einer page-Grenze liegt. LCD_fillPage_with_BMP kopiert dann direkt je ein Byte.

Benutzerdefinierte Bilder

    Hier sieht man sich einer Reihe von Schwierigkeiten gegenüber:
  • Wo werden Bilder gespeichert?
    Hier sind zwei Möglichkeiten offen: entweder man benutzt eine SD-Karte (diese wäre per SPI ansteuerbar) oder man verwendet das auf dem Board vorbereitete Flash. Gerade wegen des schnelle Zugriffes durch eine angepasste Speicherorganisation (s.u.) habe ich die zweite Alternative gewählt.
  • Wie kommen die Bilder in den Handregler?
    Die Bilder werden über das Kommando-Interface am USB-Port übertragen. Dies ist zwar nicht so schnell, aber der Download muß ja nur einmal erfolgen.
  • Wie kann man schnell darauf zugreifen?
    Innerhalb des Handregler muß zum einen ein Bild schnell zu einer Picture-ID gefunden werden (Blättern in der Lokliste), zum anderen muß man bei der Zuweisung eines Bildes schnell zu Vorgänger oder Nachfolger finden.
  • Bei einer Speicherung in einem Flash ist zudem noch die Schwierigkeit, dass das Flash nur in der Richtung von 1 nach 0 überschrieben werden kann. Ein Löschen ist nur sektorweise (in Blöcken zu 512kBit) möglich. Folgender Lösungsansatz wird im Handregler verfolgt:
  • Neue Bilder werden 'wahllos' im Speicher abgelegt, wobei der Index des abzulegenden Bildes so gewählt wird, dass möglichst viele Indexbits auf 1 sind. Überarbeitete Bilder (also solche, die nochmal geladen werden) werden zuerst überprüft, ob sie 'kleiner' oder gleich dem bisherigen Bild sind. Wenn ja, dann bleibt das Bild an dieser Stelle. Wenn nein, wird ein neuer Bildplatz gesucht, dessen Index sich aus dem bisherigen Index durch hinzufügen von 0-Bits bilden läßt.
  • Diese Bildindeces werden in einer Lookup-Tabelle gespeichert, deren Index die Picture-ID ist. Diese Tabelle hat also 65536 mögliche Einträge und ist 128kByte groß. Ein Bild zu einer Picture-ID kann nun also durch Nachschlagen des Index und Zugriff auf den Bildspeicher schnell gefunden werden.
  • Um beim Suchen in der Bildliste nicht immer die lange Lookuptabelle durchwühlen zu müssen, sind je 32 Lookupeinträge zu einem Allokationsbit zusammengefasst. Bei 65536 Tabelleneinträge ergeben sich also 2048 Allokationsbits bzw. 256 Byte Allokationsspeicher. Damit können unbenutze Indexbereiche bei der Suche schnell übersprungen werden.

Links