Генератор видео на STM32F407: рецепт быстрого приготовления

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

Предыстория

Как-то неожиданно в моём авто появилась Вебаста. Штука удобная и полезная. Управляется фирменным таймером. Кто в теме, тот знает, что это такая овальная приблуда, обычно устанавливаемая на приборную панель. Портит интерьер, нужно сверлить дырку в торпеде, и ценник неслабый. Есть ещё блок дистанционного радиоуправления, купить который жаба не позволяет.

Есть альтернативный вариант — для управления использовать автомагнитолу. Комфортный экран, есть возможность тыкать в него пальцами и иметь обратную связь. Вопщем, сказано — сделано:


Магнитола предпочитает видео стандарта NTSC, поэтому далее будет идти речь именно об этом формате
(хотя при желании можно конечно замутить VGA/PAL etc). Собственно, из формата NTSC мы возьмём только тайминги. Про несущие/поднесущие и прочий хлам можно забыть, так как будем делать простой RGB-сигнал.

Что нужно сгенерить


Для успешного видеопоказа необходимы следующие сигналы:

  • сигнал строчной синхронизации HSYNC;
  • сигнал кадровой синхронизации VSYNC (иногда объединяется с HSYNC в композитный синхро CSYNC);
  • три сигнала яркости/цветности, R+G+B.

И ещё раз повторю: будем делать RGB-сигнал. Программно сформировать полноценное композитное видео — проблема (хотя и решаемая); если кому очень надо — лучше воспользоваться аппаратным кодером AD724/5 или подобным.

В Сети есть масса информации про форматы видеосигнала. Я пользовался, например, вот этим.


Итак, один кадр состоит из 525 строк. Видимых (полезных) из них — только 485. Это есть разрешение по вертикали. А разрешение по горизонтали обычно определяется полосой пропускания видеотракта. С другой стороны, если хочется реализовать квадратный пиксель на экране, скажем, формата 16:9, то необходимо напечатать около 485*16/9 = 862 точек.

Т.е. полноценный кадр должен иметь размер 862*485 px. Хорошо. А хватит ли памяти, чтобы отобразить столько пикселей? И вообще, нужно ли столько?

Для формирования изображения можно использовать следующие методы:

Вариант 1. Если требуется выводить только текстовую информацию, то незачем хранить в памяти весь кадр. Можно иметь текстовый буфер и буфер на одну видеостроку. Каждая видеострока формируется непосредственно перед выводом посредством знакогенератора. Так например сделано в Простом VGA/Video адаптере.

Вариант 2. Цветную графическую информацию можно хранить в виде спрайтов (в памяти FLASH). Видеостроку также подготавливать непосредственно перед показом. Типичный пример — игровая консоль Uzebox.

Ну а если хочется иметь произвольную текстовую и графическую информацию — то просто необходим вариант 3. Это полноценный видеобуфер, где за каждым экранным пикселем закреплена определённая область памяти. 1, 8, 16 бит на точку — зависит от желаемой глубины цвета.

Кстати, можно существенно сэкономить, если уменьшить цветовое разрешение. Как это было сделано в легендарном ZX-Spectrum. Там каждому пикселу отводился 1 бит (включен/выключен), а цвет хранился сразу для целого знакоместа 8*8 px. Но такая экономия оборачивается сложностью подготовки картинки. Если кто помнит, в спектрумовских играх довольно часто вокруг юркого подвижного героя возникали цветные артефакты.

Не будем создавать себе сложностей, и реализуем самый простой вариант №3.

Наиболее оптимально с аппаратной и программной точки зрения иметь 8 бит на пиксель. Либо использовать монохромный режим, 1 бит на 1 пиксель. В последнем случае можем воспользоваться SPI (аппаратно преобразовать параллельные 8 бит в последовательные). Но это не наш метод — монохромное однобитное изображение выглядит слишком скучно.

Значит, 862*485 = 408 кб ОЗУ. Многовато для встроенной памяти. А внешнюю SRAM прикручивать ну совсем не хочется. А если уменьшить разрешение в 2 раза?

431*242 = 102 кб — это уже нормально, влезает. Для экрана автомагнитолы (6'') такого разрешения вполне достаточно. Кстати, раз уменьшили вертикальное разрешение, то можем упростить себе задачу и отказаться от чересстрочной развёртки.


Приступимс


Микроконтроллер STM32 изобилует периферийными «примочками», поэтому грех ими не воспользоваться. Видео гнать будем через DMA, а тактировать и синхронизировать — от встроенных аппаратных таймеров. Упрощённая структурная схема такова:


Тайминги:

Здесь выделена частота кадровая, строчная и некая магическая константа. Кварц именно такой частоты (14,318 МГц) стоит в большинстве кодеров/декодеров цвета. Как наследство первых персональных компьютеров (подключаемых к бытовому телевизору), такой кварцевый резонатор перекочевал и в IBM-PC.

По-хорошему, чтобы точно соблюсти эти частоты, на плате STM32F4Discovery нужно заменить кварцевый резонатор. Но лениво как-то. Строчную частоту можно довольно точно получить например из 162 МГц делением на 10296. А 162 МГц получим от штатного HSE на 8 МГц.

Если вдруг решитесь на замену резонатора — то не забудьте снять резистор R68, иначе HSE будет продолжать работать на 8 МГц (см. схему Discovery).

Так как мы отказались от чересстрочной развёртки, то полукадры фактически стали кадрами. В каждом кадре будет 525/2=262 строки. И кадровая частота чуть изменится.

Порт RGB


Подключить несложный ЦАП к любому порту (8 младших либо старших бит). Взято из Uzebox:

Развязывающие конденсаторы добавить по вкусу. Хотя вполне можно обойтись и без них.

В STM32F4Discovery нет полностью свободных портов. Будем осваивать PORTD пины 0..7, пожертвовав аудиоЦАПой (сигнал RST) и контролем перегрузки USB (PD5, требуется снять R50).

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

DMA


Нужно выбрать подходящий поток и канал DMA. Чтобы это сделать, сначала смотрим на схему шинной организации. Оказывается, не все DMA одинаково полезны:

GPIO подключен к шине AHB1, а с ней может работать только DMA2.

Примечание: ОЗУ микроконтроллера поделено на несколько блоков, по-разному подключенных к внутренним шинам. Для видеоОЗУ логично использовать SRAM1, а стек, переменные и прочие ресурсы разместить в CCM. Иначе ядро ARM, обращаясь к SRAM1, будет задерживать транзакции DMA. Как результат — дрожание фазы видеосигнала и появление ряби/муара.

Тактирование DMA

«Пинать» DMA будет какой-нибудь таймер. Какой? Смотрим другую картинку:


При всём богатстве выбора другой альтернативы нет: либо TIM1, либо TIM8.

Берём первый. Он будет работать в режиме SlaveMode_Gated. Т.е. сигнал тактирования будет включаться на время активности некоего сигнала. Эти «ворота» будут формироваться другим таймером — генератором строчной развёртки.

TIM1 может быть подчинённым у следующих таймеров (см. описание регистра TIMx_SMCR):

Отлично, выбираем

Генератор строчной развёртки


Пусть им будет таймер TIM2. Его задача — дать стабильный синхро (красный), попутно управляя таймером тактирования DMA (синяя трасса).


Остальные действия, не требующие супержёсткой привязки ко времени, будем выполнять по прерыванию. Там посчитаем строки, настроим DMA, сформируем HSYNC…

Итоговая структурная схема


Реализацию см. в приложении. Инструментарий — Eclipse + ARM GCC + ARM plugin + OpenOCD.

Тайминги осциллографом, наконец, проверены, все системы работают нормально, пора делать

Натурные испытания


Демонстрационный экран любезно предоставлен устройством SONY XAV-601BT. Его LCD-экран имеет размер 800*480px (а экран-то формата 5:3, а не 16:9). Сложная для отображения картинка — вертикальные линии с интервалом 1 пиксел:



Понятно, что размер нашего изображения не кратен нативному разрешению дисплея, поэтому имеем муар. Требуется подстройка TIM1. Или, точнее, подстройка соотношения пиксельной частоты к частоте строчной развёртки HSYNC. Подстраиваем в небольших пределах TIM1->ARR и TIM2->ARR до получения приемлемой картинки.
К слову сказать, в рабочей картинке (см. в начале статьи) муар практически отсутствует. В боевых условиях (во время движения авто) — проблема ваще не актуальна.

А вот на картинке с вертикальными линиями удвоенной ширины — придраться особо не к чему:



И в заключение необходимо подкорректировать размер картинки под конкретные условия работы. К примеру, мой экран честно отображает 240 строк. Но, учитывая типичный верхний угол наблюдения, несколько верхних строк скрываются пластмассовой окантовкой корпуса. Ну и нечего на них тратить память и процессорное время.

Напоследок: чтобы по окончании строки установить уровень чёрного (время обратного хода строчной развёртки, когда измеряется «уровень чёрного»), можно зарезервировать в экранном ОЗУ последнюю вертикальную линию шириной в пиксел и записать туда 0. GUI, естественно, про этот столбец ничего не говорить.

Итоги


Для генерации видео оказалось достаточно двух аппаратных таймеров, одного канала DMA и немного ОЗУ. Неплохо. Процессор 90% времени (-O0) может заниматься своими делами, по мере необходимости подкидывая в SRAM1 новые пригоршни разноцветных точек. И иногда (каждые 63,5 мкс) прерываясь на загрузку DMA. Естественно, во избежание неприятностей этому прерыванию нужно назначить высший приоритет.

А как прикрутить GUI ?


А это уже совсем другая история…
  • +17
  • 17 ноября 2014, 02:05
  • MikeSmith
  • 1
Файлы в топике: RGB_gen.zip

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

RSS свернуть / развернуть
Это же на STM32F429Discovery можно Full HD сделать!
0
Неа, с аппаратным модулем видео там максимум 1024х768 60Hz 8bit (подменять таблицу цветов по ходу дела, вроде, не запрещено), большее он, видимо, не успевает. Но с помощью кодеров VGA/HDMI/LCD на вывод подключается влёт, причём микросхемы-кодеры на VGA и HDMI даже настраивать не обязательно.
По идее, можно сделать с помощью видео-цап и чересстрочный композит/s-video, но там есть ряд сложностей по синхронизации его с модулем ltdc.з.
0
Как планируется это подключать к вебасте? Очень интересует именно эта часть.
0
Модификаций у Вебасты довольно много, отличаются и интерфейсы. В моём случае это Webasto Thermo Top Evo 4 с цифровой шиной управления W-bus. По физике шина идентична K-Line.
+1
Спасибо, тема интересная

0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.