Close

Generování VGA signálu s Arduino Uno

Zobrazení 32x15 znaků přes VGA na Arduinu

Způsobů, jak si u Arduina poradit s VGA je hned několik. Mezi ty nejjednodušší patří využití některého z mnoha VGA shieldů, které obsahují svůj vlastní procesor a jsou vybaveny VGA konektorem. Dalším způsobem je vytváření videosignálu přímo v rámci Arduina. V takovém případě toho už ale na svém Arduino mnoho dalšího nerozběhnete, protože většina výkonnostní kapacity procesoru padne právě na generování signálu. A nyní konečně přichází na scénu třetí způsob, který je dílem Damiana Pecketta. Připravte se na bastlení se širokým záběrem!

VGA bez dalšího hardware

Damian pro svůj Arduino projekt nechtěl využít žádný VGA shield a na procesoru Arduina potřeboval rozběhnout relativně náročné aplikace, takže musel přijít s nějakým jiným řešením. Ale abychom pochopili, s čím se Damian potýkal, musíme se nejprve seznámit s protokolem VGA. VGA většinou označuje kromě vlastního protokolu také rozlišení 640×480 pixelů. Kromě tohoto rozlišení ale protokol VGA podporuje i další a to jak menší, tak větší.

Zobrazení jedné řádky

Skutečné rozlišení je vždy větší než viditelná část(v případě 640×480 je to 800×525). Máme tedy 525 řádků na jeden snímek. To znamená, že s obnovovací frekvencí VGA 60Hz je to 31500 řádek za sekundu. Každá řádka se navíc skládá z 800 pixelů (25MHz) a její časový průběh vypadá následovně.

Průběh VGA signálu - horizontální synchronizace (zdroj: http://dpeckett.com/vga-on-the-arduino-with-no-external-parts)

Průběh VGA signálu – horizontální synchronizace [zdroj: http://dpeckett.com/vga-on-the-arduino-with-no-external-parts]

Nejdříve je vidět levý okraj, který se nezobrazuje. Poté přichází na řadu vlastní video signál (25,4 μs). Poté přichází pravý okraj. S malým zpožděním je pak  sníženo napětí horizontální synchronizace a po 3,8 μs je opět zvýšeno, čímž je započata nová řádka.

Zobrazení snímku

Vertikální synchronizace je oproti tomu mnohem jednodušší. V tomto případě máme opět okrajové části a mezi nimi indikujeme, že jsou vysílány video signály. Na konci je pomocí vertikální synchronizace započat další snímek.

Průběh VGA signálu - vertikální synchronizace [zdroj: http://damian.pecke.tt/vga-on-the-arduino-with-no-external-parts

Průběh VGA signálu – vertikální synchronizace [zdroj: http://dpeckett.com/vga-on-the-arduino-with-no-external-parts]

Řešení Daminana Pecketta

Nyní se tedy můžeme dostat k vlastní problematice implementace VGA protokolu na Arduino.

Z diagramu horizontální synchronizace je patrné, že na vykreslení jedné řádky máme 25,4 μs. S AVR, které běží na 16MHz to představuje 400 cyklů na řádku. Pokud bychom tedy chtěli zobrazit 40 znaků na řádce, zbylo by nám 10 cyklů na znak. Změna na pinu zabere 2 cykly a pokud navíc chceme, aby se znaky měnil a bylo možné ho natáhnout z paměti, vychází nám, že jsme schopni vykreslit znak s pouhými 2 horizontálními pixely.

Tento problém vyřešil Damian využitím posuvného registru s paralelním vstupem a sériovým výstupem, který na Arduino slouží k ovládání SPI portu. Tímto způsobem se dostaneme na 5 horizontálních pixelů na znak.

Ve výsledku po připočítání nějakého toho zpoždění dostaneme 4 horizontální pixely na znak. To je celkem klasické rozlišení pro fonty, ale nesmíme zapomenout, že musíme přidat mezery mezi jednotlivé znaky, takže nakonec skončíme s rozlišením znaku 3px. To by mohl být problém. Lze vůbec s tak málo pixely vytvořit čitelný font. Damianovi se ale podařilo najít font z roku 1983 „Tiny Alice“, který má rozlišení znaku 3x5px.

Pak přichází otázka: kam uložit buffer snímků? Jediným možnou odpovědí je SRAM, vzhledem k tomu, že EEPROM je příliš pomalá. SRAM paměť na použitém Arduinu má pouze 512 B a pokud chcete používat přerušení, funkce a podobné, musíte si nechat nějaký prostor navíc. S přihlédnutím na rozlišení displeje a další veličiny autoru vyšlo nejlepší rozlišení displeje 32×15 znaků.

Zobrazení 32x15 znaků přes VGA na Arduinu

Zobrazení 32×15 znaků přes VGA

Nakonec přichází nejtěžší otázka. Jak vyřešit problém s CPU? Prvotním cílem přece bylo nezatížit procesor přespříliš. Damian proto využil čip Atmega16u2, který na Arduino slouží jako převodník mezi sériovou linkou a USB, který k tomuto účelu přeprogramoval.

Článek byl zpracován na základě návodu od Daminana Pecketta http://damian.pecke.tt/vga-on-the-arduino-with-no-external-parts. Na stejném místě naleznete více informací a také zdrojové kódy.

Napsat komentář