Игровая видеоконсоль на avr avga

Pinboard II (AVR) формирование ч/б видеосигнала

Простой VGA/Видео адаптер
(проект по формированию VGA сигнала при помощи 8-ми битных MCU фирмы AVR)

Технические характеристики проекта:
Технические характеристики VGA-адаптера:
Количество символов: 20 строк по 20 символов
Разрешение матрицы знакогенератора: 8×12 точек
Кодовая таблица знакогенератора: WIN 1251
Формируемый сигнал: VGA
Разрешение: 640×480
Частота кадровой синхронизации: 60Hz
Скорость обмена UART 19200 bps

Технические характеристики Video-адаптера:
Количество символов: 20 строк по 38 символов
Разрешение матрицы знакогенератора: 8×12 точек
Кодовая таблица знакогенератора: 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.

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

  • pinboard2,
  • avr,
  • pal,
  • video
  • 02 марта 2012, 02:07
  • uni

Комментарии ( 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 с микрочиповским чипом, думаю, что пора.

6. Подумать на счёт лучшей «аудиосистемы», что-то по типу вот этого: AN #165 — RC2 sound / Voice playback (Part 1). Там два вывода используется и немного дополнительных деталей. В архиве есть пояснение как такая штука работает с графиками и пр.

  • uni
  • 02 марта 2012, 04:52

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

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

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

  • DIHALT
  • 03 марта 2012, 22:35

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

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

  • uni
  • 03 марта 2012, 23:30

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

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

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

Игровая видеоконсоль на avr avga

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

(проект о формированию VGA сигнала при помощи 8-ми битных MCU фирмы AVR)

Эта статья была опубликована в Atmel Application Journal #6 Winter 2006

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

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

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

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

Конечно, существуют промышленные платы стандарта PC-104, можно кое-что “нарыть” и на www.opencores.org для реализации на FPGA, есть графические контроллеры Fujitsu , кто-то здесь недавно на местной конференции предлагал за 5000$ проект на ACEX ’е , но надо признать — все это страшно далеко от народа..

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

8-ми битное RISC ядро AVR обеспечивает пиковую производительность порядка 16 MIPS на тактовой частоте 16M H z. Плюс на подходе более скоростные семейства Mega 48,88,168 поддерживающие официальную тактовую частоту 20 MHz .При этом скорость вывода данных через стандартный порт ввода-вывода при FOSC = 16 MHz командами вывода в порт (out port x..) 8 MIPS. К тому же я уже имел достаточный опыт разработки устройств на микроконтроллерах AVR. И я засучил рукава..

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Кодовая таблица знакогенератора: 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, думаю они не критичны.

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

За дальнейшим развитием проекта следите за: http :// www . vga — avr . narod . ru /

Ибрагимов Максим Рафикович

20.10.2005 г. Откорректировано 6.2011

Игровая видеоконсоль на avr avga

Возможность генерации видео при помощи микроконтроллеров avr заинтересовала меня с полгода назад. Потратив совсем немного времени на поиски в интернете я нашел достаточно большое количество проектов различных авторов позволяющих генерировать видеосигнал.
Несмотря на достаточно большое количество конструкций в глаза бросались два основных ограничения подобных проектов:
Первое, вывод только черно-белого изображения, для цветного у контроллеров AVR или PIC просто не хватает быстродействия.
Второе, низкое разрешение экрана, на уровне 160х100 точек — что конечно очень и очень мало для генерации на экране чего нибудь содержательного.. Это ограничение исходило из низкого быстродействия используемых микроконтроллеров.
Например, тактовая частота микроконтроллера ATMEGA32, без разгона, 16 мгц. Микроконтроллер на языке ассемблера выполняет операции за 1-5 тактов, нужные нам операции для генерации видео это загрузка регистров, сдвиг, выдача бита в порт вводавывода занимают 1 такт, различные операторы переходов (для организации циклов и ветвлений) 2 такта.
Таким образом реальные возможности микроконтроллера по генерации видеосигнала фактически подходили только для генерации изображения по качеству намного хуже какого нить давно забытого многими ZX-Spectrum.
Причем, низкое разрешение экрана — это ограничение не только быстродействия, но и зачастую объема памяти ОЗУ в микроконтроллерах: например, такой контроллер как ATMEGA16 имеет на борту всего 1 кб оперативной памяти. Если принять что один бит ОЗУ соответствует одному пикселу изображения, то максимум который мы сможем получить 1 кб * 8 бит в байте = 8192 пиксела изображения на экране.
Выше я указал разрешение 160 на 100 точек, это 16000 пикселов, для хранения которых нужно 16000 пикселов 8 бит = 2000 байт ОЗУ (уже видно что на ATMEGA16 графические изображения без ухищрений не получить никак — просто нет памяти !)

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

Но в поиске мне повезло и я набрел на ресурс http://vga-avr.narod.ru/main_rus.html в котором подчерпнул идею как можно ускорить выдачу изображения на телевизор, с этого момента идея генерации видеосигнала силами AVR микроконтроллера завладела моей головой 🙂

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

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

.
Электронный луч рисует изображение. Две части изображения образуют одно сплошное.

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

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

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

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

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

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

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

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

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

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


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


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

.org 0
cli ; на всякий случай запретим прерывания

; настроим порты
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

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

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

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

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

Как я делал игру под AVR

Уже давно было желание написать статью по какой-нибудь поделке. Но изо дня в день, читая очередную статью про очередной «умный дом» или «умную метеостанцию на Ar. » все меньше хотелось написать точно то же самое, но с другого ракурса, а тем у меня было не много. И вот однажды…

Внимание! Под катом кривой код, пара изображений и много воды.

Все началось с того, что как-то раз заметил свою вторую половинку за игрой про некогда популярный интернет-мем «Nyan Cat», мне он настолько понравился, что я неудержимо захотел сделать с ним игру! Беглый поиск на наличие подобных статей на GT и H дал нулевой результат. В принципе не удивительно, мало кто сегодня будет заморачиваться и делать подобное (знаю, что есть GameBuino, но на GT и H нет ни одного упоминания). Что ж, раз пусто, значит, заполним эту пустоту!

Сделать нечто в ретро стиле, что-нибудь простое… И конечно же! На ум сразу приходит классика жанра — Space Invaders. Что может быть проще, чем сделать свой клон?

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

Железо

Микроконтроллер Atmel AVR ATmega328P на частоте 16 МГц (плата Arduino Nano). Экран ILI9341 SPI TFT 2.4” 320×240 и резистивный сенсорный экран на драйвере XPT2046 (китайский клон ADS7846). Заказан экран с Али (предназначался под осциллограф на STM32), о чем сперва пожалел, так как нормально работающих библиотек под драйвер сенсорного экрана почти нет. Впоследствии с этого был профит в виде сносно работающей библиотеки, хоть и собранной из кусков.

К сожалению, в силу своей титанической ленивости, на первых порах использовалась Arduino IDE. Потом из-за разросшегося проекта там стало тесно, и я перешел на Sublime Text 2 с последующим прикручиванием Arduino IDE (библиотеки, компилятор – слишком тяжело отказаться). Под конец, ради спортивного интереса и оптимизации собрал все в Atmel Studio (Кто-то скажет, что сразу надо было писать там! Как уже писал: просто лень). В итоге так и оставил все под Arduino IDE, исходя из соображений, что далеко не у каждого есть желание ставить и разбираться с Atmel Studio.

Изображения

Поскольку ресурсы контроллера весьма скромны, то впоследствии от некоторых идей пришлось отказаться (например, фон стал одноцветный, хотя в планах была текстура). Более того пришлось перечитать кучу статей по NES, именно из них я почерпнул некоторые трюки по оптимизации.

Первая проблема началась с изображений, а именно из-за их размера. Места просто не хватало. Экран принимает цвета 16 бит на пиксель, т.е. мы рисуем картинки в RGB565. Читать изображения через SPI с SD карты без DMA очень затратно и долго.
Например, картинка ниже занимает при размере 51х20 — 1360 байт, но для нормальной анимации таких нужно 6!

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

Например, радугу можно сделать из двух картинок, что на четыре меньше! Далее тело. Это одно и то же тело на всех 6 кадрах! Вместо 6 используем одно! Идентично с головой. Остальное не содержит повторений (или можно пренебречь).

Собирается все воедино на экране, поскольку он не очищает изображение, а хранит его во внутреннем буфере, что так же накладывает определенные ограничения. Например, если сначала отрисовать голову, а потом тело, то выглядеть это будет так:

После того как остался набор отдельных изображений, они все равно много занимают (5504 байт вместо 8160).

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

То размер радуги уменьшится c 2016 байт до 16 байт + примерно 200 байт на код. При этом, немного потеряв в производительности.

Промежуточный итог №1.

Высвободилось примерно 1800 байт (целый кот занимает 3704). Можно сделать меньше? Конечно! Вместо огромных массивов с цветами использовать два массива: один таблица цветов с типом uint16_t, второй изображение, но вместо цветов индексы нужного цвета в таблице цветов. Для этого уже вполне подойдет uint8_t ( для 255 цветов вполне хватит, привет GIF).

Промежуточный итог №2.

Освободилось еще 1944 байт (целый кот теперь занимает 1760). Можно сделать меньше? Можно! Внимательно смотрим на массивы и видим колоссальные однотипные последовательности! Бежим читать про RLE сжатие (забавное совпадение, через некоторое время, когда уже сделал кодер и декодер, на H появилось несколько статей на тему RLE, как мне не хватало их несколько раньше).

Если с декодером проблем не возникло, я четко знал, что у меня будет на входе и что я буду со всем этим делать, то вот с кодером как раз наоборот…

На вход декодера идет:

— координаты на экране где выводим изображение;
— высота и ширина в пикселях;
— таблица с индексами цветов;
— таблица цветов;
— размер сжатого изображения.

Кодер написал как смог на Qt (собирал статику Qt 4.8.6 под OS X). Суть кодера: сжать идентичные последовательности в файлах изображений и поместить результат в заголовочные файлы.

Вышел он очень привередливый к входным изображениям. Нужно убирать альфа канал и экспортировать как raw data RGB565, хорошо хоть в Gimp это делается легко. Использование: помещаем в папку с программой *.data файлы изображений, запускаем, и на выходе заголовочные файлы.

Промежуточный итог №3.

Места стало больше всего на 229 байт (все вместе занимает 1531). Отчего так мало? Не стоит забывать, что из-за некоторых проблем с отрисовкой (неправильное наложение цветов) сжато по RLE было только тело. Так же, я не рассматривал изображения Invaders и подарка, которые так же были сжаты по RLE и уменьшили свой размер с 3456 байт до 722 байт.

Дальше, скорее всего, будет куда более сильное падение производительности на распаковке или нехватка памяти (в зависимости от алгоритма), так что остановлюсь на этом.

Многозадачность

Вторая проблема пришла с ростом количества задач. В начале, задач было мало и все выполнялись последовательно, вполне быстро — 20-28 кадров в секунду. Со временем, рост количества задач привел к падению до 7-10 кадров в секунду! Сначала думал о банальной нехватке ресурсов ЦПУ, уже планировал перейти на более серьезный МК. Но меня осенило! Я ведь делаю действия, которые, по сути, не требуют постоянного выполнения в каждом цикле! Нужно размазать задачи во времени, сделать подобие многозадачности!

Первое что пришло на ум: FreeRTOS… К сожалению, при 16 (17 если вывод debug info) задачах это оказалось не по силам этой AVR.

Поиск решения приводил в основном к статьям DIHALT. Изучив их, сделал свой велосипед менеджер задач. Что есть:

— добавление задачи (как же без этого);
— удаление всех или одной задачи;
— замены одной задачи на другую;
— количество задач до 254 (по факту, сколько хватит памяти);
— 9 байт на задачу (можно и меньше).
— используется timer 0 в качестве системного таймера;
— таймаут вызова задачи (ради этого все и делалось);
— флаг необходимости исполнения задачи;
— глупая защита от не выделения памяти синим экраном;
— указатели, много указателей;
— . ;
— PROFIT.

И некоторое немногое другое, что мне было нужно для моего велосипеда менеджера задач. Принцип работы:

— создаем структуру (в ней указатель на массив и количество текущих задач);
— указываем что это наш основной массив задач;
— добавляем все задачи, какие нужно;
— вызываем функцию runTasks() и больше оттуда не возвращаемся.

В основном цикле перебирается весь массив задач. Задачи выполняются только по таймауту и если флаг на выполнение в истине.
На счет эффективности решения ничего говорить не буду, просто напишу, что стало значительно лучше! Даже эта кривая реализация разгрузила ЦПУ и падение частоты кадров пропало от слова совсем.

Полет в космос

В оригинале кот летит в космосе мимо звезд (судя по синему фону летит на околосветовой), не беда прикрутим звезды и будем их двигать!

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

Но звезд на экране может поместиться много, неужели придется писать координаты для каждой? Нет, присвоим псевдослучайные значения. Возьмем значение температуры с 8 канала ADMUX (нам все равно на точность, чем не точнее, тем лучше) и загрузим в srand (при этом, если температура всегда одинакова, то и rand будет идентичен).

Если хотя бы одна звезда была создана, то применяем параметры для каждой:

Invaders

Они есть. Их пять (столько отлично помещается в ряд) и они как терминатор (все время возвращаются обратно).

Оптимизация

После переноса в Atmel Studio (выдернув что нужно из Arduino), где можно было с легкостью получить asm листинг и примерно понять, что я натворил, начал переписывать используемые библиотеки и некоторые кодовые конструкции (некоторые заметят, что я понаделал неведомой фигни непонятно зачем, и будут правы).

Что это дало? Высвободило около 6 Кбайт ПЗУ, уменьшило объем используемой ОЗУ и увеличило скорость передачи данных по SPI (пожертвовав некоторыми возможностями).

Хоть игра примитивна, но вполне неплохо работает и может занять на некоторое время. Более того, осталось свободно 10 Кбайт ПЗУ и около 1 Кбайт ОЗУ.

— Добавление звука. Без него скучно нажимать стилусом в экран.
— Добавить больше различной анимации, для более живой игры.
— Победить незначительные баги.
— Перенос на более серьезный МК и добавление новых плюшек, или тех которые не влезли.

ТВ терминал на базе микроконтроллера AVR

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

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

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

  • дисплейный модуль должен быть максимально простым;
  • для отображения данных достаточно текстового и псевдографического режима;
  • за всю работу модуля должен отвечать лишь 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 AVGA

Игровая видеоконсоль на AVR AVGA

Современная техника не стоит на месте и когда-то казавшиеся сложными ЭВМ состоящие из множества микросхем и прочих радиоэлементов в наше время могут быть заменены всего одним дешевым микроконтроллером, способным выполнять функции когда-то современного компьютера. В данной статье будет рассказано как с помощью одного микроконтроллера 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 – синий). При смешивании данных цветов с различной яркостью можно получить любой цвет из гаммы.


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

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

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

Конструктивно описываемое устройство представляет собой схему, основанную на 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. Обратите внимание, что вы можете сделать свое собственное видео разрешение. Вы даже можете изменить высоту блока. При разгоне МК можно получить гораздо выше разрешение, например, 320×240.

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

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

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.

c. sound.c — звуковой драйвер. Звуковой секвенсор. Используется 8-битный таймер/счетчик в режиме CTC для воспроизведения последовательностей аудио сигнала. Модуль настраивается в sound.h или config_hw.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.

Добавить комментарий