acidportal

- 😈 Worlds smallest Evil Portal on a LilyGo T-QT
git clone git://git.acid.vegas/acidportal.git
Log | Files | Refs | Archive | README | LICENSE

TFT_eSPI_ESP32.c (30730B)

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