When designing an ARM-based device that should display simple graphics on a color LCD, how should one best go about designing things to allow fast updates, preferably without being tied to a particular ARM or LCD vendor? My current project uses a black-and-white display which can be driven lightning-fast by a the SPI port on a PIC (redrawing a complex display in 1/60 second). It seems common color LCD displays have an SPI port, but even filling a 160×120 LCD with a solid color would take 30ms, and a 320×240 would take 120ms best-case (10MHz shift clock).
If one could spare the controller pins, parallel mode could be better, but I don't know of any family-independent means of hooking up the parallel interface without requiring three separate memory-store instructions for each pixel (one to set the data, one to set the clock output high, and one to clock it low). Some ARM chips have memory-bus interfaces, but those often want to do things like multiplex address and data, or commit a lot of pins to outputting irrelevant address bits (the LCD would just need one address bit).
Looking at the ILI9320 by ILITEK, or the HD66789 by Renesas, one approach that would seem interesting would be to use a CPLD to convert SPI to parallel data, and include a mode which would output a pixel per bit. Looking at the Renesas data sheet, it might be possible to get pixel-per-bit writes with minimal hardware (no CPLD required) by making all the parallel-port data bits track the serial-data pin, using serial mode for everything but pixel writes, and using the compare/mask functions so that either all-zeroes pixels would be transparent and all-ones pixels would set selected bits in GRAM, or all-ones pixels would be transparent and all-zeroes pixels would clear selected bits. The "features" section of the IKITEK data sheet suggests that it has similar functionality, but the register maps don't seem to include the appropriate registers (most of the appropriate register addresses don't appear in the IKITEK, but one of them–register 4, is used for a different purpose).
Assuming the code will mainly be showing solid-color text and graphics, the ideal approach would seem to be to use a CPLD to interface the ARM's SPI port to the display's parallel port, and allow the CPLD to be loaded with foreground/background colors. This would be especially nice if one had a means of writing "transparent" pixels. Given a font as a two-color bitmap, one could simply load the font data directly into the SPI port; this would allow font data to be shown at a rate of one pixel every two ARM clocks. On the other hand, a CPLD sufficient to handle such a display-control task would cost about $2.
What's the best way to interface an ARM with a color LCD, if the objective is to mainly to show solid-color text or simple (e.g. 16-color or 64-color) graphics?
I've done many LCD display projects, with many types of LCDs, including character-mode LCDs, custom 3:1 multiplexed segment-based using my own drive method, black and white graphic LCDs with built-in controllers, and black-and-white LCDs for which I designed my own CPLD-based controller to interface with a microcontroller's general-purpose DMA (providing four-level grayscale even). I pride myself on making displays zippy. One of the graphic controllers was a bit of a dog that required about 1/10 second for a full screen refresh even when writing constant data, but most of my displays can render even a fairly complex image in under 1/50 second.
Many of the projects I do are battery-powered, so current draw is an issue. The DMA-based display controller I did worked nicely, but it was for a line-powered project. I believe the only way to get reasonable current draw from a graphics LCD is to use a controller which combines the display buffer and the column drivers. Sending lots of display between chips every frame would waste a lot of energy even on a single bit-per-pixel display; on a color display with sixteen bits per pixel, it would be far worse.
I've only started looking at color LCD data sheets; many displays seem to use a controller similar to the ILITEK ILI9320, though all of the data sheets I've found for controllers based on that general design have been marked "preliminary". Some like the ILITEK one claim to have masking and transparency features but don't list any registers for them; I don't know whether the real chips have such features but the "preliminary" data sheets neglected to include them, or whether they omitted the features but forgot to strike the mention of them. If in practice all such chips have transparency features, it would seem reasonable to design for them; if not, not.
I would expect that for most projects a typical screen would consist of arbitrarily-placed text in moderate number of arbitrarily-sized solid-color fonts. Fonts would most likely be stored as bit-per-pixel data. Using a Cortex-M3, if I wanted to write the display with parallel data, the code's "inner loop" to write two pixels would probably end up something like:
rol r0,r0,#2 ; Get one bit in C, the other in N itcs strhcs r1,[r3,#DATA_OFS] ; Write data strhcc r2,[r3,#DATA_OFS] ; Write data strb r4,[r3,#CLOCK_SET_OFS] ; Set clock high strb r4,[r3,#CLOCK_CLR_OFS] ; Set clock low itmi strhmi r1,[r3,#DATA_OFS] ; Write data strhpl r2,[r3,#DATA_OFS] ; Write data strb r4,[r3,#CLOCK_SET_OFS] ; Set clock high strb r4,[r3,#CLOCK_CLR_OFS] ; Set clock low
Not exactly the fastest thing in the world. Eliminating the writes to the set/clear clock instructions would help. My guess would be that there's no nice architecture-independent way to eliminate both clock writes, but there may be a pretty common way that would allow for eliminating one (e.g. many chips may have a counter/PWM that could be made to pulse an output briefly in response to a single memory store operation).
Using the SPI port and adding hardware to clock one pixel per bit would greatly speed up display access. If using a display without masking and transparency, the CPLD would have to include an address counter, and for each pixel either clock a word of pixel data or else a set-address command for the following pixel's position (for which it would need a counter). By contrast, if a display had masking and transparency, all I would need to do would be to have the CPLD support a mode where after it had clocked in 16 bits, each additional bit would clock a word of data out to the display with the LSB tracking the SDI pin (it might not even be necessary to use a CPLD–just a few normal logic chips). I would set the transparency color to the be color I want to write but with the LSB flipped.
I don't want to come up with a beautiful design that relies upon masking and transparency and then discover that the only displays with such features have a 30-week lead time. On the other hand, if such displays are apt to be and remain widely available from many vendors, I don't want to let paranoia about availability drive me to use an inferior design.