ST7789_fast library and 240*320 display

Hi, I am in the exact same situation as the one described here

My display is labeled GMT020-02 and is a cheap 2.0" TFT bought on aliexpress. (See link above)

I understand some solution or workaround was found but as the topic is closed, I have to ask here if anyone could tell me if it is actually possible to use a 320*240 display with this library ?
The display works fine with the adafruit library, but I'd prefer using ST7789_fast because… :thinking: well, it is faster :slight_smile:

I already tried modifying these values in the library

#define ST7789_TFTWIDTH
#define ST7789_TFTHEIGHT

as well as

#define SCR_WD   240
#define SCR_HT   320

but it does not seem to work...
Any help will be greatly appreciated, thanks in advance !

Provide a description of the behavior and errors you observe. Include your hardware details and an example sketch.

My mistake ! Bad link in my first post, of course some crucial informations are missing.

The issue was discussed in this post ⟶ https://forum.arduino.cc/t/the-320x240-display-does-not-fully-work-with-the-arduino-st7789-fast-library/1034154

Anyway : here is the video of what is happening : https://www.dropbox.com/scl/fi/pwxs3vcdxwvi1yjkl07ye/IMG_5700.MOV?rlkey=z3f53oxzy5uv13fqnv4678k88&dl=0

As for the sketch, I am just using the "ST7789_Adafruit_Benchmark" from the "Fast ST7789 Library" written by Pawel A. Hernik. I tried changing some values but it did not seem to have any effect. In my video, you can see that the screen is only used as if it was a 240*240 display, even though I changed

#define SCR_WD   240
#define SCR_HT   240
#include <SPI.h>
#include <Adafruit_GFX.h>

into

#define SCR_WD   240
#define SCR_HT   320
#include <SPI.h>
#include <Adafruit_GFX.h>

If changing these values have no effect, I wonder what they are here for...

I tried another example (ST7789_HelloWorld) from the same library

#define TFT_CS    8
#define TFT_DC    9
#define TFT_RST   10 
#define SCR_WD   240
#define SCR_HT   240  // 320 - to allow access to full 240x320 frame buffer
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Arduino_ST7789_Fast.h>
//Arduino_ST7789 lcd = Arduino_ST7789(TFT_DC, TFT_RST);
Arduino_ST7789 lcd = Arduino_ST7789(TFT_DC, TFT_RST, TFT_CS);

void setup(void) 
{
  Serial.begin(9600);
  lcd.init(SCR_WD, SCR_HT);
  lcd.fillScreen(BLACK);
  lcd.setCursor(0, 0);
  lcd.setTextColor(WHITE,BLUE);
  lcd.setTextSize(3);
  lcd.println("HELLO WORLD");
 }

void loop()
{ //nothing here
}

⟶ in this sketch, SCR_WD and SCR_HT are used in the tft.init() method (which is not the case in the other example). The result looks like this

So I've been investigating a bit further and tested a series of values for SCR_HT :


There seems to be some kind of maximum value of 273. Beyond that, as you can see on the picture, the "lower limit" of the display goes back to the top of the screen. But why 273 ?? There must be some kind of way to use the whole screen.

Is a defined rotate/orientation (landscape/portrait) overriding these values and chops the 320 at 240?

It doesn't seem so.
The odd part is that the useable area can be extended to 273 px (so, no truncation at 240px, obviously…?)

Contact GoldenMorningLCD

Hi Floki67,
What is your microcontroller? If ESP32 or ESP8266 you might work with the TFT_eSPI library: fast and versatile.
Succes, Photoncatcher

Actually I am currently working with an arduino Uno. I'm a teacher and i am investigating possibilities for my students (11th/12th grade, in france). We don't use ESP controllers in our school, unfortunately, so I have to stick to that...
This fast library was supposed to be a good solution, if only it could be used on the whole screen !
I've tried to contact the author, let's hope he'll get my message...

Thanks Floki67. What is the TFT display controller?

Hi Floki67

I am currently using this with my UNO:

t  #include <Arduino_ST7789.h>                        // hardware-specific library for ST7789
  #include <SPI.h>

  #define TFT_DC     9                               
  #define TFT_RST    8                           

  Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST);

writeMulti, uint16_t FFFF/240=273

Sorry dron999 I don't understand what you mean.

In the Arduino_ST7789_Fast.cpp
Funktion for fill screen, so it is Funktion for fillRect with argument summary pixel to fill it with color, but it is only uint16_t, so you can not have more pixel as 65535. if you reckt or full screen is 240x(more as 273) pixel, so you have overflow. 240x320pixel is 76800, minus max of 65535 (uint16_t FFFF) you have only 11,265 in the Funktion. I solved it so:

If I have more pixel as 240, so I fill the display with 2 rects. So I can use the display normally. Change in the .h file the resolution of the display))) I can’t more answer, newbie, only 3 answer of topic, if you have more questions, so I can write only in this post)))

thank you for your idea ! I will try that !

Hi all!
I have a similar problem when trying to drive a smaller display 135x240 using the same ST7789 display controller and also using the Arduino_ST7789 fast library.

What I have found is that if you look into the Arduino_ST7789.cpp file you can see a lot of code written specifically for a 240x240 display. It even states its taken most of it from the adafruit_ST7789 equivalent library.

I've tried to copy the bits relating to the 135X240 but havent had any success just a black screen. Any ideas?

To make things a bit more different I'm using a xiao nrf52840 board. But it does work with the 240x240 display.

Below is the .cpp file

// Fast ST7789 IPS 240x240 SPI display library
// (c) 2019-20 by Pawel A. Hernik

#include "Arduino_ST7789_Fast_Xiao_DW.h"
#include <limits.h>
#include "pins_arduino.h"
#include "wiring_private.h"
#include <SPI.h>
//#include "Adafruit_ST77xx.h"//DW added as there was a sendcommand function that required it

// -----------------------------------------
// ST7789 commands

#define ST7789_NOP     0x00
#define ST7789_SWRESET 0x01

#define ST7789_SLPIN   0x10  // sleep on
#define ST7789_SLPOUT  0x11  // sleep off
#define ST7789_PTLON   0x12  // partial on
#define ST7789_NORON   0x13  // partial off
#define ST7789_INVOFF  0x20  // invert off
#define ST7789_INVON   0x21  // invert on
#define ST7789_DISPOFF 0x28  // display off
#define ST7789_DISPON  0x29  // display on
#define ST7789_IDMOFF  0x38  // idle off
#define ST7789_IDMON   0x39  // idle on

#define ST7789_CASET   0x2A
#define ST7789_RASET   0x2B
#define ST7789_RAMWR   0x2C
#define ST7789_RAMRD   0x2E

#define ST7789_COLMOD  0x3A
#define ST7789_MADCTL  0x36

#define ST7789_PTLAR    0x30   // partial start/end
#define ST7789_VSCRDEF  0x33   // SETSCROLLAREA
#define ST7789_VSCRSADD 0x37

#define ST7789_WRDISBV  0x51
#define ST7789_WRCTRLD  0x53
#define ST7789_WRCACE   0x55
#define ST7789_WRCABCMB 0x5e

#define ST7789_POWSAVE    0xbc
#define ST7789_DLPOFFSAVE 0xbd

// bits in MADCTL
#define ST7789_MADCTL_MY  0x80
#define ST7789_MADCTL_MX  0x40
#define ST7789_MADCTL_MV  0x20
#define ST7789_MADCTL_ML  0x10
#define ST7789_MADCTL_RGB 0x00

#define ST7789_135x240_XSTART 0
#define ST7789_135x240_YSTART 0

#define ST_CMD_DELAY   0x80

// Initialization commands for ST7789 240x240 1.3" IPS
// taken from Adafruit



////Direct From Adafruit
/*
static const uint8_t PROGMEM
  generic_st7789[] =  {                // Init commands for 7789 screens
    9,                              //  9 commands in list:
    ST77XX_SWRESET,   ST_CMD_DELAY, //  1: Software reset, no args, w/delay
      150,                          //     ~150 ms delay
    ST77XX_SLPOUT ,   ST_CMD_DELAY, //  2: Out of sleep mode, no args, w/delay
      10,                          //      10 ms delay
    ST77XX_COLMOD , 1+ST_CMD_DELAY, //  3: Set color mode, 1 arg + delay:
      0x55,                         //     16-bit color
      10,                           //     10 ms delay
    ST77XX_MADCTL , 1,              //  4: Mem access ctrl (directions), 1 arg:
      0x08,                         //     Row/col addr, bottom-top refresh
    ST77XX_CASET  , 4,              //  5: Column addr set, 4 args, no delay:
      0x00,
      0,        //     XSTART = 0
      0,
      240,  //     XEND = 240
    ST77XX_RASET  , 4,              //  6: Row addr set, 4 args, no delay:
      0x00,
      0,             //     YSTART = 0
      320>>8,
      320&0xFF,  //     YEND = 320
    ST77XX_INVON  ,   ST_CMD_DELAY,  //  7: hack
      10,
    ST77XX_NORON  ,   ST_CMD_DELAY, //  8: Normal display on, no args, w/delay
      10,                           //     10 ms delay
    ST77XX_DISPON ,   ST_CMD_DELAY, //  9: Main screen turn on, no args, delay
      10 };                          //    10 ms delay
// -----------------------------------------

*/
//---------
// Initialization commands for ST7789 240x240 1.3" IPS
// taken from Adafruit
static const uint8_t PROGMEM init_135x240[] = {
    9,                       				// 9 commands in list:
    ST7789_SWRESET,   ST_CMD_DELAY,  		// 1: Software reset, no args, w/delay
      150,                     				// 150 ms delay
    ST7789_SLPOUT ,   ST_CMD_DELAY,  		// 2: Out of sleep mode, no args, w/delay
      255,                    				// 255 = 500 ms delay
    ST7789_COLMOD , 1+ST_CMD_DELAY,  		// 3: Set color mode, 1 arg + delay:
      0x55,                   				// 16-bit color
      10,                     				// 10 ms delay
    ST7789_MADCTL , 1,  					// 4: Memory access ctrl (directions), 1 arg:
      0x00,                   				// Row addr/col addr, bottom to top refresh
    ST7789_CASET  , 4,  					// 5: Column addr set, 4 args, no delay:
      0x00, ST7789_135x240_XSTART,          // XSTART = 0
	    (ST7789_TFTWIDTH+ST7789_135x240_XSTART) >> 8,
	    (ST7789_TFTWIDTH+ST7789_135x240_XSTART) & 0xFF,   // XEND = 240
    ST7789_RASET  , 4,  					// 6: Row addr set, 4 args, no delay:
      0x00, ST7789_135x240_YSTART,          // YSTART = 0
      (ST7789_TFTHEIGHT+ST7789_135x240_YSTART) >> 8,
	    (ST7789_TFTHEIGHT+ST7789_135x240_YSTART) & 0xFF,	// YEND = 240
    ST7789_INVON ,   ST_CMD_DELAY,  		// 7: Inversion ON
      10,
    ST7789_NORON  ,   ST_CMD_DELAY,  		// 8: Normal display on, no args, w/delay
      10,                     				// 10 ms delay
    ST7789_DISPON ,   ST_CMD_DELAY,  		// 9: Main screen turn on, no args, w/delay
      20
};
// -----------------------------------------

//---------


#ifdef COMPATIBILITY_MODE
static SPISettings spiSettings;
#define SPI_START  SPI.beginTransaction(spiSettings)
#define SPI_END    SPI.endTransaction()
#else
#define SPI_START
#define SPI_END
#endif

// macros for fast DC and CS state changes
#ifdef COMPATIBILITY_MODE
#define DC_DATA     digitalWrite(dcPin, HIGH)
#define DC_COMMAND  digitalWrite(dcPin, LOW)
#define CS_IDLE     digitalWrite(csPin, HIGH)
#define CS_ACTIVE   digitalWrite(csPin, LOW)
#else
#define DC_DATA    *dcPort |= dcMask
#define DC_COMMAND *dcPort &= ~dcMask
#define CS_IDLE    *csPort |= csMask
#define CS_ACTIVE  *csPort &= ~csMask
#endif

// if CS always connected to the ground then don't do anything for better performance
#ifdef CS_ALWAYS_LOW
#define CS_IDLE
#define CS_ACTIVE
#endif

// ----------------------------------------------------------
// speed test results:
// in AVR best performance mode -> about 6.9 Mbps
// in compatibility mode (SPI.transfer(c)) -> about 4 Mbps
inline void Arduino_ST7789::writeSPI(uint8_t c) 
{
#ifdef COMPATIBILITY_MODE
    SPI.transfer(c);
#else
    SPDR = c;
    /*
    asm volatile("nop"); // 8 NOPs seem to be enough for 16MHz AVR @ DIV2 to avoid using while loop
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    asm volatile("nop");
    */
    asm volatile("rjmp .+0\n");
    asm volatile("rjmp .+0\n");
    asm volatile("rjmp .+0\n");
    asm volatile("rjmp .+0\n");
    //while(!(SPSR & _BV(SPIF))) ;
#endif
}

// ----------------------------------------------------------
// fast method to send multiple 16-bit values via SPI
inline void Arduino_ST7789::writeMulti(uint16_t color, uint16_t num)
{
#ifdef COMPATIBILITY_MODE
  while(num--) { SPI.transfer(color>>8);  SPI.transfer(color); }
#else
  asm volatile
  (
  "next:\n"
    "out %[spdr],%[hi]\n"
    "rjmp .+0\n"  // wait 8*2+1 = 17 cycles
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "nop\n"
    "out %[spdr],%[lo]\n"
    "rjmp .+0\n"  // wait 6*2+1 = 13 cycles + sbiw + brne
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "nop\n"
    "sbiw %[num],1\n"
    "brne next\n"
    : [num] "+w" (num)
    : [spdr] "I" (_SFR_IO_ADDR(SPDR)), [lo] "r" ((uint8_t)color), [hi] "r" ((uint8_t)(color>>8))
  );
#endif
} 
// ----------------------------------------------------------
// fast method to send multiple 16-bit values from RAM via SPI
inline void Arduino_ST7789::copyMulti(uint8_t *img, uint16_t num)
{
#ifdef COMPATIBILITY_MODE
  while(num--) { SPI.transfer(*(img+1)); SPI.transfer(*(img+0)); img+=2; }
#else
  uint8_t lo,hi;
  asm volatile
  (
  "nextCopy:\n"
    "ld  %[hi],%a[img]+\n"
    "ld  %[lo],%a[img]+\n"
    "out %[spdr],%[lo]\n"
    "rjmp .+0\n"  // wait 8*2+1 = 17 cycles
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "nop\n"
    "out %[spdr],%[hi]\n"
    "rjmp .+0\n"  // wait 4*2+1 = 9 cycles + sbiw + brne + ld*2
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "nop\n"
    "sbiw %[num],1\n"
    "brne nextCopy\n"
    : [num] "+w" (num)
    : [spdr] "I" (_SFR_IO_ADDR(SPDR)), [img] "e" (img), [lo] "r" (lo), [hi] "r" (hi)
  );
#endif
} 
// ----------------------------------------------------------
Arduino_ST7789::Arduino_ST7789(int8_t dc, int8_t rst, int8_t cs) : Adafruit_GFX(ST7789_TFTWIDTH, ST7789_TFTHEIGHT) 
{
  csPin = cs;
  dcPin = dc;
  rstPin = rst;
}

// ----------------------------------------------------------
void Arduino_ST7789::init(uint16_t width, uint16_t height) 
{
  commonST7789Init(NULL); ///not sure

if (width == 135 && height == 240) {
    // 1.14" display (centered, with odd size)
    _rowstart = _rowstart2 = (int)((320 - height) / 2);
    // This is the only device currently supported device that has different
    // values for _colstart & _colstart2. You must ensure that the extra
    // pixel lands in _colstart and not in _colstart2
    _colstart = (int)((240 - width + 1) / 2);
    _colstart2 = (int)((240 - width) / 2);
}

//
 // windowWidth = width; DW//Seems adafruit use the var windowWidth for _width which what the fast library use
 // windowHeight = height;

    _width = width;
   _height = height;

  displayInit(init_135x240);
  setRotation(2);

}

// ----------------------------------------------------------
void Arduino_ST7789::writeCmd(uint8_t c) 
{
  DC_COMMAND;
  CS_ACTIVE;
  SPI_START;

  writeSPI(c);

  CS_IDLE;
  SPI_END;
}

// ----------------------------------------------------------
void Arduino_ST7789::writeData(uint8_t d8) 
{
  DC_DATA;
  CS_ACTIVE;
  SPI_START;
    
  writeSPI(d8);

  CS_IDLE;
  SPI_END;
}

// ----------------------------------------------------------
void Arduino_ST7789::writeData16(uint16_t d16) 
{
  DC_DATA;
  CS_ACTIVE;
  SPI_START;
    
  writeMulti(d16,1);

  CS_IDLE;
  SPI_END;
}

// ----------------------------------------------------------
void Arduino_ST7789::displayInit(const uint8_t *addr) //DW not present in adafruit 
{
  uint8_t  numCommands, numArgs;
  uint16_t ms;
  numCommands = pgm_read_byte(addr++);
  while(numCommands--) {
    writeCmd(pgm_read_byte(addr++));
    numArgs  = pgm_read_byte(addr++);
    ms       = numArgs & ST_CMD_DELAY;
    numArgs &= ~ST_CMD_DELAY;
    while(numArgs--) writeData(pgm_read_byte(addr++));

    if(ms) {
      ms = pgm_read_byte(addr++);
      if(ms==255) ms=500;
      delay(ms);
    }
  }
}


// ----------------------------------------------------------
// Initialization code common to all ST7789 displays
void Arduino_ST7789::commonST7789Init(const uint8_t *cmdList) 
{
  pinMode(dcPin, OUTPUT);
#ifndef CS_ALWAYS_LOW
	pinMode(csPin, OUTPUT);
#endif

#ifndef COMPATIBILITY_MODE
  dcPort = portOutputRegister(digitalPinToPort(dcPin));
  dcMask = digitalPinToBitMask(dcPin);
#ifndef CS_ALWAYS_LOW
	csPort = portOutputRegister(digitalPinToPort(csPin));
	csMask = digitalPinToBitMask(csPin);
#endif
#endif

  // on AVR ST7789 works correctly in MODE2 and MODE3 but for STM32 only MODE3 seems to be working
  SPI.begin();
#ifdef COMPATIBILITY_MODE
  spiSettings = SPISettings(4000000, MSBFIRST, SPI_MODE3);  // 8000000 gives max speed on AVR 16MHz
#else
  SPI.setClockDivider(SPI_CLOCK_DIV2);
  SPI.setDataMode(SPI_MODE3);
#endif

  CS_ACTIVE;
  if(rstPin != -1) {
    pinMode(rstPin, OUTPUT);
    digitalWrite(rstPin, HIGH);
    delay(50);
    digitalWrite(rstPin, LOW);
    delay(50);
    digitalWrite(rstPin, HIGH);
    delay(50);
  }

  if(cmdList) displayInit(cmdList);
}

// ----------------------------------------------------------

/////DW Removed due to it not having the colstart2 needed for the 135x240. Substituted with the adafruit version
/*void Arduino_ST7789::setRotation(uint8_t m) 
{
  writeCmd(ST7789_MADCTL);
  rotation = m & 3;
  switch (rotation) {
   case 0:
     writeData(ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB);
     _xstart = _colstart;
     _ystart = _rowstart;
     break;
   case 1:
     writeData(ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_RGB);
     _ystart = _colstart;
     _xstart = _rowstart;
     break;
  case 2:
     writeData(ST7789_MADCTL_RGB);
     _xstart = 0;
     _ystart = 0;
     break;
   case 3:
     writeData(ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB);
     _xstart = 0;
     _ystart = 0;
     break;
  }
}
*/

void Arduino_ST7789::setRotation(uint8_t m) { //DW here I have issues with the windowWidth command which is not used by the arduino_ST7789_fast library.Remamed to Arduino_St7789. I've also commented it out these below as the equivalent lines of code did not contain it. 
  uint8_t madctl = 0;

  rotation = m & 3; // can't be higher than 3

  switch (rotation) {
  case 0:
    madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST77XX_MADCTL_RGB;
    _xstart = _colstart;
    _ystart = _rowstart;
   // _width = windowWidth; 
   // _height = windowHeight;
    break;
  case 1:
    madctl = ST77XX_MADCTL_MY | ST77XX_MADCTL_MV | ST77XX_MADCTL_RGB;
    _xstart = _rowstart;
    _ystart = _colstart2;
   // _height = windowWidth;
   // _width = windowHeight;
    break;
  case 2:
    madctl = ST77XX_MADCTL_RGB;
    _xstart = _colstart2;
    _ystart = _rowstart2;
   // _width = windowWidth;
   // _height = windowHeight;
    break;
  case 3:
    madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MV | ST77XX_MADCTL_RGB;
    _xstart = _rowstart2;
    _ystart = _colstart;
  //  _height = windowWidth;
  //  _width = windowHeight;
    break;
  }

 //sendCommand(ST77XX_MADCTL, &madctl, 1);  //DW this was not present in the arduino_ST7789_fast code. I added the ST78XX library to accomodate it
}

// ----------------------------------------------------------
void Arduino_ST7789::setAddrWindow(uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye)
{
  xs+=_xstart; xe+=_xstart;
  ys+=_ystart; ye+=_ystart;

  CS_ACTIVE;
  SPI_START;
  
  DC_COMMAND; writeSPI(ST7789_CASET);
  DC_DATA;
  writeSPI(xs >> 8); writeSPI(xs);
  writeSPI(xe >> 8); writeSPI(xe);

  DC_COMMAND; writeSPI(ST7789_RASET);
  DC_DATA;
  writeSPI(ys >> 8); writeSPI(ys);
  writeSPI(ye >> 8); writeSPI(ye);

  DC_COMMAND; writeSPI(ST7789_RAMWR);

  DC_DATA;
  // no CS_IDLE + SPI_END, DC_DATA to save memory
}

// ----------------------------------------------------------
void Arduino_ST7789::pushColor(uint16_t color) 
{
  SPI_START;
  //DC_DATA;
  CS_ACTIVE;

  writeSPI(color>>8); writeSPI(color);

  CS_IDLE;
  SPI_END;
}

// ----------------------------------------------------------
void Arduino_ST7789::drawPixel(int16_t x, int16_t y, uint16_t color) 
{
  if(x<0 ||x>=_width || y<0 || y>=_height) return;
  setAddrWindow(x,y,x+1,y+1);

  writeSPI(color>>8); writeSPI(color);
  /*
  asm volatile
  (
    "out %[spdr],%[hi]\n"
    "rjmp .+0\n"  // wait 8*2+1 = 17 cycles
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "rjmp .+0\n"
    "nop\n"
    "out %[spdr],%[lo]\n"
    //"rjmp .+0\n"  // wait 6*2+1 = 13 cycles + sbiw + brne
    //"rjmp .+0\n"
    //"rjmp .+0\n"
    //"rjmp .+0\n"
    //"nop\n"
    :
    : [spdr] "I" (_SFR_IO_ADDR(SPDR)), [lo] "r" ((uint8_t)color), [hi] "r" ((uint8_t)(color>>8))
  );
  */
  CS_IDLE;
  SPI_END;
}

// ----------------------------------------------------------
void Arduino_ST7789::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) 
{
  if(x>=_width || y>=_height || h<=0) return;
  if(y+h-1>=_height) h=_height-y;
  setAddrWindow(x, y, x, y+h-1);

  writeMulti(color,h);

  CS_IDLE;
  SPI_END;
}

// ----------------------------------------------------------
void Arduino_ST7789::drawFastHLine(int16_t x, int16_t y, int16_t w,  uint16_t color) 
{
  if(x>=_width || y>=_height || w<=0) return;
  if(x+w-1>=_width)  w=_width-x;
  setAddrWindow(x, y, x+w-1, y);

  writeMulti(color,w);

  CS_IDLE;
  SPI_END;
}

// ----------------------------------------------------------
void Arduino_ST7789::fillScreen(uint16_t color) 
{
  fillRect(0, 0,  _width, _height, color);
}

// ----------------------------------------------------------
void Arduino_ST7789::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) 
{
  if(x>=_width || y>=_height || w<=0 || h<=0) return;
  if(x+w-1>=_width)  w=_width -x;
  if(y+h-1>=_height) h=_height-y;
  setAddrWindow(x, y, x+w-1, y+h-1);

  writeMulti(color,w*h);

  CS_IDLE;
  SPI_END;
}

// ----------------------------------------------------------
// draws image from RAM
void Arduino_ST7789::drawImage(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t *img16) 
{
  // all protections should be on the application side
  if(w<=0 || h<=0) return;  // left for compatibility
  //if(x>=_width || y>=_height || w<=0 || h<=0) return;
  //if(x+w-1>=_width)  w=_width -x;
  //if(y+h-1>=_height) h=_height-y;
  setAddrWindow(x, y, x+w-1, y+h-1);

  copyMulti((uint8_t *)img16, w*h);

  CS_IDLE;
  SPI_END;
}

// ----------------------------------------------------------
// draws image from flash (PROGMEM)
void Arduino_ST7789::drawImageF(int16_t x, int16_t y, int16_t w, int16_t h, const uint16_t *img16) 
{
  if(x>=_width || y>=_height || w<=0 || h<=0) return;
  setAddrWindow(x, y, x+w-1, y+h-1);

  uint32_t num = (uint32_t)w*h;
  uint16_t num16 = num>>3;
  uint8_t *img = (uint8_t *)img16;
  while(num16--) {
    writeSPI(pgm_read_byte(img+1)); writeSPI(pgm_read_byte(img+0)); img+=2;
    writeSPI(pgm_read_byte(img+1)); writeSPI(pgm_read_byte(img+0)); img+=2;
    writeSPI(pgm_read_byte(img+1)); writeSPI(pgm_read_byte(img+0)); img+=2;
    writeSPI(pgm_read_byte(img+1)); writeSPI(pgm_read_byte(img+0)); img+=2;
    writeSPI(pgm_read_byte(img+1)); writeSPI(pgm_read_byte(img+0)); img+=2;
    writeSPI(pgm_read_byte(img+1)); writeSPI(pgm_read_byte(img+0)); img+=2;
    writeSPI(pgm_read_byte(img+1)); writeSPI(pgm_read_byte(img+0)); img+=2;
    writeSPI(pgm_read_byte(img+1)); writeSPI(pgm_read_byte(img+0)); img+=2;
  }
  uint8_t num8 = num & 0x7;
  while(num8--) { writeSPI(pgm_read_byte(img+1)); writeSPI(pgm_read_byte(img+0)); img+=2; }

  CS_IDLE;
  SPI_END;
}

// ----------------------------------------------------------
// Pass 8-bit (each) R,G,B, get back 16-bit packed color
uint16_t Arduino_ST7789::Color565(uint8_t r, uint8_t g, uint8_t b) 
{
  return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}

// ----------------------------------------------------------
void Arduino_ST7789::invertDisplay(boolean mode) 
{
  writeCmd(!mode ? ST7789_INVON : ST7789_INVOFF);  // modes inverted?
}

// ----------------------------------------------------------
void Arduino_ST7789::partialDisplay(boolean mode) 
{
  writeCmd(mode ? ST7789_PTLON : ST7789_NORON);
}

// ----------------------------------------------------------
void Arduino_ST7789::sleepDisplay(boolean mode) 
{
  writeCmd(mode ? ST7789_SLPIN : ST7789_SLPOUT);
  delay(5);
}

// ----------------------------------------------------------
void Arduino_ST7789::enableDisplay(boolean mode) 
{
  writeCmd(mode ? ST7789_DISPON : ST7789_DISPOFF);
}

// ----------------------------------------------------------
void Arduino_ST7789::idleDisplay(boolean mode) 
{
  writeCmd(mode ? ST7789_IDMON : ST7789_IDMOFF);
}

// ----------------------------------------------------------
void Arduino_ST7789::resetDisplay() 
{
  writeCmd(ST7789_SWRESET);
  delay(5);
}

// ----------------------------------------------------------
void Arduino_ST7789::setScrollArea(uint16_t tfa, uint16_t bfa) 
{
  uint16_t vsa = 320-tfa-bfa; // ST7789 320x240 VRAM
  writeCmd(ST7789_VSCRDEF);
  writeData16(tfa);
  writeData16(vsa);
  writeData16(bfa);
}

// ----------------------------------------------------------
void Arduino_ST7789::setScroll(uint16_t vsp) 
{
  writeCmd(ST7789_VSCRSADD);
  writeData16(vsp);
}

// ----------------------------------------------------------
void Arduino_ST7789::setPartArea(uint16_t sr, uint16_t er) 
{
  writeCmd(ST7789_PTLAR);
  writeData16(sr);
  writeData16(er);
}

// ----------------------------------------------------------
// doesn't work
void Arduino_ST7789::setBrightness(uint8_t br) 
{
  //writeCmd(ST7789_WRCACE);
  //writeData(0xb1);  // 80,90,b0, or 00,01,02,03
  //writeCmd(ST7789_WRCABCMB);
  //writeData(120);

  //BCTRL=0x20, dd=0x08, bl=0x04
  int val = 0x04;
  writeCmd(ST7789_WRCTRLD);
  writeData(val);
  writeCmd(ST7789_WRDISBV);
  writeData(br);
}

// ----------------------------------------------------------
// 0 - off
// 1 - idle
// 2 - normal
// 4 - display off
void Arduino_ST7789::powerSave(uint8_t mode) 
{
  if(mode==0) {
    writeCmd(ST7789_POWSAVE);
    writeData(0xec|3);
    writeCmd(ST7789_DLPOFFSAVE);
    writeData(0xff);
    return;
  }
  int is = (mode&1) ? 0 : 1;
  int ns = (mode&2) ? 0 : 2;
  writeCmd(ST7789_POWSAVE);
  writeData(0xec|ns|is);
  if(mode&4) {
    writeCmd(ST7789_DLPOFFSAVE);
    writeData(0xfe);
  }
}

// ------------------------------------------------
// Input a value 0 to 511 (85*6) to get a color value.
// The colours are a transition R - Y - G - C - B - M - R.
void Arduino_ST7789::rgbWheel(int idx, uint8_t *_r, uint8_t *_g, uint8_t *_b)
{
  idx &= 0x1ff;
  if(idx < 85) { // R->Y  
    *_r = 255; *_g = idx * 3; *_b = 0;
    return;
  } else if(idx < 85*2) { // Y->G
    idx -= 85*1;
    *_r = 255 - idx * 3; *_g = 255; *_b = 0;
    return;
  } else if(idx < 85*3) { // G->C
    idx -= 85*2;
    *_r = 0; *_g = 255; *_b = idx * 3;
    return;  
  } else if(idx < 85*4) { // C->B
    idx -= 85*3;
    *_r = 0; *_g = 255 - idx * 3; *_b = 255;
    return;    
  } else if(idx < 85*5) { // B->M
    idx -= 85*4;
    *_r = idx * 3; *_g = 0; *_b = 255;
    return;    
  } else { // M->R
    idx -= 85*5;
    *_r = 255; *_g = 0; *_b = 255 - idx * 3;
   return;
  }
} 

uint16_t Arduino_ST7789::rgbWheel(int idx)
{
  uint8_t r,g,b;
  rgbWheel(idx, &r,&g,&b);
  return RGBto565(r,g,b);
}

// ------------------------------------------------type or paste code here

Hi! Did you have any success with that? I have the same issue.

try to use this line of code in void setup

  tft.init(240, 320, SPI_MODE2);

Like this example below

void setup(void) {
  
  // initialize the ST7789 display (240x320 pixel)
  // if the display has CS pin try with SPI_MODE0
  tft.init(240, 320, SPI_MODE2);

  // if the screen is flipped, remove this command
  tft.setRotation(2);
  // fill the screen with black color
  tft.fillScreen(ST77XX_BLACK);

  tft.setTextWrap(false);                        // turn off text wrap option
  tft.setTextColor(ST77XX_GREEN, ST77XX_BLACK);  // set text color to green and black background
  tft.setTextSize(3);                            // caption text size = 3
  tft.setCursor(15, 40);                         // move cursor to position (15, 40) pixel
  tft.print("TEMPERATURE.");
  tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK);  // set text color to yellow and black background
  tft.setCursor(43, 140);    // move cursor to position (43, 140) pixel
  tft.print("HUMIDITY:");
  tft.setTextSize(4);        // Reading text size = 4

  // initialize DHT11 sensor
  dht11.begin();

}