Darren Ulrich / UniGraphic

Dependents:   Bicycl_Computer_NUCLEO-F411RE Bicycl_Computer_NUCLEO-L476RG

Fork of UniGraphic by GraphicsDisplay

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TFT.cpp Source File

TFT.cpp

00001  /* mbed UniGraphic library - universal TFT driver class
00002  * Copyright (c) 2015 Giuliano Dianda
00003  * Released under the MIT License: http://mbed.org/license/mit
00004  *
00005  * Derived work of:
00006  *
00007  * mbed library for 240*320 pixel display TFT based on ILI9341 LCD Controller
00008  * Copyright (c) 2013 Peter Drescher - DC2PD
00009  *
00010  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00011  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00012  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00013  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00014  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00015  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00016  * THE SOFTWARE.
00017  */
00018 
00019 #include "TFT.h"
00020 
00021 //#include "mbed_debug.h"
00022 
00023 #define SWAP(a, b)  { a ^= b; b ^= a; a ^= b; }
00024 
00025 TFT::TFT(proto_t displayproto, PortName port, PinName CS, PinName reset, PinName DC, PinName WR, PinName RD, const int lcdsize_x, const int lcdsize_y, const char *name)
00026     : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y)
00027 {
00028     if(displayproto==PAR_8) proto = new PAR8(port, CS, reset, DC, WR, RD);
00029     else if(displayproto==PAR_16) proto = new PAR16(port, CS, reset, DC, WR, RD);
00030     useNOP=false;
00031     scrollbugfix=0;
00032     mipistd=false;
00033     set_orientation(0);
00034     foreground(White);
00035     background(Black);
00036     set_auto_up(false); //we don't have framebuffer
00037     topfixedareasize=0;
00038     scrollareasize=0;
00039     usefastwindow=false;
00040     fastwindowready=false;
00041     is18bit=false;
00042     isBGR=false;
00043   //  cls();
00044   //  locate(0,0);
00045 }
00046 TFT::TFT(proto_t displayproto, int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC, const int lcdsize_x, const int lcdsize_y, const char *name)
00047     : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y)
00048 {
00049     if(displayproto==SPI_8)
00050     {
00051         proto = new SPI8(Hz, mosi, miso, sclk, CS, reset, DC);
00052         useNOP=false;
00053     }
00054     else if(displayproto==SPI_16)
00055     {
00056         proto = new SPI16(Hz, mosi, miso, sclk, CS, reset, DC);
00057         useNOP=true;
00058     }
00059     scrollbugfix=0;
00060     mipistd=false;
00061     set_orientation(0);
00062     foreground(White);
00063     background(Black);
00064     set_auto_up(false);
00065     topfixedareasize=0;
00066     scrollareasize=0;
00067     usefastwindow=false;
00068     fastwindowready=false;
00069     is18bit=false;
00070     isBGR=false;
00071   //  locate(0,0);
00072 }
00073 void TFT::wr_cmd8(unsigned char cmd)
00074     {
00075         if(useNOP) proto->wr_cmd16(cmd); // 0x0000|cmd, 00 is NOP cmd for TFT
00076         else proto->wr_cmd8(cmd);
00077     }
00078 void TFT::wr_data8(unsigned char data)
00079     {
00080         proto->wr_data8(data);
00081     }
00082 void TFT::wr_data16(unsigned short data)
00083     {
00084         proto->wr_data16(data);
00085     }
00086 void TFT::wr_gram(unsigned short data)
00087     {
00088         proto->wr_gram(data);
00089     }
00090 void TFT::wr_gram(unsigned short data, unsigned int count)
00091     {
00092         proto->wr_gram(data, count);
00093     }
00094 void TFT::wr_grambuf(unsigned short* data, unsigned int lenght)
00095     {
00096         proto->wr_grambuf(data, lenght);
00097     }
00098 unsigned short TFT::rd_gram()
00099     {
00100         return proto->rd_gram(is18bit); // protocol will handle 18to16 bit conversion
00101     }
00102 unsigned int TFT::rd_reg_data32(unsigned char reg)
00103     {
00104         return proto->rd_reg_data32(reg);
00105     }
00106 unsigned int TFT::rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd)
00107     {
00108         return proto->rd_extcreg_data32(reg, SPIreadenablecmd);
00109     }
00110 //for TFT, just send data, position counters are in hw
00111 void TFT::window_pushpixel(unsigned short color)
00112 {
00113     proto->wr_gram(color);
00114 }
00115 void TFT::window_pushpixel(unsigned short color, unsigned int count)
00116 {
00117     proto->wr_gram(color, count);
00118 }
00119 void TFT::window_pushpixelbuf(unsigned short* color, unsigned int lenght)
00120     {
00121         proto->wr_grambuf(color, lenght);
00122     }
00123 void TFT::hw_reset()
00124     {
00125         proto->hw_reset();
00126     }
00127 void TFT::BusEnable(bool enable)
00128     {
00129         proto->BusEnable(enable);
00130     }
00131 // color TFT can rotate in hw (swap raw<->columns) for landscape views
00132 void TFT::set_orientation(int o)
00133 {
00134     orientation = o;
00135     wr_cmd8(0x36);
00136     switch (orientation) {
00137         case 0:// default, portrait view 0°
00138             if(mipistd) wr_data8(0x0A); // this is in real a vertical flip enabled, seems most displays are vertical flipped
00139             else wr_data8(0x48); //for some other ILIxxxx
00140             set_width(screensize_X);
00141             set_height(screensize_Y);
00142             break;
00143         case 1:// landscape view +90°
00144             if(mipistd) wr_data8(0x28); 
00145             else wr_data8(0x29);//for some other ILIxxxx
00146             set_width(screensize_Y);
00147             set_height(screensize_X);
00148             break;
00149         case 2:// portrait view +180°
00150             if(mipistd) wr_data8(0x09); 
00151             else wr_data8(0x99);//for some other ILIxxxx
00152             set_width(screensize_X);
00153             set_height(screensize_Y);
00154             break;
00155         case 3:// landscape view -90°
00156             if(mipistd) wr_data8(0x2B); 
00157             else wr_data8(0xF8);//for some other ILIxxxx
00158             set_width(screensize_Y);
00159             set_height(screensize_X);
00160             break;
00161     }
00162 }
00163 void TFT::invert(unsigned char o)
00164 {
00165     if(o == 0) wr_cmd8(0x20);
00166     else wr_cmd8(0x21);
00167 }
00168 void TFT::FastWindow(bool enable)
00169     {
00170         usefastwindow=enable;
00171     }
00172 // TFT have both column and raw autoincrement inside a window, with internal counters
00173 void TFT::window(int x, int y, int w, int h)
00174 {
00175     fastwindowready=false; // end raw/column going to be set to lower value than bottom-right corner
00176     wr_cmd8(0x2A);
00177     wr_data16(x);   //start column
00178     wr_data16(x+w-1);//end column
00179 
00180     wr_cmd8(0x2B);
00181     wr_data16(y);   //start page
00182     wr_data16(y+h-1);//end page
00183     
00184     wr_cmd8(0x2C);  //write mem, just send pixels color next
00185 }
00186 void TFT::window4read(int x, int y, int w, int h)
00187 {
00188     fastwindowready=false;
00189     wr_cmd8(0x2A);
00190     wr_data16(x);   //start column
00191     wr_data16(x+w-1);//end column
00192 
00193     wr_cmd8(0x2B);
00194     wr_data16(y);   //start page
00195     wr_data16(y+h-1);//end page
00196     
00197     wr_cmd8(0x2E);  //read mem, just pixelread next
00198 }
00199 void TFT::pixel(int x, int y, unsigned short color)
00200 {
00201     if(usefastwindow) //ili9486 does not like truncated 2A/2B cmds, at least in par mode
00202     {
00203         if(fastwindowready) //setting only start column/page does speedup, but needs end raw/column previously set to bottom-right corner
00204         {
00205             wr_cmd8(0x2A);
00206             wr_data16(x);   //start column only
00207             wr_cmd8(0x2B);
00208             wr_data16(y);   //start page only
00209             wr_cmd8(0x2C);  //write mem, just send pixels color next
00210         }
00211         else
00212         {
00213             window(x,y,width()-x,height()-y); // set also end raw/column to bottom-right corner
00214             fastwindowready=true;
00215         }
00216     }
00217     else window(x,y,1,1);
00218   //  proto->wr_gram(color);   // 2C expects 16bit parameters
00219     wr_gram(color);
00220 }
00221 unsigned short TFT::pixelread(int x, int y)
00222 {
00223     if(usefastwindow) //ili9486 does not like truncated 2A/2B cmds, at least in par mode
00224     {
00225         if(fastwindowready) //setting only start column/page does speedup, but needs end raw/column previously set to bottom-right corner
00226         {
00227             wr_cmd8(0x2A);
00228             wr_data16(x);   //start column only
00229             wr_cmd8(0x2B);
00230             wr_data16(y);   //start page only
00231             wr_cmd8(0x2E);  //read mem, just pixelread next
00232         }
00233         else
00234         {
00235             window4read(x,y,width()-x,height()-y); // set also end raw/column to bottom-right corner
00236             fastwindowready=true;
00237         }
00238     }
00239     else window4read(x,y,1,1);
00240     
00241     unsigned short color;
00242   //  proto->wr_gram(color);   // 2C expects 16bit parameters
00243     color = rd_gram();
00244     if(isBGR) color = BGR2RGB(color); // in case, convert BGR to RGB (should depend on cmd36 bit3) but maybe is device specific
00245     return color;
00246 }
00247 void TFT::setscrollarea (int startY, int areasize) // ie 0,480 for whole screen
00248 {
00249     unsigned int bfa;
00250     topfixedareasize=startY;
00251     scrollareasize=areasize;
00252     wr_cmd8(0x33);
00253     wr_data16(topfixedareasize); //num lines of top fixed area
00254     wr_data16(scrollareasize+scrollbugfix); //num lines of vertical scroll area, +1 for ILI9481 fix
00255     if((areasize+startY)>screensize_Y) bfa=0;
00256     else bfa = screensize_Y-(areasize+startY);
00257     wr_data16(bfa); //num lines of bottom fixed area
00258 }
00259 void TFT::scroll (int lines) // ie 1= scrollup 1, 479= scrolldown 1
00260 {
00261     wr_cmd8(0x37);
00262     wr_data16(topfixedareasize+(lines%scrollareasize)); // select the (absolute)line which will be displayed as first scrollarea line 
00263 }
00264 void TFT::scrollreset()
00265 {
00266     wr_cmd8(0x13);  //normal display mode
00267 }
00268 void TFT::cls (void)
00269 {
00270     WindowMax();
00271   //  proto->wr_gram(_background,screensize_X*screensize_Y);
00272   //  proto->wr_gram(0,screensize_X*screensize_Y);
00273     wr_gram(_background,screensize_X*screensize_Y);
00274 }
00275 // try to get read gram pixel format, could be 16bit or 18bit, RGB or BGR
00276 void TFT::auto_gram_read_format()
00277 {
00278     unsigned short px=0xCDB1;
00279     unsigned short rback, rback18;
00280     pixel(0,0,px);
00281     window4read(0,0,1,1);
00282     rback=proto->rd_gram(0); // try 16bit
00283     window4read(0,0,1,1);
00284     rback18=proto->rd_gram(1); // try 18bit converted to 16
00285     if((rback18==px) || (BGR2RGB(rback18)==px))
00286     {
00287         is18bit=true;
00288         if(BGR2RGB(rback18)==px) isBGR=true;
00289     }
00290     else if((rback==px) || (BGR2RGB(rback)==px))
00291     {
00292         if(BGR2RGB(rback)==px) isBGR=true;
00293     }
00294  //   else debug("\r\nfail to identify gram read color format,\r\nsent %.4X read16 %.4X read18 %.4X", px, rback, rback18);    
00295 }
00296 // try to identify display controller
00297 void TFT::identify()
00298 {
00299     // MIPI std read ID cmd
00300     tftID=rd_reg_data32(0xBF);
00301     mipistd=true;
00302  //   debug("ID MIPI : 0x%8X\r\n",tftID);
00303     if(((tftID&0xFF)==((tftID>>8)&0xFF)) && ((tftID&0xFF)==((tftID>>16)&0xFF)))
00304     {
00305         mipistd=false;
00306         // ILI specfic read ID cmd
00307         tftID=rd_reg_data32(0xD3)>>8; 
00308     //    debug("ID ILI : 0x%8X\r\n",tftID);
00309     }
00310     if(((tftID&0xFF)==((tftID>>8)&0xFF)) && ((tftID&0xFF)==((tftID>>16)&0xFF)))
00311     {
00312         // ILI specfic read ID cmd with ili9341 specific spi read-in enable 0xD9 cmd
00313         tftID=rd_extcreg_data32(0xD3, 0xD9);
00314     //    debug("ID D9 extc ILI : 0x%8X\r\n",tftID);
00315     }
00316     if(((tftID&0xFF)==((tftID>>8)&0xFF)) && ((tftID&0xFF)==((tftID>>16)&0xFF)))
00317     {
00318         // ILI specfic read ID cmd with ili9486/88 specific spi read-in enable 0xFB cmd
00319         tftID=rd_extcreg_data32(0xD3, 0xFB);
00320     //    debug("ID D9 extc ILI : 0x%8X\r\n",tftID);
00321     }
00322     if(((tftID&0xFF)==((tftID>>8)&0xFF)) && ((tftID&0xFF)==((tftID>>16)&0xFF))) tftID=0xDEAD;
00323     if ((tftID&0xFFFF)==0x9481) scrollbugfix=1;
00324     else scrollbugfix=0;
00325     hw_reset(); // in case wrong cmds messed up important settings
00326 }
00327 int TFT::sizeX()
00328 {
00329     return screensize_X;
00330 }
00331 int TFT::sizeY()
00332 {
00333     return screensize_Y;
00334 }