diff --git a/Processors/TFT_eSPI_STM32.c b/Processors/TFT_eSPI_STM32.c index 776cc84..e20c6a2 100644 --- a/Processors/TFT_eSPI_STM32.c +++ b/Processors/TFT_eSPI_STM32.c @@ -24,9 +24,6 @@ DMA_HandleTypeDef dmaHal; #endif - // Buffer for SPI transmit byte padding and byte order manipulation - uint8_t spiBuffer[8]; - //////////////////////////////////////////////////////////////////////////////////////// #if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT) //////////////////////////////////////////////////////////////////////////////////////// @@ -296,34 +293,19 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) #define BUF_SIZE 240*3 void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) { - uint8_t col[BUF_SIZE]; + //uint8_t col[BUF_SIZE]; // Always using swapped bytes is a peculiarity of this function... //color = color>>8 | color<<8; uint8_t r = (color & 0xF800)>>8; // Red uint8_t g = (color & 0x07E0)>>3; // Green uint8_t b = (color & 0x001F)<<3; // Blue - if (len=BUF_SIZE/3 ) ; - // Send remaining pixels - if (len) HAL_SPI_Transmit(&spiHal, col, len*3, HAL_MAX_DELAY); //*/ + SPI_BUSY_CHECK; } /*************************************************************************************** ** Function name: pushPixels - for STM32 and 3 byte RGB display @@ -333,26 +315,25 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) { uint16_t *data = (uint16_t*)data_in; - if(_swapBytes) { + if(!_swapBytes) { while ( len-- ) { // Split out the colours - spiBuffer[0] = (*data & 0xF8); // Red - spiBuffer[1] = (*data & 0xE000)>>11 | (*data & 0x07)<<5; // Green - spiBuffer[2] = (*data & 0x1F00)>>5; // Blue + TX_FIFO = (*data & 0xF8); // Red + TX_FIFO = (*data & 0xE000)>>11 | (*data & 0x07)<<5; // Green + TX_FIFO = (*data & 0x1F00)>>5; // Blue data++; - HAL_SPI_Transmit(&spiHal, spiBuffer, 3, HAL_MAX_DELAY); } } else { while ( len-- ) { // Split out the colours - spiBuffer[0] = (*data & 0xF800)>>8; // Red - spiBuffer[1] = (*data & 0x07E0)>>3; // Green - spiBuffer[2] = (*data & 0x001F)<<3; // Blue + TX_FIFO = (*data & 0xF800)>>8; // Red + TX_FIFO = (*data & 0x07E0)>>3; // Green + TX_FIFO = (*data & 0x001F)<<3; // Blue data++; - HAL_SPI_Transmit(&spiHal, spiBuffer, 3, HAL_MAX_DELAY); } } + SPI_BUSY_CHECK; } //////////////////////////////////////////////////////////////////////////////////////// @@ -364,6 +345,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) ** Description: Write a block of pixels of the same colour ***************************************************************************************/ #define BUF_SIZE 480 +/* void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) { uint16_t col[BUF_SIZE]; @@ -381,7 +363,47 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) len -= BUF_SIZE; } while ( len>=BUF_SIZE ) ; // Send remaining pixels - if (len) HAL_SPI_Transmit(&spiHal, (uint8_t*)col, len<<1, HAL_MAX_DELAY); //*/ + if (len) HAL_SPI_Transmit(&spiHal, (uint8_t*)col, len<<1, HAL_MAX_DELAY); +} + //*/ +void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ + // Loop unrolling improves speed dramatically graphics test 0.634s => 0.374s + while (len>31) { + #if !defined (SSD1963_DRIVER) + // 32D macro writes 16 bits twice + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + #else + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + #endif + len-=32; + } + + while (len>7) { + #if !defined (SSD1963_DRIVER) + tft_Write_32D(color); tft_Write_32D(color); + tft_Write_32D(color); tft_Write_32D(color); + #else + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); + #endif + len-=8; + } + + while (len--) {tft_Write_16(color);} } @@ -392,26 +414,23 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) void TFT_eSPI::pushPixels(const void* data_in, uint32_t len) { uint16_t *data = (uint16_t*)data_in; + if(_swapBytes) { - uint16_t col[BUF_SIZE]; // Buffer for swapped bytes - while ( len>=BUF_SIZE ) { - for (uint32_t i = 0; i < BUF_SIZE; i++) { col[i] = (*data>>8) | (*data<<8); data++; } - HAL_SPI_Transmit(&spiHal, (uint8_t*)col, BUF_SIZE<<1, HAL_MAX_DELAY); - len -= BUF_SIZE; + while ( len-- ) { + TX_FIFO = (uint8_t)(*data>>8); + TX_FIFO = (uint8_t)(*data<<8); + data++; } - for (uint32_t i = 0; i < len; i++) { col[i] = (*data>>8) | (*data<<8); data++; } - HAL_SPI_Transmit(&spiHal, (uint8_t*)col, len<<1, HAL_MAX_DELAY); } else { - // HAL byte count for transmit is only 16 bits maximum so to avoid this constraint - // transfers of small blocks are performed until HAL capacity is reached. - while(len>0x7FFF) { // Transfer 16-bit pixels in blocks if len*2 over 65534 bytes - HAL_SPI_Transmit(&spiHal, (uint8_t*)data, 0x800<<1, HAL_MAX_DELAY); - len -= 0x800; data+= 0x800; // Arbitrarily use 2KByte blocks + while ( len-- ) { + // Split out the colours + TX_FIFO = (uint8_t)(*data); + TX_FIFO = (uint8_t)(*data>>8); + data++; } - // Send remaining pixels (max 65534 bytes) - HAL_SPI_Transmit(&spiHal, (uint8_t*)data, len<<1, HAL_MAX_DELAY); } + SPI_BUSY_CHECK; } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/Processors/TFT_eSPI_STM32.h b/Processors/TFT_eSPI_STM32.h index 65e710d..73a22cb 100644 --- a/Processors/TFT_eSPI_STM32.h +++ b/Processors/TFT_eSPI_STM32.h @@ -151,6 +151,15 @@ #define TFT_SPI_PORT 1 #endif + #if (TFT_SPI_PORT == 1) + #define SPIX SPI1 + #elif (TFT_SPI_PORT == 2) + #define SPIX SPI2 + #elif (TFT_SPI_PORT == 3) + #define SPIX SPI3 + #elif (TFT_SPI_PORT == 4) + #define SPIX SPI4 + #endif // Global define is _VARIANT_ARDUINO_STM32_, see board package stm32_def.h for specific variants #if defined (STM32F2xx) || defined (STM32F4xx) || defined (STM32F7xx) @@ -226,8 +235,8 @@ #define DC_PORT digitalPinToPort(TFT_DC) #define DC_PIN_MASK digitalPinToBitMask(TFT_DC) // Use bit set reset register - #define DC_C DC_PORT->BSRR = DC_PIN_MASK<<16 - #define DC_D DC_PORT->BSRR = DC_PIN_MASK + #define DC_C DC_DELAY; DC_PORT->BSRR = DC_PIN_MASK<<16 + #define DC_D DC_DELAY; DC_PORT->BSRR = DC_PIN_MASK #endif //////////////////////////////////////////////////////////////////////////////////////// @@ -962,64 +971,56 @@ //////////////////////////////////////////////////////////////////////////////////////// #elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour - // Write 8 bits to TFT - #define tft_Write_8(C) \ - { spiBuffer[0] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 1, 10); } + #define SPI_TXE_CHECK while(!__HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_TXE)){} + //BSY check must allow for APB clock delay by checking TXE flag first + #define SPI_BUSY_CHECK SPI_TXE_CHECK; while( __HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_BSY)){} + #define TX_FIFO SPI_TXE_CHECK; *((__IO uint8_t *)&SPIX->DR) - // Convert 16-bit colour to 18-bit and write in 3 bytes - #define tft_Write_16(C) \ - { spiBuffer[0] = ((C) & 0xF800)>>8; spiBuffer[1] = ((C) & 0x07E0)>>3; spiBuffer[2] = ((C) & 0x001F)<<3; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 3, 10); } + //#define tft_Write_8(C) spi.transfer(C) + #define tft_Write_8(C) TX_FIFO = (C); SPI_BUSY_CHECK + #define tft_Write_16(C) TX_FIFO = ((C) & 0xF800)>>8; TX_FIFO = ((C) & 0x07E0)>>3; TX_FIFO = ((C) & 0x001F)<<3; SPI_BUSY_CHECK + #define tft_Write_16S(C) TX_FIFO = (C) & 0xF8; TX_FIFO = ((C) & 0xE000)>>11 | ((C) & 0x07)<<5; TX_FIFO = ((C) & 0x1F00)>>5; SPI_BUSY_CHECK + #define tft_Write_16N(C) TX_FIFO = ((C) & 0xF800)>>8; TX_FIFO = ((C) & 0x07E0)>>3; TX_FIFO = ((C) & 0x001F)<<3 - // Convert swapped byte 16-bit colour to 18-bit and write in 3 bytes - #define tft_Write_16S(C) \ - { spiBuffer[0] = (C) & 0xF8; spiBuffer[1] = ((C) & 0xE000)>>11 | ((C) & 0x07)<<5; spiBuffer[2] = ((C) & 0x1F00)>>5; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 3, 10); } - - // Write 32 bits to TFT #define tft_Write_32(C) \ - { spiBuffer[0] = (C)>>24; spiBuffer[1] = (C)>>16; spiBuffer[2] = (C)>>8; spiBuffer[3] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); } + TX_FIFO = (C)>>24; TX_FIFO = (C)>>16; \ + TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK - // Write two address coordinates #define tft_Write_32C(C,D) \ - { spiBuffer[0] = (C)>>8; spiBuffer[1] = C; spiBuffer[2] = (D)>>8; spiBuffer[3] = D; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); } + TX_FIFO = (C)>>8; TX_FIFO = (C); \ + TX_FIFO = (D)>>8; TX_FIFO = (D); SPI_BUSY_CHECK - // Write same value twice #define tft_Write_32D(C) \ - { spiBuffer[0] = spiBuffer[2] = (C)>>8; spiBuffer[1] = spiBuffer[3] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); } + TX_FIFO = (C)>>8; TX_FIFO = (C); \ + TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK //////////////////////////////////////////////////////////////////////////////////////// // Macros to write commands/pixel colour data to a SPI Raspberry Pi TFT //////////////////////////////////////////////////////////////////////////////////////// #elif defined (RPI_DISPLAY_TYPE) - #define tft_Write_8(C) \ - { spiBuffer[0] = 0; spiBuffer[1] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); } + #define SPI_TXE_CHECK while(!__HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_TXE)){} + //BSY check must allow for APB clock delay by checking TXE flag first + #define SPI_BUSY_CHECK SPI_TXE_CHECK; while( __HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_BSY)){} + #define TX_FIFO SPI_TXE_CHECK; *((__IO uint8_t *)&SPIX->DR) - #define tft_Write_16(C) \ - { spiBuffer[0] = (C)>>8; spiBuffer[1] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); } - - #define tft_Write_16S(C) \ - { spiBuffer[0] = C; spiBuffer[1] = (C)>>8; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); } + //#define tft_Write_8(C) spi.transfer(C) + #define tft_Write_8(C) TX_FIFO = (0); TX_FIFO = (C); SPI_BUSY_CHECK + #define tft_Write_16(C) TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK + #define tft_Write_16S(C) TX_FIFO = (C); TX_FIFO = (C)>>8; SPI_BUSY_CHECK + #define tft_Write_16N(C) TX_FIFO = (C)>>8; TX_FIFO = (C) #define tft_Write_32(C) \ - { spiBuffer[0] = (C)>>24; spiBuffer[1] = (C)>>16; spiBuffer[2] = (C)>>8; spiBuffer[3] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); } + TX_FIFO = (C)>>24; TX_FIFO = (C)>>16; \ + TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK #define tft_Write_32C(C,D) \ - { spiBuffer[1] = ((C)>>8); spiBuffer[3] = (C); spiBuffer[5] = ((D)>>8); spiBuffer[7] = D; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 8, 10); } + TX_FIFO = (0); TX_FIFO = (C)>>8; TX_FIFO = (0); TX_FIFO = (C); \ + TX_FIFO = (0); TX_FIFO = (D)>>8; TX_FIFO = (0); TX_FIFO = (D); SPI_BUSY_CHECK #define tft_Write_32D(C) \ - { spiBuffer[1] = ((C)>>8); spiBuffer[3] = (C); spiBuffer[5] = ((C)>>8); spiBuffer[7] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 8, 10); } + TX_FIFO = (0); TX_FIFO = (C)>>8; TX_FIFO = (0); TX_FIFO = (C); \ + TX_FIFO = (0); TX_FIFO = (C)>>8; TX_FIFO = (0); TX_FIFO = (C); SPI_BUSY_CHECK //////////////////////////////////////////////////////////////////////////////////////// // Macros for all other SPI displays @@ -1027,40 +1028,37 @@ #else -/* Remove patch to fix #2933 - #if defined(ST7789_DRIVER) || defined(ST7789_2_DRIVER) - // Temporary workaround for issue #510 part 2 - #define tft_Write_8(C) spi.transfer(C) - #else -*/ - #define tft_Write_8(C) \ - { spiBuffer[0] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 1, 10); delayMicroseconds(1);} -/* Remove patch to fix #2933 - #endif -*/ - #define tft_Write_16(C) \ - { spiBuffer[0] = (C)>>8; spiBuffer[1] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); } + //#define DC_DELAY delayMicroseconds(1) // Premature BSY clear Hardware bug? - #define tft_Write_16S(C) \ - { spiBuffer[0] = C; spiBuffer[1] = (C)>>8; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); } + #define SPI_TXE_CHECK while(!__HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_TXE)){} + //BSY check must allow for APB clock delay by checking TXE flag first + #define SPI_BUSY_CHECK SPI_TXE_CHECK; while( __HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_BSY)){} + #define TX_FIFO SPI_TXE_CHECK; *((__IO uint8_t *)&SPIX->DR) + + #define tft_Write_8(C) TX_FIFO = (C); SPI_BUSY_CHECK + #define tft_Write_16(C) TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK + #define tft_Write_16S(C) TX_FIFO = (C); TX_FIFO = (C)>>8; SPI_BUSY_CHECK + #define tft_Write_16N(C) TX_FIFO = (C)>>8; TX_FIFO = (C) #define tft_Write_32(C) \ - { spiBuffer[0] = (C)>>24; spiBuffer[1] = (C)>>16; spiBuffer[2] = (C)>>8; spiBuffer[3] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); } + TX_FIFO = (C)>>24; TX_FIFO = (C)>>16; \ + tft_Write_16((uint16_t) ((C)>>0)) #define tft_Write_32C(C,D) \ - { spiBuffer[0] = (C)>>8; spiBuffer[1] = C; spiBuffer[2] = (D)>>8; spiBuffer[3] = D; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); } + TX_FIFO = (C)>>8; TX_FIFO = (C); \ + tft_Write_16((uint16_t) (D)) #define tft_Write_32D(C) \ - { spiBuffer[0] = spiBuffer[2] = (C)>>8; spiBuffer[1] = spiBuffer[3] = C; \ - HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); } + TX_FIFO = (C)>>8; TX_FIFO = (C); \ + tft_Write_16((uint16_t) (C)) #endif +#ifndef DC_DELAY + //#define DC_DELAY delayMicroseconds(1) // Premature BSY clear hardware bug? + #define DC_DELAY +#endif + #ifndef tft_Write_16N #define tft_Write_16N tft_Write_16 #endif diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 3ce8554..1a0370b 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -16,7 +16,7 @@ #ifndef _TFT_eSPIH_ #define _TFT_eSPIH_ -#define TFT_ESPI_VERSION "2.5.42" +#define TFT_ESPI_VERSION "2.5.43" // Bit level feature flags // Bit 0 set: viewport capability diff --git a/library.json b/library.json index be2db5f..f590f3e 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "2.5.42", + "version": "2.5.43", "keywords": "Arduino, tft, display, ttgo, LilyPi, WT32-SC01, ePaper, display, Pico, RP2040 Nano Connect, RP2040, STM32, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9481, ILI9486, ILI9488, ST7789, ST7796, RM68140, SSD1351, SSD1963, ILI9225, HX8357D, GC9A01, R61581", "description": "A TFT and ePaper (SPI or parallel interface) graphics library with optimisation for Raspberry Pi Pico, RP2040, ESP8266, ESP32 and STM32 processors", "repository": diff --git a/library.properties b/library.properties index 69237f0..319d4ec 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=2.5.42 +version=2.5.43 author=Bodmer maintainer=Bodmer sentence=TFT graphics library for Arduino processors with performance optimisation for RP2040, STM32, ESP8266 and ESP32