diff --git a/Extensions/Smooth_font.cpp b/Extensions/Smooth_font.cpp index 7d573be..fe77885 100644 --- a/Extensions/Smooth_font.cpp +++ b/Extensions/Smooth_font.cpp @@ -78,6 +78,12 @@ void TFT_eSPI::loadFont(String fontName) _gFontFilename = "/" + fontName + ".vlw"; + // Avoid a crash on the ESP32 if the file does not exist + if (SPIFFS.exists(_gFontFilename) == false) { + Serial.println("Font file " + fontName + " not found!"); + return; + } + fontFile = SPIFFS.open( _gFontFilename, "r"); if(!fontFile) return; @@ -479,7 +485,6 @@ void TFT_eSPI::drawGlyph(uint16_t code) void TFT_eSPI::showFont(uint32_t td) { if(!fontLoaded) return; -// fontFile = SPIFFS.open( _gFontFilename, "r" ); if(!fontFile) { diff --git a/TFT_Drivers/ST7735_Defines.h b/TFT_Drivers/ST7735_Defines.h index 82a3c30..494c673 100644 --- a/TFT_Drivers/ST7735_Defines.h +++ b/TFT_Drivers/ST7735_Defines.h @@ -9,15 +9,15 @@ // Enumerate the different configurations -#define INITR_GREENTAB 0x0 -#define INITR_REDTAB 0x1 -#define INITR_BLACKTAB 0x2 -#define INITR_GREENTAB2 0x3 // Use if you get random pixels on two edges of green tab display -#define INITR_GREENTAB3 0x4 // Use if you get random pixels on edge(s) of 128x128 screen -#define INITR_GREENTAB128 0x5 // Use if you only get part of 128x128 screen in rotation 0 & 1 +#define INITR_GREENTAB 0x0 +#define INITR_REDTAB 0x1 +#define INITR_BLACKTAB 0x2 // Display with no offsets +#define INITR_GREENTAB2 0x3 // Use if you get random pixels on two edges of green tab display +#define INITR_GREENTAB3 0x4 // Use if you get random pixels on edge(s) of 128x128 screen +#define INITR_GREENTAB128 0x5 // Use if you only get part of 128x128 screen in rotation 0 & 1 #define INITR_GREENTAB160x80 0x6 // Use if you only get part of 128x128 screen in rotation 0 & 1 -#define INITR_REDTAB160x80 0x7 // Added for https://www.aliexpress.com/item/ShengYang-1pcs-IPS-0-96-inch-7P-SPI-HD-65K-Full-Color-OLED-Module-ST7735-Drive/32918394604.html -#define INITB 0xB +#define INITR_REDTAB160x80 0x7 // Added for https://www.aliexpress.com/item/ShengYang-1pcs-IPS-0-96-inch-7P-SPI-HD-65K-Full-Color-OLED-Module-ST7735-Drive/32918394604.html +#define INITB 0xB // Setup the tab color that will be used by the library setRotation() and setup command list diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index afaedd1..10f9bb3 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -185,8 +185,8 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) _booted = true; - addr_row = 0xFFFF; - addr_col = 0xFFFF; + ys_row = ye_row = addr_row = 0xFFFF; + xs_col = xe_col = addr_col = 0xFFFF; #ifdef LOAD_GLCD fontsloaded = 0x0002; // Bit 1 set @@ -530,7 +530,7 @@ uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) CS_L; tft_Write_8(cmd_function); DC_D; - reg = tft_Write_8(0); + reg = tft_Read_8(0); CS_H; spi_end_read(); @@ -628,15 +628,15 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits #if !defined (ILI9488_DRIVER) - uint8_t r = tft_Write_8(0); - uint8_t g = tft_Write_8(0); - uint8_t b = tft_Write_8(0); + uint8_t r = tft_Read_8(0); + uint8_t g = tft_Read_8(0); + uint8_t b = tft_Read_8(0); #else // The 6 colour bits are in MS 6 bits of each byte, but the ILI9488 needs an extra clock pulse // so bits appear shifted right 1 bit, so mask the middle 6 bits then shift 1 place left - uint8_t r = (tft_Write_8(0)&0x7E)<<1; - uint8_t g = (tft_Write_8(0)&0x7E)<<1; - uint8_t b = (tft_Write_8(0)&0x7E)<<1; + uint8_t r = (tft_Read_8(0)&0x7E)<<1; + uint8_t g = (tft_Read_8(0)&0x7E)<<1; + uint8_t b = (tft_Read_8(0)&0x7E)<<1; #endif CS_H; @@ -768,15 +768,15 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits #if !defined (ILI9488_DRIVER) - uint8_t r = tft_Write_8(0); - uint8_t g = tft_Write_8(0); - uint8_t b = tft_Write_8(0); + uint8_t r = tft_Read_8(0); + uint8_t g = tft_Read_8(0); + uint8_t b = tft_Read_8(0); #else // The 6 colour bits are in LS 6 bits of each byte but we do not include the extra clock pulse // so we use a trick and mask the middle 6 bits of the byte, then only shift 1 place left - uint8_t r = (tft_Write_8(0)&0x7E)<<1; - uint8_t g = (tft_Write_8(0)&0x7E)<<1; - uint8_t b = (tft_Write_8(0)&0x7E)<<1; + uint8_t r = (tft_Read_8(0)&0x7E)<<1; + uint8_t g = (tft_Read_8(0)&0x7E)<<1; + uint8_t b = (tft_Read_8(0)&0x7E)<<1; #endif // Swapped colour byte order for compatibility with pushRect() @@ -1354,15 +1354,15 @@ void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_ // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits #if !defined (ILI9488_DRIVER) - *data++ = tft_Write_8(0); - *data++ = tft_Write_8(0); - *data++ = tft_Write_8(0); + *data++ = tft_Read_8(0); + *data++ = tft_Read_8(0); + *data++ = tft_Read_8(0); #else // The 6 colour bits are in MS 6 bits of each byte, but the ILI9488 needs an extra clock pulse // so bits appear shifted right 1 bit, so mask the middle 6 bits then shift 1 place left - *data++ = (tft_Write_8(0)&0x7E)<<1; - *data++ = (tft_Write_8(0)&0x7E)<<1; - *data++ = (tft_Write_8(0)&0x7E)<<1; + *data++ = (tft_Read_8(0)&0x7E)<<1; + *data++ = (tft_Read_8(0)&0x7E)<<1; + *data++ = (tft_Read_8(0)&0x7E)<<1; #endif } @@ -2473,7 +2473,7 @@ void TFT_eSPI::setWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1) // Chip select stays low, use setWindow() from sketches #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) && !defined (RPI_ILI9486_DRIVER) -inline void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) +void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) { //spi_begin(); @@ -2563,8 +2563,8 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) DC_D; - uint8_t xBin[] = { 0, (uint8_t) (xs>>8), 0, (uint8_t) (xs>>0), 0, (uint8_t) (xe>>8), 0, (uint8_t) (xe>>0), }; - SPI.writePattern(&xBin[0], 8, 1); + uint8_t xb[] = { 0, (uint8_t) (xs>>8), 0, (uint8_t) (xs>>0), 0, (uint8_t) (xe>>8), 0, (uint8_t) (xe>>0), }; + SPI.writePattern(&xb[0], 8, 1); // Row addr set DC_C; @@ -2577,8 +2577,8 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) DC_D; - uint8_t yBin[] = { 0, (uint8_t) (ys>>8), 0, (uint8_t) (ys>>0), 0, (uint8_t) (ye>>8), 0, (uint8_t) (ye>>0), }; - SPI.writePattern(&yBin[0], 8, 1); + uint8_t yb[] = { 0, (uint8_t) (ys>>8), 0, (uint8_t) (ys>>0), 0, (uint8_t) (ye>>8), 0, (uint8_t) (ye>>0), }; + SPI.writePattern(&yb[0], 8, 1); // write to RAM DC_C; @@ -2596,7 +2596,7 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) #else #if defined (ESP8266) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits -inline void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) +void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { //spi_begin(); @@ -2673,7 +2673,7 @@ inline void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t #else // This is for the ESP32 -inline void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) +void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { //spi_begin(); @@ -2687,42 +2687,48 @@ inline void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1+=rowstart; #endif -#if !defined (RPI_ILI9486_DRIVER) - uint32_t xaw = ((uint32_t)x0 << 16) | x1; - uint32_t yaw = ((uint32_t)y0 << 16) | y1; -#endif + CS_L_DC_C; - // Column addr set - DC_C; - CS_L; + // No need to send x if it has not changed (small speed-up of complex transparent Sprites and bitmaps) + // Nb: caller must fill the set address area so that setting same area again will fill from xs, ys + if (xs_col != x0 || xe_col != x1) { + // Column addr set - tft_Write_8(TFT_CASET); + tft_Write_8(TFT_CASET); - DC_D; + DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t xBin[] = { 0, (uint8_t) (x0>>8), 0, (uint8_t) (x0>>0), 0, (uint8_t) (x1>>8), 0, (uint8_t) (x1>>0), }; - SPI.writePattern(&xBin[0], 8, 1); + uint8_t xb[] = { 0, (uint8_t) (x0>>8), 0, (uint8_t) (x0>>0), 0, (uint8_t) (x1>>8), 0, (uint8_t) (x1>>0), }; + SPI.writePattern(&xb[0], 8, 1); #else - tft_Write_32(xaw); + tft_Write_32(SPI_32(x0, x1)); #endif - // Row addr set - DC_C; - tft_Write_8(TFT_PASET); + DC_C; + xs_col = x0; xe_col = x1; + } - DC_D; + // No need to send y if it has not changed + if (ys_row != y0 || ye_row != y1) { + + // Row addr set + tft_Write_8(TFT_PASET); + + DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t yBin[] = { 0, (uint8_t) (y0>>8), 0, (uint8_t) (y0>>0), 0, (uint8_t) (y1>>8), 0, (uint8_t) (y1>>0), }; - SPI.writePattern(&yBin[0], 8, 1); + uint8_t yb[] = { 0, (uint8_t) (y0>>8), 0, (uint8_t) (y0>>0), 0, (uint8_t) (y1>>8), 0, (uint8_t) (y1>>0), }; + SPI.writePattern(&yb[0], 8, 1); #else - tft_Write_32(yaw); + tft_Write_32(SPI_32(y0, y1)); #endif + DC_C; + ys_row = y0; ye_row = y1; + } + // write to RAM - DC_C; - tft_Write_8(TFT_RAMWR); DC_D; @@ -2819,19 +2825,15 @@ void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) y1+=rowstart; #endif - uint32_t xaw = ((uint32_t)x0 << 16) | x1; - uint32_t yaw = ((uint32_t)y0 << 16) | y1; - // Column addr set - DC_C; - CS_L; + CS_L_DC_C; tft_Write_8(TFT_CASET); DC_D; - tft_Write_32(xaw); + tft_Write_32(SPI_32(x0, x1)); // Row addr set DC_C; @@ -2840,7 +2842,7 @@ void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) DC_D; - tft_Write_32(yaw); + tft_Write_32(SPI_32(y0, y1)); DC_C; tft_Write_8(TFT_RAMRD); // Read CGRAM command @@ -3053,52 +3055,49 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) y+=rowstart; #endif -#if !defined (RPI_ILI9486_DRIVER) - uint32_t xaw = ((uint32_t)x << 16) | x; - uint32_t yaw = ((uint32_t)y << 16) | y; -#endif - - CS_L; + CS_L_DC_C; // No need to send x if it has not changed (speeds things up) if (addr_col != x) { - DC_C; - tft_Write_8(TFT_CASET); DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t xBin[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), }; - SPI.writePattern(&xBin[0], 8, 1); + uint8_t xb[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), }; + SPI.writePattern(&xb[0], 8, 1); #else - tft_Write_32(xaw); + tft_Write_32(SPI_32(x, x)); #endif - + + DC_C; + addr_col = x; + xs_col = xe_col = x; + } // No need to send y if it has not changed (speeds things up) if (addr_row != y) { - DC_C; - tft_Write_8(TFT_PASET); DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t yBin[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), }; - SPI.writePattern(&yBin[0], 8, 1); + uint8_t yb[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), }; + SPI.writePattern(&yb[0], 8, 1); #else - tft_Write_32(yaw); + tft_Write_32(SPI_32(y, y)); #endif + DC_C; + addr_row = y; + ys_row = ye_row = y; } - DC_C; tft_Write_8(TFT_RAMWR); @@ -3159,6 +3158,48 @@ void TFT_eSPI::pushColor(uint16_t color, uint32_t len) spi_end(); } +/*************************************************************************************** +** Function name: startWrite +** Description: begin transaction with CS low, MUST later call endWrite +***************************************************************************************/ +void TFT_eSPI::startWrite(void) +{ + spi_begin(); + + CS_L; +} + +/*************************************************************************************** +** Function name: endWrite +** Description: end transaction with CS high +***************************************************************************************/ +void TFT_eSPI::endWrite(void) +{ + + CS_H; + + spi_end(); +} + +/*************************************************************************************** +** Function name: writeColor (use startWrite() and endWrite() before & after) +** Description: raw write of "len" pixels avoiding transaction check +***************************************************************************************/ +void TFT_eSPI::writeColor(uint16_t color, uint32_t len) +{ +#ifdef RPI_WRITE_STROBE + uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; + if(len) SPI.writePattern(&colorBin[0], 2, 1); len--; + while(len--) {WR_L; WR_H;} +#else + #if defined (ESP32_PARALLEL) + while (len--) {tft_Write_16(color);} + #else + writeBlock(color, len); + #endif +#endif +} + /*************************************************************************************** ** Function name: pushColors ** Description: push an array of pixels for 16 bit raw image drawing @@ -4655,7 +4696,7 @@ void writeBlock(uint16_t color, uint32_t repeat) #elif defined (ILI9488_DRIVER) #ifdef ESP8266 -void writeBlock(uint16_t color, uint32_t repeat) +void TFT_eSPI::writeBlock(uint16_t color, uint32_t repeat) { uint32_t mask = ~(SPIMMOSI << SPILMOSI); @@ -4722,9 +4763,6 @@ void writeBlock(uint16_t color, uint32_t repeat) } #else // Now the code for ESP32 and ILI9488 -#include "soc/spi_reg.h" -#define SPI_NUM 0x3 - void writeBlock(uint16_t color, uint32_t repeat) { // Split out the colours @@ -4795,38 +4833,46 @@ void writeBlock(uint16_t color, uint32_t repeat) #else // Low level register based ESP32 code for 16 bit colour SPI TFTs -#include "soc/spi_reg.h" -#define SPI_NUM 0x3 - - void writeBlock(uint16_t color, uint32_t repeat) { - uint16_t color16 = (color >> 8) | (color << 8); - uint32_t color32 = color16 | color16 << 16; + uint32_t color32 = SPI_32(color, color); - if (repeat > 15) + if (repeat > 31) // Revert legacy toggle buffer change { - SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_NUM), SPI_USR_MOSI_DBITLEN, 255, SPI_USR_MOSI_DBITLEN_S); - - while(repeat>15) + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 511); + while(repeat>31) { while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); - for (uint32_t i=0; i<8; i++) WRITE_PERI_REG((SPI_W0_REG(SPI_NUM) + (i << 2)), color32); + WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W1_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W2_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W3_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W4_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W5_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W6_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W7_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W8_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W9_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W10_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W11_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W12_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W13_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W14_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W15_REG(SPI_NUM), color32); SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); - repeat -= 16; + repeat -= 32; } while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); } if (repeat) { - repeat = (repeat << 4) - 1; - SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_NUM), SPI_USR_MOSI_DBITLEN, repeat, SPI_USR_MOSI_DBITLEN_S); - for (uint32_t i=0; i<8; i++) WRITE_PERI_REG((SPI_W0_REG(SPI_NUM) + (i << 2)), color32); + // Revert toggle buffer change + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), (repeat << 4) - 1); + for (uint32_t i=0; i <= (repeat>>1); i++) WRITE_PERI_REG((SPI_W0_REG(SPI_NUM) + (i << 2)), color32); SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); } - } #endif @@ -4975,10 +5021,6 @@ void TFT_eSPI::getSetup(setup_t &tft_settings) #include "Extensions/Sprite.cpp" -// #ifdef ESP32 -// #include "Extensions/pSprite.cpp" -// #endif - #ifdef SMOOTH_FONT #include "Extensions/Smooth_font.cpp" #endif diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 2c93392..456b066 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -103,6 +103,11 @@ #include +#ifdef ESP32 + #include "soc/spi_reg.h" + #define SPI_NUM 0x3 +#endif + #ifdef SMOOTH_FONT // Call up the SPIFFS FLASH filing system for the anti-aliased fonts #define FS_NO_GLOBALS @@ -127,16 +132,16 @@ #else #if TFT_DC >= 32 - #define DC_C GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); \ - GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) - #define DC_D GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); \ - GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) + #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); //\ + //GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) + #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); //\ + //GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) #else #if TFT_DC >= 0 - #define DC_C GPIO.out_w1ts = (1 << TFT_DC); \ - GPIO.out_w1tc = (1 << TFT_DC) - #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ - GPIO.out_w1ts = (1 << TFT_DC) + #define DC_C GPIO.out_w1tc = (1 << TFT_DC); //\ + //GPIO.out_w1tc = (1 << TFT_DC) + #define DC_D GPIO.out_w1ts = (1 << TFT_DC); //\ + //GPIO.out_w1ts = (1 << TFT_DC) #else #define DC_C #define DC_D @@ -166,14 +171,14 @@ #define CS_H #else #if TFT_CS >= 32 - #define CS_L GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); \ - GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) - #define CS_H GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \ - GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) + #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); //\ + //GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) + #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); //\ + //GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) #else #if TFT_CS >= 0 - #define CS_L GPIO.out_w1ts = (1 << TFT_CS);GPIO.out_w1tc = (1 << TFT_CS) - #define CS_H GPIO.out_w1tc = (1 << TFT_CS);GPIO.out_w1ts = (1 << TFT_CS) + #define CS_L GPIO.out_w1tc = (1 << TFT_CS); //GPIO.out_w1tc = (1 << TFT_CS) + #define CS_H GPIO.out_w1ts = (1 << TFT_CS); //GPIO.out_w1ts = (1 << TFT_CS) #else #define CS_L #define CS_H @@ -186,6 +191,18 @@ #endif #endif +// Use single register write for CS_L and DC_C if pins are both in range 0-31 +#ifdef ESP32 + #if (TFT_CS >= 0) && (TFT_CS < 32) && (TFT_DC >= 0) && (TFT_DC < 32) + #define CS_L_DC_C GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)); //\ + //GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)) + #else + #define CS_L_DC_C CS_L; DC_C + #endif +#else // ESP8266 + #define CS_L_DC_C CS_L; DC_C +#endif + // chip select signal for touchscreen #ifndef TOUCH_CS #define T_CS_L // No macro allocated so it generates no code @@ -206,6 +223,14 @@ #endif #endif +#ifdef ESP8266 + // Concatenate two 16 bit values for the SPI 32 bit register write + #define SPI_32(H,L) ( (H)<<16 | (L) ) +#else + // Swap byte order for concatenated 16 bit window address or colors + // AB CD -> DCBA for SPI 32 bit register write + #define SPI_32(H,L) ( ((H)<<8 | (H)>>8) | (((L)<<8 | (L)>>8)<<16 ) ) +#endif #if defined (ESP32) && defined (ESP32_PARALLEL) // Mask for the 8 data bits to set pin directions @@ -253,34 +278,75 @@ #elif defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB // Write 8 bits to TFT - #define tft_Write_8(C) SPI.transfer(C) + #define tft_Write_8(C) SPI.transfer(C) // Convert 16 bit colour to 18 bit and write in 3 bytes - #define tft_Write_16(C) SPI.transfer((C & 0xF800)>>8); \ - SPI.transfer((C & 0x07E0)>>3); \ - SPI.transfer((C & 0x001F)<<3) + #define tft_Write_16(C) SPI.transfer((C & 0xF800)>>8); \ + SPI.transfer((C & 0x07E0)>>3); \ + SPI.transfer((C & 0x001F)<<3) // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes #define tft_Write_16S(C) SPI.transfer(C & 0xF8); \ SPI.transfer((C & 0xE0)>>11 | (C & 0x07)<<5); \ SPI.transfer((C & 0x1F00)>>5) // Write 32 bits to TFT - #define tft_Write_32(C) SPI.write32(C) + #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) - #define tft_Write_32(C) SPI.write32(C) + #define tft_Write_8(C) SPI.transfer(0); SPI.transfer(C) + #define tft_Write_16(C) SPI.write16(C) + #define tft_Write_16S(C) SPI.write16(C<<8 | C>>8) + #define tft_Write_32(C) SPI.write32(C) -#else +#elif defined ESP8266 - #define tft_Write_8(C) SPI.transfer(C) - #define tft_Write_16(C) SPI.write16(C) - #define tft_Write_32(C) SPI.write32(C) + #define tft_Write_8(C) SPI.write(C) + #define tft_Write_16(C) SPI.write16(C) + #define tft_Write_32(C) SPI.write32(C) + +#else // ESP32 using SPI with 16 bit color display + + // ESP32 low level SPI writes for 8, 16 and 32 bit values + // to avoid the function call overhead + + // Write 8 bits + #define tft_Write_8(C) \ + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 8-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + + // Write 16 bits with corrected endianess for 16 bit colours + #define tft_Write_16(C) \ + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 16-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C<<8 | C>>8); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + + // Write 16 bits (used for ESP32_PARALLEL or ILI9488_DRIVER) + #define tft_Write_16S(C) \ + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 16-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + + // Write 32 bits + #define tft_Write_32(C) \ + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 32-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); #endif + +#ifndef ESP32_PARALLEL + // Support SPI TFT reads (not all displays support this) + #define tft_Read_8(C) SPI.transfer(C) +#endif + + #ifdef LOAD_GFXFF // We can include all the free fonts and they will only be built into // the sketch if they are used @@ -406,6 +472,7 @@ template static inline void swap_coord(T& a, T& b) { T t = a; a = b; b = t; } #ifndef min + // Return minimum of two numbers, may already be defined #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif @@ -667,6 +734,10 @@ class TFT_eSPI : public Print { void setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); + // These 3 functions are used together, for every startWrite() there must be an endWrite() + void startWrite(void); // Begin SPI transaction + void writeColor(uint16_t color, uint32_t len); // Write a colour without transaction overhead + void endWrite(void); // End SPI transaction size_t write(uint8_t); @@ -713,6 +784,8 @@ class TFT_eSPI : public Print { uint32_t _init_width, _init_height; // Display w/h as input, used by setRotation() uint32_t _width, _height; // Display w/h as modified by current rotation uint32_t addr_row, addr_col; + uint32_t xs_col, xe_col; + uint32_t ys_row, ye_row; uint32_t fontsloaded; @@ -750,9 +823,4 @@ class TFT_eSPI : public Print { // Load the Sprite Class #include "Extensions/Sprite.h" -// #ifdef ESP32 -// // Load the Sprite Class -// #include "Extensions/pSprite.h" -// #endif - #endif diff --git a/User_Setup.h b/User_Setup.h index 9b2359c..e8a5d79 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -113,14 +113,15 @@ // but saves pins for other functions. // Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + // In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 //#define TFT_CS PIN_D3 //#define TFT_DC PIN_D5 // 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 -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP // ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### @@ -136,6 +137,9 @@ //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST //#define TFT_BL 32 // LED back-light (only for ST7789 with backlight control pin) +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only // For the M5Stack module use these #define lines //#define TFT_MISO 19 @@ -146,10 +150,6 @@ //#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) //#define TFT_BL 32 // LED back-light (required for M5Stack) -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - // ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### // The library supports 8 bit parallel TFTs with the ESP32, the pin diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index 9b2359c..900da04 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -102,7 +102,7 @@ //#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin) -//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen +//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen //#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only @@ -113,14 +113,15 @@ // but saves pins for other functions. // Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + // In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 //#define TFT_CS PIN_D3 //#define TFT_DC PIN_D5 // 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 -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP // ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### @@ -134,8 +135,10 @@ //#define TFT_DC 2 // Data Command control pin //#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST -//#define TFT_BL 32 // LED back-light (only for ST7789 with backlight control pin) +//#define TOUCH_CS 22 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 21 // Write strobe for modified Raspberry Pi TFT only // For the M5Stack module use these #define lines //#define TFT_MISO 19 @@ -144,11 +147,7 @@ //#define TFT_CS 14 // Chip select control pin //#define TFT_DC 27 // Data Command control pin //#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light (required for M5Stack) - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only +//#define TFT_BL 32 // LED back-light (if needed) // ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### @@ -209,9 +208,9 @@ #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm -#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. -#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. //#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts // Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded @@ -263,4 +262,4 @@ // Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) // so changing it here has no effect -//#define SUPPORT_TRANSACTIONS +// #define SUPPORT_TRANSACTIONS diff --git a/keywords.txt b/keywords.txt index b197c5a..9fb1758 100644 --- a/keywords.txt +++ b/keywords.txt @@ -6,6 +6,9 @@ drawChar KEYWORD2 setAddrWindow KEYWORD2 setWindow KEYWORD2 readAddrWindow KEYWORD2 +startWrite KEYWORD2 +writeColor KEYWORD2 +endWrite KEYWORD2 pushColor KEYWORD2 pushColors KEYWORD2 fillScreen KEYWORD2 diff --git a/library.json b/library.json index 496bd2e..0867346 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.1.4", + "version": "1.2.0", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index fd62f0e..eb7a239 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.1.4 +version=1.2.0 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE