/
vga.pio
211 lines (197 loc) · 5.42 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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
.program hsync_vga
.side_set 1 opt
.wrap_target
irq clear 4
mov osr, y
out x, 8 side 0 ; sync pulse -1
loop1:
jmp x--, loop1 [4]
out x, 8 side 1 ; back porch -1
loop2:
jmp x--, loop2 [4]
irq clear 6 ; pixel start
out x, 16 ; pixel count + front porch -1
loop3:
jmp x--, loop3 [4]
.wrap
.program vsync_vga
.side_set 1 opt
.wrap_target
irq 0 ; vsync interrput
irq wait 4 side 0
irq wait 4
mov osr, y side 1
out x, 16 ; back porch -1
loop1:
irq wait 4
jmp x--, loop1
out x, 16 ; valid line count -1
loop2:
irq wait 4
irq clear 5 ; pixel valid
jmp x--, loop2
set x, 9 ; front porch -1
loop3:
irq wait 4
jmp x--, loop3
.wrap
.program pixel_vga
.side_set 3 opt
.wrap_target
out null, 32 ; discard first data
mov x, y
irq wait 5 side 0 ; wait for valid V line
irq wait 6 ; wait for pixel start
loop:
out pins, 3 ; output pixel data
out null, 1 [1]
jmp x--, loop [1]
.wrap
.program hsync_xga
.side_set 1 opt
.wrap_target
irq clear 4
mov osr, y
out x, 8 side 0 ; sync pulse -1
loop1:
jmp x--, loop1 [1]
out x, 8 side 1 ; back porch -1
loop2:
jmp x--, loop2 [1]
irq clear 6 ; pixel start
out x, 16 ; pixel count + front porch -1
loop3:
jmp x--, loop3 [1]
.wrap
.program vsync_xga
.side_set 1 opt
.wrap_target
irq 0 ; vsync interrput
set x, 5 side 0 ; sync pulse -1
loop0:
irq wait 4
jmp x--, loop0
set x, 28 side 1 ; back porch -1
loop1:
irq wait 4
jmp x--, loop1
mov x, y ; valid line count -1
loop2:
irq wait 4
irq clear 5 ; pixel valid
jmp x--, loop2
set x, 2 ; front porch -1
loop3:
irq wait 4
jmp x--, loop3
.wrap
.program pixel_xga
.side_set 1 opt
.wrap_target
out null, 32 ; discard first data
mov x, y
irq wait 5 side 0 ; wait for valid V line
irq wait 6 ; wait for pixel start
loop:
out pins, 1 ; output pixel data
jmp x--, loop
.wrap
.program copy
.wrap_target
mov pins, pins
.wrap
% c-sdk {
#define XGA
#ifdef XGA
#define PIX_XN 1024
#define PIX_YN 768
#define PIN_MONO 22
#else
#define PIX_XN 640
#define PIX_YN 480
#endif
#define PIN_VSYNC 14
#define PIN_HSYNC 18
#define PIN_RGB 15 // 15:BLUE, 16:GREEN, 17:RED
static inline void hsync_program_init(PIO pio, uint sm) {
#ifdef XGA
const uint front = 24, sync = 136, back = 160;
uint offset = pio_add_program(pio, &hsync_xga_program);
pio_sm_config c = hsync_xga_program_get_default_config(offset);
#else
const uint front = 16, sync = 96, back = 48;
uint offset = pio_add_program(pio, &hsync_vga_program);
pio_sm_config c = hsync_vga_program_get_default_config(offset);
#endif
sm_config_set_sideset_pins(&c, PIN_HSYNC);
sm_config_set_out_shift(&c, true, false, 32); // shift right, no-autopull
pio_gpio_init(pio, PIN_HSYNC);
pio_sm_set_consecutive_pindirs(pio, sm, PIN_HSYNC, 1, true); // output
pio_sm_init(pio, sm, offset, &c);
// jmp以外でかかる3ドットクロックを調整するため1ループずつ減らす
pio_sm_put_blocking(pio, sm, (PIX_XN + front - 2) << 16 | (back - 2) << 8 | (sync - 2));
pio_sm_exec_wait_blocking(pio, sm, pio_encode_pull(false, false));
pio_sm_exec_wait_blocking(pio, sm, pio_encode_mov(pio_y, pio_osr));
}
static inline void vsync_program_init(PIO pio, uint sm) {
#ifdef XGA
uint offset = pio_add_program(pio, &vsync_xga_program);
pio_sm_config c = vsync_xga_program_get_default_config(offset);
#else
const uint back = 33;
uint offset = pio_add_program(pio, &vsync_vga_program);
pio_sm_config c = vsync_vga_program_get_default_config(offset);
#endif
sm_config_set_sideset_pins(&c, PIN_VSYNC);
sm_config_set_out_shift(&c, true, false, 32); // shift right, no-autopull
pio_gpio_init(pio, PIN_VSYNC);
pio_sm_set_consecutive_pindirs(pio, sm, PIN_VSYNC, 1, true); // output
pio_sm_init(pio, sm, offset, &c);
#ifdef XGA
pio_sm_put_blocking(pio, sm, PIX_YN - 1);
#else
pio_sm_put_blocking(pio, sm, (PIX_YN - 1) << 16 | (back - 1));
#endif
pio_sm_exec_wait_blocking(pio, sm, pio_encode_pull(false, false));
pio_sm_exec_wait_blocking(pio, sm, pio_encode_mov(pio_y, pio_osr));
}
static inline void pixel_program_init(PIO pio, uint sm) {
#ifdef XGA
uint offset = pio_add_program(pio, &pixel_xga_program);
pio_sm_config c = pixel_xga_program_get_default_config(offset);
sm_config_set_out_pins(&c, PIN_MONO, 1);
sm_config_set_sideset_pins(&c, PIN_MONO);
#else
uint offset = pio_add_program(pio, &pixel_vga_program);
pio_sm_config c = pixel_vga_program_get_default_config(offset);
sm_config_set_out_pins(&c, PIN_RGB, 3);
sm_config_set_sideset_pins(&c, PIN_RGB);
#endif
sm_config_set_out_shift(&c, true, true, 32); // shift right, autopull
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
#ifdef XGA
pio_gpio_init(pio, PIN_MONO);
pio_sm_set_consecutive_pindirs(pio, sm, PIN_MONO, 1, true); // output
#else
pio_gpio_init(pio, PIN_RGB);
pio_gpio_init(pio, PIN_RGB + 1);
pio_gpio_init(pio, PIN_RGB + 2);
pio_sm_set_consecutive_pindirs(pio, sm, PIN_RGB, 3, true); // output
#endif
pio_sm_init(pio, sm, offset, &c);
pio_sm_put_blocking(pio, sm, PIX_XN - 1);
pio_sm_exec_wait_blocking(pio, sm, pio_encode_pull(false, false));
pio_sm_exec_wait_blocking(pio, sm, pio_encode_mov(pio_y, pio_osr));
}
static inline void copy_program_init(PIO pio, uint sm, uint offset, uint dstpin) {
#ifdef XGA
pio_sm_config c = copy_program_get_default_config(offset);
sm_config_set_in_pins(&c, PIN_MONO);
sm_config_set_out_pins(&c, dstpin, 1);
pio_gpio_init(pio, dstpin);
pio_sm_set_consecutive_pindirs(pio, sm, dstpin, 1, true); // output
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
#endif
}
%}