В уроке подробно расскажу об Ардуино-библиотеке для работы с OSD-генератором MAX7456. Представлю исправленный вариант библиотеки, корректно работающий с кириллическими текстами.
Предыдущий урок Список уроков Следующий урок
Для программного управления OSD-контроллером MAX7456 в системе Ардуино разработана библиотека MAX7456. Библиотека поддерживает большинство режимов и функций видеоконтроллера, удобна в использовании, работает стабильно.
Для использования библиотеки вместе с ней необходимо подключить библиотеку SPI.h и в блоке setup() разрешить работу интерфейса SPI.
#include <SPI.h>
#include <max7456.h>
void setup()
{
SPI.begin();
}
Загрузить библиотеку можно по ссылке max7456-master.zip.
Методы библиотеки MAX7456.
Max7456()
Конструктор. Создает экземпляр класса.
Max7456 osd; // создаем экземпляр класса Max7456
Max7456(byte pinCS)
Конструктор. Инициализирует интерфейс, задает вывод CS.
- pinCS – номер вывода CS.
Max7456 osd(10); // создаем экземпляр класса Max7456, CS подключен к 10 выводу
void init(byte pinCS)
Функция инициализирует интерфейс, задает вывод для сигнала CS. Должна вызываться до использования других функций. По действию аналогична конструктору Max7456(byte pinCS).
osd.init(10);
void setBlinkParams(byte blinkBase, byte blinkDC)
Метод задает временные параметры мигания символов.
- blinkBase – время мигания (BT);
Значение blinkBase | Время мигания (BT), мс | ||
в NTSC режиме | в PAL режиме | ||
00 | _2fields | 33 | 40 |
01 | _4fields | 67 | 80 |
10 | _6fields | 100 | 120 |
11 | _8fields | 133 | 160 |
- blinkDC – параметр, определяющий соотношение времени включен/погашен.
Значение blinkDC | Соотношение времени включен/погашен | ||
включен | погашен | ||
00 | _BT_BT | BT | BT |
01 | _BT_2BT | BT | 2 x BT |
10 | _BT_3BT | BT | 3 x BT |
11 | _3BT_BT | 3 x BT | BT |
В качестве аргументов blinkBase и blinkDC могут быть использованы символьные константы. Они указаны во вторых столбцах таблиц.
osd.setBlinkParams(_6fields, _BT_2BT);
void setDisplayOffsets(byte horizontal, byte vertical)
Метод задает смещение информации на экране.
- horizontal – смещение по горизонтали в пикселях. Может принимать значения от 0 до 63.
Значение horizontal | Смещение, в пикселях |
0 | - 32, смещение влево |
… | … |
32 | 0, смещения нет |
… | … |
63 | + 31, смещение вправо |
- vertical - смещение по вертикали в пикселях. Может принимать значения от 0 до 31.
Значение vertical | Смещение, в пикселях |
0 | + 16, смещение вверх |
… | … |
16 | 0, смещения нет |
… | … |
31 | - 15, смещение вниз |
osd.setDisplayOffsets(30,10);
void clearScreen()
Метод очищает информацию экрана. Экранная память заполняется нулями.
osd. clearScreen();
void activateOSD(bool act=true)
Метод разрешает или запрещает вывод OSD-информации.
- act = true – OSD разрешен;
- act = false – OSD запрещен.
osd.activateOSD(true);
void activateExternalVideo(bool activExtVid=true)
Метод разрешает или запрещает вывод фонового изображения.
- activExtVid = true – фоновое изображение разрешено;
- activExtVid = false – серый фон.
void sendCharacter(const charact array, byte x, byte y)
Загружает карту изображения символа в память (EEPROM) знакогенератора.
- array – массив карты изображения символа (54 байта). Формат массива описан в предыдущем уроке.
- x – горизонтальная координата символа в памяти знакогенератора.
- y – вертикальная координата символа в памяти знакогенератора.
Если аргумент y отсутствует, то функция воспринимает параметр x, как адрес символа в памяти знакогенератора.
Тип charact определен в библиотеке как массив размером 54 байта ( typedef byte charact[54]; ).
charact c={0x34,....}
max.sendCharacter(c,5,6); // загрузка карты 5 символа в 6 строке, т.е. адрес 65
max.sendCharacter(c,0x65); // загрузка карты символа с кодом 65
void getCharacter(charact array, byte x, byte y)
Метод по сравнению с предыдущим выполняет обратную функцию. Т.е. считывает карту изображения символа из памяти знакогенератора.
- array – массив для чтения карты изображения символа (54 байта). Формат массива описан в предыдущем уроке.
- x – горизонтальная координата символа в памяти знакогенератора.
- y – вертикальная координата символа в памяти знакогенератора.
Если аргумент y отсутствует, то функция воспринимает параметр x, как адрес символа в памяти знакогенератора.
max.getCharacter(c,0x65); // чтение карты символа с кодом 65 в массив c.
void print(const char string[], byte x, byte y, byte blink = 0,byte inv = 0)
Метод записывает символьную строку в экранную память MAX7456, т.е. выводит строку на OSD экран.
- string – строка для отображения.
- x – горизонтальная координата начала строки в экранной памяти.
- y – вертикальная координата начала строки в экранной памяти.
- blink - при значении равном 1 символ мигает.
- inv - при значении равном 1 символ отображается в инверсном состоянии.
Метод рассчитан на ASCII таблицу кодов символов в памяти знакогенератора, смещенную так, что по адресу 0 размещен символ пробел (' '). При стандартной ASCII кодировке работает неправильно. Ниже я приведу вариант библиотеки, в котором я исправил эту проблему. Также я исправил неприятности с выводом кириллического текста. В исходной версии библиотеки функция print с кириллицей работает не правильно.
max. print(“test”, 8, 1, 0, 0); // печать на экран слова test начиная с 8 символа 1 строки
void print(double value, byte x, byte y, byte before, byte after, byte blink=0,byte inv=0)
Метод выводит в экранную память число в формате float.
- value – значение числа типа float.
- x – горизонтальная координата начала числа в экранной памяти.
- y – вертикальная координата начала числа в экранной памяти.
- before – число цифр до децимальной точки.
- after – число цифр после децимальной точки.
- blink - при значении равном 1 символ мигает.
- inv - при значении равном 1 символ отображается в инверсном состоянии.
При аргументе after равном 0, децимальная точка не выводится.
В исходном варианте библиотеки у функции те же проблемы с кодировкой знакогенератора. Со стандартной кодировкой ASCI I она не работает.
max.print(4.15, 10, 1, 2, 4); // напечатает 04.1500
void printMax7456Chars(byte chars[],byte size, byte x, byte y, byte blink = 0, byte inv = 0)
Метод записывает последовательность символов в экранную память из текстового массива.
- chars – массив символов.
- size – число символов.
- x – горизонтальная координата начала строки в экранной памяти.
- y – вертикальная координата начала строки в экранной памяти.
- blink - при значении равном 1 символ мигает.
- inv - при значении равном 1 символ отображается в инверсном состоянии.
Функция print() работает с текстовыми строками. Она выводит символы последовательно, пока не встретится признак конца строки 0.
Функция printMax7456Chars выводит заданное число символов из массива.
max.printMax7456Chars(ccc, 5, 2, 1); // вывод на экран 5 символов из массива ccc
void printMax7456Char(const byte address, byte x, byte y, byte blink=0, byte inv=0)
Запись в экранную память одного символа.
- address – адрес памяти знакогенератора (код символа).
- x – горизонтальная координата символа в экранной памяти.
- y – вертикальная координата символа в экранной памяти.
- blink - при значении равном 1 символ мигает.
- inv - при значении равном 1 символ отображается в инверсном состоянии.
max.printMax7456Char(‘S’, 1, 2); // вывод на экран символа S
static void printCharacterToSerial(const charact array, bool img = true)
Метод выводит в последовательный порт Serial массив карты изображения символа.
- array – массив карты изображения символа (54 байта).
- img – способ отображения:
- img = true – символ выводится в виде рисунка;
- img = false – символ выводится в виде массива байт.
static void getCARACFromProgMem(const char *table, byte i, charact c)
Метод считывает в массив карту изображения для одного символа (54 байта) из программной памяти.
- table – указатель на массив данных знакогенератора в памяти программы.
- i – адрес символа в знакогенераторе (код символа).
- c – указатель на возвращаемый символ (массив 54 байта).
Проблемы работы с библиотекой MAX7456. Исправленный вариант.
Первая проблема заключается в том , что основная функция вывода информации print корректно работает с таблицей знакогенератора, в которой используется кодировка ASCII, но коды смещены так, что символу ‘ ‘ (пробел) соответствует нулевой адрес, а символу ‘z’ соответствует адрес 0x5a. Также со стандартной кодировкой не работает print(float) для вывода чисел.
Я убрал смещение. Исправленный вариант библиотеки корректно работает со стандартным знакогенератором ASCII.
Вторая проблема – работа функции print с кириллическим тестом. Функция print() неправильно выводит текстовые строки на русском языке.
Я напечатал начало русского алфавита командой osd.print("АБВГДЕЖЗ",6,5);
И вот, что получилось на экране.
Не буду подробно описывать последовательность поиска ошибки. Расскажу о результате.
Проблема оказалась в том, что кириллические символы Arduino IDE записывает в текстовые строки, используя кодировку UTF-8.
Упрощенно кодировка UTF-8 выглядит так.
- Если старший бит байта кода символа равен 0, то остальные 7 битов определяют код символа согласно стандарту ASCII. Т.е. символы с номерами меньше 128 это обычный ASCII текст. В этой области содержатся латинские символы, цифры, математические символы. Все эти символы корректно отображаются в исходной версии библиотеки MAX7456.
- Если старший бит равен 1, то используется 16 разрядная кодировка символов. В эту кодировку попадают кириллические символы. Т.е. если в текстовой строке встретится русский символ, то он будет представлен 2 байтами.
Я загрузил в текстовый массив кириллические символы "АБВГД", и вывел их в монитор последовательного порта.
char ccc[]= "АБВГД";
for(int i=0; i<10; i++) {
Serial.println(ccc[i], HEX);
}
Вот, что получилось
- 0xd090 это код символа ‘А’ в стандарте UTF-8;
- 0xd091 - код символа ‘Б’ и т.д.
Отсюда и вытекает, что каждый кириллический символ отображается, как два символа: ”стрелка вправо” (код 0xd0) и правильный символ.
Я исправил функцию print, сделал в ней конвертацию Unicode в стандартный ASCII 8 битный код.
Исправленную версию библиотеки MAX7456 можно загрузить по ссылке:
Теперь функция osd.print("АБВГДЕЖЗ",6,5) работает корректно.
В библиотеке отсутствует функция выбора системы видеосигнала. В следующем уроке я немного напишу об этом. Я добавил в библиотеку функцию выбора системы.
void videoStandartSelect(byte standart)
Метод позволяет задать тип аналогового видеосигнала:
- standart = 0 - NTSC;
- standart = 1 - PAL.
Вариант библиотеки с таким методом можно загрузить по ссылке:
В следующем уроке приступим к практическому программированию MAX7456.
Научимся создавать и загружать шрифты, выводить информацию на экран.
Здравствуйте.
Монитор какой используете?
Фон на мониторе как генерится у Вас?
Здравствуйте!
Там на картинке видно. С камеры.