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:
1 parent
419a7ef8de
commit
1cf2305e4d
8 files changed
+1117
-12
No files matched your search
+156
-8
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user