├── .github
├── ISSUE_TEMPLATE.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ └── githubci.yml
├── .gitignore
├── Adafruit_GC9A01A.cpp
├── Adafruit_GC9A01A.h
├── README.md
├── examples
└── graphicstest
│ └── graphicstest.ino
├── extras
├── Adafruit_Arcada_FeatherM4.h
└── Adafruit_Arcada_ItsyBitsyM4.h
└── library.properties
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Thank you for opening an issue on an Adafruit Arduino library repository. To
2 | improve the speed of resolution please review the following guidelines and
3 | common troubleshooting steps below before creating the issue:
4 |
5 | - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
6 | the forums at http://forums.adafruit.com to ask questions and troubleshoot why
7 | something isn't working as expected. In many cases the problem is a common issue
8 | that you will more quickly receive help from the forum community. GitHub issues
9 | are meant for known defects in the code. If you don't know if there is a defect
10 | in the code then start with troubleshooting on the forum first.
11 |
12 | - **If following a tutorial or guide be sure you didn't miss a step.** Carefully
13 | check all of the steps and commands to run have been followed. Consult the
14 | forum if you're unsure or have questions about steps in a guide/tutorial.
15 |
16 | - **For Arduino projects check these very common issues to ensure they don't apply**:
17 |
18 | - For uploading sketches or communicating with the board make sure you're using
19 | a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
20 | very hard to tell the difference between a data and charge cable! Try using the
21 | cable with other devices or swapping to another cable to confirm it is not
22 | the problem.
23 |
24 | - **Be sure you are supplying adequate power to the board.** Check the specs of
25 | your board and plug in an external power supply. In many cases just
26 | plugging a board into your computer is not enough to power it and other
27 | peripherals.
28 |
29 | - **Double check all soldering joints and connections.** Flakey connections
30 | cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
31 |
32 | - **Ensure you are using an official Arduino or Adafruit board.** We can't
33 | guarantee a clone board will have the same functionality and work as expected
34 | with this code and don't support them.
35 |
36 | If you're sure this issue is a defect in the code and checked the steps above
37 | please fill in the following fields to provide enough troubleshooting information.
38 | You may delete the guideline and text above to just leave the following details:
39 |
40 | - Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
41 |
42 | - Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
43 | VERSION HERE**
44 |
45 | - List the steps to reproduce the problem below (if possible attach a sketch or
46 | copy the sketch code in too): **LIST REPRO STEPS BELOW**
47 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Thank you for creating a pull request to contribute to Adafruit's GitHub code!
2 | Before you open the request please review the following guidelines and tips to
3 | help it be more easily integrated:
4 |
5 | - **Describe the scope of your change--i.e. what the change does and what parts
6 | of the code were modified.** This will help us understand any risks of integrating
7 | the code.
8 |
9 | - **Describe any known limitations with your change.** For example if the change
10 | doesn't apply to a supported platform of the library please mention it.
11 |
12 | - **Please run any tests or examples that can exercise your modified code.** We
13 | strive to not break users of the code and running tests/examples helps with this
14 | process.
15 |
16 | Thank you again for contributing! We will try to test and integrate the change
17 | as soon as we can, but be aware we have many GitHub repositories to manage and
18 | can't immediately respond to every request. There is no need to bump or check in
19 | on a pull request (it will clutter the discussion of the request).
20 |
21 | Also don't be worried if the request is closed or not integrated--sometimes the
22 | priorities of Adafruit's GitHub code (education, ease of use) might not match the
23 | priorities of the pull request. Don't fret, the open source community thrives on
24 | forks and GitHub makes it easy to keep your changes in a forked repo.
25 |
26 | After reviewing the guidelines above you can delete this text from the pull request.
27 |
--------------------------------------------------------------------------------
/.github/workflows/githubci.yml:
--------------------------------------------------------------------------------
1 | name: Arduino Library CI
2 |
3 | on: [pull_request, push, repository_dispatch]
4 |
5 | jobs:
6 | build:
7 | runs-on: ubuntu-latest
8 |
9 | steps:
10 | - uses: actions/setup-python@v1
11 | with:
12 | python-version: '3.x'
13 | - uses: actions/checkout@v2
14 | - uses: actions/checkout@v2
15 | with:
16 | repository: adafruit/ci-arduino
17 | path: ci
18 |
19 | - name: pre-install
20 | run: bash ci/actions_install.sh
21 |
22 | - name: test platforms
23 | run: python3 ci/build_platform.py main_platforms
24 |
25 | - name: clang
26 | run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r .
27 |
28 | - name: doxygen
29 | env:
30 | GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }}
31 | PRETTYNAME : "Adafruit GC9A01A"
32 | run: bash ci/doxy_gen_and_deploy.sh
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Our handy .gitignore for automation ease
2 | Doxyfile*
3 | doxygen_sqlite3.db
4 | html
5 |
--------------------------------------------------------------------------------
/Adafruit_GC9A01A.cpp:
--------------------------------------------------------------------------------
1 | /*!
2 | * @file Adafruit_GC9A01A.cpp
3 | *
4 | * @mainpage GC9A01A TFT Display library for Adafruit_GFX
5 | *
6 | * @section intro_sec Introduction
7 | *
8 | * Library to provide GC9A01A display driver support in Adafruit_GFX.
9 | *
10 | * These displays use SPI to communicate, 4 or 5 pins are required
11 | * to interface (RST is optional).
12 | *
13 | * Adafruit invests time and resources providing this open source code,
14 | * please support Adafruit and open-source hardware by purchasing
15 | * products from Adafruit!
16 | *
17 | * @section dependencies Dependencies
18 | *
19 | * This library depends on
20 | * Adafruit_GFX being present on your system. Please make sure you have
21 | * installed the latest version before using this library.
22 | *
23 | * @section author Author
24 | *
25 | * Written by Limor "ladyada" Fried for Adafruit Industries.
26 | * GC9A01A adaptation by Phil "PaintYourDragon" Burgess.
27 | *
28 | * @section license License
29 | *
30 | * BSD license, all text here must be included in any redistribution.
31 | *
32 | */
33 |
34 | #include "Adafruit_GC9A01A.h"
35 | #ifndef ARDUINO_STM32_FEATHER
36 | #include "pins_arduino.h"
37 | #ifndef RASPI
38 | #include "wiring_private.h"
39 | #endif
40 | #endif
41 | #include
42 |
43 | #if defined(ARDUINO_ARCH_ARC32) || defined(ARDUINO_MAXIM)
44 | #define SPI_DEFAULT_FREQ 16000000
45 | // Teensy 3.0, 3.1/3.2, 3.5, 3.6
46 | #elif defined(__MK20DX128__) || defined(__MK20DX256__) || \
47 | defined(__MK64FX512__) || defined(__MK66FX1M0__)
48 | #define SPI_DEFAULT_FREQ 40000000
49 | #elif defined(__AVR__) || defined(TEENSYDUINO)
50 | #define SPI_DEFAULT_FREQ 8000000
51 | #elif defined(ESP8266) || defined(ESP32)
52 | #define SPI_DEFAULT_FREQ 40000000
53 | #elif defined(RASPI)
54 | #define SPI_DEFAULT_FREQ 80000000
55 | #elif defined(ARDUINO_ARCH_STM32F1)
56 | #define SPI_DEFAULT_FREQ 36000000
57 | #else
58 | #define SPI_DEFAULT_FREQ 24000000 ///< Default SPI data clock frequency
59 | #endif
60 |
61 | #define MADCTL_MY 0x80 ///< Bottom to top
62 | #define MADCTL_MX 0x40 ///< Right to left
63 | #define MADCTL_MV 0x20 ///< Reverse Mode
64 | #define MADCTL_ML 0x10 ///< LCD refresh Bottom to top
65 | #define MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order
66 | #define MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order
67 | #define MADCTL_MH 0x04 ///< LCD refresh right to left
68 |
69 | /*!
70 | @brief Instantiate Adafruit GC9A01A driver with software SPI
71 | @param cs Chip select pin #
72 | @param dc Data/Command pin #
73 | @param mosi SPI MOSI pin #
74 | @param sclk SPI Clock pin #
75 | @param rst Reset pin # (optional, pass -1 if unused)
76 | @param miso SPI MISO pin # (optional, pass -1 if unused)
77 | */
78 | Adafruit_GC9A01A::Adafruit_GC9A01A(int8_t cs, int8_t dc, int8_t mosi,
79 | int8_t sclk, int8_t rst, int8_t miso)
80 | : Adafruit_SPITFT(GC9A01A_TFTWIDTH, GC9A01A_TFTHEIGHT, cs, dc, mosi, sclk,
81 | rst, miso) {}
82 |
83 | /*!
84 | @brief Instantiate Adafruit GC9A01A driver with hardware SPI using the
85 | default SPI peripheral.
86 | @param cs Chip select pin # (OK to pass -1 if CS tied to GND).
87 | @param dc Data/Command pin # (required).
88 | @param rst Reset pin # (optional, pass -1 if unused).
89 | */
90 | Adafruit_GC9A01A::Adafruit_GC9A01A(int8_t cs, int8_t dc, int8_t rst)
91 | : Adafruit_SPITFT(GC9A01A_TFTWIDTH, GC9A01A_TFTHEIGHT, cs, dc, rst) {}
92 |
93 | #if !defined(ESP8266)
94 | /*!
95 | @brief Instantiate Adafruit GC9A01A driver with hardware SPI using
96 | a specific SPI peripheral (not necessarily default).
97 | @param spiClass Pointer to SPI peripheral (e.g. &SPI or &SPI1).
98 | @param dc Data/Command pin # (required).
99 | @param cs Chip select pin # (optional, pass -1 if unused and
100 | CS is tied to GND).
101 | @param rst Reset pin # (optional, pass -1 if unused).
102 | */
103 | Adafruit_GC9A01A::Adafruit_GC9A01A(SPIClass *spiClass, int8_t dc, int8_t cs,
104 | int8_t rst)
105 | : Adafruit_SPITFT(GC9A01A_TFTWIDTH, GC9A01A_TFTHEIGHT, spiClass, cs, dc,
106 | rst) {}
107 | #endif // end !ESP8266
108 |
109 | /*!
110 | @brief Instantiate Adafruit GC9A01A driver using parallel interface.
111 | @param busWidth If tft16 (enumeration in Adafruit_SPITFT.h), is a
112 | 16-bit interface, else 8-bit.
113 | @param d0 Data pin 0 (MUST be a byte- or word-aligned LSB of a
114 | PORT register -- pins 1-n are extrapolated from this).
115 | @param wr Write strobe pin # (required).
116 | @param dc Data/Command pin # (required).
117 | @param cs Chip select pin # (optional, pass -1 if unused and CS
118 | is tied to GND).
119 | @param rst Reset pin # (optional, pass -1 if unused).
120 | @param rd Read strobe pin # (optional, pass -1 if unused).
121 | */
122 | Adafruit_GC9A01A::Adafruit_GC9A01A(tftBusWidth busWidth, int8_t d0, int8_t wr,
123 | int8_t dc, int8_t cs, int8_t rst, int8_t rd)
124 | : Adafruit_SPITFT(GC9A01A_TFTWIDTH, GC9A01A_TFTHEIGHT, busWidth, d0, wr, dc,
125 | cs, rst, rd) {}
126 |
127 | // clang-format off
128 | // Initialization sequence came from some early code provided by the
129 | // manufacturer. Many of these registers are undocumented, some might
130 | // be unnecessary, just playing along...
131 | static const uint8_t PROGMEM initcmd[] = {
132 | GC9A01A_INREGEN2, 0,
133 | 0xEB, 1, 0x14, // ?
134 | GC9A01A_INREGEN1, 0,
135 | GC9A01A_INREGEN2, 0,
136 | 0xEB, 1, 0x14, // ?
137 | 0x84, 1, 0x40, // ?
138 | 0x85, 1, 0xFF, // ?
139 | 0x86, 1, 0xFF, // ?
140 | 0x87, 1, 0xFF, // ?
141 | 0x88, 1, 0x0A, // ?
142 | 0x89, 1, 0x21, // ?
143 | 0x8A, 1, 0x00, // ?
144 | 0x8B, 1, 0x80, // ?
145 | 0x8C, 1, 0x01, // ?
146 | 0x8D, 1, 0x01, // ?
147 | 0x8E, 1, 0xFF, // ?
148 | 0x8F, 1, 0xFF, // ?
149 | 0xB6, 2, 0x00, 0x00, // ?
150 | GC9A01A_MADCTL, 1, MADCTL_MX | MADCTL_BGR,
151 | GC9A01A_COLMOD, 1, 0x05,
152 | 0x90, 4, 0x08, 0x08, 0x08, 0x08, // ?
153 | 0xBD, 1, 0x06, // ?
154 | 0xBC, 1, 0x00, // ?
155 | 0xFF, 3, 0x60, 0x01, 0x04, // ?
156 | GC9A01A1_POWER2, 1, 0x13,
157 | GC9A01A1_POWER3, 1, 0x13,
158 | GC9A01A1_POWER4, 1, 0x22,
159 | 0xBE, 1, 0x11, // ?
160 | 0xE1, 2, 0x10, 0x0E, // ?
161 | 0xDF, 3, 0x21, 0x0c, 0x02, // ?
162 | GC9A01A_GAMMA1, 6, 0x45, 0x09, 0x08, 0x08, 0x26, 0x2A,
163 | GC9A01A_GAMMA2, 6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6F,
164 | GC9A01A_GAMMA3, 6, 0x45, 0x09, 0x08, 0x08, 0x26, 0x2A,
165 | GC9A01A_GAMMA4, 6, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6F,
166 | 0xED, 2, 0x1B, 0x0B, // ?
167 | 0xAE, 1, 0x77, // ?
168 | 0xCD, 1, 0x63, // ?
169 | // Unsure what this line (from manufacturer's boilerplate code) is
170 | // meant to do, but users reported issues, seems to work OK without:
171 | //0x70, 9, 0x07, 0x07, 0x04, 0x0E, 0x0F, 0x09, 0x07, 0x08, 0x03, // ?
172 | GC9A01A_FRAMERATE, 1, 0x34,
173 | 0x62, 12, 0x18, 0x0D, 0x71, 0xED, 0x70, 0x70, // ?
174 | 0x18, 0x0F, 0x71, 0xEF, 0x70, 0x70,
175 | 0x63, 12, 0x18, 0x11, 0x71, 0xF1, 0x70, 0x70, // ?
176 | 0x18, 0x13, 0x71, 0xF3, 0x70, 0x70,
177 | 0x64, 7, 0x28, 0x29, 0xF1, 0x01, 0xF1, 0x00, 0x07, // ?
178 | 0x66, 10, 0x3C, 0x00, 0xCD, 0x67, 0x45, 0x45, 0x10, 0x00, 0x00, 0x00, // ?
179 | 0x67, 10, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x54, 0x10, 0x32, 0x98, // ?
180 | 0x74, 7, 0x10, 0x85, 0x80, 0x00, 0x00, 0x4E, 0x00, // ?
181 | 0x98, 2, 0x3e, 0x07, // ?
182 | GC9A01A_TEON, 0,
183 | GC9A01A_INVON, 0,
184 | GC9A01A_SLPOUT, 0x80, // Exit sleep
185 | GC9A01A_DISPON, 0x80, // Display on
186 | 0x00 // End of list
187 | };
188 | // clang-format on
189 |
190 | /*!
191 | @brief Initialize GC9A01A chip. Connects to the GC9A01A over SPI
192 | and sends initialization commands.
193 | @param freq Desired SPI clock frequency
194 | */
195 | void Adafruit_GC9A01A::begin(uint32_t freq) {
196 |
197 | if (!freq)
198 | freq = SPI_DEFAULT_FREQ;
199 | initSPI(freq);
200 |
201 | if (_rst < 0) { // If no hardware reset pin...
202 | sendCommand(GC9A01A_SWRESET); // Engage software reset
203 | delay(150);
204 | }
205 |
206 | uint8_t cmd, x, numArgs;
207 | const uint8_t *addr = initcmd;
208 | while ((cmd = pgm_read_byte(addr++)) > 0) {
209 | x = pgm_read_byte(addr++);
210 | numArgs = x & 0x7F;
211 | sendCommand(cmd, addr, numArgs);
212 | addr += numArgs;
213 | if (x & 0x80)
214 | delay(150);
215 | }
216 |
217 | _width = GC9A01A_TFTWIDTH;
218 | _height = GC9A01A_TFTHEIGHT;
219 | }
220 |
221 | /*!
222 | @brief Set origin of (0,0) and orientation of TFT display
223 | @param m The index for rotation, from 0-3 inclusive
224 | */
225 | void Adafruit_GC9A01A::setRotation(uint8_t m) {
226 | rotation = m % 4; // can't be higher than 3
227 | switch (rotation) {
228 | case 0:
229 | m = (MADCTL_MX | MADCTL_BGR);
230 | _width = GC9A01A_TFTWIDTH;
231 | _height = GC9A01A_TFTHEIGHT;
232 | break;
233 | case 1:
234 | m = (MADCTL_MV | MADCTL_BGR);
235 | _width = GC9A01A_TFTHEIGHT;
236 | _height = GC9A01A_TFTWIDTH;
237 | break;
238 | case 2:
239 | m = (MADCTL_MY | MADCTL_BGR);
240 | _width = GC9A01A_TFTWIDTH;
241 | _height = GC9A01A_TFTHEIGHT;
242 | break;
243 | case 3:
244 | m = (MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR);
245 | _width = GC9A01A_TFTHEIGHT;
246 | _height = GC9A01A_TFTWIDTH;
247 | break;
248 | }
249 |
250 | sendCommand(GC9A01A_MADCTL, &m, 1);
251 | }
252 |
253 | /*!
254 | @brief Enable/Disable display color inversion
255 | @param invert True to invert, False to have normal color
256 | */
257 | void Adafruit_GC9A01A::invertDisplay(bool invert) {
258 | sendCommand(invert ? GC9A01A_INVON : GC9A01A_INVOFF);
259 | }
260 |
261 | /*!
262 | @brief Set the "address window" - the rectangle we will write to RAM
263 | with the next chunk of SPI data. The GC9A01A will automatically
264 | wrap the data as each row is filled.
265 | @param x1 TFT memory 'x' origin
266 | @param y1 TFT memory 'y' origin
267 | @param w Width of rectangle
268 | @param h Height of rectangle
269 | */
270 | void Adafruit_GC9A01A::setAddrWindow(uint16_t x1, uint16_t y1, uint16_t w,
271 | uint16_t h) {
272 | uint16_t x2 = (x1 + w - 1), y2 = (y1 + h - 1);
273 | writeCommand(GC9A01A_CASET); // Column address set
274 | SPI_WRITE16(x1);
275 | SPI_WRITE16(x2);
276 | writeCommand(GC9A01A_RASET); // Row address set
277 | SPI_WRITE16(y1);
278 | SPI_WRITE16(y2);
279 | writeCommand(GC9A01A_RAMWR); // Write to RAM
280 | }
281 |
--------------------------------------------------------------------------------
/Adafruit_GC9A01A.h:
--------------------------------------------------------------------------------
1 | /*!
2 | * @file Adafruit_GC9A01A.h
3 | *
4 | * Library to provide GC9A01A display driver support in Adafruit_GFX.
5 | *
6 | * Adafruit invests time and resources providing this open source code,
7 | * please support Adafruit and open-source hardware by purchasing
8 | * products from Adafruit!
9 | *
10 | * This library depends on
11 | * Adafruit_GFX being present on your system. Please make sure you have
12 | * installed the latest version before using this library.
13 | *
14 | * Written by Limor "ladyada" Fried for Adafruit Industries.
15 | * GC9A01A adaptation by Phil "PaintYourDragon" Burgess.
16 | *
17 | * BSD license, all text here must be included in any redistribution.
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | #include "Adafruit_GFX.h"
24 | #include "Arduino.h"
25 | #include "Print.h"
26 | #include
27 | #include
28 | #include
29 |
30 | #define GC9A01A_TFTWIDTH 240 ///< Display width in pixels
31 | #define GC9A01A_TFTHEIGHT 240 ///< Display height in pixels
32 |
33 | #define GC9A01A_SWRESET 0x01 ///< Software Reset (maybe, not documented)
34 | #define GC9A01A_RDDID 0x04 ///< Read display identification information
35 | #define GC9A01A_RDDST 0x09 ///< Read Display Status
36 | #define GC9A01A_SLPIN 0x10 ///< Enter Sleep Mode
37 | #define GC9A01A_SLPOUT 0x11 ///< Sleep Out
38 | #define GC9A01A_PTLON 0x12 ///< Partial Mode ON
39 | #define GC9A01A_NORON 0x13 ///< Normal Display Mode ON
40 | #define GC9A01A_INVOFF 0x20 ///< Display Inversion OFF
41 | #define GC9A01A_INVON 0x21 ///< Display Inversion ON
42 | #define GC9A01A_DISPOFF 0x28 ///< Display OFF
43 | #define GC9A01A_DISPON 0x29 ///< Display ON
44 | #define GC9A01A_CASET 0x2A ///< Column Address Set
45 | #define GC9A01A_RASET 0x2B ///< Row Address Set
46 | #define GC9A01A_RAMWR 0x2C ///< Memory Write
47 | #define GC9A01A_PTLAR 0x30 ///< Partial Area
48 | #define GC9A01A_VSCRDEF 0x33 ///< Vertical Scrolling Definition
49 | #define GC9A01A_TEOFF 0x34 ///< Tearing Effect Line OFF
50 | #define GC9A01A_TEON 0x35 ///< Tearing Effect Line ON
51 | #define GC9A01A_MADCTL 0x36 ///< Memory Access Control
52 | #define GC9A01A_VSCRSADD 0x37 ///< Vertical Scrolling Start Address
53 | #define GC9A01A_IDLEOFF 0x38 ///< Idle mode OFF
54 | #define GC9A01A_IDLEON 0x39 ///< Idle mode ON
55 | #define GC9A01A_COLMOD 0x3A ///< Pixel Format Set
56 | #define GC9A01A_CONTINUE 0x3C ///< Write Memory Continue
57 | #define GC9A01A_TEARSET 0x44 ///< Set Tear Scanline
58 | #define GC9A01A_GETLINE 0x45 ///< Get Scanline
59 | #define GC9A01A_SETBRIGHT 0x51 ///< Write Display Brightness
60 | #define GC9A01A_SETCTRL 0x53 ///< Write CTRL Display
61 | #define GC9A01A1_POWER7 0xA7 ///< Power Control 7
62 | #define GC9A01A_TEWC 0xBA ///< Tearing effect width control
63 | #define GC9A01A1_POWER1 0xC1 ///< Power Control 1
64 | #define GC9A01A1_POWER2 0xC3 ///< Power Control 2
65 | #define GC9A01A1_POWER3 0xC4 ///< Power Control 3
66 | #define GC9A01A1_POWER4 0xC9 ///< Power Control 4
67 | #define GC9A01A_RDID1 0xDA ///< Read ID 1
68 | #define GC9A01A_RDID2 0xDB ///< Read ID 2
69 | #define GC9A01A_RDID3 0xDC ///< Read ID 3
70 | #define GC9A01A_FRAMERATE 0xE8 ///< Frame rate control
71 | #define GC9A01A_SPI2DATA 0xE9 ///< SPI 2DATA control
72 | #define GC9A01A_INREGEN2 0xEF ///< Inter register enable 2
73 | #define GC9A01A_GAMMA1 0xF0 ///< Set gamma 1
74 | #define GC9A01A_GAMMA2 0xF1 ///< Set gamma 2
75 | #define GC9A01A_GAMMA3 0xF2 ///< Set gamma 3
76 | #define GC9A01A_GAMMA4 0xF3 ///< Set gamma 4
77 | #define GC9A01A_IFACE 0xF6 ///< Interface control
78 | #define GC9A01A_INREGEN1 0xFE ///< Inter register enable 1
79 |
80 | // Color definitions
81 | #define GC9A01A_BLACK 0x0000 ///< 0, 0, 0
82 | #define GC9A01A_NAVY 0x000F ///< 0, 0, 123
83 | #define GC9A01A_DARKGREEN 0x03E0 ///< 0, 125, 0
84 | #define GC9A01A_DARKCYAN 0x03EF ///< 0, 125, 123
85 | #define GC9A01A_MAROON 0x7800 ///< 123, 0, 0
86 | #define GC9A01A_PURPLE 0x780F ///< 123, 0, 123
87 | #define GC9A01A_OLIVE 0x7BE0 ///< 123, 125, 0
88 | #define GC9A01A_LIGHTGREY 0xC618 ///< 198, 195, 198
89 | #define GC9A01A_DARKGREY 0x7BEF ///< 123, 125, 123
90 | #define GC9A01A_BLUE 0x001F ///< 0, 0, 255
91 | #define GC9A01A_GREEN 0x07E0 ///< 0, 255, 0
92 | #define GC9A01A_CYAN 0x07FF ///< 0, 255, 255
93 | #define GC9A01A_RED 0xF800 ///< 255, 0, 0
94 | #define GC9A01A_MAGENTA 0xF81F ///< 255, 0, 255
95 | #define GC9A01A_YELLOW 0xFFE0 ///< 255, 255, 0
96 | #define GC9A01A_WHITE 0xFFFF ///< 255, 255, 255
97 | #define GC9A01A_ORANGE 0xFD20 ///< 255, 165, 0
98 | #define GC9A01A_GREENYELLOW 0xAFE5 ///< 173, 255, 41
99 | #define GC9A01A_PINK 0xFC18 ///< 255, 130, 198
100 |
101 | /*!
102 | @brief Class to manage hardware interface with GC9A01A chipset.
103 | */
104 | class Adafruit_GC9A01A : public Adafruit_SPITFT {
105 | public:
106 | Adafruit_GC9A01A(int8_t _CS, int8_t _DC, int8_t _MOSI, int8_t _SCLK,
107 | int8_t _RST = -1, int8_t _MISO = -1);
108 | Adafruit_GC9A01A(int8_t _CS, int8_t _DC, int8_t _RST = -1);
109 | #if !defined(ESP8266)
110 | Adafruit_GC9A01A(SPIClass *spiClass, int8_t dc, int8_t cs = -1,
111 | int8_t rst = -1);
112 | #endif // end !ESP8266
113 | Adafruit_GC9A01A(tftBusWidth busWidth, int8_t d0, int8_t wr, int8_t dc,
114 | int8_t cs = -1, int8_t rst = -1, int8_t rd = -1);
115 |
116 | void begin(uint32_t freq = 0);
117 | void setRotation(uint8_t r);
118 | void invertDisplay(bool i);
119 |
120 | void setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
121 | };
122 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GC9A01A Arduino Library
2 |
3 | Library to provide GC9A01A display driver support in Adafruit_GFX.
4 |
5 | Adafruit invests time and resources providing this open source code,
6 | please support Adafruit and open-source hardware by purchasing
7 | products from Adafruit!
8 |
9 | Written by Limor Fried/Ladyada for Adafruit Industries.
10 | GC9A01A adaptation by Phil "PaintYourDragon" Burgess.
11 | BSD license, all text above must be included in any redistribution
12 |
13 | Requires the Adafruit_GFX library for Arduino.
14 |
15 | EXTRAS FOLDER: Adafruit_Arcada_FeatherM4.h file can be used with
16 | Adafruit_Arcada library to make the M4_Eyes sketch compile on Adafruit
17 | Feather M4 with this display (second display has not been tested,
18 | would require setting up a second SPI SERCOM, but in theory it should work).
19 |
--------------------------------------------------------------------------------
/examples/graphicstest/graphicstest.ino:
--------------------------------------------------------------------------------
1 | #include "SPI.h"
2 | #include "Adafruit_GFX.h"
3 | #include "Adafruit_GC9A01A.h"
4 |
5 | // Define pins for display interface. You'll probably need to edit this for
6 | // your own needs:
7 |
8 | #if defined(ARDUINO_SEEED_XIAO_RP2040)
9 |
10 | // Pinout when using Seed Round Display for XIAO in combination with
11 | // Seeed XIAO RP2040. Other (non-RP2040) XIAO boards, any Adafruit Qt Py
12 | // boards, and other GC9A01A display breakouts will require different pins.
13 | #define TFT_CS D1 // Chip select
14 | #define TFT_DC D3 // Data/command
15 | #define TFT_BL D6 // Backlight control
16 |
17 | #else // ALL OTHER BOARDS - EDIT AS NEEDED
18 |
19 | // Other RP2040-based boards might not have "D" pin defines as shown above
20 | // and will use GPIO bit numbers. On non-RP2040 boards, you can usually use
21 | // pin numbers silkscreened on the board.
22 | #define TFT_DC 9
23 | #define TFT_CS 10
24 | // If display breakout has a backlight control pin, that can be defined here
25 | // as TFT_BL. On some breakouts it's not needed, backlight is always on.
26 |
27 | #endif
28 |
29 | // Display constructor for primary hardware SPI connection -- the specific
30 | // pins used for writing to the display are unique to each board and are not
31 | // negotiable. "Soft" SPI (using any pins) is an option but performance is
32 | // reduced; it's rarely used, see header file for syntax if needed.
33 | Adafruit_GC9A01A tft(TFT_CS, TFT_DC);
34 |
35 | void setup() {
36 | Serial.begin(9600);
37 | Serial.println("GC9A01A Test!");
38 |
39 | tft.begin();
40 |
41 | #if defined(TFT_BL)
42 | pinMode(TFT_BL, OUTPUT);
43 | digitalWrite(TFT_BL, HIGH); // Backlight on
44 | #endif // end TFT_BL
45 |
46 | Serial.println(F("Benchmark Time (microseconds)"));
47 | delay(10);
48 | Serial.print(F("Screen fill "));
49 | Serial.println(testFillScreen());
50 | delay(500);
51 |
52 | Serial.print(F("Text "));
53 | Serial.println(testText());
54 | delay(3000);
55 |
56 | Serial.print(F("Lines "));
57 | Serial.println(testLines(GC9A01A_CYAN));
58 | delay(500);
59 |
60 | Serial.print(F("Horiz/Vert Lines "));
61 | Serial.println(testFastLines(GC9A01A_RED, GC9A01A_BLUE));
62 | delay(500);
63 |
64 | Serial.print(F("Rectangles (outline) "));
65 | Serial.println(testRects(GC9A01A_GREEN));
66 | delay(500);
67 |
68 | Serial.print(F("Rectangles (filled) "));
69 | Serial.println(testFilledRects(GC9A01A_YELLOW, GC9A01A_MAGENTA));
70 | delay(500);
71 |
72 | Serial.print(F("Circles (filled) "));
73 | Serial.println(testFilledCircles(10, GC9A01A_MAGENTA));
74 |
75 | Serial.print(F("Circles (outline) "));
76 | Serial.println(testCircles(10, GC9A01A_WHITE));
77 | delay(500);
78 |
79 | Serial.print(F("Triangles (outline) "));
80 | Serial.println(testTriangles());
81 | delay(500);
82 |
83 | Serial.print(F("Triangles (filled) "));
84 | Serial.println(testFilledTriangles());
85 | delay(500);
86 |
87 | Serial.print(F("Rounded rects (outline) "));
88 | Serial.println(testRoundRects());
89 | delay(500);
90 |
91 | Serial.print(F("Rounded rects (filled) "));
92 | Serial.println(testFilledRoundRects());
93 | delay(500);
94 |
95 | Serial.println(F("Done!"));
96 | }
97 |
98 | void loop(void) {
99 | for(uint8_t rotation=0; rotation<4; rotation++) {
100 | tft.setRotation(rotation);
101 | testText();
102 | delay(1000);
103 | }
104 | }
105 |
106 | unsigned long testFillScreen() {
107 | unsigned long start = micros();
108 | tft.fillScreen(GC9A01A_BLACK);
109 | yield();
110 | tft.fillScreen(GC9A01A_RED);
111 | yield();
112 | tft.fillScreen(GC9A01A_GREEN);
113 | yield();
114 | tft.fillScreen(GC9A01A_BLUE);
115 | yield();
116 | tft.fillScreen(GC9A01A_BLACK);
117 | yield();
118 | return micros() - start;
119 | }
120 |
121 | unsigned long testText() {
122 | tft.fillScreen(GC9A01A_BLACK);
123 | unsigned long start = micros();
124 | tft.setCursor(0, 0);
125 | tft.setTextColor(GC9A01A_WHITE); tft.setTextSize(1);
126 | tft.println("Hello World!");
127 | tft.setTextColor(GC9A01A_YELLOW); tft.setTextSize(2);
128 | tft.println(1234.56);
129 | tft.setTextColor(GC9A01A_RED); tft.setTextSize(3);
130 | tft.println(0xDEADBEEF, HEX);
131 | tft.println();
132 | tft.setTextColor(GC9A01A_GREEN);
133 | tft.setTextSize(5);
134 | tft.println("Groop");
135 | tft.setTextSize(2);
136 | tft.println("I implore thee,");
137 | tft.setTextSize(1);
138 | tft.println("my foonting turlingdromes.");
139 | tft.println("And hooptiously drangle me");
140 | tft.println("with crinkly bindlewurdles,");
141 | tft.println("Or I will rend thee");
142 | tft.println("in the gobberwarts");
143 | tft.println("with my blurglecruncheon,");
144 | tft.println("see if I don't!");
145 | return micros() - start;
146 | }
147 |
148 | unsigned long testLines(uint16_t color) {
149 | unsigned long start, t;
150 | int x1, y1, x2, y2,
151 | w = tft.width(),
152 | h = tft.height();
153 |
154 | tft.fillScreen(GC9A01A_BLACK);
155 | yield();
156 |
157 | x1 = y1 = 0;
158 | y2 = h - 1;
159 | start = micros();
160 | for(x2=0; x20; i-=6) {
245 | i2 = i / 2;
246 | start = micros();
247 | tft.fillRect(cx-i2, cy-i2, i, i, color1);
248 | t += micros() - start;
249 | // Outlines are not included in timing results
250 | tft.drawRect(cx-i2, cy-i2, i, i, color2);
251 | yield();
252 | }
253 |
254 | return t;
255 | }
256 |
257 | unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
258 | unsigned long start;
259 | int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;
260 |
261 | tft.fillScreen(GC9A01A_BLACK);
262 | start = micros();
263 | for(x=radius; x10; i-=5) {
317 | start = micros();
318 | tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
319 | tft.color565(0, i*10, i*10));
320 | t += micros() - start;
321 | tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
322 | tft.color565(i*10, i*10, 0));
323 | yield();
324 | }
325 |
326 | return t;
327 | }
328 |
329 | unsigned long testRoundRects() {
330 | unsigned long start;
331 | int w, i, i2,
332 | cx = tft.width() / 2 - 1,
333 | cy = tft.height() / 2 - 1;
334 |
335 | tft.fillScreen(GC9A01A_BLACK);
336 | w = min(tft.width(), tft.height());
337 | start = micros();
338 | for(i=0; i20; i-=6) {
355 | i2 = i / 2;
356 | tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0));
357 | yield();
358 | }
359 |
360 | return micros() - start;
361 | }
362 |
--------------------------------------------------------------------------------
/extras/Adafruit_Arcada_FeatherM4.h:
--------------------------------------------------------------------------------
1 | // Header file to use Adafruit_Arcada library on Feather M4 with GC9A01A
2 | // displays. Allows M4_Eyes sketch to run on this hardware combo.
3 | // As written, this only handles a single GC9A01A screen. See
4 | // Adafruit_Arcada_ItsyBitsyM4.h for insights on handling 2 screens
5 | // (requires setting up a second SPI SERCOM).
6 | // Place file in Adafruit_Arcada/Boards and add line to Adafruit_Arcada.h:
7 | // #include "Boards/Adafruit_Arcada_FeatherM4.h"
8 |
9 | #if defined(_VARIANT_FEATHER_M4_)
10 | #include
11 |
12 | #define ARCADA_TFT_SPI SPI
13 | #define ARCADA_TFT_CS 10 // Display CS Arduino pin number
14 | #define ARCADA_TFT_DC 9 // Display D/C Arduino pin number
15 | #define ARCADA_TFT_RST -1 // Display reset Arduino pin number
16 | #define ARCADA_TFT_ROTATION 2
17 | #define ARCADA_TFT_DEFAULTFILL 0xFFFF
18 | #define ARCADA_TFT_WIDTH 240
19 | #define ARCADA_TFT_HEIGHT 240
20 | // #define ARCADA_TFT_LITE 47
21 |
22 | #define ARCADA_AUDIO_OUT A0
23 |
24 | #define ARCADA_CALLBACKTIMER 4
25 | #define ARCADA_CALLBACKTIMER_HANDLER TC4_Handler
26 |
27 | #define ARCADA_USE_JSON
28 |
29 | #include "arcadatype.h"
30 |
31 | class Adafruit_Arcada : public Adafruit_Arcada_SPITFT {
32 | public:
33 | Adafruit_Arcada(void) { _has_accel = false; };
34 |
35 | bool variantBegin(void) { return true; }
36 |
37 | void displayBegin(void) {
38 | Adafruit_GC9A01A *tft = new Adafruit_GC9A01A(&ARCADA_TFT_SPI, ARCADA_TFT_DC,
39 | ARCADA_TFT_CS, ARCADA_TFT_RST);
40 | tft->begin();
41 | tft->setRotation(ARCADA_TFT_ROTATION);
42 | tft->fillScreen(ARCADA_TFT_DEFAULTFILL);
43 | uint8_t rtna =
44 | 0x01; // Screen refresh rate control (datasheet 9.2.18, FRCTRL2)
45 | tft->sendCommand(0xC6, &rtna, 1);
46 | tft->setSPISpeed(50000000); // yes fast
47 | display = tft;
48 | }
49 |
50 | uint32_t variantReadButtons(void) { return 0; }
51 |
52 | private:
53 | };
54 |
55 | #endif
56 |
--------------------------------------------------------------------------------
/extras/Adafruit_Arcada_ItsyBitsyM4.h:
--------------------------------------------------------------------------------
1 | #if defined(ADAFRUIT_ITSYBITSY_M4_EXPRESS)
2 | // INCLUDE ONLY **ONE** OF THESE DISPLAY TYPES:
3 | #include // Round 240 pixel diameter TFT
4 | // #include // Square 240x240 TFT
5 | // #include // Rectangular 320x240 TFT
6 | #include "wiring_private.h"
7 | #include
8 |
9 | #define TWO_DISPLAYS
10 |
11 | #define ARCADA_TFT_SPI SPI
12 | #define ARCADA_TFT_DC A5
13 | #define ARCADA_TFT_CS A4
14 | #define ARCADA_TFT_RST -1
15 | // #define ARCADA_TFT_LITE 47
16 | #define ARCADA_TFT_ROTATION 1
17 | #define ARCADA_TFT_DEFAULTFILL 0xFFFF
18 | #if defined(_ADAFRUIT_ILI9341H_)
19 | #define ARCADA_TFT_WIDTH 320
20 | #else
21 | #define ARCADA_TFT_WIDTH 240
22 | #endif
23 | #define ARCADA_TFT_HEIGHT 240
24 |
25 | #if defined(TWO_DISPLAYS)
26 | // SECOND DISPLAY ON SEPARATE SPI BUS:
27 | #if defined(GLOBAL_VAR)
28 | // SPI is on sercom0, I2C on sercom1, 2-5 are available
29 | // Sercom3 is normally serial1 but let use it for 2nd SPI
30 | // 0 and 1 are RX, TX respectively - PORTA16, 17
31 | // sercom_alts are SERCOM3/PAD1 and SERCOM3/PAD0
32 | // This puts MOSI on TX, SCK on RX
33 | SPIClass SPI1(&sercom3, 0, 1, 2, SPI_PAD_0_SCK_1, SERCOM_RX_PAD_3);
34 | #else
35 | extern SPIClass SPI1;
36 | #endif
37 | #define ARCADA_LEFTTFT_SPI SPI1
38 | #define ARCADA_LEFTTFT_DC 9
39 | #define ARCADA_LEFTTFT_CS 7
40 | #define ARCADA_LEFTTFT_RST -1
41 | #endif // end TWO_DISPLAYS
42 |
43 | #define TFT_RESET 2 // Used for BOTH displays
44 |
45 | #define ARCADA_AUDIO_OUT A0
46 |
47 | #define ARCADA_CALLBACKTIMER 4
48 | #define ARCADA_CALLBACKTIMER_HANDLER TC4_Handler
49 |
50 | #define ARCADA_USE_JSON
51 |
52 | #include "arcadatype.h"
53 |
54 | class Adafruit_Arcada : public Adafruit_Arcada_SPITFT {
55 | public:
56 | Adafruit_Arcada(void) { _has_accel = false; };
57 | #if defined(_ADAFRUIT_ST7789H_)
58 | Adafruit_ST7789 *_display, *display2;
59 | #elif defined(_ADAFRUIT_ILI9341H_)
60 | Adafruit_ILI9341 *_display, *display2;
61 | #else
62 | Adafruit_GC9A01A *_display, *display2;
63 | #endif
64 |
65 | bool variantBegin(void) {
66 | Adafruit_DotStar dot = Adafruit_DotStar(1, 8, 6);
67 | dot.show(); // Turn off DotStar
68 | return true;
69 | }
70 |
71 | void displayBegin(void) {
72 | // Hard reset both displays
73 | pinMode(TFT_RESET, OUTPUT);
74 | digitalWrite(TFT_RESET, LOW);
75 | delay(10);
76 | digitalWrite(TFT_RESET, HIGH);
77 | delay(10);
78 |
79 | // IMPORTANT: CS and DC are different order among displays
80 | #if defined(_ADAFRUIT_ST7789H_)
81 | _display = new Adafruit_ST7789(&ARCADA_TFT_SPI, ARCADA_TFT_CS,
82 | ARCADA_TFT_DC, ARCADA_TFT_RST);
83 | _display->init(240, 240);
84 | #elif defined(_ADAFRUIT_ILI9341H_)
85 | _display = new Adafruit_ILI9341(&ARCADA_TFT_SPI, ARCADA_TFT_DC,
86 | ARCADA_TFT_CS, ARCADA_TFT_RST);
87 | _display->begin();
88 | #else
89 | uint8_t rtna = 0x01; // Screen refresh rate control
90 | _display = new Adafruit_GC9A01A(&ARCADA_TFT_SPI, ARCADA_TFT_DC,
91 | ARCADA_TFT_CS, ARCADA_TFT_RST);
92 | _display->begin();
93 | _display->sendCommand(0xC6, &rtna, 1); // Helps contrast a little
94 | #endif
95 | _display->setSPISpeed(50000000); // yes fast
96 | _display->setRotation(ARCADA_TFT_ROTATION);
97 | _display->fillScreen(ARCADA_TFT_DEFAULTFILL);
98 |
99 | #if defined(ARCADA_LEFTTFT_SPI)
100 | pinPeripheral(0, PIO_SERCOM_ALT); // Enable SPI1 on RX, TX
101 | pinPeripheral(1, PIO_SERCOM_ALT);
102 | // IMPORTANT: CS and DC are different order among displays
103 | #if defined(_ADAFRUIT_ST7789H_)
104 | display2 = new Adafruit_ST7789(&ARCADA_LEFTTFT_SPI, ARCADA_LEFTTFT_CS,
105 | ARCADA_LEFTTFT_DC, ARCADA_LEFTTFT_RST);
106 | display2->init(240, 240);
107 | #elif defined(_ADAFRUIT_ILI9341H_)
108 | display2 = new Adafruit_ILI9341(&ARCADA_LEFTTFT_SPI, ARCADA_LEFTTFT_DC,
109 | ARCADA_LEFTTFT_CS, ARCADA_LEFTTFT_RST);
110 | display2->begin();
111 | #else
112 | display2 = new Adafruit_GC9A01A(&ARCADA_LEFTTFT_SPI, ARCADA_LEFTTFT_DC,
113 | ARCADA_LEFTTFT_CS, ARCADA_LEFTTFT_RST);
114 | display2->begin();
115 | display2->sendCommand(0xC6, &rtna, 1); // Helps contrast a little
116 | #endif
117 | display2->setSPISpeed(50000000);
118 | display2->setRotation(ARCADA_TFT_ROTATION);
119 | display2->fillScreen(ARCADA_TFT_DEFAULTFILL);
120 | #endif
121 |
122 | display = _display;
123 | }
124 |
125 | uint32_t variantReadButtons(void) { return 0; }
126 |
127 | private:
128 | };
129 |
130 | #endif
131 |
--------------------------------------------------------------------------------
/library.properties:
--------------------------------------------------------------------------------
1 | name=Adafruit GC9A01A
2 | version=1.1.1
3 | author=Adafruit
4 | maintainer=Adafruit
5 | sentence=Library for GC9A01A displays
6 | paragraph=Library for GC9A01A displays
7 | category=Display
8 | url=https://github.com/Adafruit/Adafruit_GC9A01A
9 | architectures=*
10 | depends=Adafruit GFX Library
11 |
--------------------------------------------------------------------------------