mirror of
https://github.com/Bodmer/TFT_eSPI.git
synced 2025-08-03 20:54:42 +02:00
Re-work the support for bi-directional SDA line
Tested on ESP32 and ST7789V display only. It may not work with other displays! Use: #define TFT_SDA_READ in setup file to use bi-directional SDA pin support.
This commit is contained in:
@@ -26,11 +26,11 @@ The Button class from Adafruit_GFX is incorporated, with the enhancement that th
|
||||
|
||||
The library supports SPI overlap on the ESP8266 so the TFT screen can share MOSI, MISO and SCLK pins with the program FLASH, this frees up GPIO pins for other uses.
|
||||
|
||||
The library contains proportional fonts, different sizes can be enabled/disabled at compile time to optimise the use of FLASH memory. Anti-alased (smooth) font files in vlw format stored in SPIFFS are supported and in the case any 16 bit Unicode character can be included and rendered, this means many language specific characters can be rendered to the screen.
|
||||
The library contains proportional fonts, different sizes can be enabled/disabled at compile time to optimise the use of FLASH memory. Anti-alased (smooth) font files in vlw format stored in SPIFFS are supported. Any 16 bit Unicode character can be included and rendered, this means many language specific characters can be rendered to the screen.
|
||||
|
||||
The library is based on the Adafruit GFX and Adafruit driver libraries and the aim is to retain compatibility. Significant additions have been made to the library to boost the speed for ESP8266/ESP32 processors (it is typically 3 to 10 times faster) and to add new features. The new graphics functions include different size proportional fonts and formatting features. There are lots of example sketches to demonstrate the different features and included functions.
|
||||
|
||||
Configuration of the library font selections, pins used to interface with the TFT and other features is made by editting the User_Setup.h file in the library folder, or by selecting a configuration in the library "User_Setup_Selet,h" file. Fonts and features can easily be disabled by commenting out lines.
|
||||
Configuration of the library font selections, pins used to interface with the TFT and other features is made by editting the User_Setup.h file in the library folder, or by selecting your own configuration in the "User_Setup_Selet,h" file. Fonts and features can easily be enabled/disabled by commenting out lines.
|
||||
|
||||
|
||||
# Anti-aliased Fonts
|
||||
|
220
TFT_eSPI.cpp
220
TFT_eSPI.cpp
@@ -534,7 +534,7 @@ uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index)
|
||||
CS_L;
|
||||
tft_Write_8(cmd_function);
|
||||
DC_D;
|
||||
reg = tft_Read_8(0);
|
||||
reg = tft_Read_8();
|
||||
CS_H;
|
||||
|
||||
spi_end_read();
|
||||
@@ -624,62 +624,40 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
|
||||
|
||||
spi_begin_read();
|
||||
|
||||
#ifdef ST7789_DRIVER
|
||||
writecommand(ST7789_COLMOD); // Switch from 16 bit colour to 18 bit (required)
|
||||
writedata(0x66);
|
||||
#endif
|
||||
|
||||
readAddrWindow(x0, y0, x0, y0); // Sets CS low
|
||||
|
||||
#ifdef TFT_SDA_READ
|
||||
// To be investigated: spi_end_read() is VERY slow on the ESP8266 here
|
||||
spi_end_read(); // Releasing the HAL mutex is mandatory for the ESP32
|
||||
SPI.end(); // Disconnect the SPI peripheral to release the pins
|
||||
digitalWrite(TFT_SCLK, HIGH); // Set clock pin high
|
||||
pinMode(TFT_SCLK, OUTPUT); // Set the SCLK pin to output
|
||||
pinMode(TFT_MOSI, INPUT_PULLUP); // Set the MOSI pin to input
|
||||
begin_SDA_Read();
|
||||
#endif
|
||||
|
||||
// Dummy read to throw away don't care value
|
||||
tft_Read_8(0);
|
||||
tft_Read_8();
|
||||
|
||||
#if !defined (ILI9488_DRIVER)
|
||||
|
||||
// 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_Read_8(0);
|
||||
uint8_t g = tft_Read_8(0);
|
||||
uint8_t b = tft_Read_8(0);
|
||||
uint8_t r = tft_Read_8();
|
||||
uint8_t g = tft_Read_8();
|
||||
uint8_t b = tft_Read_8();
|
||||
|
||||
#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_Read_8(0)&0x7E)<<1;
|
||||
uint8_t g = (tft_Read_8(0)&0x7E)<<1;
|
||||
uint8_t b = (tft_Read_8(0)&0x7E)<<1;
|
||||
uint8_t r = (tft_Read_8()&0x7E)<<1;
|
||||
uint8_t g = (tft_Read_8()&0x7E)<<1;
|
||||
uint8_t b = (tft_Read_8()&0x7E)<<1;
|
||||
|
||||
#endif
|
||||
|
||||
CS_H;
|
||||
|
||||
#ifdef TFT_SDA_READ
|
||||
#ifdef ESP32
|
||||
SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1);
|
||||
#else
|
||||
#ifdef TFT_SPI_OVERLAP
|
||||
SPI.pins(6, 7, 8, 0);
|
||||
#else
|
||||
SPI.begin();
|
||||
#endif
|
||||
#ifdef TFT_SDA_READ
|
||||
end_SDA_Read();
|
||||
#endif
|
||||
#ifdef ST7789_DRIVER
|
||||
writecommand(ST7789_COLMOD);
|
||||
writedata(0x55);
|
||||
#endif
|
||||
#else
|
||||
|
||||
spi_end_read();
|
||||
#endif
|
||||
|
||||
return color565(r, g, b);
|
||||
|
||||
@@ -793,44 +771,34 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t
|
||||
|
||||
spi_begin_read();
|
||||
|
||||
#ifdef ST7789_DRIVER
|
||||
writecommand(ST7789_COLMOD); // Switch from 16 bit colour to 18 bit (required)
|
||||
writedata(0x66);
|
||||
#endif
|
||||
|
||||
readAddrWindow(x, y, x + w - 1, y + h - 1); // Sets CS low
|
||||
|
||||
#ifdef TFT_SDA_READ
|
||||
// To be investigated: spi_end_read() is VERY slow on the ESP8266 here
|
||||
spi_end_read(); // Releasing the HAL mutex is mandatory for the ESP32
|
||||
SPI.end(); // Disconnect the SPI peripheral to release the pins
|
||||
digitalWrite(TFT_SCLK, HIGH); // Set clock pin high
|
||||
pinMode(TFT_SCLK, OUTPUT); // Set the SCLK pin to output
|
||||
pinMode(TFT_MOSI, INPUT_PULLUP); // Set the MOSI pin to input
|
||||
begin_SDA_Read();
|
||||
#endif
|
||||
|
||||
// Dummy read to throw away don't care value
|
||||
tft_Read_8(0);
|
||||
tft_Read_8();
|
||||
|
||||
// Read window pixel 24 bit RGB values
|
||||
uint32_t len = w * h;
|
||||
while (len--) {
|
||||
|
||||
// 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_Read_8(0);
|
||||
uint8_t g = tft_Read_8(0);
|
||||
uint8_t b = tft_Read_8(0);
|
||||
// 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
|
||||
uint8_t r = tft_Read_8();
|
||||
uint8_t g = tft_Read_8();
|
||||
uint8_t b = tft_Read_8();
|
||||
|
||||
#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_Read_8(0)&0x7E)<<1;
|
||||
uint8_t g = (tft_Read_8(0)&0x7E)<<1;
|
||||
uint8_t b = (tft_Read_8(0)&0x7E)<<1;
|
||||
uint8_t r = (tft_Read_8()&0x7E)<<1;
|
||||
uint8_t g = (tft_Read_8()&0x7E)<<1;
|
||||
uint8_t b = (tft_Read_8()&0x7E)<<1;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -840,23 +808,11 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t
|
||||
|
||||
CS_H;
|
||||
|
||||
#ifdef TFT_SDA_READ
|
||||
#ifdef ESP32
|
||||
SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1);
|
||||
#else
|
||||
#ifdef TFT_SPI_OVERLAP
|
||||
SPI.pins(6, 7, 8, 0);
|
||||
#else
|
||||
SPI.begin();
|
||||
#endif
|
||||
#ifdef TFT_SDA_READ
|
||||
end_SDA_Read();
|
||||
#endif
|
||||
#ifdef ST7789_DRIVER
|
||||
writecommand(ST7789_COLMOD);
|
||||
writedata(0x55);
|
||||
#endif
|
||||
#else
|
||||
|
||||
spi_end_read();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -865,40 +821,66 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t
|
||||
** Function name: tft_Read_8
|
||||
** Description: Software SPI to read bidirectional SDA line
|
||||
***************************************************************************************/
|
||||
// For the ST7789 the tft_Read_8() macro is replaced by a function
|
||||
#ifdef TFT_SDA_READ
|
||||
#ifdef ESP32
|
||||
#define SCLK_L GPIO.out_w1tc = (1 << TFT_SCLK)
|
||||
#define SCLK_H GPIO.out_w1ts = (1 << TFT_SCLK)
|
||||
#else // ESP8266
|
||||
#define SCLK_L GPOC=sclkpinmask
|
||||
#define SCLK_H GPOS=sclkpinmask
|
||||
#endif
|
||||
uint8_t TFT_eSPI::tft_Read_8(uint8_t dummy)
|
||||
#if defined (ESP8266) && defined (TFT_SDA_READ)
|
||||
uint8_t TFT_eSPI::tft_Read_8(void)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
uint32_t reg = 0;
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) { // read results
|
||||
ret <<= 1;
|
||||
#ifdef ESP32 // bit bangs at around 1MHz
|
||||
SCLK_L;
|
||||
//SCLK_L;
|
||||
reg = gpio_input_get(); // SDA must connect to ESP32 pin in range 0-31
|
||||
SCLK_H;
|
||||
if (reg&(1<<TFT_MOSI)) ret |= 1;
|
||||
SCLK_H; // Extra delay - must read slowly on an ST7789 to avoid bad data
|
||||
#else
|
||||
SCLK_L;
|
||||
if (digitalRead(TFT_MOSI)) ret |= 1;
|
||||
SCLK_H;
|
||||
#endif
|
||||
SCLK_L;
|
||||
if (digitalRead(TFT_MOSI)) ret |= 1;
|
||||
SCLK_H;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: beginSDA
|
||||
** Description: Detach SPI from pin to permit software SPI
|
||||
***************************************************************************************/
|
||||
#ifdef TFT_SDA_READ
|
||||
void TFT_eSPI::begin_SDA_Read(void)
|
||||
{
|
||||
#ifdef ESP32
|
||||
pinMatrixOutDetach(TFT_MOSI, false, false);
|
||||
pinMode(TFT_MOSI, INPUT);
|
||||
pinMatrixInAttach(TFT_MOSI, VSPIQ_IN_IDX, false);
|
||||
#else // ESP8266
|
||||
#ifdef TFT_SPI_OVERLAP
|
||||
// Reads in overlap mode not supported
|
||||
#else
|
||||
SPI.end();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: endSDA
|
||||
** Description: Attach SPI pins after software SPI
|
||||
***************************************************************************************/
|
||||
#ifdef TFT_SDA_READ
|
||||
void TFT_eSPI::end_SDA_Read(void)
|
||||
{
|
||||
#ifdef ESP32
|
||||
pinMode(TFT_MOSI, OUTPUT);
|
||||
pinMatrixOutAttach(TFT_MOSI, VSPID_OUT_IDX, false, false);
|
||||
pinMode(TFT_MISO, INPUT);
|
||||
pinMatrixInAttach(TFT_MISO, VSPIQ_IN_IDX, false);
|
||||
#else
|
||||
#ifdef TFT_SPI_OVERLAP
|
||||
SPI.pins(6, 7, 8, 0);
|
||||
#else
|
||||
SPI.begin();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: push rectangle (for SPI Interface II i.e. IM [3:0] = "1101")
|
||||
** Description: push 565 pixel colours into a defined area
|
||||
@@ -1454,44 +1436,34 @@ void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_
|
||||
|
||||
spi_begin_read();
|
||||
|
||||
#ifdef ST7789_DRIVER
|
||||
writecommand(ST7789_COLMOD); // Switch from 16 bit colour to 18 bit (required)
|
||||
writedata(0x66);
|
||||
#endif
|
||||
|
||||
readAddrWindow(x0, y0, x0 + w - 1, y0 + h - 1); // Sets CS low
|
||||
|
||||
#ifdef TFT_SDA_READ
|
||||
// To be investigated: spi_end_read() is VERY slow on the ESP8266 here
|
||||
spi_end_read(); // Releasing the HAL mutex is mandatory for the ESP32
|
||||
SPI.end(); // Disconnect the SPI peripheral to release the pins
|
||||
digitalWrite(TFT_SCLK, HIGH); // Set clock pin high
|
||||
pinMode(TFT_SCLK, OUTPUT); // Set the SCLK pin to output
|
||||
pinMode(TFT_MOSI, INPUT_PULLUP); // Set the MOSI pin to input
|
||||
begin_SDA_Read();
|
||||
#endif
|
||||
|
||||
// Dummy read to throw away don't care value
|
||||
tft_Read_8(0);
|
||||
|
||||
tft_Read_8();
|
||||
|
||||
// Read window pixel 24 bit RGB values, buffer must be set in sketch to 3 * w * h
|
||||
uint32_t len = w * h;
|
||||
while (len--) {
|
||||
|
||||
// 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_Read_8(0);
|
||||
*data++ = tft_Read_8(0);
|
||||
*data++ = tft_Read_8(0);
|
||||
// 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
|
||||
*data++ = tft_Read_8();
|
||||
*data++ = tft_Read_8();
|
||||
*data++ = tft_Read_8();
|
||||
|
||||
#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_Read_8(0)&0x7E)<<1;
|
||||
*data++ = (tft_Read_8(0)&0x7E)<<1;
|
||||
*data++ = (tft_Read_8(0)&0x7E)<<1;
|
||||
*data++ = (tft_Read_8()&0x7E)<<1;
|
||||
*data++ = (tft_Read_8()&0x7E)<<1;
|
||||
*data++ = (tft_Read_8()&0x7E)<<1;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1499,23 +1471,11 @@ void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_
|
||||
|
||||
CS_H;
|
||||
|
||||
#ifdef TFT_SDA_READ
|
||||
#ifdef ESP32
|
||||
SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1);
|
||||
#else
|
||||
#ifdef TFT_SPI_OVERLAP
|
||||
SPI.pins(6, 7, 8, 0);
|
||||
#else
|
||||
SPI.begin();
|
||||
#endif
|
||||
#ifdef TFT_SDA_READ
|
||||
end_SDA_Read();
|
||||
#endif
|
||||
#ifdef ST7789_DRIVER
|
||||
writecommand(ST7789_COLMOD);
|
||||
writedata(0x55);
|
||||
#endif
|
||||
#else
|
||||
|
||||
spi_end_read();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -2966,7 +2926,6 @@ void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
|
||||
|
||||
tft_Write_8(TFT_CASET);
|
||||
|
||||
|
||||
DC_D;
|
||||
|
||||
tft_Write_32(SPI_32(x0, x1));
|
||||
@@ -2981,6 +2940,7 @@ void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
|
||||
tft_Write_32(SPI_32(y0, y1));
|
||||
|
||||
DC_C;
|
||||
|
||||
tft_Write_8(TFT_RAMRD); // Read CGRAM command
|
||||
|
||||
DC_D;
|
||||
|
23
TFT_eSPI.h
23
TFT_eSPI.h
@@ -341,13 +341,16 @@
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined (ESP32_PARALLEL) && !defined (TFT_SDA_READ)
|
||||
// Support SPI TFT reads using MISO line (not all displays support this)
|
||||
#define tft_Read_8(C) SPI.transfer(C)
|
||||
#else
|
||||
// For reading from a TFT with single SDA data in/out pin
|
||||
// Uses a function in the .cpp file to read a bidirectional SDA line, the
|
||||
// tft_Read_8() function will bit bang SCLK and use MOSI as an input
|
||||
#if !defined (ESP32_PARALLEL)
|
||||
// Read from display using SPI or software SPI
|
||||
#if defined (ESP8266) && defined (TFT_SDA_READ)
|
||||
// Use a bit banged function call for ESP8266 and bi-directional SDA pin
|
||||
#define SCLK_L GPOC=sclkpinmask
|
||||
#define SCLK_H GPOS=sclkpinmask
|
||||
#else
|
||||
// Use a SPI read transfer
|
||||
#define tft_Read_8() SPI.transfer(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -746,7 +749,11 @@ class TFT_eSPI : public Print {
|
||||
size_t write(uint8_t);
|
||||
|
||||
#ifdef TFT_SDA_READ
|
||||
uint8_t tft_Read_8(uint8_t dummy);
|
||||
#if defined (ESP8266) && defined (TFT_SDA_READ)
|
||||
uint8_t tft_Read_8(void);
|
||||
#endif
|
||||
void begin_SDA_Read(void);
|
||||
void end_SDA_Read(void);
|
||||
#endif
|
||||
|
||||
void getSetup(setup_t& tft_settings); // Sketch provides the instance to populate
|
||||
|
@@ -26,6 +26,11 @@
|
||||
//#define ILI9488_DRIVER
|
||||
//#define ST7789_DRIVER // Define the screen size below for this display
|
||||
|
||||
// Some displays support SPI reads via the MISO pin, if the display has a single
|
||||
// bi-directional SDA pin the library will try to use bit banging to read the line
|
||||
// To use the SDA line for reading data from the TFT uncomment the following line:
|
||||
// #define TFT_SDA_READ
|
||||
|
||||
// For ST7789 ONLY, define the colour order if the blue and red are swapped on your display
|
||||
// Try ONE option at a time to find the correct colour order for your display
|
||||
//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue
|
||||
|
Reference in New Issue
Block a user