#include "TFT_ILI9163C.h" #include #include "pins_arduino.h" #include "wiring_private.h" #include #if defined(SPI_HAS_TRANSACTION) static SPISettings ILI9163C_SPI; #endif //constructors #if defined(__MK20DX128__) || defined(__MK20DX256__) TFT_ILI9163C::TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin,uint8_t mosi,uint8_t sclk) : Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT) { _cs = cspin; _rs = dcpin; _rst = rstpin; _mosi = mosi; _sclk = sclk; } #elif defined(__MKL26Z64__) TFT_ILI9163C::TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin,uint8_t mosi,uint8_t sclk) : Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT) { _cs = cspin; _rs = dcpin; _rst = rstpin; _mosi = mosi; _sclk = sclk; _useSPI1 = false; if ((_mosi == 0 || _mosi == 21) && (_sclk == 20)) _useSPI1 = true; } #else TFT_ILI9163C::TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin) : Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT) { _cs = cspin; _rs = dcpin; _rst = rstpin; } #endif //Arduino Uno, Leonardo, Mega, Teensy 2.0, etc #if defined(__AVR__) inline void TFT_ILI9163C::spiwrite(uint8_t c) { SPDR = c; while(!(SPSR & _BV(SPIF))); } void TFT_ILI9163C::writecommand(uint8_t c) { #if defined(SPI_HAS_TRANSACTION) SPI.beginTransaction(ILI9163C_SPI); #endif *rsport &= ~rspinmask;//low *csport &= ~cspinmask;//low spiwrite(c); *csport |= cspinmask;//hi #if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif } void TFT_ILI9163C::writedata(uint8_t c) { #if defined(SPI_HAS_TRANSACTION) SPI.beginTransaction(ILI9163C_SPI); #endif *rsport |= rspinmask;//hi *csport &= ~cspinmask;//low spiwrite(c); *csport |= cspinmask;//hi #if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif } void TFT_ILI9163C::writedata16(uint16_t d) { #if defined(SPI_HAS_TRANSACTION) SPI.beginTransaction(ILI9163C_SPI); #endif *rsport |= rspinmask;//hi *csport &= ~cspinmask;//low spiwrite(d >> 8); spiwrite(d); *csport |= cspinmask;//hi #if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif } void TFT_ILI9163C::setBitrate(uint32_t n) { #if !defined (SPI_HAS_TRANSACTION) if (n >= 8000000) { SPI.setClockDivider(SPI_CLOCK_DIV2); } else if (n >= 4000000) { SPI.setClockDivider(SPI_CLOCK_DIV4); } else if (n >= 2000000) { SPI.setClockDivider(SPI_CLOCK_DIV8); } else { SPI.setClockDivider(SPI_CLOCK_DIV16); } #endif } #elif defined(__SAM3X8E__)// Arduino Due inline void TFT_ILI9163C::spiwrite(uint8_t c) { SPI.transfer(c); } void TFT_ILI9163C::writecommand(uint8_t c) { #if defined(SPI_HAS_TRANSACTION) SPI.beginTransaction(ILI9163C_SPI); #endif rsport->PIO_CODR |= rspinmask;//LO csport->PIO_CODR |= cspinmask;//LO spiwrite(c); csport->PIO_SODR |= cspinmask;//HI #if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif } void TFT_ILI9163C::writedata(uint8_t c) { #if defined(SPI_HAS_TRANSACTION) SPI.beginTransaction(ILI9163C_SPI); #endif rsport->PIO_SODR |= rspinmask;//HI csport->PIO_CODR |= cspinmask;//LO spiwrite(c); csport->PIO_SODR |= cspinmask;//HI #if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif } void TFT_ILI9163C::writedata16(uint16_t d) { #if defined(SPI_HAS_TRANSACTION) SPI.beginTransaction(ILI9163C_SPI); #endif rsport->PIO_SODR |= rspinmask;//HI csport->PIO_CODR |= cspinmask;//LO spiwrite(d >> 8); spiwrite(d); csport->PIO_SODR |= cspinmask;//HI #if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif } void TFT_ILI9163C::setBitrate(uint32_t n) { #if !defined(SPI_HAS_TRANSACTION) uint32_t divider = 1; while (divider < 255) { if (n >= 84000000 / divider) break; divider = divider - 1; } SPI.setClockDivider(divider); #endif } #elif defined(__MKL26Z64__)//Teensy LC (preliminary void TFT_ILI9163C::writecommand(uint8_t c) { if (_useSPI1){ SPI1.beginTransaction(ILI9163C_SPI); digitalWriteFast(_rs,LOW); digitalWriteFast(_cs,LOW); SPI1.transfer(c); digitalWriteFast(_cs,HIGH); SPI1.endTransaction(); } else { SPI.beginTransaction(ILI9163C_SPI); digitalWriteFast(_rs,LOW); digitalWriteFast(_cs,LOW); SPI.transfer(c); digitalWriteFast(_cs,HIGH); SPI.endTransaction(); } } void TFT_ILI9163C::writedata(uint8_t c) { if (_useSPI1){ SPI1.beginTransaction(ILI9163C_SPI); digitalWriteFast(_rs,HIGH); digitalWriteFast(_cs,LOW); SPI1.transfer(c); digitalWriteFast(_cs,HIGH); SPI1.endTransaction(); } else { SPI.beginTransaction(ILI9163C_SPI); digitalWriteFast(_rs,HIGH); digitalWriteFast(_cs,LOW); SPI.transfer(c); digitalWriteFast(_cs,HIGH); SPI.endTransaction(); } } void TFT_ILI9163C::writedata16(uint16_t d) { if (_useSPI1){ SPI1.beginTransaction(ILI9163C_SPI); digitalWriteFast(_rs,HIGH); digitalWriteFast(_cs,LOW); SPI1.transfer16(d); digitalWriteFast(_cs,HIGH); SPI1.endTransaction(); } else { SPI.beginTransaction(ILI9163C_SPI); digitalWriteFast(_rs,HIGH); digitalWriteFast(_cs,LOW); SPI.transfer16(d); digitalWriteFast(_cs,HIGH); SPI.endTransaction(); } } void TFT_ILI9163C::setBitrate(uint32_t n) { //nop } #elif defined(__MK20DX128__) || defined(__MK20DX256__)//Teensy 3.0 & 3.1 void TFT_ILI9163C::setBitrate(uint32_t n) { //nop } #else void TFT_ILI9163C::writecommand(uint8_t c) { #if defined(SPI_HAS_TRANSACTION) SPI.beginTransaction(ILI9163C_SPI); #endif digitalWrite(_rs,LOW); digitalWrite(_cs,LOW); SPI.transfer(c); digitalWrite(_cs,HIGH); #if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif } void TFT_ILI9163C::writedata(uint8_t c) { #if defined(SPI_HAS_TRANSACTION) SPI.beginTransaction(ILI9163C_SPI); #endif digitalWrite(_rs,HIGH); digitalWrite(_cs,LOW); SPI.transfer(c); digitalWrite(_cs,HIGH); #if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif } void TFT_ILI9163C::writedata16(uint16_t d) { #if defined(SPI_HAS_TRANSACTION) SPI.beginTransaction(ILI9163C_SPI); #endif digitalWrite(_rs,HIGH); digitalWrite(_cs,LOW); SPI.transfer(d >> 8); SPI.transfer(d); digitalWrite(_cs,HIGH); #if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif } void TFT_ILI9163C::setBitrate(uint32_t n) { //nop } #endif //#if defined(TEENSY3.x) void TFT_ILI9163C::begin(void) { sleep = 0; _initError = 0b00000000; #if defined(__AVR__) pinMode(_rs, OUTPUT); pinMode(_cs, OUTPUT); csport = portOutputRegister(digitalPinToPort(_cs)); rsport = portOutputRegister(digitalPinToPort(_rs)); cspinmask = digitalPinToBitMask(_cs); rspinmask = digitalPinToBitMask(_rs); SPI.begin(); #if !defined(SPI_HAS_TRANSACTION) SPI.setClockDivider(SPI_CLOCK_DIV2); // 8 MHz SPI.setBitOrder(MSBFIRST); SPI.setDataMode(SPI_MODE0); #else ILI9163C_SPI = SPISettings(8000000, MSBFIRST, SPI_MODE0); #endif *csport &= ~cspinmask;// toggle CS low so it'll listen to us #elif defined(__SAM3X8E__) pinMode(_rs, OUTPUT); pinMode(_cs, OUTPUT); csport = digitalPinToPort(_cs); rsport = digitalPinToPort(_rs); cspinmask = digitalPinToBitMask(_cs); rspinmask = digitalPinToBitMask(_rs); SPI.begin(); #if !defined(SPI_HAS_TRANSACTION) SPI.setClockDivider(5); // 8 MHz SPI.setBitOrder(MSBFIRST); SPI.setDataMode(SPI_MODE0); #else ILI9163C_SPI = SPISettings(24000000, MSBFIRST, SPI_MODE0); #endif csport ->PIO_CODR |= cspinmask; // toggle CS low so it'll listen to us #elif defined(__MKL26Z64__)//Teensy LC (preliminary) pinMode(_rs, OUTPUT); pinMode(_cs, OUTPUT); if (_useSPI1){ if ((_mosi == 0 || _mosi == 21) && (_sclk == 20)) {//identify alternate SPI channel 1 (24Mhz) ILI9163C_SPI = SPISettings(24000000, MSBFIRST, SPI_MODE0); SPI1.setMOSI(_mosi); SPI1.setSCK(_sclk); SPI1.begin(); _useSPI1 = true; //confirm } else { bitSet(_initError,0); return; } if (!SPI.pinIsChipSelect(_cs)) {//ERROR bitSet(_initError,1); return; } } else { if ((_mosi == 11 || _mosi == 7) && (_sclk == 13 || _sclk == 14)) {//valid SPI pins? ILI9163C_SPI = SPISettings(12000000, MSBFIRST, SPI_MODE0); SPI.setMOSI(_mosi); SPI.setSCK(_sclk); SPI.begin(); _useSPI1 = false; //confirm } else { bitSet(_initError,0); return; } if (!SPI.pinIsChipSelect(_cs)) {//ERROR bitSet(_initError,1); return; } } digitalWriteFast(_cs, LOW); #elif defined(__MK20DX128__) || defined(__MK20DX256__) ILI9163C_SPI = SPISettings(30000000, MSBFIRST, SPI_MODE0); if ((_mosi == 11 || _mosi == 7) && (_sclk == 13 || _sclk == 14)) { SPI.setMOSI(_mosi); SPI.setSCK(_sclk); } else { bitSet(_initError,0); return; } SPI.begin(); if (SPI.pinIsChipSelect(_cs, _rs)) { pcs_data = SPI.setCS(_cs); pcs_command = pcs_data | SPI.setCS(_rs); } else { pcs_data = 0; pcs_command = 0; bitSet(_initError,1); return; } #else//all the rest of possible boards pinMode(_rs, OUTPUT); pinMode(_cs, OUTPUT); SPI.begin(); #if !defined(SPI_HAS_TRANSACTION) SPI.setClockDivider(4); SPI.setBitOrder(MSBFIRST); SPI.setDataMode(SPI_MODE0); #else ILI9163C_SPI = SPISettings(8000000, MSBFIRST, SPI_MODE0); #endif digitalWrite(_cs, LOW); #endif if (_rst != 255) { pinMode(_rst, OUTPUT); digitalWrite(_rst, HIGH); delay(500); digitalWrite(_rst, LOW); delay(500); digitalWrite(_rst, HIGH); delay(500); } /* 7) MY: 1(bottom to top), 0(top to bottom) Row Address Order 6) MX: 1(R to L), 0(L to R) Column Address Order 5) MV: 1(Exchanged), 0(normal) Row/Column exchange 4) ML: 1(bottom to top), 0(top to bottom) Vertical Refresh Order 3) RGB: 1(BGR), 0(RGB) Color Space 2) MH: 1(R to L), 0(L to R) Horizontal Refresh Order 1) 0) MY, MX, MV, ML,RGB, MH, D1, D0 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 //normal 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 //Y-Mirror 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 //X-Mirror 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 //X-Y-Mirror 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 //X-Y Exchange 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 //X-Y Exchange, Y-Mirror 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 //XY exchange 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 */ _Mactrl_Data = 0b00000000; _colorspaceData = __COLORSPC;//start with default data; chipInit(); } uint8_t TFT_ILI9163C::errorCode(void) { return _initError; } void TFT_ILI9163C::chipInit() { uint8_t i; #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); writecommand_cont(CMD_SWRESET);//software reset delay(500); writecommand_cont(CMD_SLPOUT);//exit sleep delay(5); writecommand_cont(CMD_PIXFMT);//Set Color Format 16bit writedata8_cont(0x05); delay(5); writecommand_cont(CMD_GAMMASET);//default gamma curve 3 writedata8_cont(0x08);//0x04 delay(1); writecommand_cont(CMD_GAMRSEL);//Enable Gamma adj writedata8_cont(0x01); delay(1); writecommand_cont(CMD_NORML); writecommand_cont(CMD_DFUNCTR); writedata8_cont(0b11111111);// writedata8_cont(0b00000110);// writecommand_cont(CMD_PGAMMAC);//Positive Gamma Correction Setting for (i=0;i<15;i++){ writedata8_cont(pGammaSet[i]); } writecommand_cont(CMD_NGAMMAC);//Negative Gamma Correction Setting for (i=0;i<15;i++){ writedata8_cont(nGammaSet[i]); } writecommand_cont(CMD_FRMCTR1);//Frame Rate Control (In normal mode/Full colors) writedata8_cont(0x08);//0x0C//0x08 writedata8_cont(0x02);//0x14//0x08 delay(1); writecommand_cont(CMD_DINVCTR);//display inversion writedata8_cont(0x07); delay(1); writecommand_cont(CMD_PWCTR1);//Set VRH1[4:0] & VC[2:0] for VCI1 & GVDD writedata8_cont(0x0A);//4.30 - 0x0A writedata8_cont(0x02);//0x05 delay(1); writecommand_cont(CMD_PWCTR2);//Set BT[2:0] for AVDD & VCL & VGH & VGL writedata8_cont(0x02); delay(1); writecommand_cont(CMD_VCOMCTR1);//Set VMH[6:0] & VML[6:0] for VOMH & VCOML writedata8_cont(0x50);//0x50 writedata8_cont(99);//0x5b delay(1); writecommand_cont(CMD_VCOMOFFS); writedata8_cont(0);//0x40 delay(1); writecommand_cont(CMD_CLMADRS);//Set Column Address writedata16_cont(0x00); writedata16_cont(_GRAMWIDTH); writecommand_cont(CMD_PGEADRS);//Set Page Address writedata16_cont(0x00); writedata16_cont(_GRAMHEIGH); // set scroll area (thanks Masuda) writecommand_cont(CMD_VSCLLDEF); writedata16_cont(__OFFSET); writedata16_cont(_GRAMHEIGH - __OFFSET); writedata16_last(0); SPI.endTransaction(); colorSpace(_colorspaceData); setRotation(0); SPI.beginTransaction(ILI9163C_SPI); writecommand_cont(CMD_DISPON);//display ON delay(1); writecommand_last(CMD_RAMWR);//Memory Write SPI.endTransaction(); delay(1); #else writecommand(CMD_SWRESET);//software reset delay(500); writecommand(CMD_SLPOUT);//exit sleep delay(5); writecommand(CMD_PIXFMT);//Set Color Format 16bit writedata(0x05); delay(5); writecommand(CMD_GAMMASET);//default gamma curve 3 writedata(0x04);//0x04 delay(1); writecommand(CMD_GAMRSEL);//Enable Gamma adj writedata(0x01); delay(1); writecommand(CMD_NORML); writecommand(CMD_DFUNCTR); writedata(0b11111111);// writedata(0b00000110);// writecommand(CMD_PGAMMAC);//Positive Gamma Correction Setting for (i=0;i<15;i++){ writedata(pGammaSet[i]); } writecommand(CMD_NGAMMAC);//Negative Gamma Correction Setting for (i=0;i<15;i++){ writedata(nGammaSet[i]); } writecommand(CMD_FRMCTR1);//Frame Rate Control (In normal mode/Full colors) writedata(0x08);//0x0C//0x08 writedata(0x02);//0x14//0x08 delay(1); writecommand(CMD_DINVCTR);//display inversion writedata(0x07); delay(1); writecommand(CMD_PWCTR1);//Set VRH1[4:0] & VC[2:0] for VCI1 & GVDD writedata(0x0A);//4.30 - 0x0A writedata(0x02);//0x05 delay(1); writecommand(CMD_PWCTR2);//Set BT[2:0] for AVDD & VCL & VGH & VGL writedata(0x02); delay(1); writecommand(CMD_VCOMCTR1);//Set VMH[6:0] & VML[6:0] for VOMH & VCOML writedata(0x50);//0x50 writedata(99);//0x5b delay(1); writecommand(CMD_VCOMOFFS); writedata(0);//0x40 delay(1); writecommand(CMD_CLMADRS);//Set Column Address writedata16(0x00); writedata16(_GRAMWIDTH); writecommand(CMD_PGEADRS);//Set Page Address writedata16(0X00); writedata16(_GRAMHEIGH); // set scroll area (thanks Masuda) writecommand(CMD_VSCLLDEF); writedata16(__OFFSET); writedata16(_GRAMHEIGH - __OFFSET); writedata16(0); colorSpace(_colorspaceData); setRotation(0); writecommand(CMD_DISPON);//display ON delay(1); writecommand(CMD_RAMWR);//Memory Write delay(1); #endif fillScreen(BLACK); } /* Colorspace selection: 0: RGB 1: GBR */ void TFT_ILI9163C::colorSpace(uint8_t cspace) { if (cspace < 1){ bitClear(_Mactrl_Data,3); } else { bitSet(_Mactrl_Data,3); } } void TFT_ILI9163C::invertDisplay(boolean i) { #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); writecommand_last(i ? CMD_DINVON : CMD_DINVOF); SPI.endTransaction(); #else writecommand(i ? CMD_DINVON : CMD_DINVOF); #endif } void TFT_ILI9163C::display(boolean onOff) { if (onOff){ #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); writecommand_last(CMD_DISPON); SPI.endTransaction(); #else writecommand(CMD_DISPON); #endif } else { #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); writecommand_last(CMD_DISPOFF); SPI.endTransaction(); #else writecommand(CMD_DISPOFF); #endif } } void TFT_ILI9163C::idleMode(boolean onOff) { if (onOff){ #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); writecommand_last(CMD_IDLEON); SPI.endTransaction(); #else writecommand(CMD_IDLEON); #endif } else { #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); writecommand_last(CMD_IDLEOF); SPI.endTransaction(); #else writecommand(CMD_IDLEOF); #endif } } void TFT_ILI9163C::sleepMode(boolean mode) { if (mode){ if (sleep == 1) return;//already sleeping sleep = 1; #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); writecommand_last(CMD_SLPIN); SPI.endTransaction(); #else writecommand(CMD_SLPIN); #endif delay(5);//needed } else { if (sleep == 0) return; //Already awake sleep = 0; #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); writecommand_last(CMD_SLPOUT); SPI.endTransaction(); #else writecommand(CMD_SLPOUT); #endif delay(120);//needed } } void TFT_ILI9163C::defineScrollArea(uint16_t tfa, uint16_t bfa){ tfa += __OFFSET; int16_t vsa = _GRAMHEIGH - tfa - bfa; if (vsa >= 0) { #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); writecommand_cont(CMD_VSCLLDEF); writedata16_cont(tfa); writedata16_cont(vsa); writedata16_last(bfa); SPI.endTransaction(); #else writecommand(CMD_VSCLLDEF); writedata16(tfa); writedata16(vsa); writedata16(bfa); #endif } } void TFT_ILI9163C::scroll(uint16_t adrs) { if (adrs <= _GRAMHEIGH) { #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); writecommand_cont(CMD_VSSTADRS); writedata16_last(adrs + __OFFSET); SPI.endTransaction(); #else writecommand(CMD_VSSTADRS); writedata16(adrs + __OFFSET); #endif } } //corrected! v3 void TFT_ILI9163C::clearScreen(uint16_t color) { int px; #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); _setAddrWindow(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH); for (px = 0;px < _GRAMSIZE; px++){ writedata16_cont(color); } writecommand_last(CMD_NOP); SPI.endTransaction(); #else setAddr(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH);//go home for (px = 0;px < _GRAMSIZE; px++){ writedata16(color); } #endif } void TFT_ILI9163C::startPushData(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { setAddr(x0,y0,x1,y1); } void TFT_ILI9163C::pushData(uint16_t color) { #if defined(__MK20DX128__) || defined(__MK20DX256__) writedata16_cont(color); #else writedata16(color); #endif } void TFT_ILI9163C::endPushData() { #if defined(__MK20DX128__) || defined(__MK20DX256__) writecommand_last(CMD_NOP); SPI.endTransaction(); #endif } void TFT_ILI9163C::pushColor(uint16_t color) { #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); writedata16_last(color); SPI.endTransaction(); #else writedata16(color); #endif } void TFT_ILI9163C::writeScreen24(const uint32_t *bitmap,uint16_t size) { uint16_t color; uint16_t px; #if defined(__MK20DX128__) || defined(__MK20DX256__) writecommand_cont(CMD_RAMWR); for (px = 0;px < size; px++){//16384 color = Color24To565(bitmap[px]); writedata16_cont(color); } _setAddrWindow(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH);//home SPI.endTransaction(); #else writecommand(CMD_RAMWR); for (px = 0;px < size; px++){ color = Color24To565(bitmap[px]); writedata16(color); } homeAddress(); #endif } void TFT_ILI9163C::homeAddress() { setAddrWindow(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH); } void TFT_ILI9163C::setCursor(int16_t x, int16_t y) { if (boundaryCheck(x,y)) return; setAddrWindow(0x00,0x00,x,y); cursor_x = x; cursor_y = y; } void TFT_ILI9163C::drawPixel(int16_t x, int16_t y, uint16_t color) { if (boundaryCheck(x,y)) return; if ((x < 0) || (y < 0)) return; setAddr(x,y,x+1,y+1); #if defined(__MK20DX128__) || defined(__MK20DX256__) writedata16_last(color); SPI.endTransaction(); #else writedata16(color); #endif } void TFT_ILI9163C::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) { // Rudimentary clipping if (boundaryCheck(x,y)) return; if (((y + h) - 1) >= _height) h = _height-y; setAddr(x,y,x,(y+h)-1); while (h-- > 0) { #if defined(__MK20DX128__) || defined(__MK20DX256__) if (h == 0){ writedata16_last(color); } else { writedata16_cont(color); } #else writedata16(color); #endif } #if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif } bool TFT_ILI9163C::boundaryCheck(int16_t x,int16_t y){ if ((x >= _width) || (y >= _height)) return true; return false; } void TFT_ILI9163C::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) { // Rudimentary clipping if (boundaryCheck(x,y)) return; if (((x+w) - 1) >= _width) w = _width-x; setAddr(x,y,(x+w)-1,y); while (w-- > 0) { #if defined(__MK20DX128__) || defined(__MK20DX256__) if (w == 0){ writedata16_last(color); } else { writedata16_cont(color); } #else writedata16(color); #endif } #if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif } void TFT_ILI9163C::fillScreen(uint16_t color) { clearScreen(color); } // fill a rectangle void TFT_ILI9163C::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { if (boundaryCheck(x,y)) return; if (((x + w) - 1) >= _width) w = _width - x; if (((y + h) - 1) >= _height) h = _height - y; setAddr(x,y,(x+w)-1,(y+h)-1); for (y = h;y > 0;y--) { for (x = w;x > 1;x--) { #if defined(__MK20DX128__) || defined(__MK20DX256__) writedata16_cont(color); #else writedata16(color); #endif } #if defined(__MK20DX128__) || defined(__MK20DX256__) writedata16_last(color); #else writedata16(color); #endif } #if defined(SPI_HAS_TRANSACTION) SPI.endTransaction(); #endif } #if defined(__MK20DX128__) || defined(__MK20DX256__) void TFT_ILI9163C::drawLine(int16_t x0, int16_t y0,int16_t x1, int16_t y1, uint16_t color){ if (y0 == y1) { if (x1 > x0) { drawFastHLine(x0, y0, x1 - x0 + 1, color); } else if (x1 < x0) { drawFastHLine(x1, y0, x0 - x1 + 1, color); } else { drawPixel(x0, y0, color); } return; } else if (x0 == x1) { if (y1 > y0) { drawFastVLine(x0, y0, y1 - y0 + 1, color); } else { drawFastVLine(x0, y1, y0 - y1 + 1, color); } return; } bool steep = abs(y1 - y0) > abs(x1 - x0); if (steep) { swap(x0, y0); swap(x1, y1); } if (x0 > x1) { swap(x0, x1); swap(y0, y1); } int16_t dx, dy; dx = x1 - x0; dy = abs(y1 - y0); int16_t err = dx / 2; int16_t ystep; if (y0 < y1) { ystep = 1; } else { ystep = -1; } SPI.beginTransaction(ILI9163C_SPI); int16_t xbegin = x0; if (steep) { for (; x0<=x1; x0++) { err -= dy; if (err < 0) { int16_t len = x0 - xbegin; if (len) { VLine(y0, xbegin, len + 1, color); } else { Pixel(y0, x0, color); } xbegin = x0 + 1; y0 += ystep; err += dx; } } if (x0 > xbegin + 1) { VLine(y0, xbegin, x0 - xbegin, color); } } else { for (; x0<=x1; x0++) { err -= dy; if (err < 0) { int16_t len = x0 - xbegin; if (len) { HLine(xbegin, y0, len + 1, color); } else { Pixel(x0, y0, color); } xbegin = x0 + 1; y0 += ystep; err += dx; } } if (x0 > xbegin + 1) { HLine(xbegin, y0, x0 - xbegin, color); } } writecommand_last(CMD_NOP); SPI.endTransaction(); } void TFT_ILI9163C::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){ SPI.beginTransaction(ILI9163C_SPI); HLine(x, y, w, color); HLine(x, y+h-1, w, color); VLine(x, y, h, color); VLine(x+w-1, y, h, color); writecommand_last(CMD_NOP); SPI.endTransaction(); } #endif void TFT_ILI9163C::setAddr(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1){ #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); _setAddrWindow(x0,y0,x1,y1); #else setAddrWindow(x0,y0,x1,y1); #endif } void TFT_ILI9163C::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); _setAddrWindow(x0,y0,x1,y1); SPI.endTransaction(); #else writecommand(CMD_CLMADRS); // Column if (rotation == 0 || rotation > 1){ writedata16(x0); writedata16(x1); } else { writedata16(x0 + __OFFSET); writedata16(x1 + __OFFSET); } writecommand(CMD_PGEADRS); // Page if (rotation == 0){ writedata16(y0 + __OFFSET); writedata16(y1 + __OFFSET); } else { writedata16(y0); writedata16(y1); } writecommand(CMD_RAMWR); //Into RAM #endif } #if defined(__MK20DX128__) || defined(__MK20DX256__) void TFT_ILI9163C::_setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { writecommand_cont(CMD_CLMADRS); // Column if (rotation == 0 || rotation > 1){ writedata16_cont(x0); writedata16_cont(x1); } else { writedata16_cont(x0 + __OFFSET); writedata16_cont(x1 + __OFFSET); } writecommand_cont(CMD_PGEADRS); // Page if (rotation == 0){ writedata16_cont(y0 + __OFFSET); writedata16_cont(y1 + __OFFSET); } else { writedata16_cont(y0); writedata16_cont(y1); } writecommand_cont(CMD_RAMWR); //Into RAM } #endif void TFT_ILI9163C::setRotation(uint8_t m) { rotation = m % 4; // can't be higher than 3 switch (rotation) { case 0: _Mactrl_Data = 0b00001000; _width = _TFTWIDTH; _height = _TFTHEIGHT;//-__OFFSET; break; case 1: _Mactrl_Data = 0b01101000; _width = _TFTHEIGHT;//-__OFFSET; _height = _TFTWIDTH; break; case 2: _Mactrl_Data = 0b11001000; _width = _TFTWIDTH; _height = _TFTHEIGHT;//-__OFFSET; break; case 3: _Mactrl_Data = 0b10101000; _width = _TFTWIDTH; _height = _TFTHEIGHT;//-__OFFSET; break; } colorSpace(_colorspaceData); #if defined(__MK20DX128__) || defined(__MK20DX256__) SPI.beginTransaction(ILI9163C_SPI); writecommand_cont(CMD_MADCTL); writedata8_last(_Mactrl_Data); SPI.endTransaction(); #else writecommand(CMD_MADCTL); writedata(_Mactrl_Data); #endif }