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

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