Add capability to read TFT SDA bi-directional pin

Tested on an ESP32 with ST7789V display
SDA read is very slow on an ESP8266 (to be investigated)
Added new setup #define TFT_SDA_READ
Add new ESP32 and ESP8266 compatible in example/Generic folder to test
capture of TFT screen
This commit is contained in:
Bodmer committed 2018-11-23 03:09:07 +00:00
1 parent 419a7ef8de
commit 1cf2305e4d
8 files changed
+1117 -12

No files matched your search

+156 -8
View File
@@ -253,6 +253,10 @@ void TFT_eSPI::init(uint8_t tc)
wrpinmask = (uint32_t) digitalPinToBitMask(TFT_WR);
#endif
#ifdef TFT_SCLK
sclkpinmask = (uint32_t) digitalPinToBitMask(TFT_SCLK);
#endif
#ifdef TFT_SPI_OVERLAP
// 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);
@@ -620,35 +624,68 @@ 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
#endif
// Dummy read to throw away don't care value
tft_Write_8(0);
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
#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);
#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;
#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
#endif
#ifdef ST7789_DRIVER
writecommand(ST7789_COLMOD);
writedata(0x55);
#endif
#else
spi_end_read();
#endif
return color565(r, g, b);
#endif
}
/***************************************************************************************
** Function name: read byte - supports class functions
** Description: Read a byte from ESP32 8 bit data port
@@ -756,10 +793,24 @@ 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
#endif
// Dummy read to throw away don't care value
tft_Write_8(0);
tft_Read_8(0);
// Read window pixel 24 bit RGB values
uint32_t len = w * h;
@@ -768,15 +819,19 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t
// Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte
// as the TFT stores colours as 18 bits
#if !defined (ILI9488_DRIVER)
uint8_t r = tft_Read_8(0);
uint8_t g = tft_Read_8(0);
uint8_t b = tft_Read_8(0);
#else
// The 6 colour bits are in LS 6 bits of each byte but we do not include the extra clock pulse
// so we use a trick and mask the middle 6 bits of the byte, then only shift 1 place left
uint8_t r = (tft_Read_8(0)&0x7E)<<1;
uint8_t g = (tft_Read_8(0)&0x7E)<<1;
uint8_t b = (tft_Read_8(0)&0x7E)<<1;
#endif
// Swapped colour byte order for compatibility with pushRect()
@@ -785,10 +840,64 @@ 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
#endif
#ifdef ST7789_DRIVER
writecommand(ST7789_COLMOD);
writedata(0x55);
#endif
#else
spi_end_read();
#endif
#endif
}
/***************************************************************************************
** 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)
{
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
}
return ret;
}
#endif
/***************************************************************************************
** Function name: push rectangle (for SPI Interface II i.e. IM [3:0] = "1101")
@@ -1337,39 +1446,78 @@ bool TFT_eSPI::getSwapBytes(void)
// If w and h are 1, then 1 pixel is read, *data array size must be 3 bytes per pixel
void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data)
{
#if !defined(ESP32_PARALLEL)
#if defined(ESP32_PARALLEL)
// ESP32 parallel bus supported yet
#else // Not ESP32_PARALLEL
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
#endif
// Dummy read to throw away don't care value
tft_Write_8(0);
tft_Read_8(0);
// 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
// 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);
#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;
#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
#endif
#ifdef ST7789_DRIVER
writecommand(ST7789_COLMOD);
writedata(0x55);
#endif
#else
spi_end_read();
#endif
#endif
}