1 = VGA Signal Output = 2 3 A number of [[VGA Output Examples|examples]] demonstrate VGA signal generation 4 from a PIC32 microcontroller. These examples employ a particular [[VGA Signal 5 Wiring|wiring scheme]] in order to deliver signals to a suitable display or 6 monitor. 7 8 Within the microcontroller, there are two principal mechanisms demonstrated in 9 this project for generating a VGA signal: 10 11 * Using the CPU to "copy" pixel data to an output port 12 * Using DMA transfers to "copy" pixel data to an output port 13 14 Within the latter, there are a number of variations in the mechanism employed: 15 16 * Use of general-purpose output pins versus parallel mode outputs 17 * Use of large transfer cells containing each entire pixel line versus small 18 transfer cells containing fragments of each line 19 * Use of a single transfer-initiating event versus separate line-initiating 20 and transfer-initiating events 21 22 == Using the CPU for Transfers == 23 24 {{{#!graphviz 25 //format=svg 26 //transform=notugly 27 digraph cpu { 28 node [shape=box,fontsize="13.0",fontname="sans-serif"]; 29 rankdir=TD; 30 31 subgraph { 32 rank=same; 33 34 timer [label="Display line\ntimer",style=filled,fillcolor=gold]; 35 t_0 [label="0",shape=ellipse]; 36 t_hsync [label="hsync",shape=ellipse]; 37 t_limit [label="limit",shape=ellipse]; 38 } 39 40 oc1 [label="Output compare",style=filled,fillcolor=gold]; 41 42 subgraph { 43 rank=same; 44 45 lineirq [label="Display line\ninterrupt handler"]; 46 pixelirq [label="Pixel output\ninterrupt handler"]; 47 } 48 49 subgraph { 50 rank=same; 51 52 pixels [label="Pixel output\nBlack/reset output",style=filled,fillcolor=green,shape=parallelogram]; 53 hsync [label="Horizontal sync",shape=house,style=filled,fillcolor=red]; 54 vsync [label="Vertical sync",shape=house,style=filled,fillcolor=red]; 55 } 56 57 /* The timer starts at 0 and wraps around at limit. */ 58 59 timer -> t_0 [arrowhead=none]; 60 t_0 -> t_hsync -> t_limit -> t_0 [style=dashed]; 61 62 /* The timer initiates the interrupt request for pixel production. */ 63 64 t_0 -> pixelirq; 65 66 /* The interrupt handler generates the pixel output. */ 67 68 pixelirq -> pixels; 69 70 /* The timer feeds the output compare unit, driving hsync. */ 71 72 t_hsync -> oc1; 73 oc1 -> hsync; 74 75 /* The output compare unit initiates the interrupt request for each line, 76 driving vsync. */ 77 78 oc1 -> lineirq; 79 lineirq -> vsync; 80 } 81 }}} 82 83 == Using DMA for Transfers == 84 85 {{{#!graphviz 86 //format=svg 87 //transform=notugly 88 digraph dma { 89 node [shape=box,fontsize="13.0",fontname="sans-serif"]; 90 rankdir=TD; 91 92 subgraph { 93 rank=same; 94 95 timer [label="Display line\ntimer",style=filled,fillcolor=gold]; 96 t_0 [label="0",shape=ellipse]; 97 t_hsync [label="hsync",shape=ellipse]; 98 t_limit [label="limit",shape=ellipse]; 99 } 100 101 oc1 [label="Output compare",style=filled,fillcolor=gold]; 102 103 subgraph { 104 rank=same; 105 106 dma_line [label="Pixel output\nDMA channel",style=filled,fillcolor=lightblue]; 107 dma_reset [label="Pixel reset\nDMA channel",style=filled,fillcolor=lightblue]; 108 lineirq [label="Display line\ninterrupt handler"]; 109 } 110 111 subgraph { 112 rank=same; 113 114 pixels [label="Pixel output",style=filled,fillcolor=green,shape=parallelogram]; 115 black [label="Black/reset output",style=filled,fillcolor=black,fontcolor=white,shape=parallelogram]; 116 hsync [label="Horizontal sync",shape=house,style=filled,fillcolor=red]; 117 vsync [label="Vertical sync",shape=house,style=filled,fillcolor=red]; 118 } 119 120 /* The timer starts at 0 and wraps around at limit. */ 121 122 timer -> t_0 [arrowhead=none]; 123 t_0 -> t_hsync -> t_limit -> t_0 [style=dashed]; 124 125 /* The timer initiates the DMA transfer for pixel production. */ 126 127 t_0 -> dma_line; 128 129 /* The line channel generates the pixel output. */ 130 131 dma_line -> pixels; 132 133 /* The completion of the line channel initiates the reset channel. */ 134 135 dma_line -> dma_reset; 136 137 /* The reset channel generates black/reset output. */ 138 139 dma_reset -> black; 140 141 /* The black/reset value follows the visible pixels. */ 142 143 pixels -> black [style=dashed]; 144 145 /* The timer feeds the output compare unit, driving hsync. */ 146 147 t_hsync -> oc1; 148 oc1 -> hsync; 149 150 /* The output compare unit initiates the interrupt request for each line, 151 driving vsync. */ 152 153 oc1 -> lineirq; 154 lineirq -> vsync; 155 } 156 }}} 157 158 == Using DMA and Timed Transfers == 159 160 {{{#!graphviz 161 //format=svg 162 //transform=notugly 163 digraph dma { 164 node [shape=box,fontsize="13.0",fontname="sans-serif"]; 165 rankdir=TD; 166 167 subgraph { 168 rank=same; 169 170 timer [label="Display line\ntimer",style=filled,fillcolor=gold]; 171 t_0 [label="0",shape=ellipse]; 172 t_hsync [label="hsync",shape=ellipse]; 173 t_limit [label="limit",shape=ellipse]; 174 } 175 176 oc1 [label="Output compare",style=filled,fillcolor=gold]; 177 178 subgraph { 179 rank=same; 180 181 trtimer [label="Transfer timer",style=filled,fillcolor=gold]; 182 tr_0 [label="0",shape=ellipse]; 183 tr_limit [label="limit",shape=ellipse]; 184 } 185 186 subgraph { 187 rank=same; 188 189 dma_init [label="Initiator\nDMA channel",style=filled,fillcolor=lightblue]; 190 dma_line [label="Pixel output\nDMA channel",style=filled,fillcolor=lightblue]; 191 dma_reset [label="Pixel reset\nDMA channel",style=filled,fillcolor=lightblue]; 192 lineirq [label="Display line\ninterrupt handler"]; 193 } 194 195 subgraph { 196 rank=same; 197 198 pixels [label="Pixel output",style=filled,fillcolor=green,shape=parallelogram]; 199 black [label="Black/reset output",style=filled,fillcolor=black,fontcolor=white,shape=parallelogram]; 200 hsync [label="Horizontal sync",shape=house,style=filled,fillcolor=red]; 201 vsync [label="Vertical sync",shape=house,style=filled,fillcolor=red]; 202 } 203 204 /* The line timer starts at 0 and wraps around at limit. */ 205 206 timer -> t_0 [arrowhead=none]; 207 t_0 -> t_hsync -> t_limit -> t_0 [style=dashed]; 208 209 /* The transfer timer starts at 0 and wraps around at limit. */ 210 211 trtimer -> tr_0 [arrowhead=none]; 212 tr_0 -> tr_limit -> tr_0 [style=dashed]; 213 214 /* The line timer initiates the DMA transfers for the display line. */ 215 216 t_0 -> dma_init; 217 218 /* The completion of the initiating channel enables the line channel. */ 219 220 dma_init -> dma_line; 221 222 /* Each cell transfer in the line channel is initiated by the transfer 223 timer. */ 224 225 tr_0 -> dma_line; 226 227 /* The line channel generates the pixel output. */ 228 229 dma_line -> pixels; 230 231 /* The completion of the line channel initiates the reset channel. */ 232 233 dma_line -> dma_reset; 234 235 /* The reset channel generates black/reset output. */ 236 237 dma_reset -> black; 238 239 /* The black/reset value follows the visible pixels. */ 240 241 pixels -> black [style=dashed]; 242 243 /* The timer feeds the output compare unit, driving hsync. */ 244 245 t_hsync -> oc1; 246 oc1 -> hsync; 247 248 /* The output compare unit initiates the interrupt request for each line, 249 driving vsync. */ 250 251 oc1 -> lineirq; 252 lineirq -> vsync; 253 } 254 }}} 255 256 == Using DMA and Timed Dual-Channel Transfers == 257 258 {{{#!graphviz 259 //format=svg 260 //transform=notugly 261 digraph dma { 262 node [shape=box,fontsize="13.0",fontname="sans-serif"]; 263 rankdir=TD; 264 265 subgraph { 266 rank=same; 267 268 timer [label="Display line\ntimer",style=filled,fillcolor=gold]; 269 t_0 [label="0",shape=ellipse]; 270 t_hsync [label="hsync",shape=ellipse]; 271 t_limit [label="limit",shape=ellipse]; 272 } 273 274 oc1 [label="Output compare",style=filled,fillcolor=gold]; 275 276 subgraph { 277 rank=same; 278 279 trtimer [label="Transfer timer",style=filled,fillcolor=gold]; 280 tr_0 [label="0",shape=ellipse]; 281 tr_limit [label="limit",shape=ellipse]; 282 } 283 284 subgraph { 285 rank=same; 286 287 dma_init [label="Initiator\nDMA channel",style=filled,fillcolor=lightblue]; 288 dma_line [label="{Pixel output\nDMA channel #1 | Pixel output\nDMA channel #2}",style=filled,fillcolor=lightblue,shape=record]; 289 dma_reset [label="Pixel reset\nDMA channel",style=filled,fillcolor=lightblue]; 290 lineirq [label="Display line\ninterrupt handler"]; 291 } 292 293 subgraph { 294 rank=same; 295 296 pixels [label="Pixel output",style=filled,fillcolor=green,shape=parallelogram]; 297 black [label="Black/reset output",style=filled,fillcolor=black,fontcolor=white,shape=parallelogram]; 298 hsync [label="Horizontal sync",shape=house,style=filled,fillcolor=red]; 299 vsync [label="Vertical sync",shape=house,style=filled,fillcolor=red]; 300 } 301 302 /* The line timer starts at 0 and wraps around at limit. */ 303 304 timer -> t_0 [arrowhead=none]; 305 t_0 -> t_hsync -> t_limit -> t_0 [style=dashed]; 306 307 /* The transfer timer starts at 0 and wraps around at limit. */ 308 309 trtimer -> tr_0 [arrowhead=none]; 310 tr_0 -> tr_limit -> tr_0 [style=dashed]; 311 312 /* The line timer initiates the DMA transfers for the display line. */ 313 314 t_0 -> dma_init; 315 316 /* The completion of the initiating channel enables the line channels. */ 317 318 dma_init -> dma_line; 319 320 /* Each cell transfer in the line channels is initiated by the transfer 321 timer. */ 322 323 tr_0 -> dma_line; 324 325 /* The line channels generate the pixel output. */ 326 327 dma_line -> pixels; 328 329 /* The completion of the line channels initiates the reset channel. */ 330 331 dma_line -> dma_reset; 332 333 /* The reset channel generates black/reset output. */ 334 335 dma_reset -> black; 336 337 /* The black/reset value follows the visible pixels. */ 338 339 pixels -> black [style=dashed]; 340 341 /* The timer feeds the output compare unit, driving hsync. */ 342 343 t_hsync -> oc1; 344 oc1 -> hsync; 345 346 /* The output compare unit initiates the interrupt request for each line, 347 driving vsync. */ 348 349 oc1 -> lineirq; 350 lineirq -> vsync; 351 } 352 }}}