Interfejs graficzny jest ważną częścią systemów z wbudowanym wyświetlaczem, które oprócz wyprowadzania tekstu mają również za zadanie rysowanie innych obiektów, poczynając od elementów ozdobnych takich jak ramki, a kończąc na prezentacji danych w postaci wykresów. Z drugiej strony istotną rolę odgrywa interfejs wejściowy dający użytkownikowi możliwość wpływania na stan systemu oraz na wyświetlaną zawartość ekranu. W przypadku niewielkich aplikacji realizacja oprogramowaniainterfejsów wejścia i wyjścia sprowadza się zwykle do kilkunastu procedur, które można przygotować samodzielnie bez większego kłopotu. Jednak, gdy potrzeba czegoś więcej na wzór interfejsów obecnych w klasycznych komputerach lub nowoczesnych telefonach to wartosięgnąć po gotowe i sprawdzonerozwiązania w postaci bibliotek – jedną z nich oferuje firma STMicroelectronics pod nazwą STemWin.

Wspomniana biblioteka powstała we współpracy z firmą Segger na bazie biblioteki emWin, charakteryzująca się bogatą listą możliwości, które są dość dobrze opisane w obszernej ponad tysiąc stronnej dokumentacji [2]. Darmowy pakiet STemWin jaki można pobrać na stronie [4] zawiera m.in. pliki obiektowe skompilowanej biblioteki (przeznaczone dla mikrokontrolerów STM32 z rdzeniem Cortex-M0, Cortex-M3 lub Cortex-M4 i środowisk wykorzystujących narzędzia GCC, IAR lub Keil) oraz pliki konfiguracyjne (do ustawienia parametrów użytego wyświetlacza jak również parametrów samej biblioteki). Ogólną organizację biblioteki przedstawia rysunek 1.

Rys. 1. Warstwowa organizacja biblioteki STemWin (podobnie jak dla emWin [2])

 

Widżety

Interfejs graficzny użytkownika to przede wszystkim różnego rodzaju kontrolki, nazywane w bibliotece STemWin widżetami, do których należą m.in. etykiety, przyciski, checkboksy, listy rozwijane, pola tekstowe i suwaki (rysunek 2, 3). Dodatkowo istnieje możliwość budowania aplikacji z ikonkam i(rysunek 4), jak również z obrazkami zapisanymi w formacie GIF, JPG lub PNG, a także z wykresami na podstawie przekazanej tablicy z danymi (rysunek 5). Tworzenie widżetów jest zadaniem dość prostym i sprowadza się do wywołania ujednoliconej procedury CreateEx() (tabela 1). Lista procedur API biblioteki jest na tyle bogata, że pozwala nie tylko na modyfikację wartości widżetów (tekst pola, etykieta przycisku, stan checkboksa, pozycja suwaka), ale również na zmianę ich wyglądu (warto przy tym wspomnieć, że istnieje jeszcze możliwość skonfigurowania wyglądu na poziomie kompilacji projektu, definiując odpowiednie stałe).

Rys. 2. Wybór koloru przy pomocy suwaka i pól tekstowych

Rys. 3. Podgląd zawartości katalogów w widoku drzewa

 

Rys. 4. Przyciski w formie ikonek

 

Rys. 5. Rejestracja przebiegów sygnałów

 

Tab. 1. Wybrane procedury biblioteki STemWin powiązane z widżetami

Procedura Opis
<WIDGET>_Handle

<WIDGET>_CreateEx(int     x0,      int y0,

intxSize,   intySize,

WM_HWIN hParent,

intWinFlags, intExFlags, int Id,

<pozostałe_parametry> . . . );

Procedura tworzy widżet<WIDGET> (np. BUTTON, FRAMEWIN, SLIDER, itp.) o wymiarach (xSize,ySize) i umieszcza go w pozycji (x0,y0) układu współrzędnych okna rodzica, wskazywanego przez parametr hParent, do jakiego zostanie on przyczepiony. Parametr WinFlags przyjmuje wartości wspólne dla okien i widżetów, a ExFlags – powiązane z konkretnym widżetem. Lista pozostałych parametrów zależy od widżetu. Procedura zwraca uchwyt do utworzonego widżetu, który może zostać wykorzystany do wszelkich manipulacji (przenoszenie, zmiana wyglądu, itd.).
void WM_MoveTo(WM_HWIN hWin, int x, int y); Przesuwa oknohWin do wskazanej pozycji(x,y) we współrzędnych pulpitu.
void WM_Paint(WM_HWIN hWin); Rysuje lub przerysowuje oknohWin natychmiast z chwilą wywołania.
void WM_SetSize(WM_HWIN hWin, intXSize, intYSize); Ustawia nowe wymiary oknahWin – odpowiednio:XSize x YSize.
void WM_Update(WM_HWIN hWin); Przerysowuje unieważnioną część oknahWin, które zostaje następnie zatwierdzone.

 

Jeśli z jakiegoś powodu dostępne formy widżetów (można ustawićwygląd klasyczny lub Flex) nie odpowiadają naszym wymaganiom, tzn. gdy oprócz zmiany standardowych kolorów i wymiarów charakterystycznych jak np. grubość ramki okna czy szerokość suwaka chcemy całkowicie zmienić wygląd komponentu (rysunek 6) to najprościej można to zrobić poprzez dodanie stosownych operacji rysowania w funkcji zwrotnej powiązanej z konkretną kopią widżetu.

 

Rys. 6. Przykład zdefiniowania niestandardowego wyglądu przycisku

 

Funkcja zwrotna (ang. callbackroutine) to taka funkcja, która jest wywoływana automatycznie po wystąpieniu zdarzenia powiązanego z widżetem (i nie tylko) dla którego została ona zdefiniowana. Przykładowo aplikacja z rysunku 6 zawiera cztery przyciski sterujące po naciśnięciu których przycisk z etykietą Button po prawej stronie będzie zmieniał kształt, czcionkę tekstu oraz kolor – to właśnie w funkcji zwrotnej są wywoływane procedury zmieniające dane parametry. Przykładowa struktura takiej funkcji wygląda jak poniżej – można zauważyć, że w zależności od zawartości powiadomienia typu WM_MESSAGE wykonywane są różne czynności.

Ogólnie do dyspozycji mamy 22 rodzaje widżetów, które w zupełności powinny wystarczyć do budowy standardowych aplikacji. Niemniej jednak nie jest to jakiekolwiek ograniczenie – biblioteka STemWin umożliwia tworzenie własnych widżetów i można wykorzystać do tego celu procedury rysujące prymitywy (podobnie jak w funkcjach zwrotnych). Wszystko to nie mogłoby poprawnie funkcjonować bez istnienia pewnego mechanizmu jakim jest menedżer okien, dzięki któremu można bez problemów wykonywać dowolne manipulacje nad obiektami widocznymi na wyświetlaczu (można również operować na tym co jest poza widocznym obszarem, gdyż biblioteka posiada funkcję wirtualnych wyświetlaczy) i który jest odpowiedzialny za prezentację tych obiektów w sposób naturalny – głównie chodzi o przesłanianie okien i widżetów, które są ułożone w przestrzeni trójwymiarowej, przy czym użytkownik widzi tylko dwa wymiary.

 

Funkcje graficzne

Prymitywy o jakich wspomniano powyżej są nieodłączną częścią biblioteki i można je stosować na równi z widżetami (tabelka 2). Oprócz standardowych procedur rysujących mamy również do wyboru takie, które korzystają z funkcji AntiAliasing (procedury z przedrostkiem GUI_AA_<Nazwa_Procedury>), która z kolei wygładza wszelkie nierówności krawędzi rysowanych elementów (rysunek 7). Istotnym jest także możliwość wyprowadzania tekstu i do tego celu w bibliotece zaimplementowano kilka procedur; jedne przyjmują wskaźnik do ciągu znaków, a inne – konkretne wartości zmiennych, które chcemy wyświetlić w różnych systemach (tabelka 3). Podobnie jak poprzednio biblioteka oferuje funkcję wygładzania czcionek.

 

Tab. 2. Wybrane procedurybiblioteki STemWin powiązane z grafiką 2D

Procedura Opis
GUI_AA_DrawArc() Rysuje wygładzony łuk o zadanym promieniu w zadanym zakresie kątów
GUI_AA_DrawLine() Rysuje wygładzoną linię o zadanych punktach początku i końca
GUI_AA_DrawPolyOutline() Rysuje wygładzony kontur wielokąta opisanego listą punktów
GUI_AA_DrawRoundedRect() Rysuje kontur prostokąta z wygładzonymi zaokrągleniami
GUI_AA_FillCircle() Rysuje wypełnione koło z wygładzonymi krawędziami
GUI_AA_FillPolygon() Rysuje wypełniony wielokąt z wygładzonymi krawędziami
GUI_AA_FillRoundedRect() Rysuje wypełniony prostokąt z wygładzonymi zaokrągleniami
GUI_AA_SetFactor() Ustawia wartość współczynnika funkcji AntiAliasing (od 1 do 6)
GUI_ClearRect() Wypełnia wskazany obszar kolorem tła
GUI_CopyRect() Kopiuje wskazany obszar ekranu
GUI_DrawArc() Rysuje łuk
GUI_DrawBitmap() Rysuje mapę bitową
GUI_DrawCircle() Rysuje kontur koła
GUI_DrawEllipse() Rysuje kontur elipsy
GUI_DrawGraph() Rysuje wykres
GUI_DrawLine() Rysuje linię wyznaczoną przez dwa punkty
GUI_DrawPoint() Rysuje punkt
GUI_DrawPolygon() Rysuje kontur wielokąta
GUI_DrawPolyLine() Rysuje polilinię
GUI_DrawRect() Rysuje kontur prostokąta
GUI_EnableAlpha() Włącza/wyłącza kanał alpha
GUI_FillCircle() Rysuje wypełnione koło
GUI_FillEllipse() Rysuje wypełnioną elipsę
GUI_FillPolygon() Rysuje wypełniony wielokąt
GUI_FillRect() Rysuje wypełniony prostokąt
GUI_InvertRect() Inwertuje kolory wskazanego obszaru ekranu
GUI_RestoreContext() Przywraca kontekst GUI
GUI_RotatePolygon() Obraca wielokąt o zadany kąt
GUI_SaveContext() Zapisuje kontekst GUI
GUI_SetAlpha() Ustawia wartość kanału alpha
GUI_SetDrawMode() Ustawia tryb rysowania (tryb normalny, tryb XOR)
GUI_SetLineStyle() Ustawia styl linii
GUI_SetPenSize() Ustawia rozmiar pióra rysującego w pikselach

 

Kreator GUI oraz symulacja projektu

Pakiet z biblioteką STemWin zawiera narzędzia ułatwiające projektowanie interfejsu graficznego. Pierwsze z nich to GUIBuilder, które pozwala w prosty sposób tworzyć okienka i układać widżety z możliwością ustawiania wymiarów oraz definiowania ich zawartości – do pewnego stopnia (rysunek 9). Narzędzie to przechowuje ustawienia zaprojektowanych okienek w postaci pliku źródłowego z rozszerzeniem .c, a więc w pliku nadającym się do bezpośredniego podłączenia do projektu.Pozostałe narzędzia pozwalają na konwersje obrazków (narzędzie BmpCvt) oraz czcionek (narzędzie FontCvt) do plików z rozszerzeniem .c, w których dane są zapisane w tablicach.

 

Rys. 8. Projektowanie interfejsu graficznego z wykorzystaniem narzędziaGUIBuilder

 

W większości przypadków,gdy chcemy sprawdzić wygląd i działanie zaprojektowanej aplikacji graficznej, nie ma potrzeby za każdym razem programować układu. Wystarczy skompilować i uruchomić projekt w środowisku MS Visual C++, który jest dostępny w pakiecie z biblioteką emWin (STemWin niestety nie posiada takiego). Dzięki tej metodzie znacząco zaoszczędzimy czas oraz cykle zapisu pamięci Flash układu.

 

Pozostałe możliwości

Oprócz powyższych możliwości biblioteka pozwala także na wyświetlanie duszków – obrazki statyczne, bądź zmieniające się cyklicznie (rysunek 8, tabela 4) oraz kursorów (jeśli wykorzystujemy np. joystick lub myszkę). Te elementy graficzne są o tyle ciekawe, gdyż mogą być umieszczone w dowolnym miejscu i o dowolnym kształcie bez utraty tego co znajduje się „za” nimi – przy wyświetlaniu duszka/kursora tło przez niego zakrywane zapisywane jest w pamięci układu, a przy przemieszczaniu lub ukrywaniu dane w postaci wartości pikseli są odczytywane i ponownie przerysowywane.

Dostępna funkcja wielowarstwowości pozwala nie tylko organizować obiekty w grupy, ale także umożliwia realizację przenikania warstw (rysunek 10, 11). Przykładową syntezę dwóch warstw przedstawia rysunek 12, a za pomocą odpowiednich funkcji do ustawiania wartości kanału alpha można uzyskiwać łagodne przejścia między zawartością poszczególnych warstw.

Ciekawą jeszcze funkcjonalnością jaką udostępnia biblioteka jest możliwość zdalnego podglądu zawartości wyświetlacza orazsterowania pracą urządzenia na którym jest włączony serwer VNC. Przykładowo, jeżeli urządzenie z włączoną funkcją serwera VNC jest podłączone do typowej sieci komputerowej z obsługą protokołu TCP/IP (bezpośrednie podłączenie do komputera lub do routera) to na dowolnym komputerze w tej sieci po uruchomieniu klienta VNC i połączeniu się z urządzeniem docelowym można zdalnie pracować z jego interfejsem graficznym tak jakby to wyglądało fizycznie z wykorzystaniem ekranu i urządzeń wejścia.

Rys. 9. Przykład z dwoma duszkami

 

Tab. 4. Wybrane procedury biblioteki STemWin powiązane z duszkami (ang. sprites)

Procedura Opis
GUI_SPRITE_CreateEx() Procedura tworzy duszka, który jest opisany bitmapą do której przekazuje się wskaźnik jako argument. Duszek zostanie umieszczony w zadanej pozycji (x,y) w wybranej warstwie.
GUI_SPRITE_CreateExAnim() Procedura tworzy animowanego duszka na podstawie serii obrazków statycznych, przy czym czasy ich przełączania mogą być takie same (przekazanie wartości czasu w argumencie funkcji) lub różne (przekazanie wskaźnika do tablicy wartości czasów).
GUI_SPRITE_Hide() Ukrywa duszka.
GUI_SPRITE_SetLoop() Włącza lub wyłącza nieskończoną animację duszka.
GUI_SPRITE_Show() Pokazuje duszka.
GUI_SPRITE_StartAnim() Kontynuuje animowanie duszka.
GUI_SPRITE_StopAnim() Zatrzymuje animowanie duszka.

Rys. 10. Funkcja wielowarstwowości umożliwiająca realizację przezroczystości części obszaru

Rys. 11.  Hierarchia okien w poszczególnych warstwach

Rys. 12. Przykład syntezy dwóch różnych warstw z wykorzystaniem przezroczystości

 

Warstwa sprzętowa

Biblioteka STemWin obsługuje większość popularnych wyświetlaczy graficznych wyposażonych w różne kontrolery i wynika to nie tylko z dostępności sterowników konkretnych urządzeń, ale także z pewnej uniwersalności istniejących interfejsów komunikacyjnych za pomocą których można uzyskać bezpośredni lub pośredni dostęp do pamięci graficznej urządzenia. W przypadku, gdy występuje bezpośredni dostęp do pamięci graficznej komunikacja między mikrokontrolerem, a kontrolerem wyświetlacza odbywa się poprzez szynę adresową, szynę danych i linie sterujące (rysunek 13). Warto tutaj wspomnieć, że bardziej rozbudowane mikrokontrolery z serii STM32 posiadają moduł FSMC (FlexibleStatic Memory Controller) lub jego rozszerzonyodpowiednikFMC (Flexible Memory Controller) dedykowany do komunikacji z zewnętrzną pamięcią, a szczególnie z pamięcią graficzną wyświetlaczy.

Rys. 13. Typowy interfejs przy bezpośrednim dostępie do pamięci graficznej wyświetlacza

 

Natomiast w sytuacji, gdy dostęp do pamięci graficznej odbywa się pośrednio to komunikacja może się odbywać z wykorzystaniem jednego z poniższych interfejsów:

  • interfejs równoległy (typu 6800 lub 8080),
  • 4-liniowy interfejs SPI,
  • 3-liniowy interfejs SPI,
  • interfejs magistrali I2C.

Przykłady sterowników tego typu połączeń komunikacyjnychmożna znaleźć w katalogu Samples/LCD_Xpakietu emWin: LCD_X_6800.c, LCD_X_8080.c, LCD_X_SERIAL.c, LCD_X_Serial_3Pin.c, LCD_X_Serial_3Wire.c oraz LCD_X_I2CBUS.c, a w tabeli 5 zestawiono listę kontrolerów obsługiwanych przez pakiet STemWin. W plikach sterowników można znaleźć różne opcje konfiguracyjne, m.in. do ustawiania wymiarów w dwóch osiach obszaru roboczego wyświetlacza oraz do zmiany orientacji wyświetlanej zawartości.

 

Tab. 5. Lista obsługiwanych przez bibliotekę kontrolerów wyświetlaczy graficznych [1]

Epson S1D19122
FocalTech FT1509
Himax HX8301, HX8340, HX8347, HX8352, HX8353, HX8325A
Hitachi HD66772
Ilitek ILI9220, ILI9221, ILI9320, ILI9325, ILI9328, ILI9335,
ILI9338, ILI9340, ILI9341, ILI9342, ILI9481
LG Electronics LGDP4531, LGDP4551
Novatek NT39122
OriseTech SPFD5408, SPFD54124C, SPFD5414D
Renesas R61505, R61516, R61526, R61580
Samsung S6D0117, S6E63D6
Sitronix ST7628, ST7637, ST7687, ST7712, ST7735
Solomon SSD1355, SSD1961, SSD1963, SSD2119
Syncoam SEPS525
Pozostałe kontrolery z liniową adresacją pamięci graficznej i bezpośrednim dostępem

 

Dodatkowo biblioteka zawiera sterowniki urządzeń wskazujących (Pointer Input Devices) do których należą: panel dotykowy, myszka i joystick, a także sterowniki klawiatury. Domyślnie pakiet STemWin obsługuje panele dotykowe zarówno w trybie analogowym jak i cyfrowym, przy czym oprogramowanie jest zdolne do rozpoznawania tylko pojedynczych dotknięć – oprogramowanie z opcją MultiTouch(dotyczy paneli typu pojemnościowego) jest dostępne jako oddzielny pakiet dopełniający.

 

Wymagania sprzętowe

System wbudowany, w jakim ma zostać zaimplementowana bibliotekaSTemWin, powinien spełniać podstawowe wymagania [2]:

  • posiadać 8/16/32/64-bitowąjednostkę przetwarzającą (wszystkie mikrokontrolery producenta ST z rdzeniem Cortex M0, M3 oraz M4 posiadają 32-bitową jednostkę CPU),
  • udostępniać niezbędne minimum ilość pamięci do wykorzystania przez bibliotekę (tabelka 6) z możliwością pracy w trybie 8-, 16- i 32-bitowym; zapotrzebowanie pamięci ROM wzrasta wraz z implementacją czcionek oraz plików graficznych,
  • zawierać wyświetlacz graficzny dowolnego typu (monochromatyczny, kolorowy) i rozdzielczości – ważne jest aby był dostępny odpowiedni sterownik.

Określenie dokładnej wartości ilości pamięci wymaganej przez bibliotekę nie jest możliwe w prosty sposób. Należy tutaj uwzględnić także fakt, że zależy ona również od tego jakie elementy biblioteki będą wykorzystywane oraz od stopnia optymalizacji kodu przez kompilator. W systemach z niewielką ilością pamięci RAM można zaimplementować bibliotekę bez włączonego menedżera okien, przy czym wtedy nie będzie możliwym uzyskanie pełnowartościowego interfejsu graficznego m.in. z funkcją automatycznego przerysowywania modyfikowanych okienek, czy zarządzania ich ułożeniem w hierarchii oraz wysyłania sygnałów od zdarzeń i wywoływania funkcji zwrotnych.

Tab. 6. Przybliżone wymagania pamięciowe biblioteki STemWin w zależności od wykorzystanych opcji [2]

Zasoby Systemy z ograniczoną ilością zasobów
(brak menedżera okien)
Systemy z dużą ilością zasobów
(z menedżerem okien i widżetami)
Pamięć RAM 100 B 2 – 6 kB
Pamięć ROM 10 – 25 kB 30 – 60 kB
Stos 600 B 1200 – 1800 B

 

Dodatkowo, wymagania pamięciowe wzrastają w przypadku implementacji systemu operacyjnego czasu rzeczywistego – warto o tym wspomnieć, gdyż interfejs graficzny zaprojektowany z wykorzystaniem bibliotekiSTemWin może działać jako jedno z zadań w systemie, przy czym taka struktura oprogramowania znacząco upraszcza implementację obsługi innych procesów (np. odczyt wartości z czujników). Aby biblioteka graficzna mogła współpracować wraz z systemem czasu rzeczywistego należy zmodyfikować wartość makrodefinicji GUI_OS poprzez ustawienie jej na 1 (można również ustawić maksymalną liczbę zadań do wykorzystania przez bibliotekę – do tego celu służy makrodefinicja GUI_MAXTASK). W przypadku, gdy włączona jest funkcja serwera VNC zużycie pamięci ROM wzrasta od 3,5 kBdo 5 kB. Dodatkowe informacjedotyczące wymaganej pamięci można znaleźć w dokumencie [1].

Jan Szemiet

 

Literatura

[1] AN4323: Gettingstarted with STemWin Library

[2] UM03001: emWin, Graphic Library with Graphical User Interface, User & Reference Guide

[3] http://www.segger.com/emwin.html – oficjalna strona biblioteki emWin

[4]http://www.st.com/web/en/catalog/tools/PF259225 – oficjalna strona biblioteki STemWin