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 GraphicsDisplay

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TFT932x.cpp Source File

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 }