Witam!
Generowanie obrazu za pomocą AVR w polskim internecie to temat tabu. Zdaję sobie oczywiście sprawę, że wyważam otwarte drzwi, gdyż są już odpowiednie procedury obsługi wyświetlania. Niemniej każdy pisze pod siebie, a raz napisana dobre procedura np. do obsługi LCD, czy jakiejś magistrali jest bezcenna.
Nie jestem zawodowcem w programowaniu, wiec proszę jak najbardziej o konstruktywną krytykę.
Dziś postaram się przybliżyć Wam jak generować linie i złożyć je w cały obraz na TV.
Trochę teorii:
Jedna linia generowana przez działo elektronowe trwa 64us. Na jeden pełny obraz potrzeba 625 linii. Sygnał składa się z dwóch połówek obrazu gdyż po pierwszym przejściu działo kreśli nieparzyste linie a przy drugim parzyste.
Czas na obliczenia:
Linia 64us * 625 linii * 25 klatek/s = równo 1s
Tyle musimy zrobić w tym czasie. Dodam że nie wszystkie linie są widoczne na ekranie (na wyświetlany obraz mamy do dyspozycji 576 linii). W czasie gdy rysujemy niewidoczne linie odbywa się synchronizacja pionowa o częstotliwości 50Hz.
Vsync omówimy sobie kiedy indziej gdyż do dzisiejszego przykładu nam się nie przyda.
Rysowanie linii:
Tu mamy zasadnicze 4 części:
- Front porch trwający około 1,7us. Na pinie VIDEO ustawiamy 0, SYNC 1
- Synchronizacja trwa dokładnie 4,7us. VIDEO 0, SYNC 0
- Sygnał użyteczny trwa 52us. SYNC 1, VIDEO w zależności co chcemy wyświetlić.
- Back porch 5,6us. Na pinie VIDEO ustawiamy 0, SYNC 1
Całość bezwzględnie musi trwać te 64us. Pełną kontrolę nad czasami daje nam język assembler.
Do działania układu potrzebny nam będzie jeszcze prosty DAC oparty na 3 opornikach (schemat w załączniku). Oporniki odpowiadają za poziom napięcia skutecznego. Poziom logiczny 1 na wyjściu VIDEO da nam około 1V,
gdy VIDEO=0 SYNC=1 to odpowiada 0,3V, a VIODE=0 SYNC=0 oczywiście 0V.
Prezentowany kod programu wyświetla nam połowę obrazu biały as a druga połowa czarny. Pisany pod atmega8 o kwarcu 16MHz.
Oczywiście kod nie jest optymalny i marnujemy bez sensu kupę cykli na procedurę "czekaj". Nic nie stoi na przeszkodzie aby zrobić to na przerwaniach
.
W kolejnym odcinku wyświetlanie białego kwadracika na środku ekranu.
Jeżeli będzie zainteresowanie to wstawię płytkę do prototypowego układu posiadający pamięć EEPROM, złącze COM, wyjście dźwięku, wyście obrazu o możliwości dostosowania oprócz białego i czarnego jeszcze 3 poziomów szarości.
Generowanie obrazu za pomocą AVR w polskim internecie to temat tabu. Zdaję sobie oczywiście sprawę, że wyważam otwarte drzwi, gdyż są już odpowiednie procedury obsługi wyświetlania. Niemniej każdy pisze pod siebie, a raz napisana dobre procedura np. do obsługi LCD, czy jakiejś magistrali jest bezcenna.
Nie jestem zawodowcem w programowaniu, wiec proszę jak najbardziej o konstruktywną krytykę.
Dziś postaram się przybliżyć Wam jak generować linie i złożyć je w cały obraz na TV.
Trochę teorii:
Jedna linia generowana przez działo elektronowe trwa 64us. Na jeden pełny obraz potrzeba 625 linii. Sygnał składa się z dwóch połówek obrazu gdyż po pierwszym przejściu działo kreśli nieparzyste linie a przy drugim parzyste.
Czas na obliczenia:
Linia 64us * 625 linii * 25 klatek/s = równo 1s
Tyle musimy zrobić w tym czasie. Dodam że nie wszystkie linie są widoczne na ekranie (na wyświetlany obraz mamy do dyspozycji 576 linii). W czasie gdy rysujemy niewidoczne linie odbywa się synchronizacja pionowa o częstotliwości 50Hz.
Vsync omówimy sobie kiedy indziej gdyż do dzisiejszego przykładu nam się nie przyda.
Rysowanie linii:
Tu mamy zasadnicze 4 części:
- Front porch trwający około 1,7us. Na pinie VIDEO ustawiamy 0, SYNC 1
- Synchronizacja trwa dokładnie 4,7us. VIDEO 0, SYNC 0
- Sygnał użyteczny trwa 52us. SYNC 1, VIDEO w zależności co chcemy wyświetlić.
- Back porch 5,6us. Na pinie VIDEO ustawiamy 0, SYNC 1
Całość bezwzględnie musi trwać te 64us. Pełną kontrolę nad czasami daje nam język assembler.
Do działania układu potrzebny nam będzie jeszcze prosty DAC oparty na 3 opornikach (schemat w załączniku). Oporniki odpowiadają za poziom napięcia skutecznego. Poziom logiczny 1 na wyjściu VIDEO da nam około 1V,
gdy VIDEO=0 SYNC=1 to odpowiada 0,3V, a VIODE=0 SYNC=0 oczywiście 0V.
Prezentowany kod programu wyświetla nam połowę obrazu biały as a druga połowa czarny. Pisany pod atmega8 o kwarcu 16MHz.
.nolist
.include "/home/maro/include/m8def.inc"
.list ;
.listmac
.cseg
.equ video=7 ; pin obrazu video
.equ sync=0 ; pin synchronizacji
.equ port=PORTC ; port synchronizacji
.equ port2=PORTD ; port obrazu video
.org 0 ;generowany kod wynikowy będzie umieszczany w pamięci od adresu o wartości zero
rjmp ResetProcessor ;skok do procedury resetu
ResetProcessor:
cli
ldi r16, high(RAMEND) ;Deklaracja stosu
out SPH,r16
ldi r16, low(RAMEND)
out SPL,r16
sbi DDRD,7 ; ustaw pin video jako wyjście
sbi DDRC,0 ;ustaw pin synch jako wyjście
loop: ; wyświetlamy w nieskończoność tą jedną linię obrazu
cbi port,sync ; synchronizacja
cbi port2,video
ldi r17,21
rcall czekaj
nop
nop
sbi port,sync ; back porch
cbi port2,video
ldi r17,27
rcall czekaj
cbi port2,video ; czarny pas
ldi r17,135
nop
nop
rcall czekaj
sbi port2,video ; biały pas
ldi r17,135
nop
nop
rcall czekaj
cbi port2,video ;front porch
sbi port,sync
ldi r17,3
nop
nop
rcall czekaj
rjmp loop
czekaj:
dec r17
brne czekaj
ret
Oczywiście kod nie jest optymalny i marnujemy bez sensu kupę cykli na procedurę "czekaj". Nic nie stoi na przeszkodzie aby zrobić to na przerwaniach
W kolejnym odcinku wyświetlanie białego kwadracika na środku ekranu.
Jeżeli będzie zainteresowanie to wstawię płytkę do prototypowego układu posiadający pamięć EEPROM, złącze COM, wyjście dźwięku, wyście obrazu o możliwości dostosowania oprócz białego i czarnego jeszcze 3 poziomów szarości.
