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