Реклама ⓘ
Главная » Микроконтроллеры
Призовой фонд
на июль 2024 г.
1. 100 руб.
От пользователей

Похожие статьи:


Реклама ⓘ

Видеоадаптер HDMI для микроконтроллера на FPGA

Устройство представляет из себя видеоадаптер разрешением 640х480 с выводом изображения на монитор или телевизор через HDMI, управляемый по параллельной шине данных. Его можно использовать в радиолюбительских конструкциях на микроконтроллерах таких как, например, UART терминал, простые видеоигры, типа тетриса или змейки с выводом изображения на монитор. При этом, вывод изображения на монитор делается не сложнее, чем на какой-нибудь китайский LCD дисплей для Arduino. 

Простота и скорость работы с видеоконтроллером достигается за счёт способа построения изображения. Изображение строится не из отдельных пикселей, а из тайлов (плиток, знакомест), на подобие фона в известной многим приставке NES. Весь экран разделён в виде сетки с ячейками 8х8 пикселей, получается таблица из 2400 ячеек (60 строк по 80 ячеек). Каждая ячейка в видеопамяти занимает всего два байта, один байт - номер тайла, который необходимо в ней нарисовать, второй байт - атрибут цвета. Сами изображения тайлов также хранятся в видеопамяти и могут быть записаны заранее. Таким образом, чтобы изменить изображения одной ячейки, достаточно записать всего два байта в память видеоконтроллера.  

В этом есть как плюсы, так и минусы. Основные преимущества такого способа построения изображения - это небольшой объём памяти, необходимый для хранения изображения (в данном случае 16Кб) и скорость работы с памятью. Недостатки - невозможность вывода растрового изображения (привычных нам картинок, типа *bmp файлов), ограниченный набор тайлов, которые могут одномоментно выводиться на экран (256), ограничения, связанные с назначением цвета каждого пикселя (можно назначать отдельные цвета только для знакоместа, наподобие экрана ZX Spectrum). 

Вся память видеоконтроллера разделена на несколько секций и имеет следующий вид:

  • 0x0000 - 0x12BF: 4800 байт - номера тайлов для каждого знакомемта
  • 0x12C0 - 0x257F: 4800 байт - атрибут цвета каждого знакоместа
  • 0x2580 - 0x27FF: 640 байт - не используется
  • 0x2800 - 0x2FFF: 2048 байт - первый банк тайлов
  • 0x3000 - 0x37FF: 2048 байт - второй банк тайлов
  • 0x3800 - 0x3FFF: 2048 байт - третий банк тайлов

Из карты видно, что память имеет три банка тайлов одинакового размера 2048 байт. Это сделано не просто так. Так как на хранение номера тайла в каждом знакоместе отводится один байт, то для каждого знакоместа можно закодировать всего 256 номеров (0 - 255). Это значит что одномоментно на экране может отображаться изображение из 256 комбинаций различных тайлов. Так как тайл имеет размер 8х8 пикселей, для хранения его изображения нужно 8 байт. Вот и получается 256х8=2048 - размер банка тайлов. А чтобы хоть как-то увеличить количество возможных изображений тайлов, используются три переключаемых банка по 2048 байт каждый. 

Принцип работы видеоадаптера следующий: при построении изображения видеоконтроллер во время отображения текущего знакоместа подготавливает данные для следующего знакоместа. Для этого он по номеру пикселя в строке и номеру строки вычисляет номер знакоместа (от 0 до 4799) и читает из видеопамяти три байта: 1 - номер тайла для знакоместа (из диапазона 0x0000 - 0x12BF), 2 - значение атрибута цвета для знакоместа (из диапазона 0x12C0 - 0x257F), 3 - байт одной строки изображения тайла для знакоместа (адрес изображения тайла в видеопамяти вычисляется из первого прочитанного байта, номера строки и номера банка тайлов). Защёлкивает байт изображения тайла сначала во временный регистр, затем перед переходом на следующее знакоместо - в сдвиговый регистр. Все эти действия происходят за 8 тактов пиксельной частоты HDMI. После перехода на следующее знакоместо видеоконтроллер выводит изображение из сдвигового регистра в соответствии с цветами, заданными байтом атрибута.

Цвета из атрибута формируются следующим образом: старший полубайт атрибута (4 бита [7:4]) задаёт цвет символа, младший полубайт (4 бита [3:0]) задаёт цвет фона знакоместа. Соответственно для фона и для цвета тайла можно закодировать по 16 цветов. Все цвета берутся из фиксированной палитры (палитра представляет из себя 16 произвольных цверов в формате RGB888). 

В качестве видеопамяти видеоконтроллера используется встроенная в FPGA блочная память. Она сконфигурирована в виде Simple Dual PORT RAM, что позволяет читать и записывать данные одномоментно. Благодаря этому можно записывать видеоданные даже во время отрисовки видимой области экрана. Это конечно может вызвать мерцание единичных знакомест при одномоментной записи  всей памяти, но при изменении отдельных ячеек памяти, будет незаметно. При желании можно вывести из видеоконтроллера сигнал гашения экрана после 639 строки и отрисовывать экран вообще незаметно.

Для управления видеоконтроллером используется параллельная 8-битная шина данных и несколько управляющих сигналов:

  • AD[7:0] - мультиплексированная шина адреса/данных
  • CMD[2:0] - номер команды
  • STROBE - стробирующий импульс

Команды CMD[2:0]:

  • 000 - запись байта данных во временный регистр данных
  • 001 - запись младшего байта адреса во временный регистр адреса
  • 010 - запись старшего байта адреса во временный регистр адреса
  • 011 - запись данных в видеопамять из временного регистра данных по адресу из временного регистра адреса
  • 100 - выбор номера банка изображений тайлов (1-3) из линии данных (AD[1:0])

Запись данных производится следующим образом: сначала выставляются данные на шину данных (AD) и номер команды на шину команд (CMD), затем подаётся стробирующий импульс. Стробирующий импульс имеет положительную полярность.

Диаграмма записи данных в видеоконтроллер:

На первом такте strobe происходит запись байта 0x1F во временный регистр данных, на втором и третьем тактах strobeпроисходит запись адреса 0x01D3 во временный регистр адреса, на четвёртом такте strobe данные из временного регистра записываются в видеопамять. Запись данных и адреса во временные регистры можно производить в произвольном порядке. На пятом такте strobe показано переключение на второй банк тайлов. 

Мой вариант видеоконтроллере сделан на Altera Cyclone4 EP4CE6E22C8N. Специально для этого проекта сделал отладочную плату с HDMI разъёмом. Хорошо, в своё время прикупил на Ali за недорого несколько таких ПЛИС-ин, б/у, но рабочих. Кварцевый генератор установлен на 50MHz, микросхема SRAM, установленная на плате в данном проекте не используется. Использовал эту плату совместно с платкой Black pill на stm32f411ceu, хотя можно любой другой с достаточным количеством выводов и желательно логическими уровнями 3,3 вольта:

Проект для Altera написан в среде Quartus 13.0 на Verilog и занимает 363 ячейки (6%). Из периферии FPGA используется 1 модуль PLL для формирования частоты 25MHz для пиксельклока и 250MHz для формирования TMDSclock модуля HDMI. Также используется 16 ячеек M9K памяти (это чуть меньше половины всей блочной памяти данной FPGA).  

Проект несложно адаптировать под любые другие отладочные платы с HDMI разъёмом, как на Altera, так и на других FPGA, например, Xilinx или Gowin. Благо, ножки у FPGA назначаются практически все произвольно. Единственное, что необходимо учитывать, дифференциальные пары сигналов HDMI желательно назначать на дифференциальные пары выводов FPGA.

Для демонстрации работы написал минимальную библиотеку с самыми необходимыми функциями работы с дисплеем и небольшую демку (см. проект для stm32).

1. Вывод всех символов знакогенератора (ASCII) на экран. Знакогенератор записывается в первый банк тайлов при инициализации FPGA (используется файл начальной инициализации памяти, расположен в папке "rom" проекта для Altera).

2. Вывод текста на экран. Как видно, фон и цвет символов уже совсем другие:

С растровыми изображениями всё намного сложнее. Из-за ограничений, обусловленных упрощённой структурой видеоконтроллера и экономией видеопамяти, вывести просто так растровое изображение в полном разрешении, даже монохромное практически невозможно. Можно только его составлять из набора тайлов, будь то - псевдографика или набор маленьких рисунков как у NES. Но, используя некоторые хитрости, можно вывести что-то похожее на растр, уменьшив разрешение экрана в 4 раза. Если поделить каждое знакоместо на 4 части (на 4 кубика 4х4 пикселя), то получится всего 16 комбинаций изображения данного знакоместа. Таким образом, комбинируя эти тайлы, можно вывести монохромное изображение в разрешении 160х120 пикселей. Выглядит, конечно, как японский кроссворд, особенно на 2К мониторе:

Специально для конвертации *bmp файла в тайловое изображение написал небольшую утилиту (прикреплю к статье архив "Software"). Она конвертирует монохромный (1bit) *bmp файл разрешением 160х120 пикселей в массив байтов (точнее - номеров тайлов). Сам набор изображений этих 16 тайлов есть в демонстрационном проекте на stm32 в файле "main.c" (массив pseudoGraph[]). В демке набор из 16 тайлов записывается в CHAR BANK3.

Также в папке "Software" есть утилита для конвертации файлов инициализации памяти FPGA из *hex или *bin в *mif (Altera), *coe (Xilinx) и *mi (Gowin).

Нормальные тайловые изображения пока не пробовал рисовать, так как не имею такого опыта. Попробую позже, возможно, попробую составить их из тайлов от какой-нибудь игры для NES.

Когда-то писал игру "тетрис" для микроконтроллера с TFT-дисплеем, адаптировал её на скорую руку для этого видеоконтроллера. Переписал её без особых переделок, чисто для демонстрации: 

В перспективе, есть мысли попробовать добавить спрайты. Это значительно усложнит проект, но будет очень интересно и полезно для саморазвития.

А пока на этом всё. Пишите комментарии, конструктивная критика приветствуется.

Прикрепленные файлы:

Теги:

Опубликована: 0 0
Я собрал 0 2
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 5 Проголосовало: 2 чел.

Комментарии (3) | Я собрал (0) | Подписаться

0
Публикатор #
На форуме автоматически создана тема для обсуждения статьи.
Ответить
0
Дмитрий #
Плата ЛУТом изготовлена? Поделитесь пожалуйста, какая бумага и текстолит?
Ответить
0

[Автор]
AndrejChoo #
Нет, платы делаю фоторезистом, в данном случае жидким. ЛУТом не пользуюсь уже давно.
Текстолит самый обыкновенный китайский
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется электрическая мощность?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Pickit 2 - USB-программатор PIC-микроконтроллеров
Pickit 2 - USB-программатор PIC-микроконтроллеров
Лазерный модуль 650нм 5мВт Мини гравер 125 Ватт
вверх