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