Подключение микроконтроллера к hdmi

Обновлено: 07.07.2024

Эти ограничения немного удручали и явно не побуждали к каким-то действиям..

первое с чем я столкнулся - это необходимость разобраться, а что же на самом деле представляет из себя видеосигнал.

Неплохо о видеосигнале написал Rickard Gunee в статье "How to generate video signals in real-time using a PIC16F84". Данная статья есть в переводе с английского, с различными сокращениями. Я вряд ли напишу о видеосигнале лучше (вернее подобное наверное напишу, но вот иллюстрации скорее всего будут намного хуже), поэтому предлагаю Вам фрагмент этой статьи:

Как работает стандартный телевизор.

В стандартном телевизоре используется вакуумная труба, которая имеет экран, покрытый слоем люминофора и электронную пушку, которая излучает электроны в направлении экрана. В момент удара электрона об экран и в течении некоторого времени после удара в месте удара люминофорный слой излучает свет. Траекторию электронного потока, излучаемого пушкой, можно изменить с помощью магнитного поля и тогда электроны будут ударяться в другую точку экрана. Используя такое управление можно рисовать горизонтальные линии по всему экрану. При изменении интенсивности электронного луча изменяется яркость свечения, таким образом можно получить на экране изображение. В системе PAL экран перерисовывается 25 раз в секунду. Чтобы уменьшить мерцание экрана при обновлении картинки, сначала рисуются все нечетные, а потом все четные линии. Поэтому картинка практически обновляется 50 раз в секунду. Для того чтобы получить цветное изображение, необходимо чтобы каждая точка экрана состояла из трех цветов: красного, зеленого и синего. Здесь мы будим рассматривать только черно-белое телевидение, так как только его можно получить в реальном времени с помощью PIC16F84.
.
Электронный луч рисует изображение.
Две части изображения образуют одно сплошное.

Существуют три основных телевизионных стандарта: NTSC, SECAM и PAL. NTSC ( National Television System Committe ) – это американский стандарт. Он имеет 525 строк и частоту обновления кадров 30 Гц. SECAM ( Sequentil Color And Memory ) - французский стандарт и PAL ( Phase Alternating Lines ) имеют 625 строк в кадре при частоте кадров 25 Гц. Кроме различия кадровой и строчной частот эти стандарты отличаются способом кодирования цветного сигнала. Далее мы будим рассматривать стандарт PAL.
Точки разной яркости образуют на экране изображение. Когда электронный луч проходит по экрану, его интенсивность изменяется за счет изменения уровня видеосигнала. Но в этом сигнале нет информации о том, в какой части экрана находится в настоящее время луч. Для решения этой проблемы используется синхроимпульс, который передается в начале каждой строки. Синхроимпульс говорит телеприемнику, что текущая строка закончилась и необходимо перевести луч вниз, в начало следующей строки ( это похоже на нажатие кнопки 'Enter' на клавиатуре когда Вы набираете текст на компьютере ). Телеприемник должен также знать, когда начинается новый кадр. Об этом сообщает специальная комбинация синхроимпульсов ( как функция 'Новый документ' при написании текста с помощью компьютера ). При обновлении кадра 25 раз в секунду изображение будит заметно мерцать, поэтому сначала рисуются все нечетные, а потом все четные линии. За счет этого число кадров в секунду увеличивается до 50, и изображение становится более качественным. Информация о четности/нечетности строки передается в комбинации вертикальных синхроимпульсов. Амплитуда видеосигнала изменяется в пределах от 0 до 1В. Уровень 0,3В соответствует черному цвету, а 1В – белому (яркость серого изменяется между этими значениями ). Уровень 0В соответствует синхроимпульсу.

Строка видеосигнала.

Изображение разделено на строки. Каждая строка имеет длительность 64 мкс. В первые 4 мкс передается строчный синхроимпульс. Это производится переводом уровня сигнала в 0 для того, чтобы сказать телеприемнику, что началась новая строка. Старые телевизоры были очень медленными, после получения синхроимпульса им требовалось 8 мкс для перевода электронного луча в начало следующей строки. В течении этого времени сигнал поддерживается на уровне черного. В оставшиеся 52 мкс передаются данные изображения. Изображение рисуется слева направо с яркостью, соответствующей уровню видеосигнала. Черный цвет соответствует уровню 0,3В, и с увеличением уровня видеосигнала увеличивается яркость. Максимум яркости достигается при уровне видеосигнала 1В ( белый цвет ). На рисунке показана осциллограмма строки видеосигнала.

Осциллограмма строки видеосигнала.

Объединение строк вместе в изображение.

Изображение состоит из 625 строк. Но телевизор не показывает все 625. Часть из них используется для синхронизации. Другая часть ( не знаю точно сколько ) не видна на экране так как старым телевизорам требовалось некоторое время для перевода электронного луча из нижнего правого угла растра в верхний левый. (В настоящее время эти строки используются для других возможностей, например для телетекста ).

Осциллограмма нескольких строк видеосигнала.

Вертикальная синхронизация.

Для того чтобы сообщить телеприемнику, что начинается новый кадр, посылается специальный импульсный пакет. Так как изображение состоит из двух полукадров, пакеты отличаются в четном и нечетном полукадрах. Импульсы кадровой синхронизации выглядят как на рисунке.

Здесь показано, чем отличаются вертикальные синхроимпульсы в разных полукадрах. Уровень напряжения изменяется от 0 до 0,3 В. Цифры указывают номер строки.

Давайте прервемся на секунду, и отметим себе важную информацию по "железной" реализации:

наше устройство должно генерировать минимум 3 уровня сигнала на выходе для подключения телевизора:

- 0 вольт - это уровень синхроимпульсов
- 0.3 вольта - это уровень "черного", при данном сигнале телевизор рисует черным
- 1 вольт - это уровень "белого", при данном сигнале телевизор рисует изображение белым

в принципе уровень белого не обязательно должен равняться 1 вольту, можно и 0.7 и 0.8 - просто изображение будет чуть "серее"

теперь вернемся в нашу статью.

Схемное решение.

Для генерации видеосигнала необходима некая схема, способная создавать сигналы с амплитудой напряжения от 0 до 1В. Чтобы создать изображение Вам необходимо как минимум три уровня сигнала. Телевизор должен получать уровень черного и уровень синхросигнала для того, чтобы синхронизировать изображение. Если Вы хотите большего, чем просто черный экран, Вам понадобится некоторый уровень серого или белого. Для получения трех необходимых уровней аналогового сигнала требуется два бита данных цифрового сигнала. Стандартное входное сопротивление видеовхода телевизора – 75 Ом. Используя два резистора и два выхода порта микроконтроллера можно создать требуемые уровни напряжения.


При соединении обоих выходов D0 и D1 с землей, напряжение на видеовходе телевизора будит равно 0, что соответствует синхроуровню.


Выход D1 соединен с землей, а выход D0 - с +5В. В этом случае резистор 450 Ом включен параллельно 75 Ом-ному сопротивлению видеовхода телевизора, а резистор 900 Ом подключен к этой цепи последовательно. Этот делитель напряжения позволяет получить на видеовходе уровень 0,33В, что очень близко к уровню черного. (Истинный уровень черного 0,3В.)
Выход D0 соединен с землей, а выход D1 - с +5В. В этом случае резистор 900 Ом включен параллельно 75 Ом-ному сопротивлению видеовхода телевизора, а резистор 450 Ом подключен к этой цепи последовательно. Этот делитель напряжения позволяет получить на видеовходе уровень 0,67В. Это уровень серого.
Оба выхода D0 и D1 соединены с +5В. В этом случае резисторы 900 Ом и 450 Ом включены параллельно, а 75 Ом-ное сопротивление видеовхода телевизора, подключено к этой цепи последовательно. Этот делитель напряжения позволяет получить на видеовходе уровень 1В. Это уровень белого.
Эта схема позволяет получить четыре уровня напряжения. На рисунках представлены эквивалентные схемы четырех различных уровней напряжения и показано, каким образом они получаются. Номинал резисторов не критичен. Вы можете использовать большие, стандартные значения: 470 Ом и 1 кОм вместо 450 Ом и 900 Ом. Схема будит работать, просто немного изменится яркость изображения.
Итак, мы можем создать синхроуровень, уровни черного, серого и белого. Возможно создание и большего числа уровней яркости если использовать большее число бит выходного порта. Но в этом случае Вы не сможете с помощью них выполнять другие функции.
Теперь у тех кто внимательно читал наверняка в голове начала проявляться схема нашего будущего устройства, нарисуем !



Посмотрите свои припасы и выбирайте свой контроллер, могу вам посоветовать взять более "жирный" ATMEGA32 так как у него 2 кб ОЗУ которые мы будем использовать как видеопамять.
По номиналам резисторов, при питании микроконтроллера от 5 вольт я в первых своих тестах использовал постоянные резисторы следующих номиналов:
R3 = не устанавливал поскольку указываемое в некоторых схемах значение в 75 ом по моему мнению сильно нагружало на землю выводы порта С, и я не захотел рисковать.
Если вы хотите получить гарантировано рабочую конструкцию, то лучше не доверять написанным значениям резисторов, а поставить вместо них подстроечные резисторы номиналом в 1 ком и настроить на выходе напряжения:
- 0.3 вольта при PC0=1 и PC1=0
- 1 вольт при PC0=1 и PC1=1

Я для этого написал кратенькую программку на ассемблере (хотя нет, вру, в первый раз тестовую программу генерации уровней сигнала для настройки я написал на СИ, но делала она в точности тоже самое что и предложенная мною ниже программа на ассемблере).

.include "m32def.inc" ; Используем ATMega32

; настроим порты
sbi DDRC , 0 ; режим работы PC0 - выход
sbi DDRC , 1 ; режим работы PC1 - выход

; уровень синхроимпульса, на выходе 0 вольт
cbi PORTC , 0 ; PC0=0
cbi PORTC , 1 ; PC1=0

; уровень черного, на выходе 0.3 вольта
; sbi PORTC , 0 ; PC0=1
; cbi PORTC , 1 ; PC1=0

; уровень белого, на выходе 0.7 - 1 вольт
; sbi PORTC , 0 ; PC0=1
; sbi PORTC , 1 ; PC1=1

loop: rjmp loop

Вот в общем то и вся программа. Порядок действий думаю откровения не вызовет:

а) компилируем, заливаем в контроллер, мерим на выходе 0 вольт (уровень синхроимпульса) - с ним обычно проблем не бывает :-)
б) комментируем строки задающие уровень синхроимпульса, и раскоментируем строки отвечающие за уровень черного, опять компилируем, заливаем в контроллер, мерим напряжение на выходе, подбираем R1 (тот который около 1 ком) чтобы было около 0.3 вольт
в) комментируем строки задающие уровень черного (строки задающие уровень синхроимпульса мы уже закоментировали ранее), и раскоментируем строки отвечающие за уровень белого, опять компилируем, заливаем в контроллер, мерим, подбираем R2 (тот который около 300 ом) чтобы было около 1 вольта (можно чуть меньше)

Все замеры я осуществлял при подключенной нагрузке (телевизоре).

После того как вы проделали эту не сложную операцию - вы аппаратно готовы к генерации видео и можно переходить к следующему шагу:

Генерация видеосигнала при помощи контроллеров AVR. Часть 2. Синхроимпульсы

Часто при разработке своих проектов на микроконтроллерах появляется проблема в том, что необходимо как-то отображать данные. Конечно решением может быть использование ЖК индикаторов или нескольких светодиодных дисплеев, просто используя светодиоды. Но если требуется отображение различных данных и этих данных будет много… Большие LCD модули еще остаются дорогими в цене, использование графических модулей затрудняется из-за сложного протокола контроля и управления. Для решения таковой проблемы можно использовать компьютер, передавая данные по последовательному интерфейсу с вашего устройства и данные будут отображаться на мониторе. Но очень часто случается так, что компьютер необходим для другой работы или занят другим пользователем.

Вебинар «Новые решения STMicroelectronics в области спутниковой навигации» (17.11.2021)

Решением проблемы может быть данная разработка. Для отображения данных, которые передаются пользовательским устройством по последовательному интерфейсу, используется обычный телевизор с небольшим размером по диагонали. Сейчас можно без особых трудностей найти такой телевизор.

При разработке данного устройства преследовались определенные цели:

  • дисплейный модуль должен быть максимально простым;
  • для отображения данных достаточно текстового и псевдографического режима;
  • за всю работу модуля должен отвечать лишь 1 микроконтроллер
  • использование совместимой IBM PC AT клавиатуры для ввода данных

В итоге было разработано два варианта ТВ терминала: встраиваемый (для использования в устройстве) и как отдельный модуль с внешним блоком питания.


Основные параметры ТВ терминала:

  • цветовой режим: черно-белый;
  • разрешение в текстовом режиме: 40 символов × 25 строк;
  • разрешение в псевдографическом режиме: 80 × 75 точек;
  • отображаемые символы: ASCII 32 – 127;
  • скорость последовательного интерфейса: 1200 бод – 115.2 КБод;
  • источник питания: 9.0 – 12.0 В (5.0 В для встраиваемой версии).

Схема двух вариантов устройства представлена на рисунке. Различия, лишь в том, что в отдельном модуле имеется простой преобразователь уровней RS232-TTL и стабилизатор напряжения 78L05.


Как видите все основные функции возложены на микроконтроллер U1. Для текстового режима (40 символов × 25 строк) необходим минимальный объем памяти 1 КБайт, поэтому был выбран хорошо изученный и доступный микроконтроллер Atmega8 фирмы Atmel (для встраиваемой версии – в smd исполнении).

Микроконтроллер выполняет 3 задачи:

  • генерация видеосигнала;
  • прием символов с клавиатуры, декодирование и отправка по последовательному интерфейсу;
  • прием символов с последовательного интерфейса и сохранение их в памяти.

Организация одновременного выполнения этих трех процессов была самой трудной задачей. Генерация видеосигнала должно быть крайне точной, поэтому исходный код программы микроконтроллера был написан на ассемблере. Рабочая частота микроконтроллера – 20 МГц, предпочтительнее, конечно было бы 22 МГц, но в целях повторяемости была выбрана 20 МГц, вследствие этого присутствуют некоторые различия в горизонтальной ширине пикселей.

Источник питания и преобразователь логических уровней включены в версию отдельного модуля. Для упрощения схемы использовался вариант преобразователя на двух транзисторах, при небольших расстояниях последовательной линии. При увеличении расстояния возможно появление ошибок на высоких скоростях обмена. Также хочется отметить, что необходима определенная осторожность при использовании указанного типа клавиатуры. Энергопотребление многих из них в пределах допустимого, но не исключаются варианты у которых потребление более 100 мА. Повышенное потребление может вывести из строя регулятор напряжения U2 78L05. В этом случае лучше использовать регулятор напряжения 7805 в корпусе TO220.

Клавиатуру можно подключать с коннектором PS/2 или DIN5. Устройство в виде отдельного модуля рассчитано сразу для подключения PS/2 клавиатуры. Возможно использование переходника DIN5/PS2 для клавиатур со старым вариантом разъема DIN5.

При программировании микроконтроллера необходимо выставить Fuse-биты: RESET=ON, BROWN-OUT LEVEL 4.0V, OSCILLATOR=EXT. CRYSTAL HIGH FREQ. Правильно запрограммированный микроконтроллер генерирует видеосигнал, при подаче питания на экране ТВ отображаются текущие параметры, спустя 3 с терминал полностью готов к работе. Если нет синхронизации на необходимо подобрать резистор R7.

Современная техника не стоит на месте и когда-то казавшиеся сложными ЭВМ состоящие из множества микросхем и прочих радиоэлементов в наше время могут быть заменены всего одним дешевым микроконтроллером, способным выполнять функции когда-то современного компьютера. В данной статье будет рассказано как с помощью одного микроконтроллера AVR и небольшой обвязки создать простейшую игровую консоль, способную «запустить» такие легендарные игры как Super Mario и Pacman, думаю у многих это вызовет чувство ностальгии. При желании, основываясь на существующей библиотеке и видеодрайвере, можно создать свою собственную оригинальную видео игру. Помимо этого данная статья расскажет о том, как легко можно превратить обычный монитор или телевизор в дисплей для вывода на него текстовой и графической информации с микроконтроллера. Таким образом, данная схема предоставляет не только функции игрушки, но и является своеобразным драйвером для сопряжения какого либо устройства с системой графического отображения информации.

Принципы работы видео систем

Чтобы понять, как же работает игровая видеоконсоль, сперва разберемся с принципами работы аналоговой видео системы. Для этого рассмотрим пример основанный на принципе работы стандартного телевизора с электронно-лучевой трубкой (ЭЛТ).

В стандартном телевизоре с электронно-лучевой трубкой имеется экран покрытый слоем люминофора и электронная пушку, которая излучает электроны в направлении экрана. В момент удара электрона об экран и в течении небольшого времени после удара в месте удара о слой люминофора, происходит излучение света. Траекторию электронного потока, излучаемого пушкой, можно изменить с помощью магнитного поля и тогда электроны будут ударяться в другую точку экрана. Используя такое управление можно рисовать горизонтальные линии по всему экрану. При изменении интенсивности электронного луча изменяется яркость свечения, таким образом можно получить на экране изображение. В системе PAL экран перерисовывается 25 раз в секунду. Чтобы уменьшить мерцание экрана при обновлении картинки, сначала рисуются все нечетные, а потом все четные линии. Поэтому картинка практически обновляется 50 раз в секунду. Для того чтобы получить цветное изображение, необходимо чтобы каждая точка экрана состояла из трех цветов: красного, зеленого и синего.

Изображение на экране формируется точками разной яркости. Когда электронный луч проходит по экрану, его интенсивность изменяется за счет изменения уровня видеосигнала. Но в этом сигнале нет информации о том, в какой части экрана находится в настоящее время луч. Для решения этой проблемы используется синхроимпульс, который передается в начале каждой строки. Синхроимпульс говорит телеприемнику, что текущая строка закончилась и необходимо перевести луч в начало следующей строки. Телеприемник также должен знать, когда начинается новый кадр. Об этом сообщает специальная комбинация синхроимпульсов. При обновлении кадра 25 раз в секунду изображение будет заметно мерцать, поэтому сначала рисуются все нечетные, а потом все четные линии. За счет этого число обновлений экрана увеличивается до 50 в секунду, и изображение становится более сглаженным. Информация о четности/нечетности строки передается в комбинации вертикальных синхроимпульсов. Амплитуда видеосигнала изменяется в пределах от 0 до 1В. Уровень 0,3В соответствует черному цвету, а 1В – белому (яркость цвета изменяется между этими значениями). Уровень 0В соответствует синхроимпульсу.

Для генерации видеосигнала необходима схема, способная создавать сигналы с амплитудой напряжения от 0 до 1В. Чтобы создать изображение необходимо как минимум три уровня сигнала. Телевизор должен получать уровень цвета, черного и уровень синхросигнала для того, чтобы синхронизировать изображение. Для получения трех необходимых уровней аналогового сигнала требуется два бита данных цифрового сигнала. Используя два резистора и два выхода порта микроконтроллера можно создать требуемые уровни напряжения.

При соединении обоих выходов 0 и 1 с землей, напряжение на видеовходе телевизора будит равно 0, что соответствует синхроуровню.

Выход 1 соединен с землей, а выход 0 - с +5В. В этом случае резистор 450 Ом включен параллельно 75 Ом-ному сопротивлению видеовхода телевизора, а резистор 900 Ом подключен к этой цепи последовательно. Этот делитель напряжения позволяет получить на видеовходе уровень 0,33В, что очень близко к уровню черного.

Выход 0 соединен с землей, а выход 1 - с +5В. В этом случае резистор 900 Ом включен параллельно 75 Ом-ному сопротивлению видеовхода телевизора, а резистор 450 Ом подключен к этой цепи последовательно. Этот делитель напряжения позволяет получить на видеовходе уровень 0,67В. Это уровень серого.

Оба выхода 0 и 1 соединены с +5В. В этом случае резисторы 900 Ом и 450 Ом включены параллельно, а 75 Ом-ное сопротивление видеовхода телевизора, подключено к этой цепи последовательно. Этот делитель напряжения позволяет получить на видеовходе уровень 1В. Это уровень белого.

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

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

На осциллограмме видно, что синхроимпульс имеет самый минимальный уровень сигнала, он равен 0В и его длительность составляет 4 мкс. За горизонтальным синхроимпульсом в течении 8мкс следует уровень сигнала равный 0,33В, данному уровню соответствует уровень черного, затем идет короткий импульс амплитудой 0,6В соответствующий серому, затем опять уровень черного и короткий импульс белого амплитудой 1В. Длительность всей строки составляет 52мкс. В результате подачи такого сигнала на видеовход получится такое изображение:

Отличие цветного видео от ч/б заключается в разделении белого цвета на три составляющие, это RGB цвета (R=Red – красный, G=Green – зеленый и B=Blue – синий). При смешивании данных цветов с различной яркостью можно получить любой цвет из гаммы.

RGB


Изображение показывающее эффекты наложения цветов

Реализация системы видео вывода

Разобравшись с принципом работы аналоговых видео устройств можно начать приступать к реализации собственного устройства видео вывода.

Конструктивно описываемое устройство представляет собой схему, основанную на AVR микроконтроллере, подключаемую к монитору либо телевизору через своеобразный резистивный ЦАП.

Процессоры AVR не предоставляет достаточного объема оперативной памяти для использования ОЗУ в качестве видеопамяти, поэтому некоторые элементы при работе в режиме реального времени должны использоваться в сжатом виде. Распространенный способ преодоления нехватки ОЗУ является способ разбиения экрана на блоки. В системах такого рода, экран делится на поля X*Y (блоки), и каждый блок графически адресован в таблицу текстур находящуюся в оперативной памяти. В действительности растровые изображения хранятся в другом месте, например в ПЗУ.

Основой однокристальной игровой консоли AVGA является блочная структура, основанная на прерываниях AVR управляемые аудио-видео драйвером. Однако имеются некоторые очень специфичные функции:

1. Графический драйвер может получить любой растровый блок для показа в любом месте экрана из оперативной памяти или флэш. Что это значит? Вы можете скопировать блок графики из FLASH, в оперативную памяти основной программы. Для этого укажите драйверу, что он должен получить данные для этого блока из оперативной памяти, а не из флеш. На экране ничего не изменится. Тем не менее, вы можете изменить отображение, когда блок будет в оперативной памяти. Эта функция используется для наложения (Overlay). Существует функция с именем overlay_draw(pointer_to_image, x, y, width, height). Эта функция ведет себя так же, как putimage(. ) в полноценной графической среде, отображая отдельные пиксель (не блок) по координатам плюс он имеет определяемую прозрачность, зеркальное отображение исходного растрового изображения, обрезка, выбор области рисования и т.д. Эта функция перемещает все блоки под данный спрайт оперативной памяти и рисует его. Тогда вы можете просто вызвать overlay_clear() и спрайт исчезает - все используемые блоки, на которые ссылаются, возьмутся из FLASH. Есть также классические примитивные графические функции, такие как putpixel(. ).

2. Экран может быть разделен на вертикальные участки. Каждое такое окно что-то вроде интерфейса между видимым экраном и видео-памятью. Можно, например, создать окно где-то на экране с высотой 50px, которое показывает вещи, начиная с линии 10 в псевдо видео ОЗУ. Можно создать два окна, показывающие одно и то же (клон), создать пустое окно, поэтому эти видео линии не проверяются – это экономит процессорное время, позволяет создать окно с цветом маски, и т.д.

3. Низкоуровневый графический драйвер поддерживает горизонтальную прокрутку (один блок, пиксель за пикселем). Это позволяет писать игры с горизонтальной прокруткой. Фоновая утилита рисует блоки основного объекта на определенное место на экране (окно), расположенные относительно левого верхнего угла экрана.

4. Не имеется абсолютно никаких задержек внутри системных функций. Все прерывания ядра рассчитаны для возврата процессора в основную программу, когда это только становится возможным. Быстрый режим ШИМ используется для генерации высокоточных видео синхронизаций, с правильными таймингами. Это дает более чем 3М тактов процессора в секунду для основного приложения (19.6608MHz, полноэкранное видео, PAL, 192х144).

Все может быть настроено для удовлетворения ваших требований. AVGA не использует специфических особенностей МК. Он будет работать на любом AVR ATMega контроллере, по крайней мере, имеющим один полный 16-разрядный таймер для видео.

Оптимальное разрешение выбрано для PAL это 192х144 (не разогнанный МК). Это разрешение с соотношением 4:3 и делиться на восемь. Каждый кадр PAL имеет 288 строк, поэтому, когда удваивается каждая строка, она охватывает весь экран. Для NTSC это 160х120. Обратите внимание, что вы можете сделать свое собственное видео разрешение. Вы даже можете изменить высоту блока. При разгоне МК можно получить гораздо выше разрешение, например, 320x240.

Структура программы

Программа состоит из двух основных частей, это ядро и утилиты:

1. Ядро

a. video.c - генератор видео синхронизации сигналов. Он использует один 16-битный таймер/счетчик в режиме быстрой ШИМ без задержки цикла для высокоточной генерации сигнала синхронизации. Шаблон сигнала описан как определение (define) во флеш, при этом очень легко переключаться между видео стандартами в режиме исполнения программы. Модуль настраивается в video.h или config_hw.h и config_screen.h.

b. DRIVER.S - графический видео драйвер. Драйвер вывода видео в порт. Модуль написан на ассемблере. Он производит 4-битный видео поток пикселей с периодом цикла 5 пикселей. Ширина блока фиксируется на 8 пикселей. Разрешение и размер блока могут быть изменены. Он поддерживает один блок прокрутки вдоль горизонтальной оси. Модуль настраивается в driver.h или config_hw.h и config_screen.h.

2. Утилиты

a. window.c - утилита вертикального отображения экрана. Модуль может разделять экран для вертикальных секций. Каждый может иметь различные параметры, например: прокрутка, цвет маски, таблицы текстур и т.д. модуль настраивается в window.h или config_utils.h.

b. overlay.c - плавающий рендеринг изображений. Использование оперативной памяти драйвера для возможности отображения плавающих изображений. Это обеспечивается мощным API overlay_draw(. ) который ведет себя точно так же как putimage(. ) в полноценной графической окружающей среде. Он поддерживает обрезание, зеркалирование, прозрачность и т.д. модуль настраивается в overlay.h или config_utils.h.

c. background.c - поблочный рендеринга изображения. Драйвер использует PGM отображение для вывода статичных изображений. В сочетании с прокруткой, он может отображать гладкое отображение игры с возможностью вертикальной прокрутки. Модуль настраивается в background.h или config_utils.h.

Простейший пример использования функций вывода текстовой строки через драйвер видео AVGA.

Требования к аппаратному обеспечению

AVGA успешно протестирована на следующих контроллерах:
ATmega16
ATMega88
ATmega168
ATMega128 (разогнан до 19.6608MHz)
ATMega644

Подключение AVR к монитору

Для своей работы система нуждается в одном 16-битном AVR таймере/счетчике. Горизонтальной сигнал синхронизации подается через выход OCRxB таймера. Выходной порт вертикальной выходной синхронизации может быть настроен в config_hw.h. Поток пикселов появляется при выставлении верхних тетрад порта. Поток пикселов может быть преобразован с помощью резисторного ЦАП в видео RGB со стандартной 16 цветной EGA/VGA палитрой.

Резистивный 4-х битный ЦАП


Резистивный 4-х битный ЦАП

Где R1 = R2 = R3, R4 = R5 = R6 и R7 = R8 = R9;

Регулируя отношения R1:R4, легко меняется контраст между нижней и верхней границей цветной гаммы. Фактические значения резистора зависит от входного уровня монитора и импеданса. Вот несколько примеров:

ЭЛТ-монитор VGA и аналоговый ТВ PAL с разъемом SCART (75 входов Ом):
R1 = R2 = R3 = 470R
R4 = R5 = R6 = 680R
R7 = R8 = R9 = 100R

Sony PSOne TFT экран (высокий импеданс входа):
R1 = R2 = R3 = 2k2
R4 = R5 = R6 = 3k3
R7 = R8 = R9 = 1k

Цветовая палитра, полученная с ЦАП


Цветовая палитра, полученная с ЦАП

Кроме того, R2R лестница может быть использована для создания 16 цветных оттенков серого. Такой сигнал может быть, например, смешан с VSYNC непосредственно для создания Ч/Б композитного видео.

Аппаратная реализация системы видеовывода AVGA

Схема системы видеовывода AVGA

Напряжение сигнала синхронизации снижается до требуемого уровня благодаря использованию резисторных делителей R11 и К12. В результате линии: R, G, B и VSYNC (HSYNC) могут быть подключены непосредственно к монитору (например, VGA D-Sub, разъем SCART, . ) или к устройству преобразования сигнала RGB в композитный (например, AD725).

Выход аудио сигнала через вывод OCR2B таймера Т2 должен быть подключен через конденсатор между входом и выходом аудио для удаления постоянной составляющей тока и резисторного делителя для уменьшения уровня громкости.

Фото собранного устройства в выводном исполнении представлено ниже:

Плата на Mega168


Плата на Mega168

Программная реализация системы видеовывода AVGA

Библиотека драйвера видеовывода AVGA находится в архиве AVGA_release_022.zip. Описание API функций, для работы с библиотекой в файле AVGA_0_2_API_pre.pdf.

Фото и видео, демонстрирующее возможности библиотеки AVGA:

AVGA

Пример фото и видео игры Super Mario, созданной с применением библиотеки AVGA, запущенной на плате "AVRmario":

AVRmario

AVRmario

AVRmario

AVRmario

Пример фото и видео игры Pacman:

Pacman

Pacman

Примеры схемы и платы:

Версия в выводном исполнении

Описание:
Имеет CINCH разъемы для подключения аудио и каждого цвета (VSYNC только), стабилизатор напряжения 78L05 и шесть кнопок, извлеченных из старой AT клавиатуры.

Файлы:
m168/schematic.jpg схема в формате png
m168/schematic.sch схема в формате sch (eagle)
m168/layout.brd файл трассировки печатной платы (eagle)
m168/config_hw.h файл настроек конфигурации драйвера AVGA

Версия от Slime2k's "AVRmario" в SMD исполнении

Файлы:
SuperMario/Supermario.sch Файл схемы
Supermario/Supermario.brd файл трассировки печатной платы (eagle)
Supermario/supermario_board.pdf pdf файл с трассировкой печатной платы
Supermario/config_hw.h файл настроек конфигурации драйвера AVGA

Файлы драйвера:
AVGA/AVGA_release_022.zip Драйвер системы вывода графики в аналоговом виде
AVGA/v01_demo.zip Демо проект
AVGA/AVGA_0_2_API_pre.pdf Справочник по API функциям AVGA

При написании статьи использовались следующие источники:

В статье Текстовый VGA-модуль для микроконтроллеров я рассказывал о доработанном варианте терминала 64х30 символов. 15 цветов. Всё хорошо, сделал плату, допилил софт под себя, но текст это текст. Только символы и только 8х16. Можно конечно рисовать псевдографикой. Таблички выходят на ура. Я даже написал колхозную функцию увеличения цифр. Работает достаточно шустро:

И что-то можно изобразить похожее на интерфейс

Но, черт возьми, как рисовать диагональные линии ? В принципе, если хорошенько дунуть пораскинуть мозгами, то можно из этой таблицы символов


выкинуть всё не нужное и заменить на своё. Как собственно это сделано с логотипом Microchip. (Символы с кодами с 0x80 по 0x98, выстроенные в 5 рядов по 5 символов, образуют графическое изображение логотипа Microchip.) Ну то есть взять и выкинуть например английский алфавит. Или русский. Или всякие стрелочки и параграфы с тильдами и стрелочками. Получаем кучу символов, которые можно перерисовать и сделать части окружностей, дуг, диагональные линии и.т.д. Потом наколбасить библиотеку, которая будет рисовать кривые этой псевдографикой. Но что-то это сильно пахнет адским геморроем и я начал искать варианты с графикой.





// отображение пикселя
case WORK_PUT_PIXEL:
break;

В итоге функция рисования линии по двум точкам стала одной функцией а не тремя. (Хотя я понимаю, это было для быстродействия). Мой код в этом нисколько не проиграл. Функцию рисования окружностей сделал по алгоритму Брезенхэма. У Этого дядьки окружности более округлые. Переписал все команды по-своему, а их там 31. Сделал рисование не только белым, но и черным. Задаваемую толщину линий. Закраску прямоугольников и окружностей. Встроил второй громадный шрифт. Запилил пропорциональное увеличение шрифта 8*16 на заданную величину множителя. Убил весь обратный вывод в UART. Не нужно ничего отвечать на команды. Просто рисуй быстрее. Одно подтверждение обработки команды тормозит вывод графики в десятки раз. Естественно добавил кольцевой буфер на 1024 байта. Конечно UART в этом смысле достаточно убогий по скорости интерфейс, но зато более универсальный. Во-первых, в микроконтроллере их может быть несколько, а во-вторых, можно и в ПК воткнуть. I2C интерфейс убил по-этой же причине. Да и в скорости он не сильно выигрывает, особенно софтварный.


Далее пошли первые тесты. (фотографировал на тапок)


Округлые окружности


Прямоугольнички

А дальше пошел писать библиотеку для ардуино. В этом плане всё проще. Берем стандартный класс SoftwareSerial и наследуемся от него, добавляя свои функции.

Можно конечно юзать и HardwareSerial, но их в ардуине гораздо меньше чем SoftwareSerial 🙂 Cофтовый UART спокойно работает на 115200 и в arduino nano (Atmega328) и в arduino pro micro (Atmega32u).

class VgaSoftwareSerial : public SoftwareSerial <
public:
VgaSoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false);

void cls(void);
void pixel(int x1, int y1, uint8_t color);
void setcolor(uint8_t color);
void setcursor(uint8_t x1, uint8_t y1);
void line(int x1, int y1, int x2, int y2, uint8_t color);
void rectangle(int x1, int y1, int x2, int y2, uint8_t color, uint8_t filling);
void circle(int x1, int y1, uint8_t color, uint8_t radius, uint8_t filling);
int version(void);

Собственно всё рисование сводится к последовательной подаче байт в UART.

void VgaSoftwareSerial::pixel(int x1, int y1, uint8_t color)
<
uint8_t buf[] = x1, // значение X1 Lo
0x10, // команда установки X1 Hi
x1 >> 8, // значение X1 Hi
0x13, // команда установки Y1 Lo
y1, // значение Y1 Lo
0x12, // команда установки Y1 Hi
y1 >> 8, // значение Y1 Hi
0x03, // команда установки цвета пикселя
color, // значение цвета пикселя
0x0A // команда рисования пикселя
>;
VgaSoftwareSerial::write(buf, 11);
>

А так рисуется линия:

В самом скетче всё еще проще:

И на обоих мониторах рисуется точка по центру.

Обкатанные платы были заново отрисованы в DipTrace и отправлены на завод.

Изменилась схема питания. Применен прекраснейший DC-DC преобразователь LM3671MF. Платы стали еще меньше.



И это, на минуточку, PIC32. Расту над собой 🙂


Такими же нехитрыми командами был наколбашен тест всего что есть в модуле.

В дальнейшем использовал сей девайс для отрисовки приборной панели для второй версии автомобильчика.

Ну и 3D до кучи:

Данный VGA-модуль доступен в 4х вариантах исполнения и вы можете его приобрести в соответствующем разделе.

Буду рад вопросам и комментариям. Еще больше буду рад рационализаторским предложениям.

Читайте также: