ISIX-RTOS – przykład 2 – kolejki FIFO i obsługa graficznego wyświetlacza LCD
Ustawienie wybranej pozycji kursora w pamięci obrazu sprowadza się do wysłania do wyświetlacza komendy Set Row Position oraz Set Col Position.
Działanie klasy display_server (wątku serwera) , sprowadza się do odczytywania komunikatów (wskaźników do klas komunikatów) z kolejki FIFO, a następnie odpowiednie wykorzystanie metod klasy nokia_display do sterowania wyświetlaczem. Zadanie to realizowane jest przez metodę wirtualną main() klasy display_server (list. 7).
List. 7. Metoda wirtualna main() klasy display_server
//Main thread void display_server::main() { const display_msg *msg = NULL; for(;;) { //Try read message from the fifo if(io_fifo.pop(msg) == isix::ISIX_EOK) { //Validate message if( msg ) { //Clear display display.clear(); //If text message if(msg->get_type() == display_msg::MSG_TEXT) { //Cast to the text message class const text_msg *t = static_cast(msg); if(t->get_text()) { //Write text on the display display.put_string( t->get_text(), t->get_x(), t->get_y()); } } //If graphics message else if( msg->get_type() == display_msg::MSG_GRAPHICS) { //Get image const images::img_def *img = static_cast (msg)->get_image(); if(img) { //Display bitmap display.put_bitmap(*img); } } } } } }
W pętli głównej wątku wywoływana jest metoda pop() obiektu kolejki FIFO (io_fifo). Metoda ta blokuje wykonywanie wątku do momentu odebrania od innego zadania komunikatu przekazanego za pomocą metody push(). W przypadku, gdy kolejka FIFO zawiera jakiś komunikat, wówczas metoda pop(), wybudza wątek i zwraca kod błędu isix::ISIX_EOK. W przypadku odebrania prawidłowego komunikatu, zawartość wyświetlacza LCD jest czyszczona za pomocą metody clear() obiektu wyświetlacza display, a następnie sprawdzany jest typ przekazanego komunikatu (obiektu) za pomocą metody get_type() klasy bazowej display_msg. Wykrywanie typów klas również można zrealizować za pomocą mechanizmu RTTI (Run Time Type Information) i operatora typeid(), jednak z uwagi na dużą zajętość pamięci Flash mechanizm RTTI został wyłączony za pomocą flagi kompilatora -fno-rtti) Jeżeli przekazany obiekt jest typu tekstowego (text_msg), wówczas jest on rzutowany na wskaźnik do klasy text_msg, i następnie wywoływane są metody pobierające wskaźnik do napisu oraz pozycję tekstu na ekranie. Następnie wywoływana jest metoda obiektu wyświetlacza (display), wypisująca tekst na wyświetlaczu LCD na zadanej pozycji. W przypadku, gdy mamy do czynienia z obiektem typu graficznego (graph_msg), wówczas jest on rzutowany na wskaźnik do tego obiektu, a następnie wywoływana jest metoda pobierająca wskaźnik na strukturę opisującą obrazek (img_def). Następnie wskaźnik ten jest przekazywany do metody put_bitmap() obiektu wyświetlacza, który jest odpowiedzialny za wyświetlenie bitmapy. Obiekt keys, klasy graph_key jest odpowiedzialny za odczyt stanu joysticka oraz wysyłanie komend dla serwera wyświetlania w zależności od kierunku przechylenia josyticka.
List. 8. Klasa graph_key jest odpowiedzialna za odczyt stanu joysticka oraz wysyłanie komend dla serwera wyświetlania w zależności od kierunku przechylenia joysticka
//Constructor graph_key::graph_key(display_server &_srv) : task_base( STACK_SIZE, TASK_PRIO), disp_srv(_srv) { //Enable PE in APB2 RCC->APB2ENR |= RCC_APB2Periph_GPIOE; //Set GPIO as inputs io_config( KEY_PORT, KEY_OK_BIT, GPIO_MODE_INPUT, GPIO_CNF_IN_FLOAT); io_config( KEY_PORT, KEY_UP_BIT, GPIO_MODE_INPUT, GPIO_CNF_IN_FLOAT); io_config( KEY_PORT, KEY_DOWN_BIT, GPIO_MODE_INPUT, GPIO_CNF_IN_FLOAT); io_config( KEY_PORT, KEY_LEFT_BIT, GPIO_MODE_INPUT, GPIO_CNF_IN_FLOAT); io_config( KEY_PORT, KEY_RIGHT_BIT, GPIO_MODE_INPUT, GPIO_CNF_IN_FLOAT); }
Obiekt inicjalizowany jest za pomocą konstruktora, który jako argument przyjmuje referencję do klasy display_server. W konstruktorze inicjalizowane są porty GPIO do których podłączone są poszczególne styki joysticka. Odczyt stanu joysticka oraz wysyłanie komunikatów realizowane jest przez metodę główną wątku main() – list. 9.
List. 9. Metoda główna wątku main() odpowiada za odczyt stanu joysticka oraz wysyłanie komunikatów
//Task/thread method void graph_key::main() { //Previous key variable static short p_key = -1; //Graphics message class static graph_msg gmsg; //Text message class static text_msg tmsg("Wcisnales OK"); for(;;) { //Get key short key = get_key(); //Check if any key is pressed if(key!=0 && p_key==0) { switch(key) { case KEY_OK: disp_srv.send_message(tmsg); break; case KEY_LEFT: gmsg.set_image( images::isixlogo_bmp); disp_srv.send_message(gmsg); break; case KEY_RIGHT: gmsg.set_image( images::disk_bmp); disp_srv.send_message(gmsg); break; case KEY_UP: gmsg.set_image( images::printer_bmp); disp_srv.send_message(gmsg); break; case KEY_DOWN: gmsg.set_image( images::scriba_bmp); disp_srv.send_message(gmsg); break; } } //Previous key assignement p_key = key; //Wait short time isix::isix_wait( isix::isix_ms2tick(DELAY_TIME) ); } }
Wykrywanie kierunku przechylenia joysticka jest realizowane w pętli głównej wątku, na zasadzie wykrywania zbocza na linii GPIO, do której dołączono styki joysticka. W przypadku wykrycia zbocza opadającego na którymś z wejść program ustala jaki kierunek wskazuje josytick, następnie do kolejki FIFO serwera wyświetlania jest przekazywany obiekt komunikatu za pomocą metody send_message(). Dodatkowe krótkie opóźnienie o długości DELAY_TIME (25 ms) eliminuje wpływ drgań styków na działanie aplikacji.