Русификация RGB LCD Shield for Arduino 65K color KIT

Мой приход в мир Ардуино не был оригинальным — прочитал, заинтересовался, купил,
попробовал и… подсел. Тысячный раз читать об этом никому не интересно (хотя,
должен признаться, фотографии процесса распаковывания первой заветной коробочки
есть и у меня). Поэтому перейдем к делу.

Цветной дисплей для Ардуино


Среди доступного сейчас великого разнообразия готовых модулей расширения (или, как их часто называют, шилдов) для ардуино-подобных контроллеров имеется (в виде набора для домашней сборки) неплохой RGB-дисплей размером 128*128 точек и 64К цветовой палитрой. Производитель называет его довольно длинно — «RGB LCD Shield for Arduino 65K color KIT» — и поддерживает программно. Подлкючаемая библиотека позволяет скрыть от пользователя внутреннюю кухню управления контроллером дисплея, предоставляя простые функции типа drawPixel, drawLine, drawCircle и т.п. Быстродействия дисплейчика хватает даже на простую движущуюся графику. Имеется также функция вывода строки текста print, которая умеет автоматически выравнивать строку по центру или по краю.
Короче говоря, полный джентельменский набор. За одним досадным исключением — не поддерживается кириллица. Но ведь открытая платформа на то и открыта, чтобы можно было что-нибудь улучшить.

Изучаем библиотеку


К счастью подключаемая библиотека не сложна, и легко обнаружить, что для вывода текста используется растровый шрифт размером 6*9 пикселей. Но при этом в структуре данных библиотеки описаны графические образы размером только 5*9, а шестой столбец всегда пустой (т.е. цвета фона) и просто дорисовывается в момент вывода символа на экран. Надо сказать, что это вполне разумно, поскольку в большинстве растровых шрифтов только несколько символов псевдографики (которые здесь совершенно не нужны) используют всю ширину матрицы, а буквы на один столбец уже (тем самым создается межсимвольный интервал). Поэтому тратить небольшие ресурсы контроллера на хранение заведомо пустых столбцов графических образов символов очевидно не нужно.
Графические образы хранятся в переменной с именем Font5x9Mono, технически являющейся массивом байт(записанных в шестнадцатеричной форме), а логически — непрерывной цепочкой бит. Каждые 45 бит этой цепочки представляют собой один символ (т.е. 9 строк по 5 пикселей). Значение бита 0 означает закраску цветом фона, 1 — цветом символа.
Выглядит это примерно так:
byte Font5x9Mono[535] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x42, 0x10, 0x04,
0x00, 0x14, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x05, 0x7D, 0x4A,
0xFA, 0x80, 0x02, 0x3E, 0x8E, 0x2F, 0x88, 0x00, 0x02, 0x22,
и т.д.
}

Функция библиотеки print() принимает на входе строку символов, которую нужно вывести на экран, и в свою очередь вызывает для каждого символа функцию printChar. Последняя, вычислив нужное смещение от начала массива Font5x9Mono, просто выводит на экран 45 пикселей нужного цвета в нужном месте. Теперь становится очевидным, что для получения вместо символов латиницы символов кириллицы (или вообще любых других) достаточно сформировать нужным образом массив Font5x9Mono. Можно, например, нарисовать буквы на бумаге в клеточку, потом закодировать их строкой нулей и единиц, потом преобразовать каждый байт этой строки в шестрадцатеричное число… Только ведь сущесвтует уже масса готовых растровых шрифтов, в т.ч. и нужного нам размера 6*9. Разумнее использовать их.

Вносим изменения


Тут настала пора сказать, что дело происходит в Linux, и пользы в дальнейших рассуждениях для приверженцев продуктов от MS, возможно, не очень много. Но идея уже ясна, и её реализация может быть любой, в т.ч. и под Windows. А я продолжу про реализацию идеи в среде Linux.
Возьмем любой подходящий шрифт (а обычно их установлено и по умолчанию в достатке). Мне первым подвернулся 6x9-KOI8-R.pcf. Хотя, должен сознаться, что не совсем случайно именно KOI8. По-правильному, конечно, нужно было бы делать так, чтобы при написании скетча для Ардуино можно было вводить текст (который передается функции print) сразу по-русски. Но тогда пришлось бы делать различные преобразования, а это дополнительная трата ресурсов контроллера. Не думаю, что это сильно нужно. Ведь не текстовый процессор собираемся программировать на экранчике 128*128. Для вывода пары слов достаточно транслитерации. А транслитерация, очевидно, будет удобна именно в KOI8.
Шрифт в формате pcf преобразовываем в формат bdf. Для этого есть готовая улитилита с названием (кто бы мог подумать!) pcf2bdf. Формат bdf хорош тем, что это просто текст с очевидной структурой, которым легко манипулировать в скриптах. Посмотреть графические образы символов шрифта (и при желании подредактировать) можно редактором gbdfed.
А теперь берем самодельный скрипт (текст ниже) и выбираем из bdf-файла строки с шестнадцатеричным описанием символов, преобразуя их в формат массива Font5x9Mono. При запуске скрипта в качестве аргумента ему передается имя файла шрифта.
Скрипт может не очень хорош, поскольку я все же программист-любитель, но функцию свою выполняет.
#!/usr/bin/perl
#
%hex1=(«0» => «0000»,«1» => «0001»,«2» => «0010»,«3» => «0011»,
«4» => «0100»,«5» => «0101»,«6» => «0110»,«7» => «0111»,
«8» => «1000»,«9» => «1001»,«A» => «1010»,«B» => «1011»,
«C» => «1100»,«D» => «1101»,«E» => «1110»,«F» => «1111»);

%hex2=(«0» => «0»,«1» => «0»,«2» => «0»,«3» => «0»,
«4» => «0»,«5» => «0»,«6» => «0»,«7» => «0»,
«8» => «1»,«9» => «1»,«A» => «1»,«B» => «1»,
«C» => «1»,«D» => «1»,«E» => «1»,«F» => «1»);

%hex3=(«0000» => «0»,«0001» => «1»,«0010» => «2»,«0011» => «3»,
«0100» => «4»,«0101» => «5»,«0110» => «6»,«0111» => «7»,
«1000» => «8»,«1001» => «9»,«1010» => «A»,«1011» => «B»,
«1100» => «C»,«1101» => «D»,«1110» => «E»,«1111» => «F»);

$bin="";

$file=$ARGV[0];
$sym_num=0;
$i=0;
$j=0;
open (F,"$file");
while () {
$_ =~ s/\n//;
$str=$_;
if ($str =~ s/^(ENCODING[^0-9]*)([0-9]*)/$2/) {$sym_num=$str;$j++};
if ((($sym_num >= 32)&&($sym_num <= 63))||(($sym_num >= 192)&&($sym_num <= 255))) {
if ($_ =~ s/^([0-9,A-F])([0-9,A-F])$/$hex1{$1}$hex2{$2}/) {
$i++;
$bin = $bin.$_;
};
};
};
close (F);
$bin =~ s/([0-1]{4})([0-1]{4})/0x$hex3{$1}$hex3{$2}, /g;
$bin =~ s/(.{60})/$1\n/g;
print $bin;

Числа в строке if ((($sym_num >= 32)&&($sym_num <= 63))||(($sym_num >= 192)&&($sym_num <= 255))) означают, что из всего файла выбраны будут только символы с 32 по 63 и со 192 по 255. Полученный на выходе текст вставляем на место прежнего значения массива Font5x9Mono. Обратите внимание, что размер оригинального массива 535 байт, а нового 540, и нужно соответственно изменить объявление массива. Теперь пишем тестовый скетч.
#include <RGB_GLCD.h>

GLCD L;

void setup()
{
randomSeed(analogRead(0));
L.initLCD();
L.clrScr();
L.setContrast(64);
}

void loop ()
{
L.setColor(255,0,0);
L.drawRoundRect(0,0,127,127);
L.setColor(255,255,255);
L.print(«arduino PO-RUSSKI»,CENTER,60,0,0,0);
}

И получаем на экране текст по-русски. При этом помним, что строчные буквы в транслитерации станут заглавными в кириллическом варианте.

Улучшаем


Все хорошо, только теперь нет латиницы. Может оно и не нужно в каком-то конктретном скетче, но все же… Понятно, что тут не обойтись без двух массивов-описаний графических образов символов. А они оба у нас уже есть.
Объявим их в тексте библиотеки одновременно, назвав, например, Font5x9MonoC для кириллицы и Font5x9MonoL для латиницы. И несколько изменим функции print и printChar.
Обе объявим с дополнительным параметром lang:
void GLCD::print(char *st, byte x, byte y, char lang, byte r, byte g, byte b)
void GLCD::printChar(byte c, byte x, byte y, byte r, byte g, byte b, char lang)

Из первой будем вызвать вторую с этим дополнительным параметром, т.е. вместо оригинального вызова
printChar(*st++, x + (i*6), y, r, g, b);
использовать
printChar(*st++, x + (i*6), y, r, g, b, lang);
Внутри второй функции вместо
pf = &Font5x9MonoC[iFont];
использовать проверку дополнительного параметра lang
if (lang=='C')
pf = &Font5x9MonoC[iFont];
else
pf = &Font5x9MonoL[iFont];

Теперь в скетче можно выводить текст обоими наборами символов одновременно:
L.print(«arduino PO-RUSSKI»,CENTER,60,'C',0,0,0);
L.print(«ARDUINO on english»,CENTER,60,'L',0,0,0);
Далее можно заниматься оптимизацией. Например, в обоих массивах есть описание одинаковых небуквенных символов
(скобки, знаки препинания и пр.). Можно исколючить дублирования. Но это тема уже другй статьи.


0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.