tft_t_dma.cpp
1 /* 2 Based on C64 ILI9341 dma driver from Frank Bösing, 2017 3 */ 4 5 #include "TFT_T_DMA.h" 6 7 #ifndef HAS_T4_VGA 8 9 #include "font8x8.h" 10 11 // LPSPI4 = SPI0 in Teensy 4.0 12 // LPSPI3 = SPI1 in Teensy 4.0 13 // LPSPI1 = SPI2 in Teensy 4.0 (used for SD on T4.0 but not T4.1) 14 #ifdef TFTSPI1 15 #define SPI SPI1 16 #define LPSPIP_TDR LPSPI3_TDR 17 #define LPSPIP_CR LPSPI3_CR 18 #define LPSPIP_CFGR1 LPSPI3_CFGR1 19 #define LPSPIP_TCR LPSPI3_TCR 20 #define LPSPIP_DER LPSPI3_DER 21 #define DMAMUX_SOURCE_LPSPIP_TX DMAMUX_SOURCE_LPSPI3_TX 22 #else 23 #define LPSPIP_TDR LPSPI4_TDR 24 #define LPSPIP_CR LPSPI4_CR 25 #define LPSPIP_CFGR1 LPSPI4_CFGR1 26 #define LPSPIP_TCR LPSPI4_TCR 27 #define LPSPIP_DER LPSPI4_DER 28 #define DMAMUX_SOURCE_LPSPIP_TX DMAMUX_SOURCE_LPSPI4_TX 29 #endif 30 31 32 #define SPICLOCK 60000000 //144e6 //Just a number..max speed 33 #ifdef ILI9341 34 #define SPI_MODE SPI_MODE0 35 #endif 36 #ifdef ST7789 37 #define SPI_MODE SPI_MODE2 38 #endif 39 40 // touch 41 #define SPI_SETTING SPISettings(2500000, MSBFIRST, SPI_MODE) 42 #define XPT2046_CFG_START _BV(7) 43 #define XPT2046_CFG_MUX(v) ((v&0b111) << (4)) 44 #define XPT2046_CFG_8BIT _BV(3) 45 #define XPT2046_CFG_12BIT (0) 46 #define XPT2046_CFG_SER _BV(2) 47 #define XPT2046_CFG_DFR (0) 48 #define XPT2046_CFG_PWR(v) ((v&0b11)) 49 #define XPT2046_MUX_Y 0b101 50 #define XPT2046_MUX_X 0b001 51 #define XPT2046_MUX_Z1 0b011 52 #define XPT2046_MUX_Z2 0b100 53 54 55 #ifdef TFT_STATICFB 56 static uint16_t fb0[LINES_PER_BLOCK*TFT_WIDTH]; 57 static uint16_t fb1[LINES_PER_BLOCK*TFT_WIDTH]; 58 static uint16_t fb2[LINES_PER_BLOCK*TFT_WIDTH]; 59 static uint16_t fb3[(TFT_HEIGHT-3*LINES_PER_BLOCK)*TFT_WIDTH]; 60 static uint16_t * blocks[NR_OF_BLOCK]={fb0,fb1,fb2,fb3}; 61 #else 62 static uint16_t * blocks[NR_OF_BLOCK]; 63 #endif 64 65 66 static DMASetting dmasettings[SCREEN_DMA_NUM_SETTINGS]; 67 static DMAChannel dmatx;//(false); 68 static volatile uint8_t rstop = 0; 69 static volatile bool cancelled = false; 70 static volatile uint8_t curTransfer = 0; 71 static uint8_t nbTransfer = 0; 72 73 74 PROGMEM static const uint8_t init_commands[] = { 75 #ifdef ILI9341 76 4, 0xEF, 0x03, 0x80, 0x02, 77 4, 0xCF, 0x00, 0XC1, 0X30, 78 5, 0xED, 0x64, 0x03, 0X12, 0X81, 79 4, 0xE8, 0x85, 0x00, 0x78, 80 6, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02, 81 2, 0xF7, 0x20, 82 3, 0xEA, 0x00, 0x00, 83 2, ILI9341_PWCTR1, 0x23, // Power control 84 2, ILI9341_PWCTR2, 0x10, // Power control 85 3, ILI9341_VMCTR1, 0x3e, 0x28, // VCM control 86 2, ILI9341_VMCTR2, 0x86, // VCM control2 87 2, ILI9341_MADCTL, 0x48, // Memory Access Control 88 2, ILI9341_PIXFMT, 0x55, 89 3, ILI9341_FRMCTR1, 0x00, 0x18, 90 4, ILI9341_DFUNCTR, 0x08, 0x82, 0x27, // Display Function Control 91 2, 0xF2, 0x00, // Gamma Function Disable 92 2, ILI9341_GAMMASET, 0x01, // Gamma curve selected 93 16, ILI9341_GMCTRP1, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 94 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, // Set Gamma 95 16, ILI9341_GMCTRN1, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 96 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, // Set Gamma 97 // 3, 0xb1, 0x00, 0x1f, // FrameRate Control 61Hz 98 3, 0xb1, 0x00, 0x10, // FrameRate Control 119Hz 99 2, ILI9341_MADCTL, ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR, 100 0 101 #endif 102 #ifdef ST7789 103 #define DELAY 0x80 104 9, // 9 commands in list: 105 ST7735_SWRESET, DELAY, // 1: Software reset, no args, w/delay 106 150, // 150 ms delay 107 ST7735_SLPOUT , DELAY, // 2: Out of sleep mode, no args, w/delay 108 255, // 255 = 500 ms delay 109 ST7735_COLMOD , 1+DELAY, // 3: Set color mode, 1 arg + delay: 110 0x55, // 16-bit color 111 10, // 10 ms delay 112 ST7735_MADCTL , 1 , // 4: Memory access ctrl (directions), 1 arg: 113 0x08, // Row addr/col addr, bottom to top refresh 114 ST7735_CASET , 4 , // 5: Column addr set, 4 args, no delay: 115 0x00, 116 0x00, // XSTART = 0 117 0x00, 118 240, // XEND = 240 119 ST7735_RASET , 4 , // 6: Row addr set, 4 args, no delay: 120 0x00, 121 0x00, // YSTART = 0 122 320>>8, 123 320 & 0xFF, // YEND = 320 124 ST7735_INVON , DELAY, // 7: hack 125 10, 126 ST7735_NORON , DELAY, // 8: Normal display on, no args, w/delay 127 10, // 10 ms delay 128 ST7735_DISPON , DELAY, // 9: Main screen turn on, no args, w/delay 129 255 130 #endif 131 }; 132 133 static void dmaInterrupt() { 134 dmatx.clearInterrupt(); 135 curTransfer++; 136 if (curTransfer >= nbTransfer) { 137 curTransfer = 0; 138 if (cancelled) { 139 dmatx.disable(); 140 rstop = 1; 141 } 142 } 143 arm_dcache_flush(blocks[curTransfer], LINES_PER_BLOCK*TFT_WIDTH*2); 144 } 145 146 static void setDmaStruct() { 147 uint32_t remaining = TFT_HEIGHT*TFT_WIDTH*2; 148 int i=0; 149 uint16_t col=RGBVAL16(0x00,0x00,0x00);; 150 while (remaining > 0) { 151 uint16_t * fb = blocks[i]; 152 int32_t len = (remaining >= (LINES_PER_BLOCK*TFT_WIDTH*2)?LINES_PER_BLOCK*TFT_WIDTH*2:remaining); 153 #ifdef TFT_DEBUG 154 Serial.println((unsigned long)blocks[i]); 155 Serial.println(remaining); 156 #endif 157 switch (i) { 158 case 0: 159 if (fb == 0) fb = (uint16_t*)((int)malloc(len+64)&0xffffffe0); 160 //fb=&fb0[0]; 161 #ifdef TFT_DEBUG 162 col = RGBVAL16(0x00,0xff,0x00); 163 #endif 164 break; 165 case 1: 166 if (fb == 0) fb = (uint16_t*)((int)malloc(len+64)&0xffffffe0); 167 //fb=&fb1[0]; 168 #ifdef TFT_DEBUG 169 col = RGBVAL16(0x00,0xff,0xff); 170 #endif 171 break; 172 case 2: 173 if (fb == 0) fb = (uint16_t*)((int)malloc(len+64)&0xffffffe0); 174 //fb=&fb2[0]; 175 #ifdef TFT_DEBUG 176 col = RGBVAL16(0x00,0x00,0xff); 177 #endif 178 break; 179 case 3: 180 if (fb == 0) fb = (uint16_t*)((int)malloc(len+64)&0xffffffe0); 181 //fb=&fb3[0]; 182 #ifdef TFT_DEBUG 183 col = RGBVAL16(0xff,0x00,0xff); 184 #endif 185 break; 186 } 187 blocks[i] = fb; 188 if (blocks[i] == 0) { 189 Serial.print("ILI9341 allocaltion failed for block "); 190 Serial.println(i); 191 delay(10000); 192 } 193 194 for (int j=0;j<len/2;j++) fb[j]=col; 195 196 dmasettings[i].sourceBuffer(fb, len); 197 dmasettings[i].destination((uint8_t &) LPSPIP_TDR); 198 dmasettings[i].TCD->ATTR_DST = 1; 199 dmasettings[i].replaceSettingsOnCompletion(dmasettings[i+1]); 200 dmasettings[i].interruptAtCompletion(); 201 remaining -= len; 202 i++; 203 } 204 dmasettings[i-1].replaceSettingsOnCompletion(dmasettings[0]); 205 nbTransfer = i; 206 #ifdef TFT_DEBUG 207 Serial.println(nbTransfer); 208 #endif 209 } 210 211 212 TFT_T_DMA::TFT_T_DMA(uint8_t cs, uint8_t dc, uint8_t rst, uint8_t mosi, uint8_t sclk, uint8_t miso, uint8_t touch_cs, uint8_t touch_irq) 213 { 214 _cs = cs; 215 _dc = dc; 216 _rst = rst; 217 _mosi = mosi; 218 _sclk = sclk; 219 _miso = miso; 220 pinMode(_dc, OUTPUT); 221 pinMode(_cs, OUTPUT); 222 digitalWrite(_cs, 1); 223 digitalWrite(_dc, 1); 224 if ( (touch_cs != 255) && (touch_irq != 255) ) { 225 _touch_irq = touch_irq; 226 _touch_cs = touch_cs; 227 pinMode(_touch_cs, OUTPUT); 228 pinMode(touch_irq, INPUT_PULLUP); 229 digitalWrite(_touch_cs, 1); 230 } 231 } 232 233 234 void TFT_T_DMA::setArea(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2) { 235 int dx=0; 236 int dy=0; 237 #ifdef ST7789 238 if (TFT_REALWIDTH == TFT_REALHEIGHT) 239 { 240 #ifdef ROTATE_SCREEN 241 if (!flipped) { 242 dy += 80; 243 } 244 #else 245 if (flipped) { 246 dx += 80; 247 } 248 #endif 249 } 250 #endif 251 252 digitalWrite(_dc, 0); 253 SPI.transfer(TFT_CASET); 254 digitalWrite(_dc, 1); 255 SPI.transfer16(x1+dx); 256 digitalWrite(_dc, 1); 257 SPI.transfer16(x2+dx); 258 digitalWrite(_dc, 0); 259 SPI.transfer(TFT_PASET); 260 digitalWrite(_dc, 1); 261 SPI.transfer16(y1+dy); 262 digitalWrite(_dc, 1); 263 SPI.transfer16(y2+dy); 264 265 digitalWrite(_dc, 0); 266 SPI.transfer(TFT_RAMWR); 267 digitalWrite(_dc, 1); 268 269 return; 270 271 272 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 273 digitalWrite(_cs, 0); 274 275 digitalWrite(_dc, 0); 276 SPI.transfer(TFT_CASET); 277 digitalWrite(_dc, 1); 278 279 SPI.transfer16(x1+dx); 280 SPI.transfer16(x2+dx); 281 282 digitalWrite(_dc, 0); 283 SPI.transfer(TFT_PASET); 284 digitalWrite(_dc, 1); 285 SPI.transfer16(y1+dy); 286 SPI.transfer16(y2+dy); 287 288 digitalWrite(_dc, 0); 289 SPI.transfer(TFT_RAMWR); 290 digitalWrite(_dc, 1); 291 292 digitalWrite(_cs, 1); 293 SPI.endTransaction(); 294 } 295 296 297 298 299 void TFT_T_DMA::begin(void) { 300 SPI.setMOSI(_mosi); 301 SPI.setMISO(_miso); 302 SPI.setSCK(_sclk); 303 SPI.begin(); 304 305 // Initialize display 306 if (_rst != 0xff) { 307 pinMode(_rst, OUTPUT); 308 digitalWrite(_rst, HIGH); 309 delay(100); 310 digitalWrite(_rst, LOW); 311 delay(100); 312 digitalWrite(_rst, HIGH); 313 delay(200); 314 } 315 316 317 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 318 const uint8_t *addr = init_commands; 319 digitalWrite(_cs, 0); 320 #ifdef ILI9341 321 while (1) { 322 uint8_t count = *addr++; 323 if (count-- == 0) break; 324 325 digitalWrite(_dc, 0); 326 SPI.transfer(*addr++); 327 328 while (count-- > 0) { 329 digitalWrite(_dc, 1); 330 SPI.transfer(*addr++); 331 } 332 } 333 334 digitalWrite(_dc, 0); 335 SPI.transfer(ILI9341_SLPOUT); 336 digitalWrite(_dc, 1); 337 digitalWrite(_cs, 1); 338 SPI.endTransaction(); 339 340 digitalWrite(_dc, 1); 341 digitalWrite(_cs, 1); 342 SPI.endTransaction(); 343 344 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 345 digitalWrite(_dc, 0); 346 digitalWrite(_cs, 0); 347 SPI.transfer(ILI9341_DISPON); 348 digitalWrite(_dc, 1); 349 digitalWrite(_cs, 1); 350 #endif 351 #ifdef ST7789 352 uint8_t numCommands, numArgs; 353 uint16_t ms; 354 numCommands = *addr++; // Number of commands to follow 355 while(numCommands--) { // For each command... 356 digitalWrite(_dc, 0); 357 SPI.transfer(*addr++); 358 numArgs = *addr++; // Number of args to follow 359 ms = numArgs & DELAY; // If hibit set, delay follows args 360 numArgs &= ~DELAY; // Mask out delay bit 361 while(numArgs > 1) { // For each argument... 362 digitalWrite(_dc, 1); 363 SPI.transfer(*addr++); 364 numArgs--; 365 } 366 367 if (numArgs) { 368 digitalWrite(_dc, 1); 369 SPI.transfer(*addr++); 370 } 371 if(ms) { 372 ms = *addr++; // Read post-command delay time (ms) 373 if(ms == 255) ms = 500; // If 255, delay for 500 ms 374 digitalWrite(_cs, 1); 375 SPI.endTransaction(); 376 delay(ms); 377 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 378 digitalWrite(_cs, 0); 379 } 380 } 381 digitalWrite(_cs, 1); 382 #endif 383 setArea(0, 0, TFT_REALWIDTH-1, TFT_REALHEIGHT-1); 384 SPI.endTransaction(); 385 386 cancelled = false; 387 388 #ifdef FLIP_SCREEN 389 flipscreen(true); 390 #else 391 flipscreen(false); 392 #endif 393 #ifdef ST7789 394 if (TFT_REALWIDTH != TFT_REALHEIGHT) 395 { 396 flipscreen(true); 397 } 398 #endif 399 }; 400 401 402 403 void TFT_T_DMA::flipscreen(bool flip) 404 { 405 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 406 digitalWrite(_dc, 0); 407 digitalWrite(_cs, 0); 408 SPI.transfer(TFT_MADCTL); 409 digitalWrite(_dc, 1); 410 if (flip) { 411 flipped=true; 412 #ifdef ILI9341 413 SPI.transfer(ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR); 414 #endif 415 #ifdef ST7789 416 #ifdef ROTATE_SCREEN 417 SPI.transfer(ST77XX_MADCTL_RGB); 418 #else 419 SPI.transfer(ST77XX_MADCTL_MY | ST77XX_MADCTL_MV |ST77XX_MADCTL_RGB); 420 #endif 421 #endif 422 } 423 else { 424 flipped=false; 425 #ifdef ILI9341 426 SPI.transfer(ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR); 427 #endif 428 #ifdef ST7789 429 #ifdef ROTATE_SCREEN 430 SPI.transfer(ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST77XX_MADCTL_RGB); 431 #else 432 SPI.transfer(ST77XX_MADCTL_MX | ST77XX_MADCTL_MV | ST77XX_MADCTL_RGB); 433 #endif 434 #endif 435 } 436 digitalWrite(_cs, 1); 437 SPI.endTransaction(); 438 } 439 440 boolean TFT_T_DMA::isflipped(void) 441 { 442 return(flipped); 443 } 444 445 446 #define PRREG(x) Serial.print(#x" 0x"); Serial.println(x,HEX) 447 448 449 void TFT_T_DMA::startDMA(void) { 450 curTransfer = 0; 451 rstop = 0; 452 //dmatx.begin(true); 453 dmatx.attachInterrupt(dmaInterrupt); 454 setDmaStruct(); 455 setArea((TFT_REALWIDTH-TFT_WIDTH)/2, (TFT_REALHEIGHT-TFT_HEIGHT)/2, (TFT_REALWIDTH-TFT_WIDTH)/2 + TFT_WIDTH-1, (TFT_REALHEIGHT-TFT_HEIGHT)/2+TFT_HEIGHT-1); 456 fillScreen(RGBVAL16(0x00,0x00,0x00)); 457 458 digitalWrite(_cs, HIGH); 459 SPI.begin(); 460 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0)); 461 462 463 LPSPIP_CR &= ~LPSPI_CR_MEN;//disable LPSPI: 464 LPSPIP_CFGR1 |= LPSPI_CFGR1_NOSTALL; //prevent stall from RX 465 LPSPIP_TCR = 15; // Framesize 16 Bits 466 //LPSPIP_FCR = 0; // Fifo Watermark 467 LPSPIP_DER = LPSPI_DER_TDDE; //TX DMA Request Enable 468 LPSPIP_CR |= LPSPI_CR_MEN; //enable LPSPI: 469 dmatx.triggerAtHardwareEvent( DMAMUX_SOURCE_LPSPIP_TX ); 470 471 dmatx = dmasettings[0]; 472 digitalWrite(_cs, 0); 473 setArea((TFT_REALWIDTH-TFT_WIDTH)/2, (TFT_REALHEIGHT-TFT_HEIGHT)/2, (TFT_REALWIDTH-TFT_WIDTH)/2+TFT_WIDTH-1, (TFT_REALHEIGHT-TFT_HEIGHT)/2+TFT_HEIGHT-1); 474 digitalWrite(_dc, 0); 475 SPI.transfer(TFT_RAMWR); 476 digitalWrite(_dc, 1); 477 dmatx.enable(); 478 } 479 480 481 void TFT_T_DMA::stopDMA(void) { 482 rstop = 0; 483 wait(); 484 delay(50); 485 cancelled = false; 486 dmatx.detachInterrupt(); 487 fillScreen(RGBVAL16(0x00,0x00,0x00)); 488 SPI.end(); 489 #ifdef ST7789 490 begin(); 491 #endif 492 #ifdef ILI9341 493 SPI.begin(); 494 digitalWrite(_cs, 0); 495 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 496 SPI.endTransaction(); 497 digitalWrite(_cs, 1); 498 digitalWrite(_dc, 1); 499 #endif 500 setArea(0, 0, TFT_REALWIDTH-1, TFT_REALHEIGHT-1); 501 } 502 503 void TFT_T_DMA::wait(void) { 504 rstop = 1; 505 unsigned long m = millis(); 506 cancelled = true; 507 while (!rstop) { 508 if ((millis() - m) > 100) break; 509 delay(10); 510 asm volatile("wfi"); 511 }; 512 rstop = 0; 513 } 514 515 int TFT_T_DMA::get_frame_buffer_size(int *width, int *height){ 516 if (width != nullptr) *width = TFT_REALWIDTH; 517 if (height != nullptr) *height = TFT_REALHEIGHT; 518 return TFT_REALWIDTH; 519 } 520 521 522 /*********************************************************************************************** 523 Touch functions 524 ***********************************************************************************************/ 525 /* Code based on ... 526 * 527 * @file XPT2046.cpp 528 * @date 19.02.2016 529 * @author Markus Sattler 530 * 531 * Copyright (c) 2015 Markus Sattler. All rights reserved. 532 * This file is part of the XPT2046 driver for Arduino. 533 */ 534 535 #define ADC_MAX 0x0fff 536 537 void TFT_T_DMA::enableTouchIrq() 538 { 539 SPI.beginTransaction(SPI_SETTING); 540 digitalWrite(_touch_cs, LOW); 541 const uint8_t buf[4] = { (XPT2046_CFG_START | XPT2046_CFG_12BIT | XPT2046_CFG_DFR | XPT2046_CFG_MUX(XPT2046_MUX_Y)), 0x00, 0x00, 0x00 }; 542 SPI.transfer((void*)&buf[0],3); 543 digitalWrite(_touch_cs, HIGH); 544 SPI.endTransaction(); 545 } 546 547 //Default callibration for non flipped 548 #define TX_MIN 30 549 #define TY_MIN 20 550 #define TX_MAX 300 551 #define TY_MAX 220 552 553 //Default callibration for flipped 554 #define TFX_MIN 20 555 #define TFY_MIN 25 556 #define TFX_MAX 288 557 #define TFY_MAX 221 558 559 static uint16_t txMin; 560 static uint16_t tyMin; 561 static uint16_t txMax; 562 static uint16_t tyMax; 563 564 565 void TFT_T_DMA::callibrateTouch(uint16_t xMin,uint16_t yMin,uint16_t xMax,uint16_t yMax) { 566 if ( (xMin >= 0) && (yMin >= 0) && (xMax < 320) && (yMax < 200) ) { 567 txMin = xMin; 568 tyMin = yMin; 569 txMax = xMax; 570 tyMax = yMax; 571 } 572 else { 573 if (flipped) { 574 txMin = TFX_MIN; 575 tyMin = TFY_MIN; 576 txMax = TFX_MAX; 577 tyMax = TFY_MAX; 578 } 579 else { 580 txMin = TX_MIN; 581 tyMin = TY_MIN; 582 txMax = TX_MAX; 583 tyMax = TY_MAX; 584 } 585 } 586 } 587 588 589 void TFT_T_DMA::readRaw(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { 590 if ( TOUCH_ENABLED() ) { 591 uint16_t x = 0; 592 uint16_t y = 0; 593 uint16_t z1 = 0; 594 uint16_t z2 = 0; 595 uint8_t i = 0; 596 int16_t xraw=0, yraw=0; 597 598 SPI.beginTransaction(SPI_SETTING); 599 digitalWrite(_touch_cs, LOW); 600 601 for(; i < 15; i++) { 602 // SPI requirer 32bit aliment 603 uint8_t buf[12] = { 604 (XPT2046_CFG_START | XPT2046_CFG_12BIT | XPT2046_CFG_DFR | XPT2046_CFG_MUX(XPT2046_MUX_Y) | XPT2046_CFG_PWR(3)), 0x00, 0x00, 605 (XPT2046_CFG_START | XPT2046_CFG_12BIT | XPT2046_CFG_DFR | XPT2046_CFG_MUX(XPT2046_MUX_X) | XPT2046_CFG_PWR(3)), 0x00, 0x00, 606 (XPT2046_CFG_START | XPT2046_CFG_12BIT | XPT2046_CFG_DFR | XPT2046_CFG_MUX(XPT2046_MUX_Z1)| XPT2046_CFG_PWR(3)), 0x00, 0x00, 607 (XPT2046_CFG_START | XPT2046_CFG_12BIT | XPT2046_CFG_DFR | XPT2046_CFG_MUX(XPT2046_MUX_Z2)| XPT2046_CFG_PWR(3)), 0x00, 0x00 608 }; 609 SPI.transfer(&buf[0], &buf[0], 12); 610 y += (buf[1] << 8 | buf[2])>>3; 611 x += (buf[4] << 8 | buf[5])>>3; 612 z1 += (buf[7] << 8 | buf[8])>>3; 613 z2 += (buf[10] << 8 | buf[11])>>3; 614 } 615 enableTouchIrq(); 616 617 if(i == 0) { 618 *oX = 0; 619 *oY = 0; 620 *oZ = 0; 621 } 622 else { 623 x /= i; 624 y /= i; 625 z1 /= i; 626 z2 /= i; 627 } 628 629 digitalWrite(_touch_cs, HIGH); 630 SPI.endTransaction(); 631 int z = z1 + ADC_MAX - z2; 632 if (flipped) { 633 xraw = x; 634 yraw = y; 635 } else { 636 xraw = ADC_MAX - x; 637 yraw = ADC_MAX - y; 638 } 639 xraw=(xraw*TFT_REALWIDTH)/(ADC_MAX+1); 640 yraw=(yraw*TFT_REALHEIGHT)/(ADC_MAX+1); 641 642 *oX = xraw; 643 *oY = yraw; 644 *oZ = z; 645 } 646 else 647 { 648 *oX = 0; 649 *oY = 0; 650 *oZ = 0; 651 } 652 } 653 654 void TFT_T_DMA::readCal(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { 655 readRaw(oX,oY,oZ); 656 // callibrate ... 657 if(*oX >= txMin) *oX = ((*oX - txMin)*TFT_REALWIDTH)/(txMax-txMin); 658 if(*oY >= tyMin) *oY = ((*oY - tyMin)*TFT_REALHEIGHT)/(tyMax-tyMin); 659 //Serial.print(*oX); 660 //Serial.print(" "); 661 //Serial.println(*oY); 662 } 663 664 665 /*********************************************************************************************** 666 No DMA functions 667 ***********************************************************************************************/ 668 void TFT_T_DMA::fillScreenNoDma(uint16_t color) { 669 670 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 671 digitalWrite(_cs, 0); 672 setArea(0, 0, TFT_REALWIDTH-1, TFT_REALHEIGHT-1); 673 //digitalWrite(_dc, 0); 674 //SPI.transfer(TFT_RAMWR); 675 int i,j; 676 for (j=0; j<TFT_REALHEIGHT; j++) 677 { 678 for (i=0; i<TFT_REALWIDTH; i++) { 679 //digitalWrite(_dc, 1); 680 SPI.transfer16(color); 681 } 682 } 683 #ifdef ILI9341 684 digitalWrite(_dc, 0); 685 SPI.transfer(ILI9341_SLPOUT); 686 digitalWrite(_dc, 1); 687 #endif 688 digitalWrite(_cs, 1); 689 setArea(0, 0, (TFT_REALWIDTH-1), (TFT_REALHEIGHT-1)); 690 SPI.endTransaction(); 691 } 692 693 void TFT_T_DMA::drawRectNoDma(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { 694 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 695 digitalWrite(_cs, 0); 696 setArea(x,y,x+w-1,y+h-1); 697 // digitalWrite(_dc, 0); 698 // SPI.transfer(TFT_RAMWR); 699 int i; 700 for (i=0; i<(w*h); i++) 701 { 702 //digitalWrite(_dc, 1); 703 SPI.transfer16(color); 704 } 705 #ifdef ILI9341 706 digitalWrite(_dc, 0); 707 SPI.transfer(ILI9341_SLPOUT); 708 digitalWrite(_dc, 1); 709 #endif 710 digitalWrite(_cs, 1); 711 setArea(0, 0, (TFT_REALWIDTH-1), (TFT_REALHEIGHT-1)); 712 SPI.endTransaction(); 713 } 714 715 void TFT_T_DMA::writeScreenNoDma(const uint16_t *pcolors) { 716 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 717 digitalWrite(_cs, 0); 718 setArea(0, 0, TFT_WIDTH-1, TFT_HEIGHT-1); 719 //digitalWrite(_dc, 0); 720 //SPI.transfer(TFT_RAMWR); 721 int i,j; 722 for (j=0; j<240; j++) 723 { 724 for (i=0; i<TFT_WIDTH; i++) { 725 // digitalWrite(_dc, 1); 726 SPI.transfer16(*pcolors++); 727 } 728 } 729 #ifdef ILI9341 730 digitalWrite(_dc, 0); 731 SPI.transfer(ILI9341_SLPOUT); 732 digitalWrite(_dc, 1); 733 #endif 734 digitalWrite(_cs, 1); 735 setArea(0, 0, (TFT_REALWIDTH-1), (TFT_REALHEIGHT-1)); 736 SPI.endTransaction(); 737 } 738 739 void TFT_T_DMA::drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap) { 740 drawSpriteNoDma(x,y,bitmap, 0,0,0,0); 741 } 742 743 void TFT_T_DMA::drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap, uint16_t arx, uint16_t ary, uint16_t arw, uint16_t arh) 744 { 745 int bmp_offx = 0; 746 int bmp_offy = 0; 747 uint16_t *bmp_ptr; 748 749 int w =*bitmap++; 750 int h = *bitmap++; 751 //Serial.println(w); 752 //Serial.println(h); 753 754 if ( (arw == 0) || (arh == 0) ) { 755 // no crop window 756 arx = x; 757 ary = y; 758 arw = w; 759 arh = h; 760 } 761 else { 762 if ( (x>(arx+arw)) || ((x+w)<arx) || (y>(ary+arh)) || ((y+h)<ary) ) { 763 return; 764 } 765 766 // crop area 767 if ( (x > arx) && (x<(arx+arw)) ) { 768 arw = arw - (x-arx); 769 arx = arx + (x-arx); 770 } else { 771 bmp_offx = arx; 772 } 773 if ( ((x+w) > arx) && ((x+w)<(arx+arw)) ) { 774 arw -= (arx+arw-x-w); 775 } 776 if ( (y > ary) && (y<(ary+arh)) ) { 777 arh = arh - (y-ary); 778 ary = ary + (y-ary); 779 } else { 780 bmp_offy = ary; 781 } 782 if ( ((y+h) > ary) && ((y+h)<(ary+arh)) ) { 783 arh -= (ary+arh-y-h); 784 } 785 } 786 787 788 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 789 digitalWrite(_cs, 0); 790 setArea(arx, ary, arx+arw-1, ary+arh-1); 791 //digitalWrite(_dc, 0); 792 //SPI.transfer(TFT_RAMWR); 793 794 bitmap = bitmap + bmp_offy*w + bmp_offx; 795 for (int row=0;row<arh; row++) 796 { 797 bmp_ptr = (uint16_t*)bitmap; 798 for (int col=0;col<arw; col++) 799 { 800 uint16_t color = *bmp_ptr++; 801 // digitalWrite(_dc, 1); 802 SPI.transfer16(color); 803 } 804 bitmap += w; 805 } 806 #ifdef ILI9341 807 digitalWrite(_dc, 0); 808 SPI.transfer(ILI9341_SLPOUT); 809 digitalWrite(_dc, 1); 810 #endif 811 setArea(0, 0, TFT_REALWIDTH-1, TFT_REALHEIGHT-1); 812 digitalWrite(_cs, 1); 813 SPI.endTransaction(); 814 } 815 816 void TFT_T_DMA::drawTextNoDma(int16_t x, int16_t y, const char * text, uint16_t fgcolor, uint16_t bgcolor, bool doublesize) { 817 uint16_t c; 818 while ((c = *text++)) { 819 const unsigned char * charpt=&font8x8[c][0]; 820 821 822 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 823 digitalWrite(_cs, 0); 824 setArea(x,y,x+7,y+(doublesize?15:7)); 825 //digitalWrite(_dc, 0); 826 //SPI.transfer(TFT_RAMWR); 827 //digitalWrite(_dc, 1); 828 for (int i=0;i<8;i++) 829 { 830 unsigned char bits; 831 if (doublesize) { 832 bits = *charpt; 833 //digitalWrite(_dc, 1); 834 if (bits&0x01) SPI.transfer16(fgcolor); 835 else SPI.transfer16(bgcolor); 836 bits = bits >> 1; 837 if (bits&0x01) SPI.transfer16(fgcolor); 838 else SPI.transfer16(bgcolor); 839 bits = bits >> 1; 840 if (bits&0x01) SPI.transfer16(fgcolor); 841 else SPI.transfer16(bgcolor); 842 bits = bits >> 1; 843 if (bits&0x01) SPI.transfer16(fgcolor); 844 else SPI.transfer16(bgcolor); 845 bits = bits >> 1; 846 if (bits&0x01) SPI.transfer16(fgcolor); 847 else SPI.transfer16(bgcolor); 848 bits = bits >> 1; 849 if (bits&0x01) SPI.transfer16(fgcolor); 850 else SPI.transfer16(bgcolor); 851 bits = bits >> 1; 852 if (bits&0x01) SPI.transfer16(fgcolor); 853 else SPI.transfer16(bgcolor); 854 bits = bits >> 1; 855 if (bits&0x01) SPI.transfer16(fgcolor); 856 else SPI.transfer16(bgcolor); 857 } 858 bits = *charpt++; 859 //digitalWrite(_dc, 1); 860 if (bits&0x01) SPI.transfer16(fgcolor); 861 else SPI.transfer16(bgcolor); 862 bits = bits >> 1; 863 if (bits&0x01) SPI.transfer16(fgcolor); 864 else SPI.transfer16(bgcolor); 865 bits = bits >> 1; 866 if (bits&0x01) SPI.transfer16(fgcolor); 867 else SPI.transfer16(bgcolor); 868 bits = bits >> 1; 869 if (bits&0x01) SPI.transfer16(fgcolor); 870 else SPI.transfer16(bgcolor); 871 bits = bits >> 1; 872 if (bits&0x01) SPI.transfer16(fgcolor); 873 else SPI.transfer16(bgcolor); 874 bits = bits >> 1; 875 if (bits&0x01) SPI.transfer16(fgcolor); 876 else SPI.transfer16(bgcolor); 877 bits = bits >> 1; 878 if (bits&0x01) SPI.transfer16(fgcolor); 879 else SPI.transfer16(bgcolor); 880 bits = bits >> 1; 881 if (bits&0x01) SPI.transfer16(fgcolor); 882 else SPI.transfer16(bgcolor); 883 } 884 x +=8; 885 #ifdef ILI9341 886 digitalWrite(_dc, 0); 887 SPI.transfer(ILI9341_SLPOUT); 888 digitalWrite(_dc, 1); 889 #endif 890 digitalWrite(_cs, 1); 891 SPI.endTransaction(); 892 } 893 894 SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE)); 895 digitalWrite(_cs, 0); 896 setArea(0, 0, (TFT_REALWIDTH-1), (TFT_REALHEIGHT-1)); 897 digitalWrite(_cs, 1); 898 SPI.endTransaction(); 899 } 900 901 902 903 904 905 906 /*********************************************************************************************** 907 DMA functions 908 ***********************************************************************************************/ 909 uint16_t * TFT_T_DMA::getLineBuffer(int j) 910 { 911 uint16_t * block=blocks[j>>6]; 912 return(&block[(j&0x3F)*TFT_REALWIDTH]); 913 } 914 915 void TFT_T_DMA::writeScreen(int width, int height, int stride, uint8_t *buf, uint16_t *palette16) { 916 uint8_t *buffer=buf; 917 uint8_t *src; 918 919 int i,j,y=0; 920 if (width*2 <= TFT_REALWIDTH) { 921 for (j=0; j<height; j++) 922 { 923 uint16_t * block=blocks[y>>6]; 924 uint16_t * dst=&block[(y&0x3F)*TFT_WIDTH]; 925 src=buffer; 926 for (i=0; i<width; i++) 927 { 928 uint16_t val = palette16[*src++]; 929 *dst++ = val; 930 *dst++ = val; 931 } 932 y++; 933 if (height*2 <= TFT_HEIGHT) { 934 block=blocks[y>>6]; 935 dst=&block[(y&0x3F)*TFT_WIDTH]; 936 src=buffer; 937 for (i=0; i<width; i++) 938 { 939 uint16_t val = palette16[*src++]; 940 *dst++ = val; 941 *dst++ = val; 942 } 943 y++; 944 } 945 buffer += stride; 946 } 947 } 948 else if (width <= TFT_REALWIDTH) { 949 //dst += (TFT_WIDTH-width)/2; 950 for (j=0; j<height; j++) 951 { 952 uint16_t * block=blocks[y>>6]; 953 uint16_t * dst=&block[(y&0x3F)*TFT_WIDTH+(TFT_WIDTH-width)/2]; 954 src=buffer; 955 for (i=0; i<width; i++) 956 { 957 uint16_t val = palette16[*src++]; 958 *dst++ = val; 959 } 960 y++; 961 if (height*2 <= TFT_HEIGHT) { 962 block=blocks[y>>6]; 963 dst=&block[(y&0x3F)*TFT_WIDTH+(TFT_WIDTH-width)/2]; 964 src=buffer; 965 for (i=0; i<width; i++) 966 { 967 uint16_t val = palette16[*src++]; 968 *dst++ = val; 969 } 970 y++; 971 } 972 buffer += stride; 973 } 974 } 975 } 976 977 void TFT_T_DMA::writeLine(int width, int height, int y, uint8_t *buf, uint16_t *palette16) { 978 uint16_t * block=blocks[y>>6]; 979 uint16_t * dst=&block[(y&0x3F)*TFT_WIDTH]; 980 if (width > TFT_WIDTH) { 981 #ifdef TFT_LINEARINT 982 int delta = (width/(width-TFT_WIDTH))-1; 983 int pos = delta; 984 for (int i=0; i<TFT_WIDTH; i++) 985 { 986 uint16_t val = palette16[*buf++]; 987 pos--; 988 if (pos == 0) { 989 #ifdef LINEARINT_HACK 990 val = ((uint32_t)palette16[*buf++] + val)/2; 991 #else 992 uint16_t val2 = *buf++; 993 val = RGBVAL16((R16(val)+R16(val2))/2,(G16(val)+G16(val2))/2,(B16(val)+B16(val2))/2); 994 #endif 995 pos = delta; 996 } 997 *dst++=val; 998 } 999 #else 1000 int step = ((width << 8)/TFT_WIDTH); 1001 int pos = 0; 1002 for (int i=0; i<TFT_WIDTH; i++) 1003 { 1004 *dst++=palette16[buf[pos >> 8]]; 1005 pos +=step; 1006 } 1007 #endif 1008 } 1009 else if ((width*2) == TFT_WIDTH) { 1010 for (int i=0; i<width; i++) 1011 { 1012 *dst++=palette16[*buf]; 1013 *dst++=palette16[*buf++]; 1014 } 1015 } 1016 else { 1017 if (width <= TFT_WIDTH) { 1018 dst += (TFT_WIDTH-width)/2; 1019 } 1020 for (int i=0; i<width; i++) 1021 { 1022 *dst++=palette16[*buf++]; 1023 } 1024 } 1025 } 1026 1027 void TFT_T_DMA::writeLine(int width, int height, int y, uint16_t *buf) { 1028 uint16_t * block=blocks[y>>6]; 1029 uint16_t * dst=&block[(y&0x3F)*TFT_WIDTH]; 1030 if (width > TFT_WIDTH) { 1031 #ifdef TFT_LINEARINT 1032 int delta = (width/(width-TFT_WIDTH))-1; 1033 int pos = delta; 1034 for (int i=0; i<TFT_WIDTH; i++) 1035 { 1036 uint16_t val = *buf++; 1037 pos--; 1038 if (pos == 0) { 1039 #ifdef LINEARINT_HACK 1040 val = ((uint32_t)*buf++ + val)/2; 1041 #else 1042 uint16_t val2 = *buf++; 1043 val = RGBVAL16((R16(val)+R16(val2))/2,(G16(val)+G16(val2))/2,(B16(val)+B16(val2))/2); 1044 #endif 1045 pos = delta; 1046 } 1047 *dst++=val; 1048 } 1049 #else 1050 int step = ((width << 8)/TFT_WIDTH); 1051 int pos = 0; 1052 for (int i=0; i<TFT_WIDTH; i++) 1053 { 1054 *dst++=buf[pos >> 8]; 1055 pos +=step; 1056 } 1057 #endif 1058 } 1059 else if ((width*2) == TFT_WIDTH) { 1060 for (int i=0; i<width; i++) 1061 { 1062 *dst++=*buf; 1063 *dst++=*buf++; 1064 } 1065 } 1066 else { 1067 if (width <= TFT_WIDTH) { 1068 dst += (TFT_WIDTH-width)/2; 1069 } 1070 for (int i=0; i<width; i++) 1071 { 1072 *dst++=*buf++; 1073 } 1074 } 1075 } 1076 1077 void TFT_T_DMA::fillScreen(uint16_t color) { 1078 int i,j; 1079 for (j=0; j<TFT_HEIGHT; j++) 1080 { 1081 uint16_t * block=blocks[j>>6]; 1082 uint16_t * dst=&block[(j&0x3F)*TFT_WIDTH]; 1083 for (i=0; i<TFT_WIDTH; i++) 1084 { 1085 *dst++ = color; 1086 } 1087 } 1088 } 1089 1090 void TFT_T_DMA::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { 1091 int i,j,l=y; 1092 color=color; 1093 for (j=0; j<h; j++) 1094 { 1095 uint16_t * block=blocks[l>>6]; 1096 uint16_t * dst=&block[(l&0x3F)*TFT_WIDTH+x]; 1097 for (i=0; i<w; i++) 1098 { 1099 *dst++ = color; 1100 } 1101 l++; 1102 } 1103 } 1104 1105 void TFT_T_DMA::drawText(int16_t x, int16_t y, const char * text, uint16_t fgcolor, uint16_t bgcolor, bool doublesize) { 1106 uint16_t c; 1107 uint16_t * block; 1108 uint16_t * dst; 1109 fgcolor = fgcolor; 1110 bgcolor = bgcolor; 1111 1112 while ((c = *text++)) { 1113 const unsigned char * charpt=&font8x8[c][0]; 1114 1115 int l=y; 1116 for (int i=0;i<8;i++) 1117 { 1118 unsigned char bits; 1119 if (doublesize) { 1120 block=blocks[l>>6]; 1121 dst=&block[(l&0x3F)*TFT_WIDTH+x]; 1122 bits = *charpt; 1123 if (bits&0x01) *dst++=fgcolor; 1124 else *dst++=bgcolor; 1125 bits = bits >> 1; 1126 if (bits&0x01) *dst++=fgcolor; 1127 else *dst++=bgcolor; 1128 bits = bits >> 1; 1129 if (bits&0x01) *dst++=fgcolor; 1130 else *dst++=bgcolor; 1131 bits = bits >> 1; 1132 if (bits&0x01) *dst++=fgcolor; 1133 else *dst++=bgcolor; 1134 bits = bits >> 1; 1135 if (bits&0x01) *dst++=fgcolor; 1136 else *dst++=bgcolor; 1137 bits = bits >> 1; 1138 if (bits&0x01) *dst++=fgcolor; 1139 else *dst++=bgcolor; 1140 bits = bits >> 1; 1141 if (bits&0x01) *dst++=fgcolor; 1142 else *dst++=bgcolor; 1143 bits = bits >> 1; 1144 if (bits&0x01) *dst++=fgcolor; 1145 else *dst++=bgcolor; 1146 l++; 1147 } 1148 block=blocks[l>>6]; 1149 dst=&block[(l&0x3F)*TFT_WIDTH+x]; 1150 bits = *charpt++; 1151 if (bits&0x01) *dst++=fgcolor; 1152 else *dst++=bgcolor; 1153 bits = bits >> 1; 1154 if (bits&0x01) *dst++=fgcolor; 1155 else *dst++=bgcolor; 1156 bits = bits >> 1; 1157 if (bits&0x01) *dst++=fgcolor; 1158 else *dst++=bgcolor; 1159 bits = bits >> 1; 1160 if (bits&0x01) *dst++=fgcolor; 1161 else *dst++=bgcolor; 1162 bits = bits >> 1; 1163 if (bits&0x01) *dst++=fgcolor; 1164 else *dst++=bgcolor; 1165 bits = bits >> 1; 1166 if (bits&0x01) *dst++=fgcolor; 1167 else *dst++=bgcolor; 1168 bits = bits >> 1; 1169 if (bits&0x01) *dst++=fgcolor; 1170 else *dst++=bgcolor; 1171 bits = bits >> 1; 1172 if (bits&0x01) *dst++=fgcolor; 1173 else *dst++=bgcolor; 1174 l++; 1175 } 1176 x +=8; 1177 } 1178 } 1179 1180 void TFT_T_DMA::drawSprite(int16_t x, int16_t y, const uint16_t *bitmap) { 1181 drawSprite(x,y,bitmap, 0,0,0,0); 1182 } 1183 1184 void TFT_T_DMA::drawSprite(int16_t x, int16_t y, const uint16_t *bitmap, uint16_t arx, uint16_t ary, uint16_t arw, uint16_t arh) 1185 { 1186 int bmp_offx = 0; 1187 int bmp_offy = 0; 1188 uint16_t *bmp_ptr; 1189 1190 int w =*bitmap++; 1191 int h = *bitmap++; 1192 1193 1194 if ( (arw == 0) || (arh == 0) ) { 1195 // no crop window 1196 arx = x; 1197 ary = y; 1198 arw = w; 1199 arh = h; 1200 } 1201 else { 1202 if ( (x>(arx+arw)) || ((x+w)<arx) || (y>(ary+arh)) || ((y+h)<ary) ) { 1203 return; 1204 } 1205 1206 // crop area 1207 if ( (x > arx) && (x<(arx+arw)) ) { 1208 arw = arw - (x-arx); 1209 arx = arx + (x-arx); 1210 } else { 1211 bmp_offx = arx; 1212 } 1213 if ( ((x+w) > arx) && ((x+w)<(arx+arw)) ) { 1214 arw -= (arx+arw-x-w); 1215 } 1216 if ( (y > ary) && (y<(ary+arh)) ) { 1217 arh = arh - (y-ary); 1218 ary = ary + (y-ary); 1219 } else { 1220 bmp_offy = ary; 1221 } 1222 if ( ((y+h) > ary) && ((y+h)<(ary+arh)) ) { 1223 arh -= (ary+arh-y-h); 1224 } 1225 } 1226 1227 1228 int l=ary; 1229 bitmap = bitmap + bmp_offy*w + bmp_offx; 1230 for (int row=0;row<arh; row++) 1231 { 1232 uint16_t * block=blocks[l>>6]; 1233 uint16_t * dst=&block[(l&0x3F)*TFT_WIDTH+arx]; 1234 bmp_ptr = (uint16_t*)bitmap; 1235 for (int col=0;col<arw; col++) 1236 { 1237 *dst++ = *bmp_ptr++; 1238 } 1239 bitmap += w; 1240 l++; 1241 } 1242 } 1243 #endif