In this guide we show how to use the Adafruit_GFX library to renderer menu items with tcMenu. This rendering driver for Adafruit_GFX is built into the core menu designer download, meaning it’s available out of the box.
The Adafruit_GFX library supports a lot of different displays, with very different capabilities. Some are monochrome with an in-memory buffer; whereas others are high resolution colour displays that are not buffered in memory. In order to make our renderer as generic as possible it supports both of these capabilities through configuration. It’s worth reading this guide fully so that you understand how we manage the various capabilities.
Before proceeding, you’ll need to make sure you’ve installed both the Adafruit_GFX core library and the library that is compatible with your display. Also, I’d recommend taking a read through the Adafruit_GFX library documentation if you’re not familiar with the library already. We’ll also assume you’ve got a menu structure already prepared in the menu designer UI.
Related documentation:
First, ensure your menu structure is saved and then choose Code -> Generate Code from the menu. Once the code generation dialog appears, you can change the display renderer by clicking on the image to the left of the renderer.
There are two possibilities for Adafruit_GFX based displays, the first and easiest is the “quick start” option, it supports a few common displays (ST7735, ST7789, ILI9341 and Nokia 5110), it creates all the variables and initialises the display for you. We’ll refer to this option as quick start.
If you need full control over the display variable, and all the configuration options, then you choose the “Manual Declaration” option, in which case you prepare the variable yourself, and just tell tcMenu the name and type of variable you’ve created. We’ll refer to this as “Manual Configuration”.
If you choose quick start, then the code generator will create the variable, and initialise the display on your behalf. It is obviously far less configurable than manual option, but easier for a few select display. It looks like there are more options than for the manual case, but that is because we will create everything on your behalf.
The graphics variable that the generator will generate on your behalf, it will be exported with this name to use in your own code.
We support only a few displays with this quick start method, if your display is not listed, use the manual configuration option instead. Select the appropriate display driver for your hardware. Supported quick start displays:
Set these to the hardware width and height of your display
You can configure a reset pin if your display requires it. Either set to a pin value or -1 for none.
Set this to the chip select (CS) pin for the display. All displays in this category need this.
Set this to the pin for Register select or Data/Command. All displays in this category need this.
Only set these two pins to a value other than -1 if you want to use software SPI. This is much slower than hardware SPI, so do not use on bigger displays.
You can specify the initial rotation of the display as a value from 0 to 3.
How many times the menu structure should be scanned for changes and redrawn if needed. TcMenu tries to minimise redraws where reasonably possible.
When you choose the manual configuration option, you need to create the display variable in your sketch, and make sure it is fully initialised before calling setupMenu
in your sketch.
In this case you simply create a global variable in your sketch that creates the graphics object. You make sure that the library has been initialised before calling setupMenu() in your sketch. Set this value to the name of the global variable.
There are many types of display supported by this library, therefore you just provide the variable type that you declared. For example Adafruit_SSD1306.
Indicates if this display uses memory buffering. Often, mono displays are memory buffered. For example Nokia 5110 and SSD1306 are memory buffered. When displays are memory buffered, the library will then call display()
after each rendering change.
How many times the menu structure should be scanned for changes and redrawn if needed. TcMenu tries to minimise redraws where reasonably possible.
Each of the display drivers shown below is fully tested with every release of tcMenu. Many other displays will probably work with this renderer, but we’ve not got one to hand to test.
The library for this display is both memory buffered and monochrome. There is a complete example menu packaged with the core tcMenu library. This example was tested on MEGA / AVR with a UipEthernet remote. However, the concepts are generally applicable. Link below takes you to the source on github.
[https://github.com/TcMenu/tcMenuLib/tree/main/examples/nokia5110]
The library for this display is both memory buffered and monochrome. Again there is a complete example menu packaged with tcMenu. This example was tested on both ESP32 and ESP8266, but the concepts are generally applicable to any processor. Link below takes you to the source on github.
[https://github.com/TcMenu/tcMenuLib/tree/main/examples/esp8266WifiOled]
Both ILI9341 and ST7735 are high resolution, color displays with built in memory. Therefore, these display libraries are unbuffered on the Arduino side. In order to improve performance where memory allows we support drawing menu items into a 2-bit (4 color) area first in RAM, then using a high performance blit function to transfer the data. Using this buffer the performance is excellent.
There are some additional classes and functions available within our plugin that you can use yourself, these are how we improve drawing performance very significantly, they are available to you as well. But first we need to understand that all of the performance increase is down to RAM buffering (IE drawing into a canvas object first). We support two canvas types, the built in GFXcanvas1
that is directly available in the library, or our extension TcGFXcanvas2
that provides two bits per pixel (or 4 colors from 0..3).
We have two drawing functions that can take the buffers that back the canvas and present it optimally, we’ve optimized them as much as we can, they both perform quite well, but working with TcGFXcanvas2
being the most tested overall. These “CookieCut” functions allow you cut a range of bitmap data out of a larger bitmap area. Our canvas extension works just like the other canvas objects that are built in.
Once you have drawn to a canvas, you now need to push to the display, for single bit (fgColor/bgColor) drawing, there is drawCookieCutBitmap
where you provide the graphics, x, and y of the destination area, then the bitmap obtained from getBuffer()
on the canvas followed by the width and height, then the total width of the bitmap, this is followed by the x and y starting location inside the bitmap and the foreground and background color.
void drawCookieCutBitmap(Adafruit_SPITFT* gfx, int16_t x, int16_t y,
const uint8_t *bitmap, int16_t w, int16_t h,
int16_t totalWidth, int16_t xStart, int16_t yStart,
uint16_t fgColor, uint16_t bgColor);
Next, for 2-bit per pixel drawing, there drawCookieCutBitmap2bpp
that does exactly the same as above, but with a color palette, which you pass instead of the foreground and background.
void drawCookieCutBitmap2bpp(Adafruit_SPITFT* gfx, int16_t x, int16_t y,
const uint8_t *bitmap, int16_t w, int16_t h,
int16_t totalWidth, int16_t xStart, int16_t yStart,
const uint16_t* palette);
We have many examples that use Adafruit displays packaged in the examples folder within tcMenu. We test TFTs on a very wide range of boards.