Многие экспериментирующие с *duino сталкиваются с графическими монохромными LCD экранчиками на контроллерах ks0107/ks0108. Благо для их поддержки имеются несколько версий только официальной библиотеки.
Библиотечку можно взять здесь:
http://code.google.com/p/glcd-arduino/downloads/list
Вопросы подключения экранчика к контроллеру я рассматривать не буду, примеры есть и на этом сайте и на просторах интернета желающий найдет без труда. Кроме того, достаточно подробно расписано в документации к библиотеке.
Засада кроется в том, что без телодвижений, напряжения серого вещества русский текст из скетча ардуино никакими судьбами не выведешь. Ну нет в составе библиотеки русских шрифтов и все! Правда прилагается на страничке скачивания программулина для изобретения своих шрифтов и конвертации виндовых. 
Ну во-первых, написана она на JAVA, следовательно запустить ее тоже надо суметь, а во-вторых ну никак она у меня не захотела находить русские буквы в виндовых шрифтах, кракозябры и все!! 🙂
Лень, она конечно сильна, слов нет. Поэтому яндексу и гуглу были скормлены пара десятков запросов на различные вариации ключевых слов «русский шрифт GLCD». Ничего вразумительного, а тем более готового файла не нашлось. Может конечно не так искал….
Ну да ладно, делать нечего, пришлось напрягать пресловутое вещество.
Оговорюсь сразу: В данной заметке я рассмотрю создание (а точнее — модификацию) шрифта содержащего символы фиксированной ширины. Если тема кого заинтересует можно будет подобраться и к шрифту с символами переменной ширины.
Итак поехали!
Скачиваем и распаковываем библиотеку. Файлы с описанием шрифтов лежат в папочке «fonts». Открываем самый мелкий SystemFont5x7.h и пытаемся сделать ему трепанацию. Нас интересует какие параметры описывает этот файл, т.е. структура описания шрифта.
/*
 *
 * System5x7
 *
 Ну информация в комментах читаем!
 *
 * File Name           : System5x7.h  - это понятно!
 * Date                : 28 Oct 2008 - не интересно!!!
 * Font size in bytes  : 470  - поменяется!!
 * Font width          : 5 - вот первое важное - ширина символа
 * Font height         : 7 - его высота
 * Font first char     : 32 - хм.... это у нас код первого символа шрифта
                               (ASCII - пробел)
 * Font last char      : 127 - код последнего символа шрифта
 * Font used chars     : 94 - количество запользованных символов
 *
 * The font data are defined as  - опачки! описание структуры шрифта, разгребаем!!!
 *
 * struct _FONT_ {
 *     uint16_t   font_Size_in_Bytes_over_all_included_Size_it_self; -
ни что иное как размер шрифта в байтах включая все размеры самого себя (вроде тафтология
но выясняется что файл описания может содержать несколько размеров символов
или я чегой-то не так понял)
 *     uint8_t    font_Width_in_Pixel_for_fixed_drawing; -
ширина шрифта в пикселах для фиксированной отрисовки (не, но вот тут как-то не ясно,
 а как же шрифты с переменным размером?)
 *     uint8_t    font_Height_in_Pixel_for_all_characters; -
высота шрифта для всех символов (я так понимаю наибольшая)
 *     unit8_t    font_First_Char; -
код первого символа
 *     uint8_t    font_Char_Count;
количество символов (где-то это мы уже видели)
 *
 *     uint8_t    font_Char_Widths[font_Last_Char - font_First_Char +1];
 *                  // for each character the separate width in pixels,
 *                  // characters < 128 have an implicit virtual right empty row -
если переводить буквально то диапазон ширины символов ширина_последнего - ширина_первого + 1
добавляем межсимвольный интервал - виртуальный правый пустой столбец.
 *
 *     uint8_t    font_data[];
 *                  // bit field of all characters -
описание символов в виде битовой маски.
 */
#include <inttypes.h>
#include <avr/pgmspace.h>
#ifndef SYSTEM5x7_H
#define SYSTEM5x7_H
#define SYSTEM5x7_WIDTH 5
#define SYSTEM5x7_HEIGHT 7
/*
 * added to allow fontname to match header file name.
 * as well as keep the old name for backward compability
 */
#define SystemFont5x7 System5x7
static uint8_t System5x7[] PROGMEM = {
    0x0, 0x0, // size of zero indicates fixed width font, actual length is width * height -
нули здесь говорят о том что мы имеем шрифт фиксированного размера!!
    0x05, // width  -5 на
    0x07, // height -7 пикселей
    0x20, // first char    -HEX-код первого символа
    0x60, // char count    -количество буков в HEX!
    // Fixed width; char width table not used !!!!
АГА!!!! здесь должна располагаться таблица ширин символов отличающихся от базового размера
у нас в данном случае таких нет!
    // font data
    0x00, 0x00, 0x00, 0x00, 0x00,// (space) - пошло описалово в HEX-формате.
Ну вроде все достаточно ясно для практического использования:
размер символов строго 5х7 точек, межсимвольный интервал добавляется автоматом, последний использованный код 0x20+0x60 — 1 = 0x7F. Начиня с 0x80 можно куролесить свои битовые маски.
Конечно, желающие могут взять тетрадку в клеточку, карандашик, разметить знакоместа 5 на 7 клеточек, закрасить соответствующие и перевести в начале в бинарный код а потом в HEX. Круто!!
🙂 Только для начала надо интерпретировать по клеточкам коды символа 0х41, чтобы разобраться как библиотека отрисовывает символ по вертикали или по горизонтали.
Я воспользовался для этой цели найденной на просторе интернета программой, могущей пригодиться не только при изобретении шрифтов но и для других работ с нашим экранчиком. (можно взять здесь: http://ikarab.narod.ru/KS0108.html ) В ней есть преобразование «код — картинка» можно проверить символ 0х41 и получить «A». Соответственно, закрашивая попиксельно знакоместа — получаем строчку HEX-кодов символов.
Ну что ж, рисуем:
0x7e, 0x11, 0x11, 0x11, 0x7e,//A 0x80 0x7f, 0x49, 0x49, 0x49, 0x33,//Б 0x81 0x7f, 0x49, 0x49, 0x49, 0x36,//В 0x82 0x7f, 0x01, 0x01, 0x01, 0x03,//Г 0x83 0xe0, 0x51, 0x4f, 0x41, 0xff,//Д 0x84 0x7f, 0x49, 0x49, 0x49, 0x41,//E 0x85 0x77, 0x08, 0x7f, 0x08, 0x77,//Ж 0x86 0x41, 0x49, 0x49, 0x49, 0x36,//З 0x87 0x7f, 0x10, 0x08, 0x04, 0x7f,//И 0x88 0x7c, 0x21, 0x12, 0x09, 0x7c,//Й 0x89 0x7f, 0x08, 0x14, 0x22, 0x41,//K 0x8A 0x20, 0x41, 0x3f, 0x01, 0x7f,//Л 0x8B 0x7f, 0x02, 0x0c, 0x02, 0x7f,//M 0x8C 0x7f, 0x08, 0x08, 0x08, 0x7f,//H 0x8D 0x3e, 0x41, 0x41, 0x41, 0x3e,//O 0x8E 0x7f, 0x01, 0x01, 0x01, 0x7f,//П 0x8F 0x7f, 0x09, 0x09, 0x09, 0x06,//P 0x90 0x3e, 0x41, 0x41, 0x41, 0x22,//C 0x91 0x01, 0x01, 0x7f, 0x01, 0x01,//T 0x92 0x47, 0x28, 0x10, 0x08, 0x07,//У 0x93 0x1c, 0x22, 0x7f, 0x22, 0x1c,//Ф 0x94 0x63, 0x14, 0x08, 0x14, 0x63,//X 0x95 0x7f, 0x40, 0x40, 0x40, 0xff,//Ц 0x96 0x07, 0x08, 0x08, 0x08, 0x7f,//Ч 0x97 0x7f, 0x40, 0x7f, 0x40, 0x7f,//Ш 0x98 0x7f, 0x40, 0x7f, 0x40, 0xff,//Щ 0x99 0x01, 0x7f, 0x48, 0x48, 0x30,//Ъ 0x9A 0x7f, 0x48, 0x30, 0x00, 0x7f,//Ы 0x9B 0x00, 0x7f, 0x48, 0x48, 0x30,//Э 0x9C 0x22, 0x41, 0x49, 0x49, 0x3e,//Ь 0x9D 0x7f, 0x08, 0x3e, 0x41, 0x3e,//Ю 0x9E 0x46, 0x29, 0x19, 0x09, 0x7f,//Я 0x9F // маленькие буквы 0x20, 0x54, 0x54, 0x54, 0x78,//a 0xA0 0x3c, 0x4a, 0x4a, 0x49, 0x31,//б 0xA1 0x7c, 0x54, 0x54, 0x28, 0x00,//в 0xA2 0x7c, 0x04, 0x04, 0x04, 0x0c,//г 0xA3 0xe0, 0x54, 0x4c, 0x44, 0xfc,//д 0xA4 0x38, 0x54, 0x54, 0x54, 0x18,//e 0xA5 0x6c, 0x10, 0x7c, 0x10, 0x6c,//ж 0xA6 0x44, 0x44, 0x54, 0x54, 0x28,//з 0xA7 0x7c, 0x20, 0x10, 0x08, 0x7c,//и 0xA8 0x7c, 0x41, 0x22, 0x11, 0x7c,//й 0xA9 0x7c, 0x10, 0x28, 0x44, 0x00,//к 0xAA 0x20, 0x44, 0x3c, 0x04, 0x7c,//л 0xAB 0x7c, 0x08, 0x10, 0x08, 0x7c,//м 0xAC 0x7c, 0x10, 0x10, 0x10, 0x7c,//н 0xAD 0x38, 0x44, 0x44, 0x44, 0x38,//o 0xAE 0x7c, 0x04, 0x04, 0x04, 0x7c,//п 0xAF 0x7C, 0x14, 0x14, 0x14, 0x08,//p 0xB0 0x38, 0x44, 0x44, 0x44, 0x20,//c 0xB1 0x04, 0x04, 0x7c, 0x04, 0x04,//т 0xB2 0x0C, 0x50, 0x50, 0x50, 0x3C,//у 0xB3 0x30, 0x48, 0xfc, 0x48, 0x30,//ф 0xB4 0x44, 0x28, 0x10, 0x28, 0x44,//x 0xB5 0x7c, 0x40, 0x40, 0x40, 0xfc,//ц 0xB6 0x0c, 0x10, 0x10, 0x10, 0x7c,//ч 0xB7 0x7c, 0x40, 0x7c, 0x40, 0x7c,//ш 0xB8 0x7c, 0x40, 0x7c, 0x40, 0xfc,//щ 0xB9 0x04, 0x7c, 0x50, 0x50, 0x20,//ъ 0xBA 0x7c, 0x50, 0x50, 0x20, 0x7c,//ы 0xBB 0x7c, 0x50, 0x50, 0x20, 0x00,//ь 0xBC 0x28, 0x44, 0x54, 0x54, 0x38,//э 0xBD 0x7c, 0x10, 0x38, 0x44, 0x38,//ю 0xBE 0x08, 0x54, 0x34, 0x14, 0x7c //я 0xBF
Ну вот, самая трудоемкая часть работы позади…. Не притомились?
Идем дальше…
Казалось бы, добавляем наш двоичный массив в хвост шрифта, корректируем заголовок и вот оно — счастье! Не тут-то было!
Меня осенила здравая идея — проверить в какой кодировке работает Arduino IDE. Для этого был спешно набросан кусочек кода:
#include <glcd.h>
#include "fonts/SystemFont5x7.h"
char myString[] = "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя";
void setup ()
{
  GLCD.Init();
  GLCD.SelectFont(System5x7,BLACK);
}
void loop()
{
  byte i=0;
  while (i<120)
   {
     GLCD.print(myString[i]);
     GLCD.print(" == ");
     GLCD.print(myString[i],HEX);
     GLCD.println();
     delay(100);
     i++;
   }
  GLCD.println();
  GLCD.println(myString);
 delay(5000);
}
Выяснилось — работаем в UTF-8. Берем таблицу кодировки и получается что:
диапазону 0x80 — 0x8F соответствуют маленькие буквы от «р» до «я»
с 0x90 и до 0xAF идут заглавные по порядку «А» — «Я» исключая «Ё»
и в хвосте с 0xB0 до 0xBF маленькие от «а» до «п». Корректируем наш сотворенный битовый массив согласно кодировке и добавляем в хвост h-файла. Не забываем поправить служебные поля в начале.
Вуаля!

Ну и бонусом для тех кто дочитал до сего места ссылка на готовый файл шрифта:
Брать здесь: http://narod.ru/disk/47094865001.37fe25fb0ce3344acb820deb206144db/SystemRus5x7.h.html

0 комментариев на «“Русифицируем LCD экранчик 128х64, точнее библиотеку GLCD”»
Вот только шрифт на проверку оказался 5×7, что всплывает при попытке использования букв с «хвостами» типа «Д».