Electronic – Efficient display of simple text/graphics on color LCD by ARM

armlcd

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?

Edit

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.

Best Answer

The problem with using a microcontroller to drive an LCD is that an LCD requires constant attention. This can be mitigated with a CPLD driven over SPI (using DMA, of course), but then you run into the other problem: Color LCDs require a lot of data. 320x240 in black and white is marginal at 9.6KB, but make it 24 bit color and suddenly you need to deliver 230KB of data in 1/60th of a second. (Don't forget, though, that you can get 4-bit, 16-color control just by tieing the low 20 bits to one setting). A 24-bit frame buffer no longer fits in onboard RAM on most microcontrollers, and you probably don't have time to read from an external RAM chip, clock the data out, and still do other processing. Trying to do this with a CPLD (or an FPGA) and a RAM chip gets you well over the $2 price that caused you to balk in your question.

The traditional solution to interfacing a microcontroller with a color LCD is a display controller like an SSD1963. Here's a very simple block diagram:

MCU to RAM buffer and registers, and thence to LCD interface

Parallel input to a big RAM frame buffer (Translation: More than $2) interfaced with a register-configurable parallel LCD interface. The parallel input is usually compatible with a memory bus interface.

The color LCD market is not always easy to find on the web, usually being the domain of OEMs only, with the rest buying displays from companies who integrate the controller with the display. The best resource I've found has been Crystal Fontz, specifically this page on choosing graphic LCDs. Scroll to the bottom for the controllers, which include the following options (note: Not all are color controllers):

  • Epson S1D13521B01 E Ink Broadsheet (1 module)
  • Epson S1D13700 (11 modules)
  • Epson SED1520 Compatible (8 modules)
  • Himax HX8345 Compatible (1 module)
  • ILITek ILI9325 Compatible (3 modules)
  • KS0107/KS0108 Compatible (26 modules)
  • Novatek NT7534 (14 modules)
  • Orise Technology OTM2201A (1 module)
  • Orise Technology SPFD5420A (1 module)
  • RAiO RA8835 (1 module)
  • Sanyo LC7981 (13 modules)
  • Sino Wealth SH1101A (2 modules)
  • Sitronix ST7920 (29 modules)
  • Solomon SSD1303 (1 module)
  • Solomon SSD1305 (9 modules)
  • Solomon SSD1325 (2 modules)
  • Solomon SSD1332 (1 module)
  • Solomon SSD2119 (2 modules)
  • ST STV8105 (1 module)
  • Toshiba T6963 (23 modules)