Commit 054a824e authored by Bodmer's avatar Bodmer

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
parent 0fdd2518
......@@ -441,6 +441,8 @@ void TFT_eSPI::drawGlyph(uint16_t code)
int16_t cy = cursor_y + gFont.maxAscent - gdY[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++)
{
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);
cursor_x += gFont.spaceWidth + 1;
}
endWrite();
}
/***************************************************************************************
......
......@@ -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_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
for (int32_t x = min_x; x <= max_x; x++) {
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
}
}
_tft->endWrite();
_tft->endWrite(); // ESP32: end transaction
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 );
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 (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++)
{
......@@ -577,7 +578,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint1
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++)
{
......@@ -613,7 +614,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint1
x = y;
y = _dheight - tx - 1;
}
// Plot a 1bpp image into a 1bpp Sprite
uint8_t* pdata = (uint8_t* ) data;
uint32_t ww = (w+7) & 0xFFF8;
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*/
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 + (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 (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++)
{
......@@ -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++)
{
......@@ -706,7 +711,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const
x = y;
y = _dheight - tx - 1;
}
// Plot a 1bpp image into a 1bpp Sprite
const uint8_t* pdata = (const uint8_t* ) data;
uint32_t ww = (w+7) & 0xFFF8;
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
}
......
......@@ -22,18 +22,32 @@ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){
T_CS_L;
// Start YP sample request for x position
SPI.transfer(0xd0); // Start new YP conversion
tmp = SPI.transfer(0); // Read first 8 bits
// Start YP sample request for x position, read 4 times and keep last sample
spi.transfer(0xd0); // 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
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 |= 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;
// Start XP sample request for y position
tmp = SPI.transfer(0); // Read first 8 bits
// Start XP sample request for y position, read 4 times and keep last sample
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 |= 0x1f & (SPI.transfer(0)>>3); // Read last 8 bits
tmp |= 0x1f & (spi.transfer(0)>>3); // Read last 8 bits
*y = tmp;
......@@ -57,9 +71,9 @@ uint16_t TFT_eSPI::getTouchRawZ(void){
// Calculate Z
int16_t tz = 0xFFF;
SPI.transfer(0xb0); // Start new Z1 conversion
tz += SPI.transfer16(0xc0) >> 3; // Read Z1 and start Z2 conversion
tz -= SPI.transfer16(0x00) >> 3; // Read Z2
spi.transfer(0xb0); // Start new Z1 conversion
tz += spi.transfer16(0xc0) >> 3; // Read Z1 and start Z2 conversion
tz -= spi.transfer16(0x00) >> 3; // Read Z2
T_CS_H;
......
This diff is collapsed.
......@@ -105,7 +105,11 @@
#ifdef ESP32
#include "soc/spi_reg.h"
#define SPI_NUM 0x3
#ifdef USE_HSPI_PORT
#define SPI_PORT HSPI
#else
#define SPI_PORT VSPI
#endif
#endif
#ifdef SMOOTH_FONT
......@@ -312,32 +316,32 @@
#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)
#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_16S(C) SPI.write16(C<<8 | C>>8)
#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)
#elif defined ESP8266
#define tft_Write_8(C) SPI.write(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
......@@ -346,31 +350,31 @@
// 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_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 8-1); \
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C); \
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&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_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 16-1); \
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C<<8 | C>>8); \
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
// Write 16 bits
#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_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 16-1); \
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C); \
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&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);
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 32-1); \
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C); \
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
#endif
......@@ -383,7 +387,7 @@
#define SCLK_H GPOS=sclkpinmask
#else
// Use a SPI read transfer
#define tft_Read_8() SPI.transfer(0)
#define tft_Read_8() spi.transfer(0)
#endif
#endif
......@@ -650,7 +654,7 @@ class TFT_eSPI : public Print {
width(void);
// 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, uint32_t len),
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(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()
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
// Compatibility additions (non-essential)
void startWrite(void); // Begin SPI transaction (not normally needed)
void writeColor(uint16_t color, uint32_t len); // Write colours without transaction overhead
void endWrite(void); // End SPI transaction
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_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,
colstart = 0, rowstart = 0; // some ST7735 displays need this changed
......
......@@ -262,6 +262,10 @@
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
#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
// supported. When commented out the code size will be smaller and sketches will
......
......@@ -262,6 +262,10 @@
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
#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
// supported. When commented out the code size will be smaller and sketches will
......
......@@ -107,13 +107,17 @@ void midline() {
// 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;
tft.startWrite();
// 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) {
tft.pushColor(WHITE, dashline_w*dashline_h); // push dash pixels
tft.pushColor(BLACK, dashline_w*dashline_h); // push gap pixels
}
tft.endWrite();
}
void lpaddle() {
......
......@@ -308,14 +308,16 @@ uint32_t testHaD()
0x0a, 0x2b, 0x0b, 0x41, 0x0a, 0x29, 0x0b, 0x43, 0x0a, 0x27, 0x0a, 0x46, 0x0a, 0x25, 0x0a, 0x49,
0x09, 0x23, 0x08, 0x4e, 0x08, 0x96, 0x12
};
tft.fillScreen(TFT_BLACK);
uint32_t start = micros_start();
tft.startWrite();
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 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;
tft.setTextColor(TFT_YELLOW);
......
......@@ -7,7 +7,7 @@
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
#define ILI9341_GREY 0x7BEF
#define TFT_GREY 0x7BEF
unsigned long runTime = 0;
......@@ -16,8 +16,9 @@ uint16_t x0 = 0, x1 = 0, yy0 = 0, yy1 = 0;
void setup()
{
Serial.begin(250000);
//randomSeed(analogRead(A0));
Serial.println();
// Setup the LCD
tft.init();
tft.setRotation(3);
......@@ -27,7 +28,8 @@ void loop()
{
runTime = millis();
tft.fillScreen(ILI9341_BLACK);
tft.fillScreen(TFT_BLACK);
tft.startWrite();
for (int px = 1; px < 320; px++)
{
for (int py = 0; py < 240; py++)
......@@ -49,6 +51,9 @@ void loop()
yield();tft.drawPixel(px, py, color);
}
}
tft.endWrite();
Serial.println(millis()-runTime);
while(1) yield();
}
......
......@@ -108,13 +108,17 @@ void midline() {
// 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;
tft.startWrite();
// 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) {
tft.pushColor(WHITE, dashline_w*dashline_h); // push dash pixels
tft.pushColor(BLACK, dashline_w*dashline_h); // push gap pixels
}
tft.endWrite();
}
void lpaddle() {
......
......@@ -336,10 +336,10 @@ uint32_t testHaD()
tft.fillScreen(TFT_BLACK);
uint32_t start = micros_start();
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 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];
tft.startWrite();
while (cmp < &HaD_240x320[sizeof(HaD_240x320)])
{
cnt = pgm_read_byte(cmp++);
......@@ -354,6 +355,7 @@ uint32_t testHaD()
tft.pushColor(curcolor, cnt); // PDQ_GFX has count
curcolor ^= color;
}
tft.endWrite();
}
uint32_t t = micros() - start;
......
......@@ -171,11 +171,14 @@ void renderJPEG(int xpos, int ypos) {
// calculate how many pixels must be drawn
uint32_t mcu_pixels = win_w * win_h;
tft.startWrite();
// 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())
{
// 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
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
tft.endWrite();
}
// calculate how long it took to draw the image
......
......@@ -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)
tft.startWrite();
// 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
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]);
tft.pushColors(pix_buffer, np);
}
tft.endWrite();
}
{
"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",
"description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32",
"repository":
......
name=TFT_eSPI
version=1.3.13
version=1.4.0
author=Bodmer
maintainer=Bodmer
sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment