Fork of the Adafruit ST7735R library targeted to the 1.44" TFT with custom high speed monochrome and color drawing routines. Note that this library includes modifications to use a shared SPI module to simplify projects that use the SPI for several peripherals. Read the WIKI to see how to get this library working in your own project.

Fork of Adafruit_ST7735 by Andrew Lindsay

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