Fast! Install BurstSPI library! https://os.mbed.com/users/peekpt/code/BurstSPI/ New display (greentab2 blue module compact).

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Adafruit_ST7735.cpp Source File

Adafruit_ST7735.cpp

00001 /***************************************************
00002   This is a library for the Adafruit 1.8" SPI display.
00003   This library works with the Adafruit 1.8" TFT Breakout w/SD card
00004   ----> http://www.adafruit.com/products/358
00005   as well as Adafruit raw 1.8" TFT display
00006   ----> http://www.adafruit.com/products/618
00007 
00008   Check out the links above for our tutorials and wiring diagrams
00009   These displays use SPI to communicate, 4 or 5 pins are required to
00010   interface (RST is optional)
00011   Adafruit invests time and resources providing this open source code,
00012   please support Adafruit and open-source hardware by purchasing
00013   products from Adafruit!
00014 
00015   Written by Limor Fried/Ladyada for Adafruit Industries.
00016   MIT license, all text above must be included in any redistribution
00017  ****************************************************/
00018 
00019 // + GREENTAB2 display
00020 // BurstSPI
00021 
00022 #include "Adafruit_ST7735.h"
00023 
00024 #include "mbed.h"
00025 
00026 inline uint16_t swapcolor(uint16_t x) {
00027   return (x << 11) | (x & 0x07E0) | (x >> 11);
00028 }
00029 
00030 // Constructor
00031 Adafruit_ST7735::Adafruit_ST7735(PinName mosi, PinName miso, PinName sck,
00032                                  PinName cs, PinName rs, PinName rst)
00033     : lcdPort(mosi, miso, sck), _cs(cs), _rs(rs), _rst(rst),
00034       Adafruit_GFX(ST7735_TFTWIDTH, ST7735_TFTHEIGHT) {}
00035 
00036 void Adafruit_ST7735::writecommand(uint8_t c) {
00037   _rs = 0;
00038   _cs = 0;
00039 
00040   lcdPort.fastWrite(c);
00041   lcdPort.clearRX();
00042   _cs = 1;
00043 }
00044 
00045 void Adafruit_ST7735::writedata(uint8_t c) {
00046   _rs = 1;
00047   _cs = 0;
00048   lcdPort.fastWrite(c);
00049   lcdPort.clearRX();
00050 
00051   _cs = 1;
00052 }
00053 
00054 // Rather than a bazillion writecommand() and writedata() calls, screen
00055 // initialization commands and arguments are organized in these tables
00056 // stored in PROGMEM.  The table may look bulky, but that's mostly the
00057 // formatting -- storage-wise this is hundreds of bytes more compact
00058 // than the equivalent code.  Companion function follows.
00059 #define DELAY 0x80
00060 
00061 static unsigned char Bcmd[] =
00062     {                              // Initialization commands for 7735B screens
00063         18,                        // 18 commands in list:
00064         ST7735_SWRESET, DELAY,     //  1: Software reset, no args, w/delay
00065         50,                        //     50 ms delay
00066         ST7735_SLPOUT, DELAY,      //  2: Out of sleep mode, no args, w/delay
00067         255,                       //     255 = 500 ms delay
00068         ST7735_COLMOD, 1 + DELAY,  //  3: Set color mode, 1 arg + delay:
00069         0x05,                      //     16-bit color
00070         10,                        //     10 ms delay
00071         ST7735_FRMCTR1, 3 + DELAY, //  4: Frame rate control, 3 args + delay:
00072         0x00,                      //     fastest refresh
00073         0x06,                      //     6 lines front porch
00074         0x03,                      //     3 lines back porch
00075         10,                        //     10 ms delay
00076         ST7735_MADCTL, 1,  //  5: Memory access ctrl (directions), 1 arg:
00077         0x08,              //     Row addr/col addr, bottom to top refresh
00078         ST7735_DISSET5, 2, //  6: Display settings #5, 2 args, no delay:
00079         0x15,              //     1 clk cycle nonoverlap, 2 cycle gate
00080                            //     rise, 3 cycle osc equalize
00081         0x02,              //     Fix on VTL
00082         ST7735_INVCTR, 1,  //  7: Display inversion control, 1 arg:
00083         0x0,               //     Line inversion
00084         ST7735_PWCTR1, 2 + DELAY, //  8: Power control, 2 args + delay:
00085         0x02,                     //     GVDD = 4.7V
00086         0x70,                     //     1.0uA
00087         10,                       //     10 ms delay
00088         ST7735_PWCTR2, 1,         //  9: Power control, 1 arg, no delay:
00089         0x05,                     //     VGH = 14.7V, VGL = -7.35V
00090         ST7735_PWCTR3, 2,         // 10: Power control, 2 args, no delay:
00091         0x01,                     //     Opamp current small
00092         0x02,                     //     Boost frequency
00093         ST7735_VMCTR1, 2 + DELAY, // 11: Power control, 2 args + delay:
00094         0x3C,                     //     VCOMH = 4V
00095         0x38,                     //     VCOML = -1.1V
00096         10,                       //     10 ms delay
00097         ST7735_PWCTR6, 2,         // 12: Power control, 2 args, no delay:
00098         0x11, 0x15, ST7735_GMCTRP1,
00099         16,                     // 13: Magical unicorn dust, 16 args, no delay:
00100         0x09, 0x16, 0x09, 0x20, //     (seriously though, not sure what
00101         0x21, 0x1B, 0x13, 0x19, //      these config values represent)
00102         0x17, 0x15, 0x1E, 0x2B, 0x04, 0x05, 0x02, 0x0E, ST7735_GMCTRN1,
00103         16 + DELAY,             // 14: Sparkles and rainbows, 16 args + delay:
00104         0x0B, 0x14, 0x08, 0x1E, //     (ditto)
00105         0x22, 0x1D, 0x18, 0x1E, 0x1B, 0x1A, 0x24, 0x2B, 0x06, 0x06, 0x02, 0x0F,
00106         10,                   //     10 ms delay
00107         ST7735_CASET, 4,      // 15: Column addr set, 4 args, no delay:
00108         0x00, 0x02,           //     XSTART = 2
00109         0x00, 0x81,           //     XEND = 129
00110         ST7735_RASET, 4,      // 16: Row addr set, 4 args, no delay:
00111         0x00, 0x02,           //     XSTART = 1
00112         0x00, 0x81,           //     XEND = 160
00113         ST7735_NORON, DELAY,  // 17: Normal display on, no args, w/delay
00114         10,                   //     10 ms delay
00115         ST7735_DISPON, DELAY, // 18: Main screen turn on, no args, w/delay
00116         255},                 //     255 = 500 ms delay
00117 
00118     Rcmd1[] =
00119         {       // Init for 7735R, part 1 (red or green tab)
00120             15, // 15 commands in list:
00121             ST7735_SWRESET,
00122             DELAY, //  1: Software reset, 0 args, w/delay
00123             150,   //     150 ms delay
00124             ST7735_SLPOUT,
00125             DELAY, //  2: Out of sleep mode, 0 args, w/delay
00126             255,   //     500 ms delay
00127             ST7735_FRMCTR1,
00128             3, //  3: Frame rate ctrl - normal mode, 3 args:
00129             0x01,
00130             0x2C,
00131             0x2D, //     Rate = fosc/(1x2+40) * (LINE+2C+2D)
00132             ST7735_FRMCTR2,
00133             3, //  4: Frame rate control - idle mode, 3 args:
00134             0x01,
00135             0x2C,
00136             0x2D, //     Rate = fosc/(1x2+40) * (LINE+2C+2D)
00137             ST7735_FRMCTR3,
00138             6, //  5: Frame rate ctrl - partial mode, 6 args:
00139             0x01,
00140             0x2C,
00141             0x2D, //     Dot inversion mode
00142             0x01,
00143             0x2C,
00144             0x2D, //     Line inversion mode
00145             ST7735_INVCTR,
00146             1,    //  6: Display inversion ctrl, 1 arg, no delay:
00147             0x07, //     No inversion
00148             ST7735_PWCTR1,
00149             3, //  7: Power control, 3 args, no delay:
00150             0xA2,
00151             0x02, //     -4.6V
00152             0x84, //     AUTO mode
00153             ST7735_PWCTR2,
00154             1,    //  8: Power control, 1 arg, no delay:
00155             0xC5, //     VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
00156             ST7735_PWCTR3,
00157             2,    //  9: Power control, 2 args, no delay:
00158             0x0A, //     Opamp current small
00159             0x00, //     Boost frequency
00160             ST7735_PWCTR4,
00161             2,    // 10: Power control, 2 args, no delay:
00162             0x8A, //     BCLK/2, Opamp current small & Medium low
00163             0x2A,
00164             ST7735_PWCTR5,
00165             2, // 11: Power control, 2 args, no delay:
00166             0x8A,
00167             0xEE,
00168             ST7735_VMCTR1,
00169             1, // 12: Power control, 1 arg, no delay:
00170             0x0E,
00171             ST7735_INVOFF,
00172             0, // 13: Don't invert display, no args, no delay
00173             ST7735_MADCTL,
00174             1,    // 14: Memory access control (directions), 1 arg:
00175             0xC8, //     row addr/col addr, bottom to top refresh
00176             ST7735_COLMOD,
00177             1,     // 15: set color mode, 1 arg, no delay:
00178             0x05}, //     16-bit color
00179 
00180     Rcmd2green[] =
00181         {      // Init for 7735R, part 2 (green tab only)
00182             2, //  2 commands in list:
00183             ST7735_CASET,
00184             4, //  1: Column addr set, 4 args, no delay:
00185             0x00,
00186             0x02, //     XSTART = 0
00187             0x00,
00188             0x7F + 0x02, //     XEND = 127
00189             ST7735_RASET,
00190             4, //  2: Row addr set, 4 args, no delay:
00191             0x00,
00192             0x01, //     XSTART = 0
00193             0x00,
00194             0x9F + 0x01}, //     XEND = 159
00195     Rcmd2red[] =
00196         {      // Init for 7735R, part 2 (red tab only)
00197             2, //  2 commands in list:
00198             ST7735_CASET,
00199             4, //  1: Column addr set, 4 args, no delay:
00200             0x00,
00201             0x00, //     XSTART = 0
00202             0x00,
00203             0x7F, //     XEND = 127
00204             ST7735_RASET,
00205             4, //  2: Row addr set, 4 args, no delay:
00206             0x00,
00207             0x00, //     XSTART = 0
00208             0x00,
00209             0x9F}, //     XEND = 159
00210 
00211     Rcmd2green144[] =
00212         {      // Init for 7735R, part 2 (green 1.44 tab)
00213             2, //  2 commands in list:
00214             ST7735_CASET,
00215             4, //  1: Column addr set, 4 args, no delay:
00216             0x00,
00217             0x00, //     XSTART = 0
00218             0x00,
00219             0x7F, //     XEND = 127
00220             ST7735_RASET,
00221             4, //  2: Row addr set, 4 args, no delay:
00222             0x00,
00223             0x00, //     XSTART = 0
00224             0x00,
00225             0x7F}, //     XEND = 127
00226 
00227     Rcmd3[] = { // Init for 7735R, part 3 (red or green tab)
00228         4,      //  4 commands in list:
00229         ST7735_GMCTRP1,
00230         16, //  1: Magical unicorn dust, 16 args, no delay:
00231         0x02,
00232         0x1c,
00233         0x07,
00234         0x12,
00235         0x37,
00236         0x32,
00237         0x29,
00238         0x2d,
00239         0x29,
00240         0x25,
00241         0x2B,
00242         0x39,
00243         0x00,
00244         0x01,
00245         0x03,
00246         0x10,
00247         ST7735_GMCTRN1,
00248         16, //  2: Sparkles and rainbows, 16 args, no delay:
00249         0x03,
00250         0x1d,
00251         0x07,
00252         0x06,
00253         0x2E,
00254         0x2C,
00255         0x29,
00256         0x2D,
00257         0x2E,
00258         0x2E,
00259         0x37,
00260         0x3F,
00261         0x00,
00262         0x00,
00263         0x02,
00264         0x10,
00265         ST7735_NORON,
00266         DELAY, //  3: Normal display on, no args, w/delay
00267         10,    //     10 ms delay
00268         ST7735_DISPON,
00269         DELAY, //  4: Main screen turn on, no args w/delay
00270         100};  //     100 ms delay
00271 
00272 // Companion code to the above tables.  Reads and issues
00273 // a series of LCD commands stored in byte array.
00274 void Adafruit_ST7735::commandList(uint8_t *addr) {
00275   uint8_t numCommands, numArgs;
00276   uint16_t ms;
00277 
00278   numCommands = *addr++;   // Number of commands to follow
00279   while (numCommands--) {  // For each command...
00280     writecommand(*addr++); //   Read, issue command
00281     numArgs = *addr++;     //   Number of args to follow
00282     ms = numArgs & DELAY;  //   If hibit set, delay follows args
00283     numArgs &= ~DELAY;     //   Mask out delay bit
00284     while (numArgs--) {    //   For each argument...
00285       writedata(*addr++);  //     Read, issue argument
00286     }
00287 
00288     if (ms) {
00289       ms = *addr++; // Read post-command delay time (ms)
00290       if (ms == 255)
00291         ms = 500; // If 255, delay for 500 ms
00292       ThisThread::sleep_for(ms);
00293     }
00294   }
00295 }
00296 
00297 // Initialization code common to both 'B' and 'R' type displays
00298 void Adafruit_ST7735::commonInit(uint8_t *cmdList) {
00299 
00300   colstart = rowstart = 0; // May be overridden in init func
00301 
00302   _rs = 1;
00303   _cs = 1;
00304 
00305   // use default SPI format
00306 
00307   // lcdPort.format(8, 0);
00308   // lcdPort.frequency(4000000);
00309 
00310   lcdPort.setFormat();
00311 
00312   // toggle RST low to reset; CS low so it'll listen to us
00313   _cs = 0;
00314   _rst = 1;
00315   ThisThread::sleep_for(100);
00316   _rst = 0;
00317   ThisThread::sleep_for(100);
00318   _rst = 1;
00319   ThisThread::sleep_for(100);
00320 
00321   if (cmdList)
00322     commandList(cmdList);
00323 }
00324 
00325 // Initialization for ST7735B screens
00326 void Adafruit_ST7735::initB(void) { commonInit(Bcmd); }
00327 
00328 // Initialization for ST7735R screens (green or red tabs)
00329 void Adafruit_ST7735::initR(uint8_t options) {
00330   commonInit(Rcmd1);
00331   if (options == INITR_GREENTAB) {
00332     commandList(Rcmd2green);
00333     colstart = 2;
00334     rowstart = 1;
00335   } else if (options == INITR_GREENTAB2) {
00336     commandList(Rcmd2green);
00337     colstart = 1;
00338     rowstart = 2;
00339   } else if (options == INITR_144GREENTAB) {
00340     _height = ST7735_TFTHEIGHT_144;
00341     commandList(Rcmd2green144);
00342     colstart = 2;
00343     rowstart = 3;
00344   } else {
00345     // colstart, rowstart left at default '0' values
00346     commandList(Rcmd2red);
00347   }
00348   commandList(Rcmd3);
00349 
00350   // if black, change MADCTL color filter
00351   if (options == INITR_BLACKTAB || INITR_GREENTAB2) {
00352     writecommand(ST7735_MADCTL);
00353     writedata(0xC0);
00354   }
00355 
00356   tabcolor = options;
00357 }
00358 
00359 void Adafruit_ST7735::setAddrWindow(uint8_t x0, uint8_t y0, uint8_t x1,
00360                                     uint8_t y1) {
00361   writecommand(ST7735_CASET); // Column addr set
00362   writedata(0x00);
00363   writedata(x0 + colstart); // XSTART
00364   writedata(0x00);
00365   writedata(x1 + colstart); // XEND
00366 
00367   writecommand(ST7735_RASET); // Row addr set
00368   writedata(0x00);
00369   writedata(y0 + rowstart); // YSTART
00370   writedata(0x00);
00371   writedata(y1 + rowstart); // YEND
00372 
00373   writecommand(ST7735_RAMWR); // write to RAM
00374 }
00375 
00376 void Adafruit_ST7735::pushColor(uint16_t color) {
00377   _rs = 1;
00378   _cs = 0;
00379 
00380   lcdPort.fastWrite(color >> 8);
00381   lcdPort.clearRX();
00382   lcdPort.fastWrite(color);
00383   lcdPort.clearRX();
00384   _cs = 1;
00385 }
00386 
00387 void Adafruit_ST7735::drawPixel(int16_t x, int16_t y, uint16_t color) {
00388   if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height))
00389     return;
00390 
00391   setAddrWindow(x, y, x + 1, y + 1);
00392 
00393   _rs = 1;
00394   _cs = 0;
00395 
00396   lcdPort.fastWrite(color >> 8);
00397   lcdPort.clearRX();
00398   lcdPort.fastWrite(color);
00399   lcdPort.clearRX();
00400 
00401   _cs = 1;
00402 }
00403 
00404 void Adafruit_ST7735::drawFastVLine(int16_t x, int16_t y, int16_t h,
00405                                     uint16_t color) {
00406   // Rudimentary clipping
00407   if ((x >= _width) || (y >= _height))
00408     return;
00409   if ((y + h - 1) >= _height)
00410     h = _height - y;
00411   setAddrWindow(x, y, x, y + h - 1);
00412 
00413   uint8_t hi = color >> 8, lo = color;
00414   _rs = 1;
00415   _cs = 0;
00416   while (h--) {
00417     lcdPort.fastWrite(hi);
00418     lcdPort.clearRX();
00419     lcdPort.fastWrite(lo);
00420     lcdPort.clearRX();
00421   }
00422   _cs = 1;
00423 }
00424 
00425 void Adafruit_ST7735::drawFastHLine(int16_t x, int16_t y, int16_t w,
00426                                     uint16_t color) {
00427   // Rudimentary clipping
00428   if ((x >= _width) || (y >= _height))
00429     return;
00430   if ((x + w - 1) >= _width)
00431     w = _width - x;
00432   setAddrWindow(x, y, x + w - 1, y);
00433 
00434   uint8_t hi = color >> 8, lo = color;
00435   _rs = 1;
00436   _cs = 0;
00437   while (w--) {
00438     lcdPort.fastWrite(hi);
00439     lcdPort.clearRX();
00440     lcdPort.fastWrite(lo);
00441     lcdPort.clearRX();
00442   }
00443   _cs = 1;
00444 }
00445 
00446 void Adafruit_ST7735::fillScreen(uint16_t color) {
00447   fillRect(0, 0, _width, _height, color);
00448 }
00449 
00450 // fill a rectangle
00451 void Adafruit_ST7735::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
00452                                uint16_t color) {
00453   // rudimentary clipping (drawChar w/big text requires this)
00454   if ((x >= _width) || (y >= _height))
00455     return;
00456   if ((x + w - 1) >= _width)
00457     w = _width - x;
00458   if ((y + h - 1) >= _height)
00459     h = _height - y;
00460 
00461   setAddrWindow(x, y, x + w - 1, y + h - 1);
00462 
00463   uint8_t hi = color >> 8, lo = color;
00464   _rs = 1;
00465   _cs = 0;
00466   for (y = h; y > 0; y--) {
00467     for (x = w; x > 0; x--) {
00468       lcdPort.fastWrite(hi);
00469       lcdPort.clearRX();
00470       lcdPort.fastWrite(lo);
00471       lcdPort.clearRX();
00472     }
00473   }
00474 
00475   _cs = 1;
00476 }
00477 
00478 // Pass 8-bit (each) R,G,B, get back 16-bit packed color
00479 uint16_t Adafruit_ST7735::Color565(uint8_t r, uint8_t g, uint8_t b) {
00480   return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
00481 }
00482 
00483 #define MADCTL_MY 0x80
00484 #define MADCTL_MX 0x40
00485 #define MADCTL_MV 0x20
00486 #define MADCTL_ML 0x10
00487 #define MADCTL_RGB 0x00
00488 #define MADCTL_BGR 0x08
00489 #define MADCTL_MH 0x04
00490 
00491 void Adafruit_ST7735::setRotation(uint8_t m) {
00492   writecommand(ST7735_MADCTL);
00493   rotation = m % 4; // can't be higher than 3
00494   switch (rotation) {
00495   case 0:
00496     if (tabcolor == INITR_BLACKTAB || INITR_GREENTAB2) {
00497       writedata(MADCTL_MX | MADCTL_MY | MADCTL_RGB);
00498     } else {
00499       writedata(MADCTL_MX | MADCTL_MY | MADCTL_BGR);
00500     }
00501     _width = ST7735_TFTWIDTH;
00502 
00503     if (tabcolor == INITR_144GREENTAB)
00504       _height = ST7735_TFTHEIGHT_144;
00505     else
00506       _height = ST7735_TFTHEIGHT_18;
00507 
00508     break;
00509   case 1:
00510     if (tabcolor == INITR_BLACKTAB || INITR_GREENTAB2) {
00511       writedata(MADCTL_MY | MADCTL_MV | MADCTL_RGB);
00512     } else {
00513       writedata(MADCTL_MY | MADCTL_MV | MADCTL_BGR);
00514     }
00515 
00516     if (tabcolor == INITR_144GREENTAB)
00517       _width = ST7735_TFTHEIGHT_144;
00518     else
00519       _width = ST7735_TFTHEIGHT_18;
00520 
00521     _height = ST7735_TFTWIDTH;
00522     break;
00523   case 2:
00524     if (tabcolor == INITR_BLACKTAB || INITR_GREENTAB2) {
00525       writedata(MADCTL_RGB);
00526     } else {
00527       writedata(MADCTL_BGR);
00528     }
00529     _width = ST7735_TFTWIDTH;
00530     if (tabcolor == INITR_144GREENTAB)
00531       _height = ST7735_TFTHEIGHT_144;
00532     else
00533       _height = ST7735_TFTHEIGHT_18;
00534 
00535     break;
00536   case 3:
00537     if (tabcolor == INITR_BLACKTAB || INITR_GREENTAB2) {
00538       writedata(MADCTL_MX | MADCTL_MV | MADCTL_RGB);
00539     } else {
00540       writedata(MADCTL_MX | MADCTL_MV | MADCTL_BGR);
00541     }
00542     if (tabcolor == INITR_144GREENTAB)
00543       _width = ST7735_TFTHEIGHT_144;
00544     else
00545       _width = ST7735_TFTHEIGHT_18;
00546 
00547     _height = ST7735_TFTWIDTH;
00548     break;
00549   }
00550 }
00551 
00552 void Adafruit_ST7735::invertDisplay(boolean i) {
00553   writecommand(i ? ST7735_INVON : ST7735_INVOFF);
00554 }