Иногда, при разработке устройств на микроконтроллерах, возникает потребность в выводе на дисплей большого количества информации или же в выводе информации на крупный дисплей для возможности ее считывания с большого расстояния. К сожалению, готовых решений этой проблемы нет, а те что есть – весьма дороги. Например, графические ЖК-дисплеи с возможностью подключения к микроконтроллеру обычно имеют диагональ не более нескольких дюймов и достаточно существенную цену (причем, даже монохромные, о цветных вообще можно не говорить).
В то же время есть огромный парк старых ЖК мониторов. Модели с диагональю 15-19 дюймов можно приобрести в рабочем состоянии за 200 – 500 руб. Особенно это касается моделей с немодным сейчас соотношением сторон 4:3. Эти модели достаточно надежные. Лампы CCFL, используемые для подсветки, конечно, теряют яркость за годы эксплуатации и их спектр свечения уходит в неприятный красноватый оттенок, но благодаря большому количеству таких мониторов всегда есть возможность выбрать более-менее живой экземпляр. Кроме того, лампы CCFL относительно несложно заменить обычной светодиодной лентой, подключив ее напрямую к источнику питания 12 В монитора. Однако при этом обычно необходимо заблокировать цепи обратной связи от микросхемы управления подсветкой к контроллеру самого монитора, иначе монитор будет думать что подсветка неисправна и просто выключится. Также придется пожертвовать функцией регулировки яркости. Однако, этой функцией мало кто пользуется. Обычно яркость монитора настраивается один раз в жизни, сразу после его покупки и потом никогда не меняется.
Мной таким образом был доработан монитор диагональю 17” фирмы «Самсунг». Результат меня удовлетворил, монитором вполне можно было продолжать пользоваться по его прямому предназначению. Единственное, хочу отметить, что в моем случае причиной переделки стал пробитый повышающий трансформатор, а не вышедшая из строя лампа CCFL, которые, как я уже говорил, достаточно надежны. Также светодиодные ленты я подключил через ключ на мощном транзисторе npn для того, чтобы подсветка отключалась по команде от контроллера монитора, иначе во время инициализации монитора или переключении режимов на экране видны полосы и неприятные мерцания.
Кроме выхода из строя ламп подсветки и схемы их питания, другой наиболее частой проблемой в таких мониторах следует назвать выход из строя конденсаторов в блоке питания. Иных проблемных мест в мониторах обычно не бывает и после указанной доработки и замены конденсаторов на свежие они наверняка еще проработают не менее 10 лет.
Большинство старых мониторов обычно всегда имеют разъем VGA для подачи на него сигнала от компьютера. Часто присутствует только один этот разъем. Иногда в паре с разъемом DVI (чаще на более дорогих моделях). Разъем HDMI больше встречается на относительно современной технике.
Таким образом, разъем, который с почти 100% вероятностью найдется на старом мониторе – это разъем VGA. На него и будем ориентироваться.
Чтобы вывести изображение на монитор достаточно оперировать всего 5-ю сигналами – R, G, B – отвечающие за цвет и яркость, HS, VS – отвечающие за синхронизацию. Как это сделать, подробно рассмотрено в статьях 1, 2, 3, 4, поэтому не буду повторяться.
В вышеперечисленных статьях для вывода видеосигнала чаще всего используется ПЛИС, которая обычно весьма недешевая. В одном из вариантов сигналы генерируются на микроконтроллере и рассыпухе. Хотелось бы попроще и подешевле одновременно. Поэтому было принято решение использовать ПЛИС, но не PGA, а CPLD. Такие ПЛИС имеют существенно меньше доступных логических ячеек, но также и стоят дешевле. Например, макетную плату ПЛИС MAX II Altera EPM240 мне удалось приобрести на Aliexpress всего за 8,57$ (без учета доставки). Причем, в комплект входил также и программатор. Сами чипы можно найти за 1,6 – 2,1$ (не оригинал, разумеется).
Макетная плата MAX II Altera EPM240
Да, для реализации был выбран текстовый режим, как наиболее простой для микроконтроллера, но, в то же время, достаточно информативный. Некоторые простые графические вещи можно реализовать символами псевдографики, как это широко практиковалось во времена DOS. Для реализации графического режима потребуется передавать большой объем данных от микроконтроллера и дополнительно загружать его формированием графики, что не всегда допустимо, особенно для слабых ядер.
Первый шаг — успешный вывод на экран символа «2». Символ получился отзеркаленным. Не беда
У указанной ПЛИС на борту имеется flash ПЗУ, которое весьма заманчиво использовать для хранения ПЗУ знакогенератора. Однако объем его крайне невелик – всего 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 кБайт. Однако современные микросхемы памяти имеют достаточно большие объемы, экономить ее сейчас смысла особого нет. Более того, можно сознательно пойти на нерациональное использование объема памяти в угоду упрощения логики дешифрации и экономии логических ячеек ПЛИС. Итак, нужен объем 4096 байт (212, 12 бит адреса), который можно разделить следующим образом: 5 бит адреса выделить на адрес строки (будет использовано 30 из 32) и 7 бит на адрес столбца (будет использовано 80 из 128).
Такой же объем памяти потребуется для страницы атрибутов символов. В качестве атрибутов обязательно нужны будут цвет символа, цвет фона, подчеркивание, мигание.
Итого, необходима память размером не менее 8 кБайт. Из вариантов «под рукой» лучше всего подходит статическая память (используемая как кэш-память), также взятая со старых материнок. Единственное, эта память обычно 5-вольтовая. Однако если это память КМОП, она чаще всего без проблем работает и при напряжении 3,3 В, единственное, при этом необходимо закладывать бОльшие тайминги.
Итак, получилась следующая схема.
Первый вариант схемы
Как видно, схема включает в себя только 3 микросхемы и минимум внешних деталей. Если применить в качестве основы вышеупомянутую макетную плату EPM240, то кроме нее потребуются только микросхемы ПЗУ, ОЗУ и разъем VGA с пятью резисторами. Подключение сигналов к ПЛИС показано условно, поскольку почти все ее ножки равнозначны (кроме глобальных тактовых сигналов, на один из которых необходимо подать сигнал с тактового генератора). При программировании микросхемы под конкретное устройство почти все сигналы можно будет переназначить. Пока же устройство собрано на макетной плате и этот вопрос можно отложить.
Устройство общается с микроконтроллером по параллельному 8-битному интерфейсу (сигналы с префиксом HOST), логически почти идентичному широко распространенному интерфейсу дисплеев на контроллере 1602 и им подобных. Единственное отличие – добавлен сигнал BUSY от устройства к микроконтроллеру. Его необходимость обусловлена тем, что доступ к микросхеме ОЗУ предоставляется только в момент обратного хода кадровой развертки. В остальное время микросхема занята логикой ПЛИС. Сигнал BUSY также имеет смысл сигнала запроса прерывания. По его перепаду контроллер может автоматически начинать запись в буфер экрана.
Второй шаг — вывод некоторых символов знакогенератора различным цветом символа и фона
Описание интерфейса:
- DATA[7:0] – данные 8 бит, порт однонаправленный, только на запись в устройство.
- CS – выбор устройства, 0 – устройство выбрано, 1 – устройство не выбрано. По положительному перепаду CS защелкиваются данные при записи.
- AD – адрес/данные, при операции записи: 0 – передаются данные, 1 – передается адрес.
- BUSY – занятость устройства, 0 – не занято, 1 – занято. Если устройство занято, операция записи данных в ОЗУ игнорируется. Возможна запись только в регистр адреса.
- RESET – сброс устройства. 0 – сбросе, 1 — работа. Аппаратный сброс можно использовать для мгновенного гашения экрана. При активации этого сигнала прекращается выдача сигнала на монитор. Сброс не влияет на содержимое микросхемы ОЗУ.
Запись данных от микроконтроллера в ОЗУ возможна только во время кадрового гасящего импульса, когда микросхема ОЗУ не занята логикой ПЛИС. Это время составляет 1,440 мс. Несмотря на то, что это довольно-таки большой интервал, при использовании медленных микроконтроллеров может не хватить времени чтобы полностью перезаписать всю область памяти. Например, микроконтроллер AVR при работе на частоте 11,0592 МГц успевает записать только 3 полные строки экрана со всеми атрибутами. Если не перезаписывать атрибуты (как это обычно и происходит при реальном использовании – атрибуты записываются один раз при старте программы), то можно за один раз записать 6 строк. Наверное, если оптимизировать код, переписать его на ассемблере, то можно существенно ускорить обновление данных. Иначе для перезаписи всего экрана может потребоваться от 5 циклов (если обновлять только данные) до 15 циклов (если обновлять еще и атрибуты). При частоте развертки 60 кадров в секунду, это займет от 1/12 до 1/4 секунды. Если кто-то из читателей когда-то работал на машинах класса ХТ или АТ с тактовыми частотами процессора в районе 4 – 12 МГц, то ощущения при обновлении экрана будут примерно такие же.
Если же ждать очередной гасящий импульс неохота и хочется записать все за один присест, можно воспользоваться сигналом RESET. При его активации внутренняя логика ПЛИС останавливается и отключается от микросхемы ОЗУ, давая прямой доступ микроконтроллеру к памяти. Регистры для работы с ОЗУ сигнал сброса не затрагивает.
В общем же случае операции при записи такие: нужно дождаться когда сигнал BUSY станет нулевым, затем необходимо выставить на шину данных нужные данные, выставить сигнал типа данных (адрес или данные) – AD и «щелкнуть» сигналом CS, сначала в лог. 0, затем в лог. 1. При переходе этого сигнала из лог. 0 в лог. 1 данные защелкнутся в памяти. Во время гасящего импульса микросхема ОЗУ напрямую подключается к сигналам HOST микроконтроллера, соответственно, соблюдение таймингов при записи является заботой микроконтроллера. Но, чаще всего, статическое ОЗУ — достаточно шустрое устройство и обычно имеет тайминги существенно меньшие того, с какой максимальной скоростью средний микроконтроллер может управлять своими линиями ввода/вывода.
Микросхема ОЗУ D43256BGU-70LL подключается к ножкам ПЛИС сигналами с префиксом RAM. К этим сигналам относится 8-разрядная шина данных (двунаправленная) и 13-разрядная шина адреса. Из управляющих сигналов используется только сигнал WE. Поскольку на шине RAM микросхема одна и обе шины (адреса и данных) в ее полном и безграничном владении, сигналы OE и CS не используются, на них необходимо подать постоянный лог. 0, соединив их с общим проводом.
Примерно так же подключена (сигналы с префиксом ROM) микросхема ПЗУ SST49LF002A, за исключением того, что шина данных однонаправленная. Сигналы OE и WE этой микросхемы также не используются и напрямую подключены к лог. 0 и лог. 1 соответственно.
На свободные ножки ПЛИС подключены джамперы для выбора текущего шрифта. Поскольку объем микросхемы ПЗУ достаточно велик, это позволяет записать в нее несколько различных шрифтов, в т. ч. и с национальными алфавитами и переключать их простой установкой джамперов.
Разъем VGA подключен к ПЛИС с помощью всего 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:
Палитра EGA
Как видно, в этой палитре 4-й бит отвечает за яркость. Но половинки таблицы поделены по яркости неодинаково. Первая половина «настроена» на 2/3 яркости (байт ААH = 170 = 2/3*256). Во второй половине добавляется еще 1/3 яркости (байт 55H = 85 = 1/3*256) и цвета называются bright *color*. Интересный момент: из схемы выбивается цвет №6 (yellow/brown), который по логике должен быть АААА00, но специально сделан АА5500 для того, чтобы малопривлекательный грязно-желтый цвет заменить на более востребованный коричневый. Это известная аппаратная фича видеокарт и мониторов EGA. Причем, в некоторых мониторах это было учтено, а в некоторых моделях с целью упрощения схемотехники на это забивали. А в других даже добавляли отдельный регулятор для настройки (назывался «BROWN ADJ.»), которым можно было отрегулировать желаемый оттенок этого цвета. Поэтому цвет в таблице обозначен как желтый/коричневый.
Нелинейное деление по яркости автоматически приводит к появлению в палитре двух оттенков серого – светло-серого и темно-серого цвета, которые весьма востребованы на практике.
Однако, 16-цветная палитра VGA немного другая. Там цвета делятся по яркости ровно пополам (80Н = 128 = 1/2*256):
Палитра VGA
В ней также выбивается из логики один цвет – светло серый (С0С0С0), который должен быть черным и, соответственно, дублировать уже имеющийся. Кроме того, этот цвет поменялся местами с темно-серым цветом (808080). Это сделано специально для совместимости 16-цветных палитр VGA и EGA, которые, таким образом, почти идентичны по восприятию.
В нашем же случае, когда сигналы формируются аппаратно с помощью резисторов представляется более удобным использовать палитру EGA. При этом необходимо добавить в логику дешифрации коррекцию только одного цвета – того самого №6. Все остальные цвета получаются автоматически. Для коррекции палитры VGA только изменением программы дело бы не обошлось — понадобилось бы добавлять еще группу резисторов для формирования светло-серого цвета (С0С0С0).
Резисторы должны быть рассчитаны так, чтобы одна группа давала 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 код в качестве адреса прочитать из ПЗУ битовую маску символа. Только после этого у логики ПЛИС будет вся необходимая информация для начала формирования изображения.
Третий шаг — получение информации от микроконтроллера
Согласно даташиту, для выбранной микросхемы 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):
data page
[7 - 0]
sym ASCII (8 bit)
На странице данных хранятся ASCII коды символов.
attribute page
[7 - 3] [2 - 0]
font (5 bit) sym attribute (3 bit)
sym attribute (3 bit):
bit 0 – symbol blinking
bit 1 – background blinking
bit 2 – underline symbol
На странице атрибутов хранятся шрифты и атрибуты символов. Младшие два бита отвечают за аппаратное моргание символа или фона, третий бит – за формирование подчеркивания. Старшие биты выбирают шрифт. Соответственно, можно выводить на экран символы из разных шрифтов вперемешку в любой комбинации. 5 разрядов для выбора шрифта позволяют хранить 32 разных шрифта, включающие как любые символы национальных алфавитов, так и спрайты для вывода картинки, например.
color page
[7 - 4] [3 - 0]
background color (4 bit) symbol color (4 bit)
Страница цвета содержит, соответственно цвет символа и цвет фона. Цвета могут быть любые из 16-цветной палитры.
Регистров адреса — 3. Выбор, в какой конкретно из них идет запись осуществляется старшими битами. Если старший бит [7] равен лог. 0, то записывается регистр позиции в строке (столбец). Если он равен лог. 1, то записывается регистр номера строки (строка) и номера страницы ОЗУ (данные или атрибуты или цвет). Если три старших бит равны лог. 1 то записывается специальный управляющий регистр, биты 4, 3 которого определяют положение аппаратно формируемой черты при включении бита подчеркивания, биты 2 – 0 зарезервированы для будущих настроек.
Формат данных для записи адреса (AD=1):
[7] [6 - 0]
0 sym col pos (7 bit)
Регистр хранит позицию в строке.
[7] [6 - 5] [4 - 0]
1 page (2 bit) sym row pos (5 bit)
page: 00 – data page, 01 – attribute page, 10 – color page
Регистр хранит номер строки и выбор страницы.
[7 - 5] [4 - 0]
1 1 1 control reg (5 bit)
control reg: bit 4,3 – adjust underline
00 – 11 and 12 lines
01 – 12 and 13 lines
10 – 13 and 14 lines
11 – 14 and 15 lines
bit 2,1,0 – for future use
Специальный управляющий регистр.
Если задать адрес вне диапазона 0-79 по столбцу и 0-29 по строке, то данные начнут записываться в теневую область памяти, которая не отображается на экране. Ничего страшного в этом нет, после прохождения адреса 128 данные снова запишутся в видимую область. Была идея использовать теневую область данных как дополнительное ОЗУ для микроконтроллера. При этом, шину данных необходимо сделать двунаправленной и добавить сигнал чтения/записи. Однако от этого было решено отказаться с целью упрощения интерфейса. Тем более, что современные микроконтроллеры не испытывают настолько сильного недостатка в ОЗУ, как это было раньше. Кроме того, доступ к этому ОЗУ происходит не в любое время по желанию микроконтроллера, а также только во время гасящего импульса.
Пятый шаг — попытка вывести графическое изображение (неудачно)
Внутренние регистры ПЛИС (некоторые):
hreg[10:0] min-0, max-1599
[10 - 4] [3 - 1] [ 0 ]
sym col pos (7 bit) sym col (3 bit) tact bit
Регистр содержит текущее положение развертки по горизонтали. Тактируется от частоты 50 МГц, что в 2 раза больше необходимых 25 МГц, поэтому младший бит (tact bit) не используется. Соответственно, биты с 1 по 3 обозначают позицию внутри символа, биты с 4 по 10 – позицию символа в строке. При достижении значения 1600 регистр обнуляется и на 1 увеличивается регистр vreg.
vreg[9:0] min-0, max-524
[9] [8 - 4] [3 - 0]
0 sym row pos (5 bit) sym row (4 bit)
Регистр содержит текущее положение развертки по вертикали. Тактируется от регистра hreg. Соответственно, биты с 0 по 3 обозначают строку внутри символа, биты с 4 по 8 – строку символов. Бит 9 попадает уже в область гашения, поэтому не используется. При достижении значения 525 регистр обнуляется.
ram_addr_int[13:0], ram_addr_ext[13:0]
[13 - 12] [11 - 7] [6 - 0]
page (2 bit) sym row pos (5 bit) sym col pos (7 bit)
page: 00 – data page 01 – color page, 10- attr page
Регистры содержат текущее значение адреса для доступа к ОЗУ (всего 16 кБайт). Младшие 7 бит – адрес символа в строке (столбец), затем 5 бит – адрес строки и 2 бита – адрес страницы (данные, атрибуты или цвет). Этих регистров 2 – один для внутреннего использования логикой ПЛИС, второй управляется извне, микроконтроллером и может быть изменен только им.
rom_addr[10:0] row
[10 - 4] [3 - 0]
ASCII code (7 bit) sym row (4 bit)
rom_addr[10:0] col
[10 - 6] [5 - 1] [0]
0 0 0 0 0 font (5 bit) ASCII code[7]
Регистр адреса ПЗУ, записывается в два приема. Содержит адрес строки символа, ASCII код символа и адрес шрифта. Эти адреса расположены таким образом, что в ПЗУ можно прошивать стандартные файлы шрифтов *.fnt без какой-либо дополнительной обработки, просто подряд. Объединить несколько шрифтов в один файл для прошивки можно, например, программой редактирования файлов WinHex. Главное, чтобы шрифты были с разрешением 8х16.
rgb[5:0]
[5 - 3] [2 - 0]
rgb color 1/3 rgb color 2/3
Регистр вывода цвета. Этот регистр подключен непосредственно к ножкам ПЛИС, подающие сигналы R, G, B на монитор. Младшие 3 бита подают сигнал уровнем 2/3 яркости (должны подключаться к резисторам 390 Ом), старшие подают сигнал уровнем 1/3 яркости (их необходимо подключить к резисторам 750 Ом).
Файлы проекта выложены на Гитхаб.
Поскольку объем данных ПЗУ достаточен, на монитор также можно выводить и графические изображения. При этом, изображение необходимо разбить на спрайты размером 8х16 и зашить в ПЗУ знакогенератора. Изображение только должно удовлетворять двум требованиям: чтобы в пределах одного спрайта было использовано не более двух цветов из палитры и количество спрайтов не превышало 256. Как, например, на изображении ниже. За специально подготовленное изображение спасибо художнику A_Foxli.
Текст
К слову сказать, уложиться в 256 спрайтов — задача не из легких, именно поэтому изображение выглядит больше как детский рисунок. В процессе подгонки его приходилось несколько раз упрощать. Рисование спрайтами отлично подходит, например, при выводе на экран логотипа фирмы.
Вопросы и предложения прошу писать в комментариях.
Возможно, захочется почитать и это:
- ➤ Программируем микроконтроллеры ESP32 и STM32 на C# (nanoFramework)
- ➤ Паттерн внедрение зависимостей в .NET nanoFramework для микроконтроллеров
- ➤ Как подключить термопринтер к микроконтроллеру
- ➤ Сам себе игровая консоль: превращаем планшет с нерабочим тачскрином в игровой девайс из 8 кнопок и микроконтроллера
- ➤ Запускаем матричный принтер от старого банковского терминала
Комментарии (54)
MaFrance351
29.08.2023 07:16+5Понравился пост.
Из вариантов «под рукой» лучше всего подходит статическая память (используемая как кэш-память), также взятая со старых материнок.
Кстати, раз уж упомянули части от старых компьютеров, можно вспомнить и вот этот проект:
https://habr.com/ru/articles/406193/Сейчас, конечно, ПЛИС достать проще и дешевле, чем такую карту и слот для неё, но всё же.
zatim Автор
29.08.2023 07:16+3Да, с видеокартой ISA у меня тоже была идея сделать. Но, как правильно вы заметили, достать их сейчас сложнее (хотя у меня есть их некоторое количество), их осталось мало и они пользуются спросом у любителей старых ПК и спектрумов. Кроме того, как указано в той статье, их настройка - весьма непростое дело, там огромное количество регистров и нужно достаточно глубоко погружаться в аппаратуру и принципы формирования изображения. Кстати, там настолько все гибко сделано, что видеокарту VGA можно настроить и на вывод изображения с частотами ТВ-стандарта. Мне встречался и такой проект.
MaFrance351
29.08.2023 07:16+3Тому посту шесть лет уже, за это время численность таких видях всё же сократилась. И если у энтузиастов типа меня они ещё есть, то сомневаюсь, что у простого обывателя такая тоже найдётся.
Кстати, там настолько все гибко сделано, что видеокарту VGA можно настроить и на вывод изображения с частотами ТВ-стандарта. Мне встречался и такой проект.
Во времена MS-DOS были специальные драйверы для перевода видеокарты в этот режим. И с помощью специального переходника (например, на К155ЛП5 я собирал) можно было подрубить ПК к композитному входу обычного телевизора.
da-nie
29.08.2023 07:16то сомневаюсь, что у простого обывателя такая тоже найдётся.
Тут Avito может помочь. :)
И с помощью специального переходника (например, на К155ЛП5 я собирал) можно было подрубить ПК к композитному входу обычного телевизора.
Только вот цвета не должно быть без кодера PAL/SECAM/NTSC. Впрочем, если цветоразностные сигналы видеокарта сможет сформировать каким-либо способом, то эта проблема решаемая и без кодера (кстати, для ZX был сделан даже кодер на обычной ПЗУ для заданных цветов из палитры).
axe_chita
29.08.2023 07:16Тут Avito может помочь. :)
На Авито барыги уже просекли фишку с коллекционерами, и теперь ISA/VLB/PCI VGA видеокарты доступны только по оверпрайсу.
Да и честно говоря, рука не поднимается уничтожать рабочую железку. И кстати, тот же bluepill STM32F103T8U6 может вполне формировать VGA сигнал, как монохромный, так и цветной.da-nie
29.08.2023 07:16+1Да и честно говоря, рука не поднимается уничтожать рабочую железку.
Уничтожать? :O Нет, что вы! Она подключается по её родному ISA-разъёму и совершенно не страдает. Там просто эмулируется шина данных и шина адреса и всё.
И кстати, тот же bluepill STM32F103T8U6 может вполне формировать VGA сигнал
Может, конечно. У меня и ATMEGA8 это умела в 256 цветов. Но специализированная видеокарта это сделает всё же лучше.
zatim Автор
29.08.2023 07:16Когда то очень давно я формировал видеосигнал (пцтс) с помощью AT89C2051. Делал генератор испытательных сигналов для телевизоров. Приходилось считать каждый такт.
Проблема с использованием микроконтроллера в том, что кроме вывода изображения он не сможет ничем больше заниматься.
axe_chita
29.08.2023 07:16Проблема с использованием микроконтроллера в том, что кроме вывода изображения он не сможет ничем больше заниматься.
Сколько останется свободного времени у микроконтроллера, зависит разрешения которое он формирует. У AVGA как минимум хватало времени на обработку игровой логики. Да и никто не мешает, если идет речь о специализированной видеокарте, создать специализированную видеокарту на базе микроконтроллера или FPGA.
axe_chita
29.08.2023 07:16Уничтожать? :O Нет, что вы! Она подключается по её родному ISA-разъёму и совершенно не страдает. Там просто эмулируется шина данных и шина адреса и всё.
Эмулируя ISA мы добавляем еще один слой абстракции, и теряем на этом часть и так небольшой, по нынешним временам, производительности микроконтроллера, попутно создавая лишнюю точку возникновения «призраков в машине».Может, конечно. У меня и ATMEGA8 это умела в 256 цветов. Но специализированная видеокарта это сделает всё же лучше.
Согласен что специализированная видеокарта лучше, и ещё будет лучше чтобы она была достаточно компактна по сравнению с тем к чему её подключают, и не требовала героического преодоления собственноручно созданных проблем.da-nie
29.08.2023 07:16Эмулируя ISA
Так ISA — это просто обычные внутренние шины компьютера. Ничего там эмулировать не нужно от слова совсем. Какая эмуляция нужна самым обычным шинам данных, адреса и управления? Да никакой же. Точно так же к МК подключается память с параллельным интерфейсом (все те же ШД, ША, ШУ).
axe_chita
29.08.2023 07:16Так ISA — это просто обычные внутренние шины компьютера. Ничего там эмулировать не нужно от слова совсем. Какая эмуляция нужна самым обычным шинам данных, адреса и управления? Да никакой же. Точно так же к МК подключается память с параллельным интерфейсом (все те же ШД, ША, ШУ).
Но дьявол скрывается в деталях, выдержкам из вашей статьиДля некоторых видеокарт нужно подключить -5 В и -12 В (их придётся вам откуда-то взять — например, из источников TracoPower) и сигнал OSC (14.318 МГц) — его можно генерировать простейшим генератором на К155ЛН1. Другим видеокартам эти линии не требуются. Тут уж как повезёт. В общем, если на видеокарте соответствующая ножка на ISA висит в воздухе — её точно можно не подключать. Имейте в виду, потребление видеокартой по линии +5В довольно существенное — если вы будете использовать для питания что-то типа LM7805, то обязательно поставьте её на радиатор (лучше с вентилятором).
Дальше у нас возникает вопрос, вот мы благополучно присоединили видеокарту к МК и запитали её. Но что дальше? Видеокарта то не проинициализирована!Осталось дело за малым — как-то инициализировать видеокарту и начать с ней работать. В интернете есть подобные проекты — я нашёл один (ссылка), откуда и взял код инициализации видеокарты Trident 9000i. В той же программе из интернета есть и код инициализации для Trident9000C, но в комментариях указано, что он не работает. Я проверил. Действительно не работает — на экране мусор и видеокарта не реагирует на запись данных в ОЗУ.
Мы решая одну проблему, благополучно порождаем другую.Если же у вас есть желание запустить любую имеющуюся видеокарту ISA, то для этого вам следует в интернете найти BIOS требуемой видеокарты (скажем, тут) и с помощью IDA дизассемблировать его. Там обычный X86 код. Только начинается он не с 0 адреса — там сигнатура (2 байта) и контрольная сумма (1 байт). Итого, начинать надо с 3-его байта. И последовательно выяснить в какие порты что нужно записать, чтобы карта заработала. Скажу честно, мне терпения не хватило, чтобы понять, что не так с Trident9000C.
И в этот момент возникает крамольная мысль, а может проше в МК запилить эмулятор х86, и с помощью него заставить BIOS проинициализировать видеокарту?
WARNING!
Сразу чтоб прервать холивар и бурление поднимаю руки и прямым текстом говорю «Это не наезд!». Вы в своей статье искали возможность задействовать старую ISA VGA, просто потому что она у вас была под руками. В этой же статье ищут возможность подключения МК к монитору.
Мне кажется что видеокарта для подключение к монитору VGA должна быть компактной и не требовать множества костылей для реализации.
P.S. Рекомендую обратить внимание на канал James Sharman на ютубе, где он на дискретной логике создал и процессор, и видеокарту способную выводить изображение на VGA
Вот его плейлист VGA From Scratch
Предупреждаю — в плейлисте жесткий технопрон, фулл хардкор, фиг оторвешься пока не досмотришь. ;))da-nie
29.08.2023 07:16Но дьявол скрывается в деталях,
Разве подача питания — детали? Как без питания что-то будет работать? Да, отрицательное многим картам можно не подавать. Но что мешает вам его реализовать независимо от того, нужно конкретной карте оно или нет?
Видеокарта то не проинициализирована!
Мы решая одну проблему, благополучно порождаем другую.Для того, чтобы этой проблемы не было, возьмите на авито ту карту, инициализация которой известна. ;) Ну или попрактикуйтесь в асме x86 c IDA.
В этой же статье ищут возможность подключения МК к монитору.
Ну тут уже на ваш вкус: https://habr.com/ru/articles/495542/
И в этот момент возникает крамольная мысль, а может проше в МК запилить эмулятор х86,
Пробовали, кстати, написать эмулятор x86? Я попробовал, мне не понравилось.
Мне кажется что видеокарта для подключение к монитору VGA должна быть компактной и не требовать множества костылей для реализации.
Так это никакие не костыли. Это штатный запуск карты.
Ivanii
29.08.2023 07:16+3У китайцев существует недорогая ардуиноподобная плата с HDMI, ПЛИС и процом - Tang Nano 4K - https://wiki.sipeed.com/hardware/en/tang/Tang-Nano-4K/Nano-4K.html
tormozedison
29.08.2023 07:16EGA (не любую) без драйверов можно в этот режим DIP-переключателями перевести.
da-nie
29.08.2023 07:16+3можно вспомнить и вот этот проект:
У меня ещё и так проект был. :) https://habr.com/ru/articles/495542/
iliasam
29.08.2023 07:16+5Масштабный подход.
Я для вывода изображения на VGA монитор с контроллера использовал дешевый USB переходник DisplayLink: https://github.com/iliasam/STM32_DisplayLink
Раньше переходников USB 2.0 было много на AliEхpress, сейчас именно 2.0 найти сложно.
NivER
29.08.2023 07:16+2Кстати, именно поэтому получил распространение текстовый режим 80х25, в котором 5 строк были попросту выброшены.
Откуда это, позвольте спросить, они были "выброшены"? С чего вдруг количество знакомест должно было рассчитываться с поправкой на не существовавшее тогда 640x480?
zatim Автор
29.08.2023 07:16Да, я неудачно выразился. 5 строк выброшены по отношению к 30-строчному режиму. К разрешению по вертикали это имеет слабое отношение, поскольку тогда чаще использовались символы с разрешением по высоте 8 и 14 пикселей, а не 16.
NivER
29.08.2023 07:16Да нет же :) 30-строчного режима никогда и не существовало, я именно об этом. Их изначально было 24 либо 25, вы совершенно верно написали, что это связано с наиболее рациональным использованием видеопамяти.
LAutour
29.08.2023 07:16А если заменить FLASH на FRAM (например FM1808)? Скорость у FRAM будет как у RAM, плюс можно будетдобавить возможность обновлять знакогенератор как в RAM.
zatim Автор
29.08.2023 07:16Можно, почему бы и нет. Вообще и сейчас ничто не мешает добавить возможность обновлять ПЗУ знакогенератора. В регистре управления есть незадействованные биты, по одному из которых можно коммутировать линии ПЗУ на микроконтроллер аналогично тому как это происходит с ОЗУ во время записи образа экрана. Единственное, запаса логических ячеек почти не осталось, необходимо применять EPM570.
sterr
29.08.2023 07:16Поздравляю. Вы заново изобрели ULA (или проапгрейдили 580ВГ75). Похоже мир реально деградирует, если мы заново изобретаем девайсы 30-летней давности. Пусть не для TV, а для VGA, но все же...
da-nie как то по современному все-таки сделал.
bodyawm
29.08.2023 07:16+5Ну, значит в подразделении Mali от ARM, Imagination Techonologies и Broadcom тоже по вашему мнению деграданты, ведь мобильные гпу только-только догоняют десктопные? :
NivER
29.08.2023 07:16+5Да, вот девайсы от Эпыл, в которых количество кнопок и настроек сведено к минимуму, чтобы пользователь ненароком не перегрузил себе мозг избытком информации - это вершина прогресса. А когда человек не просто самостоятельно закопался в принцип формирования изображения, его схемотехнику и низкоуровневые алгоритмы, а и сам построил действующую модель видеокарты - это деградация как она есть. Главное - не перепутать.
sterr
29.08.2023 07:16+1ведь мобильные гпу только-только догоняют десктопные?
Но если честно. Пусть догоняют. М1 догнал же. Где то была интересная статья. Кол-во MIPS на ватт у мобильных чипов всегда было больше. Их ограничивает только батарея и TDP.
девайсы от Эпыл,
всегда были бабушкофонами. За это я их и не люблю. У них нет развития. Эпл определило само понятие "развитие". "Я думаю за вас"!
а и сам построил действующую модель видеокарты - это деградация как она есть.
вы не поверите, но да! Это все равно, что построить вертолет Архимеда.
Тут больше смысл в понимании работы на низком железном уровне.
Эту всякомуть я изучал в 90-х по схемам спектрума "Ленинград" Зонова. И не только это. Еще XORки Bill Gilbert, хакинг "Пентагоном" RAM. А в схеме те же самые тайминги, только там еще подмешивается обновление DRAM. Ну и тайминги для SECAM, а не VGA. в принципе неважно, разница в частотах. Просто ТЕ инженеры (хотя они и еще учились) смогли создать такие немыслимые вещи, достаточно сложные для проектирования и понимания. Сейчас, через 30 лет это кажется чем то детским.
Я был вахуе, когда нативно вывели видеосигнал с ардуино, это да. Неважно, что она ничего не умела делать кроме этого, но это было круто. И всякие подобные революционные решения меня радовали. Но это пройденный этап и статья меня не удивила. Меня удивило бы то, как вывели HDMI нативно с чипа и это было бы а@енно! Причем это не занимало бы площадь спектрума, а было бы сравнимо со спичечным коробком (как в старые добрые 70-е). Вы не поверите, но в 60-е молодежь представляла, что через х0 лет человечество будет бороздить просторы Альфа Кентавра, но мы до сих пор воюем и роняем КА на луну.
Извините, не могу сразу отвечать, на меня действуют дебильные правила хабра. Но потом могу и забыть. Не хабром единым....
tormozedison
29.08.2023 07:16+1Это не спрайты, а тайлы, как в ПК8000, MSX и NES?
zatim Автор
29.08.2023 07:16Нет, это все же ближе к спрайту. Спрайт может быть использован повторно неограниченное число раз с разной расцветкой и атрибутами. Тайл - просто кусочек заранее заготовленной мозаики. Примерно так себе я все это представляю.
tormozedison
29.08.2023 07:16У меня спрайт ассоциируется с возможностью плавного перемещения поверх неподвижного фона, в т.ч., из тайлов, здесь предусмотрена такая функция?
zatim Автор
29.08.2023 07:16У девайса нет игрового функционала в принципе, он изначально не предусматривался. Я надеялся что предполагаемое назначение устройства и его возможности у меня получилось достаточно подробно описать в статье.
tormozedison
29.08.2023 07:16Дело не в игровом/неигровом предназначении видеоадаптера. Почему-то привык, что тайловая графика реализуется в текстовом режиме при возможности переопределения знакогенератора. А спрайт - то, что подвижно. Другое дело, что на платформе ПК8000, где аппаратных спрайтов нет, тайлы часто применяют в качестве резко перепрыгивающих спрайтов. Но если пассатижи применять в качестве молотка, что тоже иногда практикуется, они от этого в молоток не превратятся.
NutsUnderline
29.08.2023 07:16+1Так тайл по сути своей рассчитан на сколько угодно кратное повторение с разными атрибутами
acc0unt
29.08.2023 07:16+2Как "поиграться" - прикольно, но на практике сейчас для такого даже CLPD не надо. Найди только микроконтроллер с ядрами пожирнее и параллельной шиной потолще. Из рассыпухи - только обвязка МК и резисторы.
Видел примеры VGA в софте для ESP32 и RP2040.
Moog_Prodigy
29.08.2023 07:16Я делал даже на esp8266 с текстовым и графическим режимом. а esp32 вообще крутости вплоть до 3д позволяет в этом плане. И цена очень вкусная.
Schokn-Itrch
29.08.2023 07:16К слову сказать, уложиться в 256 спрайтов — задача не из легких, именно поэтому изображение выглядит больше как детский рисунок.
У вас там 8 цветов, значит укладываться нужно было в 512 символов, а с учетом инверсии минимум в 1024, и это без оптимизации. Поэтому рисунок и впрямь детский.
За специально подготовленное изображение спасибо художнику A_Foxli.
Посмотрел на его работы. Удивительно что предыдущий абзац озвучил не он и что именно он выдал этот рисунок.
zatim Автор
29.08.2023 07:16Не понял, как вы посчитали. В спрайте кодируется битовая маска изображения, а их - всяких разных в кодовой таблице может быть только 256. Один и тот же спрайт может выводиться разными цветами. Но всего их - 256, одна кодовая таблица. В принципе, никто не мешает занять несколько кодовых таблиц, места в ПЗУ достаточно. В исходном изображении, например, было 400 с чем то уникальных спрайтов, в две кодовые таблицы поместилось бы.
NutsUnderline
29.08.2023 07:16+1В любом случае, даже в 255 символов можно даже примитивное видео закодировать. На ZX Spectrum так BadApple реализовали
zatim Автор
29.08.2023 07:16Один кадр можно закодировать, все видео - маловероятно. Но, если вы уверены, то попробуйте, обещаю опубликовать ваш результат.
NutsUnderline
29.08.2023 07:16Не я лично это делал, но видел реализацию, описание с формулами здесь https://hype.retroscene.org/blog/360.html
Кстати живя в НН нет знакомства с местной демосценой?
NutsUnderline
29.08.2023 07:16Для полноты картины подброшу что когда то давно существовали проекты самодельных видеокарт на ПЛИС которые 3D могли (треугольники с заливкой). Но до логического конца вроде не довели.
IGR2014
29.08.2023 07:16Как для поиграться - круто. но опроса в конце совсем не понял... Зачем оно мне да ещё и в количестве более 1 штуки?!
zatim Автор
29.08.2023 07:16Надо или нет - каждый решает для себя сам. В конце концов, именно для этого в опросе есть пункт "нет". А опрос добавлен с одной целью - я все равно собираюсь заказывать изготовление устройства, поэтому могу заложить небольшой запас для тех, кто тоже захочет приобрести данный девайс.
Worky
29.08.2023 07:16+1Вообще тема интересная, но что во что гаразд - не радует. И это не только по сабжу, это вообще по самодельным компам на Z80 и пр поделкам. Обычно все ограничивается последовательным портом и все. Но хотелось бы графики, игр! И не на плисе, а на каком то ширпотребовском девайсе - малинка пико, стм какойто с встроенной графикой и тд
Из того, что я видел в инете это были такие варианты:
стм проц с граф поддержкой и звуком - Colour Maximite 2. Игры уровня денди можно писать на бейсике. как по мне очень перспективно, если хочется получить игровую консоль и поучиться писать игры (внутри проц стм на 400МГц)
AgonLight2 - eZ80 проц на 33МГц, плюс CP/М, плюс ESP32 для видео, котороый много чего умеет. Подключен по скоростной шине, не дма, но все же. Цена гуманная, в продаже на тини есть. Самый доступный проект и перспективы есть. Присматриваюсь к нему, хочу купить.
для RC2014 компа на базе Z80 делали видюху на базе чипа от параллакса (многоядерный контроллер). якобы умеет спрайты и тд
геймдуино проект, очень впечатлила демо КобрыМК2 из элиты, но похоже, что проект скис, развития не видно
ESP32 VGA32 от ЛилиГО с библиотекой FabGL - готовый девайс с али. есть прошивки с эмулем спекки, сп\м, форта и бейсика.Купил зимой. никак руки не дойдут пощупать.
Хотелось бы стандартизации, акселерации и совместимости, чтобы портировать игры со спекки (и не только) на такие девайсы, но при этом обращение к акселератору было одинаково на разных платах с разными процами. Ведь это же прикольно! все фо фан!
NutsUnderline
29.08.2023 07:16Спектрумов с расширенными режимами понаделали немало, с давних лет, и все они остались нестандартными стандартами, но в целом - такие же ширпотребные как и перечисленные, взял и купил готовое устройство (плату) и софта на них всяко побольше уже понаделано.
Даже и портировать не надо, работает в режиме совместимости, ну а в целом же любое портирование со спектрумов будет означать полное пересоздание игры
Да и на плис давно уже сделали tang, ну и в в общем то MiST (были бы деньги на него) - тоже самое, можно заказать, купить и даже VGA монитор не искать, но тоже своеобразные стандарты.
А вот на любом PC есть поддержка VESA, Direct X, Open GL, ну и более древние, и это вот как раз соответствует "было одинаково на разных платах с разными процами" и каков результат? Пока некоторые рождают новые стандарты (которые сейчас уже в принципе очень мало кому нужны) ПК просто работает, и им же пользуются чтобы эти стандарты рождать.
rus-spb
29.08.2023 07:16Есть 5-ти дюймовые 854х480, 16М-цветные графические экраны с полной видеопамятью на борту.
Легко вешаются на любой STM-подобный микропроцессор, спокойно работает от батарейки.
Контроллер ILI9806G, очень примерно от 2500 руб.
Например, https://aliexpress.ru/item/32674132797.html?sku_id=10000000263874528
simenoff
Если только они вечером/ночью ни разу за ним не сидели
LAutour
А вечером/ночью желательно иметь рядом включеную настольную лампу.
VT100
Особенно — по СанПиН.