kopia lustrzana https://github.com/Jean-MarcHarvengt/MCUME
				
				
				
			
		
			
				
	
	
		
			1241 wiersze
		
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			1241 wiersze
		
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
	
| /*
 | |
|   Based on C64 ILI9341 dma driver from Frank Bösing, 2017
 | |
| */
 | |
| 
 | |
| #include "TFT_T_DMA.h"
 | |
| 
 | |
| #ifndef HAS_T4_VGA
 | |
| 
 | |
| #include "font8x8.h"
 | |
| 
 | |
| 
 | |
| #define SPICLOCK 60000000 //144e6 //Just a number..max speed
 | |
| #ifdef ILI9341
 | |
| #define SPI_MODE SPI_MODE0
 | |
| #endif
 | |
| #ifdef ST7789
 | |
| #define SPI_MODE SPI_MODE2
 | |
| #endif
 | |
| 
 | |
| // touch
 | |
| #define SPI_SETTING         SPISettings(2500000, MSBFIRST, SPI_MODE)
 | |
| #define XPT2046_CFG_START   _BV(7)
 | |
| #define XPT2046_CFG_MUX(v)  ((v&0b111) << (4))
 | |
| #define XPT2046_CFG_8BIT    _BV(3)
 | |
| #define XPT2046_CFG_12BIT   (0)
 | |
| #define XPT2046_CFG_SER     _BV(2)
 | |
| #define XPT2046_CFG_DFR     (0)
 | |
| #define XPT2046_CFG_PWR(v)  ((v&0b11))
 | |
| #define XPT2046_MUX_Y       0b101
 | |
| #define XPT2046_MUX_X       0b001
 | |
| #define XPT2046_MUX_Z1      0b011
 | |
| #define XPT2046_MUX_Z2      0b100
 | |
| 
 | |
| 
 | |
| #ifdef TFT_STATICFB
 | |
| static uint16_t fb0[LINES_PER_BLOCK*TFT_WIDTH];
 | |
| static uint16_t fb1[LINES_PER_BLOCK*TFT_WIDTH];
 | |
| static uint16_t fb2[LINES_PER_BLOCK*TFT_WIDTH];
 | |
| static uint16_t fb3[(TFT_HEIGHT-3*LINES_PER_BLOCK)*TFT_WIDTH];
 | |
| static uint16_t * blocks[NR_OF_BLOCK]={fb0,fb1,fb2,fb3};
 | |
| #else
 | |
| static uint16_t * blocks[NR_OF_BLOCK];
 | |
| #endif
 | |
| 
 | |
| 
 | |
| static DMASetting dmasettings[SCREEN_DMA_NUM_SETTINGS];
 | |
| static DMAChannel dmatx;//(false);
 | |
| static volatile uint8_t rstop = 0;
 | |
| static volatile bool cancelled = false;
 | |
| static volatile uint8_t curTransfer = 0;
 | |
| static uint8_t nbTransfer = 0;
 | |
| 
 | |
| 
 | |
| PROGMEM static const uint8_t init_commands[] = {
 | |
| #ifdef ILI9341  
 | |
|   4, 0xEF, 0x03, 0x80, 0x02,
 | |
|   4, 0xCF, 0x00, 0XC1, 0X30,
 | |
|   5, 0xED, 0x64, 0x03, 0X12, 0X81,
 | |
|   4, 0xE8, 0x85, 0x00, 0x78,
 | |
|   6, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02,
 | |
|   2, 0xF7, 0x20,
 | |
|   3, 0xEA, 0x00, 0x00,
 | |
|   2, ILI9341_PWCTR1, 0x23, // Power control
 | |
|   2, ILI9341_PWCTR2, 0x10, // Power control
 | |
|   3, ILI9341_VMCTR1, 0x3e, 0x28, // VCM control
 | |
|   2, ILI9341_VMCTR2, 0x86, // VCM control2
 | |
|   2, ILI9341_MADCTL, 0x48, // Memory Access Control
 | |
|   2, ILI9341_PIXFMT, 0x55,
 | |
|   3, ILI9341_FRMCTR1, 0x00, 0x18,
 | |
|   4, ILI9341_DFUNCTR, 0x08, 0x82, 0x27, // Display Function Control
 | |
|   2, 0xF2, 0x00, // Gamma Function Disable
 | |
|   2, ILI9341_GAMMASET, 0x01, // Gamma curve selected
 | |
|   16, ILI9341_GMCTRP1, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08,
 | |
|   0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, // Set Gamma
 | |
|   16, ILI9341_GMCTRN1, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07,
 | |
|   0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, // Set Gamma
 | |
| //  3, 0xb1, 0x00, 0x1f, // FrameRate Control 61Hz
 | |
|   3, 0xb1, 0x00, 0x10, // FrameRate Control 119Hz
 | |
|   2, ILI9341_MADCTL, ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR,
 | |
|   0
 | |
| #endif
 | |
| #ifdef ST7789
 | |
| #define DELAY 0x80
 | |
|     9,                       // 9 commands in list:
 | |
|     ST7735_SWRESET,   DELAY,  //  1: Software reset, no args, w/delay
 | |
|       150,                     //    150 ms delay
 | |
|     ST7735_SLPOUT ,   DELAY,  //  2: Out of sleep mode, no args, w/delay
 | |
|       255,                    //     255 = 500 ms delay
 | |
|     ST7735_COLMOD , 1+DELAY,  //  3: Set color mode, 1 arg + delay:
 | |
|       0x55,                   //     16-bit color
 | |
|       10,                     //     10 ms delay
 | |
|     ST7735_MADCTL , 1      ,  //  4: Memory access ctrl (directions), 1 arg:
 | |
|       0x08,                   //     Row addr/col addr, bottom to top refresh
 | |
|     ST7735_CASET  , 4      ,  //  5: Column addr set, 4 args, no delay:
 | |
|       0x00, 
 | |
|       0x00,                   //     XSTART = 0
 | |
|       0x00, 
 | |
|       240,                    //      XEND = 240
 | |
|     ST7735_RASET  , 4      ,  // 6: Row addr set, 4 args, no delay:
 | |
|       0x00, 
 | |
|       0x00,                   //     YSTART = 0
 | |
|       320>>8, 
 | |
|       320 & 0xFF,             //      YEND = 320
 | |
|     ST7735_INVON ,   DELAY,   // 7: hack
 | |
|       10,
 | |
|     ST7735_NORON  ,   DELAY,  // 8: Normal display on, no args, w/delay
 | |
|       10,                     //     10 ms delay
 | |
|     ST7735_DISPON ,   DELAY,  // 9: Main screen turn on, no args, w/delay
 | |
|     255
 | |
| #endif       
 | |
| };
 | |
| 
 | |
| static void dmaInterrupt() {
 | |
|   dmatx.clearInterrupt();
 | |
|   curTransfer++;
 | |
|   if (curTransfer >= nbTransfer) {
 | |
|     curTransfer = 0;
 | |
|     if (cancelled) {
 | |
|         dmatx.disable();
 | |
|         rstop = 1;
 | |
|     }
 | |
|   }
 | |
| #if defined(__IMXRT1052__) || defined(__IMXRT1062__)    
 | |
|   arm_dcache_flush(blocks[curTransfer], LINES_PER_BLOCK*TFT_WIDTH*2);
 | |
| #endif  
 | |
| }
 | |
| 
 | |
| static void setDmaStruct() {
 | |
|   uint32_t remaining = TFT_HEIGHT*TFT_WIDTH*2;
 | |
|   int i=0;
 | |
|   uint16_t col=RGBVAL16(0x00,0x00,0x00);;
 | |
|   while (remaining > 0) {
 | |
|     uint16_t * fb = blocks[i];
 | |
|     int32_t len = (remaining >= (LINES_PER_BLOCK*TFT_WIDTH*2)?LINES_PER_BLOCK*TFT_WIDTH*2:remaining);
 | |
| #ifdef TFT_DEBUG        
 | |
|     Serial.println((unsigned long)blocks[i]);    
 | |
|     Serial.println(remaining);
 | |
| #endif        
 | |
|     switch (i) {
 | |
|       case 0:
 | |
|         if (fb == 0) fb = (uint16_t*)((int)malloc(len+64)&0xffffffe0);
 | |
|         //fb=&fb0[0];
 | |
| #ifdef TFT_DEBUG        
 | |
|         col = RGBVAL16(0x00,0xff,0x00);
 | |
| #endif        
 | |
|         break;
 | |
|       case 1:
 | |
|         if (fb == 0) fb = (uint16_t*)((int)malloc(len+64)&0xffffffe0);
 | |
|         //fb=&fb1[0];
 | |
| #ifdef TFT_DEBUG        
 | |
|         col = RGBVAL16(0x00,0xff,0xff);
 | |
| #endif        
 | |
|         break;
 | |
|       case 2:
 | |
|         if (fb == 0) fb = (uint16_t*)((int)malloc(len+64)&0xffffffe0);
 | |
|         //fb=&fb2[0];
 | |
| #ifdef TFT_DEBUG        
 | |
|         col = RGBVAL16(0x00,0x00,0xff);
 | |
| #endif        
 | |
|         break;
 | |
|       case 3:
 | |
|         if (fb == 0) fb = (uint16_t*)((int)malloc(len+64)&0xffffffe0);
 | |
|         //fb=&fb3[0];
 | |
| #ifdef TFT_DEBUG        
 | |
|         col = RGBVAL16(0xff,0x00,0xff);
 | |
| #endif        
 | |
|         break;
 | |
|     }
 | |
|     blocks[i] = fb;
 | |
|     if (blocks[i] == 0) {
 | |
|       Serial.print("ILI9341 allocaltion failed for block ");
 | |
|       Serial.println(i);
 | |
|       delay(10000);    
 | |
|     }
 | |
|        
 | |
|     for (int j=0;j<len/2;j++) fb[j]=col;
 | |
| 
 | |
| #if defined(__IMXRT1052__) || defined(__IMXRT1062__)    
 | |
|     dmasettings[i].sourceBuffer(fb, len);
 | |
|     dmasettings[i].destination((uint8_t &)  LPSPI4_TDR);
 | |
|     dmasettings[i].TCD->ATTR_DST = 1;
 | |
| #else
 | |
|     dmasettings[i].sourceBuffer(fb, len);
 | |
|     dmasettings[i].destination((uint8_t &)  SPI0_PUSHR);
 | |
|     dmasettings[i].TCD->ATTR_DST = 1;
 | |
| #endif       
 | |
|     dmasettings[i].replaceSettingsOnCompletion(dmasettings[i+1]);
 | |
|     dmasettings[i].interruptAtCompletion();
 | |
|     remaining -= len;
 | |
|     i++;
 | |
|   }
 | |
|   dmasettings[i-1].replaceSettingsOnCompletion(dmasettings[0]);
 | |
|   nbTransfer = i;
 | |
| #ifdef TFT_DEBUG        
 | |
|   Serial.println(nbTransfer);
 | |
| #endif  
 | |
| }
 | |
| 
 | |
| 
 | |
| 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)
 | |
| {
 | |
|   _cs   = cs;
 | |
|   _dc   = dc;
 | |
|   _rst  = rst;
 | |
|   _mosi = mosi;
 | |
|   _sclk = sclk;
 | |
|   _miso = miso;
 | |
|   pinMode(_dc, OUTPUT);
 | |
|   pinMode(_cs, OUTPUT); 
 | |
|   digitalWrite(_cs, 1);
 | |
|   digitalWrite(_dc, 1);
 | |
|   if ( (touch_cs != 255) && (touch_irq != 255) ) {
 | |
|     _touch_irq = touch_irq;
 | |
|     _touch_cs = touch_cs;
 | |
|     pinMode(_touch_cs, OUTPUT);
 | |
|     pinMode(touch_irq, INPUT_PULLUP);  
 | |
|     digitalWrite(_touch_cs, 1);    
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TFT_T_DMA::setArea(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2) {
 | |
|   int dx=0;
 | |
|   int dy=0;
 | |
| #ifdef ST7789
 | |
|   if (TFT_REALWIDTH == TFT_REALHEIGHT)
 | |
|   {
 | |
| #ifdef ROTATE_SCREEN
 | |
|     if (!flipped) {
 | |
|       dy += 80;    
 | |
|     }
 | |
| #else  
 | |
|     if (flipped) {
 | |
|       dx += 80;    
 | |
|     }
 | |
| #endif      
 | |
|   }
 | |
| #endif  
 | |
| 
 | |
|   digitalWrite(_dc, 0);
 | |
|   SPI.transfer(TFT_CASET);
 | |
|   digitalWrite(_dc, 1);
 | |
|   SPI.transfer16(x1+dx);
 | |
|   digitalWrite(_dc, 1);
 | |
|   SPI.transfer16(x2+dx);  
 | |
|   digitalWrite(_dc, 0);
 | |
|   SPI.transfer(TFT_PASET);
 | |
|   digitalWrite(_dc, 1);
 | |
|   SPI.transfer16(y1+dy);
 | |
|   digitalWrite(_dc, 1);
 | |
|   SPI.transfer16(y2+dy);  
 | |
| 
 | |
|   digitalWrite(_dc, 0);
 | |
|   SPI.transfer(TFT_RAMWR);
 | |
|   digitalWrite(_dc, 1);
 | |
|   
 | |
|   return;
 | |
|   
 | |
| 
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   digitalWrite(_cs, 0);
 | |
| 
 | |
|   digitalWrite(_dc, 0);
 | |
|   SPI.transfer(TFT_CASET);
 | |
|   digitalWrite(_dc, 1);
 | |
| 
 | |
|   SPI.transfer16(x1+dx);
 | |
|   SPI.transfer16(x2+dx);
 | |
| 
 | |
|   digitalWrite(_dc, 0);
 | |
|   SPI.transfer(TFT_PASET);
 | |
|   digitalWrite(_dc, 1);
 | |
|   SPI.transfer16(y1+dy);
 | |
|   SPI.transfer16(y2+dy);
 | |
| 
 | |
|   digitalWrite(_dc, 0);
 | |
|   SPI.transfer(TFT_RAMWR);
 | |
|   digitalWrite(_dc, 1);
 | |
|   
 | |
|   digitalWrite(_cs, 1);
 | |
|   SPI.endTransaction();  
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| void TFT_T_DMA::begin(void) {
 | |
|   SPI.setMOSI(_mosi);
 | |
|   SPI.setMISO(_miso);
 | |
|   SPI.setSCK(_sclk);
 | |
|   SPI.begin();
 | |
|       
 | |
|   // Initialize display
 | |
|   if (_rst != 0xff) {
 | |
|     pinMode(_rst, OUTPUT);
 | |
|     digitalWrite(_rst, HIGH);
 | |
|     delay(100);
 | |
|     digitalWrite(_rst, LOW);
 | |
|     delay(100);
 | |
|     digitalWrite(_rst, HIGH);
 | |
|     delay(200);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   const uint8_t *addr = init_commands;
 | |
|   digitalWrite(_cs, 0);
 | |
| #ifdef ILI9341 
 | |
|   while (1) {
 | |
|     uint8_t count = *addr++;
 | |
|     if (count-- == 0) break;
 | |
| 
 | |
|     digitalWrite(_dc, 0);
 | |
|     SPI.transfer(*addr++);
 | |
| 
 | |
|     while (count-- > 0) {
 | |
|       digitalWrite(_dc, 1);
 | |
|       SPI.transfer(*addr++);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   digitalWrite(_dc, 0);
 | |
|   SPI.transfer(ILI9341_SLPOUT);
 | |
|   digitalWrite(_dc, 1);
 | |
|   digitalWrite(_cs, 1);
 | |
|   SPI.endTransaction();
 | |
| 
 | |
|   digitalWrite(_dc, 1);
 | |
|   digitalWrite(_cs, 1);
 | |
|   SPI.endTransaction();
 | |
| 
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   digitalWrite(_dc, 0);
 | |
|   digitalWrite(_cs, 0);
 | |
|   SPI.transfer(ILI9341_DISPON);
 | |
|   digitalWrite(_dc, 1);
 | |
|   digitalWrite(_cs, 1);
 | |
| #endif
 | |
| #ifdef ST7789 
 | |
|   uint8_t  numCommands, numArgs;
 | |
|   uint16_t ms;
 | |
|   numCommands = *addr++;    // Number of commands to follow
 | |
|   while(numCommands--) {        // For each command...
 | |
|     digitalWrite(_dc, 0);
 | |
|     SPI.transfer(*addr++);    
 | |
|     numArgs  = *addr++; //   Number of args to follow
 | |
|     ms       = numArgs & DELAY;   //   If hibit set, delay follows args
 | |
|     numArgs &= ~DELAY;      //   Mask out delay bit
 | |
|     while(numArgs > 1) {      //   For each argument...
 | |
|       digitalWrite(_dc, 1);
 | |
|       SPI.transfer(*addr++);
 | |
|       numArgs--;
 | |
|     }
 | |
| 
 | |
|     if (numArgs)  {
 | |
|       digitalWrite(_dc, 1);
 | |
|       SPI.transfer(*addr++);
 | |
|     }
 | |
|     if(ms) {
 | |
|       ms = *addr++; // Read post-command delay time (ms)
 | |
|       if(ms == 255) ms = 500;   // If 255, delay for 500 ms
 | |
|       digitalWrite(_cs, 1);
 | |
|       SPI.endTransaction();
 | |
|       delay(ms);
 | |
|       SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|       digitalWrite(_cs, 0);
 | |
|     }
 | |
|   }
 | |
|   digitalWrite(_cs, 1);
 | |
| #endif
 | |
|   setArea(0, 0, TFT_REALWIDTH-1, TFT_REALHEIGHT-1);  
 | |
|   SPI.endTransaction();
 | |
| 
 | |
|   cancelled = false;
 | |
| 
 | |
| #ifdef FLIP_SCREEN          
 | |
|   flipscreen(true);           
 | |
| #else
 | |
|   flipscreen(false);  
 | |
| #endif   
 | |
| #ifdef ST7789 
 | |
|   if (TFT_REALWIDTH != TFT_REALHEIGHT)
 | |
|   {
 | |
|     flipscreen(true);      
 | |
|   }
 | |
| #endif   
 | |
| };
 | |
| 
 | |
| 
 | |
|   
 | |
| void TFT_T_DMA::flipscreen(bool flip)
 | |
| {
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   digitalWrite(_dc, 0);
 | |
|   digitalWrite(_cs, 0);
 | |
|   SPI.transfer(TFT_MADCTL);
 | |
|   digitalWrite(_dc, 1);
 | |
|   if (flip) {
 | |
|     flipped=true;
 | |
| #ifdef ILI9341         
 | |
|     SPI.transfer(ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR);
 | |
| #endif
 | |
| #ifdef ST7789
 | |
| #ifdef ROTATE_SCREEN
 | |
|     SPI.transfer(ST77XX_MADCTL_RGB);
 | |
| #else
 | |
|     SPI.transfer(ST77XX_MADCTL_MY | ST77XX_MADCTL_MV |ST77XX_MADCTL_RGB);
 | |
| #endif
 | |
| #endif    
 | |
|   }
 | |
|   else {
 | |
|     flipped=false;
 | |
| #ifdef ILI9341        
 | |
|     SPI.transfer(ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR);
 | |
| #endif
 | |
| #ifdef ST7789
 | |
| #ifdef ROTATE_SCREEN
 | |
|     SPI.transfer(ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST77XX_MADCTL_RGB);
 | |
| #else
 | |
|     SPI.transfer(ST77XX_MADCTL_MX | ST77XX_MADCTL_MV | ST77XX_MADCTL_RGB);
 | |
| #endif
 | |
| #endif    
 | |
|   }
 | |
|   digitalWrite(_cs, 1);  
 | |
|   SPI.endTransaction();
 | |
| }
 | |
| 
 | |
| boolean TFT_T_DMA::isflipped(void)
 | |
| {
 | |
|   return(flipped);
 | |
| }
 | |
|   
 | |
| 
 | |
| #define PRREG(x) Serial.print(#x" 0x"); Serial.println(x,HEX)
 | |
| 
 | |
| 
 | |
| void TFT_T_DMA::startDMA(void) {
 | |
|   curTransfer = 0;  
 | |
|   rstop = 0;     
 | |
|   //dmatx.begin(true);
 | |
|   dmatx.attachInterrupt(dmaInterrupt);
 | |
|   setDmaStruct();
 | |
|   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);  
 | |
|   fillScreen(RGBVAL16(0x00,0x00,0x00));
 | |
|   
 | |
|   digitalWrite(_cs, HIGH);
 | |
|   SPI.begin();
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
 | |
| #if defined(__IMXRT1052__) || defined(__IMXRT1062__)
 | |
| 
 | |
| #ifdef TFT_DEBUG          
 | |
|   PRREG(LPSPI4_CCR);
 | |
|   PRREG(LPSPI4_TCR);
 | |
|   PRREG(LPSPI4_FCR);
 | |
|   Serial.printf("SPI CLOCK %d CCR freq %.1f MHz\n", SPICLOCK, 528. / 7 / ((0xff & LPSPI4_CCR) + 2));
 | |
| #endif
 | |
|   LPSPI4_CR &= ~LPSPI_CR_MEN;//disable LPSPI:
 | |
|   LPSPI4_CFGR1 |= LPSPI_CFGR1_NOSTALL; //prevent stall from RX
 | |
|   LPSPI4_TCR = 15; // Framesize 16 Bits
 | |
|   //LPSPI4_FCR = 0; // Fifo Watermark
 | |
|   LPSPI4_DER = LPSPI_DER_TDDE; //TX DMA Request Enable
 | |
|   LPSPI4_CR |= LPSPI_CR_MEN; //enable LPSPI:
 | |
|   dmatx.triggerAtHardwareEvent( DMAMUX_SOURCE_LPSPI4_TX );
 | |
| #else  
 | |
|   SPI0_RSER |= SPI_RSER_TFFF_DIRS | SPI_RSER_TFFF_RE;  // Set ILI_DMA Interrupt Request Select and Enable register
 | |
|   SPI0_MCR &= ~SPI_MCR_HALT;  //Start transfers.
 | |
|   SPI0_CTAR0 = SPI0_CTAR1;
 | |
|   (*(volatile uint16_t *)((int)&SPI0_PUSHR + 2)) = (SPI_PUSHR_CTAS(1) | SPI_PUSHR_CONT) >> 16; //Enable 16 Bit Transfers + Continue-Bit
 | |
|   dmatx.triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_TX );
 | |
| #endif
 | |
|   dmatx = dmasettings[0];
 | |
|   digitalWrite(_cs, 0); 
 | |
|   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);  
 | |
|   digitalWrite(_dc, 0);
 | |
|   SPI.transfer(TFT_RAMWR); 
 | |
|   digitalWrite(_dc, 1);      
 | |
|   dmatx.enable();
 | |
| }
 | |
| 
 | |
| 
 | |
| void TFT_T_DMA::stopDMA(void) {
 | |
|   rstop = 0;
 | |
|   wait();
 | |
|   delay(50);
 | |
|   cancelled = false;  
 | |
|   dmatx.detachInterrupt();
 | |
|   fillScreen(RGBVAL16(0x00,0x00,0x00));
 | |
|   SPI.end();
 | |
| #ifdef ST7789  
 | |
|   begin();
 | |
| #endif
 | |
| #ifdef ILI9341 
 | |
|   SPI.begin();
 | |
|   digitalWrite(_cs, 0);
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));  
 | |
|   SPI.endTransaction();
 | |
|   digitalWrite(_cs, 1);
 | |
|   digitalWrite(_dc, 1); 
 | |
| #endif    
 | |
|   setArea(0, 0, TFT_REALWIDTH-1, TFT_REALHEIGHT-1);    
 | |
| }
 | |
| 
 | |
| void TFT_T_DMA::wait(void) {
 | |
|   rstop = 1;
 | |
|   unsigned long m = millis(); 
 | |
|   cancelled = true; 
 | |
|   while (!rstop)  {
 | |
|     if ((millis() - m) > 100) break;
 | |
|     delay(10);
 | |
|     asm volatile("wfi");
 | |
|   };
 | |
|   rstop = 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| /***********************************************************************************************
 | |
|     Touch functions
 | |
|  ***********************************************************************************************/
 | |
| /* Code based on ...
 | |
|  *
 | |
|  * @file XPT2046.cpp
 | |
|  * @date 19.02.2016
 | |
|  * @author Markus Sattler
 | |
|  *
 | |
|  * Copyright (c) 2015 Markus Sattler. All rights reserved.
 | |
|  * This file is part of the XPT2046 driver for Arduino.
 | |
|  */
 | |
| 
 | |
| #define ADC_MAX                 0x0fff  
 | |
| 
 | |
| void TFT_T_DMA::enableTouchIrq() 
 | |
| {
 | |
|     SPI.beginTransaction(SPI_SETTING);
 | |
|     digitalWrite(_touch_cs, LOW);
 | |
|     const uint8_t buf[4] = { (XPT2046_CFG_START | XPT2046_CFG_12BIT | XPT2046_CFG_DFR | XPT2046_CFG_MUX(XPT2046_MUX_Y)), 0x00, 0x00, 0x00 };
 | |
|     SPI.transfer((void*)&buf[0],3);   
 | |
|     digitalWrite(_touch_cs, HIGH);
 | |
|     SPI.endTransaction();
 | |
| }
 | |
| 
 | |
| //Default callibration for non flipped
 | |
| #define TX_MIN 30
 | |
| #define TY_MIN 20
 | |
| #define TX_MAX 300
 | |
| #define TY_MAX 220
 | |
| 
 | |
| //Default callibration for flipped
 | |
| #define TFX_MIN 20
 | |
| #define TFY_MIN 25
 | |
| #define TFX_MAX 288
 | |
| #define TFY_MAX 221
 | |
| 
 | |
| static uint16_t txMin;
 | |
| static uint16_t tyMin;
 | |
| static uint16_t txMax;
 | |
| static uint16_t tyMax;
 | |
| 
 | |
|  
 | |
| void TFT_T_DMA::callibrateTouch(uint16_t xMin,uint16_t yMin,uint16_t xMax,uint16_t yMax)  {
 | |
|   if ( (xMin >= 0) && (yMin >= 0) && (xMax < 320) && (yMax < 200) ) {
 | |
|       txMin = xMin;
 | |
|       tyMin = yMin;
 | |
|       txMax = xMax;
 | |
|       tyMax = yMax;     
 | |
|   }
 | |
|   else {
 | |
|     if (flipped) {
 | |
|       txMin = TFX_MIN;
 | |
|       tyMin = TFY_MIN;
 | |
|       txMax = TFX_MAX;
 | |
|       tyMax = TFY_MAX;              
 | |
|     }
 | |
|     else {
 | |
|       txMin = TX_MIN;
 | |
|       tyMin = TY_MIN;
 | |
|       txMax = TX_MAX;
 | |
|       tyMax = TY_MAX;      
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TFT_T_DMA::readRaw(uint16_t * oX, uint16_t * oY, uint16_t * oZ) {
 | |
|   if ( TOUCH_ENABLED() ) {
 | |
|     uint16_t x = 0;
 | |
|     uint16_t y = 0;
 | |
|     uint16_t z1 = 0;
 | |
|     uint16_t z2 = 0;
 | |
|     uint8_t i = 0;
 | |
|     int16_t xraw=0, yraw=0;
 | |
|   
 | |
|     SPI.beginTransaction(SPI_SETTING);
 | |
|     digitalWrite(_touch_cs, LOW);
 | |
|   
 | |
|     for(; i < 15; i++) {
 | |
|       // SPI requirer 32bit aliment
 | |
|       uint8_t buf[12] = {
 | |
|         (XPT2046_CFG_START | XPT2046_CFG_12BIT | XPT2046_CFG_DFR | XPT2046_CFG_MUX(XPT2046_MUX_Y) | XPT2046_CFG_PWR(3)), 0x00, 0x00,
 | |
|         (XPT2046_CFG_START | XPT2046_CFG_12BIT | XPT2046_CFG_DFR | XPT2046_CFG_MUX(XPT2046_MUX_X) | XPT2046_CFG_PWR(3)), 0x00, 0x00,
 | |
|         (XPT2046_CFG_START | XPT2046_CFG_12BIT | XPT2046_CFG_DFR | XPT2046_CFG_MUX(XPT2046_MUX_Z1)| XPT2046_CFG_PWR(3)), 0x00, 0x00,
 | |
|         (XPT2046_CFG_START | XPT2046_CFG_12BIT | XPT2046_CFG_DFR | XPT2046_CFG_MUX(XPT2046_MUX_Z2)| XPT2046_CFG_PWR(3)), 0x00, 0x00
 | |
|       };
 | |
|       SPI.transfer(&buf[0], &buf[0], 12);
 | |
|       y += (buf[1] << 8 | buf[2])>>3;
 | |
|       x += (buf[4] << 8 | buf[5])>>3;
 | |
|       z1 += (buf[7] << 8 | buf[8])>>3;
 | |
|       z2 += (buf[10] << 8 | buf[11])>>3;
 | |
|     }
 | |
|     enableTouchIrq();
 | |
|   
 | |
|     if(i == 0) {
 | |
|         *oX = 0;
 | |
|         *oY = 0;
 | |
|         *oZ = 0;
 | |
|     }
 | |
|     else {
 | |
|         x /= i;
 | |
|         y /= i;
 | |
|         z1 /= i;
 | |
|         z2 /= i;
 | |
|     }
 | |
|   
 | |
|     digitalWrite(_touch_cs, HIGH);
 | |
|     SPI.endTransaction();
 | |
|     int z = z1 + ADC_MAX - z2;
 | |
|     if (flipped) {
 | |
|       xraw = x;
 | |
|       yraw = y;
 | |
|     } else {
 | |
|       xraw = ADC_MAX - x;
 | |
|       yraw = ADC_MAX - y;
 | |
|     }
 | |
|     xraw=(xraw*TFT_REALWIDTH)/(ADC_MAX+1);
 | |
|     yraw=(yraw*TFT_REALHEIGHT)/(ADC_MAX+1);
 | |
|   
 | |
|     *oX = xraw;
 | |
|     *oY = yraw;
 | |
|     *oZ = z;
 | |
|   }
 | |
|   else 
 | |
|   {
 | |
|     *oX = 0;
 | |
|     *oY = 0;
 | |
|     *oZ = 0;    
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TFT_T_DMA::readCal(uint16_t * oX, uint16_t * oY, uint16_t * oZ) {
 | |
|   readRaw(oX,oY,oZ);
 | |
|   // callibrate ...
 | |
|   if(*oX >= txMin) *oX = ((*oX - txMin)*TFT_REALWIDTH)/(txMax-txMin);
 | |
|   if(*oY >= tyMin) *oY = ((*oY - tyMin)*TFT_REALHEIGHT)/(tyMax-tyMin);
 | |
|   //Serial.print(*oX);
 | |
|   //Serial.print(" ");
 | |
|   //Serial.println(*oY);
 | |
| }
 | |
| 
 | |
| 
 | |
| /***********************************************************************************************
 | |
|     No DMA functions
 | |
|  ***********************************************************************************************/
 | |
| void TFT_T_DMA::fillScreenNoDma(uint16_t color) {
 | |
|   
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   digitalWrite(_cs, 0);
 | |
|   setArea(0, 0, TFT_REALWIDTH-1, TFT_REALHEIGHT-1);  
 | |
|   //digitalWrite(_dc, 0);
 | |
|   //SPI.transfer(TFT_RAMWR);
 | |
|   int i,j;
 | |
|   for (j=0; j<TFT_REALHEIGHT; j++)
 | |
|   {
 | |
|     for (i=0; i<TFT_REALWIDTH; i++) {
 | |
|       //digitalWrite(_dc, 1);
 | |
|       SPI.transfer16(color);     
 | |
|     }
 | |
|   }
 | |
| #ifdef ILI9341  
 | |
|   digitalWrite(_dc, 0);
 | |
|   SPI.transfer(ILI9341_SLPOUT);
 | |
|   digitalWrite(_dc, 1);
 | |
| #endif
 | |
|   digitalWrite(_cs, 1);
 | |
|   setArea(0, 0, (TFT_REALWIDTH-1), (TFT_REALHEIGHT-1));  
 | |
|   SPI.endTransaction();    
 | |
| }
 | |
| 
 | |
| void TFT_T_DMA::drawRectNoDma(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   digitalWrite(_cs, 0);
 | |
|   setArea(x,y,x+w-1,y+h-1);
 | |
| //  digitalWrite(_dc, 0);
 | |
| //  SPI.transfer(TFT_RAMWR);
 | |
|   int i;
 | |
|   for (i=0; i<(w*h); i++)
 | |
|   {
 | |
|     //digitalWrite(_dc, 1);
 | |
|     SPI.transfer16(color);
 | |
|   }
 | |
| #ifdef ILI9341  
 | |
|   digitalWrite(_dc, 0);
 | |
|   SPI.transfer(ILI9341_SLPOUT);
 | |
|   digitalWrite(_dc, 1);
 | |
| #endif
 | |
|   digitalWrite(_cs, 1);
 | |
|   setArea(0, 0, (TFT_REALWIDTH-1), (TFT_REALHEIGHT-1));
 | |
|   SPI.endTransaction();    
 | |
| }
 | |
| 
 | |
| void TFT_T_DMA::writeScreenNoDma(const uint16_t *pcolors) {  
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   digitalWrite(_cs, 0);
 | |
|   setArea(0, 0, TFT_WIDTH-1, TFT_HEIGHT-1);  
 | |
|   //digitalWrite(_dc, 0);
 | |
|   //SPI.transfer(TFT_RAMWR);
 | |
|   int i,j;
 | |
|   for (j=0; j<240; j++)
 | |
|   {
 | |
|     for (i=0; i<TFT_WIDTH; i++) {
 | |
|  //     digitalWrite(_dc, 1);
 | |
|       SPI.transfer16(*pcolors++);     
 | |
|     }
 | |
|   }
 | |
| #ifdef ILI9341  
 | |
|   digitalWrite(_dc, 0);
 | |
|   SPI.transfer(ILI9341_SLPOUT);
 | |
|   digitalWrite(_dc, 1);
 | |
| #endif
 | |
|   digitalWrite(_cs, 1);
 | |
|   setArea(0, 0, (TFT_REALWIDTH-1), (TFT_REALHEIGHT-1));  
 | |
|   SPI.endTransaction();    
 | |
| }
 | |
| 
 | |
| void TFT_T_DMA::drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap) {
 | |
|     drawSpriteNoDma(x,y,bitmap, 0,0,0,0);
 | |
| }
 | |
| 
 | |
| 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)
 | |
| {
 | |
|   int bmp_offx = 0;
 | |
|   int bmp_offy = 0;
 | |
|   uint16_t *bmp_ptr;
 | |
|     
 | |
|   int w =*bitmap++;
 | |
|   int h = *bitmap++;
 | |
| //Serial.println(w);
 | |
| //Serial.println(h);
 | |
| 
 | |
|   if ( (arw == 0) || (arh == 0) ) {
 | |
|     // no crop window
 | |
|     arx = x;
 | |
|     ary = y;
 | |
|     arw = w;
 | |
|     arh = h;
 | |
|   }
 | |
|   else {
 | |
|     if ( (x>(arx+arw)) || ((x+w)<arx) || (y>(ary+arh)) || ((y+h)<ary)   ) {
 | |
|       return;
 | |
|     }
 | |
|     
 | |
|     // crop area
 | |
|     if ( (x > arx) && (x<(arx+arw)) ) { 
 | |
|       arw = arw - (x-arx);
 | |
|       arx = arx + (x-arx);
 | |
|     } else {
 | |
|       bmp_offx = arx;
 | |
|     }
 | |
|     if ( ((x+w) > arx) && ((x+w)<(arx+arw)) ) {
 | |
|       arw -= (arx+arw-x-w);
 | |
|     }  
 | |
|     if ( (y > ary) && (y<(ary+arh)) ) {
 | |
|       arh = arh - (y-ary);
 | |
|       ary = ary + (y-ary);
 | |
|     } else {
 | |
|       bmp_offy = ary;
 | |
|     }
 | |
|     if ( ((y+h) > ary) && ((y+h)<(ary+arh)) ) {
 | |
|       arh -= (ary+arh-y-h);
 | |
|     }     
 | |
|   }
 | |
| 
 | |
|   
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   digitalWrite(_cs, 0);
 | |
|   setArea(arx, ary, arx+arw-1, ary+arh-1);  
 | |
|   //digitalWrite(_dc, 0);
 | |
|   //SPI.transfer(TFT_RAMWR);      
 | |
| 
 | |
|   bitmap = bitmap + bmp_offy*w + bmp_offx;
 | |
|   for (int row=0;row<arh; row++)
 | |
|   {
 | |
|     bmp_ptr = (uint16_t*)bitmap;
 | |
|     for (int col=0;col<arw; col++)
 | |
|     {
 | |
|         uint16_t color = *bmp_ptr++;
 | |
| //        digitalWrite(_dc, 1);
 | |
|         SPI.transfer16(color);             
 | |
|     } 
 | |
|     bitmap +=  w;
 | |
|   }
 | |
| #ifdef ILI9341  
 | |
|   digitalWrite(_dc, 0);
 | |
|   SPI.transfer(ILI9341_SLPOUT);
 | |
|   digitalWrite(_dc, 1);
 | |
| #endif
 | |
|   setArea(0, 0, TFT_REALWIDTH-1, TFT_REALHEIGHT-1);  
 | |
|   digitalWrite(_cs, 1);
 | |
|   SPI.endTransaction();   
 | |
| }
 | |
| 
 | |
| void TFT_T_DMA::drawTextNoDma(int16_t x, int16_t y, const char * text, uint16_t fgcolor, uint16_t bgcolor, bool doublesize) {
 | |
|   uint16_t c;
 | |
|   while ((c = *text++)) {
 | |
|     const unsigned char * charpt=&font8x8[c][0];
 | |
| 
 | |
|   
 | |
|     SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|     digitalWrite(_cs, 0);
 | |
|     setArea(x,y,x+7,y+(doublesize?15:7));
 | |
|     //digitalWrite(_dc, 0);
 | |
|     //SPI.transfer(TFT_RAMWR);
 | |
|     //digitalWrite(_dc, 1);
 | |
|     for (int i=0;i<8;i++)
 | |
|     {
 | |
|       unsigned char bits;
 | |
|       if (doublesize) {
 | |
|         bits = *charpt;     
 | |
|         //digitalWrite(_dc, 1);
 | |
|         if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|         else SPI.transfer16(bgcolor);
 | |
|         bits = bits >> 1;     
 | |
|         if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|         else SPI.transfer16(bgcolor);
 | |
|         bits = bits >> 1;     
 | |
|         if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|         else SPI.transfer16(bgcolor);
 | |
|         bits = bits >> 1;     
 | |
|         if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|         else SPI.transfer16(bgcolor);
 | |
|         bits = bits >> 1;     
 | |
|         if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|         else SPI.transfer16(bgcolor);
 | |
|         bits = bits >> 1;     
 | |
|         if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|         else SPI.transfer16(bgcolor);
 | |
|         bits = bits >> 1;     
 | |
|         if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|         else SPI.transfer16(bgcolor);
 | |
|         bits = bits >> 1;     
 | |
|         if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|         else SPI.transfer16(bgcolor);       
 | |
|       }
 | |
|       bits = *charpt++;     
 | |
|       //digitalWrite(_dc, 1);
 | |
|       if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|       else SPI.transfer16(bgcolor);
 | |
|       bits = bits >> 1;     
 | |
|       if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|       else SPI.transfer16(bgcolor);
 | |
|       bits = bits >> 1;     
 | |
|       if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|       else SPI.transfer16(bgcolor);
 | |
|       bits = bits >> 1;     
 | |
|       if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|       else SPI.transfer16(bgcolor);
 | |
|       bits = bits >> 1;     
 | |
|       if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|       else SPI.transfer16(bgcolor);
 | |
|       bits = bits >> 1;     
 | |
|       if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|       else SPI.transfer16(bgcolor);
 | |
|       bits = bits >> 1;     
 | |
|       if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|       else SPI.transfer16(bgcolor);
 | |
|       bits = bits >> 1;     
 | |
|       if (bits&0x01) SPI.transfer16(fgcolor);
 | |
|       else SPI.transfer16(bgcolor);
 | |
|     }
 | |
|     x +=8;
 | |
| #ifdef ILI9341  
 | |
|   digitalWrite(_dc, 0);
 | |
|   SPI.transfer(ILI9341_SLPOUT);
 | |
|   digitalWrite(_dc, 1);
 | |
| #endif
 | |
|     digitalWrite(_cs, 1);
 | |
|     SPI.endTransaction();  
 | |
|   }
 | |
|   
 | |
|   SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 | |
|   digitalWrite(_cs, 0);
 | |
|   setArea(0, 0, (TFT_REALWIDTH-1), (TFT_REALHEIGHT-1));  
 | |
|   digitalWrite(_cs, 1);
 | |
|   SPI.endTransaction();  
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /***********************************************************************************************
 | |
|     DMA functions
 | |
|  ***********************************************************************************************/
 | |
| uint16_t * TFT_T_DMA::getLineBuffer(int j)
 | |
| {
 | |
|   uint16_t * block=blocks[j>>6];  
 | |
|   return(&block[(j&0x3F)*TFT_REALWIDTH]);
 | |
| }
 | |
| 
 | |
| void TFT_T_DMA::writeScreen(int width, int height, int stride, uint8_t *buf, uint16_t *palette16) {
 | |
|   uint8_t *buffer=buf;
 | |
|   uint8_t *src; 
 | |
| 
 | |
|   int i,j,y=0;
 | |
|   if (width*2 <= TFT_REALWIDTH) {
 | |
|     for (j=0; j<height; j++)
 | |
|     {
 | |
|       uint16_t * block=blocks[y>>6];
 | |
|       uint16_t * dst=&block[(y&0x3F)*TFT_WIDTH];        
 | |
|       src=buffer;
 | |
|       for (i=0; i<width; i++)
 | |
|       {
 | |
|         uint16_t val = palette16[*src++];
 | |
|         *dst++ = val;
 | |
|         *dst++ = val;
 | |
|       }
 | |
|       y++;
 | |
|       if (height*2 <= TFT_HEIGHT) {
 | |
|         block=blocks[y>>6];
 | |
|         dst=&block[(y&0x3F)*TFT_WIDTH];          
 | |
|         src=buffer;
 | |
|         for (i=0; i<width; i++)
 | |
|         {
 | |
|           uint16_t val = palette16[*src++];
 | |
|           *dst++ = val;
 | |
|           *dst++ = val;
 | |
|         }
 | |
|         y++;      
 | |
|       } 
 | |
|       buffer += stride;      
 | |
|     }
 | |
|   }
 | |
|   else if (width <= TFT_REALWIDTH) {
 | |
|     //dst += (TFT_WIDTH-width)/2;
 | |
|     for (j=0; j<height; j++)
 | |
|     {
 | |
|       uint16_t * block=blocks[y>>6];
 | |
|       uint16_t * dst=&block[(y&0x3F)*TFT_WIDTH+(TFT_WIDTH-width)/2];         
 | |
|       src=buffer;
 | |
|       for (i=0; i<width; i++)
 | |
|       {
 | |
|         uint16_t val = palette16[*src++];
 | |
|         *dst++ = val;
 | |
|       }
 | |
|       y++;
 | |
|       if (height*2 <= TFT_HEIGHT) {
 | |
|         block=blocks[y>>6];
 | |
|         dst=&block[(y&0x3F)*TFT_WIDTH+(TFT_WIDTH-width)/2];        
 | |
|         src=buffer;
 | |
|         for (i=0; i<width; i++)
 | |
|         {
 | |
|           uint16_t val = palette16[*src++];
 | |
|           *dst++ = val;
 | |
|         }
 | |
|         y++;
 | |
|       }      
 | |
|       buffer += stride;  
 | |
|     }
 | |
|   }   
 | |
| }
 | |
| 
 | |
| void TFT_T_DMA::writeLine(int width, int height, int y, uint8_t *buf, uint16_t *palette16) {
 | |
|   uint16_t * block=blocks[y>>6];
 | |
|   uint16_t * dst=&block[(y&0x3F)*TFT_WIDTH]; 
 | |
|   if (width > TFT_WIDTH) {
 | |
| #ifdef TFT_LINEARINT    
 | |
|     int delta = (width/(width-TFT_WIDTH))-1;
 | |
|     int pos = delta;
 | |
|     for (int i=0; i<TFT_WIDTH; i++)
 | |
|     {
 | |
|       uint16_t val = palette16[*buf++];
 | |
|       pos--;      
 | |
|       if (pos == 0) {
 | |
| #ifdef LINEARINT_HACK        
 | |
|         val  = ((uint32_t)palette16[*buf++] + val)/2;
 | |
| #else
 | |
|         uint16_t val2 = *buf++;
 | |
|         val = RGBVAL16((R16(val)+R16(val2))/2,(G16(val)+G16(val2))/2,(B16(val)+B16(val2))/2);
 | |
| #endif        
 | |
|         pos = delta;
 | |
|       }
 | |
|       *dst++=val;
 | |
|     }
 | |
| #else
 | |
|     int step = ((width << 8)/TFT_WIDTH);
 | |
|     int pos = 0;
 | |
|     for (int i=0; i<TFT_WIDTH; i++)
 | |
|     {
 | |
|       *dst++=palette16[buf[pos >> 8]];
 | |
|       pos +=step;
 | |
|     }  
 | |
| #endif       
 | |
|   }
 | |
|   else if ((width*2) == TFT_WIDTH) {
 | |
|     for (int i=0; i<width; i++)
 | |
|     {
 | |
|       *dst++=palette16[*buf];
 | |
|       *dst++=palette16[*buf++];
 | |
|     }       
 | |
|   }
 | |
|   else {
 | |
|     if (width <= TFT_WIDTH) {
 | |
|       dst += (TFT_WIDTH-width)/2;
 | |
|     }
 | |
|     for (int i=0; i<width; i++)
 | |
|     {
 | |
|       *dst++=palette16[*buf++];
 | |
|     }       
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TFT_T_DMA::writeLine(int width, int height, int y, uint16_t *buf) {
 | |
|   uint16_t * block=blocks[y>>6];
 | |
|   uint16_t * dst=&block[(y&0x3F)*TFT_WIDTH];  
 | |
|   if (width > TFT_WIDTH) {
 | |
| #ifdef TFT_LINEARINT   
 | |
|     int delta = (width/(width-TFT_WIDTH))-1;   
 | |
|     int pos = delta;
 | |
|     for (int i=0; i<TFT_WIDTH; i++)
 | |
|     {
 | |
|       uint16_t val = *buf++;
 | |
|       pos--;      
 | |
|       if (pos == 0) {
 | |
| #ifdef LINEARINT_HACK        
 | |
|         val  = ((uint32_t)*buf++ + val)/2;
 | |
| #else
 | |
|         uint16_t val2 = *buf++;
 | |
|         val = RGBVAL16((R16(val)+R16(val2))/2,(G16(val)+G16(val2))/2,(B16(val)+B16(val2))/2);
 | |
| #endif        
 | |
|         pos = delta;
 | |
|       }
 | |
|       *dst++=val;
 | |
|     }
 | |
| #else
 | |
|     int step = ((width << 8)/TFT_WIDTH);
 | |
|     int pos = 0;
 | |
|     for (int i=0; i<TFT_WIDTH; i++)
 | |
|     {
 | |
|       *dst++=buf[pos >> 8];
 | |
|       pos +=step;
 | |
|     }  
 | |
| #endif       
 | |
|   }
 | |
|   else if ((width*2) == TFT_WIDTH) {
 | |
|     for (int i=0; i<width; i++)
 | |
|     {
 | |
|       *dst++=*buf;
 | |
|       *dst++=*buf++;
 | |
|     }       
 | |
|   }
 | |
|   else {
 | |
|     if (width <= TFT_WIDTH) {
 | |
|       dst += (TFT_WIDTH-width)/2;
 | |
|     }
 | |
|     for (int i=0; i<width; i++)
 | |
|     {
 | |
|       *dst++=*buf++;
 | |
|     }       
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TFT_T_DMA::fillScreen(uint16_t color) {
 | |
|   int i,j;
 | |
|   for (j=0; j<TFT_HEIGHT; j++)
 | |
|   {
 | |
|     uint16_t * block=blocks[j>>6];
 | |
|     uint16_t * dst=&block[(j&0x3F)*TFT_WIDTH];
 | |
|     for (i=0; i<TFT_WIDTH; i++)
 | |
|     {
 | |
|       *dst++ = color;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TFT_T_DMA::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
 | |
|   int i,j,l=y;
 | |
|   color=color;
 | |
|   for (j=0; j<h; j++)
 | |
|   {
 | |
|     uint16_t * block=blocks[l>>6];
 | |
|     uint16_t * dst=&block[(l&0x3F)*TFT_WIDTH+x];
 | |
|     for (i=0; i<w; i++)
 | |
|     {
 | |
|       *dst++ = color;
 | |
|     }
 | |
|     l++;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TFT_T_DMA::drawText(int16_t x, int16_t y, const char * text, uint16_t fgcolor, uint16_t bgcolor, bool doublesize) {
 | |
|   uint16_t c;
 | |
|   uint16_t * block;
 | |
|   uint16_t * dst;
 | |
|   fgcolor = fgcolor;
 | |
|   bgcolor = bgcolor;
 | |
|   
 | |
|   while ((c = *text++)) {
 | |
|     const unsigned char * charpt=&font8x8[c][0];
 | |
| 
 | |
|     int l=y;
 | |
|     for (int i=0;i<8;i++)
 | |
|     {     
 | |
|       unsigned char bits;
 | |
|       if (doublesize) {
 | |
|         block=blocks[l>>6];
 | |
|         dst=&block[(l&0x3F)*TFT_WIDTH+x];         
 | |
|         bits = *charpt;     
 | |
|         if (bits&0x01) *dst++=fgcolor;
 | |
|         else *dst++=bgcolor;
 | |
|         bits = bits >> 1;     
 | |
|         if (bits&0x01) *dst++=fgcolor;
 | |
|         else *dst++=bgcolor;
 | |
|         bits = bits >> 1;     
 | |
|         if (bits&0x01) *dst++=fgcolor;
 | |
|         else *dst++=bgcolor;
 | |
|         bits = bits >> 1;     
 | |
|         if (bits&0x01) *dst++=fgcolor;
 | |
|         else *dst++=bgcolor;
 | |
|         bits = bits >> 1;     
 | |
|         if (bits&0x01) *dst++=fgcolor;
 | |
|         else *dst++=bgcolor;
 | |
|         bits = bits >> 1;     
 | |
|         if (bits&0x01) *dst++=fgcolor;
 | |
|         else *dst++=bgcolor;
 | |
|         bits = bits >> 1;     
 | |
|         if (bits&0x01) *dst++=fgcolor;
 | |
|         else *dst++=bgcolor;
 | |
|         bits = bits >> 1;     
 | |
|         if (bits&0x01) *dst++=fgcolor;
 | |
|         else *dst++=bgcolor;
 | |
|         l++;       
 | |
|       }
 | |
|       block=blocks[l>>6];
 | |
|       dst=&block[(l&0x3F)*TFT_WIDTH+x]; 
 | |
|       bits = *charpt++;     
 | |
|       if (bits&0x01) *dst++=fgcolor;
 | |
|       else *dst++=bgcolor;
 | |
|       bits = bits >> 1;     
 | |
|       if (bits&0x01) *dst++=fgcolor;
 | |
|       else *dst++=bgcolor;
 | |
|       bits = bits >> 1;     
 | |
|       if (bits&0x01) *dst++=fgcolor;
 | |
|       else *dst++=bgcolor;
 | |
|       bits = bits >> 1;     
 | |
|       if (bits&0x01) *dst++=fgcolor;
 | |
|       else *dst++=bgcolor;
 | |
|       bits = bits >> 1;     
 | |
|       if (bits&0x01) *dst++=fgcolor;
 | |
|       else *dst++=bgcolor;
 | |
|       bits = bits >> 1;     
 | |
|       if (bits&0x01) *dst++=fgcolor;
 | |
|       else *dst++=bgcolor;
 | |
|       bits = bits >> 1;     
 | |
|       if (bits&0x01) *dst++=fgcolor;
 | |
|       else *dst++=bgcolor;
 | |
|       bits = bits >> 1;     
 | |
|       if (bits&0x01) *dst++=fgcolor;
 | |
|       else *dst++=bgcolor;
 | |
|       l++;
 | |
|     }
 | |
|     x +=8;
 | |
|   } 
 | |
| }
 | |
| 
 | |
| void TFT_T_DMA::drawSprite(int16_t x, int16_t y, const uint16_t *bitmap) {
 | |
|     drawSprite(x,y,bitmap, 0,0,0,0);
 | |
| }
 | |
| 
 | |
| 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)
 | |
| {
 | |
|   int bmp_offx = 0;
 | |
|   int bmp_offy = 0;
 | |
|   uint16_t *bmp_ptr;
 | |
|     
 | |
|   int w =*bitmap++;
 | |
|   int h = *bitmap++;
 | |
| 
 | |
| 
 | |
|   if ( (arw == 0) || (arh == 0) ) {
 | |
|     // no crop window
 | |
|     arx = x;
 | |
|     ary = y;
 | |
|     arw = w;
 | |
|     arh = h;
 | |
|   }
 | |
|   else {
 | |
|     if ( (x>(arx+arw)) || ((x+w)<arx) || (y>(ary+arh)) || ((y+h)<ary)   ) {
 | |
|       return;
 | |
|     }
 | |
|     
 | |
|     // crop area
 | |
|     if ( (x > arx) && (x<(arx+arw)) ) { 
 | |
|       arw = arw - (x-arx);
 | |
|       arx = arx + (x-arx);
 | |
|     } else {
 | |
|       bmp_offx = arx;
 | |
|     }
 | |
|     if ( ((x+w) > arx) && ((x+w)<(arx+arw)) ) {
 | |
|       arw -= (arx+arw-x-w);
 | |
|     }  
 | |
|     if ( (y > ary) && (y<(ary+arh)) ) {
 | |
|       arh = arh - (y-ary);
 | |
|       ary = ary + (y-ary);
 | |
|     } else {
 | |
|       bmp_offy = ary;
 | |
|     }
 | |
|     if ( ((y+h) > ary) && ((y+h)<(ary+arh)) ) {
 | |
|       arh -= (ary+arh-y-h);
 | |
|     }     
 | |
|   }
 | |
| 
 | |
|    
 | |
|   int l=ary;
 | |
|   bitmap = bitmap + bmp_offy*w + bmp_offx;
 | |
|   for (int row=0;row<arh; row++)
 | |
|   {
 | |
|     uint16_t * block=blocks[l>>6];
 | |
|     uint16_t * dst=&block[(l&0x3F)*TFT_WIDTH+arx];  
 | |
|     bmp_ptr = (uint16_t*)bitmap;
 | |
|     for (int col=0;col<arw; col++)
 | |
|     {
 | |
|         *dst++ = *bmp_ptr++;            
 | |
|     } 
 | |
|     bitmap +=  w;
 | |
|     l++;
 | |
|   } 
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| 
 |