Biblioteki graficzne Microchipa: obsługa touch-panela i LCD ze sterownikiem SSD1289
List. 7. Inicjalizacja sterownika SSD1289
void ResetDevice(void) { TRISD=0xff00;//RD0…RD7 wyjściowy TRISE=0xff00;//RE0…RE7 wyjściowy LCD_CS_TRIS=0; //sterujące linie wyjściowe LCD_RS_TRIS=0; LCD_RD_TRIS=0; LCD_WR_TRIS=0; LCD_RES_TRIS=0; LCD_RES=1;//cykl zerowania sterownika DelayMs(50); LCD_RES=0; DelayMs(50); LCD_RES=1; LCD_RS = 0;//stany początkowe linii sterujących LCD_WR = 1; LCD_RD = 1; LCD_CS = 1; SetReg(0x00, 0x0001); SetReg(0x03, 0xAAAC); SetReg(0x0C, 0x0002); DelayMs(15); SetReg(0x0D, 0x000A); SetReg(0x0E, 0x2D00); SetReg(0x1E, 0x00BC); SetReg(0x01, 0x1A0C); DelayMs(15); #if (DISP_ORIENTATION == 0) SetReg(0x01, 0x293F); #else SetReg(0x01, 0x2B3F); #endif SetReg(0x02, 0x0600); SetReg(0x10, 0x0000); #if (DISP_ORIENTATION == 0) SetReg(0x11, 0x60B0); #else SetReg(0x11, 0x60B0); #endif SetReg(0x05, 0x0000); SetReg(0x06, 0x0000); DelayMs(100); SetReg(0x16, 0xEF1C); SetReg(0x17, 0x0003); SetReg(0x07, 0x0233); SetReg(0x0B, 0x0000); SetReg(0x0F, 0x0000); SetReg(0x41, 0x0000); SetReg(0x42, 0x0000); SetReg(0x48, 0x0000); SetReg(0x49, 0x013F); SetReg(0x44, 0xEF00); SetReg(0x45, 0x0000); SetReg(0x46, 0x013F); SetReg(0x4A, 0x0000); SetReg(0x4B, 0x0000); SetReg(0x30, 0x0707); SetReg(0x31, 0x0704); SetReg(0x32, 0x0204); SetReg(0x33, 0x0502); SetReg(0x34, 0x0507); SetReg(0x35, 0x0204); SetReg(0x36, 0x0204); SetReg(0x37, 0x0502); SetReg(0x3A, 0x0302); SetReg(0x3B, 0x1f00); SetReg(0x23, 0x0000); SetReg(0x24, 0x0000); DelayMs(50); }
Opisywanie tutaj wszystkich rejestrów sterujących nie jest konieczne. Te dane można sobie znaleźć w dokumentacji sterownika i na ich podstawie zobaczyć jak jest wykonywana inicjalizacja.
W Internecie można znaleźć sekwencje inicjalizacji SSD1289 różniące się nieco do tej z listingu7. Jak w trakcie testów wypróbowałem kilka alternatywnych i efekt działania był taki sam. Zainicjowany wyświetlacz jest gotowy do wyświetlania zawartości pamięci obrazu.
W dokumentacji biblioteki części poświęconej dodawaniu nowego sterownika jest opisany zestaw funkcji warstwy Device Driver Layer niezbędnych dla prawidłowego działania wyświetlacza. Ponieważ SSD1289 jest wspierany przez bibliotekę to teoretycznie wszystkie funkcje powinny być gotowe. W praktyce jednak konieczne były zmiany w kilku kluczowych procedurach. Jedną z najważniejszych procedur w tej warstwie jest z „zapalenie” jednego piksela matrycy – PutPixel . Każdy piksel ma dwa podstawowe atrybuty : adres, czyli współrzędne x,y oraz kolor. Standardowa procedura PutPixel ma dwa argumenty: współrzędna x i współrzędną y (listing 8). Kolor piksela jest zawarty w zmiennej globalnej _color .
List. 8. Procedura PutPixel
void PutPixel(SHORT x, SHORT y) { if(_clipRgn) { if(x < _clipLeft) return; if(x > _clipRight) return; if(y < _clipTop) return; if(y > _clipBottom) return; } SetAddress(x, y); WritePixel(_color); }
Przed ustaleniem adresu i zapisaniem danej sprawdzane jest czy współrzędne x oraz y nie mają wartości spoza dopuszczalnego zakresu określonego przez rozmiar matrycy. Procedura SetAdress została pokazana na listingu 9.
List. 9. Procedura ustawienia adresu piksela
inline void SetAddress(WORD x, WORD y) { #if (DISP_ORIENTATION == 0) SetReg(0x004f,x); #else SetReg(0x004e,x); #endif #if (DISP_ORIENTATION == 0) SetReg(0x004e,y); #else SetReg(0x004f,y); #endif LcdWriteControl(0x0022); }
Zależnie od przyjętej orientacji (pionowa lub pozioma) współrzędne są zapisywane zamiennie komendami o adresie 0x4e lub 0x4f. Procedurę kończy wysłanie komendy 0x22 ( write data to GRAM ). Funkcja WritePixel to zdefiniowane makro:
#define WritePixel(color) {LcdWriteData(color);}
WritePixel jest używany w 2 kolejnych ważnych procedurach: czyszczeniu ekranu ClearDevice() (listing 10) oraz rysowaniu prostokąta Bar() – listing 11.
List. 10. Procedura czyszczenia ekranu
void ClearDevice(void) { DWORD counter; SetAddress(0, 0); for(counter = 0; counter < (DWORD) (GetMaxX() + 1) * (GetMaxY() + 1); counter++) { WritePixel(_color); } }
List. 11. Funkcja rysowania prostokąta
WORD Bar(SHORT left, SHORT top, SHORT right, SHORT bottom) { register SHORT x, y; #ifndef USE_NONBLOCKING_CONFIG while(IsDeviceBusy() != 0); #else if(IsDeviceBusy() != 0) return (0); #endif if(_clipRgn) { if(left < _clipLeft) left = _clipLeft; if(right > _clipRight) right = _clipRight; if(top < _clipTop) top = _clipTop; if(bottom > _clipBottom) bottom = _clipBottom; } { for(y = top; y < bottom + 1; y++) for(x = left; x < right + 1; x++) PutPixel(x, y); } return (1); }
Obie te procedury w oryginalnej wersji nie chciały działać poprawnie. Szczególnie Bar() przysporzył mi kłopotów. Wynikały one z tego, że biblioteka ma możliwość konfigurowania orientacji, a ja przyjąłem, że wyświetlacz będzie zorientowany poziomo. Oryginalna procedura z drvTFT2.c nie chciała w tej orientacji pracować poprawnie. Na początku funkcji Bar() jest sprawdzane, czy współrzędne wierzchołków prostokąta nie maja wartości większych niż to wynika z rozmiarów matrycy wyświetlacza.
Po napisaniu i uruchomieniu procedur komunikacji ze sterownikiem wyświetlacza, poprawnym zainicjowaniu sterownika i korekt procedur Bar i ClearDevice można by było w zasadzie przystąpić do prób działania biblioteki. Jednak GDD-X generuje projekt, w którym definiowana jest obsługa panelu rezystancyjnego dotykowego. Panelem dotykowym i jego obsługa zajmiemy się później. Na tym etapie ta obsługa musiał być wyłączona przez usunięcie definicji #define USE_TOUCHSCREEN , żeby projekt mógł się skompilować bez błędów. Nie są wtedy kompilowane funkcje obsługi paneli z pliku TouchScreen.c .
Graphic Display Designer X – testy działania
Mamy już wszystko gotowe by rozpocząć testy działania biblioteki. W tym celu tworzymy projekt w środowisku MPALB X i uruchamiamy wtyczkę Graphic DisplayDesigner . Ponieważ jeszcze nie mamy obsługi panelu dotykowego, to nie można testować działania interakcji z użytkownikiem. Testy będą polegały tylko na wyświetlaniu obiektów (głównie widżetów).
Rys. 4. Okno projektu ekranu w Graphics Display Designer
W GDD-X utworzyłem projekt ekranu (rysunek 4) z umieszczonymi: bitmapą z logo Elektroniki Praktycznej i obiektami Meter oraz Button . Po skompilowaniu projektu i zaprogramowaniu mikrokontrolera te elementy zostały prawidłowo wyświetlone na ekranie wyświetlacza – fotografia 5.
Fot. 5. Efekt działania projektu ekranu z GDD-X