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
TFT932x.cpp
00001 /* mbed UniGraphic library - custom TFT driver class, ILI932x specific 00002 * Copyright (c) 2015 Giuliano Dianda 00003 * Released under the MIT License: http://mbed.org/license/mit 00004 */ 00005 00006 #include "TFT932x.h" 00007 00008 //#include "mbed_debug.h" 00009 00010 #define SWAP(a, b) { a ^= b; b ^= a; a ^= b; } 00011 00012 TFT932x::TFT932x(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) 00013 : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y) 00014 { 00015 if(displayproto==PAR_8) 00016 { 00017 proto = new PAR8(port, CS, reset, DC, WR, RD); 00018 dummycycles=1; 00019 } 00020 else if(displayproto==PAR_16) 00021 { 00022 proto = new PAR16(port, CS, reset, DC, WR, RD); 00023 dummycycles=0; 00024 } 00025 // set_orientation(0); 00026 foreground(White); 00027 background(Black); 00028 set_auto_up(false); //we don't have framebuffer 00029 usefastwindow=false; 00030 fastwindowready=false; 00031 is18bit=false; 00032 isBGR=false; 00033 // cls(); 00034 // locate(0,0); 00035 } 00036 TFT932x::TFT932x(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) 00037 : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y) 00038 { 00039 if(displayproto==BUS_8) 00040 { 00041 PinName pins[16]; 00042 for(int i=0; i<16; i++) pins[i]=NC; 00043 for(int i=0; i<8; i++) pins[i]=buspins[i]; 00044 proto = new BUS8(pins, CS, reset, DC, WR, RD); 00045 dummycycles=1; 00046 } 00047 else if(displayproto==BUS_16) 00048 { 00049 proto = new BUS16(buspins, CS, reset, DC, WR, RD); 00050 dummycycles=0; 00051 } 00052 // set_orientation(0); 00053 foreground(White); 00054 background(Black); 00055 set_auto_up(false); //we don't have framebuffer 00056 usefastwindow=false; 00057 fastwindowready=false; 00058 is18bit=false; 00059 isBGR=false; 00060 // cls(); 00061 // locate(0,0); 00062 } 00063 TFT932x::TFT932x(proto_t displayproto, int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, const int lcdsize_x, const int lcdsize_y, const char *name) 00064 : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y) 00065 { 00066 if(displayproto==SPI_8) 00067 { 00068 proto = new SPI8(Hz, mosi, miso, sclk, CS, reset); 00069 dummycycles=4; 00070 } 00071 else if(displayproto==SPI_16) 00072 { 00073 proto = new SPI16(Hz, mosi, miso, sclk, CS, reset); 00074 dummycycles=2; 00075 } 00076 // set_orientation(0); 00077 foreground(White); 00078 background(Black); 00079 set_auto_up(false); 00080 usefastwindow=false; 00081 fastwindowready=false; 00082 is18bit=false; 00083 isBGR=false; 00084 // locate(0,0); 00085 } 00086 // dummy read needed before read gram 00087 // read gram protocol function does 1 dymmy read as for MIPI standard, but ILI932x needs more and protocol specific number of cycles 00088 // for example in spi mode, 5 dummy byte read needed, so for SPI16 2x16bit clocks done here and the 5th dummy will be handled by read gram function 00089 void TFT932x::dummyread() 00090 { 00091 for(unsigned int i=0; i<dummycycles; i++) proto->dummyread(); 00092 } 00093 void TFT932x::reg_select(unsigned char reg, bool forread) 00094 { 00095 proto->reg_select(reg, forread); 00096 } 00097 void TFT932x::reg_write(unsigned char reg, unsigned short data) 00098 { 00099 proto->reg_write(reg, data); 00100 } 00101 unsigned short TFT932x::reg_read(unsigned char reg) 00102 { 00103 return proto->reg_read(reg); 00104 } 00105 void TFT932x::wr_gram(unsigned short data) 00106 { 00107 proto->wr_gram(data); 00108 } 00109 void TFT932x::wr_gram(unsigned short data, unsigned int count) 00110 { 00111 proto->wr_gram(data, count); 00112 } 00113 void TFT932x::wr_grambuf(unsigned short* data, unsigned int lenght) 00114 { 00115 proto->wr_grambuf(data, lenght); 00116 } 00117 unsigned short TFT932x::rd_gram() 00118 { 00119 return proto->rd_gram(is18bit); // protocol will handle 18to16 bit conversion 00120 00121 } 00122 //for TFT, just send data, position counters are in hw 00123 void TFT932x::window_pushpixel(unsigned short color) 00124 { 00125 proto->wr_gram(color); 00126 } 00127 void TFT932x::window_pushpixel(unsigned short color, unsigned int count) 00128 { 00129 proto->wr_gram(color, count); 00130 } 00131 void TFT932x::window_pushpixelbuf(unsigned short* color, unsigned int lenght) 00132 { 00133 proto->wr_grambuf(color, lenght); 00134 } 00135 void TFT932x::hw_reset() 00136 { 00137 proto->hw_reset(); 00138 BusEnable(true); 00139 } 00140 void TFT932x::BusEnable(bool enable) 00141 { 00142 proto->BusEnable(enable); 00143 } 00144 // ILI932x can't rotate in hw (swap raw<->columns) for landscape views, 00145 // but can change the way address counter is auto incremented/decremented 00146 void TFT932x::set_orientation(int o) 00147 { 00148 // if(orientation == o) return; 00149 orientation = o; 00150 switch (orientation) 00151 // BGR bit set for all modes, seems most TFT are like that, in case override set_orientation() in init 00152 // ORG bit set for all modes 00153 { 00154 case 0:// default, portrait view 0° 00155 reg_write(0x0001,0x0100); // S720 to S1 00156 reg_write(0x0060,0xA700); // G320 to G1 00157 reg_write(0x03, 0x10B0); 00158 set_width(screensize_X); 00159 set_height(screensize_Y); 00160 break; 00161 case 1:// landscape view +90° 00162 reg_write(0x0001,0x0000); // S1 to S720 00163 reg_write(0x0060,0xA700); // G320 to G1 00164 reg_write(0x03, 0x10B8); // AM=1 increase addr ctr first vertically then horizontally 00165 set_width(screensize_Y); 00166 set_height(screensize_X); 00167 break; 00168 case 2:// portrait view +180° 00169 reg_write(0x0001,0x0000); // S1 to S720 00170 reg_write(0x0060,0x2700); // G1 to G320 00171 reg_write(0x03, 0x10B0); 00172 set_width(screensize_X); 00173 set_height(screensize_Y); 00174 break; 00175 case 3:// landscape view -90° 00176 reg_write(0x0001,0x0100); // S720 to S1 00177 reg_write(0x0060,0x2700); // G1 to G320 00178 reg_write(0x03, 0x10B8); // AM=1 increase addr ctr first vertically then horizontally 00179 set_width(screensize_Y); 00180 set_height(screensize_X); 00181 break; 00182 } 00183 } 00184 void TFT932x::invert(unsigned char o) 00185 { 00186 unsigned short oldreg = reg_read(0x61); 00187 if(o == 0) reg_write(0x61, oldreg|1); // seems most TFT have REV bit enabled for normal display 00188 else reg_write(0x61, oldreg&0xFFFE); 00189 } 00190 void TFT932x::FastWindow(bool enable) 00191 { 00192 usefastwindow=enable; 00193 } 00194 // TFT have both column and raw autoincrement inside a window, with internal counters 00195 void TFT932x::window(int x, int y, int w, int h) 00196 { 00197 if(orientation==1 || orientation==3) 00198 { 00199 SWAP(x,y); 00200 SWAP(w,h); 00201 } 00202 fastwindowready=false; // end raw/column going to be set to lower value than bottom-right corner 00203 reg_write(0x50, x);//start column 00204 reg_write(0x51, x+w-1);//end column 00205 reg_write(0x52, y);//start page 00206 reg_write(0x53, y+h-1);//end page 00207 00208 reg_write(0x20, 0); // since ORG bit is set, address is windows relative, so should be set always to 0000 00209 reg_write(0x21, 0); 00210 00211 reg_select(0x22, false); //write mem, just write gram next 00212 } 00213 void TFT932x::window4read(int x, int y, int w, int h) 00214 { 00215 if(orientation==1 || orientation==3) 00216 { 00217 SWAP(x,y); 00218 SWAP(w,h); 00219 } 00220 fastwindowready=false; // end raw/column going to be set to lower value than bottom-right corner 00221 reg_write(0x50, x);//start column 00222 reg_write(0x51, x+w-1);//end column 00223 reg_write(0x52, y);//start page 00224 reg_write(0x53, y+h-1);//end page 00225 00226 reg_write(0x20, 0); // since ORG bit is set, address is windows relative, so should be set always to 0000 00227 reg_write(0x21, 0); 00228 00229 reg_select(0x22, true); //read mem, just read gram next 00230 dummyread(); 00231 } 00232 void TFT932x::pixel(int x, int y, unsigned short color) 00233 { 00234 if(usefastwindow) 00235 { 00236 if(fastwindowready) //setting only start column/page does speedup, but needs end raw/column previously set to bottom-right corner 00237 { 00238 if(orientation==1 || orientation==3) SWAP(x,y); 00239 reg_write(0x50, x);//start column only 00240 reg_write(0x52, y);//start page only 00241 reg_write(0x20, 0); // since ORG bit is set, address is window relative, so should be set always to 0000 00242 reg_write(0x21, 0); 00243 reg_select(0x22, false); //write mem, just write gram 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 wr_gram(color); 00253 } 00254 unsigned short TFT932x::pixelread(int x, int y) 00255 { 00256 /* if(usefastwindow) // for ILI9325 fastwindows for reading works only in PAR16 00257 { 00258 if(fastwindowready) //setting only start column/page does speedup, but needs end raw/column previously set to bottom-right corner 00259 { 00260 if(orientation==1 || orientation==3) SWAP(x,y); 00261 reg_write(0x50, x);//start column only 00262 reg_write(0x52, y);//start page only 00263 reg_write(0x20, 0); // since ORG bit is set, address is window relative, so should be set always to 0000 00264 reg_write(0x21, 0); 00265 reg_select(0x22, true); //read mem, just read gram 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*/ 00274 window4read(x,y,1,1); 00275 00276 unsigned short color; 00277 color = rd_gram(); 00278 if(isBGR) color = BGR2RGB(color); // in case, convert BGR to RGB 00279 return color; 00280 } 00281 void TFT932x::setscrollarea (int startY, int areasize) // ie 0,480 for whole screen 00282 { 00283 // ILI932x allows only ful lscreen scrolling 00284 unsigned short oldreg = reg_read(0x61); 00285 reg_write(0x61, oldreg|2); // enable scroll 00286 } 00287 void TFT932x::scroll (int lines) // ie 1= scrollup 1, 479= scrolldown 1 00288 { 00289 reg_write(0x6A, lines%screensize_Y); // select the (absolute)line which will be displayed as first line 00290 } 00291 void TFT932x::scrollreset() 00292 { 00293 unsigned short oldreg = reg_read(0x61); 00294 // reg_write(0x61, oldreg&0xFFFD); // disable scroll 00295 reg_write(0x6A, 0); 00296 } 00297 void TFT932x::cls (void) 00298 { 00299 WindowMax(); 00300 wr_gram(_background,screensize_X*screensize_Y); 00301 } 00302 // try to get read gram pixel format, could be 16bit or 18bit, RGB or BGR 00303 void TFT932x::auto_gram_read_format() 00304 { 00305 unsigned short px=0xCDB1; 00306 unsigned short rback, rback18; 00307 pixel(0,0,px); 00308 window4read(0,0,1,1); 00309 rback=proto->rd_gram(0); // try 16bit 00310 window4read(0,0,1,1); 00311 rback18=proto->rd_gram(1); // try 18bit converted to 16 00312 if((rback18==px) || (BGR2RGB(rback18)==px)) 00313 { 00314 is18bit=true; 00315 if(BGR2RGB(rback18)==px) isBGR=true; 00316 } 00317 else if((rback==px) || (BGR2RGB(rback)==px)) 00318 { 00319 if(BGR2RGB(rback)==px) isBGR=true; 00320 } 00321 // 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)); 00322 } 00323 // try to identify display controller 00324 void TFT932x::identify() 00325 { 00326 tftID = reg_read(0x00); 00327 hw_reset(); // in case wrong cmd messed up important settings 00328 } 00329 int TFT932x::sizeX() 00330 { 00331 return screensize_X; 00332 } 00333 int TFT932x::sizeY() 00334 { 00335 return screensize_Y; 00336 }
Generated on Wed Jul 13 2022 21:19:22 by 1.7.2