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