Zoltan Hudak / Mbed OS LCD_McuFriend_FSMC_STM32F407
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TFT.cpp Source File

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 #include "TFT.h"
00019 
00020 //#include "mbed_debug.h"
00021 
00022 #define MIPI_DCS_REV1   (1<<0)
00023 #define AUTO_READINC    (1<<1)
00024 #define READ_BGR        (1<<2)
00025 #define READ_LOWHIGH    (1<<3)
00026 #define READ_24BITS     (1<<4)
00027 #define XSA_XEA_16BIT   (1<<5)
00028 #define READ_NODUMMY    (1<<6)
00029 #define INVERT_GS       (1<<8)
00030 #define INVERT_SS       (1<<9)
00031 #define MV_AXIS         (1<<10)
00032 #define INVERT_RGB      (1<<11)
00033 #define REV_SCREEN      (1<<12)
00034 #define FLIP_VERT       (1<<13)
00035 #define FLIP_HORIZ      (1<<14)
00036 
00037 #define SWAP(a, b) { \
00038         a ^= b; \
00039         b ^= a; \
00040         a ^= b; \
00041     }
00042 
00043 #if DEVICE_PORTINOUT
00044 
00045 /**
00046  * @brief
00047  * @note
00048  * @param
00049  * @retval
00050  */
00051 TFT::TFT
00052 (
00053     proto_t         displayproto,
00054     PortName        port,
00055     PinName         CS,
00056     PinName         reset,
00057     PinName         DC,
00058     PinName         WR,
00059     PinName         RD,
00060     const int       lcdsize_x,
00061     const int       lcdsize_y,
00062     const char*     name
00063 ) :
00064     GraphicsDisplay(name),
00065     screensize_X(lcdsize_x),
00066     screensize_Y(lcdsize_y)
00067 {
00068     if (displayproto == PAR_8)
00069         proto = new PAR8(port, CS, reset, DC, WR, RD);
00070     else
00071     if (displayproto == PAR_16)
00072         proto = new PAR16(port, CS, reset, DC, WR, RD);
00073     useNOP = false;
00074     scrollbugfix = 0;
00075     mipistd = false;
00076     set_orientation(0);
00077     foreground(White);
00078     background(Black);
00079     set_auto_up(false); //we don't have framebuffer
00080     topfixedareasize = 0;
00081     scrollareasize = 0;
00082     usefastwindow = false;
00083     fastwindowready = false;
00084     is18bit = false;
00085     isBGR = false;
00086 
00087     //  cls();
00088     //  locate(0,0);
00089 }
00090 #endif
00091 
00092 /**
00093  * @brief
00094  * @note
00095  * @param
00096  * @retval
00097  */
00098 TFT::TFT
00099 (
00100     proto_t         displayproto,
00101     PinName*        buspins,
00102     PinName         CS,
00103     PinName         reset,
00104     PinName         DC,
00105     PinName         WR,
00106     PinName         RD,
00107     const int       lcdsize_x,
00108     const int       lcdsize_y,
00109     const char*     name
00110 ) :
00111     GraphicsDisplay(name),
00112     screensize_X(lcdsize_x),
00113     screensize_Y(lcdsize_y)
00114 {
00115     if (displayproto == BUS_8) {
00116         PinName pins[16];
00117         for (int i = 0; i < 16; i++)
00118             pins[i] = NC;
00119         for (int i = 0; i < 8; i++)
00120             pins[i] = buspins[i];
00121         proto = new BUS8(pins, CS, reset, DC, WR, RD);
00122     }
00123     else
00124     if (displayproto == BUS_16) {
00125         proto = new BUS16(buspins, CS, reset, DC, WR, RD);
00126     }
00127 
00128     useNOP = false;
00129     scrollbugfix = 0;
00130     mipistd = false;
00131     set_orientation(0);
00132     foreground(White);
00133     background(Black);
00134     set_auto_up(false); //we don't have framebuffer
00135     topfixedareasize = 0;
00136     scrollareasize = 0;
00137     usefastwindow = false;
00138     fastwindowready = false;
00139     is18bit = false;
00140     isBGR = false;
00141 
00142     //  cls();
00143     //  locate(0,0);
00144 }
00145 
00146 /**
00147  * @brief
00148  * @note
00149  * @param
00150  * @retval
00151  */
00152 TFT::TFT
00153 (
00154     proto_t         displayproto,
00155     int             Hz,
00156     PinName         mosi,
00157     PinName         miso,
00158     PinName         sclk,
00159     PinName         CS,
00160     PinName         reset,
00161     PinName         DC,
00162     const int       lcdsize_x,
00163     const int       lcdsize_y,
00164     const char*     name
00165 ) :
00166     GraphicsDisplay(name),
00167     screensize_X(lcdsize_x),
00168     screensize_Y(lcdsize_y)
00169 {
00170     if (displayproto == SPI_8) {
00171         proto = new SPI8(Hz, mosi, miso, sclk, CS, reset, DC);
00172         useNOP = false;
00173     }
00174     else
00175     if (displayproto == SPI_16) {
00176         proto = new SPI16(Hz, mosi, miso, sclk, CS, reset, DC);
00177         useNOP = true;
00178     }
00179 
00180     scrollbugfix = 0;
00181     mipistd = false;
00182     set_orientation(0);
00183     foreground(White);
00184     background(Black);
00185     set_auto_up(false);
00186     topfixedareasize = 0;
00187     scrollareasize = 0;
00188     usefastwindow = false;
00189     fastwindowready = false;
00190     is18bit = false;
00191     isBGR = false;
00192 
00193     //  locate(0,0);
00194 }
00195 
00196 /**
00197  * @brief
00198  * @note
00199  * @param
00200  * @retval
00201  */
00202 TFT::TFT(proto_t displayproto, PinName reset, const int lcdsize_x, const int lcdsize_y, const char* name) :
00203     GraphicsDisplay(name),
00204     screensize_X(lcdsize_x),
00205     screensize_Y(lcdsize_y)
00206 {
00207     if (displayproto == FSMC_8) {
00208         proto = new FSMC8(reset);
00209         useNOP = false;
00210     }
00211 
00212     scrollbugfix = 0;
00213     mipistd = false;
00214 
00215     //    set_orientation(0);
00216     foreground(White);
00217     background(Black);
00218     set_auto_up(false); //we don't have framebuffer
00219     topfixedareasize = 0;
00220     scrollareasize = 0;
00221     usefastwindow = false;
00222     fastwindowready = false;
00223     is18bit = false;
00224     isBGR = false;
00225 
00226     //  cls();
00227     //  locate(0,0);
00228 }
00229 
00230 /**
00231  * @brief
00232  * @note
00233  * @param
00234  * @retval
00235  */
00236 void TFT::wr_cmd8(unsigned char cmd)
00237 {
00238     if (useNOP)
00239         proto->wr_cmd16(cmd);   // 0x0000|cmd, 00 is NOP cmd for TFT
00240     else
00241         proto->wr_cmd8(cmd);
00242 }
00243 
00244 /**
00245  * @brief
00246  * @note
00247  * @param
00248  * @retval
00249  */
00250 void TFT::wr_data8(unsigned char data)
00251 {
00252     proto->wr_data8(data);
00253 }
00254 
00255 /**
00256  * @brief
00257  * @note
00258  * @param
00259  * @retval
00260  */
00261 void TFT::wr_data16(unsigned short data)
00262 {
00263     proto->wr_data16(data);
00264 }
00265 
00266 /**
00267  * @brief
00268  * @note
00269  * @param
00270  * @retval
00271  */
00272 void TFT::wr_gram(unsigned short data)
00273 {
00274     proto->wr_gram(data);
00275 }
00276 
00277 /**
00278  * @brief
00279  * @note
00280  * @param
00281  * @retval
00282  */
00283 void TFT::wr_gram(unsigned short data, unsigned int count)
00284 {
00285     proto->wr_gram(data, count);
00286 }
00287 
00288 /**
00289  * @brief
00290  * @note
00291  * @param
00292  * @retval
00293  */
00294 void TFT::wr_grambuf(unsigned short* data, unsigned int lenght)
00295 {
00296     proto->wr_grambuf(data, lenght);
00297 }
00298 
00299 /**
00300  * @brief
00301  * @note
00302  * @param
00303  * @retval
00304  */
00305 unsigned short TFT::rd_gram()
00306 {
00307     return proto->rd_gram(is18bit); // protocol will handle 18to16 bit conversion
00308 }
00309 
00310 /**
00311  * @brief
00312  * @note
00313  * @param
00314  * @retval
00315  */
00316 unsigned int TFT::rd_reg_data32(unsigned char reg)
00317 {
00318     return proto->rd_reg_data32(reg);
00319 }
00320 
00321 /**
00322  * @brief
00323  * @note
00324  * @param
00325  * @retval
00326  */
00327 unsigned int TFT::rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd)
00328 {
00329     return proto->rd_extcreg_data32(reg, SPIreadenablecmd);
00330 }
00331 
00332 //for TFT, just send data, position counters are in hw
00333 void TFT::window_pushpixel(unsigned short color)
00334 {
00335     proto->wr_gram(color);
00336 }
00337 
00338 /**
00339  * @brief
00340  * @note
00341  * @param
00342  * @retval
00343  */
00344 void TFT::window_pushpixel(unsigned short color, unsigned int count)
00345 {
00346     proto->wr_gram(color, count);
00347 }
00348 
00349 /**
00350  * @brief
00351  * @note
00352  * @param
00353  * @retval
00354  */
00355 void TFT::window_pushpixelbuf(unsigned short* color, unsigned int lenght)
00356 {
00357     proto->wr_grambuf(color, lenght);
00358 }
00359 
00360 /**
00361  * @brief
00362  * @note
00363  * @param
00364  * @retval
00365  */
00366 void TFT::hw_reset()
00367 {
00368     proto->hw_reset();
00369     BusEnable(true);
00370 }
00371 
00372 /**
00373  * @brief
00374  * @note
00375  * @param
00376  * @retval
00377  */
00378 void TFT::BusEnable(bool enable)
00379 {
00380     proto->BusEnable(enable);
00381 }
00382 
00383 // color TFT can rotate in hw (swap raw<->columns) for landscape views
00384 void TFT::set_orientation(int orient)
00385 {
00386     //ientation = o;
00387 
00388     //wr_cmd8(0x36);
00389     //switch (orientation) {
00390     //    case 0:                 // default, portrait view 0°
00391     //        if (mipistd)
00392     //            wr_data8(0x0A); // this is in real a vertical flip enabled, seems most displays are vertical flipped
00393     //        else
00394     //            wr_data8(0x48); //for some other ILIxxxx
00395     //        set_width(screensize_X);
00396     //        set_height(screensize_Y);
00397     //        break;
00398     //    case 1:                 // landscape view +90°
00399     //        if (mipistd)
00400     //            wr_data8(0x28);
00401     //        else
00402     //            wr_data8(0x29); //for some other ILIxxxx
00403     //        set_width(screensize_Y);
00404     //        set_height(screensize_X);
00405     //        break;
00406     //    case 2:                 // portrait view +180°
00407     //        if (mipistd)
00408     //            wr_data8(0x09);
00409     //        else
00410     //            wr_data8(0x99); //for some other ILIxxxx
00411     //        set_width(screensize_X);
00412     //        set_height(screensize_Y);
00413     //        break;
00414     //    case 3:                 // landscape view -90°
00415     //        if (mipistd)
00416     //            wr_data8(0x2B);
00417     //        else
00418     //            wr_data8(0xF8); //for some other ILIxxxx
00419     //        set_width(screensize_Y);
00420     //        set_height(screensize_X);
00421     //        break;
00422     //}
00423 
00424     uint8_t     val;
00425 
00426     orientation = orient & 3;                                       // just perform the operation ourselves on the protected variables
00427     set_width((orientation & 1) ? screensize_Y : screensize_X);
00428     set_height((orientation & 1) ? screensize_X : screensize_Y);
00429     switch (orientation) {
00430         case 0:                                                     //PORTRAIT:
00431             val = 0x48;                                             //MY=0, MX=1, MV=0, ML=0, BGR=1
00432             break;
00433 
00434         case 1:                                                     //LANDSCAPE: 90 degrees
00435             val = 0x28;                                             //MY=0, MX=0, MV=1, ML=0, BGR=1
00436             break;
00437 
00438         case 2:                                                     //PORTRAIT_REV: 180 degrees
00439             val = 0x98;                                             //MY=1, MX=0, MV=0, ML=1, BGR=1
00440             break;
00441 
00442         case 3:                                                     //LANDSCAPE_REV: 270 degrees
00443             val = 0xF8;                                             //MY=1, MX=1, MV=1, ML=1, BGR=1
00444             break;
00445     }
00446 
00447     bool        _lcd_capable = 1;
00448     bool        is8347 = 0;
00449     uint16_t    _lcd_rev = 1;
00450 
00451     uint8_t     _MC;
00452     uint8_t     _MP;
00453     uint8_t     _MW;
00454     uint8_t     _SC;
00455     uint8_t     _EC;
00456     uint8_t     _SP;
00457     uint8_t     _EP;
00458 
00459     uint16_t    GS;
00460     uint16_t    SS_v;
00461     uint16_t    ORG;
00462     uint16_t    REV = _lcd_rev;
00463     uint8_t     d[3];
00464     uint16_t    _lcd_ID = tftID;
00465     uint8_t     _lcd_madctl;
00466 
00467     if (_lcd_capable & INVERT_GS)
00468         val ^= 0x80;
00469     if (_lcd_capable & INVERT_SS)
00470         val ^= 0x40;
00471     if (_lcd_capable & INVERT_RGB)
00472         val ^= 0x08;
00473     if (_lcd_capable & MIPI_DCS_REV1) {
00474         if (_lcd_ID == 0x6814) {
00475 
00476             //.kbv my weird 0x9486 might be 68140
00477             GS = (val & 0x80) ? (1 << 6) : 0;                       //MY
00478             SS_v = (val & 0x40) ? (1 << 5) : 0;                     //MX
00479             val &= 0x28;                                            //keep MV, BGR, MY=0, MX=0, ML=0
00480             d[0] = 0;
00481             d[1] = GS | SS_v | 0x02;                                //MY, MX
00482             d[2] = 0x3B;
00483             //WriteCmdParamN(0xB6, 3, d);
00484             wr_cmd8(0xB6);
00485             for (int i = 0; i < 3; i++) {
00486                 wr_data8(d[i]);
00487             }
00488             goto common_MC;
00489         }
00490         else
00491         if (_lcd_ID == 0x1963 || _lcd_ID == 0x9481 || _lcd_ID == 0x1511) {
00492             if (val & 0x80)
00493                 val |= 0x01;                                        //GS
00494             if ((val & 0x40))
00495                 val |= 0x02;                                        //SS
00496             if (_lcd_ID == 0x1963)
00497                 val &= ~0xC0;
00498             if (_lcd_ID == 0x9481)
00499                 val &= ~0xD0;
00500             if (_lcd_ID == 0x1511) {
00501                 val &= ~0x10;                                       //remove ML
00502                 val |= 0xC0;                                        //force penguin 180 rotation
00503             }
00504 
00505             //val &= (_lcd_ID == 0x1963) ? ~0xC0 : ~0xD0; //MY=0, MX=0 with ML=0 for ILI9481
00506             goto common_MC;
00507         }
00508         else
00509         if (is8347) {
00510             uint8_t _MC = 0x02, _MP = 0x06, _MW = 0x22, _SC = 0x02, _EC = 0x04, _SP = 0x06, _EP = 0x08;
00511             if (_lcd_ID == 0x0065) {
00512 
00513                 //HX8352-B
00514                 if (!(val & 0x10))
00515                     val ^= 0x81;                                    //(!ML) flip MY, GS
00516                 if (orient & 1)
00517                     _MC = 0x82, _MP = 0x80;
00518                 else
00519                     _MC = 0x80, _MP = 0x82;
00520             }
00521 
00522             if (_lcd_ID == 0x5252) {
00523                 val |= 0x02;                                        //VERT_SCROLLON
00524                 if (val & 0x10)
00525                     val |= 0x04;                                    //if (ML) SS=1 kludge mirror in XXX_REV modes
00526             }
00527 
00528             goto common_BGR;
00529         }
00530 
00531 common_MC:
00532         _MC = 0x2A, _MP = 0x2B, _MW = 0x2C, _SC = 0x2A, _EC = 0x2A, _SP = 0x2B, _EP = 0x2B;
00533 common_BGR:
00534         //WriteCmdParamN(is8347 ? 0x16 : 0x36, 1, &val);
00535         wr_cmd8(is8347 ? 0x16 : 0x36);
00536         wr_data8(val);
00537 
00538         _lcd_madctl = val;
00539 
00540         //if (_lcd_ID   == 0x1963) WriteCmdParamN(0x13, 0, NULL);   //NORMAL mode
00541     }
00542 
00543     // cope with 9320 variants
00544     else {
00545         switch (_lcd_ID) {
00546 #define SUPPORT_9225
00547     #if defined(SUPPORT_9225)
00548 
00549             case 0x9225:
00550             case 0x9226:
00551                 _SC = 0x37, _EC = 0x36, _SP = 0x39, _EP = 0x38;
00552                 _MC = 0x20, _MP = 0x21, _MW = 0x22;
00553                 GS = (val & 0x80) ? (1 << 9) : 0;
00554                 SS_v = (val & 0x40) ? (1 << 8) : 0;
00555                 //WriteCmdData(0x01, GS | SS_v | 0x001C);             // set Driver Output Control
00556                 wr_cmd8(0x01);
00557                 wr_data8(GS | SS_v | 0x001C);
00558                 goto common_ORG;
00559     #endif
00560 #define SUPPORT_0139
00561     #if defined(SUPPORT_0139) || defined(SUPPORT_0154)
00562     #ifdef SUPPORT_0139
00563 
00564             case 0x0139:
00565                 _SC = 0x46, _EC = 0x46, _SP = 0x48, _EP = 0x47;
00566                 goto common_S6D;
00567     #endif
00568 #define SUPPORT_0154
00569     #ifdef SUPPORT_0154
00570 
00571             case 0x0154:
00572                 _SC = 0x37, _EC = 0x36, _SP = 0x39, _EP = 0x38;
00573                 goto common_S6D;
00574     #endif
00575                 common_S6D : _MC = 0x20, _MP = 0x21, _MW = 0x22;
00576                 GS = (val & 0x80) ? (1 << 9) : 0;
00577                 SS_v = (val & 0x40) ? (1 << 8) : 0;
00578 
00579                 // S6D0139 requires NL = 0x27,  S6D0154 NL = 0x28
00580                 //WriteCmdData(0x01, GS | SS_v | ((_lcd_ID == 0x0139) ? 0x27 : 0x28));
00581                 wr_cmd8(0x01);
00582                 wr_data8(GS | SS_v | ((_lcd_ID == 0x0139) ? 0x27 : 0x28));
00583                 goto common_ORG;
00584     #endif
00585 
00586             case 0x5420:
00587             case 0x7793:
00588             case 0x9326:
00589             case 0xB509:
00590                 _MC = 0x200, _MP = 0x201, _MW = 0x202, _SC = 0x210, _EC = 0x211, _SP = 0x212, _EP = 0x213;
00591                 GS = (val & 0x80) ? (1 << 15) : 0;
00592 
00593                 uint16_t    NL;
00594                 NL = ((432 / 8) - 1) << 9;
00595                 if (_lcd_ID == 0x9326 || _lcd_ID == 0x5420)
00596                     NL >>= 1;
00597                 //WriteCmdData(0x400, GS | NL);
00598                 wr_cmd8(0x400);
00599                 wr_data8(GS | NL);
00600                 goto common_SS;
00601 
00602             default:
00603                 _MC = 0x20, _MP = 0x21, _MW = 0x22, _SC = 0x50, _EC = 0x51, _SP = 0x52, _EP = 0x53;
00604                 GS = (val & 0x80) ? (1 << 15) : 0;
00605                 //WriteCmdData(0x60, GS | 0x2700);                    // Gate Scan Line (0xA700)
00606                 wr_cmd8(0x60);
00607                 wr_data8(GS | 0x2700);
00608     common_SS:
00609                 SS_v = (val & 0x40) ? (1 << 8) : 0;
00610                 //WriteCmdData(0x01, SS_v);                           // set Driver Output Control
00611                 wr_cmd8(0x01);
00612                 wr_data8(SS_v);
00613     common_ORG:
00614                 ORG = (val & 0x20) ? (1 << 3) : 0;
00615     #ifdef SUPPORT_8230
00616                 if (_lcd_ID == 0x8230) {
00617 
00618                     // UC8230 has strange BGR and READ_BGR behaviour
00619                     if (rotation == 1 || rotation == 2) {
00620                         val ^= 0x08;                                // change BGR bit for LANDSCAPE and PORTRAIT_REV
00621                     }
00622                 }
00623     #endif
00624                 if (val & 0x08)
00625                     ORG |= 0x1000;                                  //BGR
00626                 _lcd_madctl = ORG | 0x0030;
00627                 //WriteCmdData(0x03, _lcd_madctl);                    // set GRAM write direction and BGR=1.
00628                 wr_cmd8(0x03);
00629                 wr_data8(_lcd_madctl);
00630 
00631                 break;
00632     #ifdef SUPPORT_1289
00633 
00634             case 0x1289:
00635                 _MC = 0x4E, _MP = 0x4F, _MW = 0x22, _SC = 0x44, _EC = 0x44, _SP = 0x45, _EP = 0x46;
00636                 if (rotation & 1)
00637                     val ^= 0xD0;                                    // exchange Landscape modes
00638                 GS = (val & 0x80) ? (1 << 14) | (1 << 12) : 0;      //called TB (top-bottom)
00639                 SS_v = (val & 0x40) ? (1 << 9) : 0;                 //called RL (right-left)
00640                 ORG = (val & 0x20) ? (1 << 3) : 0;                  //called AM
00641                 _lcd_drivOut = GS | SS_v | (REV << 13) | 0x013F;    //REV=0, BGR=0, MUX=319
00642                 if (val & 0x08)
00643                     _lcd_drivOut |= 0x0800;                         //BGR
00644                 WriteCmdData(0x01, _lcd_drivOut);                   // set Driver Output Control
00645                 WriteCmdData(0x11, ORG | 0x6070);                   // set GRAM write direction.
00646                 break;
00647     #endif
00648         }
00649     }
00650 
00651     if ((orient & 1) && ((_lcd_capable & MV_AXIS) == 0)) {
00652         uint16_t    x;
00653         x = _MC, _MC = _MP, _MP = x;
00654         x = _SC, _SC = _SP, _SP = x;                                //.kbv check 0139
00655         x = _EC, _EC = _EP, _EP = x;                                //.kbv check 0139
00656     }
00657 
00658 //    setAddrWindow(0, 0, width() - 1, height() - 1);
00659 //    vertScroll(0, HEIGHT, 0);                                       //reset scrolling after a rotation
00660 }
00661 
00662 /**
00663  * @brief
00664  * @note
00665  * @param
00666  * @retval
00667  */
00668 void TFT::invert(unsigned char o)
00669 {
00670     if (o == 0)
00671         wr_cmd8(0x20);
00672     else
00673         wr_cmd8(0x21);
00674 }
00675 
00676 /**
00677  * @brief
00678  * @note
00679  * @param
00680  * @retval
00681  */
00682 void TFT::FastWindow(bool enable)
00683 {
00684     usefastwindow = enable;
00685 }
00686 
00687 // TFT have both column and raw autoincrement inside a window, with internal counters
00688 void TFT::window(int x, int y, int w, int h)
00689 {
00690     fastwindowready = false;    // end raw/column going to be set to lower value than bottom-right corner
00691     wr_cmd8(0x2A);
00692     wr_data16(x);               //start column
00693     wr_data16(x + w - 1);       //end column
00694     wr_cmd8(0x2B);
00695     wr_data16(y);               //start page
00696     wr_data16(y + h - 1);       //end page
00697     wr_cmd8(0x2C);              //write mem, just send pixels color next
00698 }
00699 
00700 /**
00701  * @brief
00702  * @note
00703  * @param
00704  * @retval
00705  */
00706 void TFT::window4read(int x, int y, int w, int h)
00707 {
00708     fastwindowready = false;
00709     wr_cmd8(0x2A);
00710     wr_data16(x);           //start column
00711     wr_data16(x + w - 1);   //end column
00712     wr_cmd8(0x2B);
00713     wr_data16(y);           //start page
00714     wr_data16(y + h - 1);   //end page
00715     wr_cmd8(0x2E);          //read mem, just pixelread next
00716 }
00717 
00718 /**
00719  * @brief
00720  * @note
00721  * @param
00722  * @retval
00723  */
00724 void TFT::pixel(int x, int y, unsigned short color)
00725 {
00726     if (usefastwindow) {
00727 
00728         //ili9486 does not like truncated 2A/2B cmds, at least in par mode
00729         if (fastwindowready) {
00730 
00731             //setting only start column/page does speedup, but needs end raw/column previously set to bottom-right corner
00732             wr_cmd8(0x2A);
00733             wr_data16(x);                               //start column only
00734             wr_cmd8(0x2B);
00735             wr_data16(y);                               //start page only
00736             wr_cmd8(0x2C);                              //write mem, just send pixels color next
00737         }
00738         else {
00739             window(x, y, width() - x, height() - y);    // set also end raw/column to bottom-right corner
00740             fastwindowready = true;
00741         }
00742     }
00743     else
00744         window(x, y, 1, 1);
00745 
00746     //  proto->wr_gram(color);   // 2C expects 16bit parameters
00747     wr_gram(color);
00748 }
00749 
00750 /**
00751  * @brief
00752  * @note
00753  * @param
00754  * @retval
00755  */
00756 unsigned short TFT::pixelread(int x, int y)
00757 {
00758     if (usefastwindow) {
00759 
00760         //ili9486 does not like truncated 2A/2B cmds, at least in par mode
00761         if (fastwindowready) {
00762 
00763             //setting only start column/page does speedup, but needs end raw/column previously set to bottom-right corner
00764             wr_cmd8(0x2A);
00765             wr_data16(x);                                   //start column only
00766             wr_cmd8(0x2B);
00767             wr_data16(y);                                   //start page only
00768             wr_cmd8(0x2E);                                  //read mem, just pixelread next
00769         }
00770         else {
00771             window4read(x, y, width() - x, height() - y);   // set also end raw/column to bottom-right corner
00772             fastwindowready = true;
00773         }
00774     }
00775     else
00776         window4read(x, y, 1, 1);
00777 
00778     unsigned short  color;
00779     //  proto->wr_gram(color);   // 2C expects 16bit parameters
00780 
00781     color = rd_gram();
00782     if (isBGR)
00783         color = BGR2RGB(color);                             // in case, convert BGR to RGB (should depend on cmd36 bit3) but maybe is device specific
00784     return color;
00785 }
00786 
00787 /**
00788  * @brief
00789  * @note
00790  * @param
00791  * @retval
00792  */
00793 void TFT::setscrollarea(int startY, int areasize)   // ie 0,480 for whole screen
00794 {
00795     unsigned int    bfa;
00796     topfixedareasize = startY;
00797     scrollareasize = areasize;
00798     wr_cmd8(0x33);
00799     wr_data16(topfixedareasize);                //num lines of top fixed area
00800     wr_data16(scrollareasize + scrollbugfix);   //num lines of vertical scroll area, +1 for ILI9481 fix
00801     if ((areasize + startY) > screensize_Y)
00802         bfa = 0;
00803     else
00804         bfa = screensize_Y - (areasize + startY);
00805     wr_data16(bfa);                             //num lines of bottom fixed area
00806 }
00807 
00808 /**
00809  * @brief
00810  * @note
00811  * @param
00812  * @retval
00813  */
00814 void TFT::scroll(int lines) // ie 1= scrollup 1, 479= scrolldown 1
00815 {
00816     wr_cmd8(0x37);
00817     wr_data16(topfixedareasize + (lines % scrollareasize)); // select the (absolute)line which will be displayed as first scrollarea line
00818 }
00819 
00820 /**
00821  * @brief
00822  * @note
00823  * @param
00824  * @retval
00825  */
00826 void TFT::scrollreset()
00827 {
00828     wr_cmd8(0x13);  //normal display mode
00829 }
00830 
00831 /**
00832  * @brief
00833  * @note
00834  * @param
00835  * @retval
00836  */
00837 void TFT::cls(void)
00838 {
00839     WindowMax();
00840 
00841     //  proto->wr_gram(_background,screensize_X*screensize_Y);
00842     //  proto->wr_gram(0,screensize_X*screensize_Y);
00843     wr_gram(_background, screensize_X * screensize_Y);
00844 }
00845 
00846 // try to get read gram pixel format, could be 16bit or 18bit, RGB or BGR
00847 void TFT::auto_gram_read_format()
00848 {
00849     unsigned short  px = 0xCDB1;
00850     unsigned short  rback, rback18;
00851     pixel(0, 0, px);
00852     window4read(0, 0, 1, 1);
00853     rback = proto->rd_gram(0);      // try 16bit
00854     window4read(0, 0, 1, 1);
00855     rback18 = proto->rd_gram(1);    // try 18bit converted to 16
00856     if ((rback18 == px) || (BGR2RGB(rback18) == px)) {
00857         is18bit = true;
00858         if (BGR2RGB(rback18) == px)
00859             isBGR = true;
00860     }
00861     else
00862     if ((rback == px) || (BGR2RGB(rback) == px)) {
00863         if (BGR2RGB(rback) == px)
00864             isBGR = true;
00865     }
00866 
00867     //   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));
00868 }
00869 
00870 // try to identify display controller
00871 void TFT::identify()
00872 {
00873     // MIPI std read ID cmd
00874 
00875     tftID = rd_reg_data32(0xBF);
00876     mipistd = true;
00877 
00878     //   debug("ID MIPI : 0x%8X\r\n",tftID);
00879     if (((tftID & 0xFF) == ((tftID >> 8) & 0xFF)) && ((tftID & 0xFF) == ((tftID >> 16) & 0xFF))) {
00880         mipistd = false;
00881 
00882         // ILI specfic read ID cmd
00883         tftID = rd_reg_data32(0xD3) >> 8;
00884 
00885         //    debug("ID ILI : 0x%8X\r\n",tftID);
00886     }
00887 
00888     if (((tftID & 0xFF) == ((tftID >> 8) & 0xFF)) && ((tftID & 0xFF) == ((tftID >> 16) & 0xFF))) {
00889 
00890         // ILI specfic read ID cmd with ili9341 specific spi read-in enable 0xD9 cmd
00891         tftID = rd_extcreg_data32(0xD3, 0xD9);
00892 
00893         //    debug("ID D9 extc ILI : 0x%8X\r\n",tftID);
00894     }
00895 
00896     if (((tftID & 0xFF) == ((tftID >> 8) & 0xFF)) && ((tftID & 0xFF) == ((tftID >> 16) & 0xFF))) {
00897 
00898         // ILI specfic read ID cmd with ili9486/88 specific spi read-in enable 0xFB cmd
00899         tftID = rd_extcreg_data32(0xD3, 0xFB);
00900 
00901         //    debug("ID D9 extc ILI : 0x%8X\r\n",tftID);
00902     }
00903 
00904     if (((tftID & 0xFF) == ((tftID >> 8) & 0xFF)) && ((tftID & 0xFF) == ((tftID >> 16) & 0xFF)))
00905         tftID = 0xDEAD;
00906     if ((tftID & 0xFFFF) == 0x9481)
00907         scrollbugfix = 1;
00908     else
00909         scrollbugfix = 0;
00910     if ((tftID & 0xFFFF) == 0x6814) {
00911         mipistd = false;    // RM68140
00912     }
00913 
00914     hw_reset();             // in case wrong cmds messed up important settings
00915 }
00916 
00917 /**
00918  * @brief
00919  * @note
00920  * @param
00921  * @retval
00922  */
00923 int TFT::sizeX()
00924 {
00925     return screensize_X;
00926 }
00927 
00928 /**
00929  * @brief
00930  * @note
00931  * @param
00932  * @retval
00933  */
00934 int TFT::sizeY()
00935 {
00936     return screensize_Y;
00937 }