A first port of the excellent Adafruit ST7735 library

Dependents:   mbed-pong

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