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.c (32680B)

      1         ////////////////////////////////////////////////////
      2         // TFT_eSPI driver functions for ESP32 processors //
      3         ////////////////////////////////////////////////////
      4 
      5 // Temporarily a separate file to TFT_eSPI_ESP32.c until board package low level API stabilises
      6 
      7 ////////////////////////////////////////////////////////////////////////////////////////
      8 // Global variables
      9 ////////////////////////////////////////////////////////////////////////////////////////
     10 
     11 // Select the SPI port to use, ESP32 has 2 options
     12 #if !defined (TFT_PARALLEL_8_BIT)
     13   #ifdef CONFIG_IDF_TARGET_ESP32
     14     #ifdef USE_HSPI_PORT
     15       SPIClass spi = SPIClass(HSPI);
     16     #elif defined(USE_FSPI_PORT)
     17       SPIClass spi = SPIClass(FSPI);
     18     #else // use default VSPI port
     19       SPIClass spi = SPIClass(VSPI);
     20     #endif
     21   #else
     22     #ifdef USE_HSPI_PORT
     23       SPIClass spi = SPIClass(HSPI);
     24     #elif defined(USE_FSPI_PORT)
     25       SPIClass spi = SPIClass(FSPI);
     26     #else // use FSPI port
     27       SPIClass& spi = SPI;
     28     #endif
     29   #endif
     30 #endif
     31 
     32 #ifdef ESP32_DMA
     33   // DMA SPA handle
     34   spi_device_handle_t dmaHAL;
     35   #ifdef CONFIG_IDF_TARGET_ESP32
     36     #define DMA_CHANNEL 1
     37     #ifdef USE_HSPI_PORT
     38       spi_host_device_t spi_host = HSPI_HOST;
     39     #elif defined(USE_FSPI_PORT)
     40       spi_host_device_t spi_host = SPI_HOST;
     41     #else // use VSPI port
     42       spi_host_device_t spi_host = VSPI_HOST;
     43     #endif
     44   #else
     45     #ifdef USE_HSPI_PORT
     46       #define DMA_CHANNEL SPI_DMA_CH_AUTO
     47       spi_host_device_t spi_host = SPI3_HOST;
     48     #else // use FSPI port
     49       #define DMA_CHANNEL SPI_DMA_CH_AUTO
     50       spi_host_device_t spi_host = SPI2_HOST;
     51     #endif
     52   #endif
     53 #endif
     54 
     55 ////////////////////////////////////////////////////////////////////////////////////////
     56 #if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT)
     57 ////////////////////////////////////////////////////////////////////////////////////////
     58 
     59 /***************************************************************************************
     60 ** Function name:           beginSDA - FPSI port only
     61 ** Description:             Detach MOSI and attach MISO to SDA for reads
     62 ***************************************************************************************/
     63 void TFT_eSPI::begin_SDA_Read(void)
     64 {
     65   gpio_set_direction((gpio_num_t)TFT_MOSI, GPIO_MODE_INPUT);
     66   pinMatrixInAttach(TFT_MOSI, FSPIQ_IN_IDX, false);
     67   SET_BUS_READ_MODE;
     68 }
     69 
     70 /***************************************************************************************
     71 ** Function name:           endSDA - FPSI port only
     72 ** Description:             Attach MOSI to SDA and detach MISO for writes
     73 ***************************************************************************************/
     74 void TFT_eSPI::end_SDA_Read(void)
     75 {
     76   gpio_set_direction((gpio_num_t)TFT_MOSI, GPIO_MODE_OUTPUT);
     77   pinMatrixOutAttach(TFT_MOSI, FSPID_OUT_IDX, false, false);
     78   SET_BUS_WRITE_MODE;
     79 }
     80 ////////////////////////////////////////////////////////////////////////////////////////
     81 #endif // #if defined (TFT_SDA_READ)
     82 ////////////////////////////////////////////////////////////////////////////////////////
     83 
     84 
     85 /***************************************************************************************
     86 ** Function name:           read byte  - supports class functions
     87 ** Description:             Read a byte from ESP32 8 bit data port
     88 ***************************************************************************************/
     89 // Parallel bus MUST be set to input before calling this function!
     90 uint8_t TFT_eSPI::readByte(void)
     91 {
     92   uint8_t b = 0xAA;
     93 
     94 #if defined (TFT_PARALLEL_8_BIT)
     95   RD_L;
     96   b  = gpio_get_level((gpio_num_t)TFT_D0); // Read three times to allow for bus access time
     97   b  = gpio_get_level((gpio_num_t)TFT_D0);
     98   b  = gpio_get_level((gpio_num_t)TFT_D0); // Data should be stable now
     99 
    100   // Check GPIO bits used and build value
    101   b  = (gpio_get_level((gpio_num_t)TFT_D0) << 0);
    102   b |= (gpio_get_level((gpio_num_t)TFT_D1) << 1);
    103   b |= (gpio_get_level((gpio_num_t)TFT_D2) << 2);
    104   b |= (gpio_get_level((gpio_num_t)TFT_D3) << 3);
    105   b |= (gpio_get_level((gpio_num_t)TFT_D4) << 4);
    106   b |= (gpio_get_level((gpio_num_t)TFT_D5) << 5);
    107   b |= (gpio_get_level((gpio_num_t)TFT_D6) << 6);
    108   b |= (gpio_get_level((gpio_num_t)TFT_D7) << 7);
    109   RD_H;
    110 #endif
    111 
    112   return b;
    113 }
    114 
    115 ////////////////////////////////////////////////////////////////////////////////////////
    116 #ifdef TFT_PARALLEL_8_BIT
    117 ////////////////////////////////////////////////////////////////////////////////////////
    118 
    119 /***************************************************************************************
    120 ** Function name:           GPIO direction control  - supports class functions
    121 ** Description:             Set parallel bus to INPUT or OUTPUT
    122 ***************************************************************************************/
    123 void TFT_eSPI::busDir(uint32_t mask, uint8_t mode)
    124 {
    125   // Arduino generic native function
    126   pinMode(TFT_D0, mode);
    127   pinMode(TFT_D1, mode);
    128   pinMode(TFT_D2, mode);
    129   pinMode(TFT_D3, mode);
    130   pinMode(TFT_D4, mode);
    131   pinMode(TFT_D5, mode);
    132   pinMode(TFT_D6, mode);
    133   pinMode(TFT_D7, mode);
    134 }
    135 
    136 /***************************************************************************************
    137 ** Function name:           GPIO direction control  - supports class functions
    138 ** Description:             Set ESP32 GPIO pin to input or output (set high) ASAP
    139 ***************************************************************************************/
    140 void TFT_eSPI::gpioMode(uint8_t gpio, uint8_t mode)
    141 {
    142   pinMode(gpio, mode);
    143   digitalWrite(gpio, HIGH);
    144 }
    145 ////////////////////////////////////////////////////////////////////////////////////////
    146 #endif // #ifdef TFT_PARALLEL_8_BIT
    147 ////////////////////////////////////////////////////////////////////////////////////////
    148 
    149 
    150 ////////////////////////////////////////////////////////////////////////////////////////
    151 #if defined (RPI_WRITE_STROBE) && !defined (TFT_PARALLEL_8_BIT) // Code for RPi TFT
    152 ////////////////////////////////////////////////////////////////////////////////////////
    153 
    154 /***************************************************************************************
    155 ** Function name:           pushBlock - for ESP32 or ESP8266 RPi TFT
    156 ** Description:             Write a block of pixels of the same colour
    157 ***************************************************************************************/
    158 void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
    159 {
    160   uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color };
    161   if(len) spi.writePattern(&colorBin[0], 2, 1); len--;
    162   while(len--) {WR_L; WR_H;}
    163 }
    164 
    165 /***************************************************************************************
    166 ** Function name:           pushPixels - for ESP32 or ESP8266 RPi TFT
    167 ** Description:             Write a sequence of pixels
    168 ***************************************************************************************/
    169 void TFT_eSPI::pushPixels(const void* data_in, uint32_t len)
    170 {
    171   uint8_t *data = (uint8_t*)data_in;
    172 
    173   if(_swapBytes) {
    174       while ( len-- ) {tft_Write_16(*data); data++;}
    175       return;
    176   }
    177 
    178   while ( len >=64 ) {spi.writePattern(data, 64, 1); data += 64; len -= 64; }
    179   if (len) spi.writePattern(data, len, 1);
    180 }
    181 
    182 ////////////////////////////////////////////////////////////////////////////////////////
    183 #elif !defined (SPI_18BIT_DRIVER) && !defined (TFT_PARALLEL_8_BIT) // Most SPI displays
    184 ////////////////////////////////////////////////////////////////////////////////////////
    185 
    186 /***************************************************************************************
    187 ** Function name:           pushBlock - for ESP32
    188 ** Description:             Write a block of pixels of the same colour
    189 ***************************************************************************************/
    190 /*
    191 void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){
    192 
    193   uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8);
    194   bool empty = true;
    195   volatile uint32_t* spi_w = (volatile uint32_t*)_spi_w;
    196   if (len > 31)
    197   {
    198     *_spi_mosi_dlen =  511;
    199     spi_w[0]  = color32;
    200     spi_w[1]  = color32;
    201     spi_w[2]  = color32;
    202     spi_w[3]  = color32;
    203     spi_w[4]  = color32;
    204     spi_w[5]  = color32;
    205     spi_w[6]  = color32;
    206     spi_w[7]  = color32;
    207     spi_w[8]  = color32;
    208     spi_w[9]  = color32;
    209     spi_w[10] = color32;
    210     spi_w[11] = color32;
    211     spi_w[12] = color32;
    212     spi_w[13] = color32;
    213     spi_w[14] = color32;
    214     spi_w[15] = color32;
    215     while(len>31)
    216     {
    217       while ((*_spi_cmd)&SPI_USR);
    218       *_spi_cmd = SPI_USR;
    219       len -= 32;
    220     }
    221     empty = false;
    222   }
    223 
    224   if (len)
    225   {
    226     if(empty) {
    227       for (uint32_t i=0; i <= len; i+=2) *spi_w++ = color32;
    228     }
    229     len = (len << 4) - 1;
    230     while (*_spi_cmd&SPI_USR);
    231     *_spi_mosi_dlen = len;
    232     *_spi_cmd = SPI_USR;
    233   }
    234   while ((*_spi_cmd)&SPI_USR); // Move to later in code to use transmit time usefully?
    235 }
    236 //*/
    237 //*
    238 void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){
    239 
    240   volatile uint32_t* spi_w = _spi_w;
    241   uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8);
    242   uint32_t i = 0;
    243   uint32_t rem = len & 0x1F;
    244   len =  len - rem;
    245 
    246   // Start with partial buffer pixels
    247   if (rem)
    248   {
    249     while (*_spi_cmd&SPI_USR);
    250     for (i=0; i < rem; i+=2) *spi_w++ = color32;
    251     *_spi_mosi_dlen = (rem << 4) - 1;
    252 #if CONFIG_IDF_TARGET_ESP32S3
    253     *_spi_cmd = SPI_UPDATE;
    254     while (*_spi_cmd & SPI_UPDATE);
    255 #endif
    256     *_spi_cmd = SPI_USR;
    257     if (!len) return; //{while (*_spi_cmd&SPI_USR); return; }
    258     i = i>>1; while(i++<16) *spi_w++ = color32;
    259   }
    260 
    261   while (*_spi_cmd&SPI_USR);
    262   if (!rem) while (i++<16) *spi_w++ = color32;
    263   *_spi_mosi_dlen =  511;
    264 
    265   // End with full buffer to maximise useful time for downstream code
    266   while(len)
    267   {
    268     while (*_spi_cmd&SPI_USR);
    269 #if CONFIG_IDF_TARGET_ESP32S3
    270     *_spi_cmd = SPI_UPDATE;
    271     while (*_spi_cmd & SPI_UPDATE);
    272 #endif
    273     *_spi_cmd = SPI_USR;
    274     len -= 32;
    275   }
    276 
    277   // Do not wait here
    278   //while (*_spi_cmd&SPI_USR);
    279 }
    280 //*/
    281 /***************************************************************************************
    282 ** Function name:           pushSwapBytePixels - for ESP32
    283 ** Description:             Write a sequence of pixels with swapped bytes
    284 ***************************************************************************************/
    285 void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
    286 
    287   uint8_t* data = (uint8_t*)data_in;
    288   uint32_t color[16];
    289 
    290   if (len > 31)
    291   {
    292     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511);
    293     while(len>31)
    294     {
    295       uint32_t i = 0;
    296       while(i<16)
    297       {
    298         color[i++] = DAT8TO32(data);
    299         data+=4;
    300       }
    301       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
    302       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT),  color[0]);
    303       WRITE_PERI_REG(SPI_W1_REG(SPI_PORT),  color[1]);
    304       WRITE_PERI_REG(SPI_W2_REG(SPI_PORT),  color[2]);
    305       WRITE_PERI_REG(SPI_W3_REG(SPI_PORT),  color[3]);
    306       WRITE_PERI_REG(SPI_W4_REG(SPI_PORT),  color[4]);
    307       WRITE_PERI_REG(SPI_W5_REG(SPI_PORT),  color[5]);
    308       WRITE_PERI_REG(SPI_W6_REG(SPI_PORT),  color[6]);
    309       WRITE_PERI_REG(SPI_W7_REG(SPI_PORT),  color[7]);
    310       WRITE_PERI_REG(SPI_W8_REG(SPI_PORT),  color[8]);
    311       WRITE_PERI_REG(SPI_W9_REG(SPI_PORT),  color[9]);
    312       WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), color[10]);
    313       WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), color[11]);
    314       WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), color[12]);
    315       WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), color[13]);
    316       WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), color[14]);
    317       WRITE_PERI_REG(SPI_W15_REG(SPI_PORT), color[15]);
    318 #if CONFIG_IDF_TARGET_ESP32S3
    319       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE);
    320       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE);
    321 #endif
    322       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
    323       len -= 32;
    324     }
    325   }
    326 
    327   if (len > 15)
    328   {
    329     uint32_t i = 0;
    330     while(i<8)
    331     {
    332       color[i++] = DAT8TO32(data);
    333       data+=4;
    334     }
    335     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
    336     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 255);
    337     WRITE_PERI_REG(SPI_W0_REG(SPI_PORT),  color[0]);
    338     WRITE_PERI_REG(SPI_W1_REG(SPI_PORT),  color[1]);
    339     WRITE_PERI_REG(SPI_W2_REG(SPI_PORT),  color[2]);
    340     WRITE_PERI_REG(SPI_W3_REG(SPI_PORT),  color[3]);
    341     WRITE_PERI_REG(SPI_W4_REG(SPI_PORT),  color[4]);
    342     WRITE_PERI_REG(SPI_W5_REG(SPI_PORT),  color[5]);
    343     WRITE_PERI_REG(SPI_W6_REG(SPI_PORT),  color[6]);
    344     WRITE_PERI_REG(SPI_W7_REG(SPI_PORT),  color[7]);
    345 #if CONFIG_IDF_TARGET_ESP32S3
    346     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE);
    347     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE);
    348 #endif
    349     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
    350     len -= 16;
    351   }
    352 
    353   if (len)
    354   {
    355     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
    356     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (len << 4) - 1);
    357     for (uint32_t i=0; i <= (len<<1); i+=4) {
    358       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT)+i, DAT8TO32(data)); data+=4;
    359     }
    360 #if CONFIG_IDF_TARGET_ESP32S3
    361     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE);
    362     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE);
    363 #endif
    364     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
    365   }
    366   while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
    367 
    368 }
    369 
    370 /***************************************************************************************
    371 ** Function name:           pushPixels - for ESP32
    372 ** Description:             Write a sequence of pixels
    373 ***************************************************************************************/
    374 void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
    375 
    376   if(_swapBytes) {
    377     pushSwapBytePixels(data_in, len);
    378     return;
    379   }
    380 
    381   uint32_t *data = (uint32_t*)data_in;
    382 
    383   if (len > 31)
    384   {
    385     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511);
    386     while(len>31)
    387     {
    388       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
    389       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT),  *data++);
    390       WRITE_PERI_REG(SPI_W1_REG(SPI_PORT),  *data++);
    391       WRITE_PERI_REG(SPI_W2_REG(SPI_PORT),  *data++);
    392       WRITE_PERI_REG(SPI_W3_REG(SPI_PORT),  *data++);
    393       WRITE_PERI_REG(SPI_W4_REG(SPI_PORT),  *data++);
    394       WRITE_PERI_REG(SPI_W5_REG(SPI_PORT),  *data++);
    395       WRITE_PERI_REG(SPI_W6_REG(SPI_PORT),  *data++);
    396       WRITE_PERI_REG(SPI_W7_REG(SPI_PORT),  *data++);
    397       WRITE_PERI_REG(SPI_W8_REG(SPI_PORT),  *data++);
    398       WRITE_PERI_REG(SPI_W9_REG(SPI_PORT),  *data++);
    399       WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), *data++);
    400       WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), *data++);
    401       WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), *data++);
    402       WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), *data++);
    403       WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), *data++);
    404       WRITE_PERI_REG(SPI_W15_REG(SPI_PORT), *data++);
    405 #if CONFIG_IDF_TARGET_ESP32S3
    406       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE);
    407       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE);
    408 #endif
    409       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
    410       len -= 32;
    411     }
    412   }
    413 
    414   if (len)
    415   {
    416     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
    417     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (len << 4) - 1);
    418     for (uint32_t i=0; i <= (len<<1); i+=4) WRITE_PERI_REG((SPI_W0_REG(SPI_PORT) + i), *data++);
    419 #if CONFIG_IDF_TARGET_ESP32S3
    420       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE);
    421       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE);
    422 #endif
    423     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
    424   }
    425   while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
    426 }
    427 
    428 ////////////////////////////////////////////////////////////////////////////////////////
    429 #elif defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
    430 ////////////////////////////////////////////////////////////////////////////////////////
    431 
    432 /***************************************************************************************
    433 ** Function name:           pushBlock - for ESP32 and 3 byte RGB display
    434 ** Description:             Write a block of pixels of the same colour
    435 ***************************************************************************************/
    436 void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
    437 {
    438   // Split out the colours
    439   uint32_t r = (color & 0xF800)>>8;
    440   uint32_t g = (color & 0x07E0)<<5;
    441   uint32_t b = (color & 0x001F)<<19;
    442   // Concatenate 4 pixels into three 32 bit blocks
    443   uint32_t r0 = r<<24 | b | g | r;
    444   uint32_t r1 = r0>>8 | g<<16;
    445   uint32_t r2 = r1>>8 | b<<8;
    446 
    447   if (len > 19)
    448   {
    449     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 479);
    450 
    451     while(len>19)
    452     {
    453       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
    454       WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0);
    455       WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1);
    456       WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), r2);
    457       WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0);
    458       WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1);
    459       WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2);
    460       WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0);
    461       WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1);
    462       WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2);
    463       WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), r0);
    464       WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), r1);
    465       WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), r2);
    466       WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), r0);
    467       WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), r1);
    468       WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), r2);
    469 #if CONFIG_IDF_TARGET_ESP32S3
    470       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE);
    471       while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE);
    472 #endif
    473       SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
    474       len -= 20;
    475     }
    476     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
    477   }
    478 
    479   if (len)
    480   {
    481     WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (len * 24) - 1);
    482     WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0);
    483     WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1);
    484     WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), r2);
    485     WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0);
    486     WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1);
    487     WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2);
    488     if (len > 8 )
    489     {
    490       WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0);
    491       WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1);
    492       WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2);
    493       WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), r0);
    494       WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), r1);
    495       WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), r2);
    496       WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), r0);
    497       WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), r1);
    498       WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), r2);
    499     }
    500 #if CONFIG_IDF_TARGET_ESP32S3
    501     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_UPDATE);
    502     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_UPDATE);
    503 #endif
    504     SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
    505     while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
    506   }
    507 }
    508 
    509 /***************************************************************************************
    510 ** Function name:           pushPixels - for ESP32 and 3 byte RGB display
    511 ** Description:             Write a sequence of pixels
    512 ***************************************************************************************/
    513 void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
    514 
    515   uint16_t *data = (uint16_t*)data_in;
    516   // ILI9488 write macro is not endianess dependant, hence !_swapBytes
    517   if(!_swapBytes) { while ( len-- ) {tft_Write_16S(*data); data++;} }
    518   else { while ( len-- ) {tft_Write_16(*data); data++;} }
    519 }
    520 
    521 /***************************************************************************************
    522 ** Function name:           pushSwapBytePixels - for ESP32 and 3 byte RGB display
    523 ** Description:             Write a sequence of pixels with swapped bytes
    524 ***************************************************************************************/
    525 void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
    526 
    527   uint16_t *data = (uint16_t*)data_in;
    528   // ILI9488 write macro is not endianess dependant, so swap byte macro not used here
    529   while ( len-- ) {tft_Write_16(*data); data++;}
    530 }
    531 
    532 ////////////////////////////////////////////////////////////////////////////////////////
    533 #elif defined (TFT_PARALLEL_8_BIT) // Now the code for ESP32 8 bit parallel
    534 ////////////////////////////////////////////////////////////////////////////////////////
    535 
    536 /***************************************************************************************
    537 ** Function name:           pushBlock - for ESP32 and parallel display
    538 ** Description:             Write a block of pixels of the same colour
    539 ***************************************************************************************/
    540 void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){
    541   if ( (color >> 8) == (color & 0x00FF) )
    542   { if (!len) return;
    543     tft_Write_16(color);
    544   #if defined (SSD1963_DRIVER)
    545     while (--len) {WR_L; WR_H; WR_L; WR_H; WR_L; WR_H;}
    546   #else
    547     #ifdef PSEUDO_16_BIT
    548       while (--len) {WR_L; WR_H;}
    549     #else
    550       while (--len) {WR_L; WR_H; WR_L; WR_H;}
    551     #endif
    552   #endif
    553   }
    554   else while (len--) {tft_Write_16(color);}
    555 }
    556 
    557 /***************************************************************************************
    558 ** Function name:           pushSwapBytePixels - for ESP32 and parallel display
    559 ** Description:             Write a sequence of pixels with swapped bytes
    560 ***************************************************************************************/
    561 void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
    562 
    563   uint16_t *data = (uint16_t*)data_in;
    564   while ( len-- ) {tft_Write_16(*data); data++;}
    565 }
    566 
    567 /***************************************************************************************
    568 ** Function name:           pushPixels - for ESP32 and parallel display
    569 ** Description:             Write a sequence of pixels
    570 ***************************************************************************************/
    571 void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
    572 
    573   uint16_t *data = (uint16_t*)data_in;
    574   if(_swapBytes) { while ( len-- ) {tft_Write_16(*data); data++; } }
    575   else { while ( len-- ) {tft_Write_16S(*data); data++;} }
    576 }
    577 
    578 ////////////////////////////////////////////////////////////////////////////////////////
    579 #endif // End of display interface specific functions
    580 ////////////////////////////////////////////////////////////////////////////////////////
    581 
    582 
    583 ////////////////////////////////////////////////////////////////////////////////////////
    584 #if defined (ESP32_DMA) && !defined (TFT_PARALLEL_8_BIT) //       DMA FUNCTIONS
    585 ////////////////////////////////////////////////////////////////////////////////////////
    586 
    587 /***************************************************************************************
    588 ** Function name:           dmaBusy
    589 ** Description:             Check if DMA is busy
    590 ***************************************************************************************/
    591 bool TFT_eSPI::dmaBusy(void)
    592 {
    593   if (!DMA_Enabled || !spiBusyCheck) return false;
    594 
    595   spi_transaction_t *rtrans;
    596   esp_err_t ret;
    597   uint8_t checks = spiBusyCheck;
    598   for (int i = 0; i < checks; ++i)
    599   {
    600     ret = spi_device_get_trans_result(dmaHAL, &rtrans, 0);
    601     if (ret == ESP_OK) spiBusyCheck--;
    602   }
    603 
    604   //Serial.print("spiBusyCheck=");Serial.println(spiBusyCheck);
    605   if (spiBusyCheck ==0) return false;
    606   return true;
    607 }
    608 
    609 
    610 /***************************************************************************************
    611 ** Function name:           dmaWait
    612 ** Description:             Wait until DMA is over (blocking!)
    613 ***************************************************************************************/
    614 void TFT_eSPI::dmaWait(void)
    615 {
    616   if (!DMA_Enabled || !spiBusyCheck) return;
    617   spi_transaction_t *rtrans;
    618   esp_err_t ret;
    619   for (int i = 0; i < spiBusyCheck; ++i)
    620   {
    621     ret = spi_device_get_trans_result(dmaHAL, &rtrans, portMAX_DELAY);
    622     assert(ret == ESP_OK);
    623   }
    624   spiBusyCheck = 0;
    625 }
    626 
    627 
    628 /***************************************************************************************
    629 ** Function name:           pushPixelsDMA
    630 ** Description:             Push pixels to TFT (len must be less than 32767)
    631 ***************************************************************************************/
    632 // This will byte swap the original image if setSwapBytes(true) was called by sketch.
    633 void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len)
    634 {
    635   if ((len == 0) || (!DMA_Enabled)) return;
    636 
    637   dmaWait();
    638 
    639   if(_swapBytes) {
    640     for (uint32_t i = 0; i < len; i++) (image[i] = image[i] << 8 | image[i] >> 8);
    641   }
    642 
    643   // DMA byte count for transmit is 64Kbytes maximum, so to avoid this constraint
    644   // small transfers are performed using a blocking call until DMA capacity is reached.
    645   // User sketch can prevent blocking by managing pixel count and splitting into blocks
    646   // of 32768 pixels maximum. (equivalent to an area of ~320 x 100 pixels)
    647   while(len>0x4000) { // Transfer 16 bit pixels in blocks if len*2 over 65536 bytes
    648     pushPixels(image, 0x400);
    649     len -= 0x400; image+= 0x400; // Arbitrarily send 1K pixel blocks (2Kbytes)
    650   }
    651 
    652   esp_err_t ret;
    653   static spi_transaction_t trans;
    654 
    655   memset(&trans, 0, sizeof(spi_transaction_t));
    656 
    657   trans.user = (void *)1;
    658   trans.tx_buffer = image;  //finally send the line data
    659   trans.length = len * 16;        //Data length, in bits
    660   trans.flags = 0;                //SPI_TRANS_USE_TXDATA flag
    661 
    662   ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY);
    663   assert(ret == ESP_OK);
    664 
    665   spiBusyCheck++;
    666 }
    667 
    668 
    669 /***************************************************************************************
    670 ** Function name:           pushImageDMA
    671 ** Description:             Push image to a window (w*h must be less than 65536)
    672 ***************************************************************************************/
    673 // Fixed const data assumed, will NOT clip or swap bytes
    674 void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t const* image)
    675 {
    676   if ((w == 0) || (h == 0) || (!DMA_Enabled)) return;
    677 
    678   uint16_t *buffer = (uint16_t*)image;
    679   uint32_t len = w*h;
    680 
    681   dmaWait();
    682 
    683   setAddrWindow(x, y, w, h);
    684   // DMA byte count for transmit is 64Kbytes maximum, so to avoid this constraint
    685   // small transfers are performed using a blocking call until DMA capacity is reached.
    686   // User sketch can prevent blocking by managing pixel count and splitting into blocks
    687   // of 32768 pixels maximum. (equivalent to an area of ~320 x 100 pixels)
    688   while(len>0x4000) { // Transfer 16 bit pixels in blocks if len*2 over 65536 bytes
    689     pushPixels(buffer, 0x400);
    690     len -= 0x400; buffer+= 0x400; // Arbitrarily send 1K pixel blocks (2Kbytes)
    691   }
    692 
    693   esp_err_t ret;
    694   static spi_transaction_t trans;
    695 
    696   memset(&trans, 0, sizeof(spi_transaction_t));
    697 
    698   trans.user = (void *)1;
    699   trans.tx_buffer = buffer;   //Data pointer
    700   trans.length = len * 16;   //Data length, in bits
    701   trans.flags = 0;           //SPI_TRANS_USE_TXDATA flag
    702 
    703   ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY);
    704   assert(ret == ESP_OK);
    705 
    706   spiBusyCheck++;
    707 }
    708 
    709 
    710 /***************************************************************************************
    711 ** Function name:           pushImageDMA
    712 ** Description:             Push image to a window (w*h must be less than 65536)
    713 ***************************************************************************************/
    714 // This will clip and also swap bytes if setSwapBytes(true) was called by sketch
    715 void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* image, uint16_t* buffer)
    716 {
    717   if ((x >= _vpW) || (y >= _vpH) || (!DMA_Enabled)) return;
    718 
    719   int32_t dx = 0;
    720   int32_t dy = 0;
    721   int32_t dw = w;
    722   int32_t dh = h;
    723 
    724   if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; }
    725   if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; }
    726 
    727   if ((x + dw) > _vpW ) dw = _vpW - x;
    728   if ((y + dh) > _vpH ) dh = _vpH - y;
    729 
    730   if (dw < 1 || dh < 1) return;
    731 
    732   uint32_t len = dw*dh;
    733 
    734   if (buffer == nullptr) {
    735     buffer = image;
    736     dmaWait();
    737   }
    738 
    739   // If image is clipped, copy pixels into a contiguous block
    740   if ( (dw != w) || (dh != h) ) {
    741     if(_swapBytes) {
    742       for (int32_t yb = 0; yb < dh; yb++) {
    743         for (int32_t xb = 0; xb < dw; xb++) {
    744           uint32_t src = xb + dx + w * (yb + dy);
    745           (buffer[xb + yb * dw] = image[src] << 8 | image[src] >> 8);
    746         }
    747       }
    748     }
    749     else {
    750       for (int32_t yb = 0; yb < dh; yb++) {
    751         memcpy((uint8_t*) (buffer + yb * dw), (uint8_t*) (image + dx + w * (yb + dy)), dw << 1);
    752       }
    753     }
    754   }
    755   // else, if a buffer pointer has been provided copy whole image to the buffer
    756   else if (buffer != image || _swapBytes) {
    757     if(_swapBytes) {
    758       for (uint32_t i = 0; i < len; i++) (buffer[i] = image[i] << 8 | image[i] >> 8);
    759     }
    760     else {
    761       memcpy(buffer, image, len*2);
    762     }
    763   }
    764 
    765   if (spiBusyCheck) dmaWait(); // In case we did not wait earlier
    766 
    767   setAddrWindow(x, y, dw, dh);
    768 
    769   // DMA byte count for transmit is 64Kbytes maximum, so to avoid this constraint
    770   // small transfers are performed using a blocking call until DMA capacity is reached.
    771   // User sketch can prevent blocking by managing pixel count and splitting into blocks
    772   // of 32768 pixels maximum. (equivalent to an area of ~320 x 100 pixels)
    773   while(len>0x4000) { // Transfer 16 bit pixels in blocks if len*2 over 65536 bytes
    774     pushPixels(buffer, 0x400);
    775     len -= 0x400; buffer+= 0x400; // Arbitrarily send 1K pixel blocks (2Kbytes)
    776   }
    777 
    778   esp_err_t ret;
    779   static spi_transaction_t trans;
    780 
    781   memset(&trans, 0, sizeof(spi_transaction_t));
    782 
    783   trans.user = (void *)1;
    784   trans.tx_buffer = buffer;  //finally send the line data
    785   trans.length = len * 16;   //Data length, in bits
    786   trans.flags = 0;           //SPI_TRANS_USE_TXDATA flag
    787 
    788   ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY);
    789   assert(ret == ESP_OK);
    790 
    791   spiBusyCheck++;
    792 }
    793 
    794 ////////////////////////////////////////////////////////////////////////////////////////
    795 // Processor specific DMA initialisation
    796 ////////////////////////////////////////////////////////////////////////////////////////
    797 
    798 // The DMA functions here work with SPI only (not parallel)
    799 /***************************************************************************************
    800 ** Function name:           dc_callback
    801 ** Description:             Toggles DC line during transaction (not used)
    802 ***************************************************************************************/
    803 extern "C" void dc_callback();
    804 
    805 void IRAM_ATTR dc_callback(spi_transaction_t *spi_tx)
    806 {
    807   if ((bool)spi_tx->user) {DC_D;}
    808   else {DC_C;}
    809 }
    810 
    811 /***************************************************************************************
    812 ** Function name:           dma_end_callback
    813 ** Description:             Clear DMA run flag to stop retransmission loop
    814 ***************************************************************************************/
    815 extern "C" void dma_end_callback();
    816 
    817 void IRAM_ATTR dma_end_callback(spi_transaction_t *spi_tx)
    818 {
    819   WRITE_PERI_REG(SPI_DMA_CONF_REG(spi_host), 0);
    820 }
    821 
    822 /***************************************************************************************
    823 ** Function name:           initDMA
    824 ** Description:             Initialise the DMA engine - returns true if init OK
    825 ***************************************************************************************/
    826 bool TFT_eSPI::initDMA(bool ctrl_cs)
    827 {
    828   if (DMA_Enabled) return false;
    829 
    830   esp_err_t ret;
    831   spi_bus_config_t buscfg = {
    832     .mosi_io_num = TFT_MOSI,
    833     .miso_io_num = TFT_MISO,
    834     .sclk_io_num = TFT_SCLK,
    835     .quadwp_io_num = -1,
    836     .quadhd_io_num = -1,
    837     .max_transfer_sz = 65536, // ESP32 S3 max size is 64Kbytes
    838     .flags = 0,
    839     .intr_flags = 0
    840   };
    841 
    842   int8_t pin = -1;
    843   if (ctrl_cs) pin = TFT_CS;
    844 
    845   spi_device_interface_config_t devcfg = {
    846     .command_bits = 0,
    847     .address_bits = 0,
    848     .dummy_bits = 0,
    849     .mode = TFT_SPI_MODE,
    850     .duty_cycle_pos = 0,
    851     .cs_ena_pretrans = 0,
    852     .cs_ena_posttrans = 0,
    853     .clock_speed_hz = SPI_FREQUENCY,
    854     .input_delay_ns = 0,
    855     .spics_io_num = pin,
    856     .flags = SPI_DEVICE_NO_DUMMY, //0,
    857     .queue_size = 1,            // Not using queues
    858     .pre_cb = 0, //dc_callback, //Callback to handle D/C line (not used)
    859     .post_cb = dma_end_callback //Callback to end transmission
    860   };
    861   ret = spi_bus_initialize(spi_host, &buscfg, DMA_CHANNEL);
    862   ESP_ERROR_CHECK(ret);
    863   ret = spi_bus_add_device(spi_host, &devcfg, &dmaHAL);
    864   ESP_ERROR_CHECK(ret);
    865 
    866   DMA_Enabled = true;
    867   spiBusyCheck = 0;
    868   return true;
    869 }
    870 
    871 /***************************************************************************************
    872 ** Function name:           deInitDMA
    873 ** Description:             Disconnect the DMA engine from SPI
    874 ***************************************************************************************/
    875 void TFT_eSPI::deInitDMA(void)
    876 {
    877   if (!DMA_Enabled) return;
    878   spi_bus_remove_device(dmaHAL);
    879   spi_bus_free(spi_host);
    880   DMA_Enabled = false;
    881 }
    882 
    883 ////////////////////////////////////////////////////////////////////////////////////////
    884 #endif // End of DMA FUNCTIONS
    885 ////////////////////////////////////////////////////////////////////////////////////////