Improve RPi Pico (RP2040) rendering performance

This commit is contained in:
Bodmer
2021-04-05 16:39:33 +01:00
parent 356095bdf3
commit fce86c0f2e
7 changed files with 296 additions and 118 deletions

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}