acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

TFT_eSPI_ESP32_S3.h (23543B)

      1         ////////////////////////////////////////////////////
      2         // TFT_eSPI driver functions for ESP32 processors //
      3         ////////////////////////////////////////////////////
      4 
      5 // Temporarily a separate file to TFT_eSPI_ESP32.h until board package low level API stabilises
      6 
      7 #ifndef _TFT_eSPI_ESP32H_
      8 #define _TFT_eSPI_ESP32H_
      9 
     10 // Processor ID reported by getSetup()
     11 #define PROCESSOR_ID 0x32
     12 
     13 // Include processor specific header
     14 #include "soc/spi_reg.h"
     15 #include "driver/spi_master.h"
     16 
     17 #if !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32)
     18   #define CONFIG_IDF_TARGET_ESP32
     19 #endif
     20 
     21 #ifndef VSPI
     22   #define VSPI FSPI
     23 #endif
     24 
     25 // Fix IDF problems with ESP32S3
     26 // Note illogical enumerations: FSPI_HOST=SPI2_HOST=1   HSPI_HOST=SPI3_HOST=2
     27 #if CONFIG_IDF_TARGET_ESP32S3
     28   // Fix ESP32C3 IDF bug for missing definition (FSPI only tested at the moment)
     29   #ifndef REG_SPI_BASE //                      HSPI                 FSPI/VSPI
     30     #define REG_SPI_BASE(i) (((i)>1) ? (DR_REG_SPI3_BASE) : (DR_REG_SPI2_BASE))
     31   #endif
     32 
     33   // Fix ESP32S3 IDF bug for name change
     34   #ifndef SPI_MOSI_DLEN_REG
     35     #define SPI_MOSI_DLEN_REG(x) SPI_MS_DLEN_REG(x)
     36   #endif
     37 
     38 #endif
     39 
     40 // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled
     41 #if !defined (SUPPORT_TRANSACTIONS)
     42   #define SUPPORT_TRANSACTIONS
     43 #endif
     44 
     45 /*
     46 ESP32:
     47 FSPI not defined
     48 HSPI = 2, uses SPI2
     49 VSPI = 3, uses SPI3
     50 
     51 ESP32-S2:
     52 FSPI = 1, uses SPI2
     53 HSPI = 2, uses SPI3
     54 VSPI not defined
     55 
     56 ESP32 C3:
     57 FSPI = 0, uses SPI2 ???? To be checked
     58 HSPI = 1, uses SPI3 ???? To be checked
     59 VSPI not defined
     60 
     61 For ESP32/S2/C3/S3:
     62 SPI1_HOST = 0
     63 SPI2_HOST = 1
     64 SPI3_HOST = 2
     65 */
     66 
     67 // ESP32 specific SPI port selection
     68 #ifdef USE_HSPI_PORT
     69   #ifdef CONFIG_IDF_TARGET_ESP32
     70     #define SPI_PORT HSPI  //HSPI is port 2 on ESP32
     71   #else
     72     #define SPI_PORT 3     //HSPI is port 3 on ESP32 S2
     73   #endif
     74 #elif defined(USE_FSPI_PORT)
     75     #define SPI_PORT 2 //FSPI(ESP32 S2)
     76 #else
     77   #ifdef CONFIG_IDF_TARGET_ESP32
     78     #define SPI_PORT VSPI
     79   #elif CONFIG_IDF_TARGET_ESP32S2
     80     #define SPI_PORT 2 //FSPI(ESP32 S2)
     81   #elif CONFIG_IDF_TARGET_ESP32S3
     82     #define SPI_PORT FSPI
     83   #endif
     84 #endif
     85 
     86 #ifdef RPI_DISPLAY_TYPE
     87   #define CMD_BITS (16-1)
     88 #else
     89   #define CMD_BITS (8-1)
     90 #endif
     91 
     92 // Initialise processor specific SPI functions, used by init()
     93 #define INIT_TFT_DATA_BUS // Not used
     94 
     95 // Define a generic flag for 8 bit parallel
     96 #if defined (ESP32_PARALLEL) // Specific to ESP32 for backwards compatibility
     97   #if !defined (TFT_PARALLEL_8_BIT)
     98     #define TFT_PARALLEL_8_BIT // Generic parallel flag
     99   #endif
    100 #endif
    101 
    102 // Ensure ESP32 specific flag is defined for 8 bit parallel
    103 #if defined (TFT_PARALLEL_8_BIT)
    104   #if !defined (ESP32_PARALLEL)
    105     #define ESP32_PARALLEL
    106   #endif
    107 #endif
    108 
    109 #if !defined(DISABLE_ALL_LIBRARY_WARNINGS) && defined (ESP32_PARALLEL)
    110  #warning >>>>------>> DMA is not supported in parallel mode
    111 #endif
    112 
    113 // Processor specific code used by SPI bus transaction startWrite and endWrite functions
    114 #if !defined (ESP32_PARALLEL)
    115   #define _spi_cmd       (volatile uint32_t*)(SPI_CMD_REG(SPI_PORT))
    116   #define _spi_user      (volatile uint32_t*)(SPI_USER_REG(SPI_PORT))
    117   #define _spi_mosi_dlen (volatile uint32_t*)(SPI_MOSI_DLEN_REG(SPI_PORT))
    118   #define _spi_w         (volatile uint32_t*)(SPI_W0_REG(SPI_PORT))
    119 
    120   #if (TFT_SPI_MODE == SPI_MODE1) || (TFT_SPI_MODE == SPI_MODE2)
    121     #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI | SPI_CK_OUT_EDGE
    122     #define SET_BUS_READ_MODE  *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN | SPI_CK_OUT_EDGE
    123   #else
    124     #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI
    125     #define SET_BUS_READ_MODE  *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN
    126   #endif
    127 #else
    128     // Not applicable to parallel bus
    129     #define SET_BUS_WRITE_MODE
    130     #define SET_BUS_READ_MODE
    131 #endif
    132 
    133 // Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions
    134 #if !defined(TFT_PARALLEL_8_BIT) && !defined(SPI_18BIT_DRIVER)
    135   #define ESP32_DMA
    136   // Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions
    137   #define DMA_BUSY_CHECK  dmaWait()
    138 #else
    139   #define DMA_BUSY_CHECK
    140 #endif
    141 
    142 #if defined(TFT_PARALLEL_8_BIT)
    143   #define SPI_BUSY_CHECK
    144 #else
    145   #define SPI_BUSY_CHECK while (*_spi_cmd&SPI_USR)
    146 #endif
    147 
    148 // If smooth font is used then it is likely SPIFFS will be needed
    149 #ifdef SMOOTH_FONT
    150   // Call up the SPIFFS (SPI FLASH Filing System) for the anti-aliased fonts
    151   #define FS_NO_GLOBALS
    152   #include <FS.h>
    153   #include "SPIFFS.h" // ESP32 only
    154   #define FONT_FS_AVAILABLE
    155 #endif
    156 
    157 ////////////////////////////////////////////////////////////////////////////////////////
    158 // Define the DC (TFT Data/Command or Register Select (RS))pin drive code
    159 ////////////////////////////////////////////////////////////////////////////////////////
    160 #ifndef TFT_DC
    161   #define DC_C // No macro allocated so it generates no code
    162   #define DC_D // No macro allocated so it generates no code
    163 #else
    164   #if defined (TFT_PARALLEL_8_BIT)
    165     // TFT_DC, by design, must be in range 0-31 for single register parallel write
    166     #if (TFT_DC >= 0) &&  (TFT_DC < 32)
    167       #define DC_C GPIO.out_w1tc = (1 << TFT_DC)
    168       #define DC_D GPIO.out_w1ts = (1 << TFT_DC)
    169     #elif (TFT_DC >= 32)
    170       #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC- 32))
    171       #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC- 32))
    172     #else
    173       #define DC_C
    174       #define DC_D
    175     #endif
    176   #else
    177     #if (TFT_DC >= 32)
    178       #ifdef RPI_DISPLAY_TYPE  // RPi displays need a slower DC change
    179         #define DC_C GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); \
    180                      GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))
    181         #define DC_D GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); \
    182                      GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))
    183       #else
    184         #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))
    185         #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))
    186       #endif
    187     #elif (TFT_DC >= 0)
    188       #if defined (RPI_DISPLAY_TYPE)
    189         #if defined (ILI9486_DRIVER)
    190           // RPi ILI9486 display needs a slower DC change
    191           #define DC_C GPIO.out_w1tc = (1 << TFT_DC); \
    192                        GPIO.out_w1tc = (1 << TFT_DC)
    193           #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \
    194                        GPIO.out_w1ts = (1 << TFT_DC)
    195         #else
    196           // Other RPi displays need a slower C->D change
    197           #define DC_C GPIO.out_w1tc = (1 << TFT_DC)
    198           #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \
    199                        GPIO.out_w1ts = (1 << TFT_DC)
    200         #endif
    201       #else
    202         #define DC_C GPIO.out_w1tc = (1 << TFT_DC)//;GPIO.out_w1tc = (1 << TFT_DC)
    203         #define DC_D GPIO.out_w1ts = (1 << TFT_DC)//;GPIO.out_w1ts = (1 << TFT_DC)
    204       #endif
    205     #else
    206       #define DC_C
    207       #define DC_D
    208     #endif
    209   #endif
    210 #endif
    211 
    212 ////////////////////////////////////////////////////////////////////////////////////////
    213 // Define the CS (TFT chip select) pin drive code
    214 ////////////////////////////////////////////////////////////////////////////////////////
    215 #ifndef TFT_CS
    216   #define TFT_CS -1  // Keep DMA code happy
    217   #define CS_L       // No macro allocated so it generates no code
    218   #define CS_H       // No macro allocated so it generates no code
    219 #else
    220   #if defined (TFT_PARALLEL_8_BIT)
    221     #if TFT_CS >= 32
    222         #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32))
    223         #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))
    224     #elif TFT_CS >= 0
    225         #define CS_L GPIO.out_w1tc = (1 << TFT_CS)
    226         #define CS_H GPIO.out_w1ts = (1 << TFT_CS)
    227     #else
    228       #define CS_L
    229       #define CS_H
    230     #endif
    231   #else
    232     #if (TFT_CS >= 32)
    233       #ifdef RPI_DISPLAY_TYPE  // RPi display needs a slower CS change
    234         #define CS_L GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); \
    235                      GPIO.out1_w1tc.val = (1 << (TFT_CS - 32))
    236         #define CS_H GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \
    237                      GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))
    238       #else
    239         #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); GPIO.out1_w1tc.val = (1 << (TFT_CS - 32))
    240         #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))
    241       #endif
    242     #elif (TFT_CS >= 0)
    243       #ifdef RPI_DISPLAY_TYPE  // RPi display needs a slower CS change
    244         #define CS_L GPIO.out_w1ts = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS)
    245         #define CS_H GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1ts = (1 << TFT_CS)
    246       #else
    247         #define CS_L GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS)
    248         #define CS_H GPIO.out_w1ts = (1 << TFT_CS)//;GPIO.out_w1ts = (1 << TFT_CS)
    249       #endif
    250     #else
    251       #define CS_L
    252       #define CS_H
    253     #endif
    254   #endif
    255 #endif
    256 
    257 ////////////////////////////////////////////////////////////////////////////////////////
    258 // Define the WR (TFT Write) pin drive code
    259 ////////////////////////////////////////////////////////////////////////////////////////
    260 #if defined (TFT_WR)
    261   #if (TFT_WR >= 32)
    262     // Note: it will be ~1.25x faster if the TFT_WR pin uses a GPIO pin lower than 32
    263     #define WR_L GPIO.out1_w1tc.val = (1 << (TFT_WR - 32))
    264     #define WR_H GPIO.out1_w1ts.val = (1 << (TFT_WR - 32))
    265   #elif (TFT_WR >= 0)
    266     // TFT_WR, for best performance, should be in range 0-31 for single register parallel write
    267     #define WR_L GPIO.out_w1tc = (1 << TFT_WR)
    268     #define WR_H GPIO.out_w1ts = (1 << TFT_WR)
    269   #else
    270     #define WR_L
    271     #define WR_H
    272   #endif
    273 #else
    274   #define WR_L
    275   #define WR_H
    276 #endif
    277 
    278 ////////////////////////////////////////////////////////////////////////////////////////
    279 // Define the touch screen chip select pin drive code
    280 ////////////////////////////////////////////////////////////////////////////////////////
    281 #ifndef TOUCH_CS
    282   #define T_CS_L // No macro allocated so it generates no code
    283   #define T_CS_H // No macro allocated so it generates no code
    284 #else // XPT2046 is slow, so use slower digitalWrite here
    285   #define T_CS_L digitalWrite(TOUCH_CS, LOW)
    286   #define T_CS_H digitalWrite(TOUCH_CS, HIGH)
    287 #endif
    288 
    289 ////////////////////////////////////////////////////////////////////////////////////////
    290 // Make sure SPI default pins are assigned if not specified by user or set to -1
    291 ////////////////////////////////////////////////////////////////////////////////////////
    292 #if !defined (TFT_PARALLEL_8_BIT)
    293 
    294   #ifdef USE_HSPI_PORT
    295 
    296     #ifndef TFT_MISO
    297       #define TFT_MISO -1
    298     #endif
    299 
    300     #ifndef TFT_MOSI
    301       #define TFT_MOSI 13
    302     #endif
    303     #if (TFT_MOSI == -1)
    304       #undef TFT_MOSI
    305       #define TFT_MOSI 13
    306     #endif
    307 
    308     #ifndef TFT_SCLK
    309       #define TFT_SCLK 14
    310     #endif
    311     #if (TFT_SCLK == -1)
    312       #undef TFT_SCLK
    313       #define TFT_SCLK 14
    314     #endif
    315 
    316   #else // VSPI port
    317 
    318     #ifndef TFT_MISO
    319       #define TFT_MISO -1
    320     #endif
    321 
    322     #ifndef TFT_MOSI
    323       #define TFT_MOSI 23
    324     #endif
    325     #if (TFT_MOSI == -1)
    326       #undef TFT_MOSI
    327       #define TFT_MOSI 23
    328     #endif
    329 
    330     #ifndef TFT_SCLK
    331       #define TFT_SCLK 18
    332     #endif
    333     #if (TFT_SCLK == -1)
    334       #undef TFT_SCLK
    335       #define TFT_SCLK 18
    336     #endif
    337 
    338     #if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32S2)
    339       #if (TFT_MISO == -1)
    340         #undef TFT_MISO
    341         #define TFT_MISO TFT_MOSI
    342       #endif
    343     #endif
    344 
    345   #endif
    346 
    347 #endif
    348 
    349 ////////////////////////////////////////////////////////////////////////////////////////
    350 // Define the parallel bus interface chip pin drive code
    351 ////////////////////////////////////////////////////////////////////////////////////////
    352 #if defined (TFT_PARALLEL_8_BIT)
    353 
    354   #if (TFT_D0 >= 32) // If D0 is a high GPIO assume all other data bits are high GPIO
    355     #define MASK_OFFSET 32
    356     #define GPIO_CLR_REG GPIO.out1_w1tc.val
    357     #define GPIO_SET_REG GPIO.out1_w1ts.val
    358   #else
    359     #define MASK_OFFSET 0
    360     #define GPIO_CLR_REG GPIO.out_w1tc
    361     #define GPIO_SET_REG GPIO.out_w1ts
    362   #endif
    363 
    364   // Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically
    365   // can then use e.g. GPIO.out_w1ts = set_mask(0xFF); to set data bus to 0xFF
    366   #define PARALLEL_INIT_TFT_DATA_BUS               \
    367   for (int32_t c = 0; c<256; c++)                  \
    368   {                                                \
    369     xset_mask[c] = 0;                              \
    370     if ( c & 0x01 ) xset_mask[c] |= (1 << (TFT_D0-MASK_OFFSET)); \
    371     if ( c & 0x02 ) xset_mask[c] |= (1 << (TFT_D1-MASK_OFFSET)); \
    372     if ( c & 0x04 ) xset_mask[c] |= (1 << (TFT_D2-MASK_OFFSET)); \
    373     if ( c & 0x08 ) xset_mask[c] |= (1 << (TFT_D3-MASK_OFFSET)); \
    374     if ( c & 0x10 ) xset_mask[c] |= (1 << (TFT_D4-MASK_OFFSET)); \
    375     if ( c & 0x20 ) xset_mask[c] |= (1 << (TFT_D5-MASK_OFFSET)); \
    376     if ( c & 0x40 ) xset_mask[c] |= (1 << (TFT_D6-MASK_OFFSET)); \
    377     if ( c & 0x80 ) xset_mask[c] |= (1 << (TFT_D7-MASK_OFFSET)); \
    378   }                                                              \
    379 
    380   // Mask for the 8 data bits to set pin directions
    381   #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)))
    382 
    383   #if (TFT_WR >= 32)
    384     #if (TFT_D0 >= 32)
    385       // Data bits and the write line are cleared to 0 in one step (1.25x faster)
    386       #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK | (1 << (TFT_WR-32)))
    387     #elif (TFT_D0 >= 0)
    388       // Data bits and the write line are cleared sequentially
    389       #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK); WR_L
    390     #endif
    391   #elif (TFT_WR >= 0)
    392     #if (TFT_D0 >= 32)
    393       // Data bits and the write line are cleared sequentially
    394       #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK); WR_L
    395     #elif (TFT_D0 >= 0)
    396       // Data bits and the write line are cleared to 0 in one step (1.25x faster)
    397       #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK | (1 << TFT_WR))
    398     #endif
    399   #else
    400     #define GPIO_OUT_CLR_MASK
    401   #endif
    402 
    403   // A lookup table is used to set the different bit patterns, this uses 1kByte of RAM
    404   #define set_mask(C) xset_mask[C] // 63fps Sprite rendering test 33% faster, graphicstest only 1.8% faster than shifting in real time
    405 
    406   // Real-time shifting alternative to above to save 1KByte RAM, 47 fps Sprite rendering test
    407   /*#define set_mask(C) (((C)&0x80)>>7)<<TFT_D7 | (((C)&0x40)>>6)<<TFT_D6 | (((C)&0x20)>>5)<<TFT_D5 | (((C)&0x10)>>4)<<TFT_D4 | \
    408                         (((C)&0x08)>>3)<<TFT_D3 | (((C)&0x04)>>2)<<TFT_D2 | (((C)&0x02)>>1)<<TFT_D1 | (((C)&0x01)>>0)<<TFT_D0
    409   //*/
    410 
    411   // Write 8 bits to TFT
    412   #define tft_Write_8(C)  GPIO_CLR_REG =  GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t)(C)); WR_H
    413 
    414   #if defined (SSD1963_DRIVER)
    415 
    416     // Write 18 bit color to TFT
    417     #define tft_Write_16(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0xF800)>> 8)); WR_H; \
    418                             GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x07E0)>> 3)); WR_H; \
    419                             GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x001F)<< 3)); WR_H
    420 
    421     // 18 bit color write with swapped bytes
    422     #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap)
    423 
    424   #else
    425 
    426     #ifdef PSEUDO_16_BIT
    427       // One write strobe for both bytes
    428       #define tft_Write_16(C)  GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H
    429       #define tft_Write_16S(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H
    430     #else
    431       // Write 16 bits to TFT
    432       #define tft_Write_16(C) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H; \
    433                               GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H
    434 
    435       // 16 bit write with swapped bytes
    436       #define tft_Write_16S(C) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H; \
    437                                GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H
    438     #endif
    439 
    440   #endif
    441 
    442   // Write 32 bits to TFT
    443   #define tft_Write_32(C) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 24)); WR_H; \
    444                           GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 16)); WR_H; \
    445                           GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >>  8)); WR_H; \
    446                           GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >>  0)); WR_H
    447 
    448   // Write two concatenated 16 bit values to TFT
    449   #define tft_Write_32C(C,D) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H; \
    450                              GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H; \
    451                              GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((D) >> 8)); WR_H; \
    452                              GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((D) >> 0)); WR_H
    453 
    454   // Write 16 bit value twice to TFT - used by drawPixel()
    455   #define tft_Write_32D(C) GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H; \
    456                            GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H; \
    457                            GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 8)); WR_H; \
    458                            GPIO_CLR_REG = GPIO_OUT_CLR_MASK; GPIO_SET_REG = set_mask((uint8_t) ((C) >> 0)); WR_H
    459 
    460    // Read pin
    461   #ifdef TFT_RD
    462     #if (TFT_RD >= 32)
    463       #define RD_L GPIO.out1_w1tc.val = (1 << (TFT_RD - 32))
    464       #define RD_H GPIO.out1_w1ts.val = (1 << (TFT_RD - 32))
    465     #elif (TFT_RD >= 0)
    466       #define RD_L GPIO.out_w1tc = (1 << TFT_RD)
    467       //#define RD_L digitalWrite(TFT_WR, LOW)
    468       #define RD_H GPIO.out_w1ts = (1 << TFT_RD)
    469       //#define RD_H digitalWrite(TFT_WR, HIGH)
    470     #else
    471       #define RD_L
    472       #define RD_H
    473     #endif
    474   #else
    475     #define TFT_RD -1
    476     #define RD_L
    477     #define RD_H
    478   #endif
    479 
    480 ////////////////////////////////////////////////////////////////////////////////////////
    481 // Macros to write commands/pixel colour data to a SPI ILI948x TFT
    482 ////////////////////////////////////////////////////////////////////////////////////////
    483 #elif  defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
    484 
    485   // Write 8 bits to TFT
    486   #define tft_Write_8(C)   spi.transfer(C)
    487 
    488   // Convert 16 bit colour to 18 bit and write in 3 bytes
    489   #define tft_Write_16(C)  spi.transfer(((C) & 0xF800)>>8); \
    490                            spi.transfer(((C) & 0x07E0)>>3); \
    491                            spi.transfer(((C) & 0x001F)<<3)
    492 
    493   // Future option for transfer without wait
    494   #define tft_Write_16N(C) tft_Write_16(C)
    495 
    496   // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
    497   #define tft_Write_16S(C) spi.transfer((C) & 0xF8); \
    498                            spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \
    499                            spi.transfer(((C) & 0x1F00)>>5)
    500 
    501   // Write 32 bits to TFT
    502   #define tft_Write_32(C)  spi.write32(C)
    503 
    504   // Write two concatenated 16 bit values to TFT
    505   #define tft_Write_32C(C,D) spi.write32((C)<<16 | (D))
    506 
    507   // Write 16 bit value twice to TFT
    508   #define tft_Write_32D(C)  spi.write32((C)<<16 | (C))
    509 
    510 ////////////////////////////////////////////////////////////////////////////////////////
    511 // Macros to write commands/pixel colour data to an Raspberry Pi TFT
    512 ////////////////////////////////////////////////////////////////////////////////////////
    513 #elif  defined (RPI_DISPLAY_TYPE)
    514   // ESP32-S3 low level SPI writes for 8, 16 and 32 bit values
    515   // to avoid the function call overhead
    516   #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1;    \
    517                                *_spi_w = D;              \
    518                                *_spi_cmd = SPI_UPDATE;   \
    519                         while (*_spi_cmd & SPI_UPDATE);  \
    520                                *_spi_cmd = SPI_USR;      \
    521                         while (*_spi_cmd & SPI_USR);
    522 
    523   // Write 8 bits
    524   #define tft_Write_8(C) TFT_WRITE_BITS((C)<<8, 16)
    525 
    526   // Write 16 bits with corrected endianness for 16 bit colours
    527   #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16)
    528 
    529   // Future option for transfer without wait
    530   #define tft_Write_16N(C) tft_Write_16(C)
    531 
    532   // Write 16 bits
    533   #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16)
    534 
    535   // Write 32 bits
    536   #define tft_Write_32(C) TFT_WRITE_BITS(C, 32)
    537 
    538   // Write two address coordinates
    539   #define tft_Write_32C(C,D)  TFT_WRITE_BITS((C)<<24 | (C), 32); \
    540                               TFT_WRITE_BITS((D)<<24 | (D), 32)
    541 
    542   // Write same value twice
    543   #define tft_Write_32D(C) tft_Write_32C(C,C)
    544 
    545 ////////////////////////////////////////////////////////////////////////////////////////
    546 // Macros for all other SPI displays
    547 ////////////////////////////////////////////////////////////////////////////////////////
    548 #else
    549   #if !defined(CONFIG_IDF_TARGET_ESP32S3)
    550     #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1;  \
    551                                *_spi_w = D;              \
    552                                *_spi_cmd = SPI_USR;      \
    553                         while (*_spi_cmd & SPI_USR);
    554   #else
    555     #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1;  \
    556                                *_spi_w = D;              \
    557                                *_spi_cmd = SPI_UPDATE;   \
    558                         while (*_spi_cmd & SPI_UPDATE);  \
    559                                *_spi_cmd = SPI_USR;      \
    560                         while (*_spi_cmd & SPI_USR);
    561   #endif
    562   // Write 8 bits
    563   #define tft_Write_8(C) TFT_WRITE_BITS(C, 8)
    564 
    565   // Write 16 bits with corrected endianness for 16 bit colours
    566   #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16)
    567 
    568   // Future option for transfer without wait
    569   #if !defined(CONFIG_IDF_TARGET_ESP32S3)
    570     #define tft_Write_16N(C) *_spi_mosi_dlen = 16-1;    \
    571                            *_spi_w = ((C)<<8 | (C)>>8); \
    572                            *_spi_cmd = SPI_USR;
    573   #else
    574     #define tft_Write_16N(C) *_spi_mosi_dlen = 16-1;    \
    575                            *_spi_w = ((C)<<8 | (C)>>8); \
    576                            *_spi_cmd = SPI_UPDATE;      \
    577                     while (*_spi_cmd & SPI_UPDATE);     \
    578                            *_spi_cmd = SPI_USR;
    579   #endif
    580 
    581   // Write 16 bits
    582   #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16)
    583 
    584   // Write 32 bits
    585   #define tft_Write_32(C) TFT_WRITE_BITS(C, 32)
    586 
    587   // Write two address coordinates
    588   #define tft_Write_32C(C,D)  TFT_WRITE_BITS((uint16_t)((D)<<8 | (D)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32)
    589 
    590   // Write same value twice
    591   #define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32)
    592 
    593 #endif
    594 
    595 #ifndef tft_Write_16N
    596   #define tft_Write_16N tft_Write_16
    597 #endif
    598 
    599 ////////////////////////////////////////////////////////////////////////////////////////
    600 // Macros to read from display using SPI or software SPI
    601 ////////////////////////////////////////////////////////////////////////////////////////
    602 #if !defined (TFT_PARALLEL_8_BIT)
    603   // Read from display using SPI or software SPI
    604   // Use a SPI read transfer
    605   #define tft_Read_8() spi.transfer(0)
    606 #endif
    607 
    608 // Concatenate a byte sequence A,B,C,D to CDAB, P is a uint8_t pointer
    609 #define DAT8TO32(P) ( (uint32_t)P[0]<<8 | P[1] | P[2]<<24 | P[3]<<16 )
    610 
    611 #endif // Header end