
Комментарии 67
Клёвый проект!
В хаб FPGA не хотите добавить? Вроде релевантно.
А можно поподробнее, как физически реализовали двойной буфер? В какой момент происходит перезапись из одного буфера в другой?
Буфер представляет собой 2 отдельные микросхемы. У буфера есть вход select. Когда select равен нулю , то происходит запись в первую микросхему и чтение из второй микросхемы. Когда select равен единице, то происходит запись во вторую микросхему и чтение из первой. Не происходит перезаписи из одной микросхемы в другую, они просто меняются местами.
Меняются местами по команде хоста?
Каждый полученный байт инкрементирует счётчик пикселей. Когда счётчик досчитывает до конца, то сигнал select инвертируется. Получается, что буфер переворачивается, когда полностью заполняется.
Понятно) спасибо за подробности.
Хм, а если хотим только часть кадра перерисовать? Ведь быстрее будет.
Отрисовка в буфер обычно занимает существенно больше времени, чем время вывода одного кадра. Если программа не успеет, то могут появиться неприятные визуальные артефакты. Поэтому, ИМХО, было бы не плохо дать программе возможность управлять процессом переключения буферов.
Я могу хоть 3 часа писать в первый буфер. Картинка то выводится из второго и они не поменяются местами, пока запись не завершится. Буферы меняются местами только после полной перезаписи записываемого буфера. При таком подходе они могут поменяться прямо посреди кадра , но это происходит так быстро , что этого не видно.
Если бы смена буфера осуществлялась между кадрами на каждом кадре , то действительно, надо было бы успевать перезаписывать буфер в течение одного кадра.
Если они и правда меняются в середине кадра, то как бы вы быстро не меняли их, будут артефакты на быстрых движениях. Надо менять строго во время обратного хода луча. Это вообще обязательно.
Мне кажется, не критично. Ну, испортится один кадр артефактами. Следующие кадры ведь воспроизведутся верно. Глаз не сможет заметить повреждение одного кадра.
Если это один кадр, то да видно не будет. Только дело в том, что если вы анимацию показываете, то таких кадров будет очень много если не все. И тогда они становятся видны и очень даже сильно. Всякие движущиеся полосы получаются и другие непотребства.
Ну, это точно не случай, описанный в статье. Гнать анимированную картинку в более-менее приемлемом разрешении по последовательному интерфейсу у вас вряд ли получится.
Ну-у-у, надо считать. На Apple II с частотой процессора 1 MHz и скорость записи в видеопамяти в несколько раз меньше (примерно 2..5мкс на байт) , игры и анимации были возможны.
Да, как ни считай - все одно и выходит. На apple II (и на всех машинах того времени) графическая картинка рисовалась на экране несколько секунд (и это при тех крошечных разрешениях). Более-менее что то шустрое можно было сделать с помощью спрайтовой графики. Спрайты подготавливались заранее и выводились аппаратно. На денди, например, специальный видеопроцессор - полностью спрайтовый.
Если у вас 5 мкс на байт, то чтобы вывести картинку 640х480 глубиной цвета 1 байт нужно 1,5 с. И это при том, что процессор ничем другим не будет заниматься и память - статическая.
Да вы что??? Какие несколько секунд? Я сам писал системы анимации на Apple II. Вполне даже шустро работали. Больше 200ms было признаком низкой квалификации программиста. Не говорю, о профессиональных продуктах, которые и в 3D могли, хоть и ограничено. Никакой специализированный хардуер в AppleII не был – программа и видеопамять.
Я так понимаю, вы про демки говорите? Там есть свои особенности. Во-первых, из системы выжимают все до последнего клока, а во вторых, кроме этой задачи проц ничем не занят. Но и то, 200 мс - это скорее слайд шоу, а не анимация.
Вы же сами предлагали посчитать, я и насчитал 1,5 с. Что не так в расчетах?
Нет, не про демки говорю. Вполне прикладное ПО: Обучающие программы для школы – по химии, физике, игры, презентации всякие. Вы пожалуй слишком молодой. Вот скачайте эмулятор Apple II – скорость компьютера там эмулируется корректно. И сами посмотрите что к чему.
Вы же сами предлагали посчитать, я и насчитал 1,5 с. Что не так в расчетах?
А все там не так. Графический режим в Apple II, это 280х192 пикселей. Один байт кодирует 7 пикселей. Строка: 40 байт x 192 строк = 7680 байт x 5мкс = 38мс. Но это конечно, если не делать никакие обработки. Например очистить экран – будет около того. Но в анимациях очень редко приходилось перерисовать весь экран. Поэтому время хватало и на дополнительные вычисления.
Вы всё верно говорите. Если показывать каждый кадр абсолютно новое изображение, то разрыв кадра будет очень заметен, но в реальном видео почти нет резких переходов и этих артефактов вообще не видно. Это надо прям стоять и выискивать.
Если смена буфера произойдёт посреди кадра, то там не будет битых пикселей, просто первая половина экрана покажет старый кадр, а вторая покажет новый. Если кадры отличаются не сильно, то этого не видно.
Есть sram с двойной шиной данных и адреса. Удивительная вещь. Когда подключал к FPGA было очень удобно писать туда с МК и просто переключать адрес чтения при выводе в vga
Чтобы всем было понятно, нужно нарисовать схему со всеми компонентами или хотябы блок-схему связей.
Интересный проект.
Хабр Торт! Искренне радуюсь, когда вижу подобные статьи. Пробуйте больше с ПЛИС и пишите :)
Супер! И даже Bad Apple не забыли. :)
Позавчера читал вашу статью. Глаза на лоб полезли. Очень круто получилось!
Я рад что Вам понравилось. :-)
Вашу статью я отправил своим студентам как пример того какие безграничные возможности есть у ПЛИС. И да, спасибо за то, что не стали рекламировать чей-то очередной телеграм канальчик. ;)
Было бы круто если попробовали сделать полноценный TBC (корректор временны́х искажений), пусть даже строчный, а не полнокадровый... Очень нужная для работы с аналоговыми источниками, но редкая вещь и новых никто не производит(
TBC - это по сути АЦП, буффер и ЦАП. Строки цифруются и сохраняются в память, а потом "выдаются", но уже через равные промежутки времени, что позволяет это все потом без потерь кадров захватить...
Ох, ковырял их и когда-то... Но сейчас ИМХО проще организовать оцифровку с избыточностью, причём на аппаратном уровне магнитофона. Ведь на не потребно реальное время, а вычислительной мощности сегодня предостаточно... Я был готов реализовать такой проект в середине нулевых, но не нашлось должного количества потенциальных заказов, в отличии на сканирование звуковых аналоговых лент.
Хоть я так и не полюбил ПЛИС-ы, но автору респект. Сам когда-то писал "велосипеды" для вывода картинок/текста на зомбоящик на AVR, STM32 и RISC-V.
Синхронизация VGA намного проще , чем синхронизация PAL. Я совсем не удивлён, что её можно впихнуть в 32 макроячейки. Если вы напишете модуль, который может то же самое, что и мой , но влезает в 32 макроячейки , то я буду аплодировать стоя :)
Полный видеосигнал можно генерить на r2r ЦАПе. Я делал на 8 бит. Если s-video, то можно 3 бита на цветовую поднесущую и 5 бит на яркость+синхросигнал. Поднесущая генерится с помощью DDS. Вот тут видео с цветовыми полосами: https://t.me/enginegger/107
Но ведь это ни разу не PAL. PAL - это стандарт цветного видеосигнала, а тут простой монохромный.
Не, чё годно, кто плавал - оценит! Однако где здесь PAL? Это называется композитным видеосигналом ПТС, по частотам и разложению его можно отнести к PAL\SECAM-ам, но там речь о цвете...
...предлагаю для повышения кликбейтности переименовать PAL в SECAM, дабы попавши на глаза, он вызывал в мозге зрителя сигнал "ШТА!?!?" ;-)
И, все-таки, несмотря на то, что все это очень интересно... В очередной раз, упоминание PAL здесь совсем неуместно. Статью однозначно следовало назвать как-то так: "ч/б видеоадаптер к ТВ на FPGA". С таким же успехом можно было бы взять идентичную временную диаграмму от SECAM, или "неидентичную" от NTSC. А до PAL здесь еще очень далеко: генератор поднесущей, квадратурные модуляторы, коммутаторы четных/нечетных строк, сумматоры,...
Вот тоже баловался с программными кодерами PAL, NTSC, SECAM на stm32:
Выше уже писали про это и я согласен с этим замечанием.
Ой, а запилите хотя-бы пост, кратенько по итогу, сколько времени оно кушает...
Что кушает? На что?
это же stm32 :-) там вычисления занимают конкретное время и можно прикинуть на что его ещё остаётся, например подцепить камеру, пройтись по кадру свёртками, подписи какие-то добавить, итд...
Это мне вопрос. :) В зависимости от типа кодера (PAL, NTSC, SECAM) по-разному. Для pal затраты на "видеоадаптер" составляют в пределах 15% процессорного времени, для NTSC - 13%. Для SECAM не смотрел, но, естественно, явно больше и косвенно можно оценить в сравнении с PAL. Если в PAL, например, демка дает до 36 fps, то в SECAM - до 20 fps. Соответственно, в SECAM "видеоадаптер" кушает в пределах 27% времени ядра.
Здесь надо смотреть еще и в сторону пропускной способности DMA. По дефолту 407 "камень" не потянет такую скорость (~18 Msps PAL, ~15 Msps NTSC, 13.5 Msps SECAM) для DAC. Плюс еще один поток 44100 Гц для звука. Плюс еще один DMA поток для обслуживания "видеоадаптера" ("заливка" и т.п.).
Линейность ЦАПа (соответствие расчётам) смотрели осциллографом?
Господа, это лайк! Лайк и репост!
Хорошо бы поставить на выход ЦАПа буфер (например, эмиттерный повторитель).
На UART тоже можно было бы FSM натянуть. ИМХО, было бы нагляднее и возможно по ресурсам по-приятнее.
Большое спасибо за статью, очень пригодилась.
Пробовал в 623 строке, как у вас делать импульс длительностью 2,35мкс - 120 тактов (при 50МГц)
21'd1990400: temp_sync_1 <= 1'b0;
21'd1990520: temp_sync_1 <= 1'b1;
и 4,7мкс, как по стандарту - разницы в отображении не было.
Искал что не так, когда поймал баг, который я так и не смог решить:
Если попытаться вывести чередуя строки белая-черная-белая, то вместо чередующихся строк - будет мерцание экрана.
Возможно это проблема конкретно на моем контроллере с видеовходом, но похоже что происходит восприятие по формату как на картинке:

И когда дошел до 623 строки, подумал что все, баг найден, но баг не ушел)
PAL видеоадаптер на FPGA с буфером кадра