FT8xx Library

Wechseln zu: Navigation, Suche

von Benutzer:Rudolph

Unter dem Namen EVE - Embbedded Video Engine - hat FTDI eine Reihe von Chips auf den Markt gebracht die es ermöglichen auch kleinere MikroController an TFT-Displays anzuschliessen. Die erste Generation kam bereits Anfang 2013 mit dem FT800 und FT801 auf den Markt, die aktuellen Produkte die auch als EVE2 bezeichnet werden umfassen die Chips FT810, FT811, FT812 und FT813.

Da mich die bestehenden Implemtierungen nicht überzeugt haben und ich mich andererseits tiefer mit den FT8xx beschäftigen wollte, habe ich mich gegen Ende 2015 an die Arbeit gemacht, meine eigene Funktions-Bibliothek zu schreiben.

Hardware[Bearbeiten]

Es gibt eine Reihe fertiger FT8xx Module mit TFT die man über eine SPI Schnittstelle mit einem quasi beliebigen MikroController verbinden kann.
Angefangen habe ich mit einem VM800B von FTDI, dieses 3,5" TFT mit 320x240 Pixeln hat einen resistiven Touch-Screen, Pegel-Wandler, 3,3V Regler und einen Verstärker mit Lautsprecher verbaut.
Als nächstes kam dann ein FT800CB-HY50B von HAOYU dazu welches ich später auf FT810 umgelötet habe. Die Module von HAOYU haben ebenfalls Pegelwandler und 3,3V Regler, aber keinen Verstärker für Audio.
Aktuell benutze ich ein RVT70UQFNWC0x von Riverdi, diese habe keine Pegel-Wandler und benötigen sowohl 3,3V als auch 5V.

Test-Projekt


Software[Bearbeiten]

Da mir Multi-Plattform Support wichtig ist besteht die "Library" aus mehreren Quelltext-Modulen die im Projekt-Context compiliert werden.
Implementiert für und benutzt mit habe ich die Library mit eigenen 90CANxx AVR Platinen, Arduino (miniPro) und Renesas RH850 Controller.

Die "Library" selbst besteht aktuell aus diesen Dateien:
FT8.h - Definitionen und Macros
FT8_commands.c - Die eigentlichen Funktionen, Plattform unabhängig
FT8_commands.h - exportiert die benötigten Funkionen
FT8_config.c - Abstrahierungs Funktionen die auf der verwendeten Plattform automatisch ausgewählt werden
FT8_config.h - Projekt-spezifische Einstellungen wie Chip-Select und Display-Parameter

Verwendung[Bearbeiten]

Erstmal muss ich dazu raten, einen Blick in die Datasheet/Programmers-Guides von FTDI/Bridgetek zu werfen:
DS_FT801.pdf
FT800_Series_Programmer_Guide.pdf
DS_FT81x.pdf
FT81X_Series_Programmer_Guide.pdf

Die FT8xx arbeiten Objekt-Orientiert und die Anzeige erfolgt mit einer Display-Liste, die Liste wird von meiner Library mit Hilfe des Kommando-Co-Prozessors aktualisiert.
Der Co-Prozessor verwendet einen 4096 Byte grossen FIFO Speicher, jedes Kommando belegt mindestens 4 Byte und es muss auch immer auf volle 4 Byte aufgefüllt werden. Es passen also maximal 1024 Kommandos in den FIFO und effektiv viel weniger "Objekte" weil diese meistens ein vielfaches von 4 Byte benötigen. Ein FT8_cmd_text() zum Beispiel benötigt 4 Byte für das Kommando, 4 Byte für die Koordinaten, 4 Byte für Zeichensatz und Optionen und dann noch Platz für den eigentlichen Text. Ein "Hallo Welt" kommt so in Summe auf 24 Byte im FIFO, sind zwar eigentlich nur 22, dann wird aber noch mit Null-Bytes aufgefüllt.
Wofür ist das wichtig? Nun, man muss schon ein wenig aufpassen wie viel man versucht in die Display-Liste zu stecken, hat man zu viele Einträge läuft der FIFO über und die Anzeige funktioniert nicht.
Die FT80x haben 256 kByte Grafik-Speicher, die FT81x haben 1 MByte, Bilder werden zum Programm-Start gepackt in diesen Speicher übertragen und dort vom FT8xx entpackt. Zum Laden wird entweder cmd_inflate() oder cmd_loadimage() benutzt, ersteres empfiehlt sich mit monochrom-Bildern, letzteres ist für .jpg Bilder gedacht.
Die FT81x unterstützen auch .png, man muss aber etwas mit dem Format aufpassen.
Je nach verwendetem Format belegen die Bilder unterschiedlich viel Speicher im FT8xx. Beim "L1" Format sind es 1 Bit pro Pixel, "L8" benötigt ein Byte pro Pixel, "RGB565" kommt auf zwei Byte pro Pixel.
Ein 100x100 Pixel großes Vollfarb-Icon belegt also entpackt 20.000 Bytes im FT8xx.
Ein Bild in 800x480 würde 768.000 Bytes belegen, in 800x600 gar 960.000 Bytes, es passt also überhaupt nur ein Bild in voller Auflösung in den Speicher der FT81x - dafür sind die klar nicht ausgelegt.
Ich kann grundsätzlich empfehlen, eine Memory-Map zu erstellen, dafür habe ich in der tft.c in meinem Test-Projekt am Anfang Defines für die Start-Adressen.

Unter FT800 / FT810 Library habe ich unter anderem mehrere Beispiel-Projekte veröffentlicht. Der derzeit aktuelle Stand ist das "FT8xx_Test" Projekt dessen Verzeichnis ich passend zur verwendeten Hardware benennen. Etwa "FT8xx_Test_90CAN_FT813_RVT70UQFNWC0x" oder auch "FT8xx_Test_90CAN_FT810_HY50B". Das ist ein vollständiges Projekt für Atmel-Studio 7.
Zusätzlich zu den Funktionen der "Library" gibt es Plattform-spezifische Dinge zu erledigen, etwa das Initialisieren des SPI, sowie der benötigten Pins für die Chip-Select und Powerdown Ausgänge. Zusätzlich empfiehlt sich grundsätzlich eine Art Scheduler zu benutzen der in einem Ereignis-gesteuerten Programmablauf für ein festes Zeitintervall sorgt.
Die main.c im Test-Projekt implementiert das soweit, Plattform-spezifisch für AVR Controller.
Die nächsten Dateien sind dann wieder Plattform unabhängig:
tft.c - drei Funktionen, initStaticBackground(), TFT_init() und TFT_loop() tft.h - exportiert TFT_init() und TFT_loop()
tft_data.c - test-Bilder
tft_data.h

TFT_init():
Wie der Name schon sagt wird mit dieser Funktion das Display initialisiert. Dazu erfolgt zunächst ein Aufruf von FT8_init(). Ist das Display nicht oder nicht richtig angeschlossen kehrt die Funktion nach einem 200ms Timeout mit einer Null zurück.
Dann erfolgt die Übermittlung der Touch-Kalibrier-Werte, es reicht völlig aus diese einmal zu ermitteln und in den Quelltext zu schreiben, Code zum Kalibrieren des Displays und zum Anzeigen der Werte ist per "#if 0" Statement auskommentiert.
Schliesslich werden noch die benötigten Bilder an den FT8xx übertragen und die Funktion initStaticBackground() aufgerufen.

initStaticBackground():
Mein Beispiel teilt die Display-Liste in einen statischen und einen dynamischen Teil auf. Der statische Teil wird nur einmal erzeugt, im FT8xx gespeichert und beim aktualisieren der Liste immer wieder mit einkopiert. Das hat den Vorteil, dass pro aktualisierung der Liste erheblich weniger über den SPI übertragen werden muss als wenn man das komplett übertragen würde.
Wichtig ist dabei, dass die Objekte in der Reihenfolge auf das Display gebracht werden in der sie in der Liste stehen.

TFT_loop():
Diese Funktion ist dafür ausgelegt alle 10ms aufgerufen zu werden. Es gibt zwei Teile die sich abwechseln, die Auswertung von Touch-Events und entsprechend Akualisierung von Variablen, sowie das eigentliche neu Schreiben der Display-Liste. In meinem Beispiel wird die Liste also alle 20ms neu geschrieben, die Darstellung erfolgt mit 50 neuen Bilder pro Sekunde. Das geht sowohl langsamer als auch schneller, macht man das langsamer wird allerdings die Reaktion auf den Touch träger, macht man das schneller muss man aufpassen, dass man unterhalb der 60 Hz vom TFT bleibt, die FT8xx mögen es nicht, wenn man die Liste schneller aktualisiert als sie dargestellt wird.
Die Auswertung von Touch-Events erfolgt mit TAG-Werten, über "FT8_cmd_dl(TAG(n));" kann einzelnen Objekten oder auch ganzen Gruppen von Objekten ein Wert von 1 bis 255 zugewiesen werden. Ein Wert von Null bedeutet dabei, das kein Touch-Event erfolgt ist und wenn man Objekten diesen Wert zuweist sind sie von der Erkennung ausgenommen.
Im Beispiel gibt es nur einen Toggle-Button und einen Slider die ausgewertet werden, wie man daran aber sehen kann erfolgt zwar die Erkennung von Touch-Events über den FT8xx, darauf reagieren muss aber die eigene Software indem ein Toggle-Button auch wirklich optisch umgeschaltet oder auch ein normaler Button als gedrückt dargestellt wird.
Das eigentliche Aktualisieren der Display-Liste ist recht kurz weil der größere Teil der Anzeige statisch ist und über FT8_cmd_append() mit eingehängt wird.
Die mit FT8_cmd_number() dargestellten Zahlen sind im Beispiel zwar weitgehend statisch, aber mit dem einen Wert der sich in Abhängigkeit des Sliders ändert sieht man sicher was die Idee dahinter ist das in den dynamischen Teil zu packen.

Download[Bearbeiten]