/ MCUME_teensy / teensynofrendo / tft_t_dma.cpp
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