From 51ed23af0f6aba27d11cb2edb191b44a6e55aa9c Mon Sep 17 00:00:00 2001 From: Bodmer Date: Fri, 6 Jul 2018 18:48:24 +0100 Subject: [PATCH] Support ST7789 rotation offset and boards with no chip select Other minor changes to tidy code up Put back in ability to call init() multiple times in sketch --- ...PI_ILI9486_Defines.h => ILI9486_Defines.h} | 2 +- .../{RPI_ILI9486_Init.h => ILI9486_Init.h} | 0 ..._ILI9486_Rotation.h => ILI9486_Rotation.h} | 0 TFT_Drivers/ILI9488_Init.h | 2 +- TFT_Drivers/ST7789_Defines.h | 1 + TFT_Drivers/ST7789_Init.h | 5 +- TFT_Drivers/ST7789_Rotation.h | 32 ++++++---- TFT_eSPI.cpp | 59 ++++++++++--------- TFT_eSPI.h | 25 ++++++-- User_Setup.h | 1 + User_Setup_Select.h | 5 +- User_Setups/Setup18_ST7789.h | 2 +- 12 files changed, 82 insertions(+), 52 deletions(-) rename TFT_Drivers/{RPI_ILI9486_Defines.h => ILI9486_Defines.h} (97%) rename TFT_Drivers/{RPI_ILI9486_Init.h => ILI9486_Init.h} (100%) rename TFT_Drivers/{RPI_ILI9486_Rotation.h => ILI9486_Rotation.h} (100%) diff --git a/TFT_Drivers/RPI_ILI9486_Defines.h b/TFT_Drivers/ILI9486_Defines.h similarity index 97% rename from TFT_Drivers/RPI_ILI9486_Defines.h rename to TFT_Drivers/ILI9486_Defines.h index 5ba1007..31996e4 100644 --- a/TFT_Drivers/RPI_ILI9486_Defines.h +++ b/TFT_Drivers/ILI9486_Defines.h @@ -4,7 +4,7 @@ #define TFT_HEIGHT 480 // For Raspberry Pi ILI9486 only with a modified board to add a write strobe: -#ifdef TFT_WR +#if defined (TFT_WR) && defined (RPI_ILI9486_DRIVER) #define RPI_WRITE_STROBE #endif diff --git a/TFT_Drivers/RPI_ILI9486_Init.h b/TFT_Drivers/ILI9486_Init.h similarity index 100% rename from TFT_Drivers/RPI_ILI9486_Init.h rename to TFT_Drivers/ILI9486_Init.h diff --git a/TFT_Drivers/RPI_ILI9486_Rotation.h b/TFT_Drivers/ILI9486_Rotation.h similarity index 100% rename from TFT_Drivers/RPI_ILI9486_Rotation.h rename to TFT_Drivers/ILI9486_Rotation.h diff --git a/TFT_Drivers/ILI9488_Init.h b/TFT_Drivers/ILI9488_Init.h index feaffdd..917b32b 100644 --- a/TFT_Drivers/ILI9488_Init.h +++ b/TFT_Drivers/ILI9488_Init.h @@ -42,7 +42,7 @@ writedata(0x80); writedata(0x40); - writecommand(0xE0); // Positive Gamma Control + writecommand(0xE0); // Positive Gamma Control writedata(0x00); writedata(0x03); writedata(0x09); diff --git a/TFT_Drivers/ST7789_Defines.h b/TFT_Drivers/ST7789_Defines.h index b900b79..99d35db 100644 --- a/TFT_Drivers/ST7789_Defines.h +++ b/TFT_Drivers/ST7789_Defines.h @@ -3,6 +3,7 @@ #define TFT_WIDTH 240 #define TFT_HEIGHT 240 +#define CGRAM_OFFSET // Delay between some initialisation commands #define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked diff --git a/TFT_Drivers/ST7789_Init.h b/TFT_Drivers/ST7789_Init.h index 57b526b..d5ba408 100644 --- a/TFT_Drivers/ST7789_Init.h +++ b/TFT_Drivers/ST7789_Init.h @@ -2,6 +2,7 @@ // This is the command sequence that initialises the ST7789 driver // Configure ST7789 display + { static const uint8_t PROGMEM st7789[] = { @@ -9,7 +10,7 @@ static const uint8_t PROGMEM TFT_SWRST, TFT_INIT_DELAY, 150, TFT_SLPOUT, TFT_INIT_DELAY, 255, TFT_COLMOD, 1+TFT_INIT_DELAY, 0x55, 10, - TFT_MADCTL, 1, 0x00, + TFT_MADCTL, 1, TFT_MAD_RGB, TFT_CASET, 4, 0x00, 0x00, 0x00, 0xF0, TFT_PASET, 4, 0x00, 0x00, 0x00, 0xF0, TFT_INVON, TFT_INIT_DELAY, 10, @@ -21,5 +22,3 @@ static const uint8_t PROGMEM } // End of ST7789 display configuration - - diff --git a/TFT_Drivers/ST7789_Rotation.h b/TFT_Drivers/ST7789_Rotation.h index 3a75ec6..34ba394 100644 --- a/TFT_Drivers/ST7789_Rotation.h +++ b/TFT_Drivers/ST7789_Rotation.h @@ -4,23 +4,31 @@ rotation = m % 4; switch (rotation) { case 0: // Portrait - writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_RGB); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; + writedata(TFT_MAD_RGB); + _width = _init_width; + _height = _init_height; + colstart = 0; + rowstart = 0; break; case 1: // Landscape (Portrait + 90) - writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_RGB); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_RGB); + _width = _init_height; + _height = _init_width; + colstart = 0; + rowstart = 0; break; case 2: // Inverter portrait - writedata(TFT_MAD_RGB); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_RGB); + _width = _init_width; + _height = _init_height; + colstart = 0; + rowstart = 80; break; case 3: // Inverted landscape - writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_RGB); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; + writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_RGB); + _width = _init_height; + _height = _init_width; + colstart = 80; + rowstart = 0; break; } diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index b63a1bc..0f80d68 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -48,7 +48,7 @@ void busDir(uint32_t mask, uint8_t mode); inline void TFT_eSPI::spi_begin(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) - if (locked) {locked = false; SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, SPI_MODE0));} + if (locked) {locked = false; SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE));} #endif } @@ -117,12 +117,6 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) #endif #ifdef ESP32_PARALLEL - // Create a data bus and Write line GPIO bit clear mask - //clr_mask = (1 << TFT_D0) | (1 << TFT_D1) | (1 << TFT_D2) | (1 << TFT_D3) | (1 << TFT_D4) | (1 << TFT_D5) | (1 << TFT_D6) | (1 << TFT_D7) | (1 << TFT_WR); - - // Create a data bus GPIO bit direction mask - //dir_mask = (1 << TFT_D0) | (1 << TFT_D1) | (1 << TFT_D2) | (1 << TFT_D3) | (1 << TFT_D4) | (1 << TFT_D5) | (1 << TFT_D6) | (1 << TFT_D7); - // Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically for (int c = 0; c<256; c++) @@ -168,6 +162,8 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) locked = true; // ESP32 transaction mutex lock flags inTransaction = false; + _booted = true; + addr_row = 0xFFFF; addr_col = 0xFFFF; @@ -216,11 +212,13 @@ void TFT_eSPI::begin(uint8_t tc) /*************************************************************************************** -** Function name: init +** Function name: init (tc is tab colour for ST7735 displays only) ** Description: Reset, then initialise the TFT display registers ***************************************************************************************/ void TFT_eSPI::init(uint8_t tc) { + if (_booted) + { #if !defined (ESP32) #ifdef TFT_CS cspinmask = (uint32_t) digitalPinToBitMask(TFT_CS); @@ -241,7 +239,7 @@ void TFT_eSPI::init(uint8_t tc) SPI.pins(6, 7, 8, 0); #endif - SPI.begin(); // This will set HMISO to input + SPI.begin(); // This will set HMISO to input #else #if !defined(ESP32_PARALLEL) #if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) @@ -252,15 +250,15 @@ void TFT_eSPI::init(uint8_t tc) #endif #endif - inTransaction = false; - locked = true; + inTransaction = false; + locked = true; // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled // so the code here is for ESP8266 only #if !defined (SUPPORT_TRANSACTIONS) && defined (ESP8266) - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE0); - SPI.setFrequency(SPI_FREQUENCY); + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(TFT_SPI_MODE); + SPI.setFrequency(SPI_FREQUENCY); #endif #if defined(ESP32_PARALLEL) @@ -278,11 +276,16 @@ void TFT_eSPI::init(uint8_t tc) // Set to output once again in case D6 (MISO) is used for DC #ifdef TFT_DC - digitalWrite(TFT_DC, HIGH); // Data/Command high = data mode - pinMode(TFT_DC, OUTPUT); + digitalWrite(TFT_DC, HIGH); // Data/Command high = data mode + pinMode(TFT_DC, OUTPUT); #endif + _booted = false; + } // end of: if just _booted + // Toggle RST low to reset + spi_begin(); + #ifdef TFT_RST if (TFT_RST >= 0) { digitalWrite(TFT_RST, HIGH); @@ -290,15 +293,14 @@ void TFT_eSPI::init(uint8_t tc) digitalWrite(TFT_RST, LOW); delay(20); digitalWrite(TFT_RST, HIGH); - delay(150); } + else writecommand(TFT_SWRST); // Software reset +#else + writecommand(TFT_SWRST); // Software reset #endif - spi_begin(); - writecommand(TFT_SWRST); // Software reset spi_end(); - - delay(5); // Wait for software reset to complete + delay(150); // Wait for reset to complete spi_begin(); @@ -317,7 +319,7 @@ void TFT_eSPI::init(uint8_t tc) #include "TFT_Drivers/S6D02A1_Init.h" #elif defined (RPI_ILI9486_DRIVER) - #include "TFT_Drivers/RPI_ILI9486_Init.h" + #include "TFT_Drivers/ILI9486_Init.h" #elif defined (ILI9486_DRIVER) #include "TFT_Drivers/ILI9486_Init.h" @@ -338,6 +340,7 @@ void TFT_eSPI::init(uint8_t tc) spi_end(); + setRotation(rotation); } @@ -364,7 +367,7 @@ void TFT_eSPI::setRotation(uint8_t m) #include "TFT_Drivers/S6D02A1_Rotation.h" #elif defined (RPI_ILI9486_DRIVER) - #include "TFT_Drivers/RPI_ILI9486_Rotation.h" + #include "TFT_Drivers/ILI9486_Rotation.h" #elif defined (ILI9486_DRIVER) #include "TFT_Drivers/ILI9486_Rotation.h" @@ -566,7 +569,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) // Fetch the 16 bit BRG pixel //uint16_t rgb = (readByte() << 8) | readByte(); -#if defined (ILI9341_DRIVER) | defined (ILI9488_DRIVER) // Read 3 bytes + #if defined (ILI9341_DRIVER) | defined (ILI9488_DRIVER) // Read 3 bytes // Read window pixel 24 bit RGB values and fill in LS bits uint16_t rgb = ((readByte() & 0xF8) << 8) | ((readByte() & 0xFC) << 3) | (readByte() >> 3); @@ -578,7 +581,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) return rgb; -#else // ILI9481 16 bit read + #else // ILI9481 16 bit read // Fetch the 16 bit BRG pixel uint16_t bgr = (readByte() << 8) | readByte(); @@ -590,7 +593,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) // Swap Red and Blue (could check MADCTL setting to see if this is needed) return (bgr>>11) | (bgr<<11) | (bgr & 0x7E0); -#endif + #endif #else // Not ESP32_PARALLEL @@ -2174,7 +2177,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u for (int8_t i = 0; i < 5; i++ ) column[i] = pgm_read_byte(font + (c * 5) + i); column[5] = 0; -#if defined (ESP8266) +#if defined (ESP8266) && !defined (ILI9488_DRIVER) color = (color >> 8) | (color << 8); bg = (bg >> 8) | (bg << 8); uint32_t spimask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); @@ -2197,7 +2200,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} } -#else // for ESP32 +#else // for ESP32 or ILI9488 for (int8_t j = 0; j < 8; j++) { for (int8_t k = 0; k < 5; k++ ) { diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 75362a9..5816b04 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -30,6 +30,12 @@ #define SPI_FREQUENCY 20000000 #endif +#ifdef ST7789_DRIVER + #define TFT_SPI_MODE SPI_MODE3 +#else + #define TFT_SPI_MODE SPI_MODE0 +#endif + // If the frequency is not defined, set a default #ifndef SPI_TOUCH_FREQUENCY #define SPI_TOUCH_FREQUENCY 2500000 @@ -214,12 +220,12 @@ #define tft_Write_8(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)C); WR_H // Write 16 bits to TFT -#ifdef PSEUDO_8_BIT - #define tft_Write_16(C) WR_L;GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)(C >> 0)); WR_H -#else - #define tft_Write_16(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)(C >> 8)); WR_H; \ + #ifdef PSEUDO_8_BIT + #define tft_Write_16(C) WR_L;GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)(C >> 0)); WR_H + #else + #define tft_Write_16(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)(C >> 8)); WR_H; \ GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)(C >> 0)); WR_H -#endif + #endif // 16 bit write with swapped bytes #define tft_Write_16S(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) (C >> 0)); WR_H; \ @@ -238,6 +244,13 @@ //#define RD_H digitalWrite(TFT_WR, HIGH) #endif +#elif defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 24 bit RGB + #define tft_Write_8(C) SPI.transfer(C) + #define tft_Write_16(C) SPI.transfer(((C & 0xF800)>>8) | ((C & 0xF800)>>13)); \ + SPI.transfer(((C & 0x07E0)>>3) | ((C & 0x07E0)>> 9)); \ + SPI.transfer(((C & 0x001F)<<3) | ((C & 0x001F)>> 2)) + #define tft_Write_32(C) SPI.write32(C) + #elif defined (RPI_ILI9486_DRIVER) #define tft_Write_8(C) SPI.transfer(0); SPI.transfer(C) #define tft_Write_16(C) SPI.write16(C) @@ -688,6 +701,8 @@ class TFT_eSPI : public Print { bool _swapBytes; // Swap the byte order for TFT pushImage() bool locked, inTransaction; // Transaction and mutex lock flags for ESP32 + bool _booted; + int32_t _lastColor; #ifdef LOAD_GFXFF diff --git a/User_Setup.h b/User_Setup.h index 782b71d..2548f39 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -22,6 +22,7 @@ //#define RPI_ILI9486_DRIVER // 20MHz maximum SPI //#define HX8357D_DRIVER //#define ILI9481_DRIVER +//#define ILI9486_DRIVER //#define ILI9488_DRIVER //#define ST7789_DRIVER diff --git a/User_Setup_Select.h b/User_Setup_Select.h index fe14441..bacecb9 100644 --- a/User_Setup_Select.h +++ b/User_Setup_Select.h @@ -69,7 +69,10 @@ #include #define TFT_DRIVER 0x6D02 #elif defined (RPI_ILI9486_DRIVER) - #include + #include + #define TFT_DRIVER 0x9486 +#elif defined (ILI9486_DRIVER) + #include #define TFT_DRIVER 0x9486 #elif defined (ILI9481_DRIVER) #include diff --git a/User_Setups/Setup18_ST7789.h b/User_Setups/Setup18_ST7789.h index d532d0a..1f2030a 100644 --- a/User_Setups/Setup18_ST7789.h +++ b/User_Setups/Setup18_ST7789.h @@ -88,7 +88,7 @@ // ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation -#define TFT_CS PIN_D8 // Chip select control pin D8 +//#define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V