diff --git a/GC9A01A_Demo_Code/Arduino_GC9A01A/.uno.test.only b/GC9A01A_Demo_Code/Arduino_GC9A01A/.uno.test.only new file mode 100644 index 000000000..e69de29bb diff --git a/GC9A01A_Demo_Code/Arduino_GC9A01A/Arduino_GC9A01A.ino b/GC9A01A_Demo_Code/Arduino_GC9A01A/Arduino_GC9A01A.ino new file mode 100644 index 000000000..bf6141b66 --- /dev/null +++ b/GC9A01A_Demo_Code/Arduino_GC9A01A/Arduino_GC9A01A.ino @@ -0,0 +1,622 @@ +// SPDX-FileCopyrightText: 2022 Phillip Burgess for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Graphics example for EYESPI-capable color displays. This code: +// - Functions as a "Hello World" to verify that microcontroller and screen +// are communicating. +// - Demonstrates most of the drawing commands of the Adafruit_GFX library. +// - Showcases some techniques that might not be obvious or that aren't +// built-in but can be handled with a little extra code. +// It DOES NOT: +// - Support all Adafruit screens, ONLY EYESPI products at the time this was +// written! But it's easily adapted by looking at other examples. +// - Demonstrate the Adafruit_GFX_Button class, as that's unique to +// touch-capable displays. Again, other examples may cover this topic. +// This sketch is long, but a lot of it is comments to explain each step. You +// can copy just the parts you need as a starting point for your own projects, +// and strip comments once understood. + +// CONSTANTS, HEADERS and GLOBAL VARIABLES --------------------------------- + +// *** EDIT THIS VALUE TO MATCH THE ADAFRUIT PRODUCT ID FOR YOUR DISPLAY: *** +#define SCREEN_PRODUCT_ID 6178 // GC9A01A 240x240 round display +// You can find the product ID several ways: +// - "PID" accompanies each line-item on your receipt or order details page. +// - Visit adafruit.com and search for EYESPI displays. On product pages, +// PID is shown just below product title, and is at the end of URLs. +// - Check the comments in setup() later that reference various screens. + +// **** EDIT PINS TO MATCH YOUR WIRING **** +#define TFT_CS 10 // To display chip-select pin +#define TFT_RST 9 // To display reset pin +#define TFT_DC 8 // To display data/command pin +// For the remaining pins, this code assumes display is wired to hardware SPI +// on the dev board's primary SPI interface. The display libraries can support +// secondary SPI (if present) or bitbang (software) SPI, but that's not +// demonstrated here. See other examples for more varied interfacing options. +#include +#include // Core graphics library +#include // A custom font +#if (SCREEN_PRODUCT_ID == 1480) || (SCREEN_PRODUCT_ID == 2090) +#include // Library for ILI9341-based screens +Adafruit_ILI9341 display(TFT_CS, TFT_DC, TFT_RST); +#elif (SCREEN_PRODUCT_ID == 6178) +#include "Adafruit_GC9A01A.h" +Adafruit_GC9A01A display(TFT_CS, TFT_DC, TFT_RST); +#else +#include // Library for ST7789-based screens +Adafruit_ST7789 display(TFT_CS, TFT_DC, TFT_RST); +#endif + +#define PAUSE 3000 // Delay (millisecondss) between examples +uint8_t rotate = 0; // Current screen orientation (0-3) + +// setup() RUNS ONCE AT PROGRAM STARTUP ------------------------------------ + +void setup() { + // Initialize display hardware +#if (SCREEN_PRODUCT_ID == 5393) // 1.47" 320x172 round-rect TFT +#define CORNER_RADIUS 22 + display.init(172, 320); +#elif (SCREEN_PRODUCT_ID == 3787) // 240x240 TFT + display.init(240, 240); +#elif (SCREEN_PRODUCT_ID == 5206) // 1.69" 280x240 round-rect TFT +#define CORNER_RADIUS 43 + display.init(240, 280); +#elif (SCREEN_PRODUCT_ID == 5394) // 1.9" 320x170 TFT + display.init(170, 320); +#elif (SCREEN_PRODUCT_ID == 6113) + display.init(135, 240); +#else +#define CORNER_RADIUS 45// All ILI9341 & GC9A01A TFTs (320x240)/(240x240) + display.begin(); +#endif +#if !defined(CORNER_RADIUS) +#define CORNER_RADIUS 0 +#endif + + // OPTIONAL: default TFT SPI speed is fairly conservative, you can try + // overriding here for faster screen updates. Actual SPI speed may be less + // depending on microcontroller's capabilities. Max reliable speed also + // depends on wiring length and tidyness. + //display.setSPISpeed(40000000); +} + +// MAIN LOOP, REPEATS FOREVER ---------------------------------------------- + +void loop() { + // Each of these functions demonstrates a different Adafruit_GFX concept: + show_shapes(); + show_charts(); + show_basic_text(); + show_char_map(); + show_custom_text(); + show_bitmap(); +#if !defined(AVR) + // The full set of examples (plus the custom font) won't fit on an 8-bit + // Arduino, something's got to go. You can try out this one IF the other + // examples are disabled instead. + show_canvas(); +#endif + + if (++rotate > 3) rotate = 0; // Cycle through screen rotations 0-3 + display.setRotation(rotate); // Takes effect on next drawing command +} + +// BASIC SHAPES EXAMPLE ---------------------------------------------------- + +void show_shapes() { + const int16_t cx = display.width() / 2; // Center of screen = + const int16_t cy = display.height() / 2; // half of width, height + int16_t minor = min(cx, cy); // Lesser of half width or height + // Shapes will be drawn in a square region centered on the screen. But one + // particular screen -- rounded 240x280 ST7789 -- has VERY rounded corners + // that would clip a couple of shapes if drawn full size. If using that + // screen type, reduce area by a few pixels to avoid drawing in corners. + const uint8_t pad = 5; // Space between shapes is 2X this + const int16_t size = minor - pad; // Shapes are this width & height + const int16_t half = size / 2; // 1/2 of shape size + + // Rectangle + display.fillScreen(0); + display.drawRect(cx - half, cy - half, size, size, 0xF800); + delay(500); + + display.fillScreen(0); + display.fillRect(cx - half, cy - half, size, size, 0xF800); + delay(500); + + // Triangle + display.fillScreen(0); + display.drawTriangle( + cx, cy - half, // Top + cx - half, cy + half, // Bottom left + cx + half, cy + half, // Bottom right + 0x07E0 + ); + delay(500); + + display.fillScreen(0); + display.fillTriangle( + cx, cy - half, // Top + cx - half, cy + half, // Bottom left + cx + half, cy + half, // Bottom right + 0x07E0 + ); + delay(500); + + // Circle + display.fillScreen(0); + display.drawCircle(cx, cy, half, 0x001F); + delay(500); + + display.fillScreen(0); + display.fillCircle(cx, cy, half, 0x001F); + delay(500); + + // Rounded Rectangle + display.fillScreen(0); + display.drawRoundRect(cx - half, cy - half, size, size, size/5, 0xFFE0); + delay(500); + + display.fillScreen(0); + display.fillRoundRect(cx - half, cy - half, size, size, size/5, 0xFFE0); + delay(500); +} + +// CHART EXAMPLES ---------------------------------------------------------- + +void show_charts() { + // Draw some graphs and charts. GFX library doesn't handle these as native + // object types, but it only takes a little code to build them from simple + // shapes. This demonstrates: + // - Drawing points and horizontal, vertical and arbitrary lines. + // - Adapting to different-sized displays. + // - Graphics being clipped off edge. + // - Use of negative values to draw shapes "backward" from an anchor point. + // - C technique for finding array size at runtime (vs hardcoding). + + display.fillScreen(0); // Clear screen + + const int16_t cx = display.width() / 2; // Center of screen = + const int16_t cy = display.height() / 2; // half of width, height + const int16_t minor = min(cx, cy); // Lesser of half width or height + const int16_t major = max(cx, cy); // Greater of half width or height + + // Let's start with a relatively simple sine wave graph with axes. + // Draw graph axes centered on screen. drawFastHLine() and drawFastVLine() + // need fewer arguments than normal 2-point line drawing shown later. + display.drawFastHLine(0, cy, display.width(), 0x0210); // Dark blue + display.drawFastVLine(cx, 0, display.height(), 0x0210); + + // Then draw some tick marks along the axes. To keep this code simple, + // these aren't to any particular scale, but a real program may want that. + // The loop here draws them from the center outward and pays no mind + // whether the screen is rectangular; any ticks that go off-screen will + // be clipped by the library. + for (uint8_t i=1; i<=10; i++) { + // The Arduino map() function scales an input value (e.g. "i") from an + // input range (0-10 here) to an output range (0 to major-1 here). + // Very handy for making graphics adjust to different screens! + int16_t n = map(i, 0, 10, 0, major - 1); // Tick offset relative to center point + display.drawFastVLine(cx - n, cy - 5, 11, 0x210); + display.drawFastVLine(cx + n, cy - 5, 11, 0x210); + display.drawFastHLine(cx - 5, cy - n, 11, 0x210); + display.drawFastHLine(cx - 5, cy + n, 11, 0x210); + } + + // Then draw sine wave over this using GFX drawPixel() function. + for (int16_t x=0; x(str.c_str())); +} + +// TEXT EXAMPLES ----------------------------------------------------------- + +// This section demonstrates: +// - Using the default 5x7 built-in font, including scaling in each axis. +// - How to access all characters of this font, including symbols. +// - Using a custom font, including alignment techniques that aren't a normal +// part of the GFX library (uses functions above). + +void show_basic_text() { + // Show text scaling with built-in font. + display.fillScreen(0); + display.setFont(); // Use default font + display.setCursor(50, CORNER_RADIUS); // Initial cursor position + display.setTextSize(1); // Default size + display.println(F("Standard built-in font")); + display.setTextSize(2); + display.setCursor(30, display.getCursorY()); + display.println(F("BIG TEXT")); + display.setTextSize(3); + // "BIGGER TEXT" won't fit on narrow screens, so abbreviate there. + display.setCursor(20, display.getCursorY()); + display.println((display.width() >= 200) ? F("BIGGER TEXT") : F("BIGGER")); + display.setTextSize(2, 4); + display.setCursor(15, display.getCursorY()); + display.println(F("TALL and")); + display.setCursor(15, display.getCursorY()); + display.setTextSize(4, 2); + display.println(F("WIDE")); + + delay(PAUSE); +} // END BASIC TEXT EXAMPLE + +void show_char_map() { + // "Code Page 437" is a name given to the original IBM PC character set. + // Despite age and limited language support, still seen in small embedded + // settings as it has some useful symbols and accented characters. The + // default 5x7 pixel font of Adafruit_GFX is modeled after CP437. This + // function draws a table of all the characters & explains some issues. + + // There are 256 characters in all. Draw table as 16 rows of 16 columns, + // plus hexadecimal row & column labels. How big can each cell be drawn? + const int cell_size = min(display.width(), display.height()) / 17; + if (cell_size < 8) return; // Screen is too small for table, skip example. + const int total_size = cell_size * 17; // 16 cells + 1 row or column label + + // Set up for default 5x7 font at 1:1 scale. Custom fonts are NOT used + // here as most are only 128 characters to save space (the "7b" at the + // end of many GFX font names means "7 bits," i.e. 128 characters). + display.setFont(); + display.setTextSize(1); + + // Early Adafruit_GFX was missing one symbol, throwing off some indices! + // But fixing the library would break MANY existing sketches that relied + // on the degrees symbol and others. The default behavior is thus "broken" + // to keep older code working. New code can access the CORRECT full CP437 + // table by calling this function like so: + display.cp437(true); + + display.fillScreen(0); + + const int16_t x = (display.width() - total_size) / 2; // Upper left corner of + int16_t y = (display.height() - total_size) / 2; // table centered on screen + if (y >= 4) { // If there's a little extra space above & below, scoot table + y += 4; // down a few pixels and show a message centered at top. + display.setCursor((display.width() - 114) / 2, 0); // 114 = pixel width + display.print(F("CP437 Character Map")); // of this message + } + + const int16_t inset_x = (cell_size - 5) / 2; // To center each character within cell, + const int16_t inset_y = (cell_size - 8) / 2; // compute X & Y offset from corner. + + for (uint8_t row=0; row<16; row++) { // 16 down... + // Draw row and columm headings as hexadecimal single digits. To get the + // hex value for a specific character, combine the left & top labels, + // e.g. Pi symbol is row E, column 3, thus: display.print((char)0xE3); + display.setCursor(x + (row + 1) * cell_size + inset_x, y + inset_y); + display.print(row, HEX); // This actually draws column labels + display.setCursor(x + inset_x, y + (row + 1) * cell_size + inset_y); + display.print(row, HEX); // and THIS is the row labels + for (uint8_t col=0; col<16; col++) { // 16 across... + if ((row + col) & 1) { // Fill alternating cells w/gray + display.fillRect(x + (col + 1) * cell_size, y + (row + 1) * cell_size, + cell_size, cell_size, 0x630C); + } + // drawChar() bypasses usual cursor positioning to go direct to an X/Y + // location. If foreground & background match, it's drawn transparent. + display.drawChar(x + (col + 1) * cell_size + inset_x, + y + (row + 1) * cell_size + inset_y, row * 16 + col, + 0xFFFF, 0xFFFF, 1); + } + } + + delay(PAUSE * 2); +} // END CHAR MAP EXAMPLE + +void show_custom_text() { + // Show use of custom fonts, plus how to do center or right alignment + // using some additional functions provided earlier. + + display.fillScreen(0); + display.setFont(&FreeSansBold18pt7b); + display.setTextSize(1); + display.setTextWrap(false); // Allow text off edges + + // Get "M height" of custom font and move initial base line there: + uint16_t w, h; + int16_t x, y; + display.getTextBounds("M", 0, 0, &x, &y, &w, &h); + // On rounded 240x280 display in tall orientation, "Custom Font" gets + // clipped by top corners. Scoot text down a few pixels in that one case. + if ((CORNER_RADIUS && (display.height() == 280)) || (SCREEN_PRODUCT_ID == 6178)) h += 20; + display.setCursor(display.width() / 2, h); + + if ((display.width() >= 200) && (SCREEN_PRODUCT_ID != 6178)) { + print_aligned(display, F("Custom Font"), GFX_ALIGN_CENTER); + display.setCursor(0, display.getCursorY() + 10); + print_aligned(display, F("Align Left"), GFX_ALIGN_LEFT); + display.setCursor(display.width() / 2, display.getCursorY()); + print_aligned(display, F("Centered"), GFX_ALIGN_CENTER); + // Small rounded screen, when oriented the wide way, "Right" gets + // clipped by bottom right corner. Scoot left to compensate. + int16_t x_offset = (CORNER_RADIUS && (display.height() < 200)) ? 15 : 0; + display.setCursor(display.width() - x_offset, display.getCursorY()); + print_aligned(display, F("Align Right"), GFX_ALIGN_RIGHT); + } else { + display.setCursor(display.width() / 2, display.height() / 2); + print_aligned(display, F("Custom Font"), GFX_ALIGN_CENTER); + + } + + delay(PAUSE); +} // END CUSTOM FONT EXAMPLE + +// BITMAP EXAMPLE ---------------------------------------------------------- + +// This section demonstrates: +// - Embedding a small bitmap in the code (flash memory). +// - Drawing that bitmap in various colors, and transparently (only '1' bits +// are drawn; '0' bits are skipped, leaving screen contents in place). +// - Use of the color565() function to decimate 24-bit RGB to 16 bits. + +#define HEX_WIDTH 16 // Bitmap width in pixels +#define HEX_HEIGHT 16 // Bitmap height in pixels +// Bitmap data. PROGMEM ensures it's in flash memory (not RAM). And while +// it would be valid to leave the brackets empty here (i.e. hex_bitmap[]), +// having dimensions with a little math makes the compiler verify the +// correct number of bytes are present in the list. +PROGMEM const uint8_t hex_bitmap[(HEX_WIDTH + 7) / 8 * HEX_HEIGHT] = { + 0b00000001, 0b10000000, + 0b00000111, 0b11100000, + 0b00011111, 0b11111000, + 0b01111111, 0b11111110, + 0b01111111, 0b11111110, + 0b01111111, 0b11111110, + 0b01111111, 0b11111110, + 0b01111111, 0b11111110, + 0b01111111, 0b11111110, + 0b01111111, 0b11111110, + 0b01111111, 0b11111110, + 0b01111111, 0b11111110, + 0b01111111, 0b11111110, + 0b00011111, 0b11111000, + 0b00000111, 0b11100000, + 0b00000001, 0b10000000, +}; +#define Y_SPACING (HEX_HEIGHT - 2) // Used by code below for positioning + +void show_bitmap() { + display.fillScreen(0); + + // Not screen center, but UL coordinates of center hexagon bitmap + const int16_t center_x = (display.width() - HEX_WIDTH) / 2; + const int16_t center_y = (display.height() - HEX_HEIGHT) / 2; + const uint8_t steps = min((display.height() - HEX_HEIGHT) / Y_SPACING, + display.width() / HEX_WIDTH - 1) / 2; + + display.drawBitmap(center_x, center_y, hex_bitmap, HEX_WIDTH, HEX_HEIGHT, + 0xFFFF); // Draw center hexagon in white + + // Tile the hexagon bitmap repeatedly in a range of hues. Don't mind the + // bit of repetition in the math, the optimizer easily picks this up. + // Also, if math looks odd, keep in mind "PEMDAS" operator precedence; + // multiplication and division occur before addition and subtraction. + for (uint8_t a=0; a<=steps; a++) { + for (uint8_t b=1; b<=steps; b++) { + display.drawBitmap( // Right section centered red: a = green, b = blue + center_x + (a + b) * HEX_WIDTH / 2, + center_y + (a - b) * Y_SPACING, + hex_bitmap, HEX_WIDTH, HEX_HEIGHT, + display.color565(255, 255 - 255 * a / steps, 255 - 255 * b / steps)); + display.drawBitmap( // UL section centered green: a = blue, b = red + center_x - b * HEX_WIDTH + a * HEX_WIDTH / 2, + center_y - a * Y_SPACING, + hex_bitmap, HEX_WIDTH, HEX_HEIGHT, + display.color565(255 - 255 * b / steps, 255, 255 - 255 * a / steps)); + display.drawBitmap( // LL section centered blue: a = red, b = green + center_x - a * HEX_WIDTH + b * HEX_WIDTH / 2, + center_y + b * Y_SPACING, + hex_bitmap, HEX_WIDTH, HEX_HEIGHT, + display.color565(255 - 255 * a / steps, 255 - 255 * b / steps, 255)); + } + } + + delay(PAUSE); +} // END BITMAP EXAMPLE + +// CANVAS EXAMPLE ---------------------------------------------------------- + +// This section demonstrates: +// - How to refresh changing values onscreen without erase/redraw flicker. +// - Using an offscreen canvas. It's similar to a bitmap above, but rather +// than a fixed pattern in flash memory, it's drawable like the screen. +// - More tips on text alignment, and adapting to different screen sizes. + +#define PADDING 6 // Pixels between axis label and value + +void show_canvas() { + // For this example, let's suppose we want to display live readings from a + // sensor such as a three-axis accelerometer, something like: + // X: (number) + // Y: (number) + // Z: (number) + // To look extra classy, we want a custom font, and the labels for each + // axis are right-aligned so the ':' characters line up... + + display.setFont(&FreeSansBold18pt7b); // Use a custom font + display.setTextSize(1); // and reset to 1:1 scale + + const char *label[] = { "X:", "Y:", "Z:" }; // Labels for each axis + const uint16_t color[] = { 0xF800, 0x07E0, 0x001F }; // Colors for each value + + // To get the labels right-aligned, one option would be simple trial and + // error to find a column that looks good and doesn't clip anything off. + // Let's do this dynamically though, so it adapts to any font or labels! + // Start by finding the widest of the label strings: + uint16_t w, h, max_w = 0; + int16_t x, y; + for (uint8_t i=0; i<3; i++) { // For each label... + display.getTextBounds(label[i], 0, 0, &x, &y, &w, &h); + if (w > max_w) max_w = w; // Keep track of widest label + } + + // Rounded corners throwing us a curve again. If needed, scoot everything + // to the right a bit on wide displays, down a bit on tall ones. + int16_t y_offset = 0; + if (display.width() > display.height()) max_w += CORNER_RADIUS; + else y_offset = CORNER_RADIUS; + + // Now we have max_w for right-aligning the labels. Before we draw them + // though...in order to perform flicker-free updates, the numbers we show + // will be rendered in either a GFXcanvas1 or GFXcanvas16 object; a 1-bit + // or 16-bit offscreen bitmap, RAM permitting. The correct size for this + // canvas could also be trial-and-errored, but again let's make this adapt + // automatically. The width of the canvas will span from max_w (plus a few + // pixels for padding) to the right edge. But the height? Looking at an + // uppercase 'M' can work in many situations, but some fonts have ascenders + // and descenders on digits, and in some locales a comma (extending below + // the baseline) is the decimal separator. Feed ALL the numeric chars into + // getTextBounds() for a cumulative height: + display.setTextWrap(false); // Keep on one line + display.getTextBounds(F("0123456789.,-"), 0, 0, &x, &y, &w, &h); + + // Now declare a GFXcanvas16 object based on the computed width & height: + GFXcanvas16 canvas16(display.width() - max_w - PADDING, h); + + // Small devices (e.g. ATmega328p) will almost certainly lack enough RAM + // for the canvas. Check if canvas buffer exists. If not, fall back on + // using a 1-bit (rather than 16-bit) canvas. Much more RAM friendly, but + // not as fast to draw. If a project doesn't require super interactive + // updates, consider just going straight for the more compact Canvas1. + if (canvas16.getBuffer()) { + // If here, 16-bit canvas allocated successfully! Point of interest, + // only one canvas is needed for this example, we can reuse it for all + // three numbers because the regions are the same size. + + // display and canvas are independent drawable objects; must explicitly + // set the same custom font to use on the canvas now: + canvas16.setFont(&FreeSansBold18pt7b); + + // Clear display and print labels. Once drawn, these remain untouched. + display.fillScreen(0); + display.setCursor(max_w, -y + y_offset); // Set baseline for first row + for (uint8_t i=0; i<3; i++) print_aligned(display, label[i], GFX_ALIGN_RIGHT); + + // Last part now is to print numbers on the canvas and copy the canvas to + // the display, repeating for several seconds... + uint32_t elapsed, startTime = millis(); + while ((elapsed = (millis() - startTime)) <= PAUSE * 2) { + for (uint8_t i=0; i<3; i++) { // For each label... + canvas16.fillScreen(0); // fillScreen() in this case clears canvas + canvas16.setCursor(0, -y); // Reset baseline for custom font + canvas16.setTextColor(color[i]); + // These aren't real accelerometer readings, just cool-looking numbers. + // Notice we print to the canvas, NOT the display: + canvas16.print(sin(elapsed / 200.0 + (float)i * M_PI * 2.0 / 3.0), 5); + // And HERE is the secret sauce to flicker-free updates. Canvas details + // can be passed to the drawRGBBitmap() function, which fully overwrites + // prior screen contents in that area. yAdvance is font line spacing. + display.drawRGBBitmap(max_w + PADDING, i * FreeSansBold18pt7b.yAdvance + + y_offset, canvas16.getBuffer(), canvas16.width(), + canvas16.height()); + } + } + } else { + // Insufficient RAM for Canvas16. Try declaring a 1-bit canvas instead... + GFXcanvas1 canvas1(display.width() - max_w - PADDING, h); + // If even this smaller object fails, can't proceed, cancel this example. + if (!canvas1.getBuffer()) return; + + // Remainder here is nearly identical to the code above, simply using a + // different canvas type. It's stripped of most comments for brevity. + canvas1.setFont(&FreeSansBold18pt7b); + display.fillScreen(0); + display.setCursor(max_w, -y + y_offset); + for (uint8_t i=0; i<3; i++) print_aligned(display, label[i], GFX_ALIGN_RIGHT); + uint32_t elapsed, startTime = millis(); + while ((elapsed = (millis() - startTime)) <= PAUSE * 2) { + for (uint8_t i=0; i<3; i++) { + canvas1.fillScreen(0); + canvas1.setCursor(0, -y); + canvas1.print(sin(elapsed / 200.0 + (float)i * M_PI * 2.0 / 3.0), 5); + // Here's the secret sauce to flicker-free updates with GFXcanvas1. + // Canvas details can be passed to the drawBitmap() function, and by + // specifying both a foreground AND BACKGROUND color (0), this will fully + // overwrite/erase prior screen contents in that area (vs transparent). + display.drawBitmap(max_w + PADDING, i * FreeSansBold18pt7b.yAdvance + + y_offset, canvas1.getBuffer(), canvas1.width(), + canvas1.height(), color[i], 0); + } + } + } + + // Because canvas object was declared locally to this function, it's freed + // automatically when the function returns; no explicit delete needed. +} // END CANVAS EXAMPLE diff --git a/GC9A01A_Demo_Code/CircuitPython_GC9A01A/blinka_round.bmp b/GC9A01A_Demo_Code/CircuitPython_GC9A01A/blinka_round.bmp new file mode 100644 index 000000000..9c4ce8434 Binary files /dev/null and b/GC9A01A_Demo_Code/CircuitPython_GC9A01A/blinka_round.bmp differ diff --git a/GC9A01A_Demo_Code/CircuitPython_GC9A01A/code.py b/GC9A01A_Demo_Code/CircuitPython_GC9A01A/code.py new file mode 100644 index 000000000..9e8c8fab9 --- /dev/null +++ b/GC9A01A_Demo_Code/CircuitPython_GC9A01A/code.py @@ -0,0 +1,61 @@ +# SPDX-FileCopyrightText: 2025 Liz Clark for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +import time +import board +import displayio +import terminalio +from adafruit_display_text.bitmap_label import Label +import adafruit_imageload +from fourwire import FourWire +from vectorio import Circle +from adafruit_gc9a01a import GC9A01A + +spi = board.SPI() +tft_cs = board.D5 +tft_dc = board.D6 +tft_reset = board.D9 + +displayio.release_displays() + +display_bus = FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=tft_reset) +display = GC9A01A(display_bus, width=240, height=240) + +# --- Default Shapes/Text Demo --- +main_group = displayio.Group() +display.root_group = main_group + +bg_bitmap = displayio.Bitmap(240, 240, 2) +color_palette = displayio.Palette(2) +color_palette[0] = 0x00FF00 # Bright Green +color_palette[1] = 0xAA0088 # Purple + +bg_sprite = displayio.TileGrid(bg_bitmap, pixel_shader=color_palette, x=0, y=0) +main_group.append(bg_sprite) + +inner_circle = Circle(pixel_shader=color_palette, x=120, y=120, radius=100, color_index=1) +main_group.append(inner_circle) + +text_group = displayio.Group(scale=2, x=50, y=120) +text = "Hello World!" +text_area = Label(terminalio.FONT, text=text, color=0xFFFF00) +text_group.append(text_area) # Subgroup for text scaling +main_group.append(text_group) + +# --- ImageLoad Demo --- +blinka_group = displayio.Group() +bitmap, palette = adafruit_imageload.load("/blinka_round.bmp", + bitmap=displayio.Bitmap, + palette=displayio.Palette) + +grid = displayio.TileGrid(bitmap, pixel_shader=palette) +blinka_group.append(grid) + +while True: + # show shapes/text + display.root_group = main_group + time.sleep(2) + # show blinka bitmap + display.root_group = blinka_group + time.sleep(2) diff --git a/GC9A01A_Demo_Code/Python_GC9A01A/blinka_round.jpg b/GC9A01A_Demo_Code/Python_GC9A01A/blinka_round.jpg new file mode 100644 index 000000000..2a7630855 Binary files /dev/null and b/GC9A01A_Demo_Code/Python_GC9A01A/blinka_round.jpg differ diff --git a/GC9A01A_Demo_Code/Python_GC9A01A/code.py b/GC9A01A_Demo_Code/Python_GC9A01A/code.py new file mode 100644 index 000000000..e5ff06116 --- /dev/null +++ b/GC9A01A_Demo_Code/Python_GC9A01A/code.py @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: 2025 Liz Clark for Adafruit Industries +# SPDX-FileCopyrightText: Adapted from Melissa LeBlanc-Williams's Pi Demo Code +# +# SPDX-License-Identifier: MIT + +'''Raspberry Pi Graphics example for the 240x240 Round Display''' + +import time +import digitalio +import board +from PIL import Image, ImageDraw, ImageFont +from adafruit_rgb_display import gc9a01a + +BORDER = 20 +FONTSIZE = 24 + +cs_pin = digitalio.DigitalInOut(board.CE0) +dc_pin = digitalio.DigitalInOut(board.D25) +reset_pin = digitalio.DigitalInOut(board.D27) + +BAUDRATE = 24000000 + + +spi = board.SPI() + +disp = gc9a01a.GC9A01A(spi, rotation=0, + width=240, height=240, + x_offset=0, y_offset=0, + cs=cs_pin, + dc=dc_pin, + rst=reset_pin, + baudrate=BAUDRATE, +) + +width = disp.width +height = disp.height + +# -------TEXT AND SHAPES--------- +image1 = Image.new("RGB", (width, height)) +draw1 = ImageDraw.Draw(image1) +draw1.ellipse((0, 0, width, height), fill=(0, 255, 0)) # Green background + +draw1.ellipse( + (BORDER, BORDER, width - BORDER - 1, height - BORDER - 1), fill=(170, 0, 136) +) +font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", FONTSIZE) +text = "Hello World!" +(font_width, font_height) = font.getsize(text) +draw1.text( + (width // 2 - font_width // 2, height // 2 - font_height // 2), + text, + font=font, + fill=(255, 255, 0), +) + +# ------ADABOT JPEG DISPLAY---------- +image2 = Image.open("blinka_round.jpg") +image_ratio = image2.width / image2.height +screen_ratio = width / height +scaled_width = width +scaled_height = image2.height * width // image2.width +image2 = image2.resize((scaled_width, scaled_height), Image.BICUBIC) +x = scaled_width // 2 - width // 2 +y = scaled_height // 2 - height // 2 +image2 = image2.crop((x, y, x + width, y + height)) + +while True: + disp.image(image1) # show text + time.sleep(2) + disp.image(image2) # show adabot + time.sleep(2) diff --git a/Trinkey_QT2040_Enviro_Gadget/arduino/trinkey_qt2040_enviro/trinkey_qt2040_enviro.ino b/Trinkey_QT2040_Enviro_Gadget/arduino/trinkey_qt2040_enviro/trinkey_qt2040_enviro.ino index 4ea2ab447..2c7189c3f 100755 --- a/Trinkey_QT2040_Enviro_Gadget/arduino/trinkey_qt2040_enviro/trinkey_qt2040_enviro.ino +++ b/Trinkey_QT2040_Enviro_Gadget/arduino/trinkey_qt2040_enviro/trinkey_qt2040_enviro.ino @@ -4,7 +4,7 @@ #include #include -#include +#include #include //--| User Config |----------------------------------------------- @@ -15,7 +15,7 @@ //---------------------------------------------------------------- Adafruit_BME280 bme; -SensirionI2CScd4x scd4x; +SensirionI2cScd4x scd4x; Adafruit_NeoPixel neopixel(1, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800); uint16_t CO2, data_ready; @@ -36,9 +36,9 @@ void setup() { Serial.println("Failed to initialize BME280."); neoPanic(); } - + Wire.begin(); // init SCD40 - scd4x.begin(Wire); + scd4x.begin(Wire, SCD41_I2C_ADDR_62); scd4x.stopPeriodicMeasurement(); if (scd4x.startPeriodicMeasurement()) { Serial.println("Failed to start SCD40."); diff --git a/library.deps b/library.deps index 681b8cd0d..c25f99062 100644 --- a/library.deps +++ b/library.deps @@ -1 +1 @@ -depends=Adafruit ILI9341, Adafruit BusIO, SD, Adafruit NeoPixel, Adafruit VS1053 Library, Adafruit BluefruitLE nRF51, Adafruit seesaw Library, Ethernet, Adafruit IO Arduino, FastLED, Adafruit LiquidCrystal, Adafruit SoftServo, TinyWireM, Adafruit AM radio library, WaveHC, Adafruit LED Backpack Library, MAX31850 OneWire, Adafruit VC0706 Serial Camera Library, RTClib, Adafruit SleepyDog Library, Adafruit Thermal Printer Library, Adafruit Zero I2S Library, Adafruit EPD, Adafruit SSD1351 library, Adafruit FONA Library, Adafruit Motor Shield V2 Library, Adafruit NeoMatrix, Adafruit Soundboard library, Adafruit Circuit Playground, ArduinoJson, Adafruit TCS34725, Adafruit Pixie, Adafruit GPS Library, TinyGPS, WiFi101, Adafruit DotStar, Adafruit Si7021 Library, Adafruit WS2801 Library, Mouse, Keyboard, Time, IRremote, Adafruit LSM9DS0 Library, Adafruit Arcada Library, MIDIUSB, PubSubClient, Adafruit LIS2MDL, Adafruit NeoPXL8, Adafruit MCP23017 Arduino Library, Adafruit MLX90640, LiquidCrystal, Adafruit NeoTrellis M4 Library, RGB matrix Panel, Adafruit MLX90614 Library, Adafruit RGB LCD Shield Library, MAX6675 library, Adafruit MP3, Adafruit Keypad, Adafruit Arcada GifDecoder, Keypad, Neosegment, Encoder, Adafruit TiCoServo, Adafruit Trellis Library, FauxmoESP, Adafruit LSM303 Accel, Adafruit LSM303DLH Mag, Adafruit LSM303DLHC, CapacitiveSensor, Adafruit Zero PDM Library, Adafruit DMA neopixel library, elapsedMillis, DST RTC, Adafruit SHARP Memory Display, Adafruit SPIFlash, BSEC Software Library, WiiChuck, Adafruit DPS310, Adafruit AHTX0, RotaryEncoder, Adafruit MCP9808 Library, LSM303, Adafruit Protomatter, Adafruit IS31FL3741 Library, Sensirion I2C SCD4x, Adafruit TestBed, Bounce2, Adafruit AHRS, Adafruit DRV2605 Library, STM32duino VL53L4CD, PicoDVI - Adafruit Fork, Adafruit MMA8451 Library, Adafruit TSC2007, GFX Library for Arduino, Adafruit PyCamera Library, Adafruit ADG72x, Adafruit BNO055, Adafruit SHT4x Library, Adafruit VCNL4200 Library +depends=Adafruit ILI9341, Adafruit BusIO, SD, Adafruit NeoPixel, Adafruit VS1053 Library, Adafruit BluefruitLE nRF51, Adafruit seesaw Library, Ethernet, Adafruit IO Arduino, FastLED, Adafruit LiquidCrystal, Adafruit SoftServo, TinyWireM, Adafruit AM radio library, WaveHC, Adafruit LED Backpack Library, MAX31850 OneWire, Adafruit VC0706 Serial Camera Library, RTClib, Adafruit SleepyDog Library, Adafruit Thermal Printer Library, Adafruit Zero I2S Library, Adafruit EPD, Adafruit SSD1351 library, Adafruit FONA Library, Adafruit Motor Shield V2 Library, Adafruit NeoMatrix, Adafruit Soundboard library, Adafruit Circuit Playground, ArduinoJson, Adafruit TCS34725, Adafruit Pixie, Adafruit GPS Library, TinyGPS, WiFi101, Adafruit DotStar, Adafruit Si7021 Library, Adafruit WS2801 Library, Mouse, Keyboard, Time, IRremote, Adafruit LSM9DS0 Library, Adafruit Arcada Library, MIDIUSB, PubSubClient, Adafruit LIS2MDL, Adafruit NeoPXL8, Adafruit MCP23017 Arduino Library, Adafruit MLX90640, LiquidCrystal, Adafruit NeoTrellis M4 Library, RGB matrix Panel, Adafruit MLX90614 Library, Adafruit RGB LCD Shield Library, MAX6675 library, Adafruit MP3, Adafruit Keypad, Adafruit Arcada GifDecoder, Keypad, Neosegment, Encoder, Adafruit TiCoServo, Adafruit Trellis Library, FauxmoESP, Adafruit LSM303 Accel, Adafruit LSM303DLH Mag, Adafruit LSM303DLHC, CapacitiveSensor, Adafruit Zero PDM Library, Adafruit DMA neopixel library, elapsedMillis, DST RTC, Adafruit SHARP Memory Display, Adafruit SPIFlash, BSEC Software Library, WiiChuck, Adafruit DPS310, Adafruit AHTX0, RotaryEncoder, Adafruit MCP9808 Library, LSM303, Adafruit Protomatter, Adafruit IS31FL3741 Library, Sensirion I2C SCD4x, Adafruit TestBed, Bounce2, Adafruit AHRS, Adafruit DRV2605 Library, STM32duino VL53L4CD, PicoDVI - Adafruit Fork, Adafruit MMA8451 Library, Adafruit TSC2007, GFX Library for Arduino, Adafruit PyCamera Library, Adafruit ADG72x, Adafruit BNO055, Adafruit SHT4x Library, Adafruit VCNL4200 Library, Adafruit GC9A01A