Aki nem ismerné az FT80x családot, annak előtte mindenképpen érdemes az FTDI EVE anyagok között olvasgatni. Aki inkább a videókat kedveli, van itt néhány a sok közül, lehet válogatni. Nekem a Gameduino 2 a kedvencem.
Az FT800 Programmer Guide kicsit döcögősen alakult azzá, amivé mára vált. Amikor elkezdtem a gyári fejlesztői áramkörrel és egy 4.3"-es reszisztív TFT-vel barátkozni az említett Guide alapján, hát... elég nehezen fogtam fel az egésznek a logikáját. Ma már azért sokat tisztult a kép a fejemben, meg a leíráson is javítottak, továbbá jóval több a bevezető jellegű, értelmes leírás és példaprogram is.
Időközben megjelent néhány ingyenes gyári szoftver is, ami jócskán megkönnyíti a képernyőképek grafikus tervezését. Az egyik ilyen szoftver a Screen Editor, a másik a Screen Designer. Tervezem a részletes bemutatásukat egy következő bejegyzésben. Persze, aki ennél többet akar, annak pl. a MikroElektronika kínálja a Visual TFT fejlesztői rendszert - persze nem ingyen.
2014 elején még némi nehézséget jelentett egy Atmel megaAVR-ekhez használható, működő FT800-as library beszerzése. Az FTDI gyári minta alkalmazása illetve annak megfejtése számomra sok órás keresztrejtvény fejtéssel volt egyenlő a több platformos hardver absztrakciós réteget tartalmazó forrásprogram miatt. A hócipőm is tele volt már vele, nem is tagadom!
További nehézséget jelentett, hogy én a HP InfoTech CodeVisionAVR fejlesztői rendszerét használom, ami némileg különbözik a GNU licenc alatti AVR GCC-től. De aki keres, az talál! Így jött a képbe Guillaume Smolders GitHub-os FT800 Library-ja (köszönet érte). Na ez átlendített a holtponton, ennek nyomán hamarosan megszületett a saját adaptációm, amit azóta is csiszolgatok, bővítgetek.
Emlékeztetőül, röviden: szoftveres szempontból az FT80x chip kezelése egyszerű macro-szerű vagy kicsit összetettebb tényleges függvényekkel történik. A függvények rendelkezhetnek bemenő paraméterekkel és/vagy függvényértékkel. Többek között vannak a hardvert (pl. órajel, szinkronjelek, stb.), a hangot, a megjelenési környezetet (pl. háttér vagy előtér színe), és az egyes ú.n. primitíveket és widgeteket (én utóbbiakat az egyszerűség kedvéért komponenseknek hívom) beállító függvények (pl. egy gomb, vagy egy folyamatjelző).
Csak nagyon egyszerű esetben, leginkább az FT80x programozás tanulásakor érdemes fix értékekkel ellátott ú.n. Display List-eket létrehozni, mert az így "bevasalt" értékeket nem lehet programfutás közben megváltoztatni. Ilyen tipikusan egy nyomógomb megnyomásakor látható 3D hatás (a gomb érintéskor "benyomódik", majd elengedéskor "felugrik"). Helyette minden módosítandó értéket változókba érdemes elhelyezni, amelyek értékét egy önálló megjelenítő függvény írja majd be a chip megfelelő regisztereibe. A jó átláthatóság érdekében viszont érdemes egy komponens összes paraméterét egy egységbe összefogni. Igaziból erre (is) lennének jók az egyes komponens osztályok az ő tulajdonságaikkal...
A CvAVR nem objektum orientált C++, hanem csak sima ANSI C fejlesztést enged meg. Ezért osztályok helyett előszeretettel használok struktúrákat, amikkel többek között jól össze lehet fogni az FT80x EVE grafikus primitíveinek, komponenseinek a tulajdonságait, állapotát, stb. Aki az ingyenes Atmel Studiót használja és ismeri a C++-t, meg is valósíthatja (az Arduino részére az FTDI ad C++ támogatást, de tudtommal az Atmel Studio részére nem).
Egy kicsit is összetettebb képernyőt azonban már kezelni, kiszolgálni kell.
A feladatok "ütemezéséhez" nem használok FreeRTOS-t, hanem állapotgépet. Az egyes állapotokat egy végtelen ciklusban elhelyezett függvény elemzi és azután intézkedik az éppen aktuális állapot szerint.
Ha már itt tartunk, a megjelenítéshez nálam tipikusan négy függvény tartozik, amelyek közül:
- az első függvény az adott képernyőkép megjelenítéséért felelős. A képernyőn általában vannak statikus (mindig egyformán látható, például főcím vagy ablakcím) és dinamikus (helyzettől függően látható és/vagy tulajdonságú, például gomb, szövegmező, stb.) komponensek. A megjelenítő függvény minden komponenst tartalmaz, ami csak az adott képernyőn előfordulhat. Az, hogy éppen mi látszik, az adott komponens struktúrájában egy visible nevű struktúra tag értéke határozza meg egy if feltételeként (FALSE vagy TRUE). A megjelenítő függvény neve mindig disp_xxx_yyy(), ahol a disp a megjelenítésre utal, a többi az egyéb feladatra. Például: disp_menu_main(), vagy disp_menu_treatments(), de ilyen lehet a disp_msg_error() függvény is;
- egy init_task_yyy() függvény (pl. init_task_treatment), amely többek között a feladat (taszk) változóinak, a hardvernek, stb. az inicializálását végzi el . Itt hívódik meg az yyy taszkhoz tartozó nyitó képernyő is, amelynek a neve a fenti disp_xxx_yyy (pl. disp_menu_treatment);
- egy run_task_yyy() függvény (pl. run_task_treatment), ami többek között az "eseményeket" (képernyő érintés, időzítés és számlálás eredménye, hardver állapot, stb.) kezeli, szükség szerint beállítja a megjelenítéshez tartozó komponensek állapotát, majd meghívja a hozzá tartozó disp_xxx_yyy() függvényt;
- végül egy done_task_yyy() függvény (pl. done_task_treatment), ami többek között befejezi az adott feladatot, szükség szerint módosítja a kijelzés paramétereit és végül megjeleníti a kilépő képernyőképet a disp_xxx_yyy() függvénnyel;
Egy interaktív érintőképernyős programban döntő szerep jut a képernyő érintések megfelelő kezelésének. A rezisztív érintőképernyő (FT800 chippel) mindössze egyetlen pont érintését képes helyesen kiértékelni, míg a kapacitív érintőképernyő (FT801 chippel) akár öt pontos érintést is.
A következő részben a rezisztív érintőképernyő kezelésről szeretnék írni, mert bizony itt futottam bele egy olyan fura jelenségbe, amit csak nehezen tudtam elhárítani, ez pedig a prel-szerű hatás...