tag:blogger.com,1999:blog-53528407251828099962024-03-13T06:16:45.676-07:00So many ideas, so little time...Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comBlogger15125tag:blogger.com,1999:blog-5352840725182809996.post-824670885253199272015-02-01T07:17:00.000-08:002015-02-01T07:17:02.855-08:00A New Game Console Project - Part 4
<span style="font-family: Arial,Helvetica,sans-serif;"><i>...continued</i></span><br />
<h3>
<span style="font-family: Arial,Helvetica,sans-serif;">Take 5</span><span style="font-family: Arial,Helvetica,sans-serif;"> - The STM32F407</span></h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-lEj1wQ9VxNk/VLvMaAeNbJI/AAAAAAAAAEU/Yzgig5VCsOU/s1600/STM32F4-DISCOVERY_Board.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-lEj1wQ9VxNk/VLvMaAeNbJI/AAAAAAAAAEU/Yzgig5VCsOU/s1600/STM32F4-DISCOVERY_Board.png" height="261" width="320" /></a></div>
<span style="font-family: Arial,Helvetica,sans-serif;"> The <a href="http://www.st.com/web/en/resource/technical/document/datasheet/DM00037051.pdf">STM32F407</a> is a micro-controller containing (notably):</span><br />
<ul>
<li><span style="font-family: Arial,Helvetica,sans-serif;">An ARM 32-bit Cortex™-M4 CPU with FPU rated at 168MHz</span></li>
<li><span style="font-family: Arial,Helvetica,sans-serif;">192Kbytes of SRAM which includes 64-Kbyte of CCM (core coupled memory) data RAM</span></li>
<li><span style="font-family: Arial,Helvetica,sans-serif;">A static memory controller supporting Compact Flash, SRAM, PSRAM, NOR and NAND memories </span></li>
<span style="font-family: Arial,Helvetica,sans-serif;">
</span><span style="font-family: Arial,Helvetica,sans-serif;">
</span>
<li><span style="font-family: Arial,Helvetica,sans-serif;">General-purpose DMA: 16-stream DMA controller with FIFOs and burst support</span></li>
<li><span style="font-family: Arial,Helvetica,sans-serif;">Loads of hardware timers</span></li>
</ul>
<span style="font-family: Arial,Helvetica,sans-serif;"></span><br />
<span style="font-family: Arial,Helvetica,sans-serif;">I bought a Discovery board which contained this chip. This board comes with nice 0.1" headers that I used to connect to my PAL encoder board (see previous posts) with short prototyping jumper wires.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">Firstly I set-up a development environment. I use Linux and MacOS X at home and luckily this was really quite easy. I'm pretty productive on Eclipse so I set up fresh Eclipse Luna package and added:</span><br />
<ul>
<li><span style="font-family: Arial,Helvetica,sans-serif;">C/C++ Development Tooling (CDT)</span></li>
<li><span style="font-family: Arial,Helvetica,sans-serif;"><a href="http://gnuarmeclipse.livius.net/blog/">GNU ARM Eclipse</a> Tooling</span></li>
</ul>
<span style="font-family: Arial,Helvetica,sans-serif;">Here is the software I have installed in Eclipse:</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-7l5Wjo-wLBQ/VM4wkzPJfxI/AAAAAAAAAG8/tk1BS-7RIU4/s1600/EclipseSoftware.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-7l5Wjo-wLBQ/VM4wkzPJfxI/AAAAAAAAAG8/tk1BS-7RIU4/s1600/EclipseSoftware.png" height="320" width="308" /></a></div>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">I'm running Ubuntu 14.04 so I also had to issue install cross-complier and debugger:</span><br />
<blockquote class="tr_bq">
<span style="font-family: Arial,Helvetica,sans-serif;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">sudo apt-get install gcc-arm-none-eabi gdb-arm-none-eabi</span></span></span></blockquote>
<span style="font-family: Arial,Helvetica,sans-serif;">The Discovery board has a neat ST-Link v2 interface on it which when sent certain commands over the USB connection will drive the SWD interface in the </span><span style="font-family: Arial,Helvetica,sans-serif;"><span style="font-family: Arial,Helvetica,sans-serif;">STM32F4</span> chip. This allows code on the STM32F4 chip to be debugged and also allows flashing of the chip. I used the following tool to talk ST-Link: <a href="https://github.com/texane/stlink">https://github.com/texane/stlink</a></span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">STLink provides a GDB-server interface which means that GDB (or Eclipse) can be used to debug code live on the device. Neato. So basically:</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<blockquote class="tr_bq">
<span style="font-family: Arial,Helvetica,sans-serif;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">GDB/Eclipse -> GDB server (STLink) -> STLink v2 facade chip -> SWD target (STM32F4)</span></span></span></blockquote>
<span style="font-family: Arial,Helvetica,sans-serif;">It sounds like a lot of moving parts but it really isn't. This tool chain has work 100% of the time for me without a single issue. I have debugged on-chip at least 30 times.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">It should be noted that Eclipse Luna has some bugs that stop the debugger from working. There is a bug report I can't recall but in a nutshell, the Step In/Over/Out controls remain disabled. It is a UI regression that doesn't exist in the previous Kepler release. Until fixed I suggest you use Eclipse Kepler.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<h3>
<span style="font-family: Arial,Helvetica,sans-serif;">The Architecture</span></h3>
<span style="font-family: Arial,Helvetica,sans-serif;">Ok here comes the fun stuff: software. I chose to generate a PAL compatible sync signal right out of my STM32 chip. Other have generated a VGA (two signal sync) and fed that to the AD724 chip successfully. I wanted to stick with a PAL (single signal sync - say that fast) as illustrated in the diagram below:</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-sfjHpQ0QtOs/VL0bEaSfapI/AAAAAAAAAFU/tjiDKcvQXlw/s1600/pal_tv_diagram_non_interlace.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-sfjHpQ0QtOs/VL0bEaSfapI/AAAAAAAAAFU/tjiDKcvQXlw/s1600/pal_tv_diagram_non_interlace.jpg" /></a></div>
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">In my design I decided to interrupt on every transition above. So in the top-left corner above I'd interrupt at the end of the long sync at the transition to the small yellow region. At that point i'd set the next wake-up and go to sleep. This is illustrated below:</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-vDdyUplVNlc/VM457rXfEbI/AAAAAAAAAHM/aAepYKsXEM8/s1600/ScanlineSync.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-vDdyUplVNlc/VM457rXfEbI/AAAAAAAAAHM/aAepYKsXEM8/s1600/ScanlineSync.png" /></a></div>
<span style="font-family: Arial,Helvetica,sans-serif;"></span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">Timer 2 is used to generate this pattern. It runs at half the CPU clock frequency so in my case that was 84MHz. I'm using the Output Compare Channel 1 feature to generate the CPU interrupt every time a there is an Output Compare match. A lot of micro-controllers have Output Compare features and generally they are pretty simple. Usually you load a target counter value in a register and when the timer (or counter) reaches it, it takes some fixed of configurable action. The STM32F4 is no exception. I have it generate a CPU interrupt on match. When I wake up in the interrupt handler I just load the next counter value (plus the last value since I'm accumulating) and go back the sleep. If you are looking through the sources (when I get around to making them available) you'll see this code:</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"></span><br />
<blockquote class="tr_bq">
<span style="font-family: Arial,Helvetica,sans-serif;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">HAL_TIM_OC_Init(&frameTimer);<br />HAL_TIM_OC_ConfigChannel(&frameTimer, &frameOCConfigC1, TIM_CHANNEL_1);<br />HAL_TIM_OC_Start_IT(&frameTimer, TIM_CHANNEL_1);</span></span></span></blockquote>
<span style="font-family: Arial,Helvetica,sans-serif;"></span><br />
<span style="font-family: Arial,Helvetica,sans-serif;">These functions are found in the STM32 Cube SDK. STM32 Cube is a relatively new SDK from STM and therefore there isn't much example code around. You'll find most of the code out there either targets the <a href="http://www.st.com/st-web-ui/static/active/en/resource/technical/document/user_manual/DM00023896.pdf">Standard Peripheral Library (SPL)</a> or registers directly. As far as I can tell the STM Cube SDK is the replacement for the SPL. Writing to registers directly was out of the question for me since I was going from Zero to Working in 4 weeks.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">The vital parts of STM Cube are automatically dropped into your Eclipse project using the the wonderful GNU ARM Eclipse tooling described above. This really makes it easy to get going and yet you can still dig through the included source to find out what is going on under the hood. I had to do that a lot to get this to work. Unfortunelty the STM Cube SDK suffers from a lack of documentation and a lack of examples. I'm not saying that they don't exist, I just can't find them.</span><br />
<br />
<span style="font-family: Arial,Helvetica,sans-serif;"><b><i>Generating the Sync pulse</i> </b></span><br />
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">So, how do I generate the Sync Pulse? The hardware does this for me with cycle-precision!</span><br />
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">As well as generating an interrupt on OC match, I have configured this OC Channel to toggle it's associated GPIO pin on match. In this case the pin is PA0 which is buried in the manual. Firstly, I needed to switch GPIO Port A [0] to it's alternate function as follows:</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<blockquote class="tr_bq">
<span style="font-family: Arial,Helvetica,sans-serif;"><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">GPIO_InitTypeDef GPIOA_InitStructure;<br />GPIOA_InitStructure.Pin = GPIO_PIN_0;<br />GPIOA_InitStructure.Mode = G<b>PIO_MODE_AF_PP</b>;<br />GPIOA_InitStructure.Speed = GPIO_SPEED_FAST;<br />GPIOA_InitStructure.Pull = GPIO_NOPULL;<br />GPIOA_InitStructure.Alternate = <b>GPIO_AF1_TIM2</b>;<br />HAL_GPIO_Init(GPIOA, &GPIOA_InitStructure);</span></span></span></blockquote>
<span style="font-family: Arial,Helvetica,sans-serif;"></span><br />
<span style="font-family: Arial,Helvetica,sans-serif;">This put the pin under control of the timer. So whenever there is an OC match I get a toggle on this pin for free.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<br />
<span style="font-family: Arial,Helvetica,sans-serif;"><b><i>Using hardware to control hardware</i> </b></span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">Using Timer 2 in the way described above great because the hardware is generating the time-critical events for me. I took this a step further for the pixel output stream. The diagram below shows the overall architecture of the system:</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-yjxuUe1jJsc/VM5BrhEF6qI/AAAAAAAAAHc/Le2MST_trCo/s1600/Engine.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-yjxuUe1jJsc/VM5BrhEF6qI/AAAAAAAAAHc/Le2MST_trCo/s1600/Engine.png" /></a></div>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">I'm using another Timer (Timer 1) to drive the DMA peripheral. Timer 1 is set to roll-over at 8MHz and is configured to generate a DMA Update event at that time. When the DMA peripheral received this update it transfers another byte it's configured source to destination. Timer 1 is set as a slave of Timer 2. I'm using another Output Compare channel (OC 2) to gate the Timer 1. When there is a match on OC 2, Timer 1 is allowed to tick. Latter on I force it off once I know the DMA transfer is complete so that next time it is ready to go again.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">This kind of thing really appeals to my inner engineer. It is a great example of applying a set of constrained components to a problem and coming up with a solution within those constraints. In this case, the Timer and DMA peripherals are my building blocks and an have configured them to solves the problem with very little code required.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">This gives me a jitter free pixel stream.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">What next? Let's write a game!</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: Arial,Helvetica,sans-serif;"> </span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comtag:blogger.com,1999:blog-5352840725182809996.post-28400509238952112282015-01-20T07:12:00.002-08:002015-01-20T07:12:38.304-08:00A New Game Console Project - Part 3
<span style="font-family: Arial,Helvetica,sans-serif;"></span><span style="font-family: Arial,Helvetica,sans-serif;"><i>...continued</i></span><br />
<h3>
<span style="font-family: Arial,Helvetica,sans-serif;">Take 4</span><span style="font-family: Arial,Helvetica,sans-serif;">.2 - PIC32 and PAL-based Approach (DMA)</span></h3>
<span style="font-family: Arial,Helvetica,sans-serif;">Ok, so at this point I had a PIC32 microcontroller pushing pixels out to my TV at 8MHz via an Analog Devices AD724. I had decided at this point that manually pushing out pixels in software was not going to work for a real game. There was already jitter in each line of the display and attempting to weave in a graphics kernel amongst the port I/O was going to further increase jitter. So I decided it was time to switch to DMA.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">The DMA peripheral on the PIC32 is quite flexible. You can set up a timer and have it set the cadence of the DMA stream. The DMA engine will copy the data without further intervention leaving the CPU free to run game logic etc. The DMA can also run without a timer and as far as I can tell, this is only suitable for internal SRAM to SRAM transfers. </span><span style="font-family: Arial,Helvetica,sans-serif;"><br /></span><br />
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">What I discovered was that when the DMA engine is driven by a timer the maximum rate it can manage is 3.7MHz. I still have no idea why this limit exists and I'd still love to be proved wrong. However, there is other independent evidence of this. This <a href="http://hackaday.io/post/2279">post</a> on HackADay.com shows this limitation. You need to scroll all the way down to the DMA Performance section. </span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">For some reason I don't have the source for the timer driven version but it is nearly identical to the Microchip PIC32 example <a href="http://people.ece.cornell.edu/land/courses/ece4760/PIC32/DMA_performance/led_txfer.c">here</a>. The important parts are below:</span><br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">DmaChnOpen(dmaChn, <span style="color: #0000dd; font-weight: bold;">0</span>, DMA_OPEN_AUTO);
DmaChnSetTxfer(dmaChn, pixelData, (<span style="color: #333399; font-weight: bold;">void</span><span style="color: #333333;">*</span>)<span style="color: #333333;">&</span>amp;LATA, <span style="color: #0000dd; font-weight: bold;">64</span>, <span style="color: #0000dd; font-weight: bold;">1</span>, <span style="color: #0000dd; font-weight: bold;">1</span>));
DmaChnSetEventControl(dmaChn, DMA_EV_START_IRQ(_TIMER_3_IRQ));
DmaChnEnable(dmaChn);
OpenTimer23(T2_ON <span style="color: #333333;">|</span> T2_SOURCE_INT <span style="color: #333333;">|</span> T2_PS_1_1, <span style="color: #0000dd; font-weight: bold;">10</span>);
<span style="color: #008800; font-weight: bold;">while</span>(<span style="color: #0000dd; font-weight: bold;">1</span>) {}
</pre>
</div>
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">This code sets up the DMA engine to transfer from pixelData to PORTA every time there is a timer rollover event on timer 3. Timer 2 and 3 are combined here to make a 32bit timer - which is unnecessary in this case. The OpenTimer23() call requests a rollover event after 10 cycles which at 80MHz is an 8MHz pixel clock. My pixelData array was 0x00, 0xFF, 0x00, 0xFF in a repeating pattern. My scope showed a 3.7MHz square wave. It should have been 8MHz. I have never understood where the restriction is.</span><br />
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">I had another idea. The PMP peripheral was used on the Microchip LCC <a href="http://ww1.microchip.com/downloads/en/AppNotes/01387A.pdf">example.</a> Perhaps is was required in order to exceed a 3.7MHz pixel clock. The LCC example is much higher than 3.7MHz. So I tried that. My understanding was that the PMP peripheral would request a DMA cell transfer as required - effectively pacing the DMA transfer. My cell size was set to one byte. My scope indicated I had achieved 6.25MHz. So the PMP peripheral was faster. I still don't know why. I suspect it has an internal buffer that hides some latency. I'm not sure. </span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-2Esx6CvhOgY/VL5sunfqUJI/AAAAAAAAAGM/mGyyCkNAnZo/s1600/MysilRAM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-2Esx6CvhOgY/VL5sunfqUJI/AAAAAAAAAGM/mGyyCkNAnZo/s1600/MysilRAM.png" height="292" width="400" /></a></div>
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">I tried setting the cell size to 2 and I got the following: </span><span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-PodAcYUyWMY/VL5svdWX9mI/AAAAAAAAAGQ/lGjZRw4Vr5o/s1600/MysilRAM2Cell.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-PodAcYUyWMY/VL5svdWX9mI/AAAAAAAAAGQ/lGjZRw4Vr5o/s1600/MysilRAM2Cell.png" height="292" width="400" /></a></div>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">It appeared that I was each byte was output at 19.2MHz but there was a latency which made the overall rate about 10MHz. I couldn't use this on a TV. Every second pixel would be twice as wide!</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">I posted my issue on the Microchip forum but I wasn't able to solve it. Some very kind folks tried to help me on that forum. I think there are some very smart people lurking on that forum.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">Sigh.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">At this point I was ready to give up on the PIC32. I really liked the whole stack but I wasn't getting anywhere. Towards the end of 2014 I ordered an STM32F4 Discovery board. I was really dreading this. It takes a while to get up to speed on a new microcontroller and tools. I set myself a goal to grok the STM32 and get DMA working in under 4 weeks. It arrived on the 17th December 2014.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">I'll cover the "fun" encountered with tooling and STM32 Standard Peripheral Library versus STM32 Cube in my next post.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comtag:blogger.com,1999:blog-5352840725182809996.post-88268911261859427802015-01-19T07:43:00.001-08:002015-01-20T05:46:54.938-08:00A New Game Console Project - Part 2<span style="font-family: Arial,Helvetica,sans-serif;"><i>...continued</i></span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<br />
<h3>
<span style="font-family: Arial,Helvetica,sans-serif;">Take 4</span><span style="font-family: Arial,Helvetica,sans-serif;">.1 - The PIC32 and PAL-based Approach (manual pixel push)</span></h3>
<span style="font-family: Arial,Helvetica,sans-serif;">As I said in my previous post</span><span style="font-family: Arial,Helvetica,sans-serif;">, after
reading about the PIC32-based Maximite and always having an interest in
MIPS since learning about it at university I bought a PIC32 dev board
called a UBW32. The UBW32 is the red board below. The other board is my AD724 TV encoder board.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-fHJiT7EweNI/VLvawXmy6jI/AAAAAAAAAFE/K9XtBsXFTMI/s1600/PIC32.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-fHJiT7EweNI/VLvawXmy6jI/AAAAAAAAAFE/K9XtBsXFTMI/s1600/PIC32.jpg" height="256" width="320" /></a></div>
<div style="text-align: center;">
<span style="font-family: Arial,Helvetica,sans-serif;"> A UBW32 (PIC32) + AD724 TV Encoder</span></div>
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">The processor on the UBW32 is a PIC32MX795 processor which runs at 80MHz has 512K Flash and 128K RAM. It can execute from RAM and has an instruction and data cache that hides flash read latencies. It has a DMA peripheral built in that looked perfect for my project as I could stream pixels out of it without executing code other than DMA setup and the sync signal. That would leave more time for game logic. The Parallel Master Port peripheral also looked perfect for supporting an external frame buffer down the track as it supports programmable wait states for connecting all kinds of memory. The tool chain is GCC-based as well which suits the way I like to work and fits in with the other tools I like to use well.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">I spent months with this board. I drew inspiration from a Microchip Application Note called LCC graphics or Low Cost Controller-less graphics. After reading that I thought this chip had the DMA capabilities I needed for my application. I'm not saying it doesn't - but I certainly couldn't work it out. More on that later. I still think the PIC32 is an excellent micro-controller and perhaps it could be made to work for this application, I just don't know how.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">Anyway, the first experiment I tried was to see if I could get two black and white boxes (one left, one right) to appear on my TV. I started researching how to generate a black and white PAL signal in software. I came across this <a href="http://martin.hinner.info/vga/pal.html">page</a> from Martin Hinner. This pretty much explains how to do it. The following image from that page has guided my though much of this project:</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-sfjHpQ0QtOs/VL0bEaSfapI/AAAAAAAAAFQ/5HlQDVtajIo/s1600/pal_tv_diagram_non_interlace.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-sfjHpQ0QtOs/VL0bEaSfapI/AAAAAAAAAFQ/5HlQDVtajIo/s1600/pal_tv_diagram_non_interlace.jpg" height="276" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span></div>
<span style="font-family: Arial,Helvetica,sans-serif;">This image explains the sequence of sync pulses required to generate a non-interlaced 50Hz (well 50.08Hz) PAL signal. Since my microcontroller ran at 80MHz, each of these durations can be converted to an exact number of CPU cycles.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">For example, the short sync is 2us which is 160 cycles at 80MHz because 1/80 = 0.0125us and 2/0.0125 = 160 cycles.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">You may be thinking at this point that I'm crazy and I can't count on the CPU executing one instruction per cycle. You'd be right but and I had foreseen this. That is why I wanted to use DMA instead. More on that later. This CPU has a very small cache, a pipeline in the CPU and shared buses. All of these things contribute to an execution rate of less than 80 million instructions/second. But that didn't bother me because this was just a test.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">My "design" used a timer interrupt and a simple state machine to take me through the sync pulses and visible lines. On the PIC32 there are a few timers and I picked a 32bit timer and set it to run at 80Mhz synchronous with the CPU clock. This timer keeps counting forever and I just set the next wake-up time base don how long the sleep is. I have included some of the code below.</span><br />
<br />
<pre style="background-image: URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: 500px; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> #define BLACK() mPORTEClearBits(BIT_7|BIT_6|BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0);
#define SYNC_ACTIVE() mPORTCClearBits(BIT_1);NOP3();
#define SYNC_INACTIVE() mPORTCSetBits(BIT_1);NOP3();
#define SYNC_TOGGLE() mPORTCToggleBits(BIT_1);NOP3();
#define FB_WIDTH 416
#define FB_HEIGHT 234
extern void renderLine(uint8_t *data, uint8_t *palette);
// current_next_sync
#define VISIBLE 0
#define SHORT_LONG_SYNC 1
#define SHORT_SHORT_SYNC 2
#define LONG_LONG_SYNC 3
#define LONG_SHORT_SYNC 4
#define SHORT_VISIBLE_SYNC 5
volatile uint32_t syncSequence[17] = {
SHORT_SHORT_SYNC, SHORT_SHORT_SYNC,
SHORT_SHORT_SYNC, SHORT_SHORT_SYNC,
SHORT_SHORT_SYNC, SHORT_LONG_SYNC,
LONG_LONG_SYNC, LONG_LONG_SYNC,
LONG_LONG_SYNC, LONG_LONG_SYNC,
LONG_SHORT_SYNC, SHORT_SHORT_SYNC,
SHORT_SHORT_SYNC, SHORT_SHORT_SYNC,
SHORT_SHORT_SYNC, SHORT_VISIBLE_SYNC,
VISIBLE
};
volatile uint32_t *currentNextSyncType;
volatile uint32_t frameCounter = 0;
volatile uint32_t line = 304;
void __ISR(_TIMER_23_VECTOR, IPL7SRS) timerInt(void) {
// This first bit wants to activate at exactly the same time so we use computed gotos - a GCC feature
const static void *dispatchTable[] = {
&& visible, && syncShortLong, && syncShortShort, && syncLongLong, && syncLongShort, && syncShortVisible
};
// We have woken up
register uint32_t actualTime = ReadTimer45();
register uint32_t cnst = *currentNextSyncType;
register uint32_t nextSleep;
goto *dispatchTable[cnst];
do {
visible:
{
SYNC_INACTIVE(); //(sim 25892, 31012, 36132)
#define START 259
#define STOP ((START-FB_HEIGHT)+1)
if (line > START || line < STOP) {
// blank lines off screen
delay10XCycles(478);
NOP2();
} else {
// delay for back porch 8uS
delay10XCycles(59);
NOP8();
renderLine(address, palette);
address += FB_WIDTH / 2;
BLACK();
// Front porch
delay10XCycles(9);
NOP4();
}
SYNC_ACTIVE();
line--;
nextSleep = 320 + 4800;
if (line == 0) {
// delay for the 2us of the short sync after last visible line
delay10XCycles(13);
NOP8();
// toggle sync
SYNC_INACTIVE();
// set next sync type = [0]
currentNextSyncType = &syncSequence[0];
// account for the delay above and the next sleep
nextSleep = 2400 + 160;
line = 304;
}
// go back to sleep
break;
}
syncShortLong:
{
SYNC_ACTIVE();
// Logging was here
address = frameBuffer;
// set next sync type
currentNextSyncType++;
// We expect the global clock will be at this value next interrupt
nextSleep = 2400;
// go back to sleep
break;
}
syncShortShort:
{
SYNC_ACTIVE();
// delay for the 2us
delay10XCycles(15);
NOP3();
// toggle sync
SYNC_INACTIVE();
// set next sync type
currentNextSyncType++;
// account for the delay above and the next sleep
nextSleep = 2400 + 160;
// go back to sleep
break;
}
syncLongLong:
{
SYNC_INACTIVE();
// delay for the 2us
delay10XCycles(15);
NOP2();
// toggle sync
SYNC_ACTIVE();
// set next sync type
currentNextSyncType++;
// account for the delay above and the next sleep
nextSleep = 2400 + 160;
// go back to sleep
break;
}
syncLongShort:
{
SYNC_INACTIVE();
// extra bit for long to short transitions
// delay for the 2us
delay10XCycles(15);
NOP2();
// toggle sync
SYNC_ACTIVE();
// delay for the 2us
delay10XCycles(15);
NOP2();
// toggle sync
SYNC_INACTIVE();
// set next sync type
currentNextSyncType++;
// account for the delay above and the next sleep
nextSleep = 2400 + 320;
// go back to sleep
break;
}
syncShortVisible:
{
SYNC_ACTIVE();
currentNextSyncType++;
// account for the delay above
nextSleep = 320;
// go back to sleep
break;
}
} while (0);
PR2 = nextSleep-1;
mT23ClearIntFlag();
}
</code></pre>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">This implementation has a couple of interesting features. Firstly, because it uses a timer interrupt to wake up a couple of times per line, the timing is pretty sharp - despite using NOPs to pad events out. Next, I'm using a computed GOTO. This allows my to wake up and jump to the correct state handler in the same number of cycles everytime. A SELECT of IF-ELSE block doesn't have this property as the compiler tests each case. Finally, the actual rendering function renderLine() is in a separate assembler file. I hand rolled the assembly for this to achieve the 8MHz pixel clock. This all worked after about a billion iterations of tweaking the timing and produced the desired display on my TV. There was noise all over picture though and I bit the bullet and made a PCB with a AD724 on it. I won't cover the circuit becuase I stuck largely to the reference design in the datasheet.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">The colour space is IIBBGGRR. I'll cover that in another post. But for now it is 2 bits each for Red, Green, Blue and Intensity.</span><br />
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">Here are some example images that I was able to generate with this configuration:</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-5rnV-_JVMYg/VL0iYmULFiI/AAAAAAAAAFg/3aDFEWNSYio/s1600/PIC32Boxes.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-5rnV-_JVMYg/VL0iYmULFiI/AAAAAAAAAFg/3aDFEWNSYio/s1600/PIC32Boxes.jpg" height="238" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-B8b_KuEV4VU/VL0ib2vsZnI/AAAAAAAAAFs/KLtYjU-24s0/s1600/PIC32Grid.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-B8b_KuEV4VU/VL0ib2vsZnI/AAAAAAAAAFs/KLtYjU-24s0/s1600/PIC32Grid.jpg" height="221" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-sGyda-tY1D4/VL0ibcZFT_I/AAAAAAAAAFo/Mc6kHUYGjHE/s1600/PIC32Island.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-sGyda-tY1D4/VL0ibcZFT_I/AAAAAAAAAFo/Mc6kHUYGjHE/s1600/PIC32Island.jpg" height="222" width="400" /></a></div>
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">Can you spot the issue in the first couple of lines of the checkerboard image above? They are skewed to the right. I assume this to be due to the cache in the CPU "warming up" to the drawing code. I'm not 100% sure about that though.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"></span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"></span><br />
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">The third image was a true colour image I converted to 16 colours. This let me actually have a 416x234 framebuffer because that consumed only 48,672 bytes of RAM. I wrote the renderLine() function to unpack the pixels and lookup a palette to get the right colour. Notice the colour of the sand? Hmm - not quite right. </span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br />So you if you got this far you might be wondering how this failed. Actually it didn't really fail. I just couldn't bring myself to weave a graphics engine amongst the CPU instructions in renderLine(). If you look at the Uzebox source they cleverly weave sprite reading instructions amongst the gaps in the pixel pushing code. That is fine on an AVR where the instruction rate is actually constant. When I tried this on the PIC32 I failed. Since the instruction rate is not constant (due to the factors above) you can NOT do this deterministically. Non-determinism is not normally a software engineer's friend and so therefore this approach was dead to me.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"></span><br />
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">Next stop: DMA. To be continued.</span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comtag:blogger.com,1999:blog-5352840725182809996.post-8989225237649395132015-01-18T08:13:00.004-08:002015-01-19T06:32:24.398-08:00A New Game Console Project - Part 1<br />
<span style="font-family: Arial,Helvetica,sans-serif;">Wow. A lot of time has passed since the last post. I have been busy though. I have built the bones of an ARM-based game console. I'll describe how I got to this point (a pointless spinning cube) over the last one and half years of sporadic effort.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/wQcDuN-ZfdM?feature=player_embedded' frameborder='0'></iframe></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<span style="font-family: Arial,Helvetica,sans-serif;">A spinning cube...</span></div>
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: Arial,Helvetica,sans-serif;"><a href="http://3.bp.blogspot.com/-lEj1wQ9VxNk/VLvMaAeNbJI/AAAAAAAAAEQ/lA6KpVhabes/s1600/STM32F4-DISCOVERY_Board.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-lEj1wQ9VxNk/VLvMaAeNbJI/AAAAAAAAAEQ/lA6KpVhabes/s1600/STM32F4-DISCOVERY_Board.png" height="261" width="320" /></a></span></div>
<br />
<div style="text-align: center;">
<span style="font-family: Arial,Helvetica,sans-serif;">STM32F4 Discovery Board</span></div>
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">Firstly, though here are my influences. You should certainly check out these amazing projects - they might inspire you to go down this crazy path.</span><br />
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">Lazarus64: <a href="http://lucidscience.com/pro-lazarus-64%20prototype-1.aspx">http://lucidscience.com/pro-lazarus-64%20prototype-1.aspx</a> </span><br />
<span style="font-family: Arial,Helvetica,sans-serif;">Uzebox: <a href="http://belogic.com/uzebox/">http://belogic.com/uzebox/</a></span><br />
<span style="font-family: Arial,Helvetica,sans-serif;">Bitbox: <a href="http://bitboxconsole.blogspot.com.au/">http://bitboxconsole.blogspot.com.au/</a></span><br />
<span style="font-family: Arial,Helvetica,sans-serif;">Maximite: <a href="http://geoffg.net/maximite.html">http://geoffg.net/maximite.html</a></span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<br />
<h2>
<span style="font-family: Arial,Helvetica,sans-serif;">A Quick History</span></h2>
<h3>
<span style="font-family: Arial,Helvetica,sans-serif;">Take 1: The AVR-based Approach</span></h3>
<span style="font-family: Arial,Helvetica,sans-serif;">Originally I wanted to build a Z80 based computer with nice 8-bit AVR based GPU - a software GPU. The idea for the GPU came after reading about the Lazarus64 project. Brad (from LucidScience) managed to breadboard an ATMEGA324P, 2 SRAMs, switching logic and delay lines for NTSC colour generation. It had the nice feature that it could switch which SRAM was connected to the CPU to achieve a hardware based double-buffered frame buffer.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">I started thinking how it would be neat to use a VGA output since VGA is simple to generate. I wanted to have a widescreen 16:9 resolution so that my pixels would be square on any modern TV. I settled on 480x270 which is nearly 16:9 and fits in a 128K SRAM.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">I progressed to a reasonably advanced state with the circuit and PCB layout. My design had two AVRs each with their own SRAM. They would simply take turns rendering. Another goal was to prototype at home and this meant I wanted a single-side board that I could make on my Zen Toolworks CNC router. This constraint basically killed this design. Well, in theory the design was sound but in practise it killed my patience due to the complexity involved in making changes.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<br />
<h3>
<span style="font-family: Arial,Helvetica,sans-serif;">Take 2: The AVR+FPGA-based Approach</span></h3>
<span style="font-family: Arial,Helvetica,sans-serif;">I thought it might be easier to place a small FPGA as the centre of the design as hub for the SRAM, AVR and VGA port. I bought this:</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-BghkHybpPco/VLvQvJzXpXI/AAAAAAAAAEc/RWRG-NPUKRs/s1600/FPGA.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-BghkHybpPco/VLvQvJzXpXI/AAAAAAAAAEc/RWRG-NPUKRs/s1600/FPGA.jpg" height="320" width="320" /></a></div>
<span style="font-family: Arial,Helvetica,sans-serif;"></span><br />
<div style="text-align: center;">
<span style="font-family: Arial,Helvetica,sans-serif;">Altera Cyclone II</span></div>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">I still think this was a good move. I could plug in pieces of my computer in chunks as I built them. I set about making an SRAM adapter board on my CNC that would plug into the board above. This contained the finest pitch routing I have ever attempted on my CNC and necessitated the use of a probe to correct for slight deviations in height in the PCB blank. Here is the result:</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-8J3UOTINk3Y/VLvSwAf_eqI/AAAAAAAAAEw/hIcEzs4ZJsk/s1600/SRAM-Board.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-8J3UOTINk3Y/VLvSwAf_eqI/AAAAAAAAAEw/hIcEzs4ZJsk/s1600/SRAM-Board.jpg" height="320" width="320" /></a></div>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span><span style="font-family: Arial, Helvetica, sans-serif;">For those interested, I used the following probing software with my Eagle, PCBGcode and LinuxCNC setup: <a href="http://www.autoleveller.co.uk/">AutoLeveller</a>. It is a terrific piece of software.</span><br />
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">The board above took a 10ns ISSI 512KB SRAM in a TSOP-44 package. I think the board turned out really well. I soldered it up, plugged it in and toasted both my SRAM and a couple of pins on my FPGA. That is what happens when you have a solder bridge underneath the SRAM. I should have checked it I know. I didn't. Anyway I ordered another FPGA board.</span><br />
<br />
<span style="font-family: Arial,Helvetica,sans-serif;"></span>
<span style="font-family: Arial,Helvetica,sans-serif;">So, it was time time to write some VHDL code. Since I had an FPGA, I thought I might as well move the VGA signal generation to it. I had not written VHDL since university some 15 years ago. Once I remembered that I was not supposed to be writing code but rather describing hardware, things went more smoothly. Fortunately I found some VGA generation VHDL that I modified and plugged in appropriate 50MHz clock for a nice 800x600 mode:</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"></span><br />
<pre style="background-image: URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: 500px; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY vga_controller IS
GENERIC(
h_pulse : INTEGER := 120; --horizontal sync pulse width in pixels
h_bp : INTEGER := 64; --horizontal back porch width in pixels
h_pixels : INTEGER := 800; --horizontal display width in pixels
h_fp : INTEGER := 56; --horizontal front porch width in pixels
h_pol : STD_LOGIC := '1'; --horizontal sync pulse polarity (1 = positive, 0 = negative)
v_pulse : INTEGER := 6; --vertical sync pulse width in rows
v_bp : INTEGER := 23; --vertical back porch width in rows
v_pixels : INTEGER := 600; --vertical display width in rows
v_fp : INTEGER := 37; --vertical front porch width in rows
v_pol : STD_LOGIC := '1'); --vertical sync pulse polarity (1 = positive, 0 = negative)
PORT(
pixel_clk : IN STD_LOGIC; --pixel clock at frequency of VGA mode being used
reset_n : IN STD_LOGIC; --active low asynchronous reset
h_sync : OUT STD_LOGIC; --horizontal sync pulse
v_sync : OUT STD_LOGIC; --vertical sync pulse
disp_ena : OUT STD_LOGIC; --display enable ('1' = display time, '0' = blanking time)
column : OUT INTEGER; --horizontal pixel coordinate
row : OUT INTEGER; --vertical pixel coordinate
n_blank : OUT STD_LOGIC; --direct blacking output to DAC
n_sync : OUT STD_LOGIC); --sync-on-green output to DAC
END vga_controller;
ARCHITECTURE behavior OF vga_controller IS
CONSTANT h_period : INTEGER := h_pulse + h_bp + h_pixels + h_fp; --total number of pixel clocks in a row
CONSTANT v_period : INTEGER := v_pulse + v_bp + v_pixels + v_fp; --total number of rows in column
BEGIN
n_blank <= '1'; --no direct blanking
n_sync <= '0'; --no sync on green
PROCESS(pixel_clk, reset_n)
VARIABLE h_count : INTEGER RANGE 0 TO h_period - 1 := 0; --horizontal counter (counts the columns)
VARIABLE v_count : INTEGER RANGE 0 TO v_period - 1 := 0; --vertical counter (counts the rows)
BEGIN
IF(reset_n = '0') THEN --reset asserted
h_count := 0; --reset horizontal counter
v_count := 0; --reset vertical counter
h_sync <= NOT h_pol; --deassert horizontal sync
v_sync <= NOT v_pol; --deassert vertical sync
disp_ena <= '0'; --disable display
column <= 0; --reset column pixel coordinate
row <= 0; --reset row pixel coordinate
ELSIF(pixel_clk'EVENT AND pixel_clk = '1') THEN
--counters
IF(h_count < h_period - 1) THEN --horizontal counter (pixels)
h_count := h_count + 1;
ELSE
h_count := 0;
IF(v_count < v_period - 1) THEN --veritcal counter (rows)
v_count := v_count + 1;
ELSE
v_count := 0;
END IF;
END IF;
--horizontal sync signal
IF(h_count < h_pixels + h_fp OR h_count > h_pixels + h_fp + h_pulse) THEN
h_sync <= NOT h_pol; --deassert horizontal sync pulse
ELSE
h_sync <= h_pol; --assert horizontal sync pulse
END IF;
--vertical sync signal
IF(v_count < v_pixels + v_fp OR v_count > v_pixels + v_fp + v_pulse) THEN
v_sync <= NOT v_pol; --deassert vertical sync pulse
ELSE
v_sync <= v_pol; --assert vertical sync pulse
END IF;
--set pixel coordinates
IF(h_count < h_pixels) THEN --horizontal display time
column <= h_count; --set horizontal pixel coordinate
END IF;
IF(v_count < v_pixels) THEN --vertical display time
row <= v_count; --set vertical pixel coordinate
END IF;
--set display enable output
IF(h_count < h_pixels AND v_count < v_pixels) THEN --display time
disp_ena <= '1'; --enable display
ELSE --blanking time
disp_ena <= '0'; --disable display
END IF;
END IF;
END PROCESS;
END behavior;
</code></pre>
<br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">This produced a a stable 800x600 image which I took the worst photo in world of below:</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-OCrnMH6g9ls/VLvSuF08jMI/AAAAAAAAAEo/g6ZrO13IjPU/s1600/FPGA-VGA.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-OCrnMH6g9ls/VLvSuF08jMI/AAAAAAAAAEo/g6ZrO13IjPU/s1600/FPGA-VGA.jpg" height="240" width="320" /></a></div>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">Anyway, it was time for the wheels to fall off this idea too. So, how did this one fail? I changed the timings to generate my desired 480x270 mode and plugged the contraption into the VGA port on my TV. The result: NOTHING.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">So it turns out that TVs are far more pickier about modes that PC LCD monitors. Both my Sony LCD and Pioneer Plasma will accept 640x480, 800x600, 1920x1080 and other popular modes. </span><span style="font-family: Arial,Helvetica,sans-serif;">480x270 didn't work on either. I decided at this point to have bit of rest.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<br />
<h3>
<span style="font-family: Arial,Helvetica,sans-serif;">Take 3: The ATMega328 and SVideo/Composite-based Approach</span></h3>
<span style="font-family: Arial,Helvetica,sans-serif;">About mid-2014 I started becoming interested in the Uzebox and started wondering if I could do something similar. The Uzebox is game console. It was around this time that I started becoming interested in retro gaming and the Uzebox is all about retro gaming. It still amazes me that </span><span style="font-family: Arial,Helvetica,sans-serif;"><span itemprop="articleBody">Minecraft (well Mojang) was sold for $2.5</span> billion to Microsoft . Minecraft had pixelated graphics by design. Pixel art can be very compelling clearly and I think that same spirit is found within the amazing Uzebox community. Go and check out the <a href="http://uzebox.org/forums/">Uzebox Forum</a> - amazing stuff going on in there.</span><br />
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">So my requirements were beginning to change at this point to something like the following:</span><br />
<ul>
<li><span style="font-family: Arial,Helvetica,sans-serif;">Must be largely a single-chip design except for the TV encoder</span></li>
<li><span style="font-family: Arial,Helvetica,sans-serif;">Must support SNES game pads which are available cheaply on eBay</span></li>
<li><span style="font-family: Arial,Helvetica,sans-serif;">Must support 256 colours</span></li>
<li><span style="font-family: Arial,Helvetica,sans-serif;">Must support a 16:9 resolution</span></li>
<li><span style="font-family: Arial,Helvetica,sans-serif;">Must have sufficient resolution to be fun on a 42-inch screen but not too high that it isn't fun to make graphics for.</span></li>
<li><span style="font-family: Arial,Helvetica,sans-serif;">Must support audio output of some form.</span></li>
<li><span style="font-family: Arial,Helvetica,sans-serif;">Must support the ability to execute from RAM.</span></li>
</ul>
<span style="font-family: Arial,Helvetica,sans-serif;">The last requirement gives me the ability for the console to still act as a general purpose computer. I still haven't given up on that.</span><br />
<br />
<br />
<span style="font-family: Arial,Helvetica,sans-serif;">The Uzebox uses a Analog Device AD725 PAL/NTSC encoder chip to produce a 4:3 video signal from the AVR.</span>
<span style="font-family: Arial,Helvetica,sans-serif;">I wanted to do a 16:9 widescreen mode but I remembered that the first DVD players (pre-HDMI) supported widescreen modes over composite video. I dug into it the timings more and then realised that because PAL is analog, I can push out as many pixels as I like per line to achieve a widescreen mode. Well, you are limited by the bandwidth of the AD724 and the TV's decoder though. In practise I think this is around 4-5 MHz for PAL so my mode is achievable. Essentially a </span><span style="font-family: Arial,Helvetica,sans-serif;">8-10MHz pixel clock is the upper limit. In another post I might elaborate on the why the pixel clock can be double but take my word for now.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">I started to look at other modes that might fit nicely in a PAL timing window and found that 416x234 required a nice 8MHz pixel clock that is exactly half of an Arduino clock frequency. I had an Arduino sitting around so I though I might hook them up. Unfortunately I couldn't work out how to achieve 8MHz with an external SRAM. I felt the Arduino's 2K RAM wasn't enough to make the kinds of games I wanted to make. Unfortunately there isn't enough time to address an SRAM and read data from it during scan out.</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;">So then after reading about the PIC32-based Maximite and always having an interest in MIPS since learning about it at university I bought a PIC32 dev board called a UBW32. I mad a small board for the AD724 (like the AD725) and ended up with this monstrosity:</span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-fHJiT7EweNI/VLvawXmy6jI/AAAAAAAAAFA/rTEyOD8FZIQ/s1600/PIC32.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-fHJiT7EweNI/VLvawXmy6jI/AAAAAAAAAFA/rTEyOD8FZIQ/s1600/PIC32.jpg" height="256" width="320" /></a></div>
<div style="text-align: center;">
<span style="font-family: Arial,Helvetica,sans-serif;">Note that the AD724 is on the backside as it an SMD device</span></div>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><i>More to follow in another post...</i></span><br />
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>
<span style="font-family: Arial,Helvetica,sans-serif;"><br /></span>Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comPerth WA, Australia-31.9535132 115.85704710000005-33.6775717 113.27526010000004 -30.229454699999998 118.43883410000005tag:blogger.com,1999:blog-5352840725182809996.post-49807760239621585592013-01-23T07:53:00.000-08:002013-01-23T07:53:21.567-08:00Wireless Reticulation Controller<div style="margin-bottom: 0cm;">
<div class="separator" style="clear: both; text-align: center;">
<b style="text-align: -webkit-auto;"><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></b></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/Vzwoleuy-kE?feature=player_embedded' frameborder='0'></iframe></div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;">The uWasp project has been on hold for
a while as I have been working on another project. I'm calling this
a Wireless Reticulation Controller. In fact, I have plans for an
entire wireless home automation platform but this just the first real
step.</span></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-FAQvSbaXGHo/UQAFBaAwyCI/AAAAAAAAACc/CGy8URrR0JA/s1600/ControllerInBox.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="http://1.bp.blogspot.com/-FAQvSbaXGHo/UQAFBaAwyCI/AAAAAAAAACc/CGy8URrR0JA/s320/ControllerInBox.jpg" width="320" /></a></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="CENTER" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Figure 1 – Reticulation
Controller</span></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">This is a 4 station domestic
reticulation controller which I designed and built. It runs on 24V
AC from a plug pack. It has no buttons or display – at least for
now. It receives commands via a custom protocol over UHF. The
controller utilises the ultra cheap 433MHz radio modules that are
available everywhere. I got mine from <a href="http://littlebirdelectronics.com/">Little Bird Electronics</a>.
More on the RF side of things a bit later on.</span></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-YkzpzQoUNu4/UQAFCY_TyQI/AAAAAAAAACs/1k07dGTz9Ns/s1600/RFModules.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="http://4.bp.blogspot.com/-YkzpzQoUNu4/UQAFCY_TyQI/AAAAAAAAACs/1k07dGTz9Ns/s200/RFModules.jpg" width="200" /></a></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">The controller simply plugs into an
outdoor power socket and any reticulation solenoids terminate on the
terminal block. Once powered up, the controller runs a schedule which
is uploaded via the RF link. Manual Override is also supported over
RF. Any station can be switched on independently and also in any
combination – though I need to disable that as I don't want to see
too much current draw on the plug pack. The controller receives it's
clock over RF, so no battery backup is required. A simple Ping
exchange is implemented too. I'm currently seeing a 300ms round trip
which is not too bad considering I haven't optimised anything yet.
The packet loss can also be measured by the ping facility as a bonus
and this help to position the UHF Access Point (more on that later)
as multi-path fading is an issue as far as I can tell.</span></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">The heart of the controller is a
ATMega328p (same as Arduino Uno etc). The firmware is (in my humble
opinion) properly designed for extensibility and maintainability.
I'm using a simple Task abstraction and a few different libraries for
queues and other primitives. AES128 encryption is in place but not
activated. I don't plan to activate crypto for my reticulation
system. Sure, someone can drive by and turn on my sprinklers – an
effective water pressure denial-of-service attack is possible if i'm
in the shower at the time. The individual would have to be nearby
since the range on the RF modules is not that great... I digress.</span></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div style="margin-bottom: 0cm;">
<h3>
<b><span style="font-family: Arial, Helvetica, sans-serif;">UHF Access Point</span></b></h3>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-fPksrMx2WgY/UQAFCaENovI/AAAAAAAAACw/h4cSEcl2HAE/s1600/RFGatewayOnBench.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="183" src="http://3.bp.blogspot.com/-fPksrMx2WgY/UQAFCaENovI/AAAAAAAAACw/h4cSEcl2HAE/s320/RFGatewayOnBench.jpg" width="320" /></a></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="CENTER" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Figure 2 – UHF Access
Point (UAP)</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Figure 2 above is the UHF
Access Point (UAP) I created to communicate with the controller (and
other devices to come later). It connects to my server over a
USB-to-RS232 cable from SparkFun. Eventually I want to connect this
to a Raspberry Pi to make a nice self contained UAP. I have a
headless server at home which is simply a VM host for a number of
different VMs – one of which runs my Reticulation Web Application.
The Web App talks via UDP multicast (using the fine LCM library) to
an RFGateway application which talks to the board above. I'm using
socat to move data between the USB port on the VM host and the RF
Gateway application which runs inside the guest VM.</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<h3>
<b><span style="font-family: Arial, Helvetica, sans-serif;">Web and RF Gateway
Applications</span></b></h3>
</div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">I used the project as an
excuse to learn a few new frameworks. The Web Application is written
in Sencha's ExtJS 4.1 framework heavily using their new MVC features.
</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-hbxdtaN0DHY/UQAFB5Zkk0I/AAAAAAAAACk/ihYRoOvprJU/s1600/ManualControl.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="255" src="http://2.bp.blogspot.com/-hbxdtaN0DHY/UQAFB5Zkk0I/AAAAAAAAACk/ihYRoOvprJU/s320/ManualControl.png" width="320" /></a></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="CENTER" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Figure 3 – The Simple
Controller</span></div>
<div align="CENTER" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">I wrote an administrative
interface for the system which can be extended to support different
types of devices. Currently it allows for Retic Systems to be
defined and the schedule defined too.
</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-2srDXs8D2aU/UQAFArNh4kI/AAAAAAAAACY/2NauMGA1Rmw/s1600/AdminWebApp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="173" src="http://3.bp.blogspot.com/-2srDXs8D2aU/UQAFArNh4kI/AAAAAAAAACY/2NauMGA1Rmw/s320/AdminWebApp.png" width="320" /></a></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="CENTER" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Figure 4 –
Administrative Web Application</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">I did write a previous
version of this web application in Django and JQueryUI. That was
shelved due to desire to learn ExtJS. ExtJS certainly raises the
productivity bar a lot for a RIA-type application. That said, the
Javascript front-end was probably the least productive part of the
entire suite. I'm really keen to get into Microsoft's <a href="http://www.typescriptlang.org/Playground/">TypeScript</a>.
I'd really like to stick to Eclipse though due to the cross-platform
advantages. I need to look into writing Eclipse tooling for
TypeScript. I'll probably be proved wrong but I think TypeScript is
going to be huge if it gets Eclipse support. People are starting to
write some really big applications in JavaScript and I feel that when
a project gets really large, IDE support becomes essential. Being a
weakly-typed language means it is difficult to develop great tooling.
TypeScript appears to add in basic features that I think you need to
support serious IDE-driven refactors and being strongly-typed means
the compiler is able to pick up a massive class of bugs for you. It
is Apache licensed which I think is important for adoption outside of
the enterprise world. There is a JQueryUI binding for TypeScript
which I'm very keen to have try out.</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm; page-break-before: always;">
<h3>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: medium;"><b>Architecture</b></span></h3>
</div>
<div align="LEFT" style="margin-bottom: 0cm;">
<h4>
<b><span style="font-family: Arial, Helvetica, sans-serif;">System Goals</span></b></h4>
</div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">The goal was to build a
system that could be evolved toward an entire home automation
platform. Another really important goal was to pick an RF technology
that was super low-cost – partly because I was really curious as to
whether it could be done and partly because I want to have a lot of
devices in the network. For example, I might want to put sensors on
every window lock or my garage door, or water sensors in the lawn and
gardens. I also wanted to allow for hard-wired devices (such as a
house Alarm).</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<h4>
<b><span style="font-family: Arial, Helvetica, sans-serif;">Reticulation Controller
Architecture</span></b></h4>
</div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">The architecture of the
Reticulation Controller is based around a couple of principles:</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<ol>
<li><div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Subsystems should be
decoupled to the implementation to be changed easily.</span></div>
</li>
<li><div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Collaborators should be
“injected” using IoC techniques.</span></div>
</li>
<li><div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Portability should be
maintained in order to allow easy unit testing on a Macbook or a
Linux PC.</span></div>
</li>
</ol>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">I imposed a number of design
constraints at the hardware level that influence the architecture
including:</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<ol>
<li><div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">The target device is
8-bit AVR with at least 32KB Flash and 1KB SRAM.</span></div>
</li>
<li><div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">The language would be
C++ with no RTTI used.</span></div>
</li>
<li><div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">The RF interface would
be cost optimised.</span></div>
</li>
</ol>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Low-coupling and
high-cohesion is 101 stuff as far as Software Engineering is
concerned but you do need to be careful when all you have is 32KB of
flash to work with. I wanted to try and structure things well and
decided that I would pull back from ideals as space came under
pressure. This turned out to be a great choice because I'm only
using 50% of flash currently and because I've retained good
structure, adding features has been very quick. That said there is
lot's of room for improvement and I think I trim off 1-2KB without
losing the plot.</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">I wanted to be able to
easily swap out sub-systems to support ease of system evolution,
testability and re-usability. I defined or utilised a number of
interfaces (using pure virtual classes in C++) such as Task, Handler
and Message. Queues are used to communicate Messages between Tasks
in system. For example, once a valid ManualControlMessage is decoded
by the RFTask, this POCO (Plain Old C++ Object) is placed in the
CommandQueue for the CommandPostTask to process. The CommandPostTask
pulls the message from the Queue, and using a simple dispatcher feeds
it to the appropriate Handler. The figure below shows some of the
classes/interfaces in the system.</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-84e6_dAQm6M/UQAFAkVUFQI/AAAAAAAAACU/jpmmLqCfff0/s1600/Domain.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://4.bp.blogspot.com/-84e6_dAQm6M/UQAFAkVUFQI/AAAAAAAAACU/jpmmLqCfff0/s320/Domain.png" width="267" /></a></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="CENTER" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Figure 5 – Important
classes</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Most classes within the
system heavily rely on Dependency Injection (or IoC). I love this
pattern because it let's me unit test components easily. I swap out
dependencies during unit testing for mocks that let me capture and
assert the correctness of certain behavioural interactions.</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Portability was important
too. I wanted to be able to develop on my Macbook Air or my Linux
PC. I wanted to be able to use tools like Valgrind and CGDB. So, I
picked a nice easy subset of C++ and no RTTI (I don't think that is
supported on AVR-GCC anyway). The build system is an
SConstruct-based contraption. That was new for me as I'm used to
Make, Ant, Ivy, Maven and MSBuild/TFS. I like it and I'd definitely
use it again.</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<h4>
<b><span style="font-family: Arial, Helvetica, sans-serif;">Reticulation Web
Application</span></b></h4>
</div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">The Web
Application is a typical n-Tier setup which is written in Java. I
decided (after scraping the DJango application) that it was time to
have a look at the Play! Framework that i'd heard so much about. I
downloaded Play! 2.0 and started reading the tutorials. It took me a
long time (probably more than 8 hours) to integrate Maven and Play!
together. It was an absolute nightmare but I got it working. You
might ask why, after all Play! includes a build system. I didn't
want to lose the power of Maven and I wanted the ability to work in
Eclipse. The work flow ended up being something like this:</span></div>
<ol>
<li><div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Make
sure everything compiles in Eclispe</span></div>
</li>
<li><div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Run
a Maven install from the command line</span></div>
</li>
<li><div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Run
a Play (well SBT) command to pull dependencies from Maven</span></div>
</li>
<li><div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Run
the Play Server</span></div>
</li>
<li><div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">Attach
debugger from Eclipse</span></div>
</li>
</ol>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">In the
end I got sick of this workflow and ported the solution to Jetty. It
took only 30 minutes and now I have massive amounts of flexibility
back. Please don't read too much into this. Play! Is not design for
my type of application. I just wanted to highlight that you do some
flexibility in order to maintain a Maven build system. Perhaps these
issues have been resolved recently...</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">The
rest of the application is typical. I have a Service (Business Logic
Layer) which exposes the functionality of the server. As per
defacto-standard Fowler layering, all database transactions (my Unit
of Work) are bracketed within the Service Layer. I'm using Hibernate
for the Data Access Layer and SQL-Lite at the moment.</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">The
various server side components communicate cross-process via UDP
multicast. I'm using the <a href="http://code.google.com/p/lcm">LCM</a> library to make this easy.</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<h3>
<b><span style="font-family: Arial, Helvetica, sans-serif;">Future Topics</span></b></h3>
</div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;">In
another post I might describe the communications protocol and how it
allows (well tries to allow) reliable communication over this type of
radio network. I might also explain how I made the PCBs on my Zen
Toolworks CNC.</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-L9d5v7c1Wnk/UQAFDK4g_yI/AAAAAAAAAC0/37mFoMHV1yg/s1600/Zen.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="265" src="http://1.bp.blogspot.com/-L9d5v7c1Wnk/UQAFDK4g_yI/AAAAAAAAAC0/37mFoMHV1yg/s400/Zen.jpg" width="400" /></a></div>
<div align="LEFT" style="margin-bottom: 0cm;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span></div>
<br />Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comtag:blogger.com,1999:blog-5352840725182809996.post-49687461758862543952011-05-31T07:52:00.000-07:002011-05-31T07:52:22.185-07:00Video - Update 2A little more progress made. I have routed the R2R DACs and HSYNC and VSYNC signals to a 4x2 pin header. This will go out to a chassis mounted VGA port.<br />
<br />
I think I have mostly worked out how I'll coordinate between the two GPU. I have introduced a D-Type Flip-flop to perform the role of a hardware mutex. When the GPU AVRs start up, they will read the value on their PORTD5 pin. The left hand GPU PORTD5 pin will be connected to the Q output of the Flip Flop and PORTD5 on the other GPU will be connected to Q'. Whichever GPU reads a high value is going to render while the other will perform the RAMDAC role. Then the Flip-flop flips, the roles will reverse. <br />
<br />
The RAMDAC GPU will be responsible for handing off to the other. The hand off process will look like this:<br />
<ol><li>At the end of the video frame the RAMDAC GPU will drive the Flip-flop clock pin high causing:</li>
<ol><li> The Flip-flop will toggle.</li>
<li>The VSYNC will go high (or high depending on how I wire it) </li>
<li>The Serial ports will be connected to the new Render GPU.</li>
<li>The SRAM data line buffers will toggle their enabled state.</li>
<li>The SRAM address line buffers will toggle their enabled state.</li>
</ol><li>The new RAMDAC will wait for the VSYNC period and then drive the Flip-flop clock pin low.</li>
<li>The new Render GPU will set appropriate pins to High-Z and then can get on with rendering.</li>
</ol><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-dF554QkTneQ/TeUAjo5lurI/AAAAAAAAAAs/e-jlfNgxGTo/s1600/VideoBoard-0.0.1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="538" src="http://1.bp.blogspot.com/-dF554QkTneQ/TeUAjo5lurI/AAAAAAAAAAs/e-jlfNgxGTo/s640/VideoBoard-0.0.1.png" width="640" /></a></div><br />
<br />
Things left to do on the video board:<br />
<ul><li>Ground plane</li>
<li>Decoupling capacitors</li>
</ul>Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comtag:blogger.com,1999:blog-5352840725182809996.post-38322845746337574812011-05-28T08:53:00.000-07:002011-05-28T08:53:21.679-07:00Video - UpdateI have completed a bit more of the routing work on the Video board. I still need to add decoupling capacitors and fix up a few other things. I don't have any ground plane yet, that's next - once I figure out how to do it properly in Eagle.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-7AUavnl8AxQ/TeEYCzAjL_I/AAAAAAAAAAo/46VdV3bo0V8/s1600/VideoBoard.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="337" src="http://3.bp.blogspot.com/-7AUavnl8AxQ/TeEYCzAjL_I/AAAAAAAAAAo/46VdV3bo0V8/s400/VideoBoard.png" width="400" /></a></div><br />
I changed plan slightly with the clear screen counter. In the end I chose an 8-bit counter. That means I can clear a contiguous run of 256 pixels without intervention from the AVR. There is also a jumper selectable 2x or 4x clock multiplier on the counter. Each AVR will need to increment address bits [8..16] on its own. That should be fine at 4x since the address will only increment every 64 AVR cycles; that is plenty of time to increment a variable and load a port.Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comtag:blogger.com,1999:blog-5352840725182809996.post-85829233187689834512011-05-17T06:51:00.000-07:002011-05-17T06:51:48.615-07:00VMS - Getting somewhereHave thought a lot about the Video board since the last post. Building a switch for this kind of thing out of discrete logic chips not practical. I'm limited in my board size in Eagle. I'm limited in my ability to route the thing anyway. I have an alternative design in mind. Instead of having a separate GPU and RAMDAC, I'll just have two GPUs which can also act as RAMDACs:<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-hiPY13nCa0U/TdJ7Z5uv0yI/AAAAAAAAAAg/FA4-PLStO1E/s1600/VMS_Serial_v0.0.1_Schematic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="472" src="http://1.bp.blogspot.com/-hiPY13nCa0U/TdJ7Z5uv0yI/AAAAAAAAAAg/FA4-PLStO1E/s640/VMS_Serial_v0.0.1_Schematic.png" width="640" /> </a></div><div class="separator" style="clear: both; text-align: left;">This removes the switching logic and now each GPU has a dedicated SRAM bank. Each GPU will be either in Render Mode or Scan-out Mode. They will never be in the same mode. A third AVR controls the two GPUs and tell them what mode to be in. This coordinator chip also controls which GPU is "writing" to the R2R DAC.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">I have also included a clock multiplier and 24-bit counter which will be able to quickly clear the framebuffer. This will free up the GPU for useful drawing instead of spending 80%-90% of the time clearing the screen. A clever GPU firmware might be able to sync on this and use the counter for drawing pixel spans of solid colours - yum.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Here is the routing so far...</div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-q-w9tmZF8L8/TdJ7j9bTXyI/AAAAAAAAAAk/IHT635wC7nw/s1600/VideoBoardWIP.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="267" src="http://1.bp.blogspot.com/-q-w9tmZF8L8/TdJ7j9bTXyI/AAAAAAAAAAk/IHT635wC7nw/s400/VideoBoardWIP.png" width="400" /></a></div>Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comtag:blogger.com,1999:blog-5352840725182809996.post-75850539095511774012011-05-08T08:07:00.000-07:002011-05-08T08:07:13.431-07:00VMS - Back to the drawing boardHere is the result of 20 minutes work in Eagle on the VMS board. I have place the 14 74HC157 ICs required to form the switching logic. I have also placed a header for connection to the GPU IC. I still have to place a header for each bank of RAM and a header for the RAMDAC IC.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-2wsarDUFGxE/TcakQfiYqGI/AAAAAAAAAAc/PTlqjJtxj2I/s1600/VMS_Board.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-2wsarDUFGxE/TcakQfiYqGI/AAAAAAAAAAc/PTlqjJtxj2I/s1600/VMS_Board.png" /></a></div><br />
<br />
It doesn't take a Rocket Scientist to work out that this is not going to work. I'm already at the full board size Eagle support for the free version and I don't have any room for routing traces. <br />
<br />
I need to re-think this. My options are:<br />
<ol><li>Abandon the switch and RAMDAC and have the GPU to it all.</li>
<li>Come up with a better switch.</li>
<li>Use dual-port SRAM.</li>
</ol>The first option doesn't appeal to me greatly. If I lose the switch then I lose the ability to render and scan-out at the same time. This is a big deal. Based on the figures from <a href="http://en.wikipedia.org/wiki/Video_Graphics_Array#Signal">here</a>, active video accounts for approximately 91% of a full second of video. That leaves only 9% of the AVR CPU time to actually render. My previous design allowed rendering 100% of the time. <br />
<br />
The second option could be solved with something like a FPGA of CPLD. I need to look into the cost of these. An initial look reveals this <a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&name=544-2260-ND">one</a> has 120 GPIO pins and is $31. The other cool thing about an FPGA is that I could move the CLEAR SCREEN command to the FPGA and free up the GPU too.<br />
<br />
The third option appears infeasible at this point. I can find dual-port SRAM at good price. That said, I could de-solder some from an old video card. Hmmm, might look into this. This is the ultimate because it means I can put the GPU and RAMDAC on opposite side of a single RAM IC. This is likely to be a dead end though as I'm pretty sure all most video cards use a derivative of DRAM, and I'm not getting into that.Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comtag:blogger.com,1999:blog-5352840725182809996.post-42475289654678115012011-05-07T00:02:00.000-07:002011-05-07T00:02:36.086-07:00VMS - Video Memory SwitcherI drew out the VMS below:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-_8PwIA_2Lj0/TcTuYrw_AQI/AAAAAAAAAAY/N_KWZPkB-OY/s1600/VMS_Schematic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="478" src="http://1.bp.blogspot.com/-_8PwIA_2Lj0/TcTuYrw_AQI/AAAAAAAAAAY/N_KWZPkB-OY/s640/VMS_Schematic.png" width="640" /></a></div><br />
Goodness me! This looks like PCB routing nightmare.Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comtag:blogger.com,1999:blog-5352840725182809996.post-85458946473172525392011-05-06T08:30:00.000-07:002011-05-06T08:30:26.389-07:00Block Diagram<a href="http://www.lucidscience.com/pro-lazarus-64%20prototype-1.aspx"></a>A basic architecture is emerging for this machine. This is basically what I want. The CPU can address any of the following devices:<br />
<ul><li>GPU - Graphics Processing Unit</li>
<li>APU - Audio Processing Unit</li>
<li>PPU - Peripheral Processing Unit</li>
<li>RAM - A 512KBytes SRAM.</li>
</ul><br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-RfPQEb9oidk/TcQQFYkEOGI/AAAAAAAAAAU/W1SHcjTGLko/s1600/BlockDiagram.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="http://3.bp.blogspot.com/-RfPQEb9oidk/TcQQFYkEOGI/AAAAAAAAAAU/W1SHcjTGLko/s640/BlockDiagram.png" width="588" /></a></div>The interesting thing is that the CPU can't directly access the frame buffer. The reason I have done this is due to the result of the testing I did in my previous post. It appears that the GPU is going to monopolise the bus just to clear the screen. I worked out that if the GPU was in a fact a 16MHz ATMega328 (same as Arduino Duemilanove), then just clearing the screen at 60 FPS would consume 97% of the CPU time and as a consequence a similar proportion of the bus bandwidth. Now, my GPU will run at 20MHz and I'll probably refresh at 50Hz since but the situation is still pretty dire.<br />
<br />
So, the direction I'll take will be to separate these buses. The CPU will just write commands to the GPU over the Main Address/Data bus and the GPU will render to the VRAM. This means filling single pixels is going to be much slower but other operations like solid fills should be much better.<br />
<br />
There is a potential problem here. I probably don't have enough pins on the GPU for two address and data buses. I'll need to work something out here. I have an idea involving overlapping address spaces and tri-state data buses. More to follow.<br />
<br />
Finally the VMS stands for Video Memory Switcher and is a fancy cross-bar switch. I got the idea from another project: <a href="http://www.lucidscience.com/pro-lazarus-64%20prototype-1.aspx">Lazarus-64</a>Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comtag:blogger.com,1999:blog-5352840725182809996.post-2664199158461637232011-05-05T08:54:00.000-07:002011-05-06T07:31:07.891-07:00Ok, I have worked out the problem earlier. The Arduino IDE uses the following compiler flags:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=21</div><br />
<br />
This caused my loop to be optimised out!<br />
<br />
I worked out how to build and upload outside the Arduino IDE and using an optimisation flag of -O0 I now get 39.6 seconds with the single pixel version. Writing 8 pixels per loop takes 3.9 seconds. 16 pixels is dispatched in 1.9 seconds and 32 pixels takes 0.97 seconds. At last now we have some real data! Here is a graph of those points.<br />
<div class="separator" style="clear: both; text-align: center;"></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-yQTKClL0gY8/TcLHG_CL2SI/AAAAAAAAAAQ/cTO-trcBSWo/s1600/ClearScreen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-yQTKClL0gY8/TcLHG_CL2SI/AAAAAAAAAAQ/cTO-trcBSWo/s1600/ClearScreen.png" /></a></div><br />
We have certainly reached the point of diminishing returns at 32 pixels. We might be able squeeze a bit more bit more by increasing the pixels but I tried 64 pixels and I think the Arduino ran out of flash. So if all we are doing is clearing the screen at 60 FPS, we have a 97% duty cycle. At 20 Mhz this becomes 78%. That leaves some time for drawing other things.<br />
<br />
<br />
Further improvement could be made. For example, in most games we won't need to clear the entire screen if we track the dirty regions. Finally, we can always over-clock ;-)Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comtag:blogger.com,1999:blog-5352840725182809996.post-1498616982527549952011-05-04T08:39:00.000-07:002011-05-04T08:39:48.861-07:00Video ModesI have been thinking about video modes.<br />
<br />
I want to be able to offer both 4:3 modes and 16:9 mode (since most TVs are widescreen now). So I did up a little spreadsheet that computes the Video RAM and pixel clock requirements given that I want the following features:<br />
<br />
<ul><li>Double buffering (2 frame buffers in VRAM with page flipping).</li>
<li>Clear entire screen at 60 fps.</li>
<li>8 bits per pixel (3 bits Red, 3 bits Green and 2 bits Blue)</li>
</ul><br />
Having 8 bits per pixel arranged in this way yields a palette like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://upload.wikimedia.org/wikipedia/commons/9/93/256colour.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://upload.wikimedia.org/wikipedia/commons/9/93/256colour.png" /></a></div><br />
This should look pretty tasty indeed. Here is the spreadsheet:<br />
<br />
<table border="0" cellspacing="0" cols="13" frame="VOID" rules="NONE"><colgroup><col width="40"></col><col width="50"></col><col width="63"></col><col width="63"></col><col width="63"></col><col width="86"></col><col width="63"></col><col width="55"></col><col width="47"></col><col width="73"></col><col width="75"></col><col width="82"></col><col width="87"></col></colgroup> <tbody>
<tr> <td align="CENTER" bgcolor="#FFD320" height="32" width="40"><b><span class="Apple-style-span" style="font-size: xx-small;">width</span></b></td> <td align="CENTER" bgcolor="#FFD320" width="50"><b><span class="Apple-style-span" style="font-size: xx-small;">height</span></b></td> <td align="CENTER" bgcolor="#FFD320" width="63"><b><span class="Apple-style-span" style="font-size: xx-small;">bytes/ page</span></b></td> <td align="CENTER" bgcolor="#FFD320" width="63"><b><span class="Apple-style-span" style="font-size: xx-small;">rounded page</span></b></td> <td align="CENTER" bgcolor="#FFD320" width="63"><b><span class="Apple-style-span" style="font-size: xx-small;">bytes total</span></b></td> <td align="CENTER" bgcolor="#FFD320" width="86"><b><span class="Apple-style-span" style="font-size: xx-small;">SRAM Chip</span></b></td> <td align="CENTER" bgcolor="#FFD320" width="63"><b><span class="Apple-style-span" style="font-size: xx-small;">total waste</span></b></td> <td align="CENTER" bgcolor="#FFD320" width="55"><b><span class="Apple-style-span" style="font-size: xx-small;">A pins/ page</span></b></td> <td align="CENTER" bgcolor="#FFD320" width="47"><b><span class="Apple-style-span" style="font-size: xx-small;">total pins</span></b></td> <td align="CENTER" bgcolor="#FFD320" sdnum="3081;0;#,##0" width="73"><b><span class="Apple-style-span" style="font-size: xx-small;">Pixel Clock</span></b></td> <td align="CENTER" bgcolor="#FFD320" width="75"><b><span class="Apple-style-span" style="font-size: xx-small;">Mode</span></b></td> <td align="RIGHT" bgcolor="#FFD320" width="82"><b><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></b></td> <td align="CENTER" bgcolor="#FFD320" width="87"><b><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></b></td> </tr>
<tr> <td align="RIGHT" bgcolor="#E6E6FF" height="32" sdnum="3081;" sdval="104"><span class="Apple-style-span" style="font-size: xx-small;">104</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;" sdval="78"><span class="Apple-style-span" style="font-size: xx-small;">78</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="8112"><span class="Apple-style-span" style="font-size: xx-small;">8,112</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="8192"><span class="Apple-style-span" style="font-size: xx-small;">8,192</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="16384"><span class="Apple-style-span" style="font-size: xx-small;">16,384</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(16K x 8)</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="160"><span class="Apple-style-span" style="font-size: xx-small;">160</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;" sdval="13"><span class="Apple-style-span" style="font-size: xx-small;">13</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="23"><span class="Apple-style-span" style="font-size: xx-small;">23</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="486720"><span class="Apple-style-span" style="font-size: xx-small;">486,720</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">104 x 78</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> <td align="LEFT" bgcolor="#E6E6FF"><b><span class="Apple-style-span" style="font-size: xx-small;">4:3 resolutions</span></b></td> </tr>
<tr> <td align="RIGHT" bgcolor="#E6E6FF" height="17" sdnum="3081;" sdval="144"><span class="Apple-style-span" style="font-size: xx-small;">144</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;" sdval="108"><span class="Apple-style-span" style="font-size: xx-small;">108</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="15552"><span class="Apple-style-span" style="font-size: xx-small;">15,552</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="16384"><span class="Apple-style-span" style="font-size: xx-small;">16,384</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="32768"><span class="Apple-style-span" style="font-size: xx-small;">32,768</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(32K x 8)</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="1664"><span class="Apple-style-span" style="font-size: xx-small;">1,664</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;" sdval="14"><span class="Apple-style-span" style="font-size: xx-small;">14</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="24"><span class="Apple-style-span" style="font-size: xx-small;">24</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="933120"><span class="Apple-style-span" style="font-size: xx-small;">933,120</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">144 x 108</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> <td align="LEFT" bgcolor="#E6E6FF"><b><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></b></td> </tr>
<tr> <td align="RIGHT" bgcolor="#E6E6FF" height="17" sdnum="3081;" sdval="208"><span class="Apple-style-span" style="font-size: xx-small;">208</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;" sdval="156"><span class="Apple-style-span" style="font-size: xx-small;">156</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="32448"><span class="Apple-style-span" style="font-size: xx-small;">32,448</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="32768"><span class="Apple-style-span" style="font-size: xx-small;">32,768</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="65536"><span class="Apple-style-span" style="font-size: xx-small;">65,536</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(64K x 8)</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="640"><span class="Apple-style-span" style="font-size: xx-small;">640</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;" sdval="15"><span class="Apple-style-span" style="font-size: xx-small;">15</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="25"><span class="Apple-style-span" style="font-size: xx-small;">25</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="1946880"><span class="Apple-style-span" style="font-size: xx-small;">1,946,880</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">208 x 156</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> <td align="LEFT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> </tr>
<tr> <td align="RIGHT" bgcolor="#E6E6FF" height="17" sdnum="3081;" sdval="288"><span class="Apple-style-span" style="font-size: xx-small;">288</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;" sdval="216"><span class="Apple-style-span" style="font-size: xx-small;">216</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="62208"><span class="Apple-style-span" style="font-size: xx-small;">62,208</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="65536"><span class="Apple-style-span" style="font-size: xx-small;">65,536</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="131072"><span class="Apple-style-span" style="font-size: xx-small;">131,072</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(128K x 8)</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="6656"><span class="Apple-style-span" style="font-size: xx-small;">6,656</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;" sdval="16"><span class="Apple-style-span" style="font-size: xx-small;">16</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="26"><span class="Apple-style-span" style="font-size: xx-small;">26</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="3732480"><span class="Apple-style-span" style="font-size: xx-small;">3,732,480</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">288 x 216</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> <td align="LEFT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> </tr>
<tr> <td align="RIGHT" bgcolor="#E6E6FF" height="17" sdnum="3081;" sdval="320"><span class="Apple-style-span" style="font-size: xx-small;">320</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;" sdval="240"><span class="Apple-style-span" style="font-size: xx-small;">240</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="76800"><span class="Apple-style-span" style="font-size: xx-small;">76,800</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="131072"><span class="Apple-style-span" style="font-size: xx-small;">131,072</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="262144"><span class="Apple-style-span" style="font-size: xx-small;">262,144</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(256K x 8)</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="108544"><span class="Apple-style-span" style="font-size: xx-small;">108,544</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;" sdval="17"><span class="Apple-style-span" style="font-size: xx-small;">17</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="27"><span class="Apple-style-span" style="font-size: xx-small;">27</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="4608000"><span class="Apple-style-span" style="font-size: xx-small;">4,608,000</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">320 x 240</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> <td align="LEFT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> </tr>
<tr> <td align="RIGHT" bgcolor="#E6E6FF" height="17" sdnum="3081;" sdval="360"><span class="Apple-style-span" style="font-size: xx-small;">360</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;" sdval="270"><span class="Apple-style-span" style="font-size: xx-small;">270</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="97200"><span class="Apple-style-span" style="font-size: xx-small;">97,200</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="131072"><span class="Apple-style-span" style="font-size: xx-small;">131,072</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="262144"><span class="Apple-style-span" style="font-size: xx-small;">262,144</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(256K x 8)</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="67744"><span class="Apple-style-span" style="font-size: xx-small;">67,744</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;" sdval="17"><span class="Apple-style-span" style="font-size: xx-small;">17</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="27"><span class="Apple-style-span" style="font-size: xx-small;">27</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="5832000"><span class="Apple-style-span" style="font-size: xx-small;">5,832,000</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">360 x 270</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">1080 mode</span></td> <td align="LEFT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> </tr>
<tr> <td align="RIGHT" bgcolor="#E6E6FF" height="17" sdnum="3081;" sdval="416"><span class="Apple-style-span" style="font-size: xx-small;">416</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;" sdval="312"><span class="Apple-style-span" style="font-size: xx-small;">312</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="129792"><span class="Apple-style-span" style="font-size: xx-small;">129,792</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="131072"><span class="Apple-style-span" style="font-size: xx-small;">131,072</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="262144"><span class="Apple-style-span" style="font-size: xx-small;">262,144</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(256K x 8)</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="2560"><span class="Apple-style-span" style="font-size: xx-small;">2,560</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;" sdval="17"><span class="Apple-style-span" style="font-size: xx-small;">17</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="27"><span class="Apple-style-span" style="font-size: xx-small;">27</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="7787520"><span class="Apple-style-span" style="font-size: xx-small;">7,787,520</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">416 x 312</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> <td align="LEFT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> </tr>
<tr> <td align="RIGHT" bgcolor="#E6E6FF" height="17" sdnum="3081;" sdval="480"><span class="Apple-style-span" style="font-size: xx-small;">480</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;" sdval="360"><span class="Apple-style-span" style="font-size: xx-small;">360</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="172800"><span class="Apple-style-span" style="font-size: xx-small;">172,800</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="262144"><span class="Apple-style-span" style="font-size: xx-small;">262,144</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="524288"><span class="Apple-style-span" style="font-size: xx-small;">524,288</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(512K x 8)</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="178688"><span class="Apple-style-span" style="font-size: xx-small;">178,688</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;" sdval="18"><span class="Apple-style-span" style="font-size: xx-small;">18</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="28"><span class="Apple-style-span" style="font-size: xx-small;">28</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="10368000"><span class="Apple-style-span" style="font-size: xx-small;">10,368,000</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">480 x 360</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">720 mode</span></td> <td align="LEFT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> </tr>
<tr> <td align="RIGHT" bgcolor="#E6E6FF" height="17" sdnum="3081;" sdval="512"><span class="Apple-style-span" style="font-size: xx-small;">512</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;" sdval="384"><span class="Apple-style-span" style="font-size: xx-small;">384</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="196608"><span class="Apple-style-span" style="font-size: xx-small;">196,608</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="262144"><span class="Apple-style-span" style="font-size: xx-small;">262,144</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="524288"><span class="Apple-style-span" style="font-size: xx-small;">524,288</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(512K x 8)</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="131072"><span class="Apple-style-span" style="font-size: xx-small;">131,072</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;" sdval="18"><span class="Apple-style-span" style="font-size: xx-small;">18</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="28"><span class="Apple-style-span" style="font-size: xx-small;">28</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="11796480"><span class="Apple-style-span" style="font-size: xx-small;">11,796,480</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">512 x 384</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">768 mode</span></td> <td align="LEFT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> </tr>
<tr> <td align="RIGHT" bgcolor="#E6E6FF" height="17" sdnum="3081;" sdval="584"><span class="Apple-style-span" style="font-size: xx-small;">584</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;" sdval="438"><span class="Apple-style-span" style="font-size: xx-small;">438</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="255792"><span class="Apple-style-span" style="font-size: xx-small;">255,792</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="262144"><span class="Apple-style-span" style="font-size: xx-small;">262,144</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="524288"><span class="Apple-style-span" style="font-size: xx-small;">524,288</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(512K x 8)</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="12704"><span class="Apple-style-span" style="font-size: xx-small;">12,704</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;" sdval="18"><span class="Apple-style-span" style="font-size: xx-small;">18</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="28"><span class="Apple-style-span" style="font-size: xx-small;">28</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="15347520"><span class="Apple-style-span" style="font-size: xx-small;">15,347,520</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">584 x 438</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> <td align="LEFT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> </tr>
<tr> <td align="RIGHT" bgcolor="#E6E6FF" height="17" sdnum="3081;" sdval="720"><span class="Apple-style-span" style="font-size: xx-small;">720</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;" sdval="540"><span class="Apple-style-span" style="font-size: xx-small;">540</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="388800"><span class="Apple-style-span" style="font-size: xx-small;">388,800</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="524288"><span class="Apple-style-span" style="font-size: xx-small;">524,288</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="1048576"><span class="Apple-style-span" style="font-size: xx-small;">1,048,576</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(1024K x 8)</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="270976"><span class="Apple-style-span" style="font-size: xx-small;">270,976</span></td> <td align="CENTER" bgcolor="#E6E6FF" sdnum="3081;" sdval="19"><span class="Apple-style-span" style="font-size: xx-small;">19</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="29"><span class="Apple-style-span" style="font-size: xx-small;">29</span></td> <td align="RIGHT" bgcolor="#E6E6FF" sdnum="3081;0;#,##0" sdval="23328000"><span class="Apple-style-span" style="font-size: xx-small;">23,328,000</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">720 x 540</span></td> <td align="RIGHT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;">1080 mode</span></td> <td align="LEFT" bgcolor="#E6E6FF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> </tr>
<tr> <td align="RIGHT" bgcolor="#99CCFF" height="32" sdnum="3081;" sdval="160"><span class="Apple-style-span" style="font-size: xx-small;">160</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;" sdval="90"><span class="Apple-style-span" style="font-size: xx-small;">90</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="14400"><span class="Apple-style-span" style="font-size: xx-small;">14,400</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="16384"><span class="Apple-style-span" style="font-size: xx-small;">16,384</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="32768"><span class="Apple-style-span" style="font-size: xx-small;">32,768</span></td> <td align="CENTER" bgcolor="#99CCFF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(32K x 8)</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="3968"><span class="Apple-style-span" style="font-size: xx-small;">3,968</span></td> <td align="CENTER" bgcolor="#99CCFF" sdnum="3081;" sdval="14"><span class="Apple-style-span" style="font-size: xx-small;">14</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="24"><span class="Apple-style-span" style="font-size: xx-small;">24</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="864000"><span class="Apple-style-span" style="font-size: xx-small;">864,000</span></td> <td align="RIGHT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;">160 x 90</span></td> <td align="RIGHT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> <td align="LEFT" bgcolor="#99CCFF"><b><span class="Apple-style-span" style="font-size: xx-small;">16:9 resolutions</span></b></td> </tr>
<tr> <td align="RIGHT" bgcolor="#99CCFF" height="17" sdnum="3081;" sdval="224"><span class="Apple-style-span" style="font-size: xx-small;">224</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;" sdval="126"><span class="Apple-style-span" style="font-size: xx-small;">126</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="28224"><span class="Apple-style-span" style="font-size: xx-small;">28,224</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="32768"><span class="Apple-style-span" style="font-size: xx-small;">32,768</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="65536"><span class="Apple-style-span" style="font-size: xx-small;">65,536</span></td> <td align="CENTER" bgcolor="#99CCFF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(64K x 8)</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="9088"><span class="Apple-style-span" style="font-size: xx-small;">9,088</span></td> <td align="CENTER" bgcolor="#99CCFF" sdnum="3081;" sdval="15"><span class="Apple-style-span" style="font-size: xx-small;">15</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="25"><span class="Apple-style-span" style="font-size: xx-small;">25</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="1693440"><span class="Apple-style-span" style="font-size: xx-small;">1,693,440</span></td> <td align="RIGHT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;">224 x 126</span></td> <td align="RIGHT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> <td align="LEFT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> </tr>
<tr> <td align="RIGHT" bgcolor="#99CCFF" height="17" sdnum="3081;" sdval="320"><span class="Apple-style-span" style="font-size: xx-small;">320</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;" sdval="180"><span class="Apple-style-span" style="font-size: xx-small;">180</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="57600"><span class="Apple-style-span" style="font-size: xx-small;">57,600</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="65536"><span class="Apple-style-span" style="font-size: xx-small;">65,536</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="131072"><span class="Apple-style-span" style="font-size: xx-small;">131,072</span></td> <td align="CENTER" bgcolor="#99CCFF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(128K x 8)</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="15872"><span class="Apple-style-span" style="font-size: xx-small;">15,872</span></td> <td align="CENTER" bgcolor="#99CCFF" sdnum="3081;" sdval="16"><span class="Apple-style-span" style="font-size: xx-small;">16</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="26"><span class="Apple-style-span" style="font-size: xx-small;">26</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="3456000"><span class="Apple-style-span" style="font-size: xx-small;">3,456,000</span></td> <td align="RIGHT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;">320 x 180</span></td> <td align="RIGHT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> <td align="LEFT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> </tr>
<tr> <td align="RIGHT" bgcolor="#99CCFF" height="17" sdnum="3081;" sdval="480"><span class="Apple-style-span" style="font-size: xx-small;">480</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;" sdval="270"><span class="Apple-style-span" style="font-size: xx-small;">270</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="129600"><span class="Apple-style-span" style="font-size: xx-small;">129,600</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="131072"><span class="Apple-style-span" style="font-size: xx-small;">131,072</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="262144"><span class="Apple-style-span" style="font-size: xx-small;">262,144</span></td> <td align="CENTER" bgcolor="#99CCFF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(256K x 8)</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="2944"><span class="Apple-style-span" style="font-size: xx-small;">2,944</span></td> <td align="CENTER" bgcolor="#99CCFF" sdnum="3081;" sdval="17"><span class="Apple-style-span" style="font-size: xx-small;">17</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="27"><span class="Apple-style-span" style="font-size: xx-small;">27</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="7776000"><span class="Apple-style-span" style="font-size: xx-small;">7,776,000</span></td> <td align="RIGHT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;">480 x 270</span></td> <td align="RIGHT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;">1080 mode</span></td> <td align="LEFT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> </tr>
<tr> <td align="RIGHT" bgcolor="#99CCFF" height="17" sdnum="3081;" sdval="640"><span class="Apple-style-span" style="font-size: xx-small;">640</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;" sdval="360"><span class="Apple-style-span" style="font-size: xx-small;">360</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="230400"><span class="Apple-style-span" style="font-size: xx-small;">230,400</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="262144"><span class="Apple-style-span" style="font-size: xx-small;">262,144</span></td> <td align="RIGHT" bgcolor="#3DEB3D" sdnum="3081;0;#,##0" sdval="524288"><span class="Apple-style-span" style="font-size: xx-small;">524,288</span></td> <td align="CENTER" bgcolor="#99CCFF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(512K x 8)</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="63488"><span class="Apple-style-span" style="font-size: xx-small;">63,488</span></td> <td align="CENTER" bgcolor="#99CCFF" sdnum="3081;" sdval="18"><span class="Apple-style-span" style="font-size: xx-small;">18</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="28"><span class="Apple-style-span" style="font-size: xx-small;">28</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="13824000"><span class="Apple-style-span" style="font-size: xx-small;">13,824,000</span></td> <td align="RIGHT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;">640 x 360</span></td> <td align="RIGHT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;">720 mode</span></td> <td align="LEFT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;"><br />
</span></td> </tr>
<tr> <td align="RIGHT" bgcolor="#99CCFF" height="17" sdnum="3081;" sdval="960"><span class="Apple-style-span" style="font-size: xx-small;">960</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;" sdval="540"><span class="Apple-style-span" style="font-size: xx-small;">540</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="518400"><span class="Apple-style-span" style="font-size: xx-small;">518,400</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="524288"><span class="Apple-style-span" style="font-size: xx-small;">524,288</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="1048576"><span class="Apple-style-span" style="font-size: xx-small;">1,048,576</span></td> <td align="CENTER" bgcolor="#99CCFF" sdnum="3081;0;#,##0"><span class="Apple-style-span" style="font-size: xx-small;">(1024K x 8)</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="11776"><span class="Apple-style-span" style="font-size: xx-small;">11,776</span></td> <td align="CENTER" bgcolor="#99CCFF" sdnum="3081;" sdval="19"><span class="Apple-style-span" style="font-size: xx-small;">19</span></td> <td align="CENTER" bgcolor="#3DEB3D" sdnum="3081;" sdval="29"><span class="Apple-style-span" style="font-size: xx-small;">29</span></td> <td align="RIGHT" bgcolor="#99CCFF" sdnum="3081;0;#,##0" sdval="31104000"><span class="Apple-style-span" style="font-size: xx-small;">31,104,000</span></td> <td align="RIGHT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;">960 x 540</span></td> <td align="RIGHT" bgcolor="#99CCFF"><span class="Apple-style-span" style="font-size: xx-small;">1080 mode</span></td> <td align="LEFT" bgcolor="#99CCFF"><br />
</td> </tr>
</tbody> </table><br />
I have computed the number of GPIO pins required to address one page of the framebuffer. For example, a video mode of 480x270 (Widescreen) consumes 230,400 bytes per page. Rounding up to the nearest power of 2 and multiplying by 2 (for 2 pages) requires a 512 KByte VRAM. In order to clear the screen at 60 fps, I need to be able to write 7,776,00 bytes per second. Now that is a lot of bandwidth for a 20Mhz 8-bit AVR.<br />
<br />
Can it be done? Well, at that resolution I would need 17 address pins per page + 8 pins for the data + 1 pin for SRAM Write/Enable + 1 pin for the page select. So I'd need 27 GPIO pins in total. That rules out the ATMega328 (Arduino). An ATMega164A might to the trick (<a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&name=ATMEGA164A-PU-ND">digikey.com.au</a>) as it has 32 GPIO pins. So I have enough pins but can I write to the memory fast enough to clear the screen?<br />
<br />
In order to test this I dug out my trust Arduino and ran some tests. Here is some sample code:<br />
<br />
<table style="background-color: #ffffcc;"><tbody>
<tr><td><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void loop() {</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> time = millis();</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> addr = 0;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> do {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>8);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>16);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> addr++;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> } </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> while (addr < 7776000);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> time = millis() - time;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> Serial.print("Time: ");</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> Serial.println(time);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span></td></tr>
</tbody></table><br />
This is supposed to simulate walking through a 18bit address space (17bits per page + page select). The idea is that this is basically what is required to clear a 480x270 area of an SRAM chip 60 times. This runs in 11.2 seconds. Now the chip is running at 16Mhz in this case, so on a 20Mhz setup the time would be more like 8.9 seconds but I'll stick to 16Mhz for now.<br />
<br />
11.2 seconds is far too slow. This needs to be less that 1 second in order to meet the constraint I set and ideally much less in order to allow some time to draw some other shapes! There are some things I can do here. I could unroll the loop a bit. Given that I'm clearing the screen to one colour I can safely unroll it as much as I like. This is speed/space trade-off though. Unrolling a loop uses more Flash but my whole Arduino sketch is on 2990 bytes right now and the target chip has 16Kbytes of Flash so I'm pretty safe. This is what the code looks like if I unroll the loop by a factor of 8:<br />
<br />
<br />
<br />
<table style="background-color: #ffffcc;"><tbody>
<tr><td valign="top"><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void loop() {</span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> time = millis();</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> addr = 0;</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> do {</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr);</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>8);</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>16);</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> addr++;</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr);</span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>8);</span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>16);</span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> addr++;</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"></span></span></span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr);</span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>8);</span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>16);</span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> addr++;</span></span></span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"></span></span></span></span></span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr);</span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>8);</span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>16);</span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> addr++;</span></span></span></span></span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"></span></span></span></span></span></span></span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr);</span></span></span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>8);</span></span></span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>16);</span></span></span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> addr++;</span></span></span></span></span></span></span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"></span></span></span></span></span></span></span></span></span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr);</span></span></span></span></span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>8);</span></span></span></span></span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>16);</span></span></span></span></span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> addr++;</span></span></span></span></span></span></span></span></span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"></span></span></span></span></span></span></span></span></span></span></span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr);</span></span></span></span></span></span></span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>8);</span></span></span></span></span></span></span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>16);</span></span></span></span></span></span></span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> addr++;</span></span></span></span></span></span></span></span></span></span></span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"></span></span></span></span></span></span></span></span></span></span></span></span></span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr);</span></span></span></span></span></span></span></span></span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>8);</span></span></span></span></span></span></span></span></span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> PORTC = (byte)(addr>>16);</span></span></span></span></span></span></span></span></span></span></span></span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> addr++;</span></span></span></span></span></span></span></span></span></span></span></span></span></span></div></div></div></div></div></div></div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> } </span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> while (addr < 7776000/8);</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> time = millis() - time;</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> Serial.print("Time: ");</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> Serial.println(time);</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span></div></td><td valign="top"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">40: sts 0x0000, r24</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">44: sts 0x0000, r25</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">48: ldi r18, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">4a: ldi r19, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">4c: ldi r20, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">4e: ldi r21, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">50: ldi r24, 0x01 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">52: ldi r25, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">54: ldi r26, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">56: ldi r27, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">58: std Y+9, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">5a: std Y+10, r25 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">5c: std Y+11, r26 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">5e: std Y+12, r27 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">60: ldi r24, 0x02 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">62: ldi r25, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">64: ldi r26, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">66: ldi r27, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">68: std Y+5, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">6a: std Y+6, r25 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">6c: std Y+7, r26 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">6e: std Y+8, r27 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">70: ldi r24, 0x03 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">72: ldi r25, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">74: ldi r26, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">76: ldi r27, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">78: std Y+1, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">7a: std Y+2, r25 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">7c: std Y+3, r26 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">7e: std Y+4, r27 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">80: ldi r16, 0x04 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">82: mov r2, r16</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">84: mov r3, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">86: mov r4, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">88: mov r5, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">8a: ldi r17, 0x05 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">8c: mov r6, r17</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">8e: mov r7, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">90: mov r8, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">92: mov r9, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">94: ldi r27, 0x06 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">96: mov r10, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">98: mov r11, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">9a: mov r12, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">9c: mov r13, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">9e: ldi r26, 0x07 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">a0: mov r14, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">a2: mov r15, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">a4: mov r16, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">a6: mov r17, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">a8: out 0x08, r18 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">aa: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">ac: mov r26, r21</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">ae: mov r25, r20</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">b0: mov r24, r19</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">b2: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">b4: movw r24, r20</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">b6: eor r26, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">b8: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">ba: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">bc: ldd r25, Y+9 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">be: out 0x08, r25 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">c0: ldd r24, Y+9 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">c2: ldd r25, Y+10 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">c4: ldd r26, Y+11 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">c6: ldd r27, Y+12 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">c8: mov r24, r25</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">ca: mov r25, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">cc: mov r26, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">ce: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">d0: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">d2: ldd r24, Y+9 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">d4: ldd r25, Y+10 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">d6: ldd r26, Y+11 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">d8: ldd r27, Y+12 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">da: movw r24, r26</span></td><td valign="top"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">dc: eor r26, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">de: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">e0: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">e2: ldd r25, Y+5 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">e4: out 0x08, r25 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">e6: ldd r24, Y+5 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">e8: ldd r25, Y+6 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">ea: ldd r26, Y+7 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">ec: ldd r27, Y+8 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">ee: mov r24, r25</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">f0: mov r25, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">f2: mov r26, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">f4: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">f6: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">f8: ldd r24, Y+5 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">fa: ldd r25, Y+6 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">fc: ldd r26, Y+7 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">fe: ldd r27, Y+8 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">100: movw r24, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">102: eor r26, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">104: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">106: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">108: ldd r25, Y+1 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">10a: out 0x08, r25 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">10c: ldd r24, Y+1 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">10e: ldd r25, Y+2 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">110: ldd r26, Y+3 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">112: ldd r27, Y+4 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">114: mov r24, r25</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">116: mov r25, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">118: mov r26, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">11a: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">11c: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">11e: ldd r24, Y+1 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">120: ldd r25, Y+2 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">122: ldd r26, Y+3 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">124: ldd r27, Y+4 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">126: movw r24, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">128: eor r26, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">12a: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">12c: std Y+13, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">12e: std Y+14, r25 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">130: std Y+15, r26 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">132: std Y+16, r27 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">134: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">136: out 0x08, r2 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">138: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">13a: mov r26, r5</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">13c: mov r25, r4</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">13e: mov r24, r3</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">140: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">142: movw r24, r4</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">144: eor r26, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">146: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">148: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">14a: out 0x08, r6 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">14c: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">14e: mov r26, r9</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">150: mov r25, r8</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">152: mov r24, r7</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">154: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">156: movw r24, r8</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">158: eor r26, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">15a: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">15c: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">15e: out 0x08, r10 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">160: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">162: mov r26, r13</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">164: mov r25, r12</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">166: mov r24, r11</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">168: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">16a: movw r24, r12</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">16c: eor r26, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">16e: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">170: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">172: out 0x08, r14</span></td><td valign="top"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">174: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">176: mov r26, r17</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">178: mov r25, r16</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">17a: mov r24, r15</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">17c: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">17e: movw r24, r16</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">180: eor r26, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">182: eor r27, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">184: out 0x08, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">186: subi r18, 0xF8 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">188: sbci r19, 0xFF </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">18a: sbci r20, 0xFF </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">18c: sbci r21, 0xFF </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">18e: ldd r24, Y+9 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">190: ldd r25, Y+10 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">192: ldd r26, Y+11 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">194: ldd r27, Y+12 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">196: adiw r24, 0x08 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">198: adc r26, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">19a: adc r27, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">19c: std Y+9, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">19e: std Y+10, r25 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1a0: std Y+11, r26 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1a2: std Y+12, r27 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1a4: ldd r24, Y+5 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1a6: ldd r25, Y+6 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1a8: ldd r26, Y+7 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1aa: ldd r27, Y+8 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1ac: adiw r24, 0x08 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1ae: adc r26, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1b0: adc r27, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1b2: std Y+5, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1b4: std Y+6, r25 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1b6: std Y+7, r26 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1b8: std Y+8, r27 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1ba: ldd r24, Y+1 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1bc: ldd r25, Y+2 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1be: ldd r26, Y+3 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1c0: ldd r27, Y+4 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1c2: adiw r24, 0x08 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1c4: adc r26, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1c6: adc r27, r1</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1c8: std Y+1, r24 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1ca: std Y+2, r25 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1cc: std Y+3, r26 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1ce: std Y+4, r27 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1d0: ldi r24, 0x08 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1d2: ldi r25, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1d4: ldi r26, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1d6: ldi r27, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1d8: add r2, r24</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1da: adc r3, r25</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1dc: adc r4, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1de: adc r5, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1e0: add r6, r24</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1e2: adc r7, r25</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1e4: adc r8, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1e6: adc r9, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1e8: add r10, r24</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1ea: adc r11, r25</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1ec: adc r12, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1ee: adc r13, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1f0: add r14, r24</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1f2: adc r15, r25</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1f4: adc r16, r26</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1f6: adc r17, r27</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1f8: cpi r18, 0xE0 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1fa: ldi r25, 0xD4 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1fc: cpc r19, r25</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">1fe: ldi r25, 0x0E </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">200: cpc r20, r25</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">202: ldi r25, 0x00 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">204: c</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">pc r21, r25</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">206: brcc .+0 </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">208: rjmp .+0 </span></td></tr>
</tbody></table><br />
<br />
The loop time is now 1.8 seconds. Wow. That really helped. I have included the assembly output where you can see the effect of the unrolling. This assembly covers the do() loop only. Unrolling to 16 pixels per loop yields 545 milliseconds. Now we are in business.<br />
<br />
I need to check these calculations. I seems unreal that an 8-bit micro can write 7.7 million bytes in 0.5 seconds. That is a bandwidth of 15.4 MiBytes/second on a 16Mhz part. Something must be wrong. I have certainly made a mistake somewhere...Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comtag:blogger.com,1999:blog-5352840725182809996.post-6026228403804283012011-05-04T06:26:00.000-07:002011-05-04T06:26:05.184-07:00New Project: uWasp<div class="separator" style="clear: both; text-align: center;"></div><div style="text-align: left;">Being somewhere north of 30 years of age, I grew up with 8-bit machines. I owned a Microbee 128K machine.</div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://small.gdlcdn.com/802C5F/static2/images/microbee-computer.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://small.gdlcdn.com/802C5F/static2/images/microbee-computer.jpg" /></a> </div><br />
I still have the machine actually. It was great. I was thinking about it recently when a friend was telling me about a C64 emulator he was writing. I was thinking that it would be great to create a new 8-bit machine out of modern components. It could probably be built very cheaply too! So anyway, I'm introducing project uWasp.<br />
<br />
Here is the idea. I want to do a new Z80-based machine (similar to the Microbee but not compatible) with modern features. Here is a list:<br />
<br />
<ul><li>EZ80 processor from Zilog</li>
<li>AVR-based peripheral sub-systems.</li>
<li>Video Framebuffer</li>
<li>VGA out</li>
<li>Stereo sound</li>
<li>USB keyboard</li>
</ul><div>There are two cool things with this project. Firstly the cost. I can get a EZ80 for $13 and a bunch of ATMega chips for $4 each. I can even get 512Kbyte SRAMs for $4 each! Secondly, the firmware of the AVRs is obviously upgradeable. This means I can implement a GPU(Video) and APU (Audio) on separate AVRs with upgradable features. For example, the in version 1 of the GPU I might implement a command called CLEAR_SCREEN which clears video RAM to a given value without any EZ80 involvement. Version 2 could add filled rectangles and Bit Blits. I guess the AVR chips are "Firmware Accelerators" :-)</div><div><br />
</div><div><br />
</div><div><br />
</div><div> </div><div><br />
</div><div><br />
</div>Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.comtag:blogger.com,1999:blog-5352840725182809996.post-30228187553694670402011-05-04T05:57:00.000-07:002011-05-04T05:57:55.639-07:00FinallyI have a great many project ideas in my head. I had better start writing them down...Mike Wrighthttp://www.blogger.com/profile/00588337013916179877noreply@blogger.com