Add ESP32 VSPI or HSPI port option + others

If the VSPI port is in use and pins are not accessible (e.g. TTGO
T-Beam)
then add or uncomment the following line in the setup header file:
//#define USE_HSPI_PORT

Minor performance tweaks for ESP32 to minimise the occurence of the slow
transaction overhead.

setAddrWindow now takes xstart, ystart, width and height as inputs

Multi-sample raw touch x and y for noisy displays

Example update for setAddrWindow change compatibility
This commit is contained in:
Bodmer
2019-01-22 18:41:31 +00:00
parent 0fdd25186a
commit 054a824eb8
16 changed files with 355 additions and 242 deletions

View File

@@ -441,6 +441,8 @@ void TFT_eSPI::drawGlyph(uint16_t code)
int16_t cy = cursor_y + gFont.maxAscent - gdY[gNum]; int16_t cy = cursor_y + gFont.maxAscent - gdY[gNum];
int16_t cx = cursor_x + gdX[gNum]; int16_t cx = cursor_x + gdX[gNum];
startWrite(); // Avoid slow ESP32 transaction overhead for every pixel
for (int y = 0; y < gHeight[gNum]; y++) for (int y = 0; y < gHeight[gNum]; y++)
{ {
fontFile.read(pbuffer, gWidth[gNum]); //<// fontFile.read(pbuffer, gWidth[gNum]); //<//
@@ -480,7 +482,8 @@ void TFT_eSPI::drawGlyph(uint16_t code)
drawRect(cursor_x, cursor_y + gFont.maxAscent - gFont.ascent, gFont.spaceWidth, gFont.ascent, fg); drawRect(cursor_x, cursor_y + gFont.maxAscent - gFont.ascent, gFont.spaceWidth, gFont.ascent, fg);
cursor_x += gFont.spaceWidth + 1; cursor_x += gFont.spaceWidth + 1;
} }
endWrite();
} }
/*************************************************************************************** /***************************************************************************************

View File

@@ -301,7 +301,8 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp)
if (max_x > _tft->width()) max_x = _tft->width(); if (max_x > _tft->width()) max_x = _tft->width();
if (max_y > _tft->height()) max_y = _tft->height(); if (max_y > _tft->height()) max_y = _tft->height();
_tft->startWrite(); _tft->startWrite(); // ESP32: avoid transaction overhead for every tft pixel
// Scan destination bounding box and fetch transformed pixels from source Sprite // Scan destination bounding box and fetch transformed pixels from source Sprite
for (int32_t x = min_x; x <= max_x; x++) { for (int32_t x = min_x; x <= max_x; x++) {
int32_t xt = x - _tft->_xpivot; int32_t xt = x - _tft->_xpivot;
@@ -325,7 +326,8 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp)
else if (column_drawn) y = max_y; // Skip remaining column pixels else if (column_drawn) y = max_y; // Skip remaining column pixels
} }
} }
_tft->endWrite();
_tft->endWrite(); // ESP32: end transaction
return true; return true;
} }
@@ -465,7 +467,6 @@ void TFT_eSprite::pushSprite(int32_t x, int32_t y)
if (_bpp == 16) _tft->pushImage(x, y, _iwidth, _iheight, _img ); if (_bpp == 16) _tft->pushImage(x, y, _iwidth, _iheight, _img );
else _tft->pushImage(x, y, _dwidth, _dheight, _img8, (bool)(_bpp == 8)); else _tft->pushImage(x, y, _dwidth, _dheight, _img8, (bool)(_bpp == 8));
} }
@@ -562,7 +563,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint1
if (xs + w >= _iwidth) ws = _iwidth - xs; if (xs + w >= _iwidth) ws = _iwidth - xs;
if (ys + h >= _iheight) hs = _iheight - ys; if (ys + h >= _iheight) hs = _iheight - ys;
if (_bpp == 16) if (_bpp == 16) // Plot a 16 bpp image into a 16 bpp Sprite
{ {
for (uint32_t yp = yo; yp < yo + hs; yp++) for (uint32_t yp = yo; yp < yo + hs; yp++)
{ {
@@ -577,7 +578,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint1
ys++; ys++;
} }
} }
else if (_bpp == 8) else if (_bpp == 8) // Plot a 16 bpp image into a 8 bpp Sprite
{ {
for (uint32_t yp = yo; yp < yo + hs; yp++) for (uint32_t yp = yo; yp < yo + hs; yp++)
{ {
@@ -613,7 +614,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint1
x = y; x = y;
y = _dheight - tx - 1; y = _dheight - tx - 1;
} }
// Plot a 1bpp image into a 1bpp Sprite
uint8_t* pdata = (uint8_t* ) data; uint8_t* pdata = (uint8_t* ) data;
uint32_t ww = (w+7) & 0xFFF8; uint32_t ww = (w+7) & 0xFFF8;
for (int32_t yp = 0; yp<h; yp++) for (int32_t yp = 0; yp<h; yp++)
@@ -636,6 +637,10 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint1
*************************************************************************************x*/ *************************************************************************************x*/
void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint16_t *data) void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint16_t *data)
{ {
#ifdef ESP32
pushImage(x, y, w, h, (uint16_t*) data);
#else
// Partitioned memory FLASH processor
if ((x >= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) return; if ((x >= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) return;
if ((x + (int32_t)w < 0) || (y + (int32_t)h < 0)) return; if ((x + (int32_t)w < 0) || (y + (int32_t)h < 0)) return;
@@ -654,7 +659,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const
if (xs + w >= _iwidth) ws = _iwidth - xs; if (xs + w >= _iwidth) ws = _iwidth - xs;
if (ys + h >= _iheight) hs = _iheight - ys; if (ys + h >= _iheight) hs = _iheight - ys;
if (_bpp == 16) if (_bpp == 16) // Plot a 16 bpp image into a 16 bpp Sprite
{ {
for (uint32_t yp = yo; yp < yo + hs; yp++) for (uint32_t yp = yo; yp < yo + hs; yp++)
{ {
@@ -670,7 +675,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const
} }
} }
else if (_bpp == 8) else if (_bpp == 8) // Plot a 16 bpp image into a 8 bpp Sprite
{ {
for (uint32_t yp = yo; yp < yo + hs; yp++) for (uint32_t yp = yo; yp < yo + hs; yp++)
{ {
@@ -706,7 +711,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const
x = y; x = y;
y = _dheight - tx - 1; y = _dheight - tx - 1;
} }
// Plot a 1bpp image into a 1bpp Sprite
const uint8_t* pdata = (const uint8_t* ) data; const uint8_t* pdata = (const uint8_t* ) data;
uint32_t ww = (w+7) & 0xFFF8; uint32_t ww = (w+7) & 0xFFF8;
for (int32_t yp = 0; yp<h; yp++) for (int32_t yp = 0; yp<h; yp++)
@@ -721,6 +726,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const
} }
} }
} }
#endif // if ESP32 else ESP8266 check
} }

View File

@@ -22,18 +22,32 @@ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){
T_CS_L; T_CS_L;
// Start YP sample request for x position // Start YP sample request for x position, read 4 times and keep last sample
SPI.transfer(0xd0); // Start new YP conversion spi.transfer(0xd0); // Start new YP conversion
tmp = SPI.transfer(0); // Read first 8 bits spi.transfer(0); // Read first 8 bits
spi.transfer(0xd0); // Read last 8 bits and start new YP conversion
spi.transfer(0); // Read first 8 bits
spi.transfer(0xd0); // Read last 8 bits and start new YP conversion
spi.transfer(0); // Read first 8 bits
spi.transfer(0xd0); // Read last 8 bits and start new YP conversion
tmp = spi.transfer(0); // Read first 8 bits
tmp = tmp <<5; tmp = tmp <<5;
tmp |= 0x1f & (SPI.transfer(0x90)>>3); // Read last 8 bits and start new XP conversion tmp |= 0x1f & (spi.transfer(0x90)>>3); // Read last 8 bits and start new XP conversion
*x = tmp; *x = tmp;
// Start XP sample request for y position // Start XP sample request for y position, read 4 times and keep last sample
tmp = SPI.transfer(0); // Read first 8 bits spi.transfer(0); // Read first 8 bits
spi.transfer(0x90); // Read last 8 bits and start new XP conversion
spi.transfer(0); // Read first 8 bits
spi.transfer(0x90); // Read last 8 bits and start new XP conversion
spi.transfer(0); // Read first 8 bits
spi.transfer(0x90); // Read last 8 bits and start new XP conversion
tmp = spi.transfer(0); // Read first 8 bits
tmp = tmp <<5; tmp = tmp <<5;
tmp |= 0x1f & (SPI.transfer(0)>>3); // Read last 8 bits tmp |= 0x1f & (spi.transfer(0)>>3); // Read last 8 bits
*y = tmp; *y = tmp;
@@ -57,9 +71,9 @@ uint16_t TFT_eSPI::getTouchRawZ(void){
// Calculate Z // Calculate Z
int16_t tz = 0xFFF; int16_t tz = 0xFFF;
SPI.transfer(0xb0); // Start new Z1 conversion spi.transfer(0xb0); // Start new Z1 conversion
tz += SPI.transfer16(0xc0) >> 3; // Read Z1 and start Z2 conversion tz += spi.transfer16(0xc0) >> 3; // Read Z1 and start Z2 conversion
tz -= SPI.transfer16(0x00) >> 3; // Read Z2 tz -= spi.transfer16(0x00) >> 3; // Read Z2
T_CS_H; T_CS_H;

View File

@@ -15,10 +15,16 @@
#include "TFT_eSPI.h" #include "TFT_eSPI.h"
#include <pgmspace.h> #if defined (ESP32)
#if !defined (ESP32_PARALLEL)
#ifndef ESP32_PARALLEL #ifdef USE_HSPI_PORT
#include <SPI.h> SPIClass spi = SPIClass(HSPI);
#else // use default VSPI port
SPIClass spi = SPIClass(VSPI);
#endif
#endif
#else // ESP8266
SPIClass spi = SPIClass();
#endif #endif
// SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled
@@ -48,32 +54,32 @@ void busDir(uint32_t mask, uint8_t mode);
inline void TFT_eSPI::spi_begin(void){ inline void TFT_eSPI::spi_begin(void){
#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL)
if (locked) {locked = false; SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE));} if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE));}
#endif #endif
} }
inline void TFT_eSPI::spi_end(void){ inline void TFT_eSPI::spi_end(void){
#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL)
if(!inTransaction) {if (!locked) {locked = true; SPI.endTransaction();}} if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}}
#endif #endif
} }
inline void TFT_eSPI::spi_begin_read(void){ inline void TFT_eSPI::spi_begin_read(void){
#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL)
if (locked) {locked = false; SPI.beginTransaction(SPISettings(SPI_READ_FREQUENCY, MSBFIRST, TFT_SPI_MODE));} if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_READ_FREQUENCY, MSBFIRST, TFT_SPI_MODE));}
#else #else
#if !defined(ESP32_PARALLEL) #if !defined(ESP32_PARALLEL)
SPI.setFrequency(SPI_READ_FREQUENCY); spi.setFrequency(SPI_READ_FREQUENCY);
#endif #endif
#endif #endif
} }
inline void TFT_eSPI::spi_end_read(void){ inline void TFT_eSPI::spi_end_read(void){
#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL)
if(!inTransaction) {if (!locked) {locked = true; SPI.endTransaction();}} if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}}
#else #else
#if !defined(ESP32_PARALLEL) #if !defined(ESP32_PARALLEL)
SPI.setFrequency(SPI_FREQUENCY); spi.setFrequency(SPI_FREQUENCY);
#endif #endif
#endif #endif
} }
@@ -82,17 +88,17 @@ inline void TFT_eSPI::spi_end_read(void){
inline void TFT_eSPI::spi_begin_touch(void){ inline void TFT_eSPI::spi_begin_touch(void){
#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS)
if (locked) {locked = false; SPI.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));} if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));}
#else #else
SPI.setFrequency(SPI_TOUCH_FREQUENCY); spi.setFrequency(SPI_TOUCH_FREQUENCY);
#endif #endif
} }
inline void TFT_eSPI::spi_end_touch(void){ inline void TFT_eSPI::spi_end_touch(void){
#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS)
if(!inTransaction) {if (!locked) {locked = true; SPI.endTransaction();}} if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}}
#else #else
SPI.setFrequency(SPI_FREQUENCY); spi.setFrequency(SPI_FREQUENCY);
#endif #endif
} }
@@ -263,17 +269,17 @@ void TFT_eSPI::init(uint8_t tc)
#ifdef TFT_SPI_OVERLAP #ifdef TFT_SPI_OVERLAP
// Overlap mode SD0=MISO, SD1=MOSI, CLK=SCLK must use D3 as CS // Overlap mode SD0=MISO, SD1=MOSI, CLK=SCLK must use D3 as CS
// pins(int8_t sck, int8_t miso, int8_t mosi, int8_t ss); // pins(int8_t sck, int8_t miso, int8_t mosi, int8_t ss);
//SPI.pins( 6, 7, 8, 0); //spi.pins( 6, 7, 8, 0);
SPI.pins(6, 7, 8, 0); spi.pins(6, 7, 8, 0);
#endif #endif
SPI.begin(); // This will set HMISO to input spi.begin(); // This will set HMISO to input
#else #else
#if !defined(ESP32_PARALLEL) #if !defined(ESP32_PARALLEL)
#if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) #if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP)
SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1); spi.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1);
#else #else
SPI.begin(); spi.begin();
#endif #endif
#endif #endif
#endif #endif
@@ -284,9 +290,9 @@ void TFT_eSPI::init(uint8_t tc)
// SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled
// so the code here is for ESP8266 only // so the code here is for ESP8266 only
#if !defined (SUPPORT_TRANSACTIONS) && defined (ESP8266) #if !defined (SUPPORT_TRANSACTIONS) && defined (ESP8266)
SPI.setBitOrder(MSBFIRST); spi.setBitOrder(MSBFIRST);
SPI.setDataMode(TFT_SPI_MODE); spi.setDataMode(TFT_SPI_MODE);
SPI.setFrequency(SPI_FREQUENCY); spi.setFrequency(SPI_FREQUENCY);
#endif #endif
#if defined(ESP32_PARALLEL) #if defined(ESP32_PARALLEL)
@@ -298,7 +304,7 @@ void TFT_eSPI::init(uint8_t tc)
digitalWrite(TFT_CS, HIGH); // Chip select high (inactive) digitalWrite(TFT_CS, HIGH); // Chip select high (inactive)
pinMode(TFT_CS, OUTPUT); pinMode(TFT_CS, OUTPUT);
#else #else
SPI.setHwCs(1); // Use hardware SS toggling spi.setHwCs(1); // Use hardware SS toggling
#endif #endif
#endif #endif
@@ -611,7 +617,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
{ {
#if defined(ESP32_PARALLEL) #if defined(ESP32_PARALLEL)
readAddrWindow(x0, y0, x0, y0); // Sets CS low readAddrWindow(x0, y0, 1, 1); // Sets CS low
// Set masked pins D0- D7 to input // Set masked pins D0- D7 to input
busDir(dir_mask, INPUT); busDir(dir_mask, INPUT);
@@ -652,7 +658,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
spi_begin_read(); spi_begin_read();
readAddrWindow(x0, y0, x0, y0); // Sets CS low readAddrWindow(x0, y0, 1, 1); // Sets CS low
#ifdef TFT_SDA_READ #ifdef TFT_SDA_READ
begin_SDA_Read(); begin_SDA_Read();
@@ -757,7 +763,7 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t
#if defined(ESP32_PARALLEL) #if defined(ESP32_PARALLEL)
readAddrWindow(x, y, x + w - 1, y + h - 1); // Sets CS low readAddrWindow(x, y, w, h); // Sets CS low
// Set masked pins D0- D7 to input // Set masked pins D0- D7 to input
busDir(dir_mask, INPUT); busDir(dir_mask, INPUT);
@@ -799,7 +805,7 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t
spi_begin_read(); spi_begin_read();
readAddrWindow(x, y, x + w - 1, y + h - 1); // Sets CS low readAddrWindow(x, y, w, h); // Sets CS low
#ifdef TFT_SDA_READ #ifdef TFT_SDA_READ
begin_SDA_Read(); begin_SDA_Read();
@@ -881,7 +887,7 @@ void TFT_eSPI::begin_SDA_Read(void)
#ifdef TFT_SPI_OVERLAP #ifdef TFT_SPI_OVERLAP
// Reads in overlap mode not supported // Reads in overlap mode not supported
#else #else
SPI.end(); spi.end();
#endif #endif
#endif #endif
} }
@@ -901,9 +907,9 @@ void TFT_eSPI::end_SDA_Read(void)
pinMatrixInAttach(TFT_MISO, VSPIQ_IN_IDX, false); pinMatrixInAttach(TFT_MISO, VSPIQ_IN_IDX, false);
#else #else
#ifdef TFT_SPI_OVERLAP #ifdef TFT_SPI_OVERLAP
SPI.pins(6, 7, 8, 0); spi.pins(6, 7, 8, 0);
#else #else
SPI.begin(); spi.begin();
#endif #endif
#endif #endif
} }
@@ -946,7 +952,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t
spi_begin(); spi_begin();
inTransaction = true; inTransaction = true;
setAddrWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR setWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR
data += dx + dy * w; data += dx + dy * w;
@@ -1007,7 +1013,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t
{ {
if (transp != *ptr) if (transp != *ptr)
{ {
if (move) { move = false; setAddrWindow(px, y, xe, ye); } if (move) { move = false; setWindow(px, y, xe, ye); }
lineBuf[np] = *ptr; lineBuf[np] = *ptr;
np++; np++;
} }
@@ -1042,7 +1048,10 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t
***************************************************************************************/ ***************************************************************************************/
void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint16_t *data) void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint16_t *data)
{ {
#ifdef ESP32
pushImage(x, y, w, h, (uint16_t*)data);
#else
// Partitioned memory FLASH processor
if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return; if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return;
int32_t dx = 0; int32_t dx = 0;
@@ -1066,7 +1075,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin
uint16_t buffer[64]; uint16_t buffer[64];
uint16_t* pix_buffer = buffer; uint16_t* pix_buffer = buffer;
setAddrWindow(x, y, x + dw - 1, y + dh - 1); setWindow(x, y, x + dw - 1, y + dh - 1);
// Work out the number whole buffers to send // Work out the number whole buffers to send
uint16_t nb = (dw * dh) / 64; uint16_t nb = (dw * dh) / 64;
@@ -1095,6 +1104,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin
inTransaction = false; inTransaction = false;
spi_end(); spi_end();
#endif // if ESP32 else ESP8266 check
} }
@@ -1104,7 +1114,10 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin
***************************************************************************************/ ***************************************************************************************/
void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint16_t *data, uint16_t transp) void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint16_t *data, uint16_t transp)
{ {
#ifdef ESP32
pushImage(x, y, w, h, (uint16_t*) data, transp);
#else
// Partitioned memory FLASH processor
if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return; if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return;
int32_t dx = 0; int32_t dx = 0;
@@ -1145,7 +1158,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin
uint16_t color = pgm_read_word(ptr); uint16_t color = pgm_read_word(ptr);
if (transp != color) if (transp != color)
{ {
if (move) { move = false; setAddrWindow(px, y, xe, ye); } if (move) { move = false; setWindow(px, y, xe, ye); }
lineBuf[np] = color; lineBuf[np] = color;
np++; np++;
} }
@@ -1171,6 +1184,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin
inTransaction = false; inTransaction = false;
spi_end(); spi_end();
#endif // if ESP32 else ESP8266 check
} }
@@ -1198,7 +1212,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t *
spi_begin(); spi_begin();
inTransaction = true; inTransaction = true;
setAddrWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR setWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR
// Line buffer makes plotting faster // Line buffer makes plotting faster
uint16_t lineBuf[dw]; uint16_t lineBuf[dw];
@@ -1339,7 +1353,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t *
{ {
if (transp != *ptr) if (transp != *ptr)
{ {
if (move) { move = false; setAddrWindow(px, y, xe, ye);} if (move) { move = false; setWindow(px, y, xe, ye);}
uint8_t color = *ptr; uint8_t color = *ptr;
// Shifts are slow so check if colour has changed first // Shifts are slow so check if colour has changed first
@@ -1398,7 +1412,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t *
if (move) if (move)
{ {
move = false; move = false;
setAddrWindow(px, y, xe, ye); setWindow(px, y, xe, ye);
} }
np++; np++;
} }
@@ -1464,7 +1478,7 @@ void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_
spi_begin_read(); spi_begin_read();
readAddrWindow(x0, y0, x0 + w - 1, y0 + h - 1); // Sets CS low readAddrWindow(x0, y0, w, h); // Sets CS low
#ifdef TFT_SDA_READ #ifdef TFT_SDA_READ
begin_SDA_Read(); begin_SDA_Read();
@@ -2397,7 +2411,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u
uint8_t mask = 0x1; uint8_t mask = 0x1;
spi_begin(); spi_begin();
//inTransaction = true; //inTransaction = true;
setAddrWindow(x, y, x+5, y+8); setWindow(x, y, x+5, y+8);
for (int8_t i = 0; i < 5; i++ ) column[i] = pgm_read_byte(font + (c * 5) + i); for (int8_t i = 0; i < 5; i++ ) column[i] = pgm_read_byte(font + (c * 5) + i);
column[5] = 0; column[5] = 0;
@@ -2620,27 +2634,26 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u
/*************************************************************************************** /***************************************************************************************
** Function name: setWindow ** Function name: setAddrWindow
** Description: define an area to receive a stream of pixels ** Description: define an area to receive a stream of pixels
***************************************************************************************/ ***************************************************************************************/
// Chip select is high at the end of this function // Chip select is high at the end of this function
void TFT_eSPI::setWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1) void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t w, int32_t h)
{ {
spi_begin(); spi_begin();
setAddrWindow(x0, y0, x1, y1); setWindow(x0, y0, x0 + w - 1, y0 + h - 1);
CS_H; CS_H;
spi_end(); spi_end();
} }
/*************************************************************************************** /***************************************************************************************
** Function name: setAddrWindow ** Function name: setWindow
** Description: define an area to receive a stream of pixels ** Description: define an area to receive a stream of pixels
***************************************************************************************/ ***************************************************************************************/
// Chip select stays low, use setWindow() from sketches // Chip select stays low, call spi_begin first. Use setAddrWindow() from sketches
#if defined (ESP8266) && !defined (RPI_WRITE_STROBE) && !defined (RPI_ILI9486_DRIVER) #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) && !defined (RPI_ILI9486_DRIVER)
void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye)
{ {
//spi_begin(); //spi_begin();
@@ -2708,7 +2721,7 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye)
#elif defined (ESP8266) && !defined (RPI_WRITE_STROBE) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits #elif defined (ESP8266) && !defined (RPI_WRITE_STROBE) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits
void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye)
{ {
//spi_begin(); //spi_begin();
@@ -2731,7 +2744,7 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye)
DC_D; DC_D;
uint8_t xb[] = { 0, (uint8_t) (xs>>8), 0, (uint8_t) (xs>>0), 0, (uint8_t) (xe>>8), 0, (uint8_t) (xe>>0), }; 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); spi.writePattern(&xb[0], 8, 1);
// Row addr set // Row addr set
DC_C; DC_C;
@@ -2745,7 +2758,7 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye)
DC_D; DC_D;
uint8_t yb[] = { 0, (uint8_t) (ys>>8), 0, (uint8_t) (ys>>0), 0, (uint8_t) (ye>>8), 0, (uint8_t) (ye>>0), }; 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); spi.writePattern(&yb[0], 8, 1);
// write to RAM // write to RAM
DC_C; DC_C;
@@ -2763,7 +2776,7 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye)
#else #else
#if defined (ESP8266) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits #if defined (ESP8266) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits
void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
{ {
//spi_begin(); //spi_begin();
@@ -2840,7 +2853,7 @@ void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
#else // This is for the ESP32 #else // This is for the ESP32
void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
{ {
//spi_begin(); //spi_begin();
@@ -2862,7 +2875,7 @@ void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
#if defined (RPI_ILI9486_DRIVER) #if defined (RPI_ILI9486_DRIVER)
uint8_t xb[] = { 0, (uint8_t) (x0>>8), 0, (uint8_t) (x0>>0), 0, (uint8_t) (x1>>8), 0, (uint8_t) (x1>>0), }; 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); spi.writePattern(&xb[0], 8, 1);
#else #else
tft_Write_32(SPI_32(x0, x1)); tft_Write_32(SPI_32(x0, x1));
#endif #endif
@@ -2876,7 +2889,7 @@ void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
#if defined (RPI_ILI9486_DRIVER) #if defined (RPI_ILI9486_DRIVER)
uint8_t yb[] = { 0, (uint8_t) (y0>>8), 0, (uint8_t) (y0>>0), 0, (uint8_t) (y1>>8), 0, (uint8_t) (y1>>0), }; 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); spi.writePattern(&yb[0], 8, 1);
#else #else
tft_Write_32(SPI_32(y0, y1)); tft_Write_32(SPI_32(y0, y1));
#endif #endif
@@ -2900,10 +2913,13 @@ void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
***************************************************************************************/ ***************************************************************************************/
// Chip select stays low // Chip select stays low
#if defined (ESP8266) && !defined (RPI_WRITE_STROBE) #if defined (ESP8266) && !defined (RPI_WRITE_STROBE)
void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h)
{ {
//spi_begin(); //spi_begin();
int32_t xe = xs + w - 1;
int32_t ye = ys + h - 1;
addr_col = 0xFFFF; addr_col = 0xFFFF;
addr_row = 0xFFFF; addr_row = 0xFFFF;
@@ -2966,10 +2982,13 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye)
#else //ESP32 #else //ESP32
void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h)
{ {
//spi_begin(); //spi_begin();
int32_t xe = xs + w - 1;
int32_t ye = ys + h - 1;
addr_col = 0xFFFF; addr_col = 0xFFFF;
addr_row = 0xFFFF; addr_row = 0xFFFF;
@@ -2987,7 +3006,7 @@ void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
DC_D; DC_D;
tft_Write_32(SPI_32(x0, x1)); tft_Write_32(SPI_32(xs, xe));
// Row addr set // Row addr set
DC_C; DC_C;
@@ -2996,7 +3015,7 @@ void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
DC_D; DC_D;
tft_Write_32(SPI_32(y0, y1)); tft_Write_32(SPI_32(ys, ye));
DC_C; DC_C;
@@ -3044,7 +3063,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color)
#if defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits per byte #if defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits per byte
uint8_t cBin[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0)}; uint8_t cBin[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0)};
SPI.writePattern(&cBin[0], 4, 2); spi.writePattern(&cBin[0], 4, 2);
#else #else
SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO);
// Load the two coords as a 32 bit value and shift in one go // Load the two coords as a 32 bit value and shift in one go
@@ -3072,7 +3091,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color)
#if defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits per byte #if defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits per byte
uint8_t cBin[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0)}; uint8_t cBin[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0)};
SPI.writePattern(&cBin[0], 4, 2); spi.writePattern(&cBin[0], 4, 2);
#else #else
SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO);
// Load the two coords as a 32 bit value and shift in one go // Load the two coords as a 32 bit value and shift in one go
@@ -3221,7 +3240,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color)
#if defined (RPI_ILI9486_DRIVER) #if defined (RPI_ILI9486_DRIVER)
uint8_t xb[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), }; 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); spi.writePattern(&xb[0], 8, 1);
#else #else
tft_Write_32(SPI_32(x, x)); tft_Write_32(SPI_32(x, x));
#endif #endif
@@ -3240,7 +3259,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color)
#if defined (RPI_ILI9486_DRIVER) #if defined (RPI_ILI9486_DRIVER)
uint8_t yb[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), }; 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); spi.writePattern(&yb[0], 8, 1);
#else #else
tft_Write_32(SPI_32(y, y)); tft_Write_32(SPI_32(y, y));
#endif #endif
@@ -3295,7 +3314,7 @@ void TFT_eSPI::pushColor(uint16_t color, uint32_t len)
#ifdef RPI_WRITE_STROBE #ifdef RPI_WRITE_STROBE
uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color };
if(len) SPI.writePattern(&colorBin[0], 2, 1); len--; if(len) spi.writePattern(&colorBin[0], 2, 1); len--;
while(len--) {WR_L; WR_H;} while(len--) {WR_L; WR_H;}
#else #else
#if defined (ESP32_PARALLEL) #if defined (ESP32_PARALLEL)
@@ -3340,7 +3359,7 @@ void TFT_eSPI::writeColor(uint16_t color, uint32_t len)
{ {
#ifdef RPI_WRITE_STROBE #ifdef RPI_WRITE_STROBE
uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color };
if(len) SPI.writePattern(&colorBin[0], 2, 1); len--; if(len) spi.writePattern(&colorBin[0], 2, 1); len--;
while(len--) {WR_L; WR_H;} while(len--) {WR_L; WR_H;}
#else #else
#if defined (ESP32_PARALLEL) #if defined (ESP32_PARALLEL)
@@ -3355,7 +3374,7 @@ void TFT_eSPI::writeColor(uint16_t color, uint32_t len)
** Function name: pushColors ** Function name: pushColors
** Description: push an array of pixels for 16 bit raw image drawing ** Description: push an array of pixels for 16 bit raw image drawing
***************************************************************************************/ ***************************************************************************************/
// Assumed that setWindow() has previously been called // Assumed that setAddrWindow() has previously been called
void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) void TFT_eSPI::pushColors(uint8_t *data, uint32_t len)
{ {
@@ -3364,8 +3383,8 @@ void TFT_eSPI::pushColors(uint8_t *data, uint32_t len)
CS_L; CS_L;
#if defined (RPI_WRITE_STROBE) #if defined (RPI_WRITE_STROBE)
while ( len >=64 ) {SPI.writePattern(data, 64, 1); data += 64; len -= 64; } while ( len >=64 ) {spi.writePattern(data, 64, 1); data += 64; len -= 64; }
if (len) SPI.writePattern(data, len, 1); if (len) spi.writePattern(data, len, 1);
#else #else
#ifdef ESP32_PARALLEL #ifdef ESP32_PARALLEL
while (len--) {tft_Write_8(*data); data++;} while (len--) {tft_Write_8(*data); data++;}
@@ -3374,10 +3393,10 @@ void TFT_eSPI::pushColors(uint8_t *data, uint32_t len)
while (len>1) {color = (*data++) | ((*data++)<<8); tft_Write_16(color); len-=2;} while (len>1) {color = (*data++) | ((*data++)<<8); tft_Write_16(color); len-=2;}
#else #else
#if (SPI_FREQUENCY == 80000000) #if (SPI_FREQUENCY == 80000000)
while ( len >=64 ) {SPI.writePattern(data, 64, 1); data += 64; len -= 64; } while ( len >=64 ) {spi.writePattern(data, 64, 1); data += 64; len -= 64; }
if (len) SPI.writePattern(data, len, 1); if (len) spi.writePattern(data, len, 1);
#else #else
SPI.writeBytes(data, len); spi.writeBytes(data, len);
#endif #endif
#endif #endif
#endif #endif
@@ -3403,8 +3422,8 @@ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap)
if (swap) while ( len-- ) {tft_Write_16(*data); data++;} if (swap) while ( len-- ) {tft_Write_16(*data); data++;}
else while ( len-- ) {tft_Write_16S(*data); data++;} else while ( len-- ) {tft_Write_16S(*data); data++;}
#else #else
if (swap) SPI.writePixels(data,len<<1); if (swap) spi.writePixels(data,len<<1);
else SPI.writeBytes((uint8_t*)data,len<<1); else spi.writeBytes((uint8_t*)data,len<<1);
#endif #endif
#else #else
@@ -3600,7 +3619,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t
if (x0 > x1) {spi_end(); return;} if (x0 > x1) {spi_end(); return;}
setAddrWindow(y0, x0, y0, _height); setWindow(y0, x0, y0, _height);
SPI1U1 = mask; SPI1U1 = mask;
SPI1W0 = swapped_color; SPI1W0 = swapped_color;
for (; x0 <= x1; x0++) { for (; x0 <= x1; x0++) {
@@ -3613,7 +3632,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t
if ((y0 < 0) || (y0 >= _width)) break; if ((y0 < 0) || (y0 >= _width)) break;
err += dx; err += dx;
while(SPI1CMD & SPIBUSY) {} while(SPI1CMD & SPIBUSY) {}
setAddrWindow(y0, x0+1, y0, _height); setWindow(y0, x0+1, y0, _height);
SPI1U1 = mask; SPI1U1 = mask;
SPI1W0 = swapped_color; SPI1W0 = swapped_color;
} }
@@ -3634,7 +3653,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t
if (x0 > x1) {spi_end(); return;} if (x0 > x1) {spi_end(); return;}
setAddrWindow(x0, y0, _width, y0); setWindow(x0, y0, _width, y0);
SPI1U1 = mask; SPI1U1 = mask;
SPI1W0 = swapped_color; SPI1W0 = swapped_color;
for (; x0 <= x1; x0++) { for (; x0 <= x1; x0++) {
@@ -3647,7 +3666,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t
if ((y0 < 0) || (y0 >= _height)) break; if ((y0 < 0) || (y0 >= _height)) break;
err += dx; err += dx;
while(SPI1CMD & SPIBUSY) {} while(SPI1CMD & SPIBUSY) {}
setAddrWindow(x0+1, y0, _width, y0); setWindow(x0+1, y0, _width, y0);
SPI1U1 = mask; SPI1U1 = mask;
SPI1W0 = swapped_color; SPI1W0 = swapped_color;
} }
@@ -3670,13 +3689,18 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t
#if defined (ESP8266) && !defined (RPI_WRITE_STROBE) #if defined (ESP8266) && !defined (RPI_WRITE_STROBE)
void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color)
{ {
// Rudimentary clipping // Clipping
if ((x >= _width) || (y >= _height) || (h < 1)) return; if ((x < 0) || (x >= _width) || (y >= _height)) return;
if ((y + h - 1) >= _height) h = _height - y;
if (y < 0) { h += y; y = 0; }
if ((y + h) > _height) h = _height - y;
if (h < 1) return;
spi_begin(); spi_begin();
setAddrWindow(x, y, x, y + h - 1); setWindow(x, y, x, y + h - 1);
writeBlock(color, h); writeBlock(color, h);
@@ -3689,17 +3713,22 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color)
void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color)
{ {
// Rudimentary clipping // Clipping
if ((x >= _width) || (y >= _height) || (h < 1)) return; if ((x < 0) || (x >= _width) || (y >= _height)) return;
if ((y + h - 1) >= _height) h = _height - y;
if (y < 0) { h += y; y = 0; }
if ((y + h) > _height) h = _height - y;
if (h < 1) return;
spi_begin(); spi_begin();
setAddrWindow(x, y, x, y + h - 1); setWindow(x, y, x, y + h - 1);
#ifdef RPI_WRITE_STROBE #ifdef RPI_WRITE_STROBE
#if defined (ESP8266) #if defined (ESP8266)
// SPI1U1 will already be set to transfer 16 bits by setAddrWindow() // SPI1U1 will already be set to transfer 16 bits by setWindow()
SPI1W0 = (color >> 8) | (color << 8); SPI1W0 = (color >> 8) | (color << 8);
SPI1CMD |= SPIBUSY; SPI1CMD |= SPIBUSY;
while(SPI1CMD & SPIBUSY) {} while(SPI1CMD & SPIBUSY) {}
@@ -3729,13 +3758,18 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color)
#if defined (ESP8266) && !defined (RPI_WRITE_STROBE) #if defined (ESP8266) && !defined (RPI_WRITE_STROBE)
void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color)
{ {
// Rudimentary clipping // Clipping
if ((x >= _width) || (y >= _height) || (w < 1)) return; if ((y < 0) || (x >= _width) || (y >= _height)) return;
if ((x + w - 1) >= _width) w = _width - x;
if (x < 0) { w += x; x = 0; }
if ((x + w) > _width) w = _width - x;
if (w < 1) return;
spi_begin(); spi_begin();
setAddrWindow(x, y, x + w - 1, y); setWindow(x, y, x + w - 1, y);
writeBlock(color, w); writeBlock(color, w);
@@ -3753,11 +3787,11 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color)
if ((x + w - 1) >= _width) w = _width - x; if ((x + w - 1) >= _width) w = _width - x;
spi_begin(); spi_begin();
setAddrWindow(x, y, x + w - 1, y); setWindow(x, y, x + w - 1, y);
#ifdef RPI_WRITE_STROBE #ifdef RPI_WRITE_STROBE
#if defined (ESP8266) #if defined (ESP8266)
// SPI1U1 will already be set to transfer 16 bits by setAddrWindow() // SPI1U1 will already be set to transfer 16 bits by setWindow()
SPI1W0 = (color >> 8) | (color << 8); SPI1W0 = (color >> 8) | (color << 8);
SPI1CMD |= SPIBUSY; SPI1CMD |= SPIBUSY;
while(SPI1CMD & SPIBUSY) {} while(SPI1CMD & SPIBUSY) {}
@@ -3787,13 +3821,19 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color)
#if defined (ESP8266) && !defined (RPI_WRITE_STROBE) #if defined (ESP8266) && !defined (RPI_WRITE_STROBE)
void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color)
{ {
// rudimentary clipping (drawChar w/big text requires this) // Clipping
if ((x > _width) || (y > _height) || (w < 1) || (h < 1)) return; if ((x >= _width) || (y >= _height)) return;
if ((x + w - 1) > _width) w = _width - x;
if ((y + h - 1) > _height) h = _height - y; if (x < 0) { w += x; x = 0; }
if (y < 0) { h += y; y = 0; }
if ((x + w) > _width) w = _width - x;
if ((y + h) > _height) h = _height - y;
if ((w < 1) || (h < 1)) return;
spi_begin(); spi_begin();
setAddrWindow(x, y, x + w - 1, y + h - 1); setWindow(x, y, x + w - 1, y + h - 1);
writeBlock(color, w * h); writeBlock(color, w * h);
@@ -3806,13 +3846,19 @@ void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col
void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color)
{ {
// rudimentary clipping (drawChar w/big text requires this) // Clipping
if ((x > _width) || (y > _height) || (w < 1) || (h < 1)) return; if ((x >= _width) || (y >= _height)) return;
if ((x + w - 1) > _width) w = _width - x;
if ((y + h - 1) > _height) h = _height - y; if (x < 0) { w += x; x = 0; }
if (y < 0) { h += y; y = 0; }
if ((x + w) > _width) w = _width - x;
if ((y + h) > _height) h = _height - y;
if ((w < 1) || (h < 1)) return;
spi_begin(); spi_begin();
setAddrWindow(x, y, x + w - 1, y + h - 1); setWindow(x, y, x + w - 1, y + h - 1);
uint32_t n = (uint32_t)w * (uint32_t)h; uint32_t n = (uint32_t)w * (uint32_t)h;
@@ -3906,6 +3952,10 @@ size_t TFT_eSPI::write(uint8_t utf8)
if(fontLoaded) if(fontLoaded)
{ {
uint16_t unicode = decodeUTF8(utf8); uint16_t unicode = decodeUTF8(utf8);
//Serial.print("UniCode="); Serial.println(unicode);
//Serial.print("UTF8 ="); Serial.println(utf8);
if (!unicode) return 1; if (!unicode) return 1;
//fontFile = SPIFFS.open( _gFontFilename, "r" ); //fontFile = SPIFFS.open( _gFontFilename, "r" );
@@ -4176,7 +4226,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font)
// Faster drawing of characters and background using block write // Faster drawing of characters and background using block write
{ {
spi_begin(); spi_begin();
setAddrWindow(x, y, (x + w * 8) - 1, y + height - 1); setWindow(x, y, (x + w * 8) - 1, y + height - 1);
uint8_t mask; uint8_t mask;
for (int i = 0; i < height; i++) for (int i = 0; i < height; i++)
@@ -4238,7 +4288,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font)
} }
while (line--) { // In this case the while(line--) is faster while (line--) { // In this case the while(line--) is faster
pc++; // This is faster than putting pc+=line before while()? pc++; // This is faster than putting pc+=line before while()?
setAddrWindow(px, py, px + ts, py + ts); setWindow(px, py, px + ts, py + ts);
if (ts) { if (ts) {
tnp = np; tnp = np;
@@ -4267,7 +4317,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font)
// so use faster drawing of characters and background using block write // so use faster drawing of characters and background using block write
{ {
//spi_begin(); //spi_begin();
setAddrWindow(x, y, x + width - 1, y + height - 1); setWindow(x, y, x + width - 1, y + height - 1);
#ifdef RPI_WRITE_STROBE #ifdef RPI_WRITE_STROBE
uint8_t textcolorBin[] = { (uint8_t) (textcolor >> 8), (uint8_t) textcolor }; uint8_t textcolorBin[] = { (uint8_t) (textcolor >> 8), (uint8_t) textcolor };
@@ -4282,7 +4332,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font)
line &= 0x7F; line &= 0x7F;
line++; w -= line; line++; w -= line;
#ifdef RPI_WRITE_STROBE #ifdef RPI_WRITE_STROBE
SPI.writePattern(&textcolorBin[0], 2, 1); line--; spi.writePattern(&textcolorBin[0], 2, 1); line--;
while(line--) {WR_L; WR_H;} while(line--) {WR_L; WR_H;}
#else #else
#ifdef ESP32_PARALLEL #ifdef ESP32_PARALLEL
@@ -4295,7 +4345,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font)
else { else {
line++; w -= line; line++; w -= line;
#ifdef RPI_WRITE_STROBE #ifdef RPI_WRITE_STROBE
SPI.writePattern(&textbgcolorBin[0], 2, 1); line--; spi.writePattern(&textbgcolorBin[0], 2, 1); line--;
while(line--) {WR_L; WR_H;} while(line--) {WR_L; WR_H;}
#else #else
#ifdef ESP32_PARALLEL #ifdef ESP32_PARALLEL
@@ -4927,56 +4977,56 @@ void writeBlock(uint16_t color, uint32_t repeat)
if (repeat > 19) if (repeat > 19)
{ {
SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_NUM), SPI_USR_MOSI_DBITLEN, 479, SPI_USR_MOSI_DBITLEN_S); SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_PORT), SPI_USR_MOSI_DBITLEN, 479, SPI_USR_MOSI_DBITLEN_S);
while(repeat>19) while(repeat>19)
{ {
while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), r0); WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0);
WRITE_PERI_REG(SPI_W1_REG(SPI_NUM), r1); WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1);
WRITE_PERI_REG(SPI_W2_REG(SPI_NUM), r2); WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), r2);
WRITE_PERI_REG(SPI_W3_REG(SPI_NUM), r0); WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0);
WRITE_PERI_REG(SPI_W4_REG(SPI_NUM), r1); WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1);
WRITE_PERI_REG(SPI_W5_REG(SPI_NUM), r2); WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2);
WRITE_PERI_REG(SPI_W6_REG(SPI_NUM), r0); WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0);
WRITE_PERI_REG(SPI_W7_REG(SPI_NUM), r1); WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1);
WRITE_PERI_REG(SPI_W8_REG(SPI_NUM), r2); WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2);
WRITE_PERI_REG(SPI_W9_REG(SPI_NUM), r0); WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), r0);
WRITE_PERI_REG(SPI_W10_REG(SPI_NUM), r1); WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), r1);
WRITE_PERI_REG(SPI_W11_REG(SPI_NUM), r2); WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), r2);
WRITE_PERI_REG(SPI_W12_REG(SPI_NUM), r0); WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), r0);
WRITE_PERI_REG(SPI_W13_REG(SPI_NUM), r1); WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), r1);
WRITE_PERI_REG(SPI_W14_REG(SPI_NUM), r2); WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), r2);
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
repeat -= 20; repeat -= 20;
} }
while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
} }
if (repeat) if (repeat)
{ {
SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_NUM), SPI_USR_MOSI_DBITLEN, (repeat * 24) - 1, SPI_USR_MOSI_DBITLEN_S); SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_PORT), SPI_USR_MOSI_DBITLEN, (repeat * 24) - 1, SPI_USR_MOSI_DBITLEN_S);
WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), r0); WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0);
WRITE_PERI_REG(SPI_W1_REG(SPI_NUM), r1); WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1);
WRITE_PERI_REG(SPI_W2_REG(SPI_NUM), r2); WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), r2);
WRITE_PERI_REG(SPI_W3_REG(SPI_NUM), r0); WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0);
WRITE_PERI_REG(SPI_W4_REG(SPI_NUM), r1); WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1);
WRITE_PERI_REG(SPI_W5_REG(SPI_NUM), r2); WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2);
if (repeat > 8 ) if (repeat > 8 )
{ {
WRITE_PERI_REG(SPI_W6_REG(SPI_NUM), r0); WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0);
WRITE_PERI_REG(SPI_W7_REG(SPI_NUM), r1); WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1);
WRITE_PERI_REG(SPI_W8_REG(SPI_NUM), r2); WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2);
WRITE_PERI_REG(SPI_W9_REG(SPI_NUM), r0); WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), r0);
WRITE_PERI_REG(SPI_W10_REG(SPI_NUM), r1); WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), r1);
WRITE_PERI_REG(SPI_W11_REG(SPI_NUM), r2); WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), r2);
WRITE_PERI_REG(SPI_W12_REG(SPI_NUM), r0); WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), r0);
WRITE_PERI_REG(SPI_W13_REG(SPI_NUM), r1); WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), r1);
WRITE_PERI_REG(SPI_W14_REG(SPI_NUM), r2); WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), r2);
} }
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
} }
} }
@@ -4990,39 +5040,39 @@ void writeBlock(uint16_t color, uint32_t repeat)
if (repeat > 31) // Revert legacy toggle buffer change if (repeat > 31) // Revert legacy toggle buffer change
{ {
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 511); WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511);
while(repeat>31) while(repeat>31)
{ {
while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W1_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W2_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W3_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W4_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W5_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W6_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W7_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W8_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W9_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W10_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W11_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W12_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W13_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W14_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W15_REG(SPI_NUM), color32); WRITE_PERI_REG(SPI_W15_REG(SPI_PORT), color32);
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
repeat -= 32; repeat -= 32;
} }
while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
} }
if (repeat) if (repeat)
{ {
// Revert toggle buffer change // Revert toggle buffer change
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), (repeat << 4) - 1); WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (repeat << 4) - 1);
for (uint32_t i=0; i <= (repeat>>1); i++) WRITE_PERI_REG((SPI_W0_REG(SPI_NUM) + (i << 2)), color32); for (uint32_t i=0; i <= (repeat>>1); i++) WRITE_PERI_REG((SPI_W0_REG(SPI_PORT) + (i << 2)), color32);
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
} }
} }
#endif #endif

View File

@@ -105,7 +105,11 @@
#ifdef ESP32 #ifdef ESP32
#include "soc/spi_reg.h" #include "soc/spi_reg.h"
#define SPI_NUM 0x3 #ifdef USE_HSPI_PORT
#define SPI_PORT HSPI
#else
#define SPI_PORT VSPI
#endif
#endif #endif
#ifdef SMOOTH_FONT #ifdef SMOOTH_FONT
@@ -312,32 +316,32 @@
#elif defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB #elif defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB
// Write 8 bits to TFT // 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 // Convert 16 bit colour to 18 bit and write in 3 bytes
#define tft_Write_16(C) SPI.transfer((C & 0xF800)>>8); \ #define tft_Write_16(C) spi.transfer((C & 0xF800)>>8); \
SPI.transfer((C & 0x07E0)>>3); \ spi.transfer((C & 0x07E0)>>3); \
SPI.transfer((C & 0x001F)<<3) spi.transfer((C & 0x001F)<<3)
// Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
#define tft_Write_16S(C) SPI.transfer(C & 0xF8); \ #define tft_Write_16S(C) spi.transfer(C & 0xF8); \
SPI.transfer((C & 0xE0)>>11 | (C & 0x07)<<5); \ spi.transfer((C & 0xE0)>>11 | (C & 0x07)<<5); \
SPI.transfer((C & 0x1F00)>>5) spi.transfer((C & 0x1F00)>>5)
// Write 32 bits to TFT // 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) #elif defined (RPI_ILI9486_DRIVER)
#define tft_Write_8(C) SPI.transfer(0); SPI.transfer(C) #define tft_Write_8(C) spi.transfer(0); spi.transfer(C)
#define tft_Write_16(C) SPI.write16(C) #define tft_Write_16(C) spi.write16(C)
#define tft_Write_16S(C) SPI.write16(C<<8 | C>>8) #define tft_Write_16S(C) spi.write16(C<<8 | C>>8)
#define tft_Write_32(C) SPI.write32(C) #define tft_Write_32(C) spi.write32(C)
#elif defined ESP8266 #elif defined ESP8266
#define tft_Write_8(C) SPI.write(C) #define tft_Write_8(C) spi.write(C)
#define tft_Write_16(C) SPI.write16(C) #define tft_Write_16(C) spi.write16(C)
#define tft_Write_32(C) SPI.write32(C) #define tft_Write_32(C) spi.write32(C)
#else // ESP32 using SPI with 16 bit color display #else // ESP32 using SPI with 16 bit color display
@@ -346,31 +350,31 @@
// Write 8 bits // Write 8 bits
#define tft_Write_8(C) \ #define tft_Write_8(C) \
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 8-1); \ WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 8-1); \
WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C); \ WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C); \
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \
while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
// Write 16 bits with corrected endianess for 16 bit colours // Write 16 bits with corrected endianess for 16 bit colours
#define tft_Write_16(C) \ #define tft_Write_16(C) \
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 16-1); \ WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 16-1); \
WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C<<8 | C>>8); \ WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C<<8 | C>>8); \
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \
while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
// Write 16 bits // Write 16 bits
#define tft_Write_16S(C) \ #define tft_Write_16S(C) \
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 16-1); \ WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 16-1); \
WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C); \ WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C); \
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \
while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
// Write 32 bits // Write 32 bits
#define tft_Write_32(C) \ #define tft_Write_32(C) \
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 32-1); \ WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 32-1); \
WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C); \ WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C); \
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \
while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
#endif #endif
@@ -383,7 +387,7 @@
#define SCLK_H GPOS=sclkpinmask #define SCLK_H GPOS=sclkpinmask
#else #else
// Use a SPI read transfer // Use a SPI read transfer
#define tft_Read_8() SPI.transfer(0) #define tft_Read_8() spi.transfer(0)
#endif #endif
#endif #endif
@@ -650,7 +654,7 @@ class TFT_eSPI : public Print {
width(void); width(void);
// The TFT_eSprite class inherits the following functions // The TFT_eSprite class inherits the following functions
void setWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1), void setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye),
pushColor(uint16_t color), pushColor(uint16_t color),
pushColor(uint16_t color, uint32_t len), pushColor(uint16_t color, uint32_t len),
pushColors(uint16_t *data, uint32_t len, bool swap = true), // With byte swap option pushColors(uint16_t *data, uint32_t len, bool swap = true), // With byte swap option
@@ -776,12 +780,12 @@ class TFT_eSPI : public Print {
fontHeight(int16_t font), fontHeight(int16_t font),
fontHeight(void); fontHeight(void);
void setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); void setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h);
// These 3 functions are used together, for every startWrite() there must be an endWrite() // Compatibility additions (non-essential)
void startWrite(void); // Begin SPI transaction void startWrite(void); // Begin SPI transaction (not normally needed)
void writeColor(uint16_t color, uint32_t len); // Write a colour without transaction overhead void writeColor(uint16_t color, uint32_t len); // Write colours without transaction overhead
void endWrite(void); // End SPI transaction void endWrite(void); // End SPI transaction
size_t write(uint8_t); size_t write(uint8_t);
@@ -816,7 +820,7 @@ class TFT_eSPI : public Print {
inline void spi_begin_read() __attribute__((always_inline)); inline void spi_begin_read() __attribute__((always_inline));
inline void spi_end_read() __attribute__((always_inline)); inline void spi_end_read() __attribute__((always_inline));
void readAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); void readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h);
uint8_t tabcolor, uint8_t tabcolor,
colstart = 0, rowstart = 0; // some ST7735 displays need this changed colstart = 0, rowstart = 0; // some ST7735 displays need this changed

View File

@@ -262,6 +262,10 @@
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: // The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
#define SPI_TOUCH_FREQUENCY 2500000 #define SPI_TOUCH_FREQUENCY 2500000
// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default.
// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam)
// then uncomment the following line:
//#define USE_HSPI_PORT
// Comment out the following #define if "SPI Transactions" do not need to be // Comment out the following #define if "SPI Transactions" do not need to be
// supported. When commented out the code size will be smaller and sketches will // supported. When commented out the code size will be smaller and sketches will

View File

@@ -262,6 +262,10 @@
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: // The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
#define SPI_TOUCH_FREQUENCY 2500000 #define SPI_TOUCH_FREQUENCY 2500000
// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default.
// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam)
// then uncomment the following line to use the HSPI port:
//#define USE_HSPI_PORT
// Comment out the following #define if "SPI Transactions" do not need to be // Comment out the following #define if "SPI Transactions" do not need to be
// supported. When commented out the code size will be smaller and sketches will // supported. When commented out the code size will be smaller and sketches will

View File

@@ -107,13 +107,17 @@ void midline() {
// If the ball is not on the line then don't redraw the line // If the ball is not on the line then don't redraw the line
if ((ball_x<dashline_x-ball_w) && (ball_x > dashline_x+dashline_w)) return; if ((ball_x<dashline_x-ball_w) && (ball_x > dashline_x+dashline_w)) return;
tft.startWrite();
// Quick way to draw a dashed line // Quick way to draw a dashed line
tft.setAddrWindow(dashline_x,0,dashline_x+dashline_w-1,h); tft.setAddrWindow(dashline_x, 0, dashline_w, h);
for(int16_t i = 0; i < dashline_n; i+=2) { for(int16_t i = 0; i < dashline_n; i+=2) {
tft.pushColor(WHITE, dashline_w*dashline_h); // push dash pixels tft.pushColor(WHITE, dashline_w*dashline_h); // push dash pixels
tft.pushColor(BLACK, dashline_w*dashline_h); // push gap pixels tft.pushColor(BLACK, dashline_w*dashline_h); // push gap pixels
} }
tft.endWrite();
} }
void lpaddle() { void lpaddle() {

View File

@@ -308,14 +308,16 @@ uint32_t testHaD()
0x0a, 0x2b, 0x0b, 0x41, 0x0a, 0x29, 0x0b, 0x43, 0x0a, 0x27, 0x0a, 0x46, 0x0a, 0x25, 0x0a, 0x49, 0x0a, 0x2b, 0x0b, 0x41, 0x0a, 0x29, 0x0b, 0x43, 0x0a, 0x27, 0x0a, 0x46, 0x0a, 0x25, 0x0a, 0x49,
0x09, 0x23, 0x08, 0x4e, 0x08, 0x96, 0x12 0x09, 0x23, 0x08, 0x4e, 0x08, 0x96, 0x12
}; };
tft.fillScreen(TFT_BLACK); tft.fillScreen(TFT_BLACK);
uint32_t start = micros_start(); uint32_t start = micros_start();
tft.startWrite();
for (int i = 0; i < 0x10; i++) for (int i = 0; i < 0x10; i++)
{ {
tft.setAddrWindow(0, 0, tft.width()-1, tft.height()-1); tft.setAddrWindow(0, 0, tft.width(), tft.height());
uint16_t cnt = 0; uint16_t cnt = 0;
uint16_t color = tft.color565((i << 4) | i, (i << 4) | i, (i << 4) | i); uint16_t color = tft.color565((i << 4) | i, (i << 4) | i, (i << 4) | i);
@@ -335,6 +337,8 @@ uint32_t testHaD()
} }
} }
tft.endWrite();
uint32_t t = micros() - start; uint32_t t = micros() - start;
tft.setTextColor(TFT_YELLOW); tft.setTextColor(TFT_YELLOW);

View File

@@ -7,7 +7,7 @@
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
#define ILI9341_GREY 0x7BEF #define TFT_GREY 0x7BEF
unsigned long runTime = 0; unsigned long runTime = 0;
@@ -16,8 +16,9 @@ uint16_t x0 = 0, x1 = 0, yy0 = 0, yy1 = 0;
void setup() void setup()
{ {
Serial.begin(250000);
//randomSeed(analogRead(A0)); //randomSeed(analogRead(A0));
Serial.println();
// Setup the LCD // Setup the LCD
tft.init(); tft.init();
tft.setRotation(3); tft.setRotation(3);
@@ -27,7 +28,8 @@ void loop()
{ {
runTime = millis(); runTime = millis();
tft.fillScreen(ILI9341_BLACK); tft.fillScreen(TFT_BLACK);
tft.startWrite();
for (int px = 1; px < 320; px++) for (int px = 1; px < 320; px++)
{ {
for (int py = 0; py < 240; py++) for (int py = 0; py < 240; py++)
@@ -49,6 +51,9 @@ void loop()
yield();tft.drawPixel(px, py, color); yield();tft.drawPixel(px, py, color);
} }
} }
tft.endWrite();
Serial.println(millis()-runTime);
while(1) yield(); while(1) yield();
} }

View File

@@ -108,13 +108,17 @@ void midline() {
// If the ball is not on the line then don't redraw the line // If the ball is not on the line then don't redraw the line
if ((ball_x<dashline_x-ball_w) && (ball_x > dashline_x+dashline_w)) return; if ((ball_x<dashline_x-ball_w) && (ball_x > dashline_x+dashline_w)) return;
tft.startWrite();
// Quick way to draw a dashed line // Quick way to draw a dashed line
tft.setWindow(dashline_x,0,dashline_x+dashline_w-1,h); tft.setAddrWindow(dashline_x, 0, dashline_w, h);
for(int16_t i = 0; i < dashline_n; i+=2) { for(int16_t i = 0; i < dashline_n; i+=2) {
tft.pushColor(WHITE, dashline_w*dashline_h); // push dash pixels tft.pushColor(WHITE, dashline_w*dashline_h); // push dash pixels
tft.pushColor(BLACK, dashline_w*dashline_h); // push gap pixels tft.pushColor(BLACK, dashline_w*dashline_h); // push gap pixels
} }
tft.endWrite();
} }
void lpaddle() { void lpaddle() {

View File

@@ -336,10 +336,10 @@ uint32_t testHaD()
tft.fillScreen(TFT_BLACK); tft.fillScreen(TFT_BLACK);
uint32_t start = micros_start(); uint32_t start = micros_start();
for (int i = 0; i < 0x10; i++) for (int i = 0; i < 0x10; i++)
{ {
tft.setWindow(0, 0, 240-1, 320-1); tft.setAddrWindow(0, 0, 240, 320);
uint16_t cnt = 0; uint16_t cnt = 0;
uint16_t color = tft.color565((i << 4) | i, (i << 4) | i, (i << 4) | i); uint16_t color = tft.color565((i << 4) | i, (i << 4) | i, (i << 4) | i);
@@ -347,6 +347,7 @@ uint32_t testHaD()
const uint8_t *cmp = &HaD_240x320[0]; const uint8_t *cmp = &HaD_240x320[0];
tft.startWrite();
while (cmp < &HaD_240x320[sizeof(HaD_240x320)]) while (cmp < &HaD_240x320[sizeof(HaD_240x320)])
{ {
cnt = pgm_read_byte(cmp++); cnt = pgm_read_byte(cmp++);
@@ -354,6 +355,7 @@ uint32_t testHaD()
tft.pushColor(curcolor, cnt); // PDQ_GFX has count tft.pushColor(curcolor, cnt); // PDQ_GFX has count
curcolor ^= color; curcolor ^= color;
} }
tft.endWrite();
} }
uint32_t t = micros() - start; uint32_t t = micros() - start;

View File

@@ -171,11 +171,14 @@ void renderJPEG(int xpos, int ypos) {
// calculate how many pixels must be drawn // calculate how many pixels must be drawn
uint32_t mcu_pixels = win_w * win_h; uint32_t mcu_pixels = win_w * win_h;
tft.startWrite();
// draw image MCU block only if it will fit on the screen // draw image MCU block only if it will fit on the screen
if (( mcu_x + win_w ) <= tft.width() && ( mcu_y + win_h ) <= tft.height()) if (( mcu_x + win_w ) <= tft.width() && ( mcu_y + win_h ) <= tft.height())
{ {
// Now set a MCU bounding window on the TFT to push pixels into (x, y, x + width - 1, y + height - 1) // Now set a MCU bounding window on the TFT to push pixels into (x, y, x + width - 1, y + height - 1)
tft.setWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1); tft.setAddrWindow(mcu_x, mcu_y, win_w, win_h);
// Write all MCU pixels to the TFT window // Write all MCU pixels to the TFT window
while (mcu_pixels--) { while (mcu_pixels--) {
@@ -185,6 +188,8 @@ void renderJPEG(int xpos, int ypos) {
} }
else if ( (mcu_y + win_h) >= tft.height()) JpegDec.abort(); // Image has run off bottom of screen so abort decoding else if ( (mcu_y + win_h) >= tft.height()) JpegDec.abort(); // Image has run off bottom of screen so abort decoding
tft.endWrite();
} }
// calculate how long it took to draw the image // calculate how long it took to draw the image

View File

@@ -251,8 +251,10 @@ void drawIcon(const unsigned short* icon, int16_t x, int16_t y, int8_t width, in
uint16_t pix_buffer[BUFF_SIZE]; // Pixel buffer (16 bits per pixel) uint16_t pix_buffer[BUFF_SIZE]; // Pixel buffer (16 bits per pixel)
tft.startWrite();
// Set up a window the right size to stream pixels into // Set up a window the right size to stream pixels into
tft.setWindow(x, y, x + width - 1, y + height - 1); tft.setAddrWindow(x, y, width, height);
// Work out the number whole buffers to send // Work out the number whole buffers to send
uint16_t nb = ((uint16_t)height * width) / BUFF_SIZE; uint16_t nb = ((uint16_t)height * width) / BUFF_SIZE;
@@ -273,5 +275,7 @@ void drawIcon(const unsigned short* icon, int16_t x, int16_t y, int8_t width, in
for (int i = 0; i < np; i++) pix_buffer[i] = pgm_read_word(&icon[nb * BUFF_SIZE + i]); for (int i = 0; i < np; i++) pix_buffer[i] = pgm_read_word(&icon[nb * BUFF_SIZE + i]);
tft.pushColors(pix_buffer, np); tft.pushColors(pix_buffer, np);
} }
tft.endWrite();
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "TFT_eSPI", "name": "TFT_eSPI",
"version": "1.3.13", "version": "1.4.0",
"keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "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", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32",
"repository": "repository":

View File

@@ -1,5 +1,5 @@
name=TFT_eSPI name=TFT_eSPI
version=1.3.13 version=1.4.0
author=Bodmer author=Bodmer
maintainer=Bodmer maintainer=Bodmer
sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE