A Generic Optimized 16-bit LCD Adaptor for the Arduino. Part 3 - Optimization and Driver Configurations

Part 1 - Schematic
Part 2 - Software

Optimising the line drawing algorithm

The first versions of my driver code featured the Extremely Fast Line Drawing Algorithm (EFLA). It seemed to perform well and so I didn’t turn my attention to optimising it.

Recently however, I was tipped off that the EFLA was suboptimal on an MCU without an intrinsic divide instruction and that the classic Bresenham would probably be be better. Time for some profiling. I implemented the Bresenham algorithm using the pseudo-code in the Wikipedia article under the Simplification header.

My pseudo-random line drawing example code runs over a fixed 5 second period. These are the timings that I got on an ILI9325 panel in 64K colours and portrait mode: EFLA -1055, Bresenham - 1110.

Sure enough Bresenham is slightly faster. Not much, but enough to get me thinking about whether it could be further optimised for this library. In producing an optimised implementation we rely on some basic facts:

  1. All the pixels in the line are the same colour.
  2. The panels provide ‘windowed’ output with auto-increment in the X-direction.
  3. The panels allow X and Y positions to be changed independently.

Here’s the resulting code.

The algorithm should be recognisable from the Wikipedia article. I initially set a window that extends from the first point to the far right and bottom of the panel. This means that in cases where two horizontal pixels have to be written out together I can omit the cursor movement entirely because the panel has done it automatically for me.

When I do have to move the cursor I am careful to only move it in the horizontal or vertical direction that’s required.

Running the line demo with this optimised implementation results in a score of 2060 lines, a solid 85% speed increase for very little effort. Here’s a chart showing the final scores:

The actual speed increase obtained is variable and the flatter the line the better the increase. My demo draws pseudo-random lines so the speed increase that I quote could be viewed as an average (Figure 11).

Line Drawing Algorithms compare
Figure 11. The actual speed increase obtained is variable and the flatter the line the better the increase.

Now that I have a solid pair of access modes I can move on to the driver templates that call upon their services to perform primitive operations.

ILI9325

The ILI9325 is a very common QVGA controller found in many of the standalone panels that you see on the market as well as in panels that ship with MCU development boards (Figure 12). The ILI9325 panel that I have came packed with an STM32 development board, but there’s nothing to stop me detaching it and hooking it up to the Arduino as I’ve done here.

I’ve provided support for portrait and landscape orientations in the 64K (16-bit) colour mode. Hardware scrolling is supported in both orientations. To use the driver you need to include the header file.

#include "Generic16BitILI9325.h"

Typedefs are provided for all combinations of orientations and access modes. In all my examples I declare a panel using code similar to this:

typedef ILI9325_Landscape_64K_Gpio16Latch TftPanel;  //typedef ILI9325_Portrait_64K_Gpio16Latch TftPanel;  //typedef ILI9325_Landscape_64K_Xmem16 TftPanel;  //typedef ILI9325_Portrait_64K_Xmem16 TftPanel;  //TftPanel *tft=new TftPanel;

The commented out drivers are provided for reference. The first two are GPIO access modes and the last two are the XMEM modes.

A very common QVGA controller ILI9325 is  found in many of the standalone TFT panels.
Figure 12. A very common QVGA controller ILI9325 is  found in many of the standalone TFT panels.

Version 3.0.0 and above of the xmemtft library provides support for the ILI9325 and includes a suite of demos that you can use to get started. Here’s a video that shows the graphics library demo in action using the optimised GPIO driver.

ILI9327

The ILI9327 controller provides a resolution of up to 432×240 pixels. This controller is not quite as common as the QVGA devices that you see everywhere (Figure 13).

The panel that I have is 400×240, 32 pixels fewer than the maximum available to the driver. The driver implements this by making the first 32 pixels invisible. That is, you can write to them but nothing will appear on the screen. I cater for this quirk with a ‘traits’ class provided as a parameter to the driver template.

I’ve provided support for portrait and landscape orientations in the 64K (16-bit) colour mode. Hardware scrolling is supported in both orientations. To use the driver you need to include the header file.

#include "Generic16BitILI9327.h"

Typedefs are provided for all combinations of orientations and access modes. In all my examples I declare a panel using code similar to this:

typedef ILI9327_400x240_Landscape_64K_Gpio16Latch TftPanel;  //typedef ILI9327_400x240_Portrait_64K_Gpio16Latch TftPanel;  //typedef ILI9327_400x240_Landscape_64K_Xmem16 TftPanel;  //typedef ILI9327_400x240_Portrait_64K_Xmem16 TftPanel;  //TftPanel *tft=new TftPanel;

The commented out drivers are provided for reference. The first two are GPIO access modes and the last two are the XMEM modes.

TFT Panel  that I have is 400×240 with QVGA controller ILI9327.
Figure 13. TFT Panel  that I have is 400×240 with QVGA controller ILI9327.

Version 3.0.0 and above of the xmemtft library provides support for the ILI9327 and includes a suite of demos that you can use to get started. Here’s a video that shows the graphics library demo in action using the optimised GPIO driver.

ILI9481

The ILI9481 controller from Ilitek is a 480×320 (HVGA) controller that is less commonly found in panels that you can get on ebay. There are four times as many pixels on an HVGA panel as there are on a QVGA panel so it was interesting to see how the graphics driver performs on this panel (Figure 14).

I’ve provided support for portrait and landscape orientations in the 64K (16-bit) colour mode. Hardware scrolling is supported in both orientations. To use the driver you need to include the header file.

#include "Generic16BitILI9481.h"

Typedefs are provided for all combinations of orientations and access modes. In all my examples I declare a panel using code similar to this:

typedef ILI9481_Landscape_64K_Gpio16Latch TftPanel;  //typedef ILI9481_Portrait_64K_Gpio16Latch TftPanel;  //typedef ILI9481_Landscape_64K_Xmem16 TftPanel;  //typedef ILI9481_Portrait_64K_Xmem16 TftPanel;  //TftPanel *tft=new TftPanel;

The commented out drivers are provided for reference. The first two are GPIO access modes and the last two are the XMEM modes.

TFT Panel  that I have is 480×320 with HVGA controller ILI9481.
Figure 14. TFT Panel  that I have is 480×320 with HVGA controller ILI9481.

Version 3.0.0 and above of the xmemtft library provides support for the ILI9481 and includes a suite of demos that you can use to get started. Here’s a video that shows the graphics library demo in action using the optimised GPIO driver. I was pleased to see that the operations that make most use of optimised fill algorithm, for example the gradient and clear screen demos, perform extremely quickly.

HX8347A

The HX8347A controller from Himax is a 320×240 (QVGA) device commonly featured in the LCD boards that you can get on ebay (Figure 15).

I’ve provided support for portrait and landscape orientations in the 64K (16-bit) colour mode. Hardware scrolling is supported in both orientations. To use the driver you need to include the header file.

#include "Generic16BitHX8347A.h"

Typedefs are provided for all combinations of orientations and access modes. In all my examples I declare a panel using code similar to this:

typedef HX8347A_Landscape_64K_Gpio16Latch TftPanel;  //typedef HX8347A_Portrait_64K_Gpio16Latch TftPanel;  //typedef HX8347A_Landscape_64K_Xmem16 TftPanel;  //typedef HX8347A_Portrait_64K_Xmem16 TftPanel;  //TftPanel *tft=new TftPanel;

The commented out drivers are provided for reference. The first two are GPIO access modes and the last two are the XMEM modes.

TFT Panel  that I have is 320×240 with QVGA controller HX8347A.
Figure 15. TFT Panel  that I have is 320×240 with QVGA controller HX8347A.

Version 3.0.0 and above of the xmemtft library provides support for the HX8347A and includes a suite of demos that you can use to get started. Here’s a video that shows the graphics library demo in action using the optimised GPIO driver.

Downloads

Source Code - download

andybrown.me.uk