//////////////////////////////////////////////////// // TFT_eSPI driver functions for ESP32 processors // //////////////////////////////////////////////////// // Temporarily a separate file to TFT_eSPI_ESP32.h until board package low level API stabilises #ifndef _TFT_eSPI_ESP32H_ #define _TFT_eSPI_ESP32H_ // Processor ID reported by getSetup() #define PROCESSOR_ID 0x32 // Include processor specific header #include "soc/spi_reg.h" #include "driver/spi_master.h" #if !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32) #define CONFIG_IDF_TARGET_ESP32 #endif #ifndef VSPI #define VSPI FSPI #endif // Fix IDF problems with ESP32S3 // Note illogical enumerations: FSPI_HOST=SPI2_HOST=1 HSPI_HOST=SPI3_HOST=2 #if CONFIG_IDF_TARGET_ESP32S3 // Fix ESP32C3 IDF bug for missing definition (FSPI only tested at the moment) #ifndef REG_SPI_BASE // HSPI FSPI/VSPI #define REG_SPI_BASE(i) (((i)>1) ? (DR_REG_SPI3_BASE) : (DR_REG_SPI2_BASE)) #endif // Fix ESP32S3 IDF bug for name change #ifndef SPI_MOSI_DLEN_REG #define SPI_MOSI_DLEN_REG(x) SPI_MS_DLEN_REG(x) #endif #endif // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled #if !defined (SUPPORT_TRANSACTIONS) #define SUPPORT_TRANSACTIONS #endif /* ESP32: FSPI not defined HSPI = 2, uses SPI2 VSPI = 3, uses SPI3 ESP32-S2: FSPI = 1, uses SPI2 HSPI = 2, uses SPI3 VSPI not defined ESP32 C3: FSPI = 0, uses SPI2 ???? To be checked HSPI = 1, uses SPI3 ???? To be checked VSPI not defined For ESP32/S2/C3/S3: SPI1_HOST = 0 SPI2_HOST = 1 SPI3_HOST = 2 */ // ESP32 specific SPI port selection #ifdef USE_HSPI_PORT #ifdef CONFIG_IDF_TARGET_ESP32 #define SPI_PORT HSPI //HSPI is port 2 on ESP32 #else #define SPI_PORT 3 //HSPI is port 3 on ESP32 S2 #endif #elif defined(USE_FSPI_PORT) #define SPI_PORT 2 //FSPI(ESP32 S2) #else #ifdef CONFIG_IDF_TARGET_ESP32 #define SPI_PORT VSPI #elif CONFIG_IDF_TARGET_ESP32S2 #define SPI_PORT 2 //FSPI(ESP32 S2) #elif CONFIG_IDF_TARGET_ESP32S3 #define SPI_PORT FSPI #endif #endif #ifdef RPI_DISPLAY_TYPE #define CMD_BITS (16-1) #else #define CMD_BITS (8-1) #endif // Initialise processor specific SPI functions, used by init() #define INIT_TFT_DATA_BUS // Not used // Define a generic flag for 8 bit parallel #if defined (ESP32_PARALLEL) // Specific to ESP32 for backwards compatibility #if !defined (TFT_PARALLEL_8_BIT) #define TFT_PARALLEL_8_BIT // Generic parallel flag #endif #endif // Ensure ESP32 specific flag is defined for 8 bit parallel #if defined (TFT_PARALLEL_8_BIT) #if !defined (ESP32_PARALLEL) #define ESP32_PARALLEL #endif #endif #if !defined(DISABLE_ALL_LIBRARY_WARNINGS) && defined (ESP32_PARALLEL) #warning >>>>------>> DMA is not supported in parallel mode #endif // Processor specific code used by SPI bus transaction startWrite and endWrite functions #if !defined (ESP32_PARALLEL) #define _spi_cmd (volatile uint32_t*)(SPI_CMD_REG(SPI_PORT)) #define _spi_user (volatile uint32_t*)(SPI_USER_REG(SPI_PORT)) #define _spi_mosi_dlen (volatile uint32_t*)(SPI_MOSI_DLEN_REG(SPI_PORT)) #define _spi_w (volatile uint32_t*)(SPI_W0_REG(SPI_PORT)) #if (TFT_SPI_MODE == SPI_MODE1) || (TFT_SPI_MODE == SPI_MODE2) #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI | SPI_CK_OUT_EDGE #define SET_BUS_READ_MODE *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN | SPI_CK_OUT_EDGE #else #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI #define SET_BUS_READ_MODE *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN #endif #else // Not applicable to parallel bus #define SET_BUS_WRITE_MODE #define SET_BUS_READ_MODE #endif // Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions #if !defined(TFT_PARALLEL_8_BIT) && !defined(SPI_18BIT_DRIVER) #define ESP32_DMA // Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions #define DMA_BUSY_CHECK dmaWait() #else #define DMA_BUSY_CHECK #endif #if defined(TFT_PARALLEL_8_BIT) #define SPI_BUSY_CHECK #else #define SPI_BUSY_CHECK while (*_spi_cmd&SPI_USR) #endif // If smooth font is used then it is likely SPIFFS will be needed #ifdef SMOOTH_FONT // Call up the SPIFFS (SPI FLASH Filing System) for the anti-aliased fonts #define FS_NO_GLOBALS #include #include "SPIFFS.h" // ESP32 only #define FONT_FS_AVAILABLE #endif //////////////////////////////////////////////////////////////////////////////////////// // Define the DC (TFT Data/Command or Register Select (RS))pin drive code //////////////////////////////////////////////////////////////////////////////////////// #ifndef TFT_DC #define DC_C // No macro allocated so it generates no code #define DC_D // No macro allocated so it generates no code #else #if defined (TFT_PARALLEL_8_BIT) // TFT_DC, by design, must be in range 0-31 for single register parallel write #if (TFT_DC >= 0) && (TFT_DC < 32) #define DC_C GPIO.out_w1tc = (1 << TFT_DC) #define DC_D GPIO.out_w1ts = (1 << TFT_DC) #elif (TFT_DC >= 32) #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC- 32)) #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC- 32)) #else #define DC_C #define DC_D #endif #else #if (TFT_DC >= 32) #ifdef RPI_DISPLAY_TYPE // RPi displays need a slower DC change #define DC_C GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); \ GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) #define DC_D GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); \ GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) #else #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) #endif #elif (TFT_DC >= 0) #if defined (RPI_DISPLAY_TYPE) #if defined (ILI9486_DRIVER) // RPi ILI9486 display needs a slower DC change #define DC_C GPIO.out_w1tc = (1 << TFT_DC); \ GPIO.out_w1tc = (1 << TFT_DC) #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ GPIO.out_w1ts = (1 << TFT_DC) #else // Other RPi displays need a slower C->D change #define DC_C GPIO.out_w1tc = (1 << TFT_DC) #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ GPIO.out_w1ts = (1 << TFT_DC) #endif #else #define DC_C GPIO.out_w1tc = (1 << TFT_DC)//;GPIO.out_w1tc = (1 << TFT_DC) #define DC_D GPIO.out_w1ts = (1 << TFT_DC)//;GPIO.out_w1ts = (1 << TFT_DC) #endif #else #define DC_C #define DC_D #endif #endif #endif //////////////////////////////////////////////////////////////////////////////////////// // Define the CS (TFT chip select) pin drive code //////////////////////////////////////////////////////////////////////////////////////// #ifndef TFT_CS #define TFT_CS -1 // Keep DMA code happy #define CS_L // No macro allocated so it generates no code #define CS_H // No macro allocated so it generates no code #else #if defined (TFT_PARALLEL_8_BIT) #if TFT_CS >= 32 #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) #elif TFT_CS >= 0 #define CS_L GPIO.out_w1tc = (1 << TFT_CS) #define CS_H GPIO.out_w1ts = (1 << TFT_CS) #else #define CS_L #define CS_H #endif #else #if (TFT_CS >= 32) #ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change #define CS_L GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); \ GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) #define CS_H GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \ GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) #else #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) #endif #elif (TFT_CS >= 0) #ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change #define CS_L GPIO.out_w1ts = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS) #define CS_H GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1ts = (1 << TFT_CS) #else #define CS_L GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS) #define CS_H GPIO.out_w1ts = (1 << TFT_CS)//;GPIO.out_w1ts = (1 << TFT_CS) #endif #else #define CS_L #define CS_H #endif #endif #endif //////////////////////////////////////////////////////////////////////////////////////// // Define the WR (TFT Write) pin drive code //////////////////////////////////////////////////////////////////////////////////////// #if defined (TFT_WR) #if (TFT_WR >= 32) // Note: it will be ~1.25x faster if the TFT_WR pin uses a GPIO pin lower than 32 #define WR_L GPIO.out1_w1tc.val = (1 << (TFT_WR - 32)) #define WR_H GPIO.out1_w1ts.val = (1 << (TFT_WR - 32)) #elif (TFT_WR >= 0) // TFT_WR, for best performance, should be in range 0-31 for single register parallel write #define WR_L GPIO.out_w1tc = (1 << TFT_WR) #define WR_H GPIO.out_w1ts = (1 << TFT_WR) #else #define WR_L #define WR_H #endif #else #define WR_L #define WR_H #endif //////////////////////////////////////////////////////////////////////////////////////// // Define the touch screen chip select pin drive code //////////////////////////////////////////////////////////////////////////////////////// #ifndef TOUCH_CS #define T_CS_L // No macro allocated so it generates no code #define T_CS_H // No macro allocated so it generates no code #else // XPT2046 is slow, so use slower digitalWrite here #define T_CS_L digitalWrite(TOUCH_CS, LOW) #define T_CS_H digitalWrite(TOUCH_CS, HIGH) #endif //////////////////////////////////////////////////////////////////////////////////////// // Make sure SPI default pins are assigned if not specified by user or set to -1 //////////////////////////////////////////////////////////////////////////////////////// #if !defined (TFT_PARALLEL_8_BIT) #ifdef USE_HSPI_PORT #ifndef TFT_MISO #define TFT_MISO -1 #endif #ifndef TFT_MOSI #define TFT_MOSI 13 #endif #if (TFT_MOSI == -1) #undef TFT_MOSI #define TFT_MOSI 13 #endif #ifndef TFT_SCLK #define TFT_SCLK 14 #endif #if (TFT_SCLK == -1) #undef TFT_SCLK #define TFT_SCLK 14 #endif #else // VSPI port #ifndef TFT_MISO #define TFT_MISO -1 #endif #ifndef TFT_MOSI #define TFT_MOSI 23 #endif #if (TFT_MOSI == -1) #undef TFT_MOSI #define TFT_MOSI 23 #endif #ifndef TFT_SCLK #define TFT_SCLK 18 #endif #if (TFT_SCLK == -1) #undef TFT_SCLK #define TFT_SCLK 18 #endif #if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32S2) #if (TFT_MISO == -1) #undef TFT_MISO #define TFT_MISO TFT_MOSI #endif #endif #endif #endif //////////////////////////////////////////////////////////////////////////////////////// // Define the parallel bus interface chip pin drive code //////////////////////////////////////////////////////////////////////////////////////// #if defined (TFT_PARALLEL_8_BIT) #if (TFT_D0 >= 32) // If D0 is a high GPIO assume all other data bits are high GPIO #define MASK_OFFSET 32 #define GPIO_CLR_REG GPIO.out1_w1tc.val #define GPIO_SET_REG GPIO.out1_w1ts.val #else #define MASK_OFFSET 0 #define GPIO_CLR_REG GPIO.out_w1tc #define GPIO_SET_REG GPIO.out_w1ts #endif // Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically // can then use e.g. GPIO.out_w1ts = set_mask(0xFF); to set data bus to 0xFF #define PARALLEL_INIT_TFT_DATA_BUS \ for (int32_t c = 0; c<256; c++) \ { \ xset_mask[c] = 0; \ if ( c & 0x01 ) xset_mask[c] |= (1 << (TFT_D0-MASK_OFFSET)); \ if ( c & 0x02 ) xset_mask[c] |= (1 << (TFT_D1-MASK_OFFSET)); \ if ( c & 0x04 ) xset_mask[c] |= (1 << (TFT_D2-MASK_OFFSET)); \ if ( c & 0x08 ) xset_mask[c] |= (1 << (TFT_D3-MASK_OFFSET)); \ if ( c & 0x10 ) xset_mask[c] |= (1 << (TFT_D4-MASK_OFFSET)); \ if ( c & 0x20 ) xset_mask[c] |= (1 << (TFT_D5-MASK_OFFSET)); \ if ( c & 0x40 ) xset_mask[c] |= (1 << (TFT_D6-MASK_OFFSET)); \ if ( c & 0x80 ) xset_mask[c] |= (1 << (TFT_D7-MASK_OFFSET)); \ } \ // Mask for the 8 data bits to set pin directions #define GPIO_DIR_MASK ((1 << (TFT_D0-MASK_OFFSET)) | (1 << (TFT_D1-MASK_OFFSET)) | (1 << (TFT_D2-MASK_OFFSET)) | (1 << (TFT_D3-MASK_OFFSET)) | (1 << (TFT_D4-MASK_OFFSET)) | (1 << (TFT_D5-MASK_OFFSET)) | (1 << (TFT_D6-MASK_OFFSET)) | (1 << (TFT_D7-MASK_OFFSET))) #if (TFT_WR >= 32) #if (TFT_D0 >= 32) // Data bits and the write line are cleared to 0 in one step (1.25x faster) #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK | (1 << (TFT_WR-32))) #elif (TFT_D0 >= 0) // Data bits and the write line are cleared sequentially #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK); WR_L #endif #elif (TFT_WR >= 0) #if (TFT_D0 >= 32) // Data bits and the write line are cleared sequentially #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK); WR_L #elif (TFT_D0 >= 0) // Data bits and the write line are cleared to 0 in one step (1.25x faster) #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK | (1 << TFT_WR)) #endif #else #define GPIO_OUT_CLR_MASK #endif // A lookup table is used to set the different bit patterns, this uses 1kByte of RAM #define set_mask(C) xset_mask[C] // 63fps Sprite rendering test 33% faster, graphicstest only 1.8% faster than shifting in real time // Real-time shifting alternative to above to save 1KByte RAM, 47 fps Sprite rendering test /*#define set_mask(C) (((C)&0x80)>>7)<>6)<>5)<>4)<>3)<>2)<>1)<>0)<> 8)); WR_H; \ GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x07E0)>> 3)); WR_H; \ GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x001F)<< 3)); WR_H // 18 bit color write with swapped bytes #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) #else #ifdef PSEUDO_16_BIT // One write strobe for both bytes #define tft_Write_16(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H #define tft_Write_16S(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H #else // Write 16 bits to TFT #define tft_Write_16(C) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H; \ GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H // 16 bit write with swapped bytes #define tft_Write_16S(C) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H; \ GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H #endif #endif // Write 32 bits to TFT #define tft_Write_32(C) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 24)); WR_H; \ GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 16)); WR_H; \ GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H; \ GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H // Write two concatenated 16 bit values to TFT #define tft_Write_32C(C,D) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H; \ GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H; \ GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((D) >> 8)); WR_H; \ GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((D) >> 0)); WR_H // Write 16 bit value twice to TFT - used by drawPixel() #define tft_Write_32D(C) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H; \ GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H; \ GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H; \ GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H // Read pin #ifdef TFT_RD #if (TFT_RD >= 32) #define RD_L GPIO.out1_w1tc.val = (1 << (TFT_RD - 32)) #define RD_H GPIO.out1_w1ts.val = (1 << (TFT_RD - 32)) #elif (TFT_RD >= 0) #define RD_L GPIO.out_w1tc = (1 << TFT_RD) //#define RD_L digitalWrite(TFT_WR, LOW) #define RD_H GPIO.out_w1ts = (1 << TFT_RD) //#define RD_H digitalWrite(TFT_WR, HIGH) #else #define RD_L #define RD_H #endif #else #define TFT_RD -1 #define RD_L #define RD_H #endif //////////////////////////////////////////////////////////////////////////////////////// // Macros to write commands/pixel colour data to a SPI ILI948x TFT //////////////////////////////////////////////////////////////////////////////////////// #elif defined (SPI_18BIT_DRIVER) // SPI 18 bit colour // Write 8 bits to TFT #define tft_Write_8(C) spi.transfer(C) // Convert 16 bit colour to 18 bit and write in 3 bytes #define tft_Write_16(C) spi.transfer(((C) & 0xF800)>>8); \ spi.transfer(((C) & 0x07E0)>>3); \ spi.transfer(((C) & 0x001F)<<3) // Future option for transfer without wait #define tft_Write_16N(C) tft_Write_16(C) // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes #define tft_Write_16S(C) spi.transfer((C) & 0xF8); \ spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \ spi.transfer(((C) & 0x1F00)>>5) // Write 32 bits to TFT #define tft_Write_32(C) spi.write32(C) // Write two concatenated 16 bit values to TFT #define tft_Write_32C(C,D) spi.write32((C)<<16 | (D)) // Write 16 bit value twice to TFT #define tft_Write_32D(C) spi.write32((C)<<16 | (C)) //////////////////////////////////////////////////////////////////////////////////////// // Macros to write commands/pixel colour data to an Raspberry Pi TFT //////////////////////////////////////////////////////////////////////////////////////// #elif defined (RPI_DISPLAY_TYPE) // ESP32-S3 low level SPI writes for 8, 16 and 32 bit values // to avoid the function call overhead #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1; \ *_spi_w = D; \ *_spi_cmd = SPI_UPDATE; \ while (*_spi_cmd & SPI_UPDATE); \ *_spi_cmd = SPI_USR; \ while (*_spi_cmd & SPI_USR); // Write 8 bits #define tft_Write_8(C) TFT_WRITE_BITS((C)<<8, 16) // Write 16 bits with corrected endianness for 16 bit colours #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) // Future option for transfer without wait #define tft_Write_16N(C) tft_Write_16(C) // Write 16 bits #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) // Write 32 bits #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) // Write two address coordinates #define tft_Write_32C(C,D) TFT_WRITE_BITS((C)<<24 | (C), 32); \ TFT_WRITE_BITS((D)<<24 | (D), 32) // Write same value twice #define tft_Write_32D(C) tft_Write_32C(C,C) //////////////////////////////////////////////////////////////////////////////////////// // Macros for all other SPI displays //////////////////////////////////////////////////////////////////////////////////////// #else #if !defined(CONFIG_IDF_TARGET_ESP32S3) #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1; \ *_spi_w = D; \ *_spi_cmd = SPI_USR; \ while (*_spi_cmd & SPI_USR); #else #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1; \ *_spi_w = D; \ *_spi_cmd = SPI_UPDATE; \ while (*_spi_cmd & SPI_UPDATE); \ *_spi_cmd = SPI_USR; \ while (*_spi_cmd & SPI_USR); #endif // Write 8 bits #define tft_Write_8(C) TFT_WRITE_BITS(C, 8) // Write 16 bits with corrected endianness for 16 bit colours #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) // Future option for transfer without wait #if !defined(CONFIG_IDF_TARGET_ESP32S3) #define tft_Write_16N(C) *_spi_mosi_dlen = 16-1; \ *_spi_w = ((C)<<8 | (C)>>8); \ *_spi_cmd = SPI_USR; #else #define tft_Write_16N(C) *_spi_mosi_dlen = 16-1; \ *_spi_w = ((C)<<8 | (C)>>8); \ *_spi_cmd = SPI_UPDATE; \ while (*_spi_cmd & SPI_UPDATE); \ *_spi_cmd = SPI_USR; #endif // Write 16 bits #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) // Write 32 bits #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) // Write two address coordinates #define tft_Write_32C(C,D) TFT_WRITE_BITS((uint16_t)((D)<<8 | (D)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) // Write same value twice #define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) #endif #ifndef tft_Write_16N #define tft_Write_16N tft_Write_16 #endif //////////////////////////////////////////////////////////////////////////////////////// // Macros to read from display using SPI or software SPI //////////////////////////////////////////////////////////////////////////////////////// #if !defined (TFT_PARALLEL_8_BIT) // Read from display using SPI or software SPI // Use a SPI read transfer #define tft_Read_8() spi.transfer(0) #endif // Concatenate a byte sequence A,B,C,D to CDAB, P is a uint8_t pointer #define DAT8TO32(P) ( (uint32_t)P[0]<<8 | P[1] | P[2]<<24 | P[3]<<16 ) #endif // Header end