Updated on 2022-04-21
Take advantage of the PlatformIO repository to easily add GFX to your projects
Note: This article does not introduce you to GFX. You can find the documentation for GFX here.
You can find a general guide and demo here, as well as drivers that aren't currently in PlatformIO's repository yet because I still need to do more work on them.
This article aims to acquaint you with using GFX from PlatformIO by way of its library import feature. With this feature, you no longer need to manually copy supporting files out of gfx_demo to use in your projects. Instead, you can simply reference the desired driver in your platformio.ini and the heavy lifting will be done by PlatformIO.
While GFX supports other platforms, the demo with this article was written for an ESP32.
The trick here is to edit your platformio.ini file:
[env:esp32-ssd1306]
platform = espressif32
board = node32s
framework = arduino
monitor_speed = 115200
upload_speed = 921600
lib_deps =
codewitch-honey-crisis/htcw_ssd1306
lib_ldf_mode = deep
build_unflags=-std=gnu++11
build_flags=-std=gnu++14
I'd like us to focus on the lines starting with lib_deps. That line tells PlatformIO to fetch the specified library and any dependencies. In this case, we're getting the latest version of the SSD1306 driver, which will also pull in GFX and the supporting bus I/O library. After that, we have lib_ldf_mode = deep. This is necessary so that PlatformIO finds the appropriate framework header files needed by GFX. Next, we have build_unflags and build_flags. These should be familiar if you've used GFX in your projects before. It changes the C++ standard from GNU C++11 which is the default to GNU C++14, which GFX requires in order to compile.
Once you do that, you can do something like this in your code:
// ensure the following is configured for your setup
#ifdef I2C // define I2C if using I2C. Otherwise defaults to SPI
#define LCD_PORT 0
#define PIN_NUM_SDA 21
#define PIN_NUM_SCL 22
#define PIN_NUM_RST -1
#define PIN_NUM_DC -1
#define LCD_WRITE_SPEED_PERCENT 800 // 800Khz
#define LCD_ADDRESS 0x3C
#else
#define LCD_HOST VSPI
#define PIN_NUM_CS 5
#define PIN_NUM_MOSI 23
#define PIN_NUM_MISO -1
#define PIN_NUM_CLK 18
#define PIN_NUM_DC 2
#define PIN_NUM_RST 4
#define LCD_ADDRESS 0
#define LCD_WRITE_SPEED_PERCENT 200 // 20Mhz
#endif
#define LCD_WIDTH 128
#define LCD_HEIGHT 64
//#define LCD_VDC_5
#if defined(LCD_VDC_5)
#define LCD_VDC_3_3 false
#else
#define LCD_VDC_3_3 true
#endif
// INCLUDE THE HEADERS:
#include <Arduino.h>
#include <tft_io.hpp>
#include <ssd1306.hpp>
#include <gfx_cpp14.hpp>
// IMPORT THE NAMESPACES:
using namespace arduino;
using namespace gfx;
// DECLARE THE BUS:
// bus setup is considerably simpler
// if we weren't defining the pins.
// you can use tft_i2c and tft_spi
// templates instead of the *_ex
// ones to use default pins
// the _ex ones aren't available on
// some platforms anyway.
#ifdef I2C
using bus_type = tft_i2c_ex<LCD_PORT,
PIN_NUM_SDA,
PIN_NUM_SCL>;
#else
using bus_type = tft_spi_ex<LCD_HOST,
PIN_NUM_CS,
PIN_NUM_MOSI,
PIN_NUM_MISO,
PIN_NUM_CLK,
SPI_MODE0,
false
// below is not needed since the SSD1306
// doesn't do async but this is boilerplate
#ifdef OPTIMIZE_DMA
,(LCD_WIDTH*LCD_HEIGHT)/8+8
#endif
>;
#endif
// DECLARE THE DRIVER:
using lcd_type = ssd1306<LCD_WIDTH,
LCD_HEIGHT,
bus_type,
0, // Rotation
4, // Dither 4-bit grayscale
LCD_ADDRESS,
LCD_VDC_3_3,
LCD_WRITE_SPEED_PERCENT,
PIN_NUM_DC,
PIN_NUM_RST,
true>;
// INSTANTIATE THE DRIVER:
lcd_type lcd;
// (Optional) DECLARE THE COLORS:
using lcd_color = color<typename
lcd_type::pixel_type>;
// You can now draw to lcd using draw:: like draw::filled_rectangle
The driver instantiation is slightly different for different device drivers due to them having different characteristics, and of course, your lib_deps entry in platformio.ini must reference the appropriate driver, but otherwise the code is the same for most any display. I have included an example of the 8-bit parallel bus in the example code but it's not shown in the excerpt above due to length and because the SSD1306 doesn't come in that configuration that I've seen at least.
There are drivers currently in the Platform IO repository as of this writing, with more added as I get the hardware:
See the platformio.ini for the lib_deps lines needed to include those drivers.
There are ESP-IDF drivers in gfx_demo as well but I am moving them to this repository as I get time, or possibly releasing them as ESP-IDF components. I have not decided yet.
The demo code was again, designed for an ESP32 and contains drawing code for several displays and configurations. You'll want to choose the configuration that matches your device.
config.hpp contains all the configuration information for the pins and drivers. It's a bit of a mess, but basically, it hides most of the differences between the different drivers.
The *.h files are jpg and font data used by the demo, embedded in program space flash.
main.cpp contains the primary drawing code. You'll note that it's largely the same for every device, with the exception of wildly different displays like the MAX7219 and the PWM controllers.