TouchGFX to framework do tworzenia graficznych interfejsów użytkownika (GUI) udostępniony przez firmę STMicroelectronics, zaprojektowany z myślą o rozwoju systemów opartych na mikrokontrolerach STM32 (MCU). Umożliwia projektowanie wyświetlaczy kontekstowych obiektów, wspierając użytkowników STM MCU w tworzeniu płynnych, atrakcyjnych i zróżnicowanych stron interfejsu użytkownika.
Poniższy przykład odnosi się do wersji TouchGFX 4.23.2:

Rysunek 1: Ekran startowy TouchGFX pokazujący opcje, takie jak Example, Demo, Create Board chip itd.
Przegląd struktury TouchGFX
Architektura programu TouchGFX opiera się na wzorcu Model-View-Presenter (MVP), jak pokazano na rysunku 2, oferując następujące zalety:
Rozdzielenie odpowiedzialności (Separation of Concerns): Utrzymanie kodu różni się w zależności od etapu, co ułatwia użytkownikom pisanie interfejsów i komunikację z niższymi warstwami, zapewniając przejrzystą i zrozumiałą strukturę oraz wysoką możliwość ponownego użycia.
Testowanie jednostkowe (Unit Testing): Górna warstwa View może bezpośrednio współpracować z kodem wygenerowanym przez GFX, co ułatwia niezależną weryfikację wyników.

Rysunek 2: Schemat zależności komponentów TouchGFX (MVP)
View: Główna strona wyświetlacza generowana przez GFX, przeznaczona do prezentacji interfejsu. Zazwyczaj działa jako pasywny element górnej warstwy MVP, obsługuje wszystkie informacje projektowe interfejsu użytkownika i wyświetla odpowiednie ekrany w oparciu o właściwości używanych obiektów.
Model: Działa jako centralne miejsce przetwarzania i przesyłania danych. Niektóre pakiety komunikacyjne są analizowane lub przetwarzane, a następnie przekazywane przez Presenter do View w celu zmiany wyświetlanych treści i stanu obiektów.
Presenter: Działa jako kanał komunikacyjny między View a Modelem, umożliwiając żądania danych z Modelu i ponowne wykorzystanie funkcji.
Ze względu na filozofię projektowania FW (Firmware), która kładzie nacisk na Model jako centrum przetwarzania poleceń, można zilustrować schemat (rysunek 3).
Poprzez przetwarzanie niskopoziomowe dla różnych interfejsów (np. CAN bus, RS485, UART, Bluetooth, Wi-Fi), dane są przekazywane do Modelu, a następnie przez Presenter do View, umożliwiając przełączanie stanu obiektów.

Rysunek 3: Komunikacja między wieloma interfejsami a architekturą MVP
Dwa przykłady mogą zilustrować sposób wymiany danych:
Przykład 1: Załóżmy, że Host wysyła polecenie CANopen do urządzenia (rysunek 4).
CANopen odbiera pakiety przez port IF, następnie dane pakietu są ewentualnie dekodowane przez zadanie CAN, a treść jest przekazywana do Modelu. Po zaktualizowaniu bazy danych i wykonaniu odpowiedniego polecenia, Model przekazuje wynik do View przez Presenter w celu odświeżenia strony.

Rysunek 4: Przykład wysłania polecenia przez Host
Przykład 2: Jeśli użytkownik dotknie obiektu interfejsu użytkownika na urządzeniu, pakiet zdarzenia dotykowego zostaje odesłany do Host (rysunek 5).
Kiedy użytkownik kliknie interaktywny obiekt, View generuje zdarzenie kliknięcia, które jest następnie przekazywane do Modelu za pomocą zdarzenia użytkownika (User Event) przez Presenter. Model odpowiada w zależności od aktualnie używanego interfejsu, przesyłając kod z powrotem do zadania CAN, a ostatecznie wysyła pakiet TX, aby powiadomić Host.

Rysunek 5: Zdarzenie dotykowe użytkownika odesłane do Host
Przegląd wiedzy o stronie View
W interfejsie oprogramowania TouchGFX projektowanie N stron spowoduje wygenerowanie N odpowiadających im zestawów View i Presenter, ale tylko jeden Model będzie kontrolował wszystkie strony View.
Kiedy użytkownik projektuje scenariusz UI, obejmujący grafikę, wygląd, współrzędne i wyświetlanie tekstu, naciśnięcie przycisku „Generate Code” wygeneruje kod w odpowiedniej nazwanej stronie View.
Wygenerowane foldery są podzielone na ..\generated\ oraz ..\gui\, gdzie ..\generated\ zawiera podstawowy kod do wyświetlania zaprojektowanej strony, a ..\gui\ zawiera logikę interakcji obiektów.
Mamy możliwość wykorzystania tych informacji, aby przeciągać obiekty na odpowiednie strony i odwoływać się do dostępnego kodu.
Oto proste wyjaśnienie krok po kroku powyższego opisu:
Na przykład:
1. Otwórz pusty projekt i naciśnij „Create New”, aby założyć nowy projekt (Rysunek 6).

Rysunek 6: Ekran otwierania projektu w TouchGFX
2. W TouchGFX dostępny będzie domyślnie Screen1. Dodajemy nowy obiekt przycisku, wybieramy żądany obraz i wykonujemy „Generate Code” (Rysunek 7).

Rysunek 7: Demonstracja tworzenia przycisku
3. Następnie przechodząc do katalogu projektu zobaczymy dwa nowe foldery: gui oraz generated (Rysunek 8):

Rysunek 8: Zawartość folderu projektu
Folder generated zawiera podstawowy kod związany z komponentami Screen1, który jest generowany automatycznie przez TouchGFX i nie można go bezpośrednio modyfikować. Jeśli stan obiektu na stronie się zmieni i kod zostanie wygenerowany ponownie, kod w folderze generated zostanie zaktualizowany.
Podobnie po wykonaniu „Generate Code” GFX utworzy plik Screen1ViewBase.cpp w ..\generated\gui_generated\src\screen1_screen (Rysunek 9).

Rysunek 9: Lokalizacja pliku Screen1ViewBase.cpp
Jeśli otworzymy Screen1ViewBase.cpp w edytorze (np. Notepad++) (Rysunek 10), możemy zobaczyć właściwości i treść powiązaną ze stroną Screen1 i danymi przycisku:
- Ustawianie współrzędnych przycisku:
button1.setXY(63, 109);
- Ustawianie identyfikatora obrazu przycisku:
button1.setBitmaps(TouchGfx::Bitmap(BITMAP_BUTTON_00_00_ID), TouchGfx::Bitmap(BITMAP_BUTTON_00_00_ID));
- Dodanie obiektu przycisku do strony:
Add(button1);

Rysunek 10: Zawartość pliku Screen1ViewBase.cpp
Kod o nazwie XXXBase.cpp zostanie ponownie zbudowany podczas „Generate Code”, a wszelkie zmiany w danych atrybutów zostaną odzwierciedlone. Dlatego jeśli zmienimy pozycję przycisku, obraz itp., odpowiednie funkcje również ulegną zmianie.
Jeśli chodzi o folder gui, to tam TouchGFX umożliwia użytkownikom pisanie logiki programu (Rysunek 8). W związku z tym architektura MVP jest również tworzona tutaj (Rysunki 11 i 12), co pozwala nam zaplanować własne metody komunikacji MVP w celu realizacji projektowanych interfejsów UI.

Rysunek 11: Ścieżka Modelu

Rysunek 12: Ścieżki Presenter i View
4. Tworzenie prostego scenariusza na potrzeby wyjaśnienia działania GUI i wygenerowanego kodu
- Napisz logikę sterującą interakcją między przyciskiem a tekstem.
- Po jednokrotnym kliknięciu przycisku wartość tekstu się zwiększy.
Oto, jak zaimplementować tę funkcję:
Krok 1:
Przeciągnij dwa obiekty: przycisk (button1) i pole tekstowe (textArea1) (Rysunek 13).

Rysunek 13: Projekt UI z kontrolką przycisk
Krok 2:
Wybierz akcję interakcji po prawej stronie, dodaj zdarzenie kliknięcia Button, i wybierz wywołanie funkcji add_number po wykonaniu tej akcji (Rysunek 14).

Rysunek 14: Dodawanie zdarzenia Interaction1
Krok 3:
Sprawdź plik Screen1ViewBase.cpp (Rysunek 15), aby znaleźć odpowiedni kod właściwości tworzący button1 i textArea1.
Dzięki dodanym interakcjom wygenerowany zostanie buttonCallbackHandler, aby obsłużyć zdarzenie dotyku button1. Po kliknięciu wywoła funkcję add_number za pomocą callbacka.

Rysunek 15: Screen1ViewBase.cpp
Zawartość pliku Screen1ViewBase.hpp (Rysunek 16).

Rysunek 16: Zawartość Screen1ViewBase.hpp
Krok 4:
W sekcji gui dodaj pliki Screen1View.cpp i Screen1View.hpp.
Dodaj procedurę add_number, wykorzystując parametr count do akumulacji (Rysunki 17 i 18).
Użyj Unicode: snprintf(textArea1Buffer, TEXTAREA1_SIZE, "%02d", count); aby odświeżyć wartość count w textArea1.
Następnie użyj textArea1.invalidate(), aby odświeżyć dane.

Rysunek 17: Zawartość Screen1View.cpp

Rysunek 18: Zawartość Screen1View.hpp
Po uruchomieniu symulatora można potwierdzić, że za każdym razem, gdy dotkniemy button1, textArea1 (wartość count) zacznie się zwiększać od 0 (Rysunek 19).

Rysunek 19: Wynik działania w symulatorze
Potwierdza to, że definicje właściwości obiektów są zazwyczaj ustalane w wygenerowanej ścieżce, podczas gdy użytkownik pisze logikę wykonawczą w sekcji gui.
Przykłady właściwości obiektów TouchGFX i Buildera
Smart Display GUI Builder dostarczony przez Winstar to narzędzie do projektowania interfejsów UI/UX z funkcją przeciągnij i upuść, które oferuje klientom usługę rozwoju bez kodowania, dostosowaną do szybkiego rozwoju i projektowania produktów opartych na STM MCU. Zbudowane jako rozszerzenie frameworku TouchGFX, GUI Builder integruje oryginalne funkcjonalności widgetów TouchGFX, a jego główną różnicą jest wsparcie dla wielu interfejsów systemowych i protokołów komunikacyjnych. Dzięki temu użytkownicy mogą bezpośrednio obserwować, jak polecenia wpływają na kontrolę widgetów i zmiany.
Oto wprowadzenie do Buildera:
https://www.winstar.com.tw/pl/video/play/142.html
Filozofia projektowania Smartdisplay jest związana z funkcjonalnością ustawień TouchGFX, w tym oprogramowaniem układowym napisanym przy użyciu STM32 MCU jako podstawy MVP. Obiekty wewnętrzne są projektowane przy użyciu istniejących elementów połączonych z logiką.
W związku z tym, wśród obiektów udostępnionych przez GUI Builder, niektóre elementy mogą być implementowane przy użyciu istniejących komponentów UI TouchGFX, aby uzyskać odpowiednie wyniki wyświetlania.
*Segment wyjaśniający
Oto prosty przykład z użyciem suwaka Buildera (Rysunek 20):

Rysunek 20: Strona właściwości suwaka Buildera
Właściwości suwaka Buildera są następujące:
Size:
- Width: 618
- Height: 20
Positions:
- Background Position (X): 0
- Background Position (Y): 4
Indicator Position:
- Min: 0
- Max: 580
- Pos: 0
Parametry te odpowiadają ustawieniom komponentu Slider w TouchGFX (Rysunek 21).

Rysunek 21: Właściwości suwaka TouchGFX
Właściwości suwaka TouchGFX są następujące:
Location:
- Width: 618
- Height: 20
Positions:
- Background Position (X): 0
- Background Position (Y): 4
Indicator Position:
- Min: 0
- Max: 580
- Y: 0
Użytkownicy mogą dostosować wartość Start w GFX, aby zasymulować wyniki w Builderze (Rysunek 22).
Jeśli wartość zostanie ustawiona na 100, można uzyskać ten sam efekt w Builderze (Rysunek 23).

Rysunek 22: Ustawienie Start = 100 w TouchGFX

Rysunek 23: Ustawienie wartości testowej = 100 w Builderze
Jeśli spojrzymy na plik Screen1ViewBase.cpp wygenerowany przez GFX (Rysunek 24):

Rysunek 24: Funkcja w Screen1ViewBase.cpp
Możemy zrozumieć, jak parametry te mogą być używane i modyfikowane w kodzie. Takie wartości liczbowe mają bezpośredni związek z projektem GFX. Gdy Builder przesyła projekt, resetuje on początkowe parametry suwaka urządzenia.
Jeśli Host wyśle polecenie zmiany wartości suwaka, zostanie wykonana funkcja slider1.setValue() w view, aby zakończyć zmianę obiektu (Rysunek 25).

Rysunek 25: Host wysyła polecenie zmiany suwaka
To proste wyjaśnienie relacji między obiektami Buildera i TouchGFX.
Przyszłe rozszerzenia i ocena rozwoju obiektów Buildera
Dzięki najnowszej aktualizacji TouchGFX do wersji 4.24.0 dostępne są nowe obiekty i funkcje. Jeśli chcemy ocenić, czy można je zintegrować z Builderem, możemy najpierw wypróbować domyślne przykłady z GFX do celów demonstracyjnych i badawczych (Rysunek 26):

Rysunek 26: Różne przykładowe projekty
Od wersji 4.24.0 wspierane są nowe obiekty, takie jak kod QR. Możemy więc ocenić, jakie parametry i funkcje można wykorzystać, jeśli zostaną zintegrowane z Builderem.
Przykład z użyciem kodu QR:
1. Wybierz BlankUI.
2. Przeciągnij kontener kodu QR.
3. Obserwuj dostępne właściwości konfiguracyjne (Rysunek 27):
Location: (X, Y)
Configuration:
- QRVersion
- Scale
- Text
- Error Correction Code…

Rysunek 27: Ekran właściwości kodu QR
Parametry te można porównać z oficjalną dokumentacją (Rysunek 28).

Rysunek 28: Wyjaśnienie ze strony oficjalnej
W wygenerowanej funkcji Screen1ViewBase.cpp można potwierdzić dostępne parametry i ustawienia (Rysunek 29):
1. Ustawienie współrzędnych: qrCode1.setXY(208, 224);
2. Ustawienie wersji kodu QR: qrCode1.setQRCodeVersion(3);
3. Ustawienie skali kodu QR: qrCode1.setScale(5);
4. Wprowadzenie tekstu do wygenerowania kodu QR:
qrCode1.convertStringToQRCode("https://www.winstar.com.tw/zh-tw/");

Rysunek 29: Wygenerowany kod w Screen1ViewBase.cpp
Jeśli w przyszłości funkcja kodu QR zostanie zintegrowana z Builderem, użytkownicy będą mogli ustawiać te parametry ręcznie.
Referencje:
https://support.touchgfx.com/docs/category/introduction
https://www.eettaiwan.com/20200203np21/
https://en.wikipedia.org/wiki/STMicroelectronics
https://www.winstar.com.tw/pl/video/smartdisplay.html