Arducam_UTFT_SPI_Library
Dependents: DigitalCamera_OV5642_WIZwiki-W7500 Prelude_OV5642_dev
UTFT_SPI.cpp
- Committer:
- justinkim
- Date:
- 2015-10-29
- Revision:
- 0:53f8d6b23687
File content as of revision 0:53f8d6b23687:
/* UTFT.cpp - Arduino library support for Color TFT LCD Boards This is special porting for ArduCAM shield LCD screen. Use SPI bus interface and SSD1289 controller. Only work on ArduCAM shield Rev.C. For more information about ArduCAM shield please visit www.arducam.com Copyright (C)2010-2014 Henning Karlsen. All right reserved This library is the continuation of my ITDB02_Graph, ITDB02_Graph16 and RGB_GLCD libraries for Arduino and chipKit. As the number of supported display modules and controllers started to increase I felt it was time to make a single, universal library as it will be much easier to maintain in the future. Basic functionality of this library was origianlly based on the demo-code provided by ITead studio (for the ITDB02 modules) and NKC Electronics (for the RGB GLCD module/shield). This library supports a number of 8bit, 16bit and serial graphic displays, and will work with both Arduino and chipKit boards. For a full list of tested display modules and controllers, see the document UTFT_Supported_display_modules_&_controllers.pdf. When using 8bit and 16bit display modules there are some requirements you must adhere to. These requirements can be found in the document UTFT_Requirements.pdf. There are no special requirements when using serial displays. You can always find the latest version of the library at http://electronics.henningkarlsen.com/ If you make any modifications or improvements to the code, I would appreciate that you share the code with me so that I might include it in the next release. I can be contacted through http://electronics.henningkarlsen.com/contact.php. 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 "mbed.h" #include "UTFT_SPI.h" ArduLCD::ArduLCD(PinName mosi, PinName miso, PinName sck, PinName cs) : spi(mosi,miso,sck), _cs(cs) { //Must initialize the Bus default status _cs = 1; model = SSD1289; disp_x_size=239; disp_y_size=319; display_transfer_mode=8; display_model=model; //_set_direction_registers(display_transfer_mode); //P_CS = portOutputRegister(digitalPinToPort(CS)); //B_CS = digitalPinToBitMask(CS); //pinMode(CS,OUTPUT); } int ArduLCD::bus_write(int address, int value) { _cs = 0; spi.write(address); spi.write(value); _cs = 1; return value; } uint8_t ArduLCD::bus_read(int address) { uint8_t value = 0; _cs = 0; spi.write(address); value = spi.write(0x00); _cs = 1; return value; } void ArduLCD::LCD_Write_COM(char VL) { bus_write(0xBE, VL); } void ArduLCD::LCD_Write_DATA(char VH,char VL) { bus_write(0xBF, VH); bus_write(0xBF, VL); } void ArduLCD::LCD_Write_COM_DATA(char com1,int dat1) { LCD_Write_COM(com1); LCD_Write_DATA(dat1>>8,dat1); } void ArduLCD::LCD_Writ_Bus(char VH,char VL) { LCD_Write_DATA(VH,VL); } void ArduLCD::InitLCD(uint8_t orientation) { orient=orientation; LCD_Write_COM_DATA(0x00,0x0001); LCD_Write_COM_DATA(0x03,0xA8A4); LCD_Write_COM_DATA(0x0C,0x0000); LCD_Write_COM_DATA(0x0D,0x080C); LCD_Write_COM_DATA(0x0E,0x2B00); LCD_Write_COM_DATA(0x1E,0x00B7); LCD_Write_COM_DATA(0x01,0x693F); LCD_Write_COM_DATA(0x02,0x0600); LCD_Write_COM_DATA(0x10,0x0000); LCD_Write_COM_DATA(0x11,0x6078); LCD_Write_COM_DATA(0x05,0x0000); LCD_Write_COM_DATA(0x06,0x0000); LCD_Write_COM_DATA(0x16,0xEF1C); LCD_Write_COM_DATA(0x17,0x0003); LCD_Write_COM_DATA(0x07,0x0233); LCD_Write_COM_DATA(0x0B,0x0000); LCD_Write_COM_DATA(0x0F,0x0000); LCD_Write_COM_DATA(0x41,0x0000); LCD_Write_COM_DATA(0x42,0x0000); LCD_Write_COM_DATA(0x48,0x0000); LCD_Write_COM_DATA(0x49,0x013F); LCD_Write_COM_DATA(0x4A,0x0000); LCD_Write_COM_DATA(0x4B,0x0000); LCD_Write_COM_DATA(0x44,0xEF00); LCD_Write_COM_DATA(0x45,0x0000); LCD_Write_COM_DATA(0x46,0x013F); LCD_Write_COM_DATA(0x30,0x0707); LCD_Write_COM_DATA(0x31,0x0204); LCD_Write_COM_DATA(0x32,0x0204); LCD_Write_COM_DATA(0x33,0x0502); LCD_Write_COM_DATA(0x34,0x0507); LCD_Write_COM_DATA(0x35,0x0204); LCD_Write_COM_DATA(0x36,0x0204); LCD_Write_COM_DATA(0x37,0x0502); LCD_Write_COM_DATA(0x3A,0x0302); LCD_Write_COM_DATA(0x3B,0x0302); LCD_Write_COM_DATA(0x23,0x0000); LCD_Write_COM_DATA(0x24,0x0000); LCD_Write_COM_DATA(0x25,0x8000); LCD_Write_COM_DATA(0x4f,0x0000); LCD_Write_COM_DATA(0x4e,0x0000); LCD_Write_COM(0x22); //setColor(255, 255, 255); //setBackColor(0, 0, 0); cfont.font=0; clrScr(); } void ArduLCD::setXY(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { if (orient==LANDSCAPE) { swap(uint16_t, x1, y1); swap(uint16_t, x2, y2) y1=disp_y_size-y1; y2=disp_y_size-y2; swap(uint16_t, y1, y2) } LCD_Write_COM_DATA(0x44,(x2<<8)+x1); LCD_Write_COM_DATA(0x45,y1); LCD_Write_COM_DATA(0x46,y2); LCD_Write_COM_DATA(0x4e,x1); LCD_Write_COM_DATA(0x4f,y1); LCD_Write_COM(0x22); } void ArduLCD::clrXY() { if (orient==PORTRAIT) setXY(0,0,disp_x_size,disp_y_size); else setXY(0,0,disp_y_size,disp_x_size); } void ArduLCD::resetXY() { clrXY(); } void ArduLCD::drawRect(int x1, int y1, int x2, int y2) { if (x1>x2) { swap(int, x1, x2); } if (y1>y2) { swap(int, y1, y2); } drawHLine(x1, y1, x2-x1); drawHLine(x1, y2, x2-x1); drawVLine(x1, y1, y2-y1); drawVLine(x2, y1, y2-y1); } void ArduLCD::drawRoundRect(int x1, int y1, int x2, int y2) { if (x1>x2) { swap(int, x1, x2); } if (y1>y2) { swap(int, y1, y2); } if ((x2-x1)>4 && (y2-y1)>4) { drawPixel(x1+1,y1+1); drawPixel(x2-1,y1+1); drawPixel(x1+1,y2-1); drawPixel(x2-1,y2-1); drawHLine(x1+2, y1, x2-x1-4); drawHLine(x1+2, y2, x2-x1-4); drawVLine(x1, y1+2, y2-y1-4); drawVLine(x2, y1+2, y2-y1-4); } } void ArduLCD::fillRect(int x1, int y1, int x2, int y2) { if (x1>x2) { swap(int, x1, x2); } if (y1>y2) { swap(int, y1, y2); } if (orient==PORTRAIT) { for (int i=0; i<((y2-y1)/2)+1; i++) { drawHLine(x1, y1+i, x2-x1); drawHLine(x1, y2-i, x2-x1); } } else { for (int i=0; i<((x2-x1)/2)+1; i++) { drawVLine(x1+i, y1, y2-y1); drawVLine(x2-i, y1, y2-y1); } } } void ArduLCD::fillRoundRect(int x1, int y1, int x2, int y2) { if (x1>x2) { swap(int, x1, x2); } if (y1>y2) { swap(int, y1, y2); } if ((x2-x1)>4 && (y2-y1)>4) { for (int i=0; i<((y2-y1)/2)+1; i++) { switch(i) { case 0: drawHLine(x1+2, y1+i, x2-x1-4); drawHLine(x1+2, y2-i, x2-x1-4); break; case 1: drawHLine(x1+1, y1+i, x2-x1-2); drawHLine(x1+1, y2-i, x2-x1-2); break; default: drawHLine(x1, y1+i, x2-x1); drawHLine(x1, y2-i, x2-x1); } } } } void ArduLCD::drawCircle(int x, int y, int radius) { int f = 1 - radius; int ddF_x = 1; int ddF_y = -2 * radius; int x1 = 0; int y1 = radius; _cs = 0; setXY(x, y + radius, x, y + radius); LCD_Write_DATA(fch,fcl); setXY(x, y - radius, x, y - radius); LCD_Write_DATA(fch,fcl); setXY(x + radius, y, x + radius, y); LCD_Write_DATA(fch,fcl); setXY(x - radius, y, x - radius, y); LCD_Write_DATA(fch,fcl); while(x1 < y1) { if(f >= 0) { y1--; ddF_y += 2; f += ddF_y; } x1++; ddF_x += 2; f += ddF_x; setXY(x + x1, y + y1, x + x1, y + y1); LCD_Write_DATA(fch,fcl); setXY(x - x1, y + y1, x - x1, y + y1); LCD_Write_DATA(fch,fcl); setXY(x + x1, y - y1, x + x1, y - y1); LCD_Write_DATA(fch,fcl); setXY(x - x1, y - y1, x - x1, y - y1); LCD_Write_DATA(fch,fcl); setXY(x + y1, y + x1, x + y1, y + x1); LCD_Write_DATA(fch,fcl); setXY(x - y1, y + x1, x - y1, y + x1); LCD_Write_DATA(fch,fcl); setXY(x + y1, y - x1, x + y1, y - x1); LCD_Write_DATA(fch,fcl); setXY(x - y1, y - x1, x - y1, y - x1); LCD_Write_DATA(fch,fcl); } _cs = 1; clrXY(); } void ArduLCD::fillCircle(int x, int y, int radius) { for(int y1=-radius; y1<=0; y1++) for(int x1=-radius; x1<=0; x1++) if(x1*x1+y1*y1 <= radius*radius) { drawHLine(x+x1, y+y1, 2*(-x1)); drawHLine(x+x1, y-y1, 2*(-x1)); break; } } void ArduLCD::clrScr() { long i; clrXY(); for (i=0; i<((disp_x_size+1)*(disp_y_size+1)); i++) { if (display_transfer_mode!=1) LCD_Writ_Bus(0x00,0x00); else { LCD_Writ_Bus(1,0); LCD_Writ_Bus(1,0); //LCD_Writ_Bus(00,0x55); } //delay(1); #if defined(ESP8266) yield(); #endif } } void ArduLCD::fillScr(uint8_t r, uint8_t g, uint8_t b) { uint16_t color = ((r&248)<<8 | (g&252)<<3 | (b&248)>>3); fillScr(color); } void ArduLCD::fillScr(uint16_t color) { long i; char ch, cl; ch=uint8_t(color>>8); cl=uint8_t(color & 0xFF); clrXY(); for (i=0; i<((disp_x_size+1)*(disp_y_size+1)); i++) { if (display_transfer_mode!=1) LCD_Writ_Bus(ch,cl); else { LCD_Writ_Bus(1,ch); LCD_Writ_Bus(1,cl); } #if defined(ESP8266) yield(); #endif } } void ArduLCD::setColor(uint8_t r, uint8_t g, uint8_t b) { fch=((r&248)|g>>5); fcl=((g&28)<<3|b>>3); } void ArduLCD::setColor(uint16_t color) { fch=uint8_t(color>>8); fcl=uint8_t(color & 0xFF); } uint16_t ArduLCD::getColor() { return (fch<<8) | fcl; } void ArduLCD::setBackColor(uint8_t r, uint8_t g, uint8_t b) { bch=((r&248)|g>>5); bcl=((g&28)<<3|b>>3); _transparent=false; } void ArduLCD::setBackColor(uint32_t color) { if (color==VGA_TRANSPARENT) _transparent=true; else { bch=uint8_t(color>>8); bcl=uint8_t(color & 0xFF); _transparent=false; } } uint16_t ArduLCD::getBackColor() { return (bch<<8) | bcl; } void ArduLCD::setPixel(uint16_t color) { LCD_Write_DATA((color>>8),(color&0xFF)); // rrrrrggggggbbbbb } void ArduLCD::drawPixel(int x, int y) { setXY(x, y, x, y); setPixel((fch<<8)|fcl); clrXY(); } void ArduLCD::drawLine(int x1, int y1, int x2, int y2) { if (y1==y2) drawHLine(x1, y1, x2-x1); else if (x1==x2) drawVLine(x1, y1, y2-y1); else { unsigned int dx = (x2 > x1 ? x2 - x1 : x1 - x2); short xstep = x2 > x1 ? 1 : -1; unsigned int dy = (y2 > y1 ? y2 - y1 : y1 - y2); short ystep = y2 > y1 ? 1 : -1; int col = x1, row = y1; if (dx < dy) { int t = - (dy >> 1); while (true) { setXY (col, row, col, row); LCD_Write_DATA (fch, fcl); if (row == y2) return; row += ystep; t += dx; if (t >= 0) { col += xstep; t -= dy; } } } else { int t = - (dx >> 1); while (true) { setXY (col, row, col, row); LCD_Write_DATA (fch, fcl); if (col == x2) return; col += xstep; t += dy; if (t >= 0) { row += ystep; t -= dx; } } } } clrXY(); } void ArduLCD::drawHLine(int x, int y, int l) { if (l<0) { l = -l; x -= l; } setXY(x, y, x+l, y); if (display_transfer_mode == 16) { _fast_fill_16(fch,fcl,l); } else if ((display_transfer_mode==8) and (fch==fcl)) { _fast_fill_8(fch,l); } else { for (int i=0; i<l+1; i++) { LCD_Write_DATA(fch, fcl); } } clrXY(); } void ArduLCD::drawVLine(int x, int y, int l) { if (l<0) { l = -l; y -= l; } setXY(x, y, x, y+l); if (display_transfer_mode == 16) { _fast_fill_16(fch,fcl,l); } else if ((display_transfer_mode==8) and (fch==fcl)) { _fast_fill_8(fch,l); } else { for (int i=0; i<l+1; i++) { LCD_Write_DATA(fch, fcl); } } clrXY(); } /* void ArduLCD::printChar(uint8_t c, int x, int y) { uint8_t i,ch; uint16_t j; uint16_t temp; if (!_transparent) { if (orient==PORTRAIT) { setXY(x,y,x+cfont.x_size-1,y+cfont.y_size-1); temp=((c-cfont.offset)*((cfont.x_size/8)*cfont.y_size))+4; for(j=0;j<((cfont.x_size/8)*cfont.y_size);j++) { ch=pgm_read_byte(&cfont.font[temp]); for(i=0;i<8;i++) { if((ch&(1<<(7-i)))!=0) { setPixel((fch<<8)|fcl); } else { setPixel((bch<<8)|bcl); } } temp++; } } else { temp=((c-cfont.offset)*((cfont.x_size/8)*cfont.y_size))+4; for(j=0;j<((cfont.x_size/8)*cfont.y_size);j+=(cfont.x_size/8)) { setXY(x,y+(j/(cfont.x_size/8)),x+cfont.x_size-1,y+(j/(cfont.x_size/8))); for (int zz=(cfont.x_size/8)-1; zz>=0; zz--) { ch=pgm_read_byte(&cfont.font[temp+zz]); for(i=0;i<8;i++) { if((ch&(1<<i))!=0) { setPixel((fch<<8)|fcl); } else { setPixel((bch<<8)|bcl); } } } temp+=(cfont.x_size/8); } } } else { temp=((c-cfont.offset)*((cfont.x_size/8)*cfont.y_size))+4; for(j=0;j<cfont.y_size;j++) { for (int zz=0; zz<(cfont.x_size/8); zz++) { ch=pgm_read_byte(&cfont.font[temp+zz]); for(i=0;i<8;i++) { setXY(x+i+(zz*8),y+j,x+i+(zz*8)+1,y+j+1); if((ch&(1<<(7-i)))!=0) { setPixel((fch<<8)|fcl); } } } temp+=(cfont.x_size/8); } } clrXY(); } void ArduLCD::rotateChar(uint8_t c, int x, int y, int pos, int deg) { uint8_t i,j,ch; uint16_t temp; int newx,newy; double radian; radian=deg*0.0175; temp=((c-cfont.offset)*((cfont.x_size/8)*cfont.y_size))+4; for(j=0;j<cfont.y_size;j++) { for (int zz=0; zz<(cfont.x_size/8); zz++) { ch=pgm_read_byte(&cfont.font[temp+zz]); for(i=0;i<8;i++) { newx=x+(((i+(zz*8)+(pos*cfont.x_size))*cos(radian))-((j)*sin(radian))); newy=y+(((j)*cos(radian))+((i+(zz*8)+(pos*cfont.x_size))*sin(radian))); setXY(newx,newy,newx+1,newy+1); if((ch&(1<<(7-i)))!=0) { setPixel((fch<<8)|fcl); } else { if (!_transparent) setPixel((bch<<8)|bcl); } } } temp+=(cfont.x_size/8); } clrXY(); } void ArduLCD::print(char *st, int x, int y, int deg) { int stl, i; stl = strlen(st); if (orient==PORTRAIT) { if (x==RIGHT) x=(disp_x_size+1)-(stl*cfont.x_size); if (x==CENTER) x=((disp_x_size+1)-(stl*cfont.x_size))/2; } else { if (x==RIGHT) x=(disp_y_size+1)-(stl*cfont.x_size); if (x==CENTER) x=((disp_y_size+1)-(stl*cfont.x_size))/2; } for (i=0; i<stl; i++) if (deg==0) printChar(*st++, x + (i*(cfont.x_size)), y); else rotateChar(*st++, x, y, i, deg); } void ArduLCD::print(string st, int x, int y, int deg) { char buf[st.length()+1]; st.toCharArray(buf, st.length()+1); print(buf, x, y, deg); } void ArduLCD::printNumI(long num, int x, int y, int length, char filler) { char buf[25]; char st[27]; bool neg=false; int c=0, f=0; if (num==0) { if (length!=0) { for (c=0; c<(length-1); c++) st[c]=filler; st[c]=48; st[c+1]=0; } else { st[0]=48; st[1]=0; } } else { if (num<0) { neg=true; num=-num; } while (num>0) { buf[c]=48+(num % 10); c++; num=(num-(num % 10))/10; } buf[c]=0; if (neg) { st[0]=45; } if (length>(c+neg)) { for (int i=0; i<(length-c-neg); i++) { st[i+neg]=filler; f++; } } for (int i=0; i<c; i++) { st[i+neg+f]=buf[c-i-1]; } st[c+neg+f]=0; } print(st,x,y); } void ArduLCD::printNumF(double num, uint8_t dec, int x, int y, char divider, int length, char filler) { char st[27]; bool neg=false; if (dec<1) dec=1; else if (dec>5) dec=5; if (num<0) neg = true; _convert_float(st, num, length, dec); if (divider != '.') { for (int i=0; i<sizeof(st); i++) if (st[i]=='.') st[i]=divider; } if (filler != ' ') { if (neg) { st[0]='-'; for (int i=1; i<sizeof(st); i++) if ((st[i]==' ') || (st[i]=='-')) st[i]=filler; } else { for (int i=0; i<sizeof(st); i++) if (st[i]==' ') st[i]=filler; } } print(st,x,y); } void ArduLCD::setFont(uint8_t* font) { cfont.font=font; cfont.x_size=fontbyte(0); cfont.y_size=fontbyte(1); cfont.offset=fontbyte(2); cfont.numchars=fontbyte(3); } uint8_t* ArduLCD::getFont() { return cfont.font; } uint8_t ArduLCD::getFontXsize() { return cfont.x_size; } uint8_t ArduLCD::getFontYsize() { return cfont.y_size; }*/ void ArduLCD::drawBitmap(int x, int y, int sx, int sy, bitmapdatatype data, int scale) { unsigned int col; int tx, ty, tc, tsx, tsy; if (scale==1) { if (orient==PORTRAIT) { setXY(x, y, x+sx-1, y+sy-1); for (tc=0; tc<(sx*sy); tc++) { col=pgm_read_word(&data[tc]); LCD_Write_DATA(col>>8,col & 0xff); } } else { for (ty=0; ty<sy; ty++) { setXY(x, y+ty, x+sx-1, y+ty); for (tx=sx-1; tx>=0; tx--) { col=pgm_read_word(&data[(ty*sx)+tx]); LCD_Write_DATA(col>>8,col & 0xff); } } } } else { if (orient==PORTRAIT) { for (ty=0; ty<sy; ty++) { setXY(x, y+(ty*scale), x+((sx*scale)-1), y+(ty*scale)+scale); for (tsy=0; tsy<scale; tsy++) for (tx=0; tx<sx; tx++) { col=pgm_read_word(&data[(ty*sx)+tx]); for (tsx=0; tsx<scale; tsx++) LCD_Write_DATA(col>>8,col & 0xff); } } } else { for (ty=0; ty<sy; ty++) { for (tsy=0; tsy<scale; tsy++) { setXY(x, y+(ty*scale)+tsy, x+((sx*scale)-1), y+(ty*scale)+tsy); for (tx=sx-1; tx>=0; tx--) { col=pgm_read_word(&data[(ty*sx)+tx]); for (tsx=0; tsx<scale; tsx++) LCD_Write_DATA(col>>8,col & 0xff); } } } } } clrXY(); } void ArduLCD::drawBitmap(int x, int y, int sx, int sy, bitmapdatatype data, int deg, int rox, int roy) { unsigned int col; int tx, ty, newx, newy; double radian; radian=deg*0.0175; if (deg==0) drawBitmap(x, y, sx, sy, data); else { for (ty=0; ty<sy; ty++) for (tx=0; tx<sx; tx++) { col=pgm_read_word(&data[(ty*sx)+tx]); newx=x+rox+(((tx-rox)*cos(radian))-((ty-roy)*sin(radian))); newy=y+roy+(((ty-roy)*cos(radian))+((tx-rox)*sin(radian))); setXY(newx, newy, newx, newy); LCD_Write_DATA(col>>8,col & 0xff); } } clrXY(); } void ArduLCD::lcdOff() { } void ArduLCD::lcdOn() { } void ArduLCD::setContrast(char c) { } int ArduLCD::getDisplayXSize() { if (orient==PORTRAIT) return disp_x_size+1; else return disp_y_size+1; } int ArduLCD::getDisplayYSize() { if (orient==PORTRAIT) return disp_y_size+1; else return disp_x_size+1; } void ArduLCD::_fast_fill_16(int ch, int cl, long pix) { } void ArduLCD::_fast_fill_8(int ch, long pix) { } void ArduLCD::setBrightness(uint8_t br) { } void ArduLCD::setDisplayPage(uint8_t page) { } void ArduLCD::setWritePage(uint8_t page) { } void ArduLCD::_convert_float(char *buf, double num, int width, uint8_t prec) { }