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