Implementacja obsługi wyświetlacza LCD Spis treści

Transkrypt

Implementacja obsługi wyświetlacza LCD Spis treści
Zespół: CZ/N/15
Wrocław, dn. 29 stycznia 2009
Karol Wrótniak, 156566
Ocena:
Marcin Załuski, 156571
Oddano:
Implementacja obsługi wyświetlacza LCD
sprawozdanie z projektu przedmiotu „Architektura Komputerów”
Rok akad. 2008/2009, kierunek: INF, specjalność: -
PROWADZĄCY:
dr inż. Piotr Patronik
Spis treści
1 Cel projektu
3
2 Realizacja sprzętowa
3
3 Protokół transmisyjny
5
4 Obsługa portu LPT
7
5 Narzędzia pomocnicze
7
6 Funkcje podstawowe
8
6.1
Funkcja setb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
6.2
Funkcja clrb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
6.3
Funkcja writeB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
6.4
Funkcja clear . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
6.5
Funkcja setPerm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
6.6
Funkcja init . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
6.7
Funkcja off . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
6.8
Funkcja normColors
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
6.9
Funkcja invColors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
6.10 Funkcja putStr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
6.11 Funkcja setXY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
7 Obsługa grafiki oraz animacji
12
7.1
Funkcja anim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
7.2
Funkcja readGif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
7.3
Funkcja playMovie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
7.4
Funkcja getImage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
7.5
Funkcja getFrameDuration . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
7.6
Funkcja displayImage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
8 Interfejs użytkownika
14
9 Podsumowanie i wnioski
15
Bibliografia
16
2
1
Cel projektu
Celem tego projektu było zaimplementowanie sterowania i obsługi z poziomu komputera
PC wyświetlacza LCD telefonu Nokia 3310. Jest to ekran monochromatyczny o wielkości 84x48 pikseli. Sprzęt ten został wybrany ze względu na nieskomplikowany protokół
transmisyjny, a także łatwość realizacji części sprzętowej oraz niską cenę elementów niezbędnych do jego działania. Połączenie z komputerem PC odbywa się przy pomocy portu
równoległego LPT. Obsługa LCD obejmuje wyświetlanie liter alfabetu łacińskiego oraz
wyświetlanie obrazków w tym prostych animacji. Kod źródłowy napisany jest w języku
asemblera, w składni AT&T i przeznaczony dla systemu Linux x86/x86 64.
2
Realizacja sprzętowa
Głównym elementem układu jest wyświetlacz LCD wyposażony w kontroler Philips
PCD8544 (szczegółowa specyfikacja dostępna w [1]). Tego typu ekrany występujące w
popularnych Nokiach 3310 (także 3210 i podobnych) obudowane są metalową maskownicą,
która zabezpiecza LCD przed uszkodzeniami i zwiększa jego trwałość. Odmiana występująca w większości modeli 3310 ma jeszcze jedną zaletę – metalowe styki kontaktowe umożliwiające bezpośrednie przylutowanie kabli i taki właśnie wyświetlacz zastosowaliśmy. Na
rynku dostępna jest też wersja z gumką przewodzącą, która wymaga użycia odpowiedniej
płytki drukowanej w celu podłączenia. Przystosowanie go do podłączenia do portu LPT
wymaga skonstruowania układu składającego elementów pasywnych, który ma za zadanie
zapewnienie odpowiednich parametrów prądowo-napięciowych oraz stabilności działania.
Nasz układ zbudowaliśmy w oparciu o schemat z [2] wprowadzając pewne modyfikacje.
Wyświetlacz wymaga napięcia w zakresie od 2,7V do 3,3V, a więc nie powinien być
podłączony bezpośrednio do portu równoległego, na którego liniach w zależności od płyty
głównej może występować napięcie aż do 5V. Żeby uzyskać pożądany poziom sygnału
użyte zostały diody Zenera 3V3 dla każdej z linii (zasilania i sterowania). Dzięki temu
napięcie między liniami LCD, a masą nie powinno przekroczyć 3,3V. W celu zabezpieczenia
3
portu przed przeciążeniem należy ograniczyć maksymalne natężenie prądu płynące przez
linie danych portu. Zadanie to realizują rezystory włączone szeregowo w linie portu. W
układzie występują, też kondensatory elektrolityczne między masą i liniami zasilającymi.
Ich zadaniem jest stabilizacja napięć, a co za tym idzie, wyświetlanego na LCD obrazu.
O ile w przypadku diod Zenera, sprawa doboru ich parametrów jest oczywista, to
dla rezystorów stanowi większy problem. Na początku zlutowaliśmy układ w oparciu o
rezystory wartości 1,2 kΩ (wg przyjętego wcześniej schematu), jednak napięcie na wyjściu
(ok. 2,4V) okazało się wtedy zbyt niskie dla prawidłowej pracy LCD i wyświetlana była
tylko jedna linia. W związku z tym zmniejszyliśmy opory rezystorów do 330Ω (tak jak w
schemacie na [3]). Po tej operacji napięcie na wyjściu mieściło się w normie i wyświetlacz
zaczął działać prawidłowo. Pojemności kondensatorów okazały się dobrane poprawnie,
dzięki czemu obraz był stabilny. Ostateczny schemat naszego układu przedstawia rys. 1.
1
14
330Ω
D0
SCK
D1
SDIN
D2
RES
D3
SCE
D4
D/C
D5
VDD
LPT
VOUT
1μF
3V3
GND
GND
13
LCD
2,2μF
25
Rysunek 1: Schemat układu służącego do podłączenia wyświetlacza z komputerem
4
Kolejnym, z pozoru błahym problemem, było wykonanie połączenia między wtyczką
a wyświetlaczem. Początkowo użyliśmy żyłek ze skrętki telefonicznej, jednak okazały się
one zbyt sztywne i powodowały zrywanie lutów nawet przy delikatnych ruchach. Zdecydowaliśmy się więc na użycie kawałka kabla (taśmy) od napędu dyskietek, ponieważ jest on
elastyczny, więc nie powodował takich problemów jak poprzednie rozwiązanie. Kabel od
FDD wygląda też bardziej estetycznie. Jak się jednak okazało, przy lutowaniu od strony
LCD trzeba było zwracać szczególną uwagę, aby taśma i wyświetlacz były ustawione idealnie w osi. Niewielkie odchylenie przy rozpoczęciu lutowania od pinów z jednej strony
w kierunku drugiej powodowało, że ostatnie żyły znajdowały się już zbyt daleko od styków. Rozwiązaniem było przylutowanie najpierw skrajnych pinów – co prawda pogarsza
to dostęp do tych znajdujących się w środku, ale ostatecznie zastosowaliśmy ten sposób.
Końcówki wszystkich elementów zostały przylutowane bezpośrednio do wtyczki LPT. Odwrotne ich umiejscowienie było by kłopotliwe ze względu na małe odległości między pinami
wyprowadzonymi z LCD i większą podatność na uszkodzenia. Miejsce styków zostało owinięte taśmą izolacyjną, co zabezpieczyło styki przed zwarciami jak i przed zerwaniem lutów.
Wygląd kompletnego układu wraz z wyświetlaczem przedstawia rys. 2.
Rysunek 2: Wyświetlacz gotowy do podłączenia
5
3
Protokół transmisyjny
Chociaż wyświetlacz podłączany jest przez port równoległy i wykorzystuje kilka linii,
to transmisja danych odbywa się w rzeczywistości w sposób szeregowy, synchroniczny po
jednej linii. Po tej samej linii przesyłane są komendy. Na zewnątrz LCD wyprowadzone
są następujące połączenia:
• SCK – sygnał zegarowy (synchronizacji)
• VOUT – stabilizacja napięć wewnętrznych
• GND – masa
• SDIN – słowa danych/komend
• RES – sygnał resetujący
• SCE – sygnał aktywacji (określa czy sygnały na SCK i SDIN są ważne)
• D/C – wybór danych/komend (określa czy wysyłamy dane czy komendę)
• VDD - zasilanie
Sterowanie wyświetlaczem polega na podawaniu kolejnych bitów przez linię SDIN w takt
sygnału zegarowego przesyłanego przez SCK (odczyt stanu ma miejsce przy rosnącym
zboczu), jeśli na SCE jest stan niski (w przeciwnym razie sygnały zegarowe są ignorowane).
Bity zgrupowane są w bajty, które mogą oznaczać dane (kolejne bity określają stan pikseli,
ustawiony bit oznacza zapalony piksel) lub polecenia (np. przesuwanie kursora), jeśli
na na linii D/C panuje wtedy stan wysoki, to przebieg jest interpretowany jako dane.
Reakcja wyświetlacza następuje po wysłaniu całego bajta, oraz zmianie stanu SCE, lub po
kolejnym takcie zegara (wysłanie pierwszego bitu z kolejnego bajta). Najbardziej znaczący
bit danych/komendy przesyłany jest jako pierwszy. Linia RES służy do restartowania
wyświetlacza, stan aktywny jest niski, przy czym restart nie powoduje zmiany zawartości
pamięci DDRAM (Display Data RAM) - stan pikseli nie zmienia się. Sygnał resetu jest
6
niezbędny w celu inicjalizacji LCD, lecz może być też użyty do przerywania transmisji
(pierwszy przesłany bit po zresetowaniu traktowany jest jako początek nowego bajta).
Przykładowe przebiegi na liniach używanych przez wyświetlacz obrazuje rys. 3, przedstawia
on pocztąek inicjalizacji wyświetlacza, a dokładnie resetowanie oraz przesłanie pierwszej
komendy (aktywacja i ustawienie rozszerzonego zakresu instrukcji). Na rysunku pominięto
linie zasilania (VDD musi by w stanie wysokim, aby kontroler działał) oraz masy, która
jak VOUT nie jest sterowalna.
105 ms
SCE
D/C
RES
SCLK
SDIN
DB7
DB6
DB5
DB4
DB3
DB2
DB1
DB0
writeB
Rysunek 3: Przebiegi sygnałów na początku inicjalizacji
Ze względu na brak możliwości zakodowania wszystkich poleceń wraz z ich parametrami na jedynie ośmiu bitach (niewystarczająca liczba kodów) zostały one podzielone na
dwa zestawy: podstawowy i rozszerzony. Ten sam kod może oznaczać różne polecenia
7
w zależności od zestawu instrukcji, który jest w danym momencie aktywny. Do wyboru
zestawu służy specjalne polecenie, które ma zawsze identyczny kod, ustawia ono także
tryb pracy kontrolera (włączony lub oszczędzanie energii) i tryb adresowania (poziomy lub
pionowy). Standardowy zestaw obejmuje najczęściej używane polecenia, czyli ustawianie
kursora i zmianę trybu wyświetlania (normalny, negatyw, zapalenie/zgaszenie wszystkich
pikseli). Natomiast rozszerzony w ogólności zawiera polecenia ustawiające napięcia wewnętrzne LCD, co ma wpływ na kontrast obrazu. Szczegółowy opis wszystkich poleceń
można znaleźć w specyfikacji kontrolera LCD.
4
Obsługa portu LPT
Realizację kodu programu rozpoczęliśmy od obsługi portu LPT. Do ustawiania rejestru
danych portu używana jest asemblerowa komenda outb, której użycie wymaga nadania odpowiednich uprawnień dostępu do portu za pomocą funkcji systemowej ioperm [4]. Tylko
użytkownik root może ją wywoływać - próba zapisu do portu bez przyznanych uprawnień
powoduje naruszenie ochrony pamięci, o czym mieliśmy okazję się przekonać. Adres portu
ustawiony jest w kodzie jako stała globalna na 0x378, co jest wartością domyślną, którą
można czasami zmienić w BIOS -ie podczas startu komputera. Funkcje wymagające adresu portu odwołują się do etykiety tej stałej. Zrezygnowaliśmy z próby automatycznego
rozpoznawania adresu portu (np. przez parsowanie pliku /proc/ioports) czy pytania
się o to użytkownika, ze względu na to, że rzadko kiedy adres portu nie jest domyślny.
Niemniej jednak wprowadzenie takiej opcji nie spowoduje konieczności zmian w funkcjach
potrzebujących adresu portu i może rozważymy to w terminie późniejszym.
5
Narzędzia pomocnicze
W trakcie tworzenia programu używaliśmy narzędzia lptmanager[6], monitora portu
LPT, który niestety nie jest już rozwijany, ale swoje zadanie spełnia bardzo dobrze. Umożliwia on wygodne sprawdzenie, czy stan rejestru portu po wykonaniu jakiegoś fragmentu
8
jest zgodny z oczekiwanym, bądź podgląd na bieżąco, przy krokowym debugowaniu programu. Kolejnym pomocnym narzędziem okazał się testserdisp, wchodzący w skład pakietu
serdisplib[7]. Stanowi on zbiór bibliotek umożliwiających obsługę różnych wyświetlaczy
podłączanych do PC. Wywołanie testserdisp -n PCD8544 -o‘‘WIRING=5‘‘ pozwala na
obsługę naszego układu. Program ten był przydatny głównie przy pisaniu podstawowych
funkcji jak inicjalizacja, czy przesyłanie poleceń i umożliwiał np. szybkie zresetowanie oraz
wyczyszczenie wyświetlacza. Wykonanie tych operacji byłoby bardzo uciążliwe, gdy nie
mieliśmy jeszcze w pełni gotowych naszych funkcji. Innego rodzaju udogodnieniem było
użycie systemu kontroli wersji Subversion (SVN[8]), dzięki czemu łatwo mogliśmy udostępniać sobie nawzajem i uaktualniać pliki wchodzące w skład projektu. SVN uniemożliwia
wystąpienie ew. konfliktów wersji plików oraz pozwala korzystać z zasobów na dowolnym
komputerze podłączonym do internetu.
6
Funkcje podstawowe
Funkcje zapewniające obsługę wyświetlacza na najniższym poziomie zostały umiesz-
czone w pliku set.s, który zawiera także definicje stałych używanych przez nie, takich
jak maski bitów portu, tablica znaków oraz numery funkcji systemowych i ich parametry. Ponieważ nie ma potrzeby ich modyfikacji przez program, całość znajduje się w sekcji
text. Tylko niektóre funkcje tego modułu dostępne są z zewnątrz. Założyliśmy, że podstawowy zestaw instrukcji jest domyślny, a więc funkcje operujące tylko na poleceniach z
niego, nie muszą go ustawiać. Jeśli wymagana jest instrukcja z rozszerzonego zestawu, to
funkcja jej potrzebująca go aktywuje, a przed zakończeniem wraca do podstawowego. Jeśli
nie jest napisane inaczej, to funkcje nie zwracają żadnych wartości i nie są dostępne na
zewnątrz. Wybrane funkcje zostały oznaczone dyrektywą global, co umożliwia wykorzystanie ich przez inne moduły. Taka enkapsulacja spełnia podobną rolę, jak modyfikatory
dostępu w klasach języków wysokiego poziomu, ograniczając możliwość błędnego użycia
niektórych funkcji.
9
6.1
Funkcja setb
Służy do ustawiania konkretnego bitu w rejestrze danych portu. Przyjmuje jako argument 1-bajtową maskę z ustawionym bitem. Jej działanie polega na odczytaniu stanu
portu do rejestru procesora, ustawieniu w nim bitu zgodnie z maską i wpisaniu wyniku do
portu LPT.
6.2
Funkcja clrb
Działa analogicznie jak poprzednia, z tym że zeruje bit ustawiony w masce.
6.3
Funkcja writeB
Wysyła bajt podany jako pierwszy argument do wyświetlacza. Drugim argumentem
jest flaga określająca czy dany bajt jest komendą czy danymi. Na początku zależnie od
drugiego argumentu ustawiany jest stan linii D/C, po czym ustawiane są stany początkowe
linii SCE i SCK, do czego służą dwie poprzednio omówione funkcje. Następnie kolejne bity
umieszczane są na linii SDIN, równolegle z generowaniem sygnału zegarowego. Najbardziej
znaczący bit transmitowany jest jako pierwszy. Po przesłaniu ostatniego bitu stan SCE
zmienia się na wysoki, co powoduje reakcję wyświetlacza na właśnie przesłany bajt. Żadna
wartość nie jest zwracana.
6.4
Funkcja clear
Nie wymaga parametrów, służy do czyszczenia pamięci DDRAM, a więc i zawartości
wyświetlacza. Jej działanie polega na ustawieniu kursora na początek wyświetlacza, punkt
o współrzędnych (0,0) i wysłaniu na wyświetlacz 4032 (liczba pikseli) bitów o wartości
zero w trybie ciągłym. Po tej operacji kursor znajduje się na początku wyświetlacza,
ponieważ jest przesuwany automatycznie w miarę napływu danych.
10
6.5
Funkcja setPerm
Nie posiada żadnych parametrów, służy do ustawiania uprawnień dla portu zdefiniowanego w zmiennej globalnej port. Jej działanie polega wyłącznie na wywołaniu funkcji
systemowej ioperm. Zwraca 0, gdy operacja ustawienia uprawnień zakończy się sukcesem
albo -1, gdy nastąpi błąd, co może mieć miejsce np. przy próbie uruchomienia programu
przez zwykłego użytkownika (UID!=0).
6.6
Funkcja init
Nie przyjmuje żadnych parametrów, zajmuje się inicjalizacją wyświetlacza. Powinna
być wywołana przed rozpoczęciem jakichkolwiek działań na LCD. Jej działanie polega na
załączeniu napięcia zasilającego i resetowaniu kontrolera przez czas określony w strukturze
waitTime, który u nas wynosi 105ms (wg specyfikacji minimalny czas resetowania w czasie inicjalizacji to 100ms). W tym celu użyta jest funkcja systemowa sleep[5]. Następnie
wysyłane są kolejno polecenia nakazujące aktywację chipa, wybór rozszerzonego zestawu
instrukcji, ustawienie poziomego trybu adresowania, napięcia, biasu i współczynnika temperaturowego. Wartości tych parametrów zostały dobrane doświadczalnie tak, aby uzyskać
jak najlepszy kontrast. Kolejnym krokiem jest aktywacja standardowego zestawu instrukcji i włączenie normalnego trybu wyświetlania. Zawartość pamięci DDRAM jest w tym
momencie niezdefiniowana, wywoływana jest więc tu funkcja clear, co kończy inicjalizację.
6.7
Funkcja off
Nie przyjmuje żadnych parametrów, a służy do wyłączania wyświetlacza, co jest osiągane poprzez ustawienie stanu niskiego wszystkich używanych linii na porcie LPT.
6.8
Funkcja normColors
Nie ma żadnych argumentów. Służy do ustawiania normalnego trybu wyświetlania
(zapalone piksele na zgaszonym tle), jeśli przed wywołaniem tryb jest już ustawiony na
11
normalny, to na wyświetlaczu nic się nie dzieje.
6.9
Funkcja invColors
Działa analogicznie do poprzedniej, z tym że ustawia tryb odwróconych kolorów (zgaszone piksele na czarnym tle).
6.10
Funkcja putStr
Przyjmuje argument w postaci adresu początku ciągu ASCIIZ, który później wysyła na
ekran LCD. Pojedynczy znak jest wielkości 5x8 pikseli, tak więc na wyświetlaczu zmieści
się 6 linii po 14 znaków każda, co daje w sumie 84 znaki. Każdy znak dający się wpisać
bezpośrednio z klawiatury (znak o kodzie ASCII od 32 do 126) zawiera swój wpis w tablicy
znaków (aby oszczędzić sobie trudu samodzielnego jej tworzenia, za pomocą polecenia
substitute edytora Vim, dostosowaliśmy znalezioną na [9]). Wiersz tablicy składa się z
5 bajtów, które odpowiadają za wygląd danego znaku na ekranie, pierwszy bit w bajcie
oznacza najwyżej znajdujący się piksel. Po wyświetleniu znaku wstawiany jest odstęp o
szerokości jednego piksela (bajt składający się z samych zer), spacja składa się z 6 pikseli
odstępu. Adres znaku do wyświetlenia jest inkrementowany w pętli, a kursor przesuwany
jest automatycznie przez kontroler miarę wyświetlania kolejnych znaków, które kończy się
w momencie napotkania na znak o kodzie poniżej 0x20. Jeśli tekst nie zmieści się na
wyświetlaczu to nadpisuje on jego zawartość zaczynając od początku.
6.11
Funkcja setXY
Przyjmuje jako argumenty numer kolumny (od 0 do 84) oraz numer wiersza (od 0 do 5)
i ustawia odpowiednio kursor (miejsce, od którego zacznie się potem wyświetlanie), gdy
któraś z wartości jest poza zakresem, to funkcja nic nie robi. Nalżey zwrócić uwagę, że
niemożliwe jest zaadresowanie w ten sposób każdego piksela bezpośrednio. Przestrzeń
adresowalna podzielona jest na linie o wysokości 8 pikseli, a numer wiersza i kolumny
12
odnosi się właśnie do takiej linii. Żeby sterować poszczególnymi pikselami należy wysłać
odpowiedni bajt danych.
7
Obsługa grafiki oraz animacji
Głównym zadaniem na drugą część projektu była implementacja obsługi wyświetlania
animacji. Pomysł stworzenia własnego sposobu zapisu grafiki został zarzucony na rzecz
popularnego formatu GIF [11] [12], który obsługuje także obrazy animowane. Kod odpowiedzialny za obsługę grafiki został umieszczony w pliku lcdplib.s. Do odczytu i dekompresji
plików została wykorzystane funkcje DGifOpenFileName oraz DGifSlurp DGifCloseFile z
biblioteki GIFLIB [13]. Implementacja interakcji z użytkownikiem w zakresie wczytywania nazwy pliku i wyświetlania komunikatów o błędach również znajduje się w tym pliku.
Ze względu na, to że funkcje biblioteki GIFLIB korzystają ze struktur typu GifFileType
oraz SavedImage, to na początku zostały zadeklarowane offsety poszczególnych ich pól,
aby można było łatwo się do nich odwoływać. Funkcje biblioteczne zwracają wartość 0
oznaczoną oryginalnie jako GIF ERROR w razie napotkania problemów w dalszym działaniu, ze względu na przejrzystość kodu używamy tej stałej jako globalnej. Natomiast stała
globalna bmMaxsize określa nam maksymalny rozmiar obrazka obsługiwany przez wyświetlacz. Ponieważ projekt nie miał na celu implementacji pełnej obsługi formatu GIF oraz
wszystkich jego rozszerzeń, w związku z tym narzucono dodatkowe ograniczenia na plik
wejściowy:
• paleta jednobitowa
• brak kanału alpha
• każdy obrazek w pliku o wymiarze 48px x 84px
13
7.1
Funkcja anim
Jako jedyna z modułu dostępna jest z zewnątrz. Odpowiada ona za wyświetlenie znaku
zachęty do wczytania nazwy pliku i wczytuje ją ze standardwego wejścia i przekształca
odpowiednio dla funkcji czytającej plik (poprzez usunięcie znaku końca linii). Następnie
wywołuje pozostałe funkcje odpowiedzialne za obsługę grafiki tj. wczytanie pliku i wyświetlenie animacji, wywołuje również zmiany trybu adresowania wyświetlacza z wierszowego
(poziomego - używanego do wyświetlania tekstu) na kolumnowe (pionowe - naturalne w
przypadku wyświetlania grafiki) przed wyświetleniem obrazka oraz odwrotnie po zakończeniu jego wyświetlania. W celu możliwośći przerwania zapętlonej animacji w dowolnym
momencie, użyta została funkcja systemowa FORK i KILL. Na końcu, w przypadku prawidłowego otwarcia i odczytu pliku wywoływana jest funkcja DGifCloseFile zwalniająca
zasoby przydzielone przez inne funkcje biblioteczne.
7.2
Funkcja readGif
Służy do odczytu pliku GIF o nazwie podanej jako argument. Wywołuje biblioteczną
funkcję DGifOpenFileName otwierającą plik, a w przypadku, gdy ta zakończy się poprawnie (zwróci wartość różną od 0, a więc poprawny wskaźnik na strukturę GifFileType)
wywoływane jest DGifSlurp wczytujące obrazek do pamięci. W przypadku, gdy obie te
funkcje zakończą się bez błędów, to zwracany jest uzyskany wcześniej wskaźnik na GifFileType. Natomiast w razie wystąpienia problemów wyśiwetlane są komunikaty o błędach i
ewentualnie plik jest zamykany oraz funkcja zwraca wartość 0.
7.3
Funkcja playMovie
Przyjmuje wskaźnik na strukturę GifFileType pliku do wyświetlenia. W ogólności odpowiada za wyśiwetlenie na LCD animacji. Wywołuje w pętli (aż do wyczerpania klatek)
funkcje odpowiedzialne za wyświetlenie i synchronizację kolejnych klatek animacji.
14
7.4
Funkcja getImage
Pobiera ona obrazek ze stuktury SavedImage(na którą wskaźnik został podany w pierwszym argumencie), dokonuje odpowiedniej konwersji (obrót o 90◦ , tak aby mógł on być
prawidłowo wyświetlony na LCD) i zapisuje go jako ciąg bitów (w miejsce wskazywane
przez drugi argument). Ze względu na konieczność dokonywania wielu dość operacji związanych z przekodowaniem obrazka z formatu dostarczanego przez funkcje z GIFLIB do
nadającego się do wysłania na LCD, funkcja ta jest jedną z najbardziej rozbudowanych w
całym projekcie.
7.5
Funkcja getFrameDuration
Funkcja ta odczytuje i zwraca czas trwania danej klatki w animacji z informacji zawartych w strukturze SavedImage, do której wskaźnik podawany jest jako argument. Wartość
zwracna podana jest w setnych częściach sekundy, gdy nie uda się jej odczytać zwracane
jest 0.
7.6
Funkcja displayImage
Funkcja ta odpowiada za wyświetlanie na LCD obrazka poprzez wywoływanie w pętli
funkcji writeB z modułu set.s. Przyjmuje jako argument wskaźnik na ciąg bitów opisujący
obrazek w formacie odpowiednim do wyświetlenia na LCD (pozyskany poprzez getImage).
Pętla biegnie dopóbki nie zostanie wyświetlony cały obrazek.
8
Interfejs użytkownika
W ramach części zadania przeznaczonej na sprawozdanie połówkowe został zaimplemen-
towany interfejs umożliwiający wypisywanie znaków ASCII na LCD, który później został
rozszerzony o opcje dotyczące grafiki i animacji. Program znajdujący się w pliku menu.s
zawiera proste tekstowe menu, które udostępnia podstawowe metody kontroli wyświetlacza, takie jak inicjalizacja, czyszczenie, odwracanie kolorów, wysłanie tekstu, wyświetlenie
15
animacji oraz wyłączanie LCD. Działają one w oparciu o funkcje opisane w poprzednich
rozdziałach. Wybranie opcji powoduje zwykle jedynie wywołanie odpowiedniej z tych
funkcji, czasami podejmowane są dodatkowe działania np. wczytanie ciągu znaków. Menu
wyświetla się ciągle w pętli, aż do momentu wybrania opcji zakończenia programu. Wybór opcji wysyłania tekstu powoduje wczytanie ciągu o długości maksimum 85 znaków, co
stanowi 84 znaki drukowalne oraz znak końca linii, niewyświetlany. Wysyłanie dłuższego
ciągu nie ma sensu ponieważ zacznie on nadpisywać początek ekranu zanim zdąży się zauważyć poprzedni tekst. Na początku program podejmuje próbę ustawienia dostępu do
portu, jeśli się ona nie powiedzie, to dalsze działanie jest bezcelowe, a więc wyświetlany jest
tylko komunikat o błędzie i następuje zakończenie programu. Menu zostało przedstawione
na rys. 4
Wybierz opcje:
1 - Inicjalizacja LCD
2 - Dopisanie tekstu
3 - Negatyw
4 - Pozytyw
5 - Wylacz LCD
6 - Czyszczenie ekranu
7 - Wyswietlenie GIFa
8 - Koniec
>>
Rysunek 4: Menu programu
9
Podsumowanie i wnioski
Realizacja tego projektu pozwoliła nam na poznanie języka asemblera od strony bardziej
praktycznej, niż miało to miejsce wcześniej. Efekty naszej pracy były widoczne na żywo na
16
sprzęcie, a więc były bardziej namacalne, niż tylko obraz na monitorze komputera, w przypadku pisania ”zwykłych“ programów, co było niewątpliwie bardzo interesujące zwłaszcza
jeśli chodzi o wyświetlanie animacji. Należy zwrócić uwagę na nienajlepszą dokumentację
biblioteki giflib, co jednak rekomensowane jest otwartością kodu źródłowego. Okazało się
to pomocne przy pisaniu funkcji wykorzystujących tę bibliotekę Samodzielne lutowanie
elementów było również ciekawym doświadczeniem, pokazało nam, że skonstruowanie nawet prostego działającego układu nie jest zadaniem trywialnym i może być bardzo czasoi praco-chłonne. Przekonaliśmy się także, jakie znaczenie mają dodatkowe narzędzia, jak
np. monitor portu LPT, bez którego zadanie było by praktycznie niewykonalne, zwłaszcza
w zakresie funkcji operujących bezpośrednio na rejestrze portu równoległego, a także o
znaczeniu aspektów nieistniejących przy zadaniach czysto programowych (jak np. konieczność odpowiedniego ułożenia elementów elektronicznych, tak aby nie było zwarć). Był to
nasz pierwszy, tak duży projekt, zrealizowany w asemblerze. Było by go ciężko zrealizować
bez sprawnej współpracy, którą ułatwiał system kontroli wersji i udostępniania kodu.
Literatura
[1] http://www.nxp.com/acrobat_download/datasheets/PCD8544_1.pdf, Specyfikacja kontrolera LCD Philips PCD8544
[2] http://www.mod-planet.com/index.php?module=subjects&func=
viewpage&pageid=196, Jak podłączyć LCD z Nokii do PC
[3] http://www.night-modders.com/index.php?module=subjects&func=
viewpage&pageid=226, Podłączanie LCD Nokia 3310
[4] info ioperm, dokumentacja info funkcji systemowej ioperm
[5] info nanosleep, dokumentacja info funkcji systemowej nanosleep
[6] http://lptman.sourceforge.net/, Strona domowa LPT Manager
17
[7] http://serdisplib.sourceforge.net/, Strona domowa serdisplib
[8] http://subversion.tigris.org/, Strona domowa systemu kontroli wersji SVN
[9] http://www.microchip.su/showthread.php?t=3245, źródło tablicy znaków
[10] http://download.savannah.gnu.org/releases/pgubook/
ProgrammingGroundUp-1-0-booksize.pdf,
Jonathan
Bartlett,
Programming
from the Ground Up
[11] www.w3.org/Graphics/GIF/spec-gif89a.txt, Cover Sheet for the GIF89a Specification
[12] http://en.wikipedia.org/wiki/Graphics_Interchange_Format, Graphics Interchange Format - Wikipedia, the free encyclopedia
[13] http://sourceforge.net/projects/giflib/, Introduction to GIFLIB – A library
for processing GIFs
18

Podobne dokumenty