Teensy version of Adafruit_ST7735 needs updating

MichaelMeissner

Senior Member+
It was reported in the adafruit forums (https://forums.adafruit.com/viewtopic.php?f=8&t=81387) that the uncanny eyes tutorial does not build on the current teensyduino.

As a matter of coincidence, I had become interested in the same project, and I had just received two 1.44" 128x128 screens from an ebay seller (http://www.ebay.com/itm/122005165823?_trksid=p2060353.m2749.l2649&ssPageName=STRK:MEBIDX:IT).

I haven't gotten to the point of wiring up the displays, but I did verify that the tutorial does not build, due to INITR_144GREENTAB not being defined in the Teensy ST7735 source (but it is in the current Adafruit source). Here are the errors, including a typo in the uncanny eyes source:

Code:
 /home/meissner/Arduino/teensy-eyes/uncannyEyes/uncannyEyes.ino:460:17: warning: extra tokens at end of #ifdef directive [enabled by default]
 #ifdef IRIS_PIN && (IRIS_PIN >= 0) // Interactive iris
                 ^
uncannyEyes: In function 'void setup()':
uncannyEyes:105: error: 'INITR_144GREENTAB' was not declared in this scope
     eye[e].display.initR(INITR_144GREENTAB);
                          ^

If I fix line 460 to be:

Code:
 #if defined(IRIS_PIN) && (IRIS_PIN >= 0) // Interactive iris

and replace hardware/teensy/avr/libraries/Adafruit_ST7735 with a link to the current Adafruit libraries, it now compiles, but it has some warnings in the library:

Code:
WARNING: Spurious .github folder in 'Adafruit ST7735 Library' library
uncannyEyes: In function 'void frame(uint16_t)':
uncannyEyes:327: warning: comparison between signed and unsigned integer expressions 
     if((t - eye[eyeIndex].blink.startTime) >= eye[eyeIndex].blink.duration) {
                                                                   ^
uncannyEyes:404: warning: comparison between signed and unsigned integer expressions 
     if(s >= eye[eyeIndex].blink.duration) s = 255;   // At or past blink end
                                 ^
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp: In member function 'void Adafruit_GFX::drawChar(int16_t, int16_t, unsigned char, uint16_t, uint16_t, uint8_t)':
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp:566:14: warning: unused variable 'xa' [-Wunused-variable]
              xa = pgm_read_byte(&glyph->xAdvance);
              ^
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp: In member function 'void Adafruit_GFX::drawBitmap(int16_t, int16_t, const uint8_t*, int16_t, int16_t, uint16_t)':
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp:392:27: warning: 'byte' may be used uninitialized in this function [-Wmaybe-uninitialized]
       if(i & 7) byte <<= 1;
                           ^
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp: In member function 'void Adafruit_GFX::drawBitmap(int16_t, int16_t, const uint8_t*, int16_t, int16_t, uint16_t, uint16_t)':
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp:410:27: warning: 'byte' may be used uninitialized in this function [-Wmaybe-uninitialized]
       if(i & 7) byte <<= 1;
                           ^
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp: In member function 'void Adafruit_GFX::drawBitmap(int16_t, int16_t, uint8_t*, int16_t, int16_t, uint16_t)':
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp:427:27: warning: 'byte' may be used uninitialized in this function [-Wmaybe-uninitialized]
       if(i & 7) byte <<= 1;
                           ^
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp: In member function 'void Adafruit_GFX::drawBitmap(int16_t, int16_t, uint8_t*, int16_t, int16_t, uint16_t, uint16_t)':
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp:443:27: warning: 'byte' may be used uninitialized in this function [-Wmaybe-uninitialized]
       if(i & 7) byte <<= 1;
                           ^
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp: In member function 'void Adafruit_GFX::drawXBitmap(int16_t, int16_t, const uint8_t*, int16_t, int16_t, uint16_t)':
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp:462:27: warning: 'byte' may be used uninitialized in this function [-Wmaybe-uninitialized]
       if(i & 7) byte >>= 1;
                           ^
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp: In member function 'void Adafruit_GFX::drawChar(int16_t, int16_t, unsigned char, uint16_t, uint16_t, uint8_t)':
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp:600:9: warning: 'bits' may be used uninitialized in this function [-Wmaybe-uninitialized]
         if(bits & 0x80) {
         ^
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp:604:47: warning: 'yo16' may be used uninitialized in this function [-Wmaybe-uninitialized]
             fillRect(x+(xo16+xx)*size, y+(yo16+yy)*size, size, size, color);
                                               ^
/rock/shared/arduino/teensy-1.30-beta1-1.6.8/hardware/teensy/avr/libraries/Adafruit_GFX/Adafruit_GFX.cpp:570:14: warning: 'xo16' may be used uninitialized in this function [-Wmaybe-uninitialized]
     int16_t  xo16, yo16;
              ^

Sketch uses 186,216 bytes (71%) of program storage space. Maximum is 262,144 bytes.
Global variables use 4,896 bytes (7%) of dynamic memory, leaving 60,640 bytes for local variables. Maximum is 65,536 bytes.

Unfortunately, the source is too large too post inside of {code} and {/code} tags. I have added uncannyEyes.ino as an attachment, but you will need to load defaultEye.h from the uncanny eyes tutorial.
 

Attachments

  • uncannyEyes.ino
    20.9 KB · Views: 141
Since this is more about the 128x128 support and not the basic Teensy 3.6 support (which Paul has updated the missing #if defined to treat the 3.5/3.6 like the 3.1/3.2), I am moving it back to this thread. Here is the thread, I posted the patch in:

I attempted to merge in the 128x128 support from Adafruit and it does not seem to work. I don't have the standard 128x64 display to test it.

On both the 3.1 and 3.6 static is displayed on the screens rather than the eyes. If I fall back to the Adafruit libraries the 3.6 can display both eyes, while the 3.1 can only display 1 eye. Note, in looking at the sketch, the sketch does all of the heavy lifting itself, and once setup, only does SPI.beginTransaction and SPI.endTransation in the main loop. So, I imagine it is dependent on something in the Adafruit initialization.

Here is the basic configuration for pins that I used:

Code:
#define DISPLAY_DC     A1  // Data/command pin for BOTH displays
#define DISPLAY_RESET   8 // Reset pin for BOTH displays
#define SELECT_L_PIN    9 // LEFT eye chip select pin
#define SELECT_R_PIN   10 // RIGHT eye chip select pin

// INPUT CONFIG (for eye motion -- enable or comment out as needed) --------

//#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 set, reverse stick X axis
//#define JOYSTICK_Y_FLIP   // If set, reverse stick Y axis
//#define TRACKING          // If enabled, eyelid tracks pupil
//#define IRIS_PIN       A2 // Photocell or potentiometer (else auto iris)
//#define IRIS_PIN_FLIP     // If set, reverse reading from dial/photocell
#define IRIS_SMOOTH       // If enabled, filter input from IRIS_PIN
#define IRIS_MIN      120 // Clip lower analogRead() range from IRIS_PIN
#define IRIS_MAX      720 // Clip upper "
#define WINK_L_PIN      0 // Pin for LEFT eye wink button
#define BLINK_PIN       3 // Pin for blink button (BOTH eyes)
#define WINK_R_PIN      1 // Pin for RIGHT eye wink button
#define AUTOBLINK         // If enabled, eyes blink autonomously

Here is the display that I got:

I soon will be switching to the Adafruit OLED displays. Given mostly the same code is used for the OLED, I don't know if I will have similar issues.

For reference, here is the patch I mentioned in the previous thread:
Code:
Index: Adafruit_ST7735.cpp
===================================================================
--- Adafruit_ST7735.cpp (revision 61)
+++ Adafruit_ST7735.cpp (working copy)
@@ -1,10 +1,15 @@
-/*************************************************** 
+/***************************************************
   This is a library for the Adafruit 1.8" SPI display.
-  This library works with the Adafruit 1.8" TFT Breakout w/SD card
+
+This library works with the Adafruit 1.8" TFT Breakout w/SD card
   ----> http://www.adafruit.com/products/358
-  as well as Adafruit raw 1.8" TFT display
+The 1.8" TFT shield
+  ----> https://www.adafruit.com/product/802
+The 1.44" TFT breakout
+  ----> https://www.adafruit.com/product/2088
+as well as Adafruit raw 1.8" TFT display
   ----> http://www.adafruit.com/products/618
- 
+
   Check out the links above for our tutorials and wiring diagrams
   These displays use SPI to communicate, 4 or 5 pins are required to
   interface (RST is optional)
@@ -25,7 +30,7 @@
 
 // Constructor when using software SPI.  All output pins are configurable.
 Adafruit_ST7735::Adafruit_ST7735(uint8_t cs, uint8_t rs, uint8_t sid,
- uint8_t sclk, uint8_t rst) : Adafruit_GFX(ST7735_TFTWIDTH, ST7735_TFTHEIGHT)
+ uint8_t sclk, uint8_t rst) : Adafruit_GFX(ST7735_TFTWIDTH, ST7735_TFTHEIGHT_18)
 {
        _cs   = cs;
        _rs   = rs;
@@ -39,7 +44,7 @@
 // Constructor when using hardware SPI.  Faster, but must use SPI pins
 // specific to each board type (e.g. 11,13 for Uno, 51,52 for Mega, etc.)
 Adafruit_ST7735::Adafruit_ST7735(uint8_t cs, uint8_t rs, uint8_t rst) :
-  Adafruit_GFX(ST7735_TFTWIDTH, ST7735_TFTHEIGHT) {
+  Adafruit_GFX(ST7735_TFTWIDTH, ST7735_TFTHEIGHT_18) {
        _cs   = cs;
        _rs   = rs;
        _rst  = rst;
@@ -233,6 +238,8 @@
        if (pin == 2 || pin == 6 || pin == 9) return true;
        if (pin == 10 || pin == 15) return true;
        if (pin >= 20 && pin <= 23) return true;
+       Serial.print ("spi_pin_is_cs failed, ");
+       Serial.println (pin);
        return false;
 }
 
@@ -249,6 +256,8 @@
                 case 22: CORE_PIN22_CONFIG = PORT_PCR_MUX(2); return 0x08; // PTC1
                 case 15: CORE_PIN15_CONFIG = PORT_PCR_MUX(2); return 0x10; // PTC0
         }
+       Serial.print ("spi_configure_cs_pin failed, ");
+       Serial.println (pin);
         return 0;
 }
 
@@ -467,6 +476,15 @@
       0x00, 0x00,             //     XSTART = 0
       0x00, 0x9F },           //     XEND = 159
 
+  Rcmd2green144[] = {              // Init for 7735R, part 2 (green 1.44 tab)
+    2,                        //  2 commands in list:
+    ST7735_CASET  , 4      ,  //  1: Column addr set, 4 args, no delay:
+      0x00, 0x00,             //     XSTART = 0
+      0x00, 0x7F,             //     XEND = 127
+    ST7735_RASET  , 4      ,  //  2: Row addr set, 4 args, no delay:
+      0x00, 0x00,             //     XSTART = 0
+      0x00, 0x7F },           //     XEND = 127
+
   Rcmd3[] = {                 // Init for 7735R, part 3 (red or green tab)
     4,                        //  4 commands in list:
     ST7735_GMCTRP1, 16      , //  1: Magical unicorn dust, 16 args, no delay:
@@ -701,6 +719,11 @@
                commandList(Rcmd2green);
                colstart = 2;
                rowstart = 1;
+       } else if(options == INITR_144GREENTAB) {
+               _height = ST7735_TFTHEIGHT_144;
+               commandList(Rcmd2green144);
+               colstart = 2;
+               rowstart = 3;
        } else {
                // colstart, rowstart left at default '0' values
                commandList(Rcmd2red);
@@ -811,7 +834,12 @@
                        writedata(MADCTL_MX | MADCTL_MY | MADCTL_BGR);
                }
                _width  = ST7735_TFTWIDTH;
-               _height = ST7735_TFTHEIGHT;
+
+               if (tabcolor == INITR_144GREENTAB) 
+                 _height = ST7735_TFTHEIGHT_144;
+               else
+                 _height = ST7735_TFTHEIGHT_18;
+
                break;
        case 1:
                if (tabcolor == INITR_BLACKTAB) {
@@ -819,7 +847,12 @@
                } else {
                        writedata(MADCTL_MY | MADCTL_MV | MADCTL_BGR);
                }
-               _width  = ST7735_TFTHEIGHT;
+
+               if (tabcolor == INITR_144GREENTAB) 
+                 _width = ST7735_TFTHEIGHT_144;
+               else
+                 _width = ST7735_TFTHEIGHT_18;
+
                _height = ST7735_TFTWIDTH;
                break;
        case 2:
@@ -829,7 +862,11 @@
                        writedata(MADCTL_BGR);
                }
                _width  = ST7735_TFTWIDTH;
-               _height = ST7735_TFTHEIGHT;
+               if (tabcolor == INITR_144GREENTAB) 
+                 _height = ST7735_TFTHEIGHT_144;
+               else
+                 _height = ST7735_TFTHEIGHT_18;
+
                break;
        case 3:
                if (tabcolor == INITR_BLACKTAB) {
@@ -837,7 +874,11 @@
                } else {
                        writedata(MADCTL_MX | MADCTL_MV | MADCTL_BGR);
                }
-               _width  = ST7735_TFTHEIGHT;
+               if (tabcolor == INITR_144GREENTAB) 
+                 _width = ST7735_TFTHEIGHT_144;
+               else
+                 _width = ST7735_TFTHEIGHT_18;
+
                _height = ST7735_TFTWIDTH;
                break;
        }
Index: Adafruit_ST7735.h
===================================================================
--- Adafruit_ST7735.h   (revision 61)
+++ Adafruit_ST7735.h   (working copy)
@@ -1,10 +1,15 @@
 /***************************************************
   This is a library for the Adafruit 1.8" SPI display.
-  This library works with the Adafruit 1.8" TFT Breakout w/SD card
+
+This library works with the Adafruit 1.8" TFT Breakout w/SD card
   ----> http://www.adafruit.com/products/358
-  as well as Adafruit raw 1.8" TFT display
+The 1.8" TFT shield
+  ----> https://www.adafruit.com/product/802
+The 1.44" TFT breakout
+  ----> https://www.adafruit.com/product/2088
+as well as Adafruit raw 1.8" TFT display
   ----> http://www.adafruit.com/products/618
- 
+
   Check out the links above for our tutorials and wiring diagrams
   These displays use SPI to communicate, 4 or 5 pins are required to
   interface (RST is optional)
@@ -44,8 +49,16 @@
 #define INITR_REDTAB   0x1
 #define INITR_BLACKTAB   0x2
 
+#define INITR_18GREENTAB    INITR_GREENTAB
+#define INITR_18REDTAB      INITR_REDTAB
+#define INITR_18BLACKTAB    INITR_BLACKTAB
+#define INITR_144GREENTAB   0x1
+
 #define ST7735_TFTWIDTH  128
-#define ST7735_TFTHEIGHT 160
+// for 1.44" display
+#define ST7735_TFTHEIGHT_144 128
+// for 1.8" display
+#define ST7735_TFTHEIGHT_18  160
 
 #define ST7735_NOP     0x00
 #define ST7735_SWRESET 0x01
@@ -100,7 +113,7 @@
 #define        ST7735_GREEN   0x07E0
 #define ST7735_CYAN    0x07FF
 #define ST7735_MAGENTA 0xF81F
-#define ST7735_YELLOW  0xFFE0  
+#define ST7735_YELLOW  0xFFE0
 #define ST7735_WHITE   0xFFFF

Here is the code to draw an eye from the source:

Code:
void drawEye( // Renders one eye.  Inputs must be pre-clipped & valid.
  uint8_t  e,       // Eye array index; 0 or 1 for left/right
  uint32_t iScale,  // Scale factor for iris
  uint8_t  scleraX, // First pixel X offset into sclera image
  uint8_t  scleraY, // First pixel Y offset into sclera image
  uint8_t  uT,      // Upper eyelid threshold value
  uint8_t  lT) {    // Lower eyelid threshold value

  uint8_t  screenX, screenY, scleraXsave;
  int16_t  irisX, irisY;
  uint16_t p, a;
  uint32_t d;

  // Set up raw pixel dump to entire screen.  Although such writes can wrap
  // around automatically from end of rect back to beginning, the region is
  // reset on each frame here in case of an SPI glitch.
  SPI.beginTransaction(settings);
#ifdef _ADAFRUIT_ST7735H_ // TFT
  eye[e].display.setAddrWindow(0, 0, 127, 127);
#else // OLED
  eye[e].display.writeCommand(SSD1351_CMD_SETROW);    // Y range
  eye[e].display.writeData(0); eye[e].display.writeData(SCREEN_HEIGHT - 1);
  eye[e].display.writeCommand(SSD1351_CMD_SETCOLUMN); // X range
  eye[e].display.writeData(0); eye[e].display.writeData(SCREEN_WIDTH  - 1);
  eye[e].display.writeCommand(SSD1351_CMD_WRITERAM);  // Begin write
#endif
  digitalWrite(eye[e].cs, LOW);                       // Chip select
  digitalWrite(DISPLAY_DC, HIGH);                     // Data mode
  // Now just issue raw 16-bit values for every pixel...

  scleraXsave = scleraX; // Save initial X value to reset on each line
  irisY       = scleraY - (SCLERA_HEIGHT - IRIS_HEIGHT) / 2;
  for(screenY=0; screenY<SCREEN_HEIGHT; screenY++, scleraY++, irisY++) {
    scleraX = scleraXsave;
    irisX   = scleraXsave - (SCLERA_WIDTH - IRIS_WIDTH) / 2;
    for(screenX=0; screenX<SCREEN_WIDTH; screenX++, scleraX++, irisX++) {
      if((lower[screenY][screenX] <= lT) ||
         (upper[screenY][screenX] <= uT)) {             // Covered by eyelid
        p = 0;
      } else if((irisY < 0) || (irisY >= IRIS_HEIGHT) ||
                (irisX < 0) || (irisX >= IRIS_WIDTH)) { // In sclera
        p = sclera[scleraY][scleraX];
      } else {                                          // Maybe iris...
        p = polar[irisY][irisX];                        // Polar angle/dist
        d = (iScale * (p & 0x7F)) / 128;                // Distance (Y)
        if(d < IRIS_MAP_HEIGHT) {                       // Within iris area
          a = (IRIS_MAP_WIDTH * (p >> 7)) / 512;        // Angle (X)
          p = iris[d][a];                               // Pixel = iris
        } else {                                        // Not in iris
          p = sclera[scleraY][scleraX];                 // Pixel = sclera
        }
      }
      // SPI FIFO technique from Paul Stoffregen's ILI9341_t3 library:
      while(KINETISK_SPI0.SR & 0xC000); // Wait for space in FIFO
      KINETISK_SPI0.PUSHR = p | SPI_PUSHR_CTAS(1) | SPI_PUSHR_CONT;
    }
  }

  KINETISK_SPI0.SR |= SPI_SR_TCF;         // Clear transfer flag
  while((KINETISK_SPI0.SR & 0xF000) ||    // Wait for SPI FIFO to drain
       !(KINETISK_SPI0.SR & SPI_SR_TCF)); // Wait for last bit out
  digitalWrite(eye[e].cs, HIGH);          // Deselect
  SPI.endTransaction();
}
 
Back
Top