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.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 ////////////////////////////////////////////////////////////////////////////////////////