/* Based on C64 ILI9341 dma driver from Frank Bösing, 2017 */ #include "TFT_T_DMA.h" #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;jATTR_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(arx+arw)) || ((x+w)(ary+arh)) || ((y+h) 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> 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>6]; uint16_t * dst=&block[(y&0x3F)*TFT_WIDTH]; src=buffer; for (i=0; i>6]; dst=&block[(y&0x3F)*TFT_WIDTH]; src=buffer; for (i=0; i>6]; uint16_t * dst=&block[(y&0x3F)*TFT_WIDTH+(TFT_WIDTH-width)/2]; src=buffer; for (i=0; i>6]; dst=&block[(y&0x3F)*TFT_WIDTH+(TFT_WIDTH-width)/2]; src=buffer; for (i=0; i>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> 8]]; pos +=step; } #endif } else if ((width*2) == TFT_WIDTH) { for (int i=0; i>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> 8]; pos +=step; } #endif } else if ((width*2) == TFT_WIDTH) { for (int i=0; i>6]; uint16_t * dst=&block[(j&0x3F)*TFT_WIDTH]; for (i=0; i>6]; uint16_t * dst=&block[(l&0x3F)*TFT_WIDTH+x]; for (i=0; i>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)(ary+arh)) || ((y+h) 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>6]; uint16_t * dst=&block[(l&0x3F)*TFT_WIDTH+arx]; bmp_ptr = (uint16_t*)bitmap; for (int col=0;col