The standard Adafruit_GFX_Library graphics code will compile and run for an Artemis board as-is, but the resulting performance is so slow as to be practically unusable (See this post: viewtopic.php?f=169&t=51831). What follows are instructions to create a high-performance version of the GFX library optimized for an Apollo3 processor.
Starting with a bit of background, the GFX library was originally developed with the following assumptions:
The performance enhancements for Apollo3 are mostly based on maximizing the number of bytes sent in an SPI transfer. Since the Apollo3 has a relatively high SPI transfer setup cost, it is far more efficient to perform 1 SPI transfer of N bytes than the default GFX approach of performing N SPI transfers of 1 byte. To avoid triggering the bug mentioned above, all Apollo3 transfers in the library are converted to be unidirectional.
The process to create an optimized Apollo3 GFX library will assume that you have already installed the Adafruit_GFX_Library version 1.9.0, which is the latest version of the released library at the time of this writing.
It is not a good idea to make source code changes directly to an installed Arduino GFX library. Those changes would get overwritten every time the Arduino system updated the GFX library. The workaround is to create an Apollo3-specific version of the GFX library. This new version of the GFX library will live beside the standard GFX library and will be used for Apollo3 builds only. For example, if you use the same Arduino installation to create AVR or SAMD builds for a different project that also uses the GFX library, those builds will continue to use the standard GFX library. The downside of this approach is that the new Apollo3-specific library will be stuck at the version where it was created. However, the apollo3 changes are almost certainly easily merged back into updated source files.
To make the Apollo3-specific GFX library, perform the following steps:
The original library will remain untouched by anything that follows. Changes will only be made to the files in the new ‘Adafruit_GFX_Library_apollo3’ folder!
I am not able to attach the source files this post, so I have them set up here as downloadable google drive links:
Multiple libraries were found for "Adafruit_GFX.h"
Used: C:\<somepath>\Arduino\libraries\Adafruit_GFX_Library_apollo3
Not used: C:\<somepath>\Arduino\libraries\Adafruit_GFX_Library
This indicates that the change to the apollo3 version of the library.properties file was recognized by the Arduino build system.
Upload the result and your GFX operations should run nice and fast now. If not, check where you put the library, check that it got named properly, check that you made the right change to the library.properties file, and make sure that your Adafruit_SPITFT.cpp file has some references to ‘apollo3’ inside it.
Results: My measurements show that with the original library, erasing a full 240x320 display would take 2.34 seconds. Copying a full 240x320 big-endian bitmap (153,600 bytes of data) was slightly worse at 2.38 seconds. With the apollo3 optimizations included, both an erase or a full-screen bitmap copy take under 57 milliseconds, or about 42 times faster. Side note: I like that the Artemis has no trouble swallowing a 153K test bitmap into its flash.
Testing: These replacement SPITFT files are only guaranteed to work with GFX library version 1.9.0. The resulting library has been tested with with 1.44" 128x128 color displays using an ST7735 controller, and 2.8" 320x240 color displays using an ILI9341 controller. However, any display supported by the standard GFX library should work fine.
Further Reading: If you are interested looking at the changes, edit the new Adafruit_SPITFT.cpp and search for all instances of ‘apollo3’. I also made a change to drawRGBBitmap(), which is the routine that copies memory-resident data from flash or RAM directly to the display. The original version always assumes that the data being copied is little-endian. The new version allows you to choose. If you create your memory-resident bitmap data in big-endian format, the new version of drawRGBBitmap() will allow you to skip the endian conversion process that would otherwise occur every single time you drew the bitmap.
What is still sub-optimal: drawing anything based on lots of individual pixels, like lines or circles or complex proportional fonts. Pixel writing times have been sped up by a factor of about two, but performing all the pixel operations to get the dots in a potentially large, complex font character onto the display just plain adds up. Even after the Apollo3 mods, writing an individual pixel to the display still requires sending something like 13 bytes. This might not be too bad except that those 13 bytes require 6 distinct SPI transfers (if memory serves). If pixel update rates matter to you, you might consider doing all your drawing using a RAM-based GFXcanvas16 object. With a canvas object, all the pixel operations turn into RAM writes which are quite fast compared to SPI transfer operations. Once all the updates are done, you can blast the whole canvas over as one massive screen update using drawRGBBitmap() since the redraw time is only 56 milliseconds regardless of how many pixels changed state. It might be worth considering if you are trying to perform a lot of complicated pixel operations and need a faster display update. The downside is that a GFXcanvas16 object for a 240x320 16-bit color display will use nearly 154K of SRAM. On most other little processors, that would be a total joke. On an Apollo3, it’s a choice.