ST7789 support for Adafruit 1.54" 240x240 Wide Angle TFT LCD Display with MicroSD

Status
Not open for further replies.

gt3073b

New member
ST7789 support for Adafruit 1.54" 240x240 Wide Angle TFT LCD Display with MicroSD

I'm trying to use the Adafruit 1.54" 240x240 Wide Angle TFT LCD Display with MicroSD that uses the ST7789 chip (https://www.adafruit.com/product/3787). It appears the Teensy optimized library in the latest Teensyduino 1.44 on has the older ST7735 supported, but not the ST7789. Is there a plan to update the library to match the latest Adafruit code? If not, what do I need to do to use the Adafruit code? Do I use the slower example that isnt using the Arduino hardware, which I'm guessing is just bit banging?

I'm using an old Teensy 3.0, and the modified example code below. The images are drawn way off into one corner with noise over most of the screen. My code is below.

Thank you,
Bryan.


Code:
// This Teensy3 native optimized version requires specific pins
//
#define sclk 13  // SCLK can also use pin 14
#define mosi 11  // MOSI can also use pin 7
#define cs   10  // CS & DC can use pins 2, 6, 9, 10, 15, 20, 21, 22, 23
#define dc   9   //  but certain pairs must NOT be used: 2+10, 6+9, 20+23, 21+22
#define rst  8   // RST can use any pin
#define sdcs 4   // CS for SD card, can use any pin

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>

#if defined(__SAM3X8E__)
    #undef __FlashStringHelper::F(string_literal)
    #define F(string_literal) string_literal
#endif

Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);
const float p = 3.1415926;

#define startPin 3
#define stopPin 5

elapsedMillis measuredTime;
volatile long capturedTime;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(sdcs, INPUT_PULLUP);  // keep SD CS high when not using SD card
  pinMode(startPin, INPUT_PULLUP);
  pinMode(stopPin, INPUT_PULLUP);

  // If your TFT's plastic wrap has a Black Tab, use the following:
  //tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
  // If your TFT's plastic wrap has a Red Tab, use the following:
  //tft.initR(INITR_REDTAB);   // initialize a ST7735R chip, red tab
  // If your TFT's plastic wrap has a Green Tab, use the following:
  tft.initR(INITR_GREENTAB); // initialize a ST7735R chip, green tab

  Serial.println("begin demo code");
  
  tft.fillScreen(ST7735_YELLOW);
  testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", ST7735_WHITE);
  delay(1000);

  // tft print function!
  tftPrintTest();
  delay(4000);

  // a single pixel
  tft.drawPixel(tft.width()/2, tft.height()/2, ST7735_GREEN);
  delay(500);

  // line draw test
  testlines(ST7735_YELLOW);
  delay(500);

  // optimized lines
  testfastlines(ST7735_RED, ST7735_BLUE);
  delay(500);

  testdrawrects(ST7735_GREEN);
  delay(500);

  testfillrects(ST7735_YELLOW, ST7735_MAGENTA);
  delay(500);

  tft.fillScreen(ST7735_BLACK);
  testfillcircles(10, ST7735_BLUE);
  testdrawcircles(10, ST7735_WHITE);
  delay(500);

  testroundrects();
  delay(500);

  testtriangles();
  delay(500);

  mediabuttons();
  delay(500);

  Serial.println("done");
  delay(1000);

  
  Serial.println("Ready to run timer.");
  attachInterrupt(digitalPinToInterrupt(startPin), startISR, FALLING);
  interrupts();
}

void loop() {
  // put your main code here, to run repeatedly:
  if (measuredTime > 5000)
  {
    attachInterrupt(digitalPinToInterrupt(startPin), startISR, FALLING);
    Serial.println("I'm not dead yet!");
    measuredTime = 0;
  }
  if (capturedTime > 0)
  {
    Serial.print("Elapsed Time: ");
    Serial.print(capturedTime);
    Serial.println(" ms");
    capturedTime = 0;
  }
}

void startISR() {
  noInterrupts();
  measuredTime = 0;
  attachInterrupt(digitalPinToInterrupt(stopPin), stopISR, FALLING);
  detachInterrupt(digitalPinToInterrupt(startPin));
  interrupts();
}

void stopISR() {
  noInterrupts();
  attachInterrupt(digitalPinToInterrupt(startPin), startISR, FALLING);
  detachInterrupt(digitalPinToInterrupt(stopPin));
  capturedTime = measuredTime;
  interrupts();  
}







// Demo code
void testlines(uint16_t color) {
  tft.fillScreen(ST7735_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(0, 0, x, tft.height()-1, color);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(0, 0, tft.width()-1, y, color);
  }

  tft.fillScreen(ST7735_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(tft.width()-1, 0, 0, y, color);
  }

  tft.fillScreen(ST7735_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(0, tft.height()-1, x, 0, color);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(0, tft.height()-1, tft.width()-1, y, color);
  }

  tft.fillScreen(ST7735_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color);
  }
}

void testdrawtext(const char *text, uint16_t color) {
  tft.setCursor(0, 0);
  tft.setTextColor(color);
  tft.setTextWrap(true);
  tft.print(text);
}

void testfastlines(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST7735_BLACK);
  for (int16_t y=0; y < tft.height(); y+=5) {
    tft.drawFastHLine(0, y, tft.width(), color1);
  }
  for (int16_t x=0; x < tft.width(); x+=5) {
    tft.drawFastVLine(x, 0, tft.height(), color2);
  }
}

void testdrawrects(uint16_t color) {
  tft.fillScreen(ST7735_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color);
  }
}

void testfillrects(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST7735_BLACK);
  for (int16_t x=tft.width()-1; x > 6; x-=6) {
    tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1);
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2);
  }
}

void testfillcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=radius; x < tft.width(); x+=radius*2) {
    for (int16_t y=radius; y < tft.height(); y+=radius*2) {
      tft.fillCircle(x, y, radius, color);
    }
  }
}

void testdrawcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=0; x < tft.width()+radius; x+=radius*2) {
    for (int16_t y=0; y < tft.height()+radius; y+=radius*2) {
      tft.drawCircle(x, y, radius, color);
    }
  }
}

void testtriangles() {
  tft.fillScreen(ST7735_BLACK);
  int color = 0xF800;
  int t;
  int w = 63;
  int x = 159;
  int y = 0;
  int z = 127;
  for(t = 0 ; t <= 15; t+=1) {
    tft.drawTriangle(w, y, y, x, z, x, color);
    x-=4;
    y+=4;
    z-=4;
    color+=100;
  }
}

void testroundrects() {
  tft.fillScreen(ST7735_BLACK);
  int color = 100;
  int i;
  int t;
  for(t = 0 ; t <= 4; t+=1) {
    int x = 0;
    int y = 0;
    int w = 127;
    int h = 159;
    for(i = 0 ; i <= 24; i+=1) {
      tft.drawRoundRect(x, y, w, h, 5, color);
      x+=2;
      y+=3;
      w-=4;
      h-=6;
      color+=1100;
    }
    color+=100;
  }
}

void tftPrintTest() {
  tft.setTextWrap(false);
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(ST7735_RED);
  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ST7735_YELLOW);
  tft.setTextSize(2);
  tft.println("Hello World!");
  tft.setTextColor(ST7735_GREEN);
  tft.setTextSize(3);
  tft.println("Hello World!");
  tft.setTextColor(ST7735_BLUE);
  tft.setTextSize(4);
  tft.print(1234.567);
  delay(1500);
  tft.setCursor(0, 0);
  tft.fillScreen(ST7735_BLACK);
  tft.setTextColor(ST7735_WHITE);
  tft.setTextSize(0);
  tft.println("Hello World!");
  tft.setTextSize(1);
  tft.setTextColor(ST7735_GREEN);
  tft.print(p, 6);
  tft.println(" Want pi?");
  tft.println(" ");
  tft.print(8675309, HEX); // print 8,675,309 out in HEX!
  tft.println(" Print HEX!");
  tft.println(" ");
  tft.setTextColor(ST7735_WHITE);
  tft.println("Sketch has been");
  tft.println("running for: ");
  tft.setTextColor(ST7735_MAGENTA);
  tft.print(millis() / 1000);
  tft.setTextColor(ST7735_WHITE);
  tft.print(" seconds.");
}

void mediabuttons() {
  // play
  tft.fillScreen(ST7735_BLACK);
  tft.fillRoundRect(25, 10, 78, 60, 8, ST7735_WHITE);
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST7735_RED);
  delay(500);
  // pause
  tft.fillRoundRect(25, 90, 78, 60, 8, ST7735_WHITE);
  tft.fillRoundRect(39, 98, 20, 45, 5, ST7735_GREEN);
  tft.fillRoundRect(69, 98, 20, 45, 5, ST7735_GREEN);
  delay(500);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST7735_BLUE);
  delay(50);
  // pause color
  tft.fillRoundRect(39, 98, 20, 45, 5, ST7735_RED);
  tft.fillRoundRect(69, 98, 20, 45, 5, ST7735_RED);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST7735_GREEN);
}
 
Update: the Adafruit libraries from github work. I don’t know if they are using hardware spi or bit banging though. It seems slow, but I dont have anything to compare it to. It would be nice to know if the current code is going to be re-optimized.
 
Update: the Adafruit libraries from github work. I don’t know if they are using hardware spi or bit banging though. It seems slow, but I dont have anything to compare it to.

Why don't you just analyze that library's source code to see how it's done? I often found, not with PJRC but with many other libraries found on GitHub, that these are are made to make things just work in whatever way, but without doing all possible optimisations. I use this kind of lazy libraries for studying purposes, to learn how things can basically be done, and then as a starting point to write my own optimized code.
 
Unfortunately, I've been complaining about this for over two years now. I just use the Adafruit version. Note, I think the most recent versions of the library now need changes in the Adafruit-GFX library as well.

The Adafruit version of the library does not have the specific Teensy optimizations that use the hardware CS/DC pins that the Teensy version has. After they added the 128x128 bit support, Adafruit restructured the entire library to add support for another chipset and other displays like your 240x240 display.

IIRC, I believe the Adafruit library does use hardware SPI if you use the right constructor. It just doesn't do the optimization with DMA that Paul put in the library.

Off hand, I would suspect you probably don't have enough memory in the Teensy's to hold the entire display in memory.
 
Thanks

Update: the Adafruit libraries from github work. I don’t know if they are using hardware spi or bit banging though. It seems slow, but I dont have anything to compare it to. It would be nice to know if the current code is going to be re-optimized.

Thanks for posting this! I'd installed a clean arduino package, teensyduino w/o graphics and used the arduino library manager to get the 'latest' adafruit graphics drivers and was unsure where to look for my problem--wouldn't have suspected github was the answer!
 
Update: the Adafruit libraries from github work.
How you made the 1.54" working?
Can you post how you initilized the TFT by using the ST7789 libs by Adafruit?

For now, all I've got is a black screen on my 22 pins TFT purchased on Aliexpress. Backlight-LEDs are working, but the screen gave no sign of life... :confused:

Here below my test code.
All I can do is to init the display by using the init(width, height) function:
Code:
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library
#include <Adafruit_ST77xx.h> // just for colo defs
#include <SPI.h>

#define TFT_RST    2   // chip reset
#define TFT_DC     3   // tells the display if you're sending data (D) or commands (C)   --> WR pin on TFT
#define TFT_MOSI   11  // Data out    (SPI standard)
#define TFT_SCLK   13  // Clock out   (SPI standard)
#define TFT_CS     15  // chip select (SPI standard)

//ST7735_t3 tft = ST7735_t3(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

void setup(void) {
  tft.init(240, 240);
  tft.fillScreen(ST77XX_BLUE);

  // up left
  tft.fillRect(0,0,10, 10,ST77XX_BLUE);
  tft.setCursor(12,12);
  tft.println("UP-LEFT");
  delay(500);

  // bottom right
  tft.fillRect(tft.width()-10, tft.height()-10, 10, 10, ST77XX_RED);
  tft.setCursor(tft.width()-82,tft.height()-20);
  tft.println("BOTTOM-RIGHT");
  delay(500);

  // area frame
  tft.drawRect(0,0, tft.width(), tft.height(), ST77XX_GREEN);
  delay(1000);
}
void loop() {
}
 
Status
Not open for further replies.
Back
Top