NEW: GC9A01A Display driver for Teensy 3.x and Teensy 4.x

I got my GC9A01A's in the mail. But they don't work with uncanny Eyes. I'll look at them tomorrow after work (probably wiring issue, and I mis-counted the pins). Should the backlight be attached to ground, 3.3v, or left floating?
 
Last edited:
@MichaelMeissner - Only got one display here just tried the two demos noted to work.
Somehow got wiring right the first time :)

As for backlight reading prior posts it said it would work on a pin powered up - one example had it in - the other when added also worked: See "BACKLIGHT_PIN":
examples/DemoSauce/DemoSauce.ino#L63

<edit>: for ref I got this from AMZN
 
@MichaelMeissner - Only got one display here just tried the two demos noted to work.
Somehow got wiring right the first time :)

As for backlight reading prior posts it said it would work on a pin powered up - one example had it in - the other when added also worked: See "BACKLIGHT_PIN":
examples/DemoSauce/DemoSauce.ino#L63

<edit>: for ref I got this from AMZN

Yep, as I thought I had the wiring wrong (I believe I forgot to add an extra pin to account for the ground pin). I got the first eye doing the graphicstest, and one or two of the other demos. Then I re-ran uncanny Eyes and it works. The second eye still does not work, but I suspect that I mis-counted the pins for the second eye. I'll look at it tomorrow when I get time.

I must say, it seems to be creepier with the round LCD than with the square LCD's.

I got my pair from Ebay
 
That ebay unit looks like the one AMZN sent - just ordered the last two from that seller. Not sure I like the large/thick connector.

And yes, the ROUNDED display at that resolution would offer a really creepy feel :eek:

Why is it that every wired display done here ends up rotated wrong - in this case FACE DOWN - on my workspace ???? :confused:
 
Yep, as I thought I had the wiring wrong (I believe I forgot to add an extra pin to account for the ground pin). I got the first eye doing the graphicstest, and one or two of the other demos. Then I re-ran uncanny Eyes and it works. The second eye still does not work, but I suspect that I mis-counted the pins for the second eye. I'll look at it tomorrow when I get time.

I must say, it seems to be creepier with the round LCD than with the square LCD's.

I got my pair from Ebay

Also You might make sure I have the pin numbers correct depending on which processor you are using.

My two I did both ways:

1st one Ebay: https://www.ebay.com/itm/185452865460
2nd one Amazon: https://smile.amazon.com/dp/B08V5538C6

Depended on expected dates...

That ebay unit looks like the one AMZN sent - just ordered the last two from that seller. Not sure I like the large/thick connector.

And yes, the ROUNDED display at that resolution would offer a really creepy feel :eek:

Why is it that every wired display done here ends up rotated wrong - in this case FACE DOWN - on my workspace ???? :confused:

Connectors me too. Although at least you don't have to solder anything.

Simple solution: rotate you desk 180 degrees :p

Yep that was my reaction as well.
Me too, which is why I ordered the 2nd one.

Still need to fix, i.e. figure out the horizontal mirror of one of the eyes.

I thought about playing with the newer generation of the Eyes code, but that would involve porting over a lot of system code, that I am not sure I have a strong enough pull to want to do all of that. Things like, they use their own filesystem, canvas, DMA setup... Would try to assist if others take it on. And I might pickup some of the interesting pieces, with some of the experiments I am doing now.
 
That ebay unit looks like the one AMZN sent - just ordered the last two from that seller. Not sure I like the large/thick connector.

Mine was from Waveshare, which makes many of these displays. But I would imagine over time there will be other clones made of the display.

And yes, the ROUNDED display at that resolution would offer a really creepy feel :eek:

Why is it that every wired display done here ends up rotated wrong - in this case FACE DOWN - on my workspace ???? :confused:

Yeah, mine seemed to want to always flop down on to the desk. For desk use, I may just make up a base and screw it in. The wiki doesn't say what size screw is used, nor the exact distance between the 4 screws. M2.5 is too large, I'm not sure if I have any M2 screws lying around. I assume it probably doesn't use units measured in inches (but 2-56 screws are slightly too big).

Also You might make sure I have the pin numbers correct depending on which processor you are using.

In this case, I was just using Teensy 4.1. I want to set up a breadboard (or maybe solder up a protoboard later) using the same color wires as they use in the connector, to make it simpler to re-connect things and swap them back and forth. Of course it would be simpler if the VCC pin used red wire (instead of purple) and the ground pin used black wire (instead of white), but that is fairly minor. I keep saying I want to create a wiring setup that has all of the pins from all of the displays I have on hand in a predefined order, that I can just make a combo cable for each display, and then plug and play. Something like:

  • Ground
  • VCC
  • SCLK
  • MOSI
  • MISO
  • CS #1
  • D/C
  • Reset
  • CS #2

Connectors me too. Although at least you don't have to solder anything.

I've seen that connector before, but I don't remember the name off-hand. It looks like it has standard 0.1" pitch.

Simple solution: rotate you desk 180 degrees :p
:p

Still need to fix, i.e. figure out the horizontal mirror of one of the eyes.

I thought about playing with the newer generation of the Eyes code, but that would involve porting over a lot of system code, that I am not sure I have a strong enough pull to want to do all of that. Things like, they use their own filesystem, canvas, DMA setup... Would try to assist if others take it on. And I might pickup some of the interesting pieces, with some of the experiments I am doing now.
Well I would hope the latest MTA/etc. changes would make the filesystem stuff easier, but the dma stuff might be harder.

One thing I wanted to try on the Teensy 4.x since we are now using 2 SPI systems (instead of the 1 SPI system used in 3.x with different CS pins), is to move the end code for USE_ASYNC_UPDATES from at the end of processing a single eye, to after processing both eyes. In theory, it should speed things up, assuming there is no bug in the system having multiple SPI systems in parallel being updated.

For reference the new code is in the M4_Eyes subdirectory of the Adafruit Learning System Guides
 
Last edited:
Well I would hope the latest MTA/etc. changes would make the filesystem stuff easier, but the dma stuff might be harder.

One thing I wanted to try on the Teensy 4.x since we are now using 2 SPI systems (instead of the 1 SPI system used in 3.x with different CS pins), is to move the end code for USE_ASYNC_UPDATES from at the end of processing a single eye, to after processing both eyes. In theory, it should speed things up, assuming there is no bug in the system having multiple SPI systems in parallel being updated.

For reference the new code is in the M4_Eyes subdirectory of the Adafruit Learning System Guides

Thanks, I already downloaded it. But you quickly run into issues. For example:

The sketch starts off with:
Code:
#if !defined(USE_TINYUSB)
  #error "Please select Tools->USB Stack->TinyUSB before compiling"
#endif

Now if you can get beyond that.
Side Note: I know with CircuitPython and MicroPython that they support/use TinyUSB, but my guess is, it will be unlikely to have that as one of our USB Type Options.

You then run into lot and lots of include libraries, many of them are specific to a different set of ARM boards.


#include "Adafruit_Arcada.h"
#include "DMAbuddy.h" // DMA-bug-workaround class

And if you go to the library manager to install Adafruit_Arcada you will find: Currently for SAMD21, SAMD51 and nRF52840 chipsets only

And it wants to install many more libraries, Maybe > 10...

So that is when my eyes glazed over.

As you mentioned, we have had the DMA stuff in place for the ST77xx code for awhile. In particular this one is mostly from our ST7789 240x240.
But so far we have only generated one set of eyes...

What might be fun is to import the code that the M4_Eyes has to convert the bitamps into the appropriate structures. @mjs513 and myself have now done some code that reads in the bitmaps and then generates header files from them.
Which we were playing with, with his Gauge...

An interesting thing is that They read in the BMP files from I believe SD card... Depending on which button is pressed. They convert the files into the formats and then write the structures to FLASH. Where the Flash is in the memory space and does not eat up the RAM.

So was looking at some of this. Which is some of the reasons for some of my sort of random postings, about maybe extensions to FS. Where we could create a simple FS on Program Flash, that could hopefully have the whole file in contiguous space... (PreAllocate) and Ask for starting sector... This on Flash would convert easily to memory location... As far as I know LittleFS would not work, so would maybe a simple Fat Flash setup. (Adafruit_InternalFlash library) With this they create a real simple BLOCKDEVICE object that they then have an instance of their FatFileSystem object which they then do a begin on passing in their blockdevice object...


Alternative, will be to Not use FS, but simply a reserve N pages of Flash and update them as appropriate...

But again totally random.
 
Ok, I mis-read the #ifdefs and for the second (right) eye, I was using the Teensy 3.5/3.6 defaults instead of the Teensy 4.1 defaults. I suspected that was probably the case
 
FWIW, the capability I've thought was really cool was on the Monster M4SK, which is a pair of 240x240 displays.

When I plug in the M4SK, it provides the flash as a removable disk as well as doing the eye patterns. I can have several eyes loaded, and I can edit the various parameters (or even replace the eye), and then reboot the microprocessor, instead of having to edit the source and re-build. Since the M4SK has 3 buttons, I can select a different eye when powering on the microprocessor by holding down a button while starting the processor. The M4 in the M4SK only has enough memory to hold one eye in memory at a time, but the T4.1 with psram might be able to hold multiple eyes, and you could jump between them.
 
Could be freaky like a POV horror movie to have a camera put video from the camera on the eyes.

Hmmmm, yeah that might get freaky. Plus I assume it would get quickly into feature overload mode. I would imagine with a PI, you might be able to take input from the camera, and clip it to the current iris size and then update that.

One of the things that I've thought about with my steampunk camera setup, is to have the painter squirrel (Livinea) hooked up with a easel that has a small monitor. I hook the monitor up to a camera, and it looks like the squirrel is painting the people in real time.

In 2014, I briefly did this with Leonardo Da Vinci helicopter build, where I put an Olympus TG-2 as the camera, and fed the output to an analog NTSC screen.


But the suitcase for the TG-2 has been dropped a few times and it needs to be rebuilt. Fortunately I think I still have one case that I could use (I bought them at A. C. Moore, which was absorbed by Michaels, but Michaels hasn't brought back some of the cheap wooden stuff A. C. Moore used to have). I would likely want to upgrade to the TG-5, but the TG-5 no longer does analog output. It would be nice if I could find a 2" HDMI display to use with the more modern cameras. At the moment, the smallest HDMI display I've seen is 5", which is a little large for what I want to do.

Also after building it, I realized that you really want the squirrel with her back to the people, so you can see the monitor clearly. But then with the older analog displays, I wouldn't be able to see it, without using a second monitor.

Another thought is to use a transparent display such as this OLED display from dfrobot.com.
 
@MichaelMeissner - I was wondering if those clear displays are as bright on both sides?

Indeed, adding a camera in the right spot is a bit beyond feature creep. But the testing done in MicroMod days left TFT on desk doing live video for days at over 10 fps.
 
In terms of the clear display, I don't have one. And the mono OLED is fairly small.

FWIW, I've been playing with adjusting the defaults.

I disabled the right eye (so I could check the results of moving the D/C pin) and I changed the D/C pin on the left eye from 9 to pin 37 or 36 (which are listed as CS pins). And it corrupted the display. If I changed the SPI frequency down to 8000000 or so, then it would display ok. If I moved the D/C pin back to 9 (not a CS pin), then it worked fine. With on eye, it would do about 22 frames a minute.

I turned off USE_ASYNC_UPDATES, and as expected it slow down the frame rate.

I bumped up the SPI frequency and it didn't seem to corrupt the display, but it didn't change the frame rate (~ 22 for a single eye, ~ 44 for two eyes).

<edit>
I also delayed waiting for clear out the dma queue until the 2nd eye had issued its changes (after checking there are 2 eyes, and the two SCLKs are different). While it worked, it didn't seem to change the frame rate.
 
Last edited:
Mine was from Waveshare, which makes many of these displays. But I would imagine over time there will be other clones made of the display.



Yeah, mine seemed to want to always flop down on to the desk. For desk use, I may just make up a base and screw it in. The wiki doesn't say what size screw is used, nor the exact distance between the 4 screws. M2.5 is too large, I'm not sure if I have any M2 screws lying around. I assume it probably doesn't use units measured in inches (but 2-56 screws are slightly too big).
...

I've seen that connector before, but I don't remember the name off-hand. It looks like it has standard 0.1" pitch.
...

One from AMZN has WaveShare on silkscreen. Two from eBay are indicated as shipped - hopefully same good units as @MichaelMeissner received from that link.

Would be nice to know the screw size, it is smaller than that 'tiny one' used on MicroMod hold down screw - don't remember the #'s for that I knew before when I got longer finger friendly versions and double nutted for use in Beta.

I have an 8 pin 0.10" connector/cable and it is too wide! A ruler suggests the pin spacing is 2mm.
 
M2 screws appear to fit it. At least I screwed one in and it felt right...

The product page mentions it is a PH2.0 connector so pretty sure 2mm
 
Speaking of uncanny eyes, has anybody tried uncannyEyes_async_st7789_240x240.ino recently? Now that I have the GC9A01A_t3n display running, I decided to bring my old Teensy 4.0 that was setup to use the 240x240 square displays and run them against each other. The code that I had installed on the T4 (from around the time the Teensy 4.0 came out and before the Teensy 4.1 was announced) didn't print the frame numbers, so I decided to rebuild it.

After rebuilding it, every time I run it, it prints up the logo screens. Then it does both eyes, and they move around a bit. It prints the first frame # and then the Teensy reboots (I assume bad pointer or such). I figured maybe something broke recently (using 1.57 beta3 and the Arduino 1.8.19 libraries), so I went to older Teensy installations (1.54 with Arduino 1.8.15, 1.55 with Arduino 1.8.16, etc.) and it seemed to crash there as well. I had to modify the config.h to use pin 0 for the right eye CS and pin 10 for the left eye CS.

Here is the config.h that I'm using, but I had also tried the example file directly with the above edits:

Code:
//#define SINGLE_EYE			// only do a single eye
//#define SERIAL_tt Serial // Send debug_tt output here. Must have SERIAL_tt.begin( ## )
//#include "debug_tt.h"

// Pin selections here are based on the original Adafruit Learning System
// guide for the Teensy 3.x project.  Some of these pin numbers don't even
// exist on the smaller SAMD M0 & M4 boards, so you may need to make other
// selections:

// GRAPHICS SETTINGS (appearance of eye) -----------------------------------

// If using a SINGLE EYE, you might want this next line enabled, which
// uses a simpler "football-shaped" eye that's left/right symmetrical.
// Default shape includes the caruncle, creating distinct left/right eyes.
// Otherwise your choice, standard is asymmetrical
  #define SYMMETRICAL_EYELID

// Enable ONE of these #includes -- HUGE graphics tables for various eyes:
#if( DISPLAY_SIZE == 240 )
#include "graphics/default_large.h"   // 240x240
#else
#include "graphics/defaultEye.h"      // Standard human-ish hazel eye -OR-
//#include "graphics/dragonEye.h"     // Slit pupil fiery dragon/demon eye -OR-
//#include "graphics/noScleraEye.h"   // Large iris, no sclera -OR-
//#include "graphics/goatEye.h"       // Horizontal pupil goat/Krampus eye -OR-
//#include "graphics/newtEye.h"       // Eye of newt -OR-
//#include "graphics/terminatorEye.h" // Git to da choppah!
//#include "graphics/catEye.h"        // Cartoonish cat (flat "2D" colors)
//#include "graphics/owlEye.h"        // Minerva the owl (DISABLE TRACKING)
//#include "graphics/naugaEye.h"      // Nauga googly eye (DISABLE TRACKING)
//#include "graphics/doeEye.h"        // Cartoon deer eye (DISABLE TRACKING)
//#include "graphics/Nebula.h"  //Dont work
//#include "graphics/MyEyeHuman1.h"
//#include "graphics/Human-HAL9000.h"
//#include "graphics/NebulaBlueGreen.h"
//#include "graphics/SpiralGalaxy.h"
//#include "graphics/ChameleonX_Eye.h"  //no work
//#include "graphics/MyEye.h"
#endif
// Optional: enable this line for startup logo (screen test/orient):
#if !defined(ADAFRUIT_HALLOWING)    // Hallowing can't always fit logo+eye
  #include "graphics/logo.h"        // Otherwise your choice, if it fits
#endif

// EYE LIST ----------------------------------------------------------------


// DISPLAY HARDWARE SETTINGS (screen type & connections) -------------------

  //#define TFT_SPI        SPI
  //#define TFT_PERIPH     PERIPH_SPI

  // Enable ONE of these #includes to specify the display type being used
  //#include <ST7735_t3.h> // TFT display library (enable one only)
  #include <ST7789_t3.h>
  
  #define SPI_FREQ 48000000    // TFT: use max SPI (clips to 12 MHz on M0)

// This table contains ONE LINE PER EYE.  The table MUST be present with
// this name and contain ONE OR MORE lines.  Each line contains THREE items:
// a pin number for the corresponding TFT/OLED display's SELECT line, a pin
// pin number for that eye's "wink" button (or -1 if not used), and a screen
// rotation value (0-3) for that eye.

eyeInfo_t eyeInfo[] =
{
#ifdef ST77XX_ON_SPI_SPI1

// SPI
//#define L_CS		-1			// left display, no CS pin
//#define L_CS		10			// left display, main CS pin for SPI
  #define L_CS		22			// left display, alternate CS, avoid I2S pins and avoid audio shield SD card
  #define L_DC		 9			// left display, D/C pin
  #define L_RST		 8			// left display, reset pin
  #define L_SCK		13			// left display, clock pin
  #define L_MOSI	11			// left display, MOSI pin
  #define L_WINK	-1			// left display, no wink
  #define L_ROT		 0			// left display, rotation
//#define L_INIT	 0			// left display, initialization for no CS pin display
  #define L_INIT	INITR_144GREENTAB	// left display, initialization for display with CS pin

// SPI1
//#define R_CS		-1			// right display, no CS pin
  #define R_CS		 0			// right display, main CS pin for SPI
  #define R_DC		25			// right display, D/C pin
  #define R_RST		 7			// right display, reset pin
  #define R_SCK		27			// right display, clock pin SPI1
  #define R_MOSI	26			// right display, MOSI pin SPI1
  #define R_WINK	-1			// right display, no wink
  #define R_ROT		 0			// right display, rotation
//#define R_INIT	0			// right display, initialization for no CS pin display
  #define R_INIT	INITR_144GREENTAB	// right display, initialization for display with CS pin

  //CS    DC    MOSI    SCK    RST    WINK    ROT    INIT
  { L_CS, L_DC, L_MOSI, L_SCK, L_RST, L_WINK, L_ROT, L_INIT },
#ifndef SINGLE_EYE
  { R_CS, R_DC, R_MOSI, R_SCK, R_RST, R_WINK, R_ROT, R_INIT },
#endif

#else
   {0,  2,  26, 27,  3, -1,  0, INITR_144GREENTAB }, // RIGHT EYE display-select and wink pins, no rotation
   {10, 9,  11, 13,  8, -1,  0, INITR_144GREENTAB }, // LEFT EYE display-select and wink pins, no rotation
#endif
};
// INPUT SETTINGS (for controlling eye motion) -----------------------------

// JOYSTICK_X_PIN and JOYSTICK_Y_PIN specify analog input pins for manually
// controlling the eye with an analog joystick.  If set to -1 or if not
// defined, the eye will move on its own.
// IRIS_PIN speficies an analog input pin for a photocell to make pupils
// react to light (or potentiometer for manual control).  If set to -1 or
// if not defined, the pupils will change on their own.
// BLINK_PIN specifies an input pin for a button (to ground) that will
// make any/all eyes blink.  If set to -1 or if not defined, the eyes will
// only blink if AUTOBLINK is defined, or if the eyeInfo[] table above
// includes wink button settings for each eye.

//#define JOYSTICK_X_PIN	  A0	// Analog pin for eye horiz pos (else auto)
//#define JOYSTICK_Y_PIN	  A1	// Analog pin for eye vert position (")
//#define JOYSTICK_X_FLIP		// If defined, reverse stick X axis
//#define JOYSTICK_Y_FLIP		// If defined, reverse stick Y axis


//#define TRACKING			// If defined, eyelid tracks pupil
//#define AUTOBLINK			// If defined, eyes also blink autonomously
  #define BLINK_PIN		   3	// Pin for manual blink button (BOTH eyes)
//#define LIGHT_PIN		  A9	// Photocell or potentiometer (else auto iris)
//#define LIGHT_PIN_FLIP		// If defined, reverse reading from dial/photocell
  #define LIGHT_MIN		   0	// Lower reading from sensor
  #define LIGHT_MAX		1023	// Upper reading from sensor

  #define IRIS_SMOOTH			// If enabled, filter input from IRIS_PIN
  #if DISPLAY_SIZE > 128
    #if !defined(IRIS_MIN)		// Each eye might have its own MIN/MAX
      #define IRIS_MIN		 500	// Iris size (0-1023) in brightest light
    #endif
    #if !defined(IRIS_MAX)
      #define IRIS_MAX		 700	// Iris size (0-1023) in darkest light
    #endif

  #else
    #if !defined(IRIS_MIN)		// Each eye might have its own MIN/MAX
      #define IRIS_MIN	120		// Iris size (0-1023) in brightest light
    #endif
    #if !defined(IRIS_MAX)
      #define IRIS_MAX	720		// Iris size (0-1023) in darkest light
    #endif
  #endif
 
M2 screws appear to fit it. At least I screwed one in and it felt right...

The product page mentions it is a PH2.0 connector so pretty sure 2mm

Yep. I can confirm that. The M2 screws I bought from the hardware store fit fine. But I will need to look around for much smaller M2 screws (h/w store only had 12m long screws, and I want something much shorter to allow me to attach the displays to something for mounting it.
 
@mjs513:

I've been making the GC9A01A uncanny eyes example into a library, so I can have different .ino files that have different # of eyes, different CS pins, etc. I noticed that there was a small typo in the example where it referred to a ST7735 inner function to do color mapping instead of GC9A01A. It is harmless since both libraries define the RGB mapping the same way. But you might want to fix it to be more type correct.

On line 54 of the uncannyEyes_GC9A01A.ino file, change:

Code:
#define RGBColor(r, g, b) ST7735_t3x::Color565(r, g, b)

to:

Code:
#define RGBColor(r, g, b) GC9A01A_t3n::Color565(r, g, b)

Whether you want to change the other ST7789 references to GC9A01A in the comments and debug #ifdefs is up to you.

Also I don't know if you wanted to delete the comment on line 213 that was left over from the ST7789 support for displays with no CS pin:

Code:
    // Try to handle the ST7789 displays without CS PINS.
 
@mjs513:

I've been making the GC9A01A uncanny eyes example into a library, so I can have different .ino files that have different # of eyes, different CS pins, etc. I noticed that there was a small typo in the example where it referred to a ST7735 inner function to do color mapping instead of GC9A01A. It is harmless since both libraries define the RGB mapping the same way. But you might want to fix it to be more type correct.

On line 54 of the uncannyEyes_GC9A01A.ino file, change:

Code:
#define RGBColor(r, g, b) ST7735_t3x::Color565(r, g, b)

to:

Code:
#define RGBColor(r, g, b) GC9A01A_t3n::Color565(r, g, b)

Whether you want to change the other ST7789 references to GC9A01A in the comments and debug #ifdefs is up to you.

Also I don't know if you wanted to delete the comment on line 213 that was left over from the ST7789 support for displays with no CS pin:

Code:
    // Try to handle the ST7789 displays without CS PINS.

Thanks Michael - just pushed the changes to uncannyeyes up to repository :)
 
Does anyone know how I can flip/mirror an image?
I wrote code for the round LCD and it worked fine, now the square LCD with same code is image mirrored.
I'd rather just flip the image to fix it.
 
Is it flipped or rotated? If it is just rotated, there is a class function setRotation that rotates the image 0, 90, 180, or 270 degrees. If it is a mirror image, you would need to do something like use 240 - x or 240 - y to change the position being written to.
 
Yes some of the uncanny eye code versions are setup to mirror one of the eyes. It does this by setting the MADCTL or the like register.

Note sure if I experimented with these displays to know if we found a set of flags that made it work or not.
 
Back
Top