forked from markadev/AppleII-VGA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vga.pio
112 lines (100 loc) · 4.27 KB
/
vga.pio
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
; This program consists of 3 state machines communicating using state machine IRQs
; - hsync generates the hsync signal and drives the vsync and data state machines
; - vsync generates the vsync signal and drives the data state machine
; - data generates the pixel data stream, synchronized with the hsync and vsync IRQs
; generated by their respective timing state machine
;
; Overall timing (in pixel times)
;
; Time | hsync action | vsync action | data action
; ------------------------------------------------------------------------------------------------
; 0 | assert lineclk IRQ | |
; 8 | | wait & reset lineclk IRQ |
; 16 | set hsync signal low | set vsync signal high/low |
; 112 | set hsync signal high | |
; 144 | | assert vsync IRQ |
; 144.5 | | | 'wait irq vsync' completes
; 152 | assert hsync IRQ | |
; 152.5 | | | 'wait irq hsync' completes
; 160 | deassert hsync IRQ | | first pixel RGB data out
; 161 | | | second pixel RGB data out
; 216 | | deassert vsync IRQ |
.define LINECLK_IRQ_NUM 4
.define HSYNC_IRQ_NUM 5
.define VSYNC_IRQ_NUM 6
; Run at 2 * pixel frequency
.program vga_data
.origin 0
.wrap_target
pixel_out:
out PINS, 9
out PC, 7
public wait_vsync:
wait 0 irq VSYNC_IRQ_NUM
public wait_hsync:
wait 0 irq HSYNC_IRQ_NUM [1]
public extend_7: ; 8 pixels / an extra 14 clocks (2+6+2+2+2)
nop [1]
public extend_6: ; 7 pixels / an extra 12 clocks (6+2+2+2)
nop [5]
public extend_3: ; 4 pixels / an extra 6 clocks (2+2+2)
nop [1]
public extend_2: ; 3 pixels / an extra 4 clocks (2+2)
nop [1]
public extend_1: ; 2 pixels / an extra 2 clocks
nop [1]
.wrap
; Run at pixel frequency / 8
.program vga_hsync
pull ; load timing loop count from the CPU
.wrap_target
irq set LINECLK_IRQ_NUM [1] ; (0) assert lineclk IRQ
set PINS, 0 [11] ; (16) set hsync signal low
set PINS, 1 [4] ; (112) set hsync signal high
irq clear HSYNC_IRQ_NUM ; (152) assert hsync IRQ
irq set HSYNC_IRQ_NUM ; (160) deassert hsync IRQ
; Wait until the next hsync should be generated
mov X, OSR
skip_loop:
jmp X--, skip_loop
.wrap
; Run at pixel frequency / 8
.program vga_vsync
pull ; load timing loop count from the CPU
.wrap_target
wait 1 irq LINECLK_IRQ_NUM ; (8) wait & reset lineclk IRQ
set pins, 0 [15] ; (16) set vsync signal low
irq clear VSYNC_IRQ_NUM [8] ; (144) assert vsync IRQ
irq set VSYNC_IRQ_NUM ; (216) deassert vsync IRQ
wait 1 irq LINECLK_IRQ_NUM
wait 1 irq LINECLK_IRQ_NUM ; (8) wait for lineclk & reset
set pins, 1 ; (16) set vsync signal high
; Skip the remaining scanlines
mov X, OSR
skip_loop:
wait 1 irq LINECLK_IRQ_NUM
jmp X--, skip_loop
.wrap
; Pixel Frequency: 25.175MHz
;
; Horizontal timing
;
; 640x480@60Hz and 640x400@70Hz (pulse low)
; Scanline part | Pixels | Time [µs]
; ------------------------------------------
; Visible area | 640 | 25.422045680238
; Front porch | 16 | 0.63555114200596
; Sync pulse | 96 | 3.8133068520357
; Back porch | 48 | 1.9066534260179
; Whole line | 800 | 31.777557100298
;
; Vertical timing
;
; [640x480@60Hz (pulse low)] || [640x400@70Hz (pulse high)]
; Frame part | Lines | Time [ms] || Lines | Time [ms]
;------------------------------------------------------------------------
; Visible area | 480 | 15.253227408143 || 400 | 12.711022840119
; Front porch | 10 | 0.31777557100298 || 12 | 0.38133068520357
; Sync pulse | 2 | 0.063555114200596 || 2 | 0.063555114200596
; Back porch | 33 | 1.0486593843098 || 35 | 1.1122144985104
; Whole frame | 525 | 16.683217477656 || 449 | 14.268123138034