circuitcellar.com
Magazine Support   Digital Library   Products & Services   Suppliers Directory 
 
 





 

Issue 158 September 2003
The XY-Plotter
Drive High-Resolution LCDs For Less
Mad Dash for Flash Cash Contest Winner


OPTIMIZATION TIPS

Optimizing the firmware’s cycle count requires a huge effort. For instance, one of its basic tasks is to send N pulses to the LCD’s nibble clock input. A loop already needs five cycles to do this, but remember that you have time for less than seven instructions per nibble, and the firmware has more to do than simply send clock pulses! So, you’ll need additional optimization techniques like code expansion and the calculated goto procedure (see Listing 1).

Listing 1—I used this coding technique to meet the strict timing requirements of the project. The routine sends a configurable number of pulses to the LCD clock input with less than three PIC instructions per pulse on average! Try to do it with a classic loop.

I used the calculated goto technique extensively. Basically, I was manually unrolling the code like an optimized compiler does (or tries to do). For instance, I used a long calculated goto table to select the specific line-generation algorithm for each column in the display (e.g., graduations, plain line, ordinary curve column, etc.). The result is a strange assembly listing to read but an interesting one to write!

Another tip is to copy, at startup, the combined pixel table from flash memory and paste it in RAM. An indirect access to RAM is quicker than a table read from flash memory.

MEMORY REQUIREMENTS

The aforementioned firmware optimizations are memory hungry. Fortunately, with 32 KB of flash memory it’s not an issue. My firmware currently uses only 10 KB.

I used the PIC18F252’s entire RAM. Three pages at 256 bytes each were used to store the respective minimum, maximum, and sampled y value for each x value. One page was devoted to the storage of the ASCII text, although only 90 bytes were actually needed. One last 256-byte page was used to store the bitmap patterns. That left 256 bytes for general-purpose variables. All in all, that’s 1536 bytes. 

DEVELOPMENT PROCESS

The project was developed with the MPLAB environment and simulator. I also used Microchip’s boot loader firmware (AN851) to burn flash memory, which is an interesting feature even if firmware improvements are welcome. In particular, no on-chip debug facility is currently provided (e.g., breakpoints), but I’m sure they’ll be in the next version.

Also note that the AN851 boot loader doesn’t provide an automatic reentry facility. As soon as an application firmware is downloaded and activated, there’s no way to reactivate the bootloader without specific user-supplied application code (like simultaneously pressing the three keys at power-up). This is well documented in the literature but more secure solutions exist (e.g., timeout).

I wasn’t lucky enough to have a full-featured ICE for the processor, so I wanted to avoid hundreds of burn and test cycles. I started by developing the critical code (e.g., the pixel generation algorithm) on a PC in C—just to validate the algorithm itself. Then, I developed the full firmware with MPLAB, keeping a structured approach to facilitate the validation.

Later, I implemented a bottom-up approach. I simulated 100% of the software with small stub routines in an effort to execute each routine individually. Note that I was still using MPLAB and didn’t have a target system at that point. I even kept a source listing and ticked all of the assembly lines to be sure to go across each of them.

I used the MPLAB stopwatch to verify the timings. When everything seemed fine under the simulation framework, I went to the target processor. That approach proved successful. My first burned firmware was not free from bugs, but I got a working display with the first burned file!

The RS-232 helped a great deal during the final debugging steps. In fact, rather than having to develop a specific protocol for each project, I used an easy and powerful method.

First, the UART firmware dumps the RAM’s content on the RS-232 port per the host’s request. Following this, software on the PC side is able to grab interesting information based on the RAM content (e.g., rebuilding something like a screen hard copy). But the most interesting point is that the same feature is invaluable during the debugging steps!