Ważnym elementem graficznego interfejsu użytkownika jest wyświetlanie informacji tekstowych. Jak wiemy sterownik zastosowany w module LCD nie zapewnia żadnego wsparcia poza możliwością zapalenia/zgaszenia pojedynczego pikseli o zadanym kolorze. Dlatego wyświetlanie znaków alfanumerycznych trzeba wykonać całkowicie programowo. Zaczniemy od generatora znaków. Tablicę z wzorcami znaków można sobie samemu zdefiniować, ale jest to żmudne zajęcie. Ja wykorzystałem gotową tablicę wykonaną przez James’a P. Lyncha dla wyświetlacza telefonu Nokia 6100. Tablica zawiera wzorce znaków o 3 wielkościach: 6 x 8 pikseli (SMALL), 8x8pikseli (MEDIUM) i 8x16pikseli (LARGE). W praktyce najbardziej przydatne okazały się największe znaki, ale pozostałe tez są używalne. Nic nie stoi na przeszkodzie by sobie zdefiniować jeszcze większe znaki. Pierwsze 3 bajty w tablicy generatora dla każdej z wielkości znaków zawierają informację o ilości kolumn, wierszy i bajtów na znak. Na tej podstawie jedna uniwersalna procedura potrafi wyświetlić znaki o różnych wielkościach.
Procedura potrafiąca wyświetlić jeden znak jest pokazana na listingu 9.
List. 9. Procedura wyświetlania jednego znaku
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
void LCDPutChar(char c, int x, int y, int size, unsigned char fColor, unsigned char bColor) { extern const unsigned char FONT6x8[97][8]; extern const unsigned char FONT8x8[97][8]; extern const unsigned char FONT8x16[97][16]; int i,j; unsigned char nCols; unsigned char nRows; unsigned char nBytes; unsigned char PixelRow; unsigned char Mask; unsigned char *pFont; unsigned char *pChar; unsigned char *FontTable[] = {(unsigned char *)FONT6x8, (unsigned char *)FONT8x8, (unsigned char *)FONT8x16}; //wskaznik na poczatek tablicy generatora znakow pFont = (unsigned char *)FontTable[size]; nCols = *pFont; //liczba kolumn wzorca znaku nRows = *(pFont + 1); //liczba wierszy wzorca znaku nBytes = *(pFont + 2); //liczba bajtow wzorca znaku //wskaznik na ostatni bajt z wzorca naszego znaku pChar = pFont + (nBytes * (c - 0x1F)) + nBytes - 1; //petla wykonywana dla kazdego wiersza for (i = nRows - 1; i >= 0; i--) { //pobierz bajt z wzorca znaków PixelRow = *pChar--; WrAddr(x,y+i); Mask=0x80; for (j = 0; j < nCols; j ++) { if ((PixelRow & Mask) == 0) WrData (bColor); //jezeli piksel = 0 kolor tla else WrData(fColor); //jezeli piksel = 1 kolor znaku Mask=Mask>>1; } } } |
Argumentami procedury są : kod ASCII wyświetlanego znaku, położenie na ekranie (współrzędne x i y ),rozmiar, kolor znaku i kolor tła. W zmiennej pFont jest umieszczany wskaźnik na początek tablicy generatora znaków. Do zmiennych nCols, nRows i nBytes są zapisywane pierwsze 3 bajty z tablicy generatora znaków. Ponieważ wzorce znaków nie są umieszczane w tablicy zgodnie z kodami ASCII, to trzeba kod ASCII wyświetlanego znaku przekształcić na pozycję w tablicy generatora. Po przekształceniu wskaźnik pChar wskazuje na ostatni bajt wzorca znaku w tablicy generatora. Program pobiera kolejne bajty z tablicy (od ostatniego do pierwszego). Każdy bit tego bajtu jest analizowany. Jeżeli jest ustawiony, to bit jest wyświetlany w kolorze znaku określonym argumentem fColor. Kiedy bit jest wyzerowany, to jest wyświetlany w kolorze określonym argumentem bColor. W ten sposób można wyświetlać znaki w dowolnym kolorze na tle w dowolnym kolorze o głębi 8-bitowej. Tryb tekstowy uzupełnimy procedurą wyświetlania tekstu w jednym z trzech rozmiarów(argument size). Pozycja początku ciągu znaków jest ustalana argumentami x, y, a kolor znaków i tła argumentami fColor i bColor.
Wynik działania tej procedury został pokazany na fotografii 5.
Fot. 5. Przykładowy efekt działania procedury z listingu 10
List. 10. Procedura wyświetlania tekstu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void LCDPutStr(const char *pString, int x, int y, int Size, char fColor, char bColor) { //w petli do znalezienia końca ciagu while (*pString != 0x00) { //wyswietl znak alfanumeryczny LCDPutChar(*pString++, x, y, Size, fColor, bColor); //korekcja pozycji y w zaleznosci od wielkosci znaku if (Size == SMALL) x = x + 6; else if (Size == MEDIUM) x = x + 8; else x = x + 8; if (x > 320) break; } } |