Avr генерация сигнала на vga

Обновлено: 07.07.2024

Простой VGA /Видео адаптер

(Что, в свое время дало мне "хорошего пинка" в деле мотивации

совершенствования моих познаний в области микроконтроллеров).

Предыстория проекта.

Несколько месяцев назад, задавшись целью подключить VGA-монитор для вывода текстовых данных с микроконтроллерной системы сбора информации - я с удивлением обнаружил, что ничего сколько-нибудь "внятного" и доступного для повторения “ на коленке ” по этой теме в Интернете отсутствует.

Хотелось что-то гораздо более “дешевое и сердитое”. Предварительные прикидки показывали, что из наиболее распространенных и достаточно быстродействующих микроконтроллеров подходит продукция фирмы ATMEL.

Результат своей работы я представляю на ВАШ суд.

Поставленная техническая задача:

Цель которую я поставил для себя, достаточно проста на первый взгляд:

Ограничившись одним корпусом распространенного MCU типа Mega8,16,8535

и т.д., и минимумом внешних элементов сконструировать символьный дисплей-адаптер с разрешением > 15x15 символов, который бы выводил информацию на VGA монитор при стандартных частотах VGA сигнала. Информацию символьный адаптер должен получать через стандартный USART порт микроконтроллера. Частота используемого микроконтроллера стандартная -16M H z.

Данная задача на данный момент успешно решена.Более того - проект несколько расширен и дополнен введением формирования обычного видео ч.б. ( PAL / SECAM ) сигнала. Т.е. в зависимости от положения джампера тип формируемого видео сигнала VGA либо Composite Video .

Фотографии и схемы проекта:

Ниже приводится принципиальная схема простого VGA/ Video адаптера (откорректировано 28.06.2011):

Принципиальная схема откорректирована, на старой схеме были ПЕРЕПУТАНЫ положение порта PAL-синхронизации и джампера PAL - VGA!Из-за этого в "железе" у многих схема НЕ РАБОТАЛА.


Так все это выглядит в железе, собранном на “коленке” за один час:


А вот что мы получаем на экране монитора:



Технические характеристики проекта:

Технические характеристики VGA-адаптера:

Количество символов: 20 строк по 20 символов

Разрешение матрицы знакогенератора: 8x12 точек

Кодовая таблица знакогенератора: WIN 1251

Формируемый сигнал: VGA

Частота кадровой синхронизации: 60Hz

Скорость обмена UART 19200 bps

Технические характеристики Video -адаптера:

Количество символов: 20 строк по 38 символов

Разрешение матрицы знакогенератора: 8x12 точек

Кодовая таблица знакогенератора: WIN 1251

Формируемый сигнал : Composite Video(PAL/SECAM)

Разрешение: 625 строк (чересстрочная)

Частота кадровой синхронизации: 50Hz

Скорость обмена UART 19200 bps

Тип используемого микроконтроллера: Mega 8, Mega16, , Mega32, Mega8535 и т.д.

Тактовая частота микроконтроллера стандартная - 16Mhz

  1. Для того чтобы избежать искажения изображения при приеме данных через UART, для VGA рекомендуется производить обмен данными с адаптером в течении приблизительно 300-600 мкс после сигнала вертикальной синхронизации VSYNC (во время обратного хода луча по кадру).
  2. Объема RAM памяти Mega 8535 (512 байт) не достаточно для формирования Видео сигнала с разрешением 38 x 20 символов.

Алгоритм работы программы:


Пояснения по работе программы:

Алгоритм рендеринга изображения достаточно традиционен, главное ноу-хау проекта в использовании для побитного вывода изображения – сдвигового регистра SPI SPDR через бит MOSI . При этом образуется двухступенчатый конвейер рендеринга:

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

предыдущий байт выводится через сдвиговый регистр SPI SPDR MOSI ..



Поскольку данный проект написан на С (WinAVR GCC), он легко масштабируем для увеличения разрешения и частот регенерации дисплея. Так, на микроконтроллерах Mega 48,88,168 поддерживающих официальную тактовую частоту 20 MHz возможно получение разрешения 20 строк по 25-30 символов при абсолютно той же схемотехнике (возможности оверклокинга автор намеренно не рассматривает). Применения проекта не ограничиваются одним лишь терминальным вариантом (смотрите примеры в папке examples ) – не смотря на серьезную загруженность процессора регенерацией дисплея, оставшейся мощности вполне достаточно для организации обработки например нескольких цифровых и аналоговых сигналов и реакции на них, а также выдаче результатов их измерений на дисплей в real - time (охранные системы, АСУТП, КИПиА и т.д.). Автор располагает улучшенными вариантами подобных систем с разрешением символьного дисплея 40 x 24 символов в режиме VGA , работающими в коммерческих изделиях.

Исходники подкорректированы под WinAVR-20090313 portable ( "пофиксена" специфика команд: cbi, sbi, PRG_RDB etc.),
не устранены некоторые warnings, думаю они не критичны.

Полезные ссылки:

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

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

Неплохо о видеосигнале написал 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. Синхроимпульсы

Современная техника не стоит на месте и когда-то казавшиеся сложными ЭВМ состоящие из множества микросхем и прочих радиоэлементов в наше время могут быть заменены всего одним дешевым микроконтроллером, способным выполнять функции когда-то современного компьютера. В данной статье будет рассказано как с помощью одного микроконтроллера 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-адаптера:
Количество символов: 20 строк по 20 символов
Разрешение матрицы знакогенератора: 8x12 точек
Кодовая таблица знакогенератора: WIN 1251
Формируемый сигнал: VGA
Разрешение: 640x480
Частота кадровой синхронизации: 60Hz
Скорость обмена UART 19200 bps

Технические характеристики Video-адаптера:
Количество символов: 20 строк по 38 символов
Разрешение матрицы знакогенератора: 8x12 точек
Кодовая таблица знакогенератора: WIN 1251
Формируемый сигнал: Composite Video(PAL/SECAM)
Разрешение: 625 строк (чересстрочная)
Частота кадровой синхронизации: 50Hz
Скорость обмена UART 19200 bps
Тип используемого микроконтроллера: Mega8, Mega16,, Mega32, Mega8535 и т.д.
Тактовая частота микроконтроллера стандартная — 16Mhz

Ресурсы (ATmega16): 1/3 flash (

5 кБ, но это и VGA тоже) и 2/3 ОЗУ (

750 байт — это экранный буфер), SPI на половине частоте кварца (16 МГц / 2 = 8 МГц) и 16-разрядный таймер, который формирует 64 мкс интервалы. Причём контроллер в главном цикле постоянно загоняется в режим «сна», чтобы по прерыванию от таймера занятся наложением видеосигнала на синхросигнал. Вся фишка тут только в аппаратной возможности быстро формировать видеосигнал при помощи линии данных SPI.

С синхронизацией пока не очень, но для лабораторных студентам — самое то.

Комментарии ( 36 )

У меня уже накопилось несколько предложений чего бы в PBII добавить:

1. Улучшить поле кнопок. Какой смысл иметь три вывода и управлять всего тремя кнопками? Всего 6 диодов и можно при помощи 4-х линий сканировать всё кнопочное поле (12 кнопок) на PBII.

2. Добавить схемы примитивной логики:
— для инвертирования;
— для селекции (CS);
— мультиплексирования/демультиплексирования;
— сдвиговый регистр.

3. Хотелось бы конечно что-то вроде контроллера прерываний, шину адреса и шину данных ;), но для двухслойной платы это можно сделать разве что с плис на борту, т.е. какую-нить многоногую плис и всех к ней подрубить, а всю разводку, что обычно делают в слоях, делать, прошивая плис. Может хватить и двух слоёв, заодно навыки работы с плис на плате — сам доразводишь её внутренности как надо.

4. Добавить RTC на плату. Что-нить любое, но было бы не плохо, чтобы можно было использовать в контроллере прерывание от RTC (на забыть про батарейку).

5. Внешние интерфейсы ;) хочу всё и много:
— 2 PS/2 разъёма, а то я не понимаю как можно использовать одновременно мышку и клаву (как с USB);
— если SimpleVGA проектик нормально заработает с синхронизацией, то не жалко будет поставить на плату VGA разъём и S-Video, для работы с видеосигналами (со звуком) — пусть лучше такой примитив, чем вообще никакого (всего-то 4 резистора и пару диодов + несколько штекеров);
— 485-й опторазвязанный, чтобы можно было потом плату не только в шкафу держать, но и реально куда-нить поставить на службу Отечеству;
— Ethernet с микрочиповским чипом, думаю, что пора.

1. Не стоит. Но можно сделать насадку подобно той, что ты применил. Повысится универсальность.
2. Можно подумать, но не знаю куда бы это впихать, т.к. плата и так размером с материнку.
3. Не нужно. Такие вещи встраивают уже в целые микропроцессорные комплексы, вроде кр580. Если что, то их можно реализовать в виде продвинутого процессорного модуля (возможно он будет из нескольких плат бутербродом).
4. Можно подумать о добавлении RTC на iic. А еще его можно сделать субмодулем, вставляющимся на ту же шину, но над процессорным блоком.
5. Можно сделать спец кабель, выведя туда сразу оба какнала PS/2 Для отладки пойдет, использовать же два PS/2 нерационально. Они занимают прорву места, а юзаются редко.

VGA — на плату не нужно, но модуль можно забабахать.
485 — в разработке, ща dcoder вылижиет все косяки и недоработки и пустим в производство.
Эзернет пиковский уже по идее должен ко мне ехать. Протестю и гербер на производство отдам.

6. Можно сделать субмодулем.

Я всё хочу один промышленный девайс повторить, который управляется по MODBUS'у. Когда-то давно сопровождал такой на 128 меге. Была у меня мечта в квартире автоматизацию сделать своими руками. Я его потихоньку портирую на PBII. Мне осталось не много: I2C флешку подключить, MMC карточку, 485 интерфейс через Modbus и всё. Со стороны компа у меня уже всё есть, кроме безлимитного OPC-сервера (ломалку для Lectus Modbus OPC я не нашёл).
У меня есть куча исходников, но они все разношёрстные, а мне хочется универсальности и побольше классов для работы с периферией и чтобы собиралось везде и чтобы в Протеусе моделировалась :), и ещё что-нибудь и побольше, побольше.

Я думаю, что куда интереснее было бы изучать работу с контроллерами, если бы, к примеру, плату PBII можно было использовать как настоящий микроПЛК со всеми «прибамбасами». Кнопочки и лампочки — это, конечно, хорошо. А вот если у тебя PBII будет круглосуточно и вечно наблюдать за «точками» в квартире/доме и архивировать данные в удобном промышленном формате (при помощи ibaPDA) — это уже по-взрослому, как у реальных автоматчиков.

Всего 6 диодов и можно при помощи 4-х линий сканировать всё кнопочное поле (12 кнопок) на PBII.

Как? 4 выводов в принципе хватит на чарлиплексинг 12 кнопок, но диодов на него надо вдвое больше. Но матричная клавиатура гораздо чаще используется, а это платформа для макетирования.

Пункты 1, 2, 4, 5, 6 можешь реализовать сам в виде плат расширения. Если какие-то из них будут удачны — то и в производство пойдут.


Привет хабр — в этой статье я собираюсь поделиться своими успехами в освоении ПЛИС Altera Cyclone III. После мигания лампочками и игр со счетчиками — решил сделать что то более серьезное. Сделал я простейший VGA адаптер. Об основных его частях и пойдет речь. Статья больше ориентирована на начинающих, так как для опытных эта задача не составит труда, но для освоения, на мой взгляд — хорошая тренировочная задача. Эксперименты я свои провожу на отладочной плате Altera DE0. Описывать схему я буду на Verilog, Среда — Quartus II v 12.0. Итак — добро пожаловать под кат:

  • Графический контроллер (Graphics Controller), посредством которого происходит обмен данными между центральным процессором и видеопамятью. Имеет возможность выполнять битовые операции над передаваемыми данными.
  • Видеопамять (Display Memory), в которой размещаются данные, отображаемые на экране монитора. 256 кБ DRAM разделены на четыре цветовых слоя по 64 кБ.
  • Последовательный преобразователь (Serializer или Sequencer) — преобразует данные из видеопамяти в поток битов, передаваемый контроллеру атрибутов.
  • Контроллер атрибутов (Attribute Controller) — с помощью палитры преобразует входные данные в цветовые значения.
  • Синхронизатор (Sequencer) — управляет временны́ми параметрами видеоадаптера и переключением цветовых слоёв.
  • Контроллер ЭЛТ (CRT Controller) — генерирует сигналы синхронизации для ЭЛТ.
  1. Синхронизатор — частота 50 мегагерц для нас не очень удобна, поэтому её придется немного изменить
  2. Контроллер ЭЛТ, который будет выдавать сигналы синхронизации в соответствии с требованиями стандарта VGA
  3. Генератор картинки — будем использовать для отладки — блок будет рисовать простейшую картинку и выдавать её контроллеру ЭЛТ

Синхронизатор


Начнем с того, что лезем на Английскую Вики и смотрим Signal timings для VGA, откуда узнаём, что частота синхрогенератора должна быть 25,175 МГц.

Вот нам и первая задача — сделать из 50 МГц — 25.175 МГц. Поможет нам в этом деле PLL или ФАПЧ.
При помощи Mega Wizard'а создаём наш PLL с нужными настройками. Для этого идем Tools/MegaWizard Plug-InManager. Там выбираем тип выходного файла Verilog HDL I/O ALTPLL и настраиваем его — устанавливаем входную частоту и затем её преобразовываем. Нам нужно получить частоту 25,175 МГц, при этом мы можем только умножать и делить на целое число, то есть нам нужно перевести число 0,5035 в дробь. Можно умножить на 5035 и поделить на 10000, но заметим, что можно сократить оба числа на 5. Получаем дробь 1007 / 2000. При этом визард сам приблизит требуемый множитель доступной ему дробью. Включаем полученный модуль в проект подключаем на его вход наш клок с платы, а для выхода создаём wire, который потом куда нибудь заведем, главная цель этого пункта достигнута — получить частоту 25,175 МГц.

Контроллер ЭЛТ

Генераторы синхроимпульсов



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

То есть мы должны перед выдачей данных подержать линию синхронизации в высоком состоянии время А, потом прижать к земле на время B, потом перевести в высокое состояние, подождать время C и только потом идет поток данных — лучик начинает пробегать строчку за время D и мы за это время должны успеть установить все пиксели с частотой 25,175 мегагерц и так для каждой строки. Вертикальная синхронизация работает почти так же, только вместо пикселей мы передаём строчки и за один период синхроимпульса отрисовываем весь кадр.
Задача определилась — создать блок, который реализует описанную выше последовательность, принимая на вход частоту VGA_CLK, из входов еще добавим, пожалуй, сигнал сброса. Реализация такого блока не проста, а очень проста:
При периоде 1/VGA_CLK = 0,03972194637537239324726911618669 микросекунд нам нужно 24 такта на A, 95 на B, 48 на C, и 640 на D. То же самое и для вертикальной синхронизации, но тут удобнее тактироваться не по тактам частоты в 25.175 мегагерц, а по восходящим фронтам сигнала горизонтальной синхронизации, тогда все задержки можно считать в периодах отрисовки строчки. Кроме того у нас есть область «холостого хода» на экране, реально — по тактам экран чуть больше, а рисовать мы должны только в видимой области, поэтому желательно еще, чтобы модуль нам сообщал текущие координаты лучика, да и если мы собираемся назначать каждому пикселю какой то цвет — без знания текущей позиции луча не обойтись.
Модуль вывода


Собственно импульсы сгенерированы, координаты точки известны, осталось только вовремя включать нужный цвет, пока лучик пробегает строчку — для этого создадим модуль, которому на вход идут сигналы синхронизации, частота 25,175 МГц, 3 шины цвета и координаты, а выход — 4х битный R-2R ЦАП для каждого цвета, ну и далее — VGA разъем


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


Получилась вот такая вот структурная схема:


Ну и видео работы:

В общем — первый шаг с созданию своей видеокарты сделан — осталось приделать видеопамять и связать это всё с внешним контроллером — например STM32. В перспективе хочется сделать, чтобы контроллер генерировал видеопоток и посылал его видеоадаптеру, а тот выводил на экран. О практическом смысле этого всего говорить конечно не стоит — вещи уже устаревшие и довольно примитивные, всё делалось лишь с целью обучения и закрепления навыков, где то конечно тут набыдлокодил, так что если есть какие то вопросы, советы и замечания — пишите в комментариях

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