Русификация библиотеки openGLCD для Arduino

Написание русскоязычного текста на графических дисплеях с контролером ks0108 или его аналогами все еще представляет существенные трудности. Библиотека openGLCD, которую рекомендуют официальные сайты Arduino, в оригинальной комплектации последней на данный момент версии не содержит никаких кириллических шрифтов, кроме шрифта cp437font8×8. На практике он малопригоден, потому что в русскоязычной части поддерживает кодировку Win-1251. Следовательно, чтобы выводить символы таким шрифтом, их нужно либо вставлять в текст восьмеричными или шестнадцатеричными кодами (и при этом остаются неясности со строчной буквой «я», как указывает в комментарии сам создатель шрифта), либо все равно писать отдельную функцию перекодировки, как это сделал arduinec для библиотеки Adafruit-GFX.

Кроме всего прочего, cp437font8×8 крупноват для экранчиков 128×64 точки. Оптимальным размером шрифта для вспомогательных надписей на таком дисплее остается System5×7. Мы здесь сосредоточимся на русификации именно системного шрифта, хотя читатель может по этому образцу самостоятельно русифицировать и любой другой шрифт (особенно, если у него экран побольше).

А в чем проблема?


Для начала давайте вникнем в корни проблемы. Среда Arduino IDE — это обычный текстовый редактор Windows, который работает в универсальной кодировке UTF-8, как любой другой в современных версиях Windows (Блокнот, например). UTF-8 представляет собой экономичную версию многобайтовой кодировки UNICODE. В UTF-8 англоязычные символы, цифры, точки-запятые-скобки и всякие прочие значки представлены одним байтом, совпадающим со стандартной кодировкой ASCII. Поэтому их представление в коде скетча не представляет никаких трудностей: строка англоязычных символов после компиляции передается в загружаемый hex-файл без изменений и оказывается понятна 8-разрядному контролеру, как говорится, «без перевода».

В процессе этого преобразования каждый символ, как и в любой программе на любом языке программирования, представляется непосредственно в виде его кода, то есть порядкового номера в таблице шрифта, из которой программа извлекает графическое начертание соответствующего символа. В файле шрифта System5×7.h библиотеки openGLCD количество символов представлено переменной font_Char_Count типа uint8_t, то есть не может превышать величины одного байта. Поэтому кириллические символы, которые в UTF-8 занимают два байта, не могут быть переданы контроллеру обычным образом.

Предыдущие попытки решения
Заметим, что это было не всегда так. Версии Arduino 1.0.x (и, по слухам, 1.6.0) усекали двухбайтовый код до однобайтового, банально отбрасывая старший байт (который для кириллицы, как следует из таблицы UTF-8 по ссылке выше, равен либо 0xD0, либо 0xD1). Потому для доработки шрифта в этих версиях среды годится старая библиотека GLCD v3, в которой массив шрифта просто дополнялся символами кириллических букв так, чтобы их позиции совпадали с младшим байтом кодировки UTF-8 (байты с 0×80 по 0xBF). Более подробно такая модернизация описана в статье автора «Работа с текстом на графическом дисплее». Повторяю — для нее нужна одна из версий Arduino IDE 1.0.x в совокупности с библиотекой GLCD v3, а не их более современные варианты.

В новых версиях Arduino IDE стало все сложнее. Библиотека решительно отказывается понимать двухбайтовые номера символов, выводя вместо них пустое место, потому простой переделкой шрифта тут не обойдешься. Приходится дополнить его функцией перекодировки двухбайтовых символов в однобайтовые.


Решение


Автор не стал лезть в недра библиотечных функций, а написал для openGLCD надстройку в виде функции outstr (), которая перебирает все элементы входной строки, пропуская их через оператор выбора Switch. Он вылавливает из строки кириллические символы и заменяет их однобайтовыми кодами, соответствующими модернизированному файлу шрифта System5×7R.h.
Например, для заглавной русской буквы «Ф» строка замены будет такой:
case 'Ф': GLCD.PutChar (0xA4); break;
Здесь 0xA4 — младший байт кодировки буквы «Ф» в UTF-8 (см. ссылку выше). В соответствии с этой кодировкой составлен новый файл шрифта System5×7R.h. В принципе при таком подходе в шрифте можно применять любую кодировку русских символов и любых других глифов, которые вздумается вставить в шрифт. Лишь бы их общее количество не превышало 128 штук: от начала таблицы до символа 0×7F (127 — последний символ стандартной таблицы ASCII) целесообразно оставить шрифт в неприкосновенности.

Правда, пару вольностей с таблицей ASCII я себе разрешил. Дело в том, что в оригинальном шрифте System5×7.h значок градуса вынесен в последнюю строку таблицы, занимая символ 0×80, который у нас уже относится к кириллице. Чтобы не нарушать порядок построения кириллической таблицы в соответствии с UTF-8, эта строка выброшена из файла. А значок градуса пристроен вместо символа ASCII »~» (номер 0×7E), который в шрифте все равно не использовался по назначению. Зато такая замена позволяет вводить значок градуса в тексте скетча прямо с клавиатуры в виде символа »~».

Еще одна вольность связана с тем, что автор на дух не переносит перечеркнутый ноль — архаику времен АЦПУ и монохромных текстовых дисплеев. Потому ноль в модернизированном шрифте заменен на глиф буквы «О». Те, кто придерживается пуристических принципов, могут просто удалить в файле шрифта System5×7R.h эту вставку (старый глиф перечеркнутого нуля там оставлен закомментированным, его код 0×30).

В модернизированной библиотеке openGLCD, которую вы можете скачать по ссылке в конце статьи, внесено еще одно исправление — изменен порядок подключения выводов для дисплеев с контроллером ks0108. Почему автором библиотеки выбран такой порядок (см. таблицу по ссылке на официальном сайте Arduino), неизвестно. В модернизированном варианте подключение дисплея (для примера выбран популярный MT-12864J) осуществляется согласно вот такой схеме:

Схема подключения MT-12864J
image


Переменный резистор R1 здесь подключается согласно рекомендации производителя, а резистор R2 служит для ограничения тока подсветки, если она подключена не к напряжению 5 В, а прямо ко входному источнику питания (вывод Vin Arduino) с более высоким напряжением.
Пример вывода на дисплей MT-12864J русского алфавита вперемешку с латинским, а также цифр и значка градуса, представлен на фото:

image
Текст скетча для этого примера:

Текст скетча с выводом русского алфавита
#include  //подключим библиотеку
#include  //файл с функцией вывода русских букв
#include  //файл с кодами русских букв

void setup() {
      GLCD.Init(); //инициализация
      GLCD.ClearScreen();
      }

void loop()
      {
      GLCD.SelectFont(System5x7R);  //выбираем шрифт
      GLCD.CursorTo(0,0); //установим курсор в начальную позицию 
      //выводим смешанные англо-русские строки: 
      outstr("ABC АВГДЕЖЗИКЛМНОП\n");
      outstr("PRQ РСТУФХЦЧШЩЪЫЬЭЮЯ\n");
      outstr("nts абвгдежзийклмноп\n");
      outstr("xyz рстуфхцчшщъыьэюя\n");
      GLCD.println("1234567890");
      GLCD.CursorTo(19,4); //установим курсор в предпоследнюю позицию 5-й строки 
      GLCD.print("~C"); //градус С 
      GLCD.println("@;/.,|<>()=-_{}\"'");
            GLCD.CursorTo(4,7); //установим курсор в поз 4 строки 8
      GLCD.print("MT-12864J");
      }


Так как файлы с функцией outstr.h и шрифтом System5×7R.h размещены в корневом каталоге модернизированной библиотеки, то на них надо размещать отдельные ссылки в начале скетча с помощью директивы #include. Для англоязычных надписей удобно по-прежнему пользоваться стандартными функциями println/print, а вот при необходимости перевода строки в русском тексте необходимо явно указывать символ »\n».

Подправленный вариант библиотеки вы можете скачать здесь. Распакованную библиотеку (папку openGLCD) следует поместить в папку Arduino\libraries, как обычно. Пример скетча находится в том же архиве отдельно (в не в папке Examples библиотеки). Подключение дисплея с контроллером ks0108 в соответствии с этой библиотекой отражено на схеме выше. Если вам захочется дополнительно изменить порядок подключения выводов, то разыщите в папке Arduino\libraries\openGLCD\config\ks0108 файл PinConfig_ks0108-Uno.h и отредактируйте в нем строки под заголовком «Data pin definitions» и далее, ориентируясь на исправления автора.

В следующей публикации мы попытаемся разобраться с русификацией строчных дисплеев. Как вы увидите, с ними все одновременно и проще и сложнее.

© Geektimes