Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Tue Jul 12 2022 17:15:58 by
1.7.2