Русификация OLED и TFT дисплеев. Дополнение
Не так давно, на сайте была размещена статья о выводе русских символов на различные типы дисплеев. В ней были рассмотрены различные способы решения данной проблемы. В частности, для вывода русских букв на OLED и TFT дисплеи предлагалось использовать модифицированный системный шрифт glcdfont.c библиотек TFT eSPI и Adafruit GFX совместно с функцией utf8rus(). Данный способ вполне работоспособен, хотя и не без некоторых недостатков, которые были описаны в статье. Но, буквально вчера, узнал о новом методе, схожем по реализации, но гораздо более простом в использовании. О нем и будет рассказано данной статье.
Введение
Данный метод вывода русских символов на экран подходит для практически любых дисплеев, с которыми умеют работать библиотеки Adafruit GFX и TFT_eSPI. Авторство принадлежит Вячеславу Загайнову, который выложил модифицированную версию библиотеки TFT_eSPI c русским шрифтом в своем Telegram канале SZLab. Главное отличие его модификации glcdfont.c от той, которая упоминалась в моей предыдущей статье, в том, что русские символы сразу хранятся в кодировке UTF-8. Поэтому для вывода их на экран в Arduino IDE достаточно стандартных функций print() и println(), без дополнительных прослоек типа изменения кодировки UTF-8 в CP-1251. Я думаю плюсы такого метода очевидны. Скачать модифицированный glcdfont.c можно здесь.
Если же вас интересует техническая сторона модификации экранного шрифта, да и вообще как вообще реализован вывод текста в библиотеках TFT_eSPI и Adafruit GFX, то самое время переходить к следующему разделу.
Структура файла glcdfont.c
Файл glcdfont.c - это файл исходного кода на языке C, который содержит данные для отображения символов на графических дисплеях, использующих стандартный набор символов ASCII. Он содержит таблицу битовых карт символов, которые можно использовать для вывода текста на графический дисплей.
В библиотеках Adafruit GFX и TFT_eSPI именно он используется по умолчанию для вывода текстовой информации на экран
Каждый символ в таблице представлен в виде битовой маски размером 5x7 пикселей. Для отображения символа на графическом дисплее, битовая маска символа обычно переносится на дисплей путем установки или сброса соответствующих пикселей.
Структура файла
glcdfont.c состоит из следующих элементов:
Заголовок, который содержит необходимые для работы функции данные.
// Original Adafruit_GFX 5x7 font
#ifndef FONT5X7_H
#define FONT5X7_H
// Standard ASCII 5x7 font
Определение массива шрифта - определяется массив данных, представляющий битовый шрифт.
static const unsigned char font[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00,
0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
............................
0x00, 0x3C, 0x3C, 0x3C, 0x3C,
0x00, 0x00, 0x00, 0x00, 0x00
};
#endif // FONT5X7_H
Представление символов в массиве
Теперь попробую подробно объяснить как же из всего этого набора байт формируется изображение на экране вашего дисплея. Это довольно проще чем кажется на первый взгляд.
Как мы знаем, символы данного шрифта имеют размер 5x7 пикселей. Если вы внимательно посмотрите на запись массива, то без труда заметите, что он сгруппирован по 5 элементов на одну строку. И ширина символа в пикселях тоже равна 5. Уже прослеживается определённая закономерность. Но все равно пока ничего не понятно.
Теперь, давайте произвольно возьмем, любую строку из 5 элементов данного массива. Например эту:
0x7C, 0x12, 0x11, 0x12, 0x7C,
Переведем значение каждого ее элемента из шестнадцатеричной в двоичную систему счисления. Получим в итоге следующее
01111100, 00010010, 00010001, 00010010, 01111100
Предположим, что каждый из 5 элементов строки отвечает за отрисовку одного из 5 столбцов пикселей каждого символа, а единицы и нули в двоичной записи числа за отвечают за отрисовку каждого пикселя в столбце. Где 1 означает зажженный пиксель, а 0 погашенный . Запишем все более наглядно в виде таблицы сверху вниз от младшего разряда к старшему, закрашивая зеленым цветом ячейки с 1 и красным с 0:
0 | 0 | 1 | 0 | 0 |
0 | 1 | 0 | 1 | 0 |
1 | 0 | 0 | 0 | 1 |
1 | 0 | 0 | 0 | 1 |
1 | 1 | 1 | 1 | 1 |
1 | 0 | 0 | 0 | 1 |
1 | 0 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 0 |
Как видите, на выходе у нас получилась буква А. Проведя подобные преобразования и с другими элементами массива, можно таким же образом отобразить и другие символы, либо внести изменение в начертание уже имеющихся.
Как библиотека работает glcdfont.c
Со структурой файла мы разобрались. Теперь осталось ответить лишь на один вопрос. Как установить соответствие символа выводимого на экран его адресу в битовой карте шрифта? Очень просто.
Шрифт содержит 127 символов. Порядок и набор символов полностью соответствует кодировке ASCII. Это буквы латинского алфавита, цифры, и некоторый набор спецсимволов. В графическом представлении шрифт выглядит так:
ASCII является стандартом, поэтому в большинстве других кодировок этот набор и его коды полностью совпадают. Arduino IDE для вывода текста использует кодировку UTF-8. То есть набор символов в строке, преобразовывается в коды UTF-8 этих символов и далее этот код сопоставляется его начертанию в шрифте для вывода на экран. Так как символы в шрифте фиксированной ширины, то чтобы получить адрес элемента массива, который соответствует полученному коду символа достаточно перемножить код и ширину шрифта.
Например, чтобы вывести на дисплей латинскую букву А, нужно узнать ее UTF-8 код (65 в десятичной системе счисления) и умножить на ширину шрифта. В данном случае 5 пикселей. Искомый адрес в итоге будет 325. То есть начиная с 325 элемента расположена битовая маска для отрисовки символа А.
Добавление дополнительных символов в шрифт
Зная структуру файла шрифта glcdfont.c и как библиотека работает с ним, можно добавить в шрифт и свои символы. Просто узнаем его код в UTF-8 и располагаем элементы массива по нужному смещению. Таким же образом реализован вывод русских букв и в модификации glcdfont.c от Вячеслава Загайнова. Первые 127 символов остались неизменными. Далее он заполнил массив нулями до элемента под номером 1040, соответствующим коду заглавной русской буквы А в Юникоде. После чего добавил в массив элементы с недостающими русскими буквами. Таким образом, логика работы библиотеки совершенно не поменялась. Она все также получает на входе код символа, умножает его на 5 (ширина символа), получает адрес элемента массива с инструкциями для отрисовки и выводит его на экран.
В графическом представлении glcdfont.c теперь выглядит так:
Таким же точно образом можно добавить и другие символы в данный шрифт.
Заключение
В данной статье мы разобрали еще один способ вывода русских символов на экран. Этот метод вывода подходит для широкого спектра дисплеев и не требует дополнительных прослоек для корректного отображения русских символов. Также можно отметить, что модификация glcdfont.c с хранением русских символов в кодировке UTF-8 является усовершенствованием, которое значительно облегчает процесс вывода русского текста на экран в Arduino IDE.