Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Bicycl_Computer_NUCLEO-F411RE Bicycl_Computer_NUCLEO-L476RG
Fork of UniGraphic by
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 }
Generated on Wed Jul 13 2022 20:11:30 by
1.7.2
