GC9A01A Round Display Adafruit Example

This example is the classic Adafruit graphics demo for the GC9A01A round TFT display. It initializes the display over SPI, runs several drawing benchmarks, prints the timing results to Serial, and then keeps rotating a text demo so you can confirm that your screen is wired and configured correctly.

The GC9A01A is a very common 240×240 round SPI TFT controller used in circular displays. If you have one of those popular round modules and want a quick way to test colours, text rendering, shapes, and rotation, this example is one of the best first sketches to try.

What this sketch does

This example is not meant to be a real application UI. It is mainly a display test and benchmark.

It does a few useful things:

  • Initializes the GC9A01A display
  • Enables the backlight if a backlight pin is defined
  • Draws text in different colours and sizes
  • Draws lines, rectangles, circles, triangles, and rounded rectangles
  • Measures how long each graphics test takes
  • Prints the timings to the Serial Monitor
  • Rotates the display through all 4 orientations in the loop()

In other words, it is a quick way to check that your display is alive, your SPI wiring works, and the library is talking properly to the panel.

Libraries used

The sketch uses three libraries:

  • SPI.h
  • Adafruit_GFX.h
  • Adafruit_GC9A01A.h

Adafruit_GFX is the general graphics library that provides text and shape drawing functions.

Adafruit_GC9A01A is the display-specific driver for the GC9A01A controller.

Install both Adafruit libraries from the Arduino Library Manager before compiling.

Typical ESP32 wiring for a GC9A01A display

The example code includes pin definitions for a Seeed XIAO RP2040 round display setup, but on an ESP32 you will usually want your own pin mapping.

A common hardware SPI wiring example for ESP32 is:

  • VCC3.3V
  • GNDGND
  • SCL / CLKGPIO18
  • SDA / MOSIGPIO23
  • CSGPIO5
  • DCGPIO27
  • RSTEN or a spare GPIO, depending on module
  • BL3.3V or a spare GPIO if you want software backlight control

If you want to adapt the sketch for a typical ESP32, the pin definitions would often look like this:

#define TFT_DC 27
#define TFT_CS 5
#define TFT_BL 4

Then the display object stays the same:

Adafruit_GC9A01A tft(TFT_CS, TFT_DC);

This constructor uses hardware SPI, which is the fast and correct choice for this kind of display.

How the sketch works

Pin selection

At the top of the file, the sketch checks whether it is being compiled for a specific board:

#if defined(ARDUINO_SEEED_XIAO_RP2040)

If that board is detected, it uses the pin mapping for the Seeed round display setup.

Otherwise, it falls back to generic pin definitions:

#define TFT_DC  9
#define TFT_CS 10

That means on most ESP32 boards, you will need to edit these pins.

Display object creation

This line creates the TFT object:

Adafruit_GC9A01A tft(TFT_CS, TFT_DC);

This tells the library which chip select and data/command pins are used. The actual SPI clock and MOSI pins come from the board’s hardware SPI pins.

setup()

The setup() function does all the initialization and benchmarking.

First it opens Serial:

Serial.begin(9600);
Serial.println("GC9A01A Test!");

Then it initializes the display:

tft.begin();

If a backlight pin exists, it turns it on:

pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, HIGH);

After that, the sketch runs each graphics benchmark one by one and prints the execution time in microseconds.

For example:

Serial.print(F("Screen fill              "));
Serial.println(testFillScreen());

So when you open the Serial Monitor, you will see timing values for each drawing test.

What each test function does

testFillScreen()

This fills the entire display with several colours:

  • Black
  • Red
  • Green
  • Blue
  • Black again

It is a simple way to verify that the whole panel updates correctly and that the colour order is right.

testText()

This demonstrates text rendering with different:

  • Colours
  • Sizes
  • Numeric formats
  • Line spacing

It writes some sample text, including the famous Adafruit nonsense phrase:

  • “Groop”
  • “I implore thee…”
  • and the rest of the classic demo text

This part is useful for checking font scaling and readability.

testLines()

This draws lines from each corner of the display toward the opposite edges.

It creates a starburst-style pattern and stresses the line drawing routine.

testFastLines()

This draws many horizontal and vertical lines using:

  • drawFastHLine()
  • drawFastVLine()

These are optimized functions and are faster than drawing generic lines one by one.

testRects()

This draws rectangle outlines centered on the screen, growing outward.

It shows how quickly the display can render repeated box shapes.

testFilledRects()

This draws filled rectangles, again centered on the screen.

Filled shapes move much more data than outlines, so this is a better stress test for screen throughput.

testFilledCircles()

This fills the screen area with solid circles laid out in a grid.

It is a nice demonstration of shape fill performance.

testCircles()

This draws circle outlines across the screen.

Unlike the filled-circle test, this focuses on edge drawing rather than block filling.

testTriangles()

This draws triangle outlines centered on the screen, growing larger in a loop.

Each triangle uses a colour made from changing RGB values.

testFilledTriangles()

This fills nested triangles with one colour and outlines them with another.

This is one of the more visually interesting parts of the demo.

testRoundRects()

This draws rounded rectangle outlines with increasing size.

testFilledRoundRects()

This fills rounded rectangles from large to small.

It is another good fill-speed test.

Why yield() appears in the code

You will notice yield() in several places.

That is there to give the system a chance to handle background tasks. On some platforms it helps avoid watchdog resets during long drawing operations.

It is not specific to the display itself, but it is good practice in longer loops.

What happens in loop()

After all the benchmarks are done in setup(), the sketch moves to the loop() function:

for(uint8_t rotation=0; rotation<4; rotation++) {
tft.setRotation(rotation);
testText();
delay(1000);
}

This rotates the display through all 4 possible orientations and redraws the text each time.

That helps confirm that:

  • Rotation works correctly
  • Text placement behaves as expected
  • Your display is not upside down relative to your project enclosure

Important practical notes

Round displays still use square coordinates

Even though the panel is round, the controller still works in a square 240×240 pixel area.

That means coordinates still start from the top-left corner like a normal rectangular display. The circular shape is just the visible part of that square area.

This is a benchmark, not a real UI example

This sketch is ideal for testing the display, but it is not structured like a menu, gauge, dashboard, or touchscreen interface.

Once the display works, you would normally move on to your own layout or graphics project.

Hardware SPI is the best choice

The comments in the code are right: software SPI is possible, but slower.

For a TFT display like this, hardware SPI is strongly preferred.

One small issue in the original example

There is one detail worth noticing in testLines().

The function appears to accumulate timing across multiple line-drawing passes using the variable t, but at the very end it returns only:

return micros() - start;

That means the reported timing does not reflect the full accumulated total from all sections of the function.

A more consistent ending would be:

t += micros() - start;
return t;

This does not stop the graphics demo from working, but it does make the benchmark number for the line test less accurate than intended.

Why this example is useful

This sketch is excellent for:

  • First-time display testing
  • Checking SPI wiring
  • Verifying backlight control
  • Confirming colour rendering
  • Testing screen rotation
  • Comparing performance between boards

If your display stays blank, shows the wrong colours, or behaves strangely, this kind of demo is much more helpful than jumping straight into a complex project.

Final thoughts

The Adafruit GC9A01A test sketch is one of those simple examples that does a lot of useful work. It proves that the screen is initialized properly, shows how the graphics library works, and gives you a rough idea of rendering speed on your board.

On ESP32, the most important step is usually just correcting the pin definitions for your hardware. Once that is done, this example is a very good foundation before moving on to gauges, clocks, sensor dashboards, or Home Assistant status displays on a round TFT.

Share your love

Leave a Reply

Your email address will not be published. Required fields are marked *