Generera VGA med PIC
Postat: 26 maj 2010, 13:56:45
Hej, jag börjar med att säga att det här inte kommer bli något så när coolt som Craft som alla borde ha sett vid det här laget. Målet är att få ut lite olika färger på en skärm med VGA anslutning, i slutändan kanske någon bild eller text.
Hårdvaran som jag använder är PIC16F887 med 20MHz kristall.
Eftersom PIC:en går på 20MHz tar varje instruktion 0.2us.
Lite om VGA:
VGA upplösning ligger på 640x480 @ 60Hz.
VGA kräver fem signaler, R, G, B samt horisontal synk och vertikal synk.
Nivåerna på färgsignalerna ligger på 0.7V där 0.7V är högst intensitet och 0V är lägst.
Hsynk och Vsynk är TTL nivåer och aktivt låga.
Vsynk signalen pulsas varje gång man når botten av en frame.
Hsynk signalen pulsas vid slutet på varje rad med pixlar.
Bilden uppdateras 60 gånger per sekund vilket ger att varje frame tar
60Hz = 16 666.6667us eller ca 16.67ms
Hsynk klockan ligger på 31 469Hz per frame = 31.777us per line
Pixelklockan för VGA upplösning ligger på 25.175MHz, vid varje klockpuls så läggs nya analoga värden ut.
Därför måste vi dela 31.777 med 1/25.175, det ger oss 800 pixlar för varje linje. Tiden för varje pixel är 1/25.175 (pixelklockan) viket är 0.03972125us (redan nu ser ni att det blir omöjligt att generera 640 pixlar med en PIC).
Varje linje är lite mer än 640. Förklaringen är att det före och efter synkpulserna är det lite dötid då färgsingnalerna ligger på 0V, kallas horisontal- repektive vertikal blankning, samt att synkpulserna i sig tar lite tid, på CRT skärmar tar det tid för elektronstrålen att flytta sig till andra sidan eller från botten till toppen av skärmen.
Exakta tider ser ni här nedan
Timingen är hämtad från en manual till en HP skärm
Timingen kan variera lite grann mellan olika grafikkort och skärmar, det är sånt man får ta när man kör analogt...
Omräknat till instruktionscykler för PIC:
Som ni ser blir det knappast exakt med 20MHz PIC och endast 126 cykler under video tiden. Anta att man ska hämta värden från en array och lägga ut på färgsinalerna, det tar väl 7-8 instruktioner bara det. Det ger oss en effektiv upplösning på kanske 20 pixlar. Men något är det iallafall, t.ex en smilie
RGB signalern kopplar jag till var sin utgång på PIC:en. För att få RGB signalerna till rätt nivå sätter jag ett motstånd i serie med signalen och clampar ner till jord med en diod. Då får jag ca 0.7V ut som max.
Ett litet kopplingschema över det hela:

Tråden kommer uppdateras så fort jag fått klart den tidskritiska koden och har något att visa. Koden kommer vara en blandning C och inline assembler.
Hårdvaran som jag använder är PIC16F887 med 20MHz kristall.
Eftersom PIC:en går på 20MHz tar varje instruktion 0.2us.
Lite om VGA:
VGA upplösning ligger på 640x480 @ 60Hz.
VGA kräver fem signaler, R, G, B samt horisontal synk och vertikal synk.
Nivåerna på färgsignalerna ligger på 0.7V där 0.7V är högst intensitet och 0V är lägst.
Hsynk och Vsynk är TTL nivåer och aktivt låga.
Vsynk signalen pulsas varje gång man når botten av en frame.
Hsynk signalen pulsas vid slutet på varje rad med pixlar.
Bilden uppdateras 60 gånger per sekund vilket ger att varje frame tar
60Hz = 16 666.6667us eller ca 16.67ms
Hsynk klockan ligger på 31 469Hz per frame = 31.777us per line
Pixelklockan för VGA upplösning ligger på 25.175MHz, vid varje klockpuls så läggs nya analoga värden ut.
Därför måste vi dela 31.777 med 1/25.175, det ger oss 800 pixlar för varje linje. Tiden för varje pixel är 1/25.175 (pixelklockan) viket är 0.03972125us (redan nu ser ni att det blir omöjligt att generera 640 pixlar med en PIC).
Varje linje är lite mer än 640. Förklaringen är att det före och efter synkpulserna är det lite dötid då färgsingnalerna ligger på 0V, kallas horisontal- repektive vertikal blankning, samt att synkpulserna i sig tar lite tid, på CRT skärmar tar det tid för elektronstrålen att flytta sig till andra sidan eller från botten till toppen av skärmen.
Exakta tider ser ni här nedan
Kod: Markera allt
Horizonal Timing
Horizonal Dots 640
Vertical Scan Lines 480
Horiz. Sync Polarity NEG
A (us) 31.77 Scanline time
B (us) 3.77 Sync pulse lenght
C (us) 1.89 Back porch
D (us) 25.17 Active video time
E (us) 0.94 Front porch
______________________ ________
________| VIDEO |________| VIDEO (next line)
|-C-|----------D-----------|-E-|
__ ______________________________ ___________
|_| |_|
|B|
|---------------A----------------|
Vertical Timing
Horizonal Dots 640
Vertical Scan Lines 480
Vert. Sync Polarity NEG
Vertical Frequency 60Hz
O (ms) 16.68 Total frame time
P (ms) 0.06 Sync length
Q (ms) 1.02 Back porch
R (ms) 15.25 Active video time
S (ms) 0.35 Front porch
______________________ ________
________| VIDEO |________| VIDEO (next frame)
|-Q-|----------R-----------|-S-|
__ ______________________________ ___________
|_| |_|
|P|
|---------------O----------------|
Timingen kan variera lite grann mellan olika grafikkort och skärmar, det är sånt man får ta när man kör analogt...
Omräknat till instruktionscykler för PIC:
Kod: Markera allt
Hsync
0 Hsync low, 0 cyc
3.8 us Hsync high, +19 cyc
1.8 us back porch, +9 cyc
25.2 us video, +126 cyc
1 us front porch, +5 cyc
---
31.8 us 159cyc
Vsync
0 Vsync low, 0 cyc
60 us Vsync high, +300 cyc
1020 us back porch, +5100 cyc
15250 us video, +76250 cyc
350 us front porch, +1750 cyc
---
16680 us 83400 cyc

RGB signalern kopplar jag till var sin utgång på PIC:en. För att få RGB signalerna till rätt nivå sätter jag ett motstånd i serie med signalen och clampar ner till jord med en diod. Då får jag ca 0.7V ut som max.
Ett litet kopplingschema över det hela:

Tråden kommer uppdateras så fort jag fått klart den tidskritiska koden och har något att visa. Koden kommer vara en blandning C och inline assembler.