UniGraphic-Fork for ST7920-LCD-controller and SH1106. Tested with 128x64 LCD with SPI and 128x64-OLED with IIC
Dependents: UniGraphic-St7920-Test AfficheurUTILECO
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 #if DEVICE_PORTINOUT 00026 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) 00027 : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y) 00028 { 00029 if(displayproto==PAR_8) proto = new PAR8(port, CS, reset, DC, WR, RD); 00030 else if(displayproto==PAR_16) proto = new PAR16(port, CS, reset, DC, WR, RD); 00031 useNOP=false; 00032 scrollbugfix=0; 00033 mipistd=false; 00034 set_orientation(0); 00035 foreground(White); 00036 background(Black); 00037 set_auto_up(false); //we don't have framebuffer 00038 topfixedareasize=0; 00039 scrollareasize=0; 00040 usefastwindow=false; 00041 fastwindowready=false; 00042 is18bit=false; 00043 isBGR=false; 00044 // cls(); 00045 // locate(0,0); 00046 } 00047 #endif 00048 00049 TFT::TFT(proto_t displayproto, PinName* buspins, PinName CS, PinName reset, PinName DC, PinName WR, PinName RD, const int lcdsize_x, const int lcdsize_y, const char *name) 00050 : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y) 00051 { 00052 if(displayproto==BUS_8) 00053 { 00054 PinName pins[16]; 00055 for(int i=0; i<16; i++) pins[i]=NC; 00056 for(int i=0; i<8; i++) pins[i]=buspins[i]; 00057 proto = new BUS8(pins, CS, reset, DC, WR, RD); 00058 } 00059 else if(displayproto==BUS_16) 00060 { 00061 proto = new BUS16(buspins, CS, reset, DC, WR, RD); 00062 } 00063 useNOP=false; 00064 scrollbugfix=0; 00065 mipistd=false; 00066 set_orientation(0); 00067 foreground(White); 00068 background(Black); 00069 set_auto_up(false); //we don't have framebuffer 00070 topfixedareasize=0; 00071 scrollareasize=0; 00072 usefastwindow=false; 00073 fastwindowready=false; 00074 is18bit=false; 00075 isBGR=false; 00076 // cls(); 00077 // locate(0,0); 00078 } 00079 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) 00080 : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y) 00081 { 00082 if(displayproto==SPI_8) 00083 { 00084 proto = new SPI8(Hz, mosi, miso, sclk, CS, reset, DC); 00085 useNOP=false; 00086 } 00087 else if(displayproto==SPI_16) 00088 { 00089 proto = new SPI16(Hz, mosi, miso, sclk, CS, reset, DC); 00090 useNOP=true; 00091 } 00092 scrollbugfix=0; 00093 mipistd=false; 00094 set_orientation(0); 00095 foreground(White); 00096 background(Black); 00097 set_auto_up(false); 00098 topfixedareasize=0; 00099 scrollareasize=0; 00100 usefastwindow=false; 00101 fastwindowready=false; 00102 is18bit=false; 00103 isBGR=false; 00104 // locate(0,0); 00105 } 00106 void TFT::wr_cmd8(unsigned char cmd) 00107 { 00108 if(useNOP) proto->wr_cmd16(cmd); // 0x0000|cmd, 00 is NOP cmd for TFT 00109 else proto->wr_cmd8(cmd); 00110 } 00111 void TFT::wr_data8(unsigned char data) 00112 { 00113 proto->wr_data8(data); 00114 } 00115 void TFT::wr_data16(unsigned short data) 00116 { 00117 proto->wr_data16(data); 00118 } 00119 void TFT::wr_gram(unsigned short data) 00120 { 00121 proto->wr_gram(data); 00122 } 00123 void TFT::wr_gram(unsigned short data, unsigned int count) 00124 { 00125 proto->wr_gram(data, count); 00126 } 00127 void TFT::wr_grambuf(unsigned short* data, unsigned int lenght) 00128 { 00129 proto->wr_grambuf(data, lenght); 00130 } 00131 unsigned short TFT::rd_gram() 00132 { 00133 return proto->rd_gram(is18bit); // protocol will handle 18to16 bit conversion 00134 } 00135 unsigned int TFT::rd_reg_data32(unsigned char reg) 00136 { 00137 return proto->rd_reg_data32(reg); 00138 } 00139 unsigned int TFT::rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd) 00140 { 00141 return proto->rd_extcreg_data32(reg, SPIreadenablecmd); 00142 } 00143 //for TFT, just send data, position counters are in hw 00144 void TFT::window_pushpixel(unsigned short color) 00145 { 00146 proto->wr_gram(color); 00147 } 00148 void TFT::window_pushpixel(unsigned short color, unsigned int count) 00149 { 00150 proto->wr_gram(color, count); 00151 } 00152 void TFT::window_pushpixelbuf(unsigned short* color, unsigned int lenght) 00153 { 00154 proto->wr_grambuf(color, lenght); 00155 } 00156 void TFT::hw_reset() 00157 { 00158 proto->hw_reset(); 00159 BusEnable(true); 00160 } 00161 void TFT::BusEnable(bool enable) 00162 { 00163 proto->BusEnable(enable); 00164 } 00165 // color TFT can rotate in hw (swap raw<->columns) for landscape views 00166 void TFT::set_orientation(int o) 00167 { 00168 orientation = o; 00169 wr_cmd8(0x36); 00170 switch (orientation) { 00171 case 0:// default, portrait view 0° 00172 if(mipistd) wr_data8(0x0A); // this is in real a vertical flip enabled, seems most displays are vertical flipped 00173 else wr_data8(0x48); //for some other ILIxxxx 00174 set_width(screensize_X); 00175 set_height(screensize_Y); 00176 break; 00177 case 1:// landscape view +90° 00178 if(mipistd) wr_data8(0x28); 00179 else wr_data8(0x29);//for some other ILIxxxx 00180 set_width(screensize_Y); 00181 set_height(screensize_X); 00182 break; 00183 case 2:// portrait view +180° 00184 if(mipistd) wr_data8(0x09); 00185 else wr_data8(0x99);//for some other ILIxxxx 00186 set_width(screensize_X); 00187 set_height(screensize_Y); 00188 break; 00189 case 3:// landscape view -90° 00190 if(mipistd) wr_data8(0x2B); 00191 else wr_data8(0xF8);//for some other ILIxxxx 00192 set_width(screensize_Y); 00193 set_height(screensize_X); 00194 break; 00195 } 00196 } 00197 void TFT::invert(unsigned char o) 00198 { 00199 if(o == 0) wr_cmd8(0x20); 00200 else wr_cmd8(0x21); 00201 } 00202 void TFT::FastWindow(bool enable) 00203 { 00204 usefastwindow=enable; 00205 } 00206 // TFT have both column and raw autoincrement inside a window, with internal counters 00207 void TFT::window(int x, int y, int w, int h) 00208 { 00209 fastwindowready=false; // end raw/column going to be set to lower value than bottom-right corner 00210 wr_cmd8(0x2A); 00211 wr_data16(x); //start column 00212 wr_data16(x+w-1);//end column 00213 00214 wr_cmd8(0x2B); 00215 wr_data16(y); //start page 00216 wr_data16(y+h-1);//end page 00217 00218 wr_cmd8(0x2C); //write mem, just send pixels color next 00219 } 00220 void TFT::window4read(int x, int y, int w, int h) 00221 { 00222 fastwindowready=false; 00223 wr_cmd8(0x2A); 00224 wr_data16(x); //start column 00225 wr_data16(x+w-1);//end column 00226 00227 wr_cmd8(0x2B); 00228 wr_data16(y); //start page 00229 wr_data16(y+h-1);//end page 00230 00231 wr_cmd8(0x2E); //read mem, just pixelread next 00232 } 00233 void TFT::pixel(int x, int y, unsigned short color) 00234 { 00235 if(usefastwindow) //ili9486 does not like truncated 2A/2B cmds, at least in par mode 00236 { 00237 if(fastwindowready) //setting only start column/page does speedup, but needs end raw/column previously set to bottom-right corner 00238 { 00239 wr_cmd8(0x2A); 00240 wr_data16(x); //start column only 00241 wr_cmd8(0x2B); 00242 wr_data16(y); //start page only 00243 wr_cmd8(0x2C); //write mem, just send pixels color next 00244 } 00245 else 00246 { 00247 window(x,y,width()-x,height()-y); // set also end raw/column to bottom-right corner 00248 fastwindowready=true; 00249 } 00250 } 00251 else window(x,y,1,1); 00252 // proto->wr_gram(color); // 2C expects 16bit parameters 00253 wr_gram(color); 00254 } 00255 unsigned short TFT::pixelread(int x, int y) 00256 { 00257 if(usefastwindow) //ili9486 does not like truncated 2A/2B cmds, at least in par mode 00258 { 00259 if(fastwindowready) //setting only start column/page does speedup, but needs end raw/column previously set to bottom-right corner 00260 { 00261 wr_cmd8(0x2A); 00262 wr_data16(x); //start column only 00263 wr_cmd8(0x2B); 00264 wr_data16(y); //start page only 00265 wr_cmd8(0x2E); //read mem, just pixelread next 00266 } 00267 else 00268 { 00269 window4read(x,y,width()-x,height()-y); // set also end raw/column to bottom-right corner 00270 fastwindowready=true; 00271 } 00272 } 00273 else window4read(x,y,1,1); 00274 00275 unsigned short color; 00276 // proto->wr_gram(color); // 2C expects 16bit parameters 00277 color = rd_gram(); 00278 if(isBGR) color = BGR2RGB(color); // in case, convert BGR to RGB (should depend on cmd36 bit3) but maybe is device specific 00279 return color; 00280 } 00281 void TFT::setscrollarea (int startY, int areasize) // ie 0,480 for whole screen 00282 { 00283 unsigned int bfa; 00284 topfixedareasize=startY; 00285 scrollareasize=areasize; 00286 wr_cmd8(0x33); 00287 wr_data16(topfixedareasize); //num lines of top fixed area 00288 wr_data16(scrollareasize+scrollbugfix); //num lines of vertical scroll area, +1 for ILI9481 fix 00289 if((areasize+startY)>screensize_Y) bfa=0; 00290 else bfa = screensize_Y-(areasize+startY); 00291 wr_data16(bfa); //num lines of bottom fixed area 00292 } 00293 void TFT::scroll (int lines) // ie 1= scrollup 1, 479= scrolldown 1 00294 { 00295 wr_cmd8(0x37); 00296 wr_data16(topfixedareasize+(lines%scrollareasize)); // select the (absolute)line which will be displayed as first scrollarea line 00297 } 00298 void TFT::scrollreset() 00299 { 00300 wr_cmd8(0x13); //normal display mode 00301 } 00302 void TFT::cls (void) 00303 { 00304 WindowMax(); 00305 // proto->wr_gram(_background,screensize_X*screensize_Y); 00306 // proto->wr_gram(0,screensize_X*screensize_Y); 00307 wr_gram(_background,screensize_X*screensize_Y); 00308 } 00309 // try to get read gram pixel format, could be 16bit or 18bit, RGB or BGR 00310 void TFT::auto_gram_read_format() 00311 { 00312 unsigned short px=0xCDB1; 00313 unsigned short rback, rback18; 00314 pixel(0,0,px); 00315 window4read(0,0,1,1); 00316 rback=proto->rd_gram(0); // try 16bit 00317 window4read(0,0,1,1); 00318 rback18=proto->rd_gram(1); // try 18bit converted to 16 00319 if((rback18==px) || (BGR2RGB(rback18)==px)) 00320 { 00321 is18bit=true; 00322 if(BGR2RGB(rback18)==px) isBGR=true; 00323 } 00324 else if((rback==px) || (BGR2RGB(rback)==px)) 00325 { 00326 if(BGR2RGB(rback)==px) isBGR=true; 00327 } 00328 // debug("\r\nIdentify gram read color format,\r\nsent %.4X read16 %.4X(bgr%.4X) read18 %.4X(bgr%.4X)", px, rback, BGR2RGB(rback), rback18, BGR2RGB(rback18)); 00329 } 00330 // try to identify display controller 00331 void TFT::identify() 00332 { 00333 // MIPI std read ID cmd 00334 tftID=rd_reg_data32(0xBF); 00335 mipistd=true; 00336 // debug("ID MIPI : 0x%8X\r\n",tftID); 00337 if(((tftID&0xFF)==((tftID>>8)&0xFF)) && ((tftID&0xFF)==((tftID>>16)&0xFF))) 00338 { 00339 mipistd=false; 00340 // ILI specfic read ID cmd 00341 tftID=rd_reg_data32(0xD3)>>8; 00342 // debug("ID ILI : 0x%8X\r\n",tftID); 00343 } 00344 if(((tftID&0xFF)==((tftID>>8)&0xFF)) && ((tftID&0xFF)==((tftID>>16)&0xFF))) 00345 { 00346 // ILI specfic read ID cmd with ili9341 specific spi read-in enable 0xD9 cmd 00347 tftID=rd_extcreg_data32(0xD3, 0xD9); 00348 // debug("ID D9 extc ILI : 0x%8X\r\n",tftID); 00349 } 00350 if(((tftID&0xFF)==((tftID>>8)&0xFF)) && ((tftID&0xFF)==((tftID>>16)&0xFF))) 00351 { 00352 // ILI specfic read ID cmd with ili9486/88 specific spi read-in enable 0xFB cmd 00353 tftID=rd_extcreg_data32(0xD3, 0xFB); 00354 // debug("ID D9 extc ILI : 0x%8X\r\n",tftID); 00355 } 00356 if(((tftID&0xFF)==((tftID>>8)&0xFF)) && ((tftID&0xFF)==((tftID>>16)&0xFF))) tftID=0xDEAD; 00357 if ((tftID&0xFFFF)==0x9481) scrollbugfix=1; 00358 else scrollbugfix=0; 00359 hw_reset(); // in case wrong cmds messed up important settings 00360 } 00361 int TFT::sizeX() 00362 { 00363 return screensize_X; 00364 } 00365 int TFT::sizeY() 00366 { 00367 return screensize_Y; 00368 }
Generated on Tue Jul 12 2022 18:00:35 by 1.7.2