CommonPIC32

Changeset

145:b572f8cd1476
2019-04-15 Paul Boddie raw files shortlog changelog graph Renamed SignalOutput and added a documentation front page.
docs/wiki/CommonPIC32 (file) docs/wiki/SignalOutput docs/wiki/VGA_Signal_Output (file)
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/docs/wiki/CommonPIC32	Mon Apr 15 17:53:50 2019 +0200
     1.3 @@ -0,0 +1,9 @@
     1.4 += CommonPIC32 =
     1.5 +
     1.6 +CommonPIC32 is a distribution of libraries and programs for developing
     1.7 +solutions for the PIC32 microcontroller platform, specifically MIPS-based
     1.8 +products for this platform.
     1.9 +
    1.10 +== Documentation ==
    1.11 +
    1.12 + * [[VGA Signal Output]]
     2.1 --- a/docs/wiki/SignalOutput	Mon Apr 15 16:18:08 2019 +0200
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,347 +0,0 @@
     2.4 -= Signal Output =
     2.5 -
     2.6 -There are two principal mechanisms for generating a VGA signal demonstrated in
     2.7 -this project:
     2.8 -
     2.9 - * Using the CPU to "copy" pixel data to an output port
    2.10 - * Using DMA transfers to "copy" pixel data to an output port
    2.11 -
    2.12 -Within the latter, there are a number of variations in the mechanism employed:
    2.13 -
    2.14 - * Use of general-purpose output pins versus parallel mode outputs
    2.15 - * Use of large transfer cells containing each entire pixel line versus small
    2.16 -   transfer cells containing fragments of each line
    2.17 - * Use of a single transfer-initiating event versus separate line-initiating
    2.18 -   and transfer-initiating events
    2.19 -
    2.20 -== Using the CPU for Transfers ==
    2.21 -
    2.22 -{{{#!graphviz
    2.23 -//format=svg
    2.24 -//transform=notugly
    2.25 -digraph cpu {
    2.26 -  node [shape=box,fontsize="13.0",fontname="Helvetica"];
    2.27 -  rankdir=TD;
    2.28 -
    2.29 -  subgraph {
    2.30 -    rank=same;
    2.31 -
    2.32 -    timer [label="Display line\ntimer",style=filled,fillcolor=gold];
    2.33 -    t_0 [label="0",shape=ellipse];
    2.34 -    t_hsync [label="hsync",shape=ellipse];
    2.35 -    t_limit [label="limit",shape=ellipse];
    2.36 -  }
    2.37 -
    2.38 -  oc1 [label="Output compare",style=filled,fillcolor=gold];
    2.39 -
    2.40 -  subgraph {
    2.41 -    rank=same;
    2.42 -
    2.43 -    lineirq [label="Display line\ninterrupt handler"];
    2.44 -    pixelirq [label="Pixel output\ninterrupt handler"];
    2.45 -  }
    2.46 -
    2.47 -  subgraph {
    2.48 -    rank=same;
    2.49 -
    2.50 -    pixels [label="Pixel output\nBlack/reset output",style=filled,fillcolor=green,shape=parallelogram];
    2.51 -    hsync [label="Horizontal sync",shape=house,style=filled,fillcolor=red];
    2.52 -    vsync [label="Vertical sync",shape=house,style=filled,fillcolor=red];
    2.53 -  }
    2.54 -
    2.55 -  /* The timer starts at 0 and wraps around at limit. */
    2.56 -
    2.57 -  timer -> t_0 [arrowhead=none];
    2.58 -  t_0 -> t_hsync -> t_limit -> t_0 [style=dashed];
    2.59 -
    2.60 -  /* The timer initiates the interrupt request for pixel production. */
    2.61 -
    2.62 -  t_0 -> pixelirq;
    2.63 -
    2.64 -  /* The interrupt handler generates the pixel output. */
    2.65 -
    2.66 -  pixelirq -> pixels;
    2.67 -
    2.68 -  /* The timer feeds the output compare unit, driving hsync. */
    2.69 -
    2.70 -  t_hsync -> oc1;
    2.71 -  oc1 -> hsync;
    2.72 -
    2.73 -  /* The output compare unit initiates the interrupt request for each line,
    2.74 -     driving vsync. */
    2.75 -
    2.76 -  oc1 -> lineirq;
    2.77 -  lineirq -> vsync;
    2.78 -}
    2.79 -}}}
    2.80 -
    2.81 -== Using DMA for Transfers ==
    2.82 -
    2.83 -{{{#!graphviz
    2.84 -//format=svg
    2.85 -//transform=notugly
    2.86 -digraph dma {
    2.87 -  node [shape=box,fontsize="13.0",fontname="Helvetica"];
    2.88 -  rankdir=TD;
    2.89 -
    2.90 -  subgraph {
    2.91 -    rank=same;
    2.92 -
    2.93 -    timer [label="Display line\ntimer",style=filled,fillcolor=gold];
    2.94 -    t_0 [label="0",shape=ellipse];
    2.95 -    t_hsync [label="hsync",shape=ellipse];
    2.96 -    t_limit [label="limit",shape=ellipse];
    2.97 -  }
    2.98 -
    2.99 -  oc1 [label="Output compare",style=filled,fillcolor=gold];
   2.100 -
   2.101 -  subgraph {
   2.102 -    rank=same;
   2.103 -
   2.104 -    dma_line [label="Pixel output\nDMA channel",style=filled,fillcolor=lightblue];
   2.105 -    dma_reset [label="Pixel reset\nDMA channel",style=filled,fillcolor=lightblue];
   2.106 -    lineirq [label="Display line\ninterrupt handler"];
   2.107 -  }
   2.108 -
   2.109 -  subgraph {
   2.110 -    rank=same;
   2.111 -
   2.112 -    pixels [label="Pixel output",style=filled,fillcolor=green,shape=parallelogram];
   2.113 -    black [label="Black/reset output",style=filled,fillcolor=black,fontcolor=white,shape=parallelogram];
   2.114 -    hsync [label="Horizontal sync",shape=house,style=filled,fillcolor=red];
   2.115 -    vsync [label="Vertical sync",shape=house,style=filled,fillcolor=red];
   2.116 -  }
   2.117 -
   2.118 -  /* The timer starts at 0 and wraps around at limit. */
   2.119 -
   2.120 -  timer -> t_0 [arrowhead=none];
   2.121 -  t_0 -> t_hsync -> t_limit -> t_0 [style=dashed];
   2.122 -
   2.123 -  /* The timer initiates the DMA transfer for pixel production. */
   2.124 -
   2.125 -  t_0 -> dma_line;
   2.126 -
   2.127 -  /* The line channel generates the pixel output. */ 
   2.128 -
   2.129 -  dma_line -> pixels;
   2.130 -
   2.131 -  /* The completion of the line channel initiates the reset channel. */
   2.132 -
   2.133 -  dma_line -> dma_reset;
   2.134 -
   2.135 -  /* The reset channel generates black/reset output. */
   2.136 -
   2.137 -  dma_reset -> black;
   2.138 -
   2.139 -  /* The black/reset value follows the visible pixels. */
   2.140 -
   2.141 -  pixels -> black [style=dashed];
   2.142 -
   2.143 -  /* The timer feeds the output compare unit, driving hsync. */
   2.144 -
   2.145 -  t_hsync -> oc1;
   2.146 -  oc1 -> hsync;
   2.147 -
   2.148 -  /* The output compare unit initiates the interrupt request for each line,
   2.149 -     driving vsync. */
   2.150 -
   2.151 -  oc1 -> lineirq;
   2.152 -  lineirq -> vsync;
   2.153 -}
   2.154 -}}}
   2.155 -
   2.156 -== Using DMA and Timed Transfers ==
   2.157 -
   2.158 -{{{#!graphviz
   2.159 -//format=svg
   2.160 -//transform=notugly
   2.161 -digraph dma {
   2.162 -  node [shape=box,fontsize="13.0",fontname="Helvetica"];
   2.163 -  rankdir=TD;
   2.164 -
   2.165 -  subgraph {
   2.166 -    rank=same;
   2.167 -
   2.168 -    timer [label="Display line\ntimer",style=filled,fillcolor=gold];
   2.169 -    t_0 [label="0",shape=ellipse];
   2.170 -    t_hsync [label="hsync",shape=ellipse];
   2.171 -    t_limit [label="limit",shape=ellipse];
   2.172 -  }
   2.173 -
   2.174 -  oc1 [label="Output compare",style=filled,fillcolor=gold];
   2.175 -
   2.176 -  subgraph {
   2.177 -    rank=same;
   2.178 -
   2.179 -    trtimer [label="Transfer timer",style=filled,fillcolor=gold];
   2.180 -    tr_0 [label="0",shape=ellipse];
   2.181 -    tr_limit [label="limit",shape=ellipse];
   2.182 -  }
   2.183 -
   2.184 -  subgraph {
   2.185 -    rank=same;
   2.186 -
   2.187 -    dma_init [label="Initiator\nDMA channel",style=filled,fillcolor=lightblue];
   2.188 -    dma_line [label="Pixel output\nDMA channel",style=filled,fillcolor=lightblue];
   2.189 -    dma_reset [label="Pixel reset\nDMA channel",style=filled,fillcolor=lightblue];
   2.190 -    lineirq [label="Display line\ninterrupt handler"];
   2.191 -  }
   2.192 -
   2.193 -  subgraph {
   2.194 -    rank=same;
   2.195 -
   2.196 -    pixels [label="Pixel output",style=filled,fillcolor=green,shape=parallelogram];
   2.197 -    black [label="Black/reset output",style=filled,fillcolor=black,fontcolor=white,shape=parallelogram];
   2.198 -    hsync [label="Horizontal sync",shape=house,style=filled,fillcolor=red];
   2.199 -    vsync [label="Vertical sync",shape=house,style=filled,fillcolor=red];
   2.200 -  }
   2.201 -
   2.202 -  /* The line timer starts at 0 and wraps around at limit. */
   2.203 -
   2.204 -  timer -> t_0 [arrowhead=none];
   2.205 -  t_0 -> t_hsync -> t_limit -> t_0 [style=dashed];
   2.206 -
   2.207 -  /* The transfer timer starts at 0 and wraps around at limit. */
   2.208 -
   2.209 -  trtimer -> tr_0 [arrowhead=none];
   2.210 -  tr_0 -> tr_limit -> tr_0 [style=dashed];
   2.211 -
   2.212 -  /* The line timer initiates the DMA transfers for the display line. */
   2.213 -
   2.214 -  t_0 -> dma_init;
   2.215 -
   2.216 -  /* The completion of the initiating channel enables the line channel. */
   2.217 -
   2.218 -  dma_init -> dma_line;
   2.219 -
   2.220 -  /* Each cell transfer in the line channel is initiated by the transfer
   2.221 -     timer. */
   2.222 -
   2.223 -  tr_0 -> dma_line;
   2.224 -
   2.225 -  /* The line channel generates the pixel output. */ 
   2.226 -
   2.227 -  dma_line -> pixels;
   2.228 -
   2.229 -  /* The completion of the line channel initiates the reset channel. */
   2.230 -
   2.231 -  dma_line -> dma_reset;
   2.232 -
   2.233 -  /* The reset channel generates black/reset output. */
   2.234 -
   2.235 -  dma_reset -> black;
   2.236 -
   2.237 -  /* The black/reset value follows the visible pixels. */
   2.238 -
   2.239 -  pixels -> black [style=dashed];
   2.240 -
   2.241 -  /* The timer feeds the output compare unit, driving hsync. */
   2.242 -
   2.243 -  t_hsync -> oc1;
   2.244 -  oc1 -> hsync;
   2.245 -
   2.246 -  /* The output compare unit initiates the interrupt request for each line,
   2.247 -     driving vsync. */
   2.248 -
   2.249 -  oc1 -> lineirq;
   2.250 -  lineirq -> vsync;
   2.251 -}
   2.252 -}}}
   2.253 -
   2.254 -== Using DMA and Timed Dual-Channel Transfers ==
   2.255 -
   2.256 -{{{#!graphviz
   2.257 -//format=svg
   2.258 -//transform=notugly
   2.259 -digraph dma {
   2.260 -  node [shape=box,fontsize="13.0",fontname="Helvetica"];
   2.261 -  rankdir=TD;
   2.262 -
   2.263 -  subgraph {
   2.264 -    rank=same;
   2.265 -
   2.266 -    timer [label="Display line\ntimer",style=filled,fillcolor=gold];
   2.267 -    t_0 [label="0",shape=ellipse];
   2.268 -    t_hsync [label="hsync",shape=ellipse];
   2.269 -    t_limit [label="limit",shape=ellipse];
   2.270 -  }
   2.271 -
   2.272 -  oc1 [label="Output compare",style=filled,fillcolor=gold];
   2.273 -
   2.274 -  subgraph {
   2.275 -    rank=same;
   2.276 -
   2.277 -    trtimer [label="Transfer timer",style=filled,fillcolor=gold];
   2.278 -    tr_0 [label="0",shape=ellipse];
   2.279 -    tr_limit [label="limit",shape=ellipse];
   2.280 -  }
   2.281 -
   2.282 -  subgraph {
   2.283 -    rank=same;
   2.284 -
   2.285 -    dma_init [label="Initiator\nDMA channel",style=filled,fillcolor=lightblue];
   2.286 -    dma_line [label="{Pixel output\nDMA channel #1 | Pixel output\nDMA channel #2}",style=filled,fillcolor=lightblue,shape=record];
   2.287 -    dma_reset [label="Pixel reset\nDMA channel",style=filled,fillcolor=lightblue];
   2.288 -    lineirq [label="Display line\ninterrupt handler"];
   2.289 -  }
   2.290 -
   2.291 -  subgraph {
   2.292 -    rank=same;
   2.293 -
   2.294 -    pixels [label="Pixel output",style=filled,fillcolor=green,shape=parallelogram];
   2.295 -    black [label="Black/reset output",style=filled,fillcolor=black,fontcolor=white,shape=parallelogram];
   2.296 -    hsync [label="Horizontal sync",shape=house,style=filled,fillcolor=red];
   2.297 -    vsync [label="Vertical sync",shape=house,style=filled,fillcolor=red];
   2.298 -  }
   2.299 -
   2.300 -  /* The line timer starts at 0 and wraps around at limit. */
   2.301 -
   2.302 -  timer -> t_0 [arrowhead=none];
   2.303 -  t_0 -> t_hsync -> t_limit -> t_0 [style=dashed];
   2.304 -
   2.305 -  /* The transfer timer starts at 0 and wraps around at limit. */
   2.306 -
   2.307 -  trtimer -> tr_0 [arrowhead=none];
   2.308 -  tr_0 -> tr_limit -> tr_0 [style=dashed];
   2.309 -
   2.310 -  /* The line timer initiates the DMA transfers for the display line. */
   2.311 -
   2.312 -  t_0 -> dma_init;
   2.313 -
   2.314 -  /* The completion of the initiating channel enables the line channels. */
   2.315 -
   2.316 -  dma_init -> dma_line;
   2.317 -
   2.318 -  /* Each cell transfer in the line channels is initiated by the transfer
   2.319 -     timer. */
   2.320 -
   2.321 -  tr_0 -> dma_line;
   2.322 -
   2.323 -  /* The line channels generate the pixel output. */ 
   2.324 -
   2.325 -  dma_line -> pixels;
   2.326 -
   2.327 -  /* The completion of the line channels initiates the reset channel. */
   2.328 -
   2.329 -  dma_line -> dma_reset;
   2.330 -
   2.331 -  /* The reset channel generates black/reset output. */
   2.332 -
   2.333 -  dma_reset -> black;
   2.334 -
   2.335 -  /* The black/reset value follows the visible pixels. */
   2.336 -
   2.337 -  pixels -> black [style=dashed];
   2.338 -
   2.339 -  /* The timer feeds the output compare unit, driving hsync. */
   2.340 -
   2.341 -  t_hsync -> oc1;
   2.342 -  oc1 -> hsync;
   2.343 -
   2.344 -  /* The output compare unit initiates the interrupt request for each line,
   2.345 -     driving vsync. */
   2.346 -
   2.347 -  oc1 -> lineirq;
   2.348 -  lineirq -> vsync;
   2.349 -}
   2.350 -}}}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/docs/wiki/VGA_Signal_Output	Mon Apr 15 17:53:50 2019 +0200
     3.3 @@ -0,0 +1,347 @@
     3.4 += VGA Signal Output =
     3.5 +
     3.6 +There are two principal mechanisms for generating a VGA signal demonstrated in
     3.7 +this project:
     3.8 +
     3.9 + * Using the CPU to "copy" pixel data to an output port
    3.10 + * Using DMA transfers to "copy" pixel data to an output port
    3.11 +
    3.12 +Within the latter, there are a number of variations in the mechanism employed:
    3.13 +
    3.14 + * Use of general-purpose output pins versus parallel mode outputs
    3.15 + * Use of large transfer cells containing each entire pixel line versus small
    3.16 +   transfer cells containing fragments of each line
    3.17 + * Use of a single transfer-initiating event versus separate line-initiating
    3.18 +   and transfer-initiating events
    3.19 +
    3.20 +== Using the CPU for Transfers ==
    3.21 +
    3.22 +{{{#!graphviz
    3.23 +//format=svg
    3.24 +//transform=notugly
    3.25 +digraph cpu {
    3.26 +  node [shape=box,fontsize="13.0",fontname="Helvetica"];
    3.27 +  rankdir=TD;
    3.28 +
    3.29 +  subgraph {
    3.30 +    rank=same;
    3.31 +
    3.32 +    timer [label="Display line\ntimer",style=filled,fillcolor=gold];
    3.33 +    t_0 [label="0",shape=ellipse];
    3.34 +    t_hsync [label="hsync",shape=ellipse];
    3.35 +    t_limit [label="limit",shape=ellipse];
    3.36 +  }
    3.37 +
    3.38 +  oc1 [label="Output compare",style=filled,fillcolor=gold];
    3.39 +
    3.40 +  subgraph {
    3.41 +    rank=same;
    3.42 +
    3.43 +    lineirq [label="Display line\ninterrupt handler"];
    3.44 +    pixelirq [label="Pixel output\ninterrupt handler"];
    3.45 +  }
    3.46 +
    3.47 +  subgraph {
    3.48 +    rank=same;
    3.49 +
    3.50 +    pixels [label="Pixel output\nBlack/reset output",style=filled,fillcolor=green,shape=parallelogram];
    3.51 +    hsync [label="Horizontal sync",shape=house,style=filled,fillcolor=red];
    3.52 +    vsync [label="Vertical sync",shape=house,style=filled,fillcolor=red];
    3.53 +  }
    3.54 +
    3.55 +  /* The timer starts at 0 and wraps around at limit. */
    3.56 +
    3.57 +  timer -> t_0 [arrowhead=none];
    3.58 +  t_0 -> t_hsync -> t_limit -> t_0 [style=dashed];
    3.59 +
    3.60 +  /* The timer initiates the interrupt request for pixel production. */
    3.61 +
    3.62 +  t_0 -> pixelirq;
    3.63 +
    3.64 +  /* The interrupt handler generates the pixel output. */
    3.65 +
    3.66 +  pixelirq -> pixels;
    3.67 +
    3.68 +  /* The timer feeds the output compare unit, driving hsync. */
    3.69 +
    3.70 +  t_hsync -> oc1;
    3.71 +  oc1 -> hsync;
    3.72 +
    3.73 +  /* The output compare unit initiates the interrupt request for each line,
    3.74 +     driving vsync. */
    3.75 +
    3.76 +  oc1 -> lineirq;
    3.77 +  lineirq -> vsync;
    3.78 +}
    3.79 +}}}
    3.80 +
    3.81 +== Using DMA for Transfers ==
    3.82 +
    3.83 +{{{#!graphviz
    3.84 +//format=svg
    3.85 +//transform=notugly
    3.86 +digraph dma {
    3.87 +  node [shape=box,fontsize="13.0",fontname="Helvetica"];
    3.88 +  rankdir=TD;
    3.89 +
    3.90 +  subgraph {
    3.91 +    rank=same;
    3.92 +
    3.93 +    timer [label="Display line\ntimer",style=filled,fillcolor=gold];
    3.94 +    t_0 [label="0",shape=ellipse];
    3.95 +    t_hsync [label="hsync",shape=ellipse];
    3.96 +    t_limit [label="limit",shape=ellipse];
    3.97 +  }
    3.98 +
    3.99 +  oc1 [label="Output compare",style=filled,fillcolor=gold];
   3.100 +
   3.101 +  subgraph {
   3.102 +    rank=same;
   3.103 +
   3.104 +    dma_line [label="Pixel output\nDMA channel",style=filled,fillcolor=lightblue];
   3.105 +    dma_reset [label="Pixel reset\nDMA channel",style=filled,fillcolor=lightblue];
   3.106 +    lineirq [label="Display line\ninterrupt handler"];
   3.107 +  }
   3.108 +
   3.109 +  subgraph {
   3.110 +    rank=same;
   3.111 +
   3.112 +    pixels [label="Pixel output",style=filled,fillcolor=green,shape=parallelogram];
   3.113 +    black [label="Black/reset output",style=filled,fillcolor=black,fontcolor=white,shape=parallelogram];
   3.114 +    hsync [label="Horizontal sync",shape=house,style=filled,fillcolor=red];
   3.115 +    vsync [label="Vertical sync",shape=house,style=filled,fillcolor=red];
   3.116 +  }
   3.117 +
   3.118 +  /* The timer starts at 0 and wraps around at limit. */
   3.119 +
   3.120 +  timer -> t_0 [arrowhead=none];
   3.121 +  t_0 -> t_hsync -> t_limit -> t_0 [style=dashed];
   3.122 +
   3.123 +  /* The timer initiates the DMA transfer for pixel production. */
   3.124 +
   3.125 +  t_0 -> dma_line;
   3.126 +
   3.127 +  /* The line channel generates the pixel output. */ 
   3.128 +
   3.129 +  dma_line -> pixels;
   3.130 +
   3.131 +  /* The completion of the line channel initiates the reset channel. */
   3.132 +
   3.133 +  dma_line -> dma_reset;
   3.134 +
   3.135 +  /* The reset channel generates black/reset output. */
   3.136 +
   3.137 +  dma_reset -> black;
   3.138 +
   3.139 +  /* The black/reset value follows the visible pixels. */
   3.140 +
   3.141 +  pixels -> black [style=dashed];
   3.142 +
   3.143 +  /* The timer feeds the output compare unit, driving hsync. */
   3.144 +
   3.145 +  t_hsync -> oc1;
   3.146 +  oc1 -> hsync;
   3.147 +
   3.148 +  /* The output compare unit initiates the interrupt request for each line,
   3.149 +     driving vsync. */
   3.150 +
   3.151 +  oc1 -> lineirq;
   3.152 +  lineirq -> vsync;
   3.153 +}
   3.154 +}}}
   3.155 +
   3.156 +== Using DMA and Timed Transfers ==
   3.157 +
   3.158 +{{{#!graphviz
   3.159 +//format=svg
   3.160 +//transform=notugly
   3.161 +digraph dma {
   3.162 +  node [shape=box,fontsize="13.0",fontname="Helvetica"];
   3.163 +  rankdir=TD;
   3.164 +
   3.165 +  subgraph {
   3.166 +    rank=same;
   3.167 +
   3.168 +    timer [label="Display line\ntimer",style=filled,fillcolor=gold];
   3.169 +    t_0 [label="0",shape=ellipse];
   3.170 +    t_hsync [label="hsync",shape=ellipse];
   3.171 +    t_limit [label="limit",shape=ellipse];
   3.172 +  }
   3.173 +
   3.174 +  oc1 [label="Output compare",style=filled,fillcolor=gold];
   3.175 +
   3.176 +  subgraph {
   3.177 +    rank=same;
   3.178 +
   3.179 +    trtimer [label="Transfer timer",style=filled,fillcolor=gold];
   3.180 +    tr_0 [label="0",shape=ellipse];
   3.181 +    tr_limit [label="limit",shape=ellipse];
   3.182 +  }
   3.183 +
   3.184 +  subgraph {
   3.185 +    rank=same;
   3.186 +
   3.187 +    dma_init [label="Initiator\nDMA channel",style=filled,fillcolor=lightblue];
   3.188 +    dma_line [label="Pixel output\nDMA channel",style=filled,fillcolor=lightblue];
   3.189 +    dma_reset [label="Pixel reset\nDMA channel",style=filled,fillcolor=lightblue];
   3.190 +    lineirq [label="Display line\ninterrupt handler"];
   3.191 +  }
   3.192 +
   3.193 +  subgraph {
   3.194 +    rank=same;
   3.195 +
   3.196 +    pixels [label="Pixel output",style=filled,fillcolor=green,shape=parallelogram];
   3.197 +    black [label="Black/reset output",style=filled,fillcolor=black,fontcolor=white,shape=parallelogram];
   3.198 +    hsync [label="Horizontal sync",shape=house,style=filled,fillcolor=red];
   3.199 +    vsync [label="Vertical sync",shape=house,style=filled,fillcolor=red];
   3.200 +  }
   3.201 +
   3.202 +  /* The line timer starts at 0 and wraps around at limit. */
   3.203 +
   3.204 +  timer -> t_0 [arrowhead=none];
   3.205 +  t_0 -> t_hsync -> t_limit -> t_0 [style=dashed];
   3.206 +
   3.207 +  /* The transfer timer starts at 0 and wraps around at limit. */
   3.208 +
   3.209 +  trtimer -> tr_0 [arrowhead=none];
   3.210 +  tr_0 -> tr_limit -> tr_0 [style=dashed];
   3.211 +
   3.212 +  /* The line timer initiates the DMA transfers for the display line. */
   3.213 +
   3.214 +  t_0 -> dma_init;
   3.215 +
   3.216 +  /* The completion of the initiating channel enables the line channel. */
   3.217 +
   3.218 +  dma_init -> dma_line;
   3.219 +
   3.220 +  /* Each cell transfer in the line channel is initiated by the transfer
   3.221 +     timer. */
   3.222 +
   3.223 +  tr_0 -> dma_line;
   3.224 +
   3.225 +  /* The line channel generates the pixel output. */ 
   3.226 +
   3.227 +  dma_line -> pixels;
   3.228 +
   3.229 +  /* The completion of the line channel initiates the reset channel. */
   3.230 +
   3.231 +  dma_line -> dma_reset;
   3.232 +
   3.233 +  /* The reset channel generates black/reset output. */
   3.234 +
   3.235 +  dma_reset -> black;
   3.236 +
   3.237 +  /* The black/reset value follows the visible pixels. */
   3.238 +
   3.239 +  pixels -> black [style=dashed];
   3.240 +
   3.241 +  /* The timer feeds the output compare unit, driving hsync. */
   3.242 +
   3.243 +  t_hsync -> oc1;
   3.244 +  oc1 -> hsync;
   3.245 +
   3.246 +  /* The output compare unit initiates the interrupt request for each line,
   3.247 +     driving vsync. */
   3.248 +
   3.249 +  oc1 -> lineirq;
   3.250 +  lineirq -> vsync;
   3.251 +}
   3.252 +}}}
   3.253 +
   3.254 +== Using DMA and Timed Dual-Channel Transfers ==
   3.255 +
   3.256 +{{{#!graphviz
   3.257 +//format=svg
   3.258 +//transform=notugly
   3.259 +digraph dma {
   3.260 +  node [shape=box,fontsize="13.0",fontname="Helvetica"];
   3.261 +  rankdir=TD;
   3.262 +
   3.263 +  subgraph {
   3.264 +    rank=same;
   3.265 +
   3.266 +    timer [label="Display line\ntimer",style=filled,fillcolor=gold];
   3.267 +    t_0 [label="0",shape=ellipse];
   3.268 +    t_hsync [label="hsync",shape=ellipse];
   3.269 +    t_limit [label="limit",shape=ellipse];
   3.270 +  }
   3.271 +
   3.272 +  oc1 [label="Output compare",style=filled,fillcolor=gold];
   3.273 +
   3.274 +  subgraph {
   3.275 +    rank=same;
   3.276 +
   3.277 +    trtimer [label="Transfer timer",style=filled,fillcolor=gold];
   3.278 +    tr_0 [label="0",shape=ellipse];
   3.279 +    tr_limit [label="limit",shape=ellipse];
   3.280 +  }
   3.281 +
   3.282 +  subgraph {
   3.283 +    rank=same;
   3.284 +
   3.285 +    dma_init [label="Initiator\nDMA channel",style=filled,fillcolor=lightblue];
   3.286 +    dma_line [label="{Pixel output\nDMA channel #1 | Pixel output\nDMA channel #2}",style=filled,fillcolor=lightblue,shape=record];
   3.287 +    dma_reset [label="Pixel reset\nDMA channel",style=filled,fillcolor=lightblue];
   3.288 +    lineirq [label="Display line\ninterrupt handler"];
   3.289 +  }
   3.290 +
   3.291 +  subgraph {
   3.292 +    rank=same;
   3.293 +
   3.294 +    pixels [label="Pixel output",style=filled,fillcolor=green,shape=parallelogram];
   3.295 +    black [label="Black/reset output",style=filled,fillcolor=black,fontcolor=white,shape=parallelogram];
   3.296 +    hsync [label="Horizontal sync",shape=house,style=filled,fillcolor=red];
   3.297 +    vsync [label="Vertical sync",shape=house,style=filled,fillcolor=red];
   3.298 +  }
   3.299 +
   3.300 +  /* The line timer starts at 0 and wraps around at limit. */
   3.301 +
   3.302 +  timer -> t_0 [arrowhead=none];
   3.303 +  t_0 -> t_hsync -> t_limit -> t_0 [style=dashed];
   3.304 +
   3.305 +  /* The transfer timer starts at 0 and wraps around at limit. */
   3.306 +
   3.307 +  trtimer -> tr_0 [arrowhead=none];
   3.308 +  tr_0 -> tr_limit -> tr_0 [style=dashed];
   3.309 +
   3.310 +  /* The line timer initiates the DMA transfers for the display line. */
   3.311 +
   3.312 +  t_0 -> dma_init;
   3.313 +
   3.314 +  /* The completion of the initiating channel enables the line channels. */
   3.315 +
   3.316 +  dma_init -> dma_line;
   3.317 +
   3.318 +  /* Each cell transfer in the line channels is initiated by the transfer
   3.319 +     timer. */
   3.320 +
   3.321 +  tr_0 -> dma_line;
   3.322 +
   3.323 +  /* The line channels generate the pixel output. */ 
   3.324 +
   3.325 +  dma_line -> pixels;
   3.326 +
   3.327 +  /* The completion of the line channels initiates the reset channel. */
   3.328 +
   3.329 +  dma_line -> dma_reset;
   3.330 +
   3.331 +  /* The reset channel generates black/reset output. */
   3.332 +
   3.333 +  dma_reset -> black;
   3.334 +
   3.335 +  /* The black/reset value follows the visible pixels. */
   3.336 +
   3.337 +  pixels -> black [style=dashed];
   3.338 +
   3.339 +  /* The timer feeds the output compare unit, driving hsync. */
   3.340 +
   3.341 +  t_hsync -> oc1;
   3.342 +  oc1 -> hsync;
   3.343 +
   3.344 +  /* The output compare unit initiates the interrupt request for each line,
   3.345 +     driving vsync. */
   3.346 +
   3.347 +  oc1 -> lineirq;
   3.348 +  lineirq -> vsync;
   3.349 +}
   3.350 +}}}