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