Library to support using the 2.8" TFT Touch Shield v1.0 - made by Seeed Studio - for Arduino This shield uses either the SPFD5408A or ST7781R display chip.
Diff: tft.cpp
- Revision:
- 0:93976d4026d3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tft.cpp Thu Feb 05 19:39:58 2015 +0000 @@ -0,0 +1,798 @@ +/* + SPFD5408A or ST7781R TFT Library. + + 2015 Copyright (c) Bluegrass Digital Inc. + + Authors: TJ Forshee (with initializtion code from TFT vendor) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "tft.h" + +BusInOut lcd_data(D2, D3, D4, D5, D6, D7, D8, D9); +DigitalOut CS_BIT(D10); +DigitalOut RS_BIT(D11); +DigitalOut WR_BIT(D12); +DigitalOut RD_BIT(D13); + +void TFT::pushData(unsigned char data) +{ + //lcd_data.output(); + lcd_data.write(data); +} + +unsigned char TFT::getData(void) +{ + //unsigned char data=0; + //delay(1); + // data |= ((PIND&0xfc)>>2); + // data |= ((PINB&0x03)<<6); + wait(0.001); + //lcd_data.input(); // ??????????? will this clear the inputs ? + return lcd_data.read(); +} + +void TFT::sendCommand(unsigned int index) +{ + CS_LOW(); + RS_LOW(); + RD_HIGH(); + WR_HIGH(); + + WR_LOW(); + pushData(0); + WR_HIGH(); + + WR_LOW(); + pushData(index&0xff); + WR_HIGH(); + + CS_HIGH(); +} + +void TFT::sendData(unsigned int data) +{ + CS_LOW(); + RS_HIGH(); + RD_HIGH(); + + WR_LOW(); + pushData((data&0xff00)>>8); + WR_HIGH(); + + WR_LOW(); + pushData(data&0xff); + WR_HIGH(); + + CS_HIGH(); +} + +unsigned int TFT::readRegister(unsigned int index) +{ + unsigned int data=0; + + CS_LOW(); + RS_LOW(); + RD_HIGH(); + + all_pin_output(); + + WR_LOW(); + pushData(0); + WR_HIGH(); + + WR_LOW(); + pushData(index); + WR_HIGH(); + + all_pin_input(); + all_pin_low(); + RS_HIGH(); + + RD_LOW(); + data |= getData()<<8; + RD_HIGH(); + + RD_LOW(); + data |= getData(); + RD_HIGH(); + + CS_HIGH(); + all_pin_output(); + return data; +} + +void TFT::init (void) +{ + //CS_OUTPUT; + CS_HIGH(); + //RD_OUTPUT; + //WR_OUTPUT; + //RS_OUTPUT; + + Tft.all_pin_output(); + Tft.all_pin_low(); + + wait(0.1); + IC_CODE = readRegister(0x0); + + if(IC_CODE == 0x5408) + { + sendCommand(0x0000); + sendData(0x0001); + wait(0.1); + + sendCommand(0x0001); + sendData(0x0000); + sendCommand(0x0002); + sendData(0x0700); + sendCommand(0x0003); + sendData(0x1030); + sendCommand(0x0004); + sendData(0x0000); + sendCommand(0x0008); + sendData(0x0207); + sendCommand(0x0009); + sendData(0x0000); + sendCommand(0x000A); + sendData(0x0000); + sendCommand(0x000C); + sendData(0x0000); + sendCommand(0x000D); + sendData(0x0000); + sendCommand(0x000F); + sendData(0x0000); + //power on sequence VGHVGL + sendCommand(0x0010); + sendData(0x0000); + sendCommand(0x0011); + sendData(0x0007); + sendCommand(0x0012); + sendData(0x0000); + sendCommand(0x0013); + sendData(0x0000); + //vgh + sendCommand(0x0010); + sendData(0x1290); + sendCommand(0x0011); + sendData(0x0227); + wait(0.1); + //vregiout + sendCommand(0x0012); + sendData(0x001d); //0x001b + wait(0.1); + //vom amplitude + sendCommand(0x0013); + sendData(0x1500); + wait(0.1); + //vom H + sendCommand(0x0029); + sendData(0x0018); + sendCommand(0x002B); + sendData(0x000D); + + //gamma + sendCommand(0x0030); + sendData(0x0004); + sendCommand(0x0031); + sendData(0x0307); + sendCommand(0x0032); + sendData(0x0002);// 0006 + sendCommand(0x0035); + sendData(0x0206); + sendCommand(0x0036); + sendData(0x0408); + sendCommand(0x0037); + sendData(0x0507); + sendCommand(0x0038); + sendData(0x0204);//0200 + sendCommand(0x0039); + sendData(0x0707); + sendCommand(0x003C); + sendData(0x0405);// 0504 + sendCommand(0x003D); + sendData(0x0F02); + //ram + sendCommand(0x0050); + sendData(0x0000); + sendCommand(0x0051); + sendData(0x00EF); + sendCommand(0x0052); + sendData(0x0000); + sendCommand(0x0053); + sendData(0x013F); + sendCommand(0x0060); + sendData(0xA700); + sendCommand(0x0061); + sendData(0x0001); + sendCommand(0x006A); + sendData(0x0000); + // + sendCommand(0x0080); + sendData(0x0000); + sendCommand(0x0081); + sendData(0x0000); + sendCommand(0x0082); + sendData(0x0000); + sendCommand(0x0083); + sendData(0x0000); + sendCommand(0x0084); + sendData(0x0000); + sendCommand(0x0085); + sendData(0x0000); + // + sendCommand(0x0090); + sendData(0x0010); + sendCommand(0x0092); + sendData(0x0600); + sendCommand(0x0093); + sendData(0x0003); + sendCommand(0x0095); + sendData(0x0110); + sendCommand(0x0097); + sendData(0x0000); + sendCommand(0x0098); + sendData(0x0000); + sendCommand(0x0007); + sendData(0x0133); + + sendCommand(0x0022);//Start to write to display RAM + + } + else + { + + sendCommand(0x0001); + sendData(0x0100); + sendCommand(0x0002); + sendData(0x0700); + sendCommand(0x0003); + sendData(0x1030); + sendCommand(0x0004); + sendData(0x0000); + sendCommand(0x0008); + sendData(0x0302); + + sendCommand(0x000A); + sendData(0x0000); + sendCommand(0x000C); + sendData(0x0000); + sendCommand(0x000D); + sendData(0x0000); + sendCommand(0x000F); + sendData(0x0000); + + wait(0.1); + + sendCommand(0x0030); + sendData(0x0000); + sendCommand(0x0031); + sendData(0x0405); + sendCommand(0x0032); + sendData(0x0203); + sendCommand(0x0035); + sendData(0x0004); + sendCommand(0x0036); + sendData(0x0B07); + sendCommand(0x0037); + sendData(0x0000); + sendCommand(0x0038); + sendData(0x0405); + sendCommand(0x0039); + sendData(0x0203); + sendCommand(0x003c); + sendData(0x0004); + sendCommand(0x003d); + sendData(0x0B07); + sendCommand(0x0020); + sendData(0x0000); + sendCommand(0x0021); + sendData(0x0000); + sendCommand(0x0050); + sendData(0x0000); + sendCommand(0x0051); + sendData(0x00ef); + sendCommand(0x0052); + sendData(0x0000); + sendCommand(0x0053); + sendData(0x013f); + + wait(0.1); + + sendCommand(0x0060); + sendData(0xa700); + sendCommand(0x0061); + sendData(0x0001); + sendCommand(0x0090); + sendData(0x003A); + sendCommand(0x0095); + sendData(0x021E); + sendCommand(0x0080); + sendData(0x0000); + sendCommand(0x0081); + sendData(0x0000); + sendCommand(0x0082); + sendData(0x0000); + sendCommand(0x0083); + sendData(0x0000); + sendCommand(0x0084); + sendData(0x0000); + sendCommand(0x0085); + sendData(0x0000); + sendCommand(0x00FF); + sendData(0x0001); + sendCommand(0x00B0); + sendData(0x140D); + sendCommand(0x00FF); + sendData(0x0000); + wait(0.1); + sendCommand(0x0007); + sendData(0x0133); + wait(0.05); + //exit standby + sendCommand(0x0010); + sendData(0x14E0); + wait(0.1); + sendCommand(0x0007); + sendData(0x0133); + sendCommand(0x0022); + } + + //paint screen black + for(unsigned char i=0;i<2;i++) + { + for(unsigned int f=0;f<38400;f++) + { + sendData(BLACK); + } + } +} + +void TFT::setOrientation(unsigned int HV)//horizontal or vertical +{ + sendCommand(0x03); + if(HV==1)//vertical + { + if(IC_CODE == 0x5408) { sendData(0x1038); } + else { sendData(0x5038); } + } + else//horizontal + { + if(IC_CODE == 0x5408) { sendData(0x1030); } + else { sendData(0x5030); } + } + sendCommand(0x0022); //Start to write to display RAM +} + +unsigned int TFT::constrain(unsigned int val2chk, unsigned int lowval, unsigned int highval) +{ + if (val2chk < lowval) + return lowval; + else if (val2chk > highval) + return highval; + else + return val2chk; +} + +void TFT::setXY(unsigned int poX, unsigned int poY) +{ + poX = constrain(poX,MIN_X,MAX_X); //Limits the pixel range to 0 - 239 + poY = constrain(poY,MIN_Y,MAX_Y); //Limits the pixel range to 0 - 319 + /* Writing to GRAM beyond the range gives unpredictable results. The above code + is to limit this. This might also slow down the writing to TFT. You can + remove the above two lines of code, if you think your application code + does not write beyond this range. This would speed up TFT writing. */ + + sendCommand(0x0020);//X + sendData(poX); + sendCommand(0x0021);//Y + sendData(poY); + sendCommand(0x0022);//Start to write to display RAM +} + +void TFT::setPixel(unsigned int poX, unsigned int poY,unsigned int color) +{ + setXY(poX,poY); + sendData(color); +} + +void TFT::drawCircle(int poX, int poY, int r,unsigned int color) +{ + int x = -r, y = 0, err = 2-2*r, e2; + do + { + setPixel(poX-x, poY+y,color); + setPixel(poX+x, poY+y,color); + setPixel(poX+x, poY-y,color); + setPixel(poX-x, poY-y,color); + e2 = err; + if (e2 <= y) + { + err += ++y*2+1; + if (-x == y && e2 <= x) e2 = 0; + } + if (e2 > x) err += ++x*2+1; + } + while (x <= 0); +} + +void TFT::fillCircle(int poX, int poY, int r,unsigned int color) +{ + int x = -r, y = 0, err = 2-2*r, e2; + do + { + drawVerticalLine(poX-x,poY-y,2*y,color); + drawVerticalLine(poX+x,poY-y,2*y,color); + + e2 = err; + if (e2 <= y) + { + err += ++y*2+1; + if (-x == y && e2 <= x) e2 = 0; + } + if (e2 > x) err += ++x*2+1; + } + while (x <= 0); +} + +void TFT::drawLine(unsigned int x0,unsigned int y0,unsigned int x1,unsigned int y1,unsigned int color) +{ + int dx = x1-x0; + dx = abs(dx); + int sx = x0<x1 ? 1 : -1; + int dy = y1-y0; + dy = -abs(dy); + int sy = y0<y1 ? 1 : -1; + int err = dx+dy, e2; /* error value e_xy */ + for (;;) + { + setPixel(x0,y0,color); + e2 = 2*err; + if (e2 >= dy) + { /* e_xy+e_x > 0 */ + if (x0 == x1) break; + err += dy; + x0 += sx; + } + if (e2 <= dx) + { /* e_xy+e_y < 0 */ + if (y0 == y1) break; + err += dx; + y0 += sy; + } + } +} + +void TFT::drawVerticalLine(unsigned int poX, unsigned int poY,unsigned int length,unsigned int color) +{ + poX = constrain(poX,MIN_X,MAX_X); //Limits the pixel range to 0 - 239 + poY = constrain(poY,MIN_Y,MAX_Y); //Limits the pixel range to 0 - 319 + + setXY(poX,poY); + setOrientation(1); + if(length+poY>MAX_Y) + { + length=MAX_Y-poY; + } + + for(unsigned int i=0;i<length;i++) + { + sendData(color); + } +} + +void TFT::drawHorizontalLine(unsigned int poX, unsigned int poY,unsigned int length,unsigned int color) +{ + poX = constrain(poX,MIN_X,MAX_X); //Limits the pixel range to 0 - 239 + poY = constrain(poY,MIN_Y,MAX_Y); //Limits the pixel range to 0 - 319 + + setXY(poX,poY); + setOrientation(0); + if(length+poX>MAX_X) + { + length=MAX_X-poX; + } + for(unsigned int i=0;i<length;i++) + { + sendData(color); + } +} + +void TFT::drawRectangle(unsigned int poX, unsigned int poY, unsigned int length,unsigned int width,unsigned int color) +{ + drawHorizontalLine(poX, poY, length, color); + drawHorizontalLine(poX, poY+width, length, color); + + drawVerticalLine(poX, poY, width,color); + drawVerticalLine(poX + length, poY, width,color); +} + +void TFT::fillRectangle(unsigned int poX, unsigned int poY, unsigned int length, unsigned int width, unsigned int color) +{ + for(unsigned int i=0;i<width;i++) + { + drawHorizontalLine(poX, poY+i, length, color); + } +} + +void TFT::drawChar(unsigned char ascii,unsigned int poX, unsigned int poY,unsigned int size, unsigned int fgcolor) +{ + setXY(poX,poY); + setOrientation(1); + if((ascii < 0x20)||(ascii > 0x7e))//Unsupported char. + { + ascii = '?'; + } + for(unsigned char i=0;i<8;i++) + { + unsigned char temp = simpleFont[ascii-0x20][i]; + for(unsigned char f=0;f<8;f++) + { + if((temp>>f)&0x01) + { + fillRectangle(poX+i*size, poY+f*size, size, size, fgcolor); + } + + } + } +} + +void TFT::drawString(char *string,unsigned int poX, unsigned int poY,unsigned int size,unsigned int fgcolor) +{ + while(*string) + { + drawChar(*string, poX, poY, size, fgcolor); + *string++; + + if(poX < MAX_X) + { + poX+=8*size; // Move cursor right + } + } +} + +unsigned char TFT::drawNumber(long long_num,unsigned int poX, unsigned int poY,unsigned int size,unsigned int fgcolor) +{ + unsigned char char_buffer[10]=""; + unsigned char i = 0; + unsigned char f = 0; + + if (long_num < 0) + { + f=1; + drawChar('-',poX, poY, size, fgcolor); + long_num = -long_num; + if(poX < MAX_X) + { + poX+=8*size; // Move cursor right + } + } + else if (long_num == 0) + { + f=1; + drawChar('0',poX, poY, size, fgcolor); + if (poX < MAX_X) + { + poX+=8*size; // Move cursor right + } + return f; + } + + while (long_num > 0) + { + char_buffer[i++] = long_num % 10; + long_num /= 10; + } + + f=f+i; + for(; i > 0; i--) + { + drawChar('0'+ char_buffer[i - 1],poX, poY, size, fgcolor); + if(poX < MAX_X) + { + poX+=8*size; // Move cursor right + } + } + return f; +} + +unsigned char TFT::drawFloat(float floatNumber,unsigned char decimal,unsigned int poX, unsigned int poY,unsigned int size,unsigned int fgcolor) +{ + unsigned int temp=0; + float decy=0.0; + float rounding = 0.5; + unsigned char f=0; + if(floatNumber<0.0) + { + drawChar('-',poX, poY, size, fgcolor); + floatNumber = -floatNumber; + if(poX < MAX_X) + { + poX+=8*size; // Move cursor right + } + f =1; + } + for (unsigned char i=0; i<decimal; ++i) + { + rounding /= 10.0; + } + floatNumber += rounding; + + temp = (unsigned int)floatNumber; + unsigned char howlong=drawNumber(temp,poX, poY, size, fgcolor); + f += howlong; + if((poX+8*size*howlong) < MAX_X) + { + poX+=8*size*howlong; // Move cursor right + } + + if(decimal>0) + { + drawChar('.',poX, poY, size, fgcolor); + if(poX < MAX_X) + { + poX+=8*size; // Move cursor right + } + f +=1; + } + decy = floatNumber-temp;//decimal part, + for(unsigned char i=0;i<decimal;i++)//4 + { + decy *=10;// for the next decimal + temp = decy;//get the decimal + drawNumber(temp,poX, poY, size, fgcolor); + floatNumber = -floatNumber; + if(poX < MAX_X) + { + poX+=8*size; // Move cursor right + } + decy -= temp; + } + f +=decimal; + return f; +} + +unsigned char TFT::drawFloat(float floatNumber,unsigned int poX, unsigned int poY,unsigned int size,unsigned int fgcolor) +{ + unsigned char decimal=2; + unsigned int temp=0; + float decy=0.0; + float rounding = 0.5; + unsigned char f=0; + if(floatNumber<0.0) + { + drawChar('-',poX, poY, size, fgcolor); + floatNumber = -floatNumber; + if(poX < MAX_X) + { + poX+=8*size; // Move cursor right + } + f =1; + } + for (unsigned char i=0; i<decimal; ++i) + { + rounding /= 10.0; + } + floatNumber += rounding; + + temp = (unsigned int)floatNumber; + unsigned char howlong=drawNumber(temp,poX, poY, size, fgcolor); + f += howlong; + if((poX+8*size*howlong) < MAX_X) + { + poX+=8*size*howlong; // Move cursor right + } + + if(decimal>0) + { + drawChar('.',poX, poY, size, fgcolor); + if(poX < MAX_X) + { + poX+=8*size; // Move cursor right + } + f +=1; + } + decy = floatNumber-temp;//decimal part, + for(unsigned char i=0;i<decimal;i++)//4 + { + decy *=10;// for the next decimal + temp = decy;//get the decimal + drawNumber(temp,poX, poY, size, fgcolor); + floatNumber = -floatNumber; + if(poX < MAX_X) + { + poX+=8*size; // Move cursor right + } + decy -= temp; + } + f +=decimal; + return f; +} + +void TFT::all_pin_input(void) +{ + //DDRD &=~ 0xfc; // 0b 1111 1100 + //DDRB &=~ 0x03; // 0b 0000 0011 + lcd_data.input(); +} + +void TFT::all_pin_output(void) +{ + //DDRD |= 0xfc; + //DDRB |= 0x03; + lcd_data.output(); +} + +void TFT::all_pin_low(void) +{ + //PORTD &=~ 0xfc; + //PORTB &=~ 0x03; + lcd_data.write(0); +} + +void TFT::CS_HIGH(void) +{ + CS_BIT.write(1); +} + +void TFT::CS_LOW(void) +{ + CS_BIT.write(0); +} + +void TFT::RS_HIGH(void) +{ + RS_BIT.write(1); +} + +void TFT::RS_LOW(void) +{ + RS_BIT.write(0); +} + +void TFT::WR_HIGH(void) +{ + WR_BIT.write(1); +} + +void TFT::WR_LOW(void) +{ + WR_BIT.write(0); +} + +void TFT::WR_RISING(void) +{ + WR_HIGH(); + WR_LOW(); +} + +void TFT::RD_HIGH(void) +{ + RD_BIT.write(1); +} + +void TFT::RD_LOW(void) +{ + RD_BIT.write(0); +} + +void TFT::RD_RISING(void) +{ + RD_HIGH(); RD_LOW(); +} + +TFT Tft=TFT(); \ No newline at end of file