Видеокарта VGA для микроконтроллера

  • Автор текста: natim

  • Больше интересных фотографий и комментариев в оригинальном материале

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

В то же время имеется огромный парк старых ЖК-экранов. Модели диагональю 15-19 дюймов можно приобрести в рабочем состоянии за 200 – 500 рублей. Особенно это касается моделей с уже немодным соотношением сторон 4:3. Эти модели достаточно надежны. Конечно, лампы CCFL, используемые для подсветки, с годами использования теряют свою яркость и спектр излучения приобретает неприятный красноватый оттенок, но благодаря большому количеству таких дисплеев всегда можно выбрать более или менее яркий экземпляр. Кроме того, лампы CCFL сравнительно легко заменить на обычную светодиодную ленту, подключив ее напрямую к источнику питания дисплея 12 В. Но в этом случае обычно приходится блокировать цепи обратной связи от микросхемы управления подсветкой к контроллеру на самом дисплее, иначе дисплей подумает, что подсветка неисправна, и просто выключится. Также придется пожертвовать функцией регулировки яркости. Однако этой функцией мало кто пользуется. Как правило, яркость монитора регулируется один раз в жизни, сразу после его покупки, и никогда не меняется.

Таким способом я модифицировал экран диагональю 17 дюймов от Samsung. Результат меня удовлетворил; Я мог бы и дальше использовать экран по прямому назначению. Единственное, что хочу отметить, что в моем случае причиной замены стал сломанный повышающий трансформатор, а не вышедшая из строя лампа CCFL, которая, как я уже говорил, вполне надежна. Светодиодные ленты я также подключил через переключатель на мощном npn-транзисторе, чтобы подсветка отключалась по команде контроллера монитора, иначе на экране были бы видны полосы и неприятное мерцание при инициализации экрана или переключении режимов.

Помимо выхода из строя ламп подсветки и цепи их питания, второй по распространенности проблемой таких дисплеев является выход из строя конденсаторов в блоке питания. Других проблемных мест у дисплеев обычно нет, и после указанной модификации и замены конденсаторов на новые они, скорее всего, проработают не менее 10 лет.

Большинство старых мониторов обычно имеют разъем VGA для подачи на него сигнала от компьютера. Часто присутствует только этот контакт. Иногда в паре с разъемом DVI (обычно на более дорогих моделях). Разъем HDMI чаще встречается на относительно современной технике.

Таким образом, разъем, который почти со 100% вероятностью можно найти на старом мониторе, — это разъем VGA. Мы сосредоточимся на этом.

Для вывода изображения на экран достаточно оперировать всего 5 сигналами – R, G, B – отвечающими за цвет и яркость, HS, VS – отвечающими за синхронизацию. Как это сделать подробно описано в статьях 1, 2, 3, 4, поэтому повторяться не буду.

В статьях выше для вывода видеосигналов чаще всего используются FPGA, которые обычно стоят довольно дорого. В одном варианте сигналы генерируются микроконтроллером и порошком. Хотелось бы, чтобы это было проще и дешевле одновременно. Поэтому было решено использовать FPGA, но не PGA, а CPLD. Такие FPGA имеют значительно меньше логических ячеек, но и стоят дешевле. Например, мне удалось купить плату разработки FPGA MAX II Altera EPM240 на Aliexpress всего за 8,57 долларов США (без учета доставки). Более того, в комплект также входил программатор. Сами чипы можно найти за $1,6–2,1 (не оригинал, конечно).

Плата разработки MAX II Altera EPM240

Да, для реализации был выбран текстовый режим, так как он наиболее простой для микроконтроллера, но в то же время достаточно информативный. Некоторые простые графические вещи можно реализовать с помощью псевдографических символов, как это часто практиковалось во времена DOS. Для реализации графического режима необходимо передать большой объем данных от микроконтроллера и дополнительно загрузить его генерацией графики, что не всегда приемлемо, особенно для слабых ядер.

Первым шагом является отображение символа «2» на экране. Символ оказался зеркальным отражением. Без проблем

Указанная ПЛИС имеет на борту флэш-ПЗУ, использовать который для хранения ПЗУ символьного генератора весьма заманчиво. Однако объем крайне мал — всего 8 Кбит или 1 Кбайт. Этого может хватить только для символов с разрешением 5х7, да и то, если пожертвовать неотображаемыми, незначительными и визуально идентичными символами из таблицы ASCII. Кроме того, использование встроенного ПЗУ потребует потребления логических ячеек, которых и так немного. Каким бы привлекательным ни был этот вариант, от него придется отказаться и использовать внешнюю микросхему ПЗУ, полученную, например, из старых материнских плат. Если вы найдете микросхему с питанием 3,3 В, то о согласовании уровней напряжения с ПЛИС можно даже не думать. Объёмы таких ПЗУ довольно большие — 2/4/8 Мбит или 256...1024 Кбайт, что позволяет хранить большое количество различных шрифтов в хорошем разрешении 8х16.

Крупный план платы разработки Altera MAX II

Для сохранения изображения экрана также понадобится чип оперативной памяти. Рассчитаем примерный необходимый объем. Если мы планируем использовать шрифт 8х16, то при разрешении экрана 640х480 мы получим 80 горизонтальных пробелов и 30 вертикальных линий. Это означает, что для хранения изображения экрана необходимо 80∙30=2400 байт. Не очень практичная цифра. Оно лишь немногим больше ближайшей степени двойки - 2048. Поэтому память используется нерационально, всего на 58%, так как ближайшее кратное степени двойки - 4096. Именно поэтому текст размером 80х25 получил распространение режим, где 5 строк вполне можно было легко выбросить. В данном случае необходимый объем памяти составляет 2000 байт, что идеально вписывается в объем памяти в 2 КБ. Однако современные микросхемы памяти имеют довольно большие объемы; сейчас нет смысла их спасать. Также можно намеренно тратить память для упрощения логики дешифрования и хранения логических ячеек FPGA. Таким образом, необходимый объем составляет 4096 байт (212, 12 адресных битов), которые можно разделить следующим образом: выделить 5 адресных битов для адреса строки (будет использовано 30 из 32) и 7 бит для адреса столбца (80 из 32) будет использоваться 128).

Такой же объем памяти потребуется для страницы атрибутов символа. Требуемыми атрибутами будут цвет символа, цвет фона, подчеркивание и мигание.

Всего требуется память не менее 8 КБ. Из «доступных» вариантов лучше всего подойдет статическая память (используется в качестве кэш-памяти), также взятая со старых материнских плат. Единственное, что эта память обычно 5-вольтовая. Но если это CMOS-память, то она обычно без проблем работает при напряжении 3,3 В, единственное, что требует более высоких таймингов.

Итак, мы получили следующую схему.

Первый вариант схемы

Как видите, схема включает всего 3 микросхемы и минимум внешних деталей. Если мы возьмем за основу указанную выше макетную плату EPM240, кроме того нам потребуются только микросхемы ПЗУ, ОЗУ и разъем VGA с пятью резисторами. Показано, что подключение сигналов к ПЛИС условно, так как практически все ветви равнозначны (кроме глобальных тактовых сигналов, на одно из которых необходимо подать сигнал от тактового генератора). При программировании микросхемы под конкретное устройство практически все сигналы можно переназначить. На данный момент устройство собрано на макетной плате и эту проблему можно отложить в сторону.

Устройство взаимодействует с микроконтроллером через параллельный 8-битный интерфейс (сигналы с префиксом HOST), логически почти идентичный широко используемому интерфейсу дисплея на контроллере 1602 и ему подобных. Разница лишь в том, что сигнал BUSY добавляется от устройства к микроконтроллеру. Ее необходимость обусловлена ​​тем, что доступ к микросхеме ОЗУ предоставляется только во время обратного сканирования кадров. Остальное время чип занимает логика FPGA. Сигнал BUSY также имеет значение сигнала запроса прерывания. При изменении контроллер может автоматически начать запись в буфер экрана.

Второй шаг — напечатать несколько символов генератора символов с разными цветами символов и фона

Описание интерфейса:

  • DATA[7:0] – 8-битные данные, однонаправленный порт, только для записи на устройство.

  • CS – выбор устройства, 0 – устройство выбрано, 1 – устройство не выбрано. Положительный фронт CS блокирует данные при записи.

  • AD – адрес/данные, во время операции записи: 0 – данные передаются, 1 – передается адрес.

  • ЗАНЯТО – устройство занято, 0 – не занято, 1 – занято. Если устройство занято, операция записи в ОЗУ игнорируется. Запись возможна только в адресный регистр.

  • RESET – сброс устройства. 0 – сброс, 1 – работа. Аппаратный сброс можно использовать для немедленного выключения экрана. При активации этого сигнала вывод сигнала на монитор прекращается. Сброс не влияет на содержимое микросхемы оперативной памяти.


запись данных из микроконтроллера в ОЗУ возможна только во время вертикального затухания импульса, когда микросхема ОЗУ не занята логикой ПЛИС. На этот раз 1440 мс. Хотя это достаточно большой интервал, при использовании медленных микроконтроллеров времени на полную перезапись всей области памяти может не хватить. Например, микроконтроллер AVR при работе на частоте 11,0592 МГц успевает занять на экране всего 3 полных строки со всеми атрибутами. Если не перезаписывать атрибуты (как это обычно бывает в реальном использовании — атрибуты записываются один раз при старте программы), то можно писать по 6 строк за раз. Вероятно, если оптимизировать код и переписать его на ассемблере, можно существенно ускорить обновление данных. В противном случае перезапись всего экрана может занять от 5 тактов (если обновлять только данные) до 15 тактов (если обновлять еще и атрибуты). При 60 кадрах в секунду это займет от 1/12 до 1/4 секунды. Если кто-то из читателей когда-либо работал на машинах класса HT или AT с тактовой частотой процессора в диапазоне 4 – 12 МГц, ощущения при обновлении экрана будут примерно такими же.

Если вы не хотите ждать следующего демпфирующего импульса и хотите записать все одним ударом, вы можете использовать сигнал RESET. При включении внутренняя логика FPGA останавливается и отключается от микросхемы ОЗУ, предоставляя микроконтроллеру прямой доступ к памяти. На регистры работы с ОЗУ сигнал сброса не влияет.

В общем случае операции по записи следующие: нужно дождаться, пока сигнал BUSY станет нулевым, затем нужно подать необходимые данные на шину данных, установить тип данных сигнала (адрес или данные) – AD и «щелкните» сигнал CS, сначала в журнале. 0, затем войти. 1. Когда этот сигнал переходит из лог. 0 для входа. 1, данные будут заблокированы в памяти. Во время импульса отключения чип RAM напрямую подключается к сигналам HOST микроконтроллера; следовательно, заботой микроконтроллера является сохранение таймингов при записи. Однако чаще всего статическая оперативная память является довольно быстрым устройством и обычно имеет тайминги значительно ниже максимальной скорости, с которой средний микроконтроллер может управлять своими линиями ввода-вывода.

Микросхема оперативной памяти D43256BGU-70LL подключается к выводам ПЛИС с помощью сигналов с префиксом RAM. Эти сигналы включают 8-битную шину данных (двунаправленную) и 13-битную адресную шину. Из управляющих сигналов используется только сигнал WE. Поскольку микросхема на шине ОЗУ имеет в своем полном и неограниченном владении одну и обе шины (адрес и данные), то сигналы ОЭ и CS не используются, на них необходимо отправлять постоянный лог. 0, подключите их к общему проводу.

Микросхема ПЗУ SST49LF002A подключается примерно так же (сигналы с префиксом ПЗУ), за исключением того, что шина данных однонаправленная. Сигналы OE и WE данной микросхемы также не используются и подключаются напрямую к логу. 0 и лог. 1 соответственно.

К свободным выводам ПЛИС подключаются перемычки для выбора текущего шрифта. Поскольку объем микросхемы ПЗУ довольно большой, это позволяет записать в нее несколько разных шрифтов, в том числе с национальными алфавитами, и переключать их установкой перемычек.

Разъем VGA подключается к FPGA с помощью всего 5 резисторов. Также резисторы в цепях HS и VS имеют более защитную функцию и их можно смело исключить. Резисторы в цепях R, G, B подобраны таким образом, что вместе с входным сопротивлением монитора (75 Ом) образуют делитель напряжения, снижающий напряжение на входе монитора до номинала 0,7 В.

Внешний вид макета

Выводы питания зашунтированы керамическими конденсаторами, а на вывод GCLK0 подается тактовый сигнал частотой 50 МГц от кварцевого генератора. Эти детали уже были на макетной плате.

К сигналу RESET подключены резистор, конденсатор и кнопка, которая собственно и формирует этот сигнал. Однако если этот сигнал генерируется микроконтроллером, эти подробности не нужны.

После написания основной части запланированной логики работы ПЛИС оказалось, что объём используемых логических ячеек незначительно превышает лишь половину имеющихся. В связи с этим возникло желание немного усложнить логику работы и добавить больше функций. Прежде всего, можно увеличить количество цветов до 16. Для этого нужно использовать еще 3 вывода ПЛИС и добавить в схему 3 резистора. Это не слишком усложнит макет, но добавит еще 8 цветов. В этом случае страница атрибутов ОЗУ должна быть полностью раскрашена и добавлена ​​еще одна страница атрибутов, увеличивающая адресную шину ОЗУ на 1 бит. Вы также можете переместить выбор шрифта на страницу дополнительных атрибутов, добавить подчеркивание, мигание символов, мигание фона и т д

Новая договоренность выглядит следующим образом. Он мало чем отличается от предыдущего.

Второй вариант схемы

По мере увеличения количества цветов возникает вопрос – какую палитру выбрать? Когда цветов всего 8, такого вопроса не возникает - все цвета представляют собой бинарный поиск трех основных цветов r, g, b (2^3=8). Когда их несколько, возможны альтернативы. Например, 16-цветная палитра EGA:

Палитра ЕГА

Как видите, в этой палитре за яркость отвечает четвертый бит. А вот половинки таблицы разделены по-разному в зависимости от яркости. Первой половине «устанавливается» яркость на 2/3 (байт AAH = 170 = 2/3*256). Во второй половине добавляется еще 1/3 яркости (байт 55H = 85 = 1/3*256) и цвета называются яркими *color*. Интересный момент: из схемы исключен цвет №6 (желтый/коричневый), который по логике должен быть АААА00, но АА5500 был специально сделан для замены непривлекательного грязно-желтого цвета на более популярный коричневый. Это хорошо известная аппаратная функция видеокарт и мониторов EGA. Причем в некоторых мониторах это было учтено, а в некоторых моделях этим пренебрегли для упрощения схемотехники. А другие даже добавили отдельную кнопку регулировки (называемую «BROWN ADJ»), которую можно использовать для настройки желаемого оттенка этого цвета. Поэтому цвет в таблице обозначен как желтый/коричневый.

Нелинейное деление по яркости автоматически приводит к появлению в палитре двух оттенков серого — светло-серого и темно-серого, которые очень популярны на практике.

Однако 16-цветная палитра VGA немного отличается. Там цвета разделены ровно пополам по яркости (80H = 128 = 1/2*256):

VGA-палитра

Еще из логики выкидывает цвет - светло-серый (С0С0С0), который должен быть черным и, следовательно, дублировать существующий. Кроме того, этот цвет заменен на темно-серый (808080). Это сделано специально для обеспечения совместимости 16-цветных палитр VGA и EGA, которые поэтому практически идентичны по восприятию.

В нашем случае, когда сигналы формируются аппаратно с помощью резисторов, удобнее использовать палитру EGA. В этом случае в логику декодирования необходимо добавить коррекцию только одного цвета — того же №6. Все остальные цвета подбираются автоматически. Чтобы исправить палитру VGA, простой сменой программы не получится — придется добавить еще одну группу резисторов, чтобы сформировать светло-серый цвет (C0C0C0).

Резисторы должны быть спроектированы так, чтобы одна группа обеспечивала 1/3 яркости, другая 2/3 яркости, а вместе обеспечивали соответственно полную яркость. Путем несложных расчетов по закону Ома были рассчитаны их сопротивления: 390 Ом и 750 Ом.

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

Итак, у нас есть режим 640х480. Выходная частота пикселей — 25 МГц (на самом деле по стандарту она должна быть 25,175 МГц, но ее можно совершенно безболезненно округлить до 25; VGA, как и многие другие аналоговые стандарты, допускает довольно существенное изменение параметров), кадр частота составляет 60 Гц (на самом деле показано 59,5 Гц), частота строчной развертки – 31,46875 кГц (на самом деле – 31,25 кГц), то есть время вывода пикселя составляет 40 нс, время вывода символа с ширина 8 бит равна 320 нс. За 320 нс необходимо прочитать код символа ASCII (байт), код цвета (байт) и поле атрибута (байт) из ОЗУ, затем использовать код ASCII в качестве адреса для чтения битовой маски символа из ПЗУ. Только тогда логика FPGA получит всю необходимую информацию для начала визуализации.

Третий шаг – получение информации от микроконтроллера

Согласно даташиту, для выбранной микросхемы D43256BGU-70LL полный цикл чтения занимает 70 нс. Поскольку мы используем его с пониженным напряжением, время цикла необходимо увеличить. Хотя бы до 100 нс. Таким образом, за 320 нс мы успеем прочитать из ОЗУ только 3 байта — код ASCII, код цвета и атрибуты символов. Большой. С ПЗУ сложнее, в нем адрес записывается в 2 приема - по строкам и столбцам, и по описанию цикл чтения занимает 270 нс. Это не быстро, но мы справляемся за 320 нс, даже с запасом.

Проблема в том, что мы не можем начать выдачу адреса ПЗУ, пока не узнаем хотя бы ASCII-код, а это занимает 100 нс. Суммарно 370 нс. Нам помогает то, что каждый цикл чтения ОЗУ и ПЗУ укладывается в разрешенный интервал, и мы можем просто потратить на чтение данных не один цикл, а два. При подготовке данных необходимо сместить область отображения символов, сделать дополнительную область гашения шириной 2 символа в начале строки и теми же 2 символами уменьшить область гашения после конца строки. Сделать это несложно — просто смещаем затухающий импульс на 640 нс (следовательно, смещается и синхроимпульс). С точки зрения монитора разницы нет.

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

Циклограмма доступа к ОЗУ и ПЗУ

Цикл начинается с помещения адреса байта символа ASCII на адресную шину ОЗУ. Через 80 нс на шине данных ОЗУ появляется запрошенный байт, который мы тут же используем для формирования адреса для чтения байта из ПЗУ символьного генератора. На отметке 100 нс мы устанавливаем адрес байта атрибутов символа на адресной шине ОЗУ. На 140 нс (60 нс после установки адреса) фиксируем первую часть адреса ПЗУ. Ждем еще 60 нс и устанавливаем вторую часть адреса на адресную шину ПЗУ. В этот момент на шине данных ОЗУ уже должен находиться байт данных с символьными атрибутами, из которых 5 бит (подробное описание регистров ниже) отвечают за шрифт и входят во вторую часть адреса ПЗУ. Остальные 3 бита данных сохраняются во временном регистре 2. Еще через 60 нс фиксируем вторую часть адреса ПЗУ. Данные на шине данных ПЗУ появятся через 120 нс после этого события, причем произойдет это уже во время второго цикла. Чтобы циклы не пересекались друг с другом, мы записываем эти данные во временный регистр 1 (на 80 нс). И наконец, на отметке 300 нс необходимо переписать все подготовленные данные в рабочие регистры. Битовая маска символа из временного регистра 1 перезаписывается в регистр rom_reg, а ранее сохраненные биты атрибута применяются к байту цвета, который был прочитан в этот момент.

Таким образом, в конце второго цикла все данные для вывода символов будут готовы.

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

Основные регистры:

запись данных из микроконтроллера в оперативную память происходит следующим образом. Дожидаемся, пока сигнал BUSY станет нулевым, записываем в адресные регистры начальные адреса, по которым будут записываться данные (чаще всего это адрес 0 - адрес начала страницы данных, но это может быть и произвольный адрес, если необходимо изменить всего несколько байтов). Затем записываем необходимые данные. После записи каждого байта адрес автоматически увеличивается на 1. При приближении к краю экрана (80-й символ в строке) адрес позиции символа в строке автоматически сбрасывается на ноль, и адрес строки увеличивается на 1. После записи всей страницы данных адрес автоматически переключается на запись атрибутов страницы, а после страницы атрибутов - на запись цветной страницы. После регистрации всех трех страниц адрес также автоматически обнуляется и начинается запись в страницу данных. Таким образом, начальный адрес можно ввести только один раз, а затем можно будет отправлять только данные. Это позволяет сэкономить несколько микросекунд на вводе адреса, а также упрощает программирование, когда все данные можно загрузить за один цикл из 7200 итераций.

Формат данных для записи данных (AD=0):

страница данных
[7 - 0]
символ ASCII (8 бит)

На странице данных хранятся коды символов ASCII.

страница атрибутов
[7 - 3] [2 - 0]
шрифт (5 бит) атрибут sym (3 бита)

атрибут sym (3 бита):
бит 0 – символ мигает
бит 1 – фон мигает
бит 2 – символ подчеркивания

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

цветная страница
[7 - 4] [3 - 0]
цвет фона (4 бита) цвет символа (4 бита)

Цветная страница содержит цвет символа и цвет фона соответственно. Цвета могут быть любые из палитры из 16 цветов.

Адресных регистров – 3. Выбор в какой из них производить запись осуществляется по старшим битам. Если старший бит [7] равен log. 0, то в строку (столбец) записывается регистр положения. Если он равен лог. 1, затем записываются регистр номера строки (строка) и регистр номера страницы ОЗУ (данные или атрибуты или цвет). Если три старших бита равны log. 1, то записывается специальный регистр управления, биты 4, 3 которого определяют положение аппаратно генерируемой строки при включении бита подчеркивания, биты 2 – 0 зарезервированы для будущих настроек.

Формат данных для регистрации адреса (AD=1):

[7] [6 - 0]
0 символов, пол. (7 бит)

Регистр хранит позицию в строке.

[7] [6–5] [4–0]
1 страница (2 бита), позиция символьной строки (5 бит)

страница: 00 – страница данных, 01 – страница атрибутов, 10 – страница цвета

В регистре хранятся номера строк и выбранные страницы.

[7–5] [4–0]
1 1 1 регистр управления (5 бит)

контрольный регистр: бит 4,3 – настроить подчеркивание
00 – 11 и 12 строки
01 – 12 и 13 строки
10 – 13 и 14 строки
11 – 14 и 15 строки

бит 2.1.0 – для использования в будущем

Специальный контрольный регистр.

Если вы введете адрес вне диапазона 0-79 для столбца и 0-29 для строки, данные начнут записываться в область теневой памяти, которая не отображается на экране. Ничего страшного в этом нет, после прохождения адреса 128 данные снова будут записываться в видимую область. Была идея использовать теневую область данных в качестве дополнительной оперативной памяти для микроконтроллера. В этом случае шину данных необходимо сделать двунаправленной и добавить сигнал чтения/записи. Однако от этого было решено отказаться для упрощения интерфейса. Более того, современным микроконтроллерам не хватает такого количества оперативной памяти, как раньше. Кроме того, доступ к этой оперативной памяти происходит не в любой момент времени по запросу микроконтроллера, а также только во время холостого импульса.

Пятый шаг – попытка отобразить графическое изображение (неудачная)

Внутренние регистры ПЛИС (некоторые):

hreg[10:0] мин-0, макс-1599
[10 - 4] [3 - 1] [0]
sym col pos (7 бит) sym col (3 бита) тактовый бит

Регистр содержит текущую позицию строчной развертки. Он тактируется на частоте 50 МГц, что в 2 раза превышает необходимые 25 МГц, поэтому младший бит (тактовый бит) не используется. Соответственно, биты с 1 по 3 обозначают позицию символа, биты с 4 по 10 указывают позицию символа в строке. Когда значение достигает 1600, регистр сбрасывается в ноль, а регистр vreg увеличивается на 1.

vreg[9:0] мин-0, макс-524
[9] [8–4] [3–0]
0 символьная строка pos (5 бит) символьная строка (4 бита)

Регистр содержит текущую позицию вертикальной развертки. Тактировалось из реестра hreg. Соответственно, биты с 0 по 3 обозначают строку символов, биты с 4 по 8 обозначают строку символов. Бит 9 уже попадает в область гашения, поэтому он не используется. Когда значение достигает 525, регистр сбрасывается в ноль.

ram_addr_int[13:0], ram_addr_ext[13:0]
[13–12] [11–7] [6–0]
страница (2 бита) sym row pos (5 бит) sym col pos (7 бит)

страница: 00 – страница данных, 01 – страница цвета, 10 – страница атрибутов

Регистры содержат текущее значение адреса для доступа к оперативной памяти (всего 16 КБ). Нижние 7 бит — это адрес символа в строке (столбце), затем 5 бит — адрес строки и 2 бита — адрес страницы (данные, атрибуты или цвет). Таких регистров 2 — один для внутреннего использования логикой ПЛИС, другой управляется извне микроконтроллером и может быть изменен только им.

комната_адрес[10:0] строка
[10 - 4] [3 - 0]
Код ASCII (7 бит) Символьная строка (4 бита)

room_addr[10:0] столбец
[10 - 6] [5 - 1] [0]
0 0 0 0 0 шрифт (5 бит) Код ASCII[7]

Регистр адреса ПЗУ записывается в два этапа. Содержит адрес строки символов, код ASCII символа и адрес шрифта. Эти адреса расположены таким образом, что стандартные файлы шрифтов *.fnt можно прошить в ПЗУ без дополнительной обработки, просто подряд. Вы можете объединить несколько шрифтов в один файл прошивки, например, с помощью редактора файлов WinHex. Главное, чтобы шрифты имели разрешение 8х16.

rGB[5:0]
[5–3] [2–0]
цвет RGB 1/3 Цвет RGB 2/3

Регистр вывода цвета. Этот регистр подключен непосредственно к выводам FPGA, которые подают сигналы R, G, B на монитор. Нижние 3 бита дают сигнал уровнем 2/3 яркости (их необходимо подключить к резисторам 390 Ом), старшие дают сигнал уровнем 1/3 яркости (их необходимо подключить к резисторам 750 Ом).

Файлы проекта размещены на GitHub.

Поскольку объем данных ПЗУ достаточен, на экран можно также выводить графические изображения. В этом случае изображение необходимо разбить на спрайты размером 8x16 и зашить в ПЗУ символогенератора. Изображение должно отвечать только двум требованиям: в спрайте должно использоваться не более двух цветов из палитры и количество спрайтов не превышает 256. Как, например, на изображении ниже. Спасибо художнику A_Foxli за индивидуальное изображение.

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

[мин]ЭлектроникаТехнологииЭлектрикаTimewebИнформативноеVGAМикроконтроллерыДлинный пост 5

Больше интересных статей здесь: Гаджеты.

Источник статьи: Видеокарта VGA для микроконтроллера.