mirror of
https://github.com/Bodmer/TFT_eSPI.git
synced 2025-08-09 23:54:43 +02:00
Improve RPi Pico (RP2040) rendering performance
This commit is contained in:
@@ -220,22 +220,10 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
|
||||
** Description: Write a block of pixels of the same colour
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){
|
||||
|
||||
bool loaded = false;
|
||||
uint16_t colorBuf[64];
|
||||
const uint16_t* colorPtr = colorBuf;
|
||||
if (len>63) {
|
||||
loaded = true;
|
||||
for (uint32_t i = 0; i < 64; i++) colorBuf[i] = color;
|
||||
while(len>63) {
|
||||
spi_write16_blocking(spi0, (const uint16_t*)colorPtr, 64);
|
||||
len -=64;
|
||||
}
|
||||
}
|
||||
|
||||
if (len) {
|
||||
if (!loaded) for (uint32_t i = 0; i < len; i++) colorBuf[i] = color;
|
||||
spi_write16_blocking(spi0, (const uint16_t*)colorPtr, len);
|
||||
while(len--)
|
||||
{
|
||||
while (!spi_is_writable(spi0)){};
|
||||
spi_get_hw(spi0)->dr = (uint32_t)color;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,14 +232,23 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){
|
||||
** Description: Write a sequence of pixels
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
|
||||
|
||||
uint16_t *data = (uint16_t*)data_in;
|
||||
if (_swapBytes) {
|
||||
spi_write16_blocking(spi0, (const uint16_t*)data_in, len);
|
||||
while(len--)
|
||||
{
|
||||
while (!spi_is_writable(spi0)){};
|
||||
spi_get_hw(spi0)->dr = (uint32_t)(*data++);
|
||||
}
|
||||
}
|
||||
else {
|
||||
spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
|
||||
spi_write_blocking(spi0, (const uint8_t*)data_in, len * 2);
|
||||
spi_set_format(spi0, 16, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
|
||||
else
|
||||
{
|
||||
while(len--)
|
||||
{
|
||||
uint16_t color = *data++;
|
||||
color = color >> 8 | color << 8;
|
||||
while (!spi_is_writable(spi0)){};
|
||||
spi_get_hw(spi0)->dr = (uint32_t)color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -14,13 +14,17 @@
|
||||
// Include processor specific header
|
||||
// None
|
||||
|
||||
// Processor specific code used by SPI bus transaction startWrite and endWrite functions
|
||||
#define SET_BUS_WRITE_MODE // Not used
|
||||
#define SET_BUS_READ_MODE // Not used
|
||||
// Processor specific code used by SPI bus transaction begin/end_tft_write functions
|
||||
#define SET_BUS_WRITE_MODE spi_set_format(spi0, 16, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST)
|
||||
#define SET_BUS_READ_MODE // spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST)
|
||||
|
||||
// Code to check if SPI or DMA is busy, used by SPI bus transaction startWrite and/or endWrite functions
|
||||
#define DMA_BUSY_CHECK // Not used so leave blank
|
||||
#define SPI_BUSY_CHECK // Not used so leave blank
|
||||
|
||||
// Wait for tx to end, flush rx FIFO, clear rx overrun
|
||||
#define SPI_BUSY_CHECK while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {}; \
|
||||
while (spi_is_readable(spi0)) (void)spi_get_hw(spi0)->dr; \
|
||||
spi_get_hw(spi0)->icr = SPI_SSPICR_RORIC_BITS
|
||||
|
||||
// To be safe, SUPPORT_TRANSACTIONS is assumed mandatory
|
||||
#if !defined (SUPPORT_TRANSACTIONS)
|
||||
@@ -28,7 +32,7 @@
|
||||
#endif
|
||||
|
||||
// Initialise processor specific SPI functions, used by init()
|
||||
#define INIT_TFT_DATA_BUS
|
||||
#define INIT_TFT_DATA_BUS // Not used
|
||||
|
||||
// If smooth fonts are enabled the filing system may need to be loaded
|
||||
#ifdef SMOOTH_FONT
|
||||
@@ -150,18 +154,27 @@
|
||||
spi.transfer(0); spi.transfer((C)>>0)
|
||||
|
||||
#else
|
||||
#define tft_Write_8(C) spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST); \
|
||||
_Cbuf = (C); spi_write_blocking(spi0, (const uint8_t*)&(_Cbuf), 1); \
|
||||
spi_set_format(spi0, 16, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST)
|
||||
#define tft_Write_16(C) _Cbuf = (C); spi_write16_blocking(spi0, (const uint16_t*)&(_Cbuf), 1)
|
||||
#define tft_Write_16N(C) _Cbuf = (C); spi_write16_blocking(spi0, (const uint16_t*)&(_Cbuf), 1)
|
||||
#define tft_Write_16S(C) _Cbuf = (C)<<8 | (C)>>8; spi_write16_blocking(spi0, (const uint16_t*)&(_Cbuf), 1)
|
||||
|
||||
#define tft_Write_32(C) _Cbuf = (C); spi_write16_blocking(spi0, (const uint16_t*)&(_Cbuf), 2)
|
||||
// This swaps to 8 bit mode, then back to 16 bit mode
|
||||
#define tft_Write_8(C) while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {}; \
|
||||
spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST); \
|
||||
spi_get_hw(spi0)->dr = (uint32_t)(C); \
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {}; \
|
||||
spi_set_format(spi0, 16, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST)
|
||||
|
||||
#define tft_Write_32C(C,D) _Cbuf = (C) | (D) << 16; spi_write16_blocking(spi0, (const uint16_t*)&(_Cbuf), 2)
|
||||
// Note: the following macros do not wait for the end of transmission
|
||||
|
||||
#define tft_Write_32D(C) _Cbuf = (C) | (C) << 16; spi_write16_blocking(spi0, (const uint16_t*)&(_Cbuf), 2)
|
||||
#define tft_Write_16(C) while (!spi_is_writable(spi0)){}; spi_get_hw(spi0)->dr = (uint32_t)(C)
|
||||
|
||||
#define tft_Write_16N(C) while (!spi_is_writable(spi0)){}; spi_get_hw(spi0)->dr = (uint32_t)(C)
|
||||
|
||||
#define tft_Write_16S(C) while (!spi_is_writable(spi0)){}; spi_get_hw(spi0)->dr = (uint32_t)(C)<<8 | (C)>>8
|
||||
|
||||
#define tft_Write_32(C) while (!spi_is_writable(spi0)){}; spi_get_hw(spi0)->dr = (uint32_t)((C)>>8);spi_get_hw(spi0)->dr = (uint32_t)(C)
|
||||
|
||||
#define tft_Write_32C(C,D) while (!spi_is_writable(spi0)){}; spi_get_hw(spi0)->dr = (uint32_t)(C);spi_get_hw(spi0)->dr = (uint32_t)(D)
|
||||
|
||||
#define tft_Write_32D(C) while (!spi_is_writable(spi0)){}; spi_get_hw(spi0)->dr = (uint32_t)(C);spi_get_hw(spi0)->dr = (uint32_t)(C)
|
||||
|
||||
#endif // RPI_DISPLAY_TYPE
|
||||
#endif
|
||||
|
262
TFT_eSPI.cpp
262
TFT_eSPI.cpp
@@ -2,7 +2,7 @@
|
||||
Arduino TFT graphics library targeted at 32 bit
|
||||
processors such as ESP32, ESP8266 and STM32.
|
||||
|
||||
This is a standalone library that contains the
|
||||
This is a stand-alone library that contains the
|
||||
hardware driver, the graphics functions and the
|
||||
proportional fonts.
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "Processors/TFT_eSPI_ESP8266.c"
|
||||
#elif defined (STM32) // (_VARIANT_ARDUINO_STM32_) stm32_def.h
|
||||
#include "Processors/TFT_eSPI_STM32.c"
|
||||
#elif defined (RP2040) // Raspberry Pi Pico
|
||||
#elif defined (ARDUINO_ARCH_RP2040) // Raspberry Pi Pico
|
||||
#include "Processors/TFT_eSPI_RP2040.c"
|
||||
#else
|
||||
#include "Processors/TFT_eSPI_Generic.c"
|
||||
@@ -56,10 +56,10 @@
|
||||
inline void TFT_eSPI::begin_tft_write(void){
|
||||
#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT)
|
||||
if (locked) {
|
||||
locked = false;
|
||||
spi.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE));
|
||||
locked = false; // Flag to show SPI access now unlocked
|
||||
spi.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE)); // RP2040 SDK -> 68us delay!
|
||||
CS_L;
|
||||
SET_BUS_WRITE_MODE;
|
||||
SET_BUS_WRITE_MODE; // Some processors (e.g. ESP32) allow recycling the tx buffer when rx is not used
|
||||
}
|
||||
#else
|
||||
CS_L;
|
||||
@@ -74,16 +74,17 @@ inline void TFT_eSPI::begin_tft_write(void){
|
||||
***************************************************************************************/
|
||||
inline void TFT_eSPI::end_tft_write(void){
|
||||
#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT)
|
||||
if(!inTransaction) {
|
||||
if (!locked) {
|
||||
locked = true;
|
||||
if(!inTransaction) { // Flag to stop ending tranaction during multiple graphics calls
|
||||
if (!locked) { // Locked when beginTransaction has been called
|
||||
locked = true; // Flag to show SPI access now locked
|
||||
SPI_BUSY_CHECK; // Check send complete and clean out unused rx data
|
||||
CS_H;
|
||||
spi.endTransaction();
|
||||
spi.endTransaction(); // RP2040 SDK -> 0.7us delay
|
||||
}
|
||||
SET_BUS_READ_MODE;
|
||||
SET_BUS_READ_MODE; // In case SPI has been configured for tx only
|
||||
}
|
||||
#else
|
||||
if(!inTransaction) {CS_H; SET_BUS_READ_MODE;}
|
||||
if(!inTransaction) {SPI_BUSY_CHECK; CS_H; SET_BUS_READ_MODE;}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -435,12 +436,13 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h)
|
||||
|
||||
_swapBytes = false; // Do not swap colour bytes by default
|
||||
|
||||
locked = true; // Transaction mutex lock flags
|
||||
inTransaction = false;
|
||||
locked = true; // Transaction mutex lock flag to ensure begin/endTranaction pairing
|
||||
inTransaction = false; // Flag to prevent multiple sequential functions to keep bus access open
|
||||
lockTransaction = false; // start/endWrite lock flag to allow sketch to keep SPI bus access open
|
||||
|
||||
_booted = true; // Default attributes
|
||||
_cp437 = true;
|
||||
_utf8 = true;
|
||||
_cp437 = true; // Legacy GLCD font bug fix
|
||||
_utf8 = true; // UTF8 decoding enabled
|
||||
|
||||
#ifdef FONT_FS_AVAILABLE
|
||||
fs_font = true; // Smooth font filing system or array (fs_font = false) flag
|
||||
@@ -452,17 +454,19 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h)
|
||||
#endif
|
||||
_psram_enable = false;
|
||||
|
||||
addr_row = 0xFFFF;
|
||||
addr_col = 0xFFFF;
|
||||
addr_row = 0xFFFF; // drawPixel command length optimiser
|
||||
addr_col = 0xFFFF; // drawPixel command length optimiser
|
||||
|
||||
_xPivot = 0;
|
||||
_yPivot = 0;
|
||||
|
||||
// Legacy support for bit GPIO masks
|
||||
cspinmask = 0;
|
||||
dcpinmask = 0;
|
||||
wrpinmask = 0;
|
||||
sclkpinmask = 0;
|
||||
|
||||
// Flags for which fonts are loaded
|
||||
#ifdef LOAD_GLCD
|
||||
fontsloaded = 0x0002; // Bit 1 set
|
||||
#endif
|
||||
@@ -515,7 +519,8 @@ void TFT_eSPI::init(uint8_t tc)
|
||||
{
|
||||
if (_booted)
|
||||
{
|
||||
#if !defined (ESP32) && !defined(TFT_PARALLEL_8_BIT) && !defined(RP2040)
|
||||
#if !defined (ESP32) && !defined(TFT_PARALLEL_8_BIT) && !defined(ARDUINO_ARCH_RP2040)
|
||||
// Legacy bitmasks for GPIO
|
||||
#if defined (TFT_CS) && (TFT_CS >= 0)
|
||||
cspinmask = (uint32_t) digitalPinToBitMask(TFT_CS);
|
||||
#endif
|
||||
@@ -543,14 +548,14 @@ void TFT_eSPI::init(uint8_t tc)
|
||||
|
||||
#else
|
||||
#if !defined(TFT_PARALLEL_8_BIT)
|
||||
#if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) && !defined(RP2040)
|
||||
#if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) && !defined(ARDUINO_ARCH_RP2040)
|
||||
spi.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1);
|
||||
#else
|
||||
spi.begin();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
lockTransaction = false;
|
||||
inTransaction = false;
|
||||
locked = true;
|
||||
|
||||
@@ -559,7 +564,7 @@ void TFT_eSPI::init(uint8_t tc)
|
||||
|
||||
|
||||
#ifdef TFT_CS
|
||||
// Set to output once again in case D6 (MISO) is used for CS
|
||||
// Set to output once again in case ESP8266 D6 (MISO) is used for CS
|
||||
pinMode(TFT_CS, OUTPUT);
|
||||
digitalWrite(TFT_CS, HIGH); // Chip select high (inactive)
|
||||
#elif defined (ESP8266) && !defined (TFT_PARALLEL_8_BIT)
|
||||
@@ -568,7 +573,7 @@ void TFT_eSPI::init(uint8_t tc)
|
||||
|
||||
|
||||
|
||||
// Set to output once again in case D6 (MISO) is used for DC
|
||||
// Set to output once again in case ESP8266 D6 (MISO) is used for DC
|
||||
#ifdef TFT_DC
|
||||
pinMode(TFT_DC, OUTPUT);
|
||||
digitalWrite(TFT_DC, HIGH); // Data/Command high = data mode
|
||||
@@ -1121,6 +1126,11 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da
|
||||
|
||||
#else // SPI interface
|
||||
|
||||
// This function can get called after a begin_tft_write
|
||||
// so a transaction may be in progress
|
||||
bool wasInTransaction = inTransaction;
|
||||
if (inTransaction) { inTransaction= false; end_tft_write();}
|
||||
|
||||
uint16_t color = 0;
|
||||
|
||||
begin_tft_read();
|
||||
@@ -1180,6 +1190,8 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da
|
||||
|
||||
end_tft_read();
|
||||
|
||||
// Reinstate the transaction if one was in progress
|
||||
if(wasInTransaction) { begin_tft_write(); inTransaction = true; }
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1222,7 +1234,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d
|
||||
}
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write();
|
||||
}
|
||||
|
||||
@@ -1280,7 +1292,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d
|
||||
data += w;
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write();
|
||||
}
|
||||
|
||||
@@ -1311,7 +1323,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1
|
||||
pushPixels(buffer, dw);
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write();
|
||||
}
|
||||
|
||||
@@ -1367,7 +1379,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1
|
||||
data += w;
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write();
|
||||
}
|
||||
|
||||
@@ -1500,7 +1512,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da
|
||||
}
|
||||
|
||||
_swapBytes = swap; // Restore old value
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write();
|
||||
}
|
||||
|
||||
@@ -1702,7 +1714,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da
|
||||
}
|
||||
}
|
||||
_swapBytes = swap; // Restore old value
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write();
|
||||
}
|
||||
|
||||
@@ -1865,7 +1877,7 @@ void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color)
|
||||
xs = xe;
|
||||
} while (xe < --r);
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -1934,7 +1946,7 @@ void TFT_eSPI::drawCircleHelper( int32_t x0, int32_t y0, int32_t rr, uint8_t cor
|
||||
}
|
||||
xs = xe;
|
||||
}
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -1975,7 +1987,7 @@ void TFT_eSPI::fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color)
|
||||
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -2059,7 +2071,7 @@ void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint1
|
||||
s += rx2 * ((4 * y) + 6);
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -2104,7 +2116,7 @@ void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint1
|
||||
s += rx2 * ((4 * y) + 6);
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -2135,7 +2147,7 @@ void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col
|
||||
drawFastVLine(x, y+1, h-2, color);
|
||||
drawFastVLine(x + w - 1, y+1, h-2, color);
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -2161,7 +2173,7 @@ void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t
|
||||
drawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4, color);
|
||||
drawCircleHelper(x + r , y + h - r - 1, r, 8, color);
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -2183,7 +2195,7 @@ void TFT_eSPI::fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t
|
||||
fillCircleHelper(x + r, y + h - r - 1, r, 1, w - r - r - 1, color);
|
||||
fillCircleHelper(x + r , y + r, r, 2, w - r - r - 1, color);
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -2202,7 +2214,7 @@ void TFT_eSPI::drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int3
|
||||
drawLine(x1, y1, x2, y2, color);
|
||||
drawLine(x2, y2, x0, y0, color);
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -2283,7 +2295,7 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in
|
||||
drawFastHLine(a, y, b - a + 1, color);
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -2307,7 +2319,7 @@ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w
|
||||
}
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -2331,7 +2343,7 @@ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w
|
||||
}
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -2354,7 +2366,7 @@ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t
|
||||
}
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -2378,7 +2390,7 @@ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t
|
||||
}
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -2787,7 +2799,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32
|
||||
}
|
||||
}
|
||||
}
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
@@ -2849,7 +2861,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32
|
||||
}
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
#endif
|
||||
@@ -2911,7 +2923,7 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
|
||||
DC_C; tft_Write_8(TFT_RAMWR);
|
||||
DC_D;
|
||||
|
||||
#else
|
||||
#else // Not ILI9225
|
||||
|
||||
#if defined (SSD1963_DRIVER)
|
||||
if ((rotation & 0x1) == 0) { swap_coord(x0, y0); swap_coord(x1, y1); }
|
||||
@@ -2927,14 +2939,50 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
|
||||
y1+=rowstart;
|
||||
#endif
|
||||
|
||||
DC_C; tft_Write_8(TFT_CASET);
|
||||
DC_D; tft_Write_32C(x0, x1);
|
||||
DC_C; tft_Write_8(TFT_PASET);
|
||||
DC_D; tft_Write_32C(y0, y1);
|
||||
DC_C; tft_Write_8(TFT_RAMWR);
|
||||
DC_D;
|
||||
// Temporary solution is to include the RP2040 optimised code here
|
||||
#if defined(ARDUINO_ARCH_RP2040) && !defined(TFT_PARALLEL_8BIT)
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_C;
|
||||
spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
|
||||
spi_get_hw(spi0)->dr = (uint32_t)TFT_CASET;
|
||||
|
||||
//end_tft_write(); // Must be called after setWindow
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_D;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)x0>>8;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)x0;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)x1>>8;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)x1;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_C;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)TFT_PASET;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_D;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)y0>>8;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)y0;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)y1>>8;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)y1;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_C;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)TFT_RAMWR;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
spi_set_format(spi0, 16, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
|
||||
DC_D;
|
||||
|
||||
#else
|
||||
|
||||
DC_C; tft_Write_8(TFT_CASET);
|
||||
DC_D; tft_Write_32C(x0, x1);
|
||||
DC_C; tft_Write_8(TFT_PASET);
|
||||
DC_D; tft_Write_32C(y0, y1);
|
||||
DC_C; tft_Write_8(TFT_RAMWR);
|
||||
DC_D;
|
||||
//end_tft_write(); // Must be called after setWindow
|
||||
|
||||
#endif // RP2040 SPI
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2964,6 +3012,44 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h)
|
||||
if ((rotation & 0x1) == 0) { swap_coord(xs, ys); swap_coord(xe, ye); }
|
||||
#endif
|
||||
|
||||
// Temporary solution is to include the RP2040 optimised code here
|
||||
#if defined(ARDUINO_ARCH_RP2040) && !defined(TFT_PARALLEL_8BIT)
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_C;
|
||||
spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
|
||||
spi_get_hw(spi0)->dr = (uint32_t)TFT_CASET;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_D;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)xs>>8;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)xs;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)xe>>8;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)xe;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_C;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)TFT_PASET;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_D;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)ys>>8;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)ys;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)ye>>8;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)ye;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_C;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)TFT_RAMRD;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
//spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
|
||||
DC_D;
|
||||
|
||||
// Flush the rx buffer and reset overflow flag
|
||||
while (spi_is_readable(spi0)) (void)spi_get_hw(spi0)->dr;
|
||||
spi_get_hw(spi0)->icr = SPI_SSPICR_RORIC_BITS;
|
||||
|
||||
#else
|
||||
// Column addr set
|
||||
DC_C; tft_Write_8(TFT_CASET);
|
||||
DC_D; tft_Write_32C(xs, xe);
|
||||
@@ -2976,6 +3062,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h)
|
||||
DC_C; tft_Write_8(TFT_RAMRD);
|
||||
|
||||
DC_D;
|
||||
#endif // RP2040 SPI
|
||||
|
||||
//end_tft_write(); // Must be called after readAddrWindow or CS set high
|
||||
}
|
||||
@@ -3030,6 +3117,63 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color)
|
||||
DC_C; tft_Write_8(TFT_RAMWR);
|
||||
DC_D; tft_Write_16(color);
|
||||
|
||||
// Temporary solution is to include the RP2040 optimised code here
|
||||
#elif defined (ARDUINO_ARCH_RP2040)
|
||||
|
||||
// Since the SPI functions do not terminate until transmission is complete
|
||||
// a busy check is not needed.
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_C;
|
||||
spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
|
||||
spi_get_hw(spi0)->dr = (uint32_t)TFT_CASET;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS){};
|
||||
DC_D;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)x>>8;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)x;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)x>>8;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)x;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_C;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)TFT_PASET;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_D;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)y>>8;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)y;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)y>>8;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)y;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_C;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)TFT_RAMWR;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_D;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)color>>8;
|
||||
spi_get_hw(spi0)->dr = (uint32_t)color;
|
||||
|
||||
/*
|
||||
// Subsequent pixel reads work OK without draining the FIFO...
|
||||
// Drain RX FIFO, then wait for shifting to finish (which may be *after*
|
||||
// TX FIFO drains), then drain RX FIFO again
|
||||
while (spi_is_readable(spi0))
|
||||
(void)spi_get_hw(spi0)->dr;
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS)
|
||||
tight_loop_contents();
|
||||
while (spi_is_readable(spi0))
|
||||
(void)spi_get_hw(spi0)->dr;
|
||||
//*/
|
||||
|
||||
// Subsequent pixel reads work without this
|
||||
// spi_get_hw(spi0)->icr = SPI_SSPICR_RORIC_BITS;
|
||||
|
||||
while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
|
||||
// Next call will start with 8 bit command so changing to 16 bit not needed here
|
||||
//spi_set_format(spi0, 16, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
|
||||
|
||||
#else
|
||||
|
||||
#if defined (SSD1963_DRIVER)
|
||||
@@ -3058,7 +3202,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color)
|
||||
}
|
||||
#endif
|
||||
DC_C; tft_Write_8(TFT_RAMWR);
|
||||
DC_D; tft_Write_16(color);
|
||||
DC_D; tft_Write_16(color);
|
||||
#endif
|
||||
|
||||
end_tft_write();
|
||||
@@ -3098,6 +3242,7 @@ void TFT_eSPI::pushColor(uint16_t color, uint32_t len)
|
||||
void TFT_eSPI::startWrite(void)
|
||||
{
|
||||
begin_tft_write();
|
||||
lockTransaction = true; // Lock transaction for all sequentially run sketch functions
|
||||
inTransaction = true;
|
||||
}
|
||||
|
||||
@@ -3107,9 +3252,10 @@ void TFT_eSPI::startWrite(void)
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::endWrite(void)
|
||||
{
|
||||
lockTransaction = false; // Release sketch induced transaction lock
|
||||
inTransaction = false;
|
||||
DMA_BUSY_CHECK; // Safety check - user code should have checked this!
|
||||
end_tft_write();
|
||||
DMA_BUSY_CHECK; // Safety check - user code should have checked this!
|
||||
end_tft_write(); // Release SPI bus
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
@@ -3217,7 +3363,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t
|
||||
if (dlen) drawFastHLine(xs, y0, dlen, color);
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write();
|
||||
}
|
||||
|
||||
@@ -3861,7 +4007,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
|
||||
pY += textsize;
|
||||
}
|
||||
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write();
|
||||
}
|
||||
else { // Faster drawing of characters and background using block write
|
||||
@@ -4006,7 +4152,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
|
||||
}
|
||||
}
|
||||
}
|
||||
inTransaction = false;
|
||||
inTransaction = lockTransaction;
|
||||
end_tft_write();
|
||||
}
|
||||
// End of RLE font rendering
|
||||
|
17
TFT_eSPI.h
17
TFT_eSPI.h
@@ -2,7 +2,7 @@
|
||||
Arduino TFT graphics library targeted at ESP8266
|
||||
and ESP32 based boards.
|
||||
|
||||
This is a standalone library that contains the
|
||||
This is a stand-alone library that contains the
|
||||
hardware driver, the graphics functions and the
|
||||
proportional fonts.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#ifndef _TFT_eSPIH_
|
||||
#define _TFT_eSPIH_
|
||||
|
||||
#define TFT_ESPI_VERSION "2.3.62"
|
||||
#define TFT_ESPI_VERSION "2.3.63"
|
||||
|
||||
// Bit level feature flags
|
||||
// Bit 0 set: viewport capability
|
||||
@@ -54,7 +54,7 @@
|
||||
#include "Processors/TFT_eSPI_ESP8266.h"
|
||||
#elif defined (STM32)
|
||||
#include "Processors/TFT_eSPI_STM32.h"
|
||||
#elif defined (RP2040)
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
#include "Processors/TFT_eSPI_RP2040.h"
|
||||
#else
|
||||
#include "Processors/TFT_eSPI_Generic.h"
|
||||
@@ -690,13 +690,13 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||
// New begin and end prototypes
|
||||
// begin/end a TFT write transaction
|
||||
// For SPI bus the transmit clock rate is set
|
||||
inline void begin_tft_write() __attribute__((always_inline));
|
||||
inline void end_tft_write() __attribute__((always_inline));
|
||||
inline void begin_tft_write() __attribute__((always_inline));
|
||||
inline void end_tft_write() __attribute__((always_inline));
|
||||
|
||||
// begin/end a TFT read transaction
|
||||
// For SPI bus: begin lowers SPI clock rate, end reinstates transmit clock rate
|
||||
inline void begin_tft_read() __attribute__((always_inline));
|
||||
inline void end_tft_read() __attribute__((always_inline));
|
||||
inline void begin_tft_read() __attribute__((always_inline));
|
||||
inline void end_tft_read() __attribute__((always_inline));
|
||||
|
||||
// Temporary library development function TODO: remove need for this
|
||||
void pushSwapBytePixels(const void* data_in, uint32_t len);
|
||||
@@ -765,7 +765,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||
bool isDigits; // adjust bounding box for numbers to reduce visual jiggling
|
||||
bool textwrapX, textwrapY; // If set, 'wrap' text at right and optionally bottom edge of display
|
||||
bool _swapBytes; // Swap the byte order for TFT pushImage()
|
||||
bool locked, inTransaction; // SPI transaction and mutex lock flags
|
||||
bool locked, inTransaction, lockTransaction; // SPI transaction and mutex lock flags
|
||||
|
||||
bool _booted; // init() or begin() has already run once
|
||||
|
||||
@@ -775,7 +775,6 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||
bool _psram_enable; // Enable PSRAM use for library functions (TBD) and Sprites
|
||||
|
||||
uint32_t _lastColor; // Buffered value of last colour used
|
||||
uint32_t _Cbuf; // SPI buffer for RP2040
|
||||
|
||||
#ifdef LOAD_GFXFF
|
||||
GFXfont *gfxFont;
|
||||
|
@@ -15,9 +15,6 @@
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// Define RP2040 to invoke optimised processor support (only for RP2040)
|
||||
//#define RP2040
|
||||
|
||||
// Define STM32 to invoke optimised processor support (only for STM32)
|
||||
//#define STM32
|
||||
|
||||
|
@@ -15,9 +15,6 @@
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// Define RP2040 to invoke optimised processor support (only for RP2040)
|
||||
#define RP2040
|
||||
|
||||
// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed)
|
||||
//#define TFT_PARALLEL_8_BIT
|
||||
|
||||
@@ -177,7 +174,7 @@
|
||||
// #define SPI_FREQUENCY 10000000
|
||||
// #define SPI_FREQUENCY 20000000
|
||||
// #define SPI_FREQUENCY 32000000
|
||||
#define SPI_FREQUENCY 63000000
|
||||
#define SPI_FREQUENCY 70000000
|
||||
|
||||
// Optional reduced SPI frequency for reading TFT
|
||||
#define SPI_READ_FREQUENCY 20000000
|
||||
@@ -185,11 +182,3 @@
|
||||
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
|
||||
#define SPI_TOUCH_FREQUENCY 2500000
|
||||
|
||||
// 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
|
||||
// run slightly faster, so leave it commented out unless you need it!
|
||||
|
||||
// Transaction support is needed to work with SD library but not needed with TFT_SdFat
|
||||
// Transaction support is required if other SPI devices are connected.
|
||||
|
||||
// #define SUPPORT_TRANSACTIONS
|
||||
|
@@ -0,0 +1,37 @@
|
||||
// Walking 1 write and read pixel test
|
||||
|
||||
#include <TFT_eSPI.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#define TDELAY 500
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
tft.init();
|
||||
tft.fillScreen(0xF81F);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static uint32_t wr = 1;
|
||||
static uint32_t rd = 0xFFFFFFFF;
|
||||
|
||||
delay(TDELAY);
|
||||
|
||||
tft.drawPixel(30,30,wr);
|
||||
Serial.print(" Pixel value written = ");Serial.println(wr,HEX);
|
||||
|
||||
rd = tft.readPixel(30,30);
|
||||
Serial.print(" Pixel value read = ");Serial.println(rd,HEX);
|
||||
|
||||
if (rd!=wr) {
|
||||
Serial.println(" ERROR ^^^^");
|
||||
//while(1) yield();
|
||||
}
|
||||
else Serial.println(" PASS ");
|
||||
// Walking 1 test
|
||||
wr = wr<<1;
|
||||
if (wr >= 0x10000) wr = 1;
|
||||
}
|
Reference in New Issue
Block a user