Serwisy partnerskie:
Close icon
Serwisy partnerskie

Kurs Arduino odcinek 25 - font podstawowy biblioteki Adafruit GFX

W poprzednim odcinku zajmowaliśmy się podstawowym fontem, zawartym w bibliotece Adafruit GFX, który jest zdefiniowany w pliku glcdfont.c. Biblioteka ta oferuje także znacznie ulepszone fonty, jednak my nie wyczerpaliśmy tematu fontu podstawowego.
Article Image
1. Kurs Arduino: wprowadzenie 2. Kurs Arduino odcinek 1 - co to jest i jak zacząć? (sprzęt, schematy, programowanie) 3. Kurs Arduino odcinek 2 - termometry: 'diodowy', pokojowy oraz 'scalony' analogowy 4. Kurs Arduino odcinek 3 - moduł wyświetlacza LCD (HD44780) 5. Kurs Arduino odcinek 4 - czujnik BME280 (pomiar ciśnienia, wilgotności i temperatury) 6. Kurs Arduino odcinek 5 - biblioteki do trzyfunkcyjnego czujnika BME280 7. Kurs Arduino odcinek 6 - wykorzystanie łącza I2C (TWI) 8. Kurs Arduino odcinek 7 - wykorzystanie łącza SPI (karty pamięci, MAX31865, MAX31855) 9. Kurs Arduino odcinek 8 - wykorzystanie czujnika dwutlenku węgla (MH-Z19) 10. Kurs Arduino odcinek 9 - wykorzystanie modułów do odmierzania czasu 11. Kurs Arduino odcinek 10 - wykorzystanie czujników temperatury (DS18B20) 12. Kurs Arduino odcinek 11 - budowa loggera (rejestratora danych) 13. Kurs Arduino odcinek 12 - rejestracja i prezentacja danych oraz obsługa karty SD 14. Kurs Arduino odcinek 13 - rejestracja danych (wykorzystanie modułu OpenLog) 15. Kurs Arduino odcinek 14 - czym zastąpić płytkę Arduino Uno? 16. Kurs Arduino odcinek 15 - budowa rejestratora (chiński klon Arduino Pro Mini) 17. Kurs Arduino odcinek 16 - problemy z kwadratowym modułem Strong 18. Kurs Arduino odcinek 17 - czujniki do pomiaru wilgotności gleby (instalacja, konfiguracja) 19. Kurs Arduino odcinek 18 - protokół MODBUS i łącze RS-485 20. Kurs Arduino odcinek 19 - wyświetlacze od podstaw (matrycowe, 7-segmentowe, MAX7219) 21. Kurs Arduino odcinek 20a - wyświetlacze matrycowe i biblioteki MD_MAX 22. Kurs Arduino odcinek 20b - przyciski i biblioteki do obsługi wyświetlaczy 23. Kurs Arduino odcinek 20c - biblioteki do obsługi wyświetlaczy graficznych 24. Kurs Arduino odcinek 21 - moduł wyświetlacza OLED 25. Kurs Arduino odcinek 22 - moduł wyświetlacza 1,3 cala 26. Kurs Arduino odcinek 23 - przygotowanie bitmap do wyświetlania 27. Kurs Arduino odcinek 24 - omówienie fontu podstawowego (Adafruit GFX) 28. Kurs Arduino odcinek 25 - font podstawowy biblioteki Adafruit GFX 29. Kurs Arduino odcinek 26 - wykorzystanie bitmapowych fontów GFX 30. Kurs Arduino odcinek 27 - polskie znaki w glcdfont.c 31. Kurs Arduino odcinek 28 - zmiana ulepszonych fontów GFX

Wiemy od dawna, że podstawowe znaki: litery, cyfry i niektóre symbole, wyświetlamy za pomocą kodów ASCII. Ściślej biorąc, te podstawowe znaki drukowalne mają kody ASCII od 32 do 126. Wiemy też, że kody ASCII 1...31 pierwotnie były kodami sterującymi dla elektromechanicznych dalekopisów. W Adafruit GFX spośród nich wykorzystujemy tylko dwa: kod numer 10 – nowa linia oraz niekiedy wraz z nim kod nr 13 – powrót karetki.

Pozostałe kody sterujące można wykorzystać, by kodowały jakieś symbole. I już wiemy, że tak jest. Można też wykorzystywać kody powyżej kodu ASCII, czyli z zakresu 128...255. Już wcześniej w cyklu „Wokół Arduino” omawialiśmy nawet sprawę stron kodowych (code page – CP).

I właśnie font podstawowy w bibliotece Adafruit GFX zawiera znaki strony kodowej CP437, znanej od roku 1981, zastosowanej w pierwszych komputerach IBM PC w pierwszej wersji systemu operacyjnego MS-DOS (1.0). Tematyka fontów jest skomplikowana. Na rysunku 1 znaki strony kodowej CP437 wypisane są wciąż bardzo popularnym fontem Arial. Pod symbolami podane są też numery tych symboli w Unikodzie.

Rys.1 Znaki strony kodowej CP437 wypisane są fontem Arial. Pod symbolami podano numery tych symboli w Unikodzie

Rysunek 2 pokazuje znaki strony kodowej CP437 jako prosty font bitmapowy na ekranie (konsoli) prymitywnego komputera.

Natomiast Rysunek 3 przedstawia znaki zawarte w foncie podstawowym z pliku glcdfont.c biblioteki Adafruit GFX. Wprawdzie w poszczególnych fontach te same znaki strony kodowej i Unikodu mogą różnić się i różnią wyglądem. Niemniej wyraźnie widać, że w Adafruit GFX też mamy znaki strony kodowej CP437.

Rys.2 Znaki strony kodowej CP437 jako prosty font bitmapowy na ekranie (konsoli) prymitywnego komputera

Tak, ale.. Na rysunku 3 żółtymi strzałkami zaznaczone są zastępcze znaki o numerach 10 i 13. Wiemy już, że biblioteka Adafruit GFX nie chce ich drukować i nie drukuje, a na potrzeby naszych rozważań w poprzednim odcinku stworzyliśmy programik, który zamiast nich zastępczo wydrukował literkę „x”. Jednak z podanego wcześniej opisu, jak działa wyświetlanie znaków, wynika, że plik glcdfont.c też musi zawierać po pięć bajtów dla kodów 10 i 13. Okazuje się, że nie są to wcale „bajty puste”:

(...)
0x00, 0x18, 0x24, 0x18, 0x00, //9
0xFF, 0xE7, 0xDB, 0xE7, 0xFF, //10
0x30, 0x48, 0x3A, 0x06, 0x0E, //11
0x26, 0x29, 0x79, 0x29, 0x26, //12
0x40, 0x7F, 0x05, 0x05, 0x07, //13
0x40, 0x7F, 0x05, 0x25, 0x3F, //14
(...)

Fotografia 4 prezentuje wynik „ręcznego dekodowania” znaków o numerach 10 i 13. To tylko ciekawostka, bowiem znaków tych nie da się w prosty sposób wykorzystać. Ważniejszy jest inny szczegół, zaznaczony na rysunku 3 czerwonymi strzałkami.

Rys.3 Znaki zawarte w foncie podstawowym z pliku glcdfont.c biblioteki Adafruit GFX

Najpierw zwróć uwagę na prawy dolny róg. Ostatni symbol w samym rogu ma numer – kod 255 i nie jest wyświetlany żaden symbol.

Prawidłowo, bo jest to albo rozkaz skasowania poprzedniego znaku (DEL), albo spacja twarda, niełamiąca (NBSP = non-breaking space). Problem jest z poprzednim symbolem o numerze 254. Na rysunku 3 pole jest puste, a według rysunków 1 i 2 powinien tam być „kwadracik”. Ten „kwadracik” na rysunku 3 jest, ale w polu o kodzie 253. Analogicznie wcześniejsze znaki! Mamy przesunięcie o jeden numer, ale nie w całej tabeli znaków. Przesunięcie zaczyna się przy kodzie numer 176, czyli szesnastkowo B0. Na rysunku 3 mamy tu dwie kolejne czerwone strzałki.

Fot.4 Wynik „ręcznego dekodowania” znaków o numerach 10 i 13

Jak pokazują rysunki 1 i 2, kody 176, 177 i 178 (0xB0, 0xB1, 0xB2) powinny zapełnić pole pikselami, które dadzą w sumie średnią jasność pola 25%, 50% i 75%. Na rysunku 3 brakuje symbolu o kodzie 176, a w polu o tym numerze wyświetlony jest symbol, który w CP437 ma numer 177. Przesunięcie wynika z braku symbolu 176 i dotyczy tylko kodów o większym numerze. Czyli pożytecznych symboli, w tym greckich liter, znaków matematycznych i innych, w tym często wykorzystywanego symbolu stopnia.

Nie tak miało być! Jest to wynik, a ściślej echo ewidentnej pomyłki. Strona kodowa CP437 od roku 1981 jednoznacznie określa, jakie mają być symbole o numerach 176 i wyższych. Jednak ktoś, kto kiedyś przygotowywał zawartość pliku glcdfont.c, popełnił ewidentny błąd i nie umieścił w nim pięciu bajtów, które powinny rysować symbol o kodzie 176.

Pomyłkę tę odkryto po dość długim czasie, gdy powstało mnóstwo programów (szkiców) wykorzystujących ten błędnie zdefiniowany font i wspomniane bardzo pożyteczne „wyższe” kody o błędnych numerach. Jak widać z rysunku 3, błędny kod zawierał mniej znaków. Jednak aktualny plik glcdfont.c zawiera już wszystkie znaki:

(...)
0x55, 0x00, 0x55, 0x00, 0x55,
//#176 (25% block) missing in old
code
0xAA, 0x55, 0xAA, 0x55, 0xAA,
// #177 50% block
0xFF, 0x55, 0xFF, 0x55, 0xFF,
// #178 75% block
(...)

Tak! „Ręczne zdekodowanie” symboli o numerach 176, 177, 178 daje efekt widoczny na rysunku 5! Kod 176 i wszystkie wyższe są więc prawidłowo zdefiniowane w aktualnym pliku glcdfont.c. Dlaczego więc są błędnie wyświetlane?

Rys.5 Efekt recznego dekodowania symboli o numerach 176, 177, 178

To proste: dla kompatybilności z wcześniejszymi programami – szkicami! Przewidziano natomiast prosty sposób korzystania z prawidłowych kodów CP437. Podczas kompilacji program sprawdza stan wewnętrznej zmiennej _cp437. Jeżeli ma ona wartość logiczną true, wykorzystywane są prawidłowe kody CP437. Domyślnie ma ona wartość false, więc wykorzystywany jest stary, błędny sposób z przesunięciem. W pliku Adafruit_GFX.cpp w definicji metody drawChar() sprawdzany jest stan tej zmiennej, jak pokazuje szkic 1.

void Adafruit_GFX::drawChar(x, y, c, color, bg, size_x, size_y) {
if(!gfxFont) { // 'Classic' built-in font
if((x >= _width) || // Clip right
(y >= _height) || // Clip bottom
((x + 6 * size_x - 1) < 0) || // Clip left
((y + 8 * size_y - 1) < 0)) // Clip top
return;
if(!_cp437 && (c >= 176)) c++; //Handle 'classic' charset behavior
startWrite();\
for(int8_t i=0; i<5; i++ ) { // Char bitmap = 5 columns
(...) // rysowanie znaku

Jeżeli zmienna _cp437 ma wartość false (domyślnie) i wyświetlany ma być symbol o kodzie 176 lub wyższym, to o 1 zwiększany jest kod – liczba w zmiennej c. Realizuje to linia

if(!_cp437 && (c >= 176)) c++;

Aby to zadziałało, w bibliotece (w pliku Adafruit_GFX.h) przewidziano funkcję-metodę (tak!) o nazwie .cp437(), która ustawi wewnętrzną zmienną (pole) _cp437, jak widać na szkicu 2.

/*! @brief Enable (or disable) Code Page Fot. 6
437-compatible charset. There was an
error in glcdfont.c for the longest time
-- one character (#176, the 'light shade'
block) was missing -- this threw off the
index of every character that followed
it. But a TON of code has been written
with the erroneous character indices. By
default, the library uses the original
'wrong' behavior and old sketches will
still work. Pass 'true' to this function
to use correct CP437 character values in
your code.
@param x true = enable (new behavior),
@param x false = disable (old behavior)
*/
/***************************************/
void cp437(boolean x=true) { _cp437 = x; }

Jeżeli więc we wcześniejszym szkicu A2301.ino w funkcji setup() dodamy instrukcję:

wysw.cp437(1);

to wtedy na wyświetlaczu zobaczymy prawidłową „wyższą” część strony CP437, jak pokazuje fotografia 6. Zmodyfikowany szkic dostępny jest w Elportalu jako A2401.ino (tylko dla SH1106, ale możesz to samodzielnie zmienić, kopiując fragmenty szkicu A2301.ino).

Fot. 6 Prawidłowa „wyższa” część strony CP437

Polskie litery - modyfikacja Adafruit GFX

Wiedząc, jak funkcjonuje podstawowy font biblioteki Adafruit GFX, możemy zmodyfikować plik glcdfont.c i dodać tam „polskie litery”. Moglibyśmy zrobić to teraz, ale proponuję, żebyś potraktował to jako zadanie domowe. Spróbuj uzyskać na wyświetlaczu polskie litery. Zadanie nie jest wcale trudne i można je zrealizować na wiele sposobów.

Wrócimy do tego później, a na razie spróbuj sam. A my w następnym odcinku omówimy ulepszone fonty Adafruit GFX.

Do pobrania
Download icon Materiały do: Kurs Arduino odcinek 25 - font podstawowy biblioteki Adafruit GFX
1. Kurs Arduino: wprowadzenie 2. Kurs Arduino odcinek 1 - co to jest i jak zacząć? (sprzęt, schematy, programowanie) 3. Kurs Arduino odcinek 2 - termometry: 'diodowy', pokojowy oraz 'scalony' analogowy 4. Kurs Arduino odcinek 3 - moduł wyświetlacza LCD (HD44780) 5. Kurs Arduino odcinek 4 - czujnik BME280 (pomiar ciśnienia, wilgotności i temperatury) 6. Kurs Arduino odcinek 5 - biblioteki do trzyfunkcyjnego czujnika BME280 7. Kurs Arduino odcinek 6 - wykorzystanie łącza I2C (TWI) 8. Kurs Arduino odcinek 7 - wykorzystanie łącza SPI (karty pamięci, MAX31865, MAX31855) 9. Kurs Arduino odcinek 8 - wykorzystanie czujnika dwutlenku węgla (MH-Z19) 10. Kurs Arduino odcinek 9 - wykorzystanie modułów do odmierzania czasu 11. Kurs Arduino odcinek 10 - wykorzystanie czujników temperatury (DS18B20) 12. Kurs Arduino odcinek 11 - budowa loggera (rejestratora danych) 13. Kurs Arduino odcinek 12 - rejestracja i prezentacja danych oraz obsługa karty SD 14. Kurs Arduino odcinek 13 - rejestracja danych (wykorzystanie modułu OpenLog) 15. Kurs Arduino odcinek 14 - czym zastąpić płytkę Arduino Uno? 16. Kurs Arduino odcinek 15 - budowa rejestratora (chiński klon Arduino Pro Mini) 17. Kurs Arduino odcinek 16 - problemy z kwadratowym modułem Strong 18. Kurs Arduino odcinek 17 - czujniki do pomiaru wilgotności gleby (instalacja, konfiguracja) 19. Kurs Arduino odcinek 18 - protokół MODBUS i łącze RS-485 20. Kurs Arduino odcinek 19 - wyświetlacze od podstaw (matrycowe, 7-segmentowe, MAX7219) 21. Kurs Arduino odcinek 20a - wyświetlacze matrycowe i biblioteki MD_MAX 22. Kurs Arduino odcinek 20b - przyciski i biblioteki do obsługi wyświetlaczy 23. Kurs Arduino odcinek 20c - biblioteki do obsługi wyświetlaczy graficznych 24. Kurs Arduino odcinek 21 - moduł wyświetlacza OLED 25. Kurs Arduino odcinek 22 - moduł wyświetlacza 1,3 cala 26. Kurs Arduino odcinek 23 - przygotowanie bitmap do wyświetlania 27. Kurs Arduino odcinek 24 - omówienie fontu podstawowego (Adafruit GFX) 28. Kurs Arduino odcinek 25 - font podstawowy biblioteki Adafruit GFX 29. Kurs Arduino odcinek 26 - wykorzystanie bitmapowych fontów GFX 30. Kurs Arduino odcinek 27 - polskie znaki w glcdfont.c 31. Kurs Arduino odcinek 28 - zmiana ulepszonych fontów GFX
Tematyka materiału: fonty, kody ASCII
AUTOR
Źródło
Elektronika dla Wszystkich czerwiec 2020
Udostępnij
UK Logo