Library for 1.8 inch 160*180 TFT Display. Nice fonts in different formats.

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ST7735.cpp Source File

ST7735.cpp

00001 #include "mbed.h"
00002 #include "ST7735.h"
00003 
00004 #ifdef LOAD_FONT2
00005   #include "Font16.h"
00006 #endif
00007 
00008 #ifdef LOAD_FONT4
00009 #include "Font32.h"
00010 #endif
00011 
00012 #ifdef LOAD_FONT6
00013 #include "Font64.h"
00014 #endif
00015 
00016 #ifdef LOAD_FONT7
00017   #include "Font7s.h"
00018 #endif
00019 
00020 #ifdef LOAD_FONT8
00021   #include "Font72.h"
00022 #endif
00023 
00024 
00025 ST7735::ST7735(PinName cePin, PinName dcPin, PinName mosiPin, PinName sclkPin)
00026 {
00027     spi = new SPI(mosiPin, NC, sclkPin); // create new SPI instance and initialise
00028     initSPI();    
00029     
00030     // set up other pins as required
00031     ce = new DigitalOut(cePin,1);
00032     dc = new DigitalOut(dcPin,0);
00033 
00034     // Defaults after power-up
00035     textsize = 1; 
00036     textcolor = ST7735_GREEN;
00037     textbgcolor = ST7735_BLACK;
00038  }
00039 
00040 // function to initialise SPI peripheral
00041 void ST7735::initSPI()
00042 {
00043     spi->format(8,0);         // 8 bits, Mode 0
00044     spi->frequency(20000000);  // SPI clock frequency
00045 }
00046 
00047 // Write data word 
00048 void ST7735::writecommand(char c) 
00049 {
00050     dc->write(0);
00051     ce->write(0);
00052     spi->write(c);
00053     ce->write(1);
00054 }
00055 
00056 // Write command word
00057 void ST7735::writedata(char c) 
00058 {
00059     dc->write(1);
00060     ce->write(0);
00061     spi->write(c);
00062     ce->write(1);
00063 } 
00064 
00065 
00066 // Rather than a bazillion writecommand() and writedata() calls, screen
00067 // initialization commands and arguments are organized in tables
00068 // The table may look bulky, but that's mostly the
00069 // formatting -- storage-wise this is hundreds of bytes more compact
00070 // than the equivalent code.  Companion function follows.
00071 #define DELAY 0x80
00072 static const uint8_t Bcmd[] = {  // Initialization commands for 7735B screens
00073     18,                       // 18 commands in list:
00074     ST7735_SWRESET,   DELAY,  //  1: Software reset, no args, w/delay
00075       50,                     //     50 ms delay
00076     ST7735_SLPOUT ,   DELAY,  //  2: Out of sleep mode, no args, w/delay
00077       255,                    //     255 = 500 ms delay
00078     ST7735_COLMOD , 1+DELAY,  //  3: Set color mode, 1 arg + delay:
00079       0x05,                   //     16-bit color
00080       10,                     //     10 ms delay
00081     ST7735_FRMCTR1, 3+DELAY,  //  4: Frame rate control, 3 args + delay:
00082       0x00,                   //     fastest refresh
00083       0x06,                   //     6 lines front porch
00084       0x03,                   //     3 lines back porch
00085       10,                     //     10 ms delay
00086     ST7735_MADCTL , 1      ,  //  5: Memory access ctrl (directions), 1 arg:
00087       0x08,                   //     Row addr/col addr, bottom to top refresh
00088     ST7735_DISSET5, 2      ,  //  6: Display settings #5, 2 args, no delay:
00089       0x15,                   //     1 clk cycle nonoverlap, 2 cycle gate
00090                               //     rise, 3 cycle osc equalize
00091       0x02,                   //     Fix on VTL
00092     ST7735_INVCTR , 1      ,  //  7: Display inversion control, 1 arg:
00093       0x0,                    //     Line inversion
00094     ST7735_PWCTR1 , 2+DELAY,  //  8: Power control, 2 args + delay:
00095       0x02,                   //     GVDD = 4.7V
00096       0x70,                   //     1.0uA
00097       10,                     //     10 ms delay
00098     ST7735_PWCTR2 , 1      ,  //  9: Power control, 1 arg, no delay:
00099       0x05,                   //     VGH = 14.7V, VGL = -7.35V
00100     ST7735_PWCTR3 , 2      ,  // 10: Power control, 2 args, no delay:
00101       0x01,                   //     Opamp current small
00102       0x02,                   //     Boost frequency
00103     ST7735_VMCTR1 , 2+DELAY,  // 11: Power control, 2 args + delay:
00104       0x3C,                   //     VCOMH = 4V
00105       0x38,                   //     VCOML = -1.1V
00106       10,                     //     10 ms delay
00107     ST7735_PWCTR6 , 2      ,  // 12: Power control, 2 args, no delay:
00108       0x11, 0x15,
00109     ST7735_GMCTRP1,16      ,  // 13: Magical unicorn dust, 16 args, no delay:
00110       0x09, 0x16, 0x09, 0x20, //     (seriously though, not sure what
00111       0x21, 0x1B, 0x13, 0x19, //      these config values represent)
00112       0x17, 0x15, 0x1E, 0x2B,
00113       0x04, 0x05, 0x02, 0x0E,
00114     ST7735_GMCTRN1,16+DELAY,  // 14: Sparkles and rainbows, 16 args + delay:
00115       0x0B, 0x14, 0x08, 0x1E, //     (ditto)
00116       0x22, 0x1D, 0x18, 0x1E,
00117       0x1B, 0x1A, 0x24, 0x2B,
00118       0x06, 0x06, 0x02, 0x0F,
00119       10,                     //     10 ms delay
00120     ST7735_CASET  , 4      ,  // 15: Column addr set, 4 args, no delay:
00121       0x00, 0x02,             //     XSTART = 2
00122       0x00, 0x81,             //     XEND = 129
00123     ST7735_RASET  , 4      ,  // 16: Row addr set, 4 args, no delay:
00124       0x00, 0x02,             //     XSTART = 1
00125       0x00, 0x81,             //     XEND = 160
00126     ST7735_NORON  ,   DELAY,  // 17: Normal display on, no args, w/delay
00127       10,                     //     10 ms delay
00128     ST7735_DISPON ,   DELAY,  // 18: Main screen turn on, no args, w/delay
00129       255 },                  //     255 = 500 ms delay
00130 
00131   Rcmd1[] = {                 // Init for 7735R, part 1 (red or green tab)
00132     15,                       // 15 commands in list:
00133     ST7735_SWRESET,   DELAY,  //  1: Software reset, 0 args, w/delay
00134       150,                    //     150 ms delay
00135     ST7735_SLPOUT ,   DELAY,  //  2: Out of sleep mode, 0 args, w/delay
00136       255,                    //     500 ms delay
00137     ST7735_FRMCTR1, 3      ,  //  3: Frame rate ctrl - normal mode, 3 args:
00138       0x01, 0x2C, 0x2D,       //     Rate = fosc/(1x2+40) * (LINE+2C+2D)
00139     ST7735_FRMCTR2, 3      ,  //  4: Frame rate control - idle mode, 3 args:
00140       0x01, 0x2C, 0x2D,       //     Rate = fosc/(1x2+40) * (LINE+2C+2D)
00141     ST7735_FRMCTR3, 6      ,  //  5: Frame rate ctrl - partial mode, 6 args:
00142       0x01, 0x2C, 0x2D,       //     Dot inversion mode
00143       0x01, 0x2C, 0x2D,       //     Line inversion mode
00144     ST7735_INVCTR , 1      ,  //  6: Display inversion ctrl, 1 arg, no delay:
00145       0x07,                   //     No inversion
00146     ST7735_PWCTR1 , 3      ,  //  7: Power control, 3 args, no delay:
00147       0xA2,
00148       0x02,                   //     -4.6V
00149       0x84,                   //     AUTO mode
00150     ST7735_PWCTR2 , 1      ,  //  8: Power control, 1 arg, no delay:
00151       0xC5,                   //     VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
00152     ST7735_PWCTR3 , 2      ,  //  9: Power control, 2 args, no delay:
00153       0x0A,                   //     Opamp current small
00154       0x00,                   //     Boost frequency
00155     ST7735_PWCTR4 , 2      ,  // 10: Power control, 2 args, no delay:
00156       0x8A,                   //     BCLK/2, Opamp current small & Medium low
00157       0x2A,  
00158     ST7735_PWCTR5 , 2      ,  // 11: Power control, 2 args, no delay:
00159       0x8A, 0xEE,
00160     ST7735_VMCTR1 , 1      ,  // 12: Power control, 1 arg, no delay:
00161       0x0E,
00162     ST7735_INVOFF , 0      ,  // 13: Don't invert display, no args, no delay
00163     ST7735_MADCTL , 1      ,  // 14: Memory access control (directions), 1 arg:
00164       0xC8,                   //     row addr/col addr, bottom to top refresh
00165     ST7735_COLMOD , 1      ,  // 15: set color mode, 1 arg, no delay:
00166       0x05 },                 //     16-bit color
00167 
00168   Rcmd2green[] = {            // Init for 7735R, part 2 (green tab only)
00169     2,                        //  2 commands in list:
00170     ST7735_CASET  , 4      ,  //  1: Column addr set, 4 args, no delay:
00171       0x00, 0x02,             //     XSTART = 0
00172       0x00, 0x7F+0x02,        //     XEND = 127
00173     ST7735_RASET  , 4      ,  //  2: Row addr set, 4 args, no delay:
00174       0x00, 0x01,             //     XSTART = 0
00175       0x00, 0x9F+0x01 },      //     XEND = 159
00176   Rcmd2red[] = {              // Init for 7735R, part 2 (red tab only)
00177     2,                        //  2 commands in list:
00178     ST7735_CASET  , 4      ,  //  1: Column addr set, 4 args, no delay:
00179       0x00, 0x00,             //     XSTART = 0
00180       0x00, 0x7F,             //     XEND = 127
00181     ST7735_RASET  , 4      ,  //  2: Row addr set, 4 args, no delay:
00182       0x00, 0x00,             //     XSTART = 0
00183       0x00, 0x9F },           //     XEND = 159
00184 
00185   Rcmd3[] = {                 // Init for 7735R, part 3 (red or green tab)
00186     4,                        //  4 commands in list:
00187     ST7735_GMCTRP1, 16      , //  1: Magical unicorn dust, 16 args, no delay:
00188       0x02, 0x1c, 0x07, 0x12,
00189       0x37, 0x32, 0x29, 0x2d,
00190       0x29, 0x25, 0x2B, 0x39,
00191       0x00, 0x01, 0x03, 0x10,
00192     ST7735_GMCTRN1, 16      , //  2: Sparkles and rainbows, 16 args, no delay:
00193       0x03, 0x1d, 0x07, 0x06,
00194       0x2E, 0x2C, 0x29, 0x2D,
00195       0x2E, 0x2E, 0x37, 0x3F,
00196       0x00, 0x00, 0x02, 0x10,
00197     ST7735_NORON  ,    DELAY, //  3: Normal display on, no args, w/delay
00198       10,                     //     10 ms delay
00199     ST7735_DISPON ,    DELAY, //  4: Main screen turn on, no args w/delay
00200       100 };                  //     100 ms delay
00201 
00202 
00203 
00204 // Companion code to the above tables.  Reads and issues
00205 // a series of LCD commands stored in PROGMEM byte array.
00206 void ST7735::commandList(const uint8_t *addr){
00207   uint8_t  numCommands, numArgs;
00208   uint16_t ms;
00209 
00210   numCommands = pgm_read_byte(addr++);   // Number of commands to follow
00211   while(numCommands--) {                 // For each command...
00212     writecommand(pgm_read_byte(addr++)); //   Read, issue command
00213     numArgs  = pgm_read_byte(addr++);    //   Number of args to follow
00214     ms       = numArgs & DELAY;          //   If hibit set, delay follows args
00215     numArgs &= ~DELAY;                   //   Mask out delay bit
00216     while(numArgs--) {                   //   For each argument...
00217     writedata(pgm_read_byte(addr++));    //   Read, issue argument
00218     }
00219 
00220     if(ms) {
00221       ms = pgm_read_byte(addr++); // Read post-command delay time (ms)
00222       if(ms == 255) ms = 500;     // If 255, delay for 500 ms
00223       wait_ms(ms);
00224     }
00225   }
00226 }
00227 
00228 // Initialization code common to both 'B' and 'R' type displays
00229 void ST7735::commonInit(const uint8_t *cmdList){
00230   wait_ms(100);   // Wait for reset to be stable after power-up
00231   colstart  = rowstart = 0; // May be overridden in init func
00232   if(cmdList) commandList(cmdList);
00233 }
00234 
00235 // Initialization for ST7735B screens
00236 void ST7735::initB() {
00237   commonInit(Bcmd);
00238 }
00239 
00240 // Initialization for ST7735R screens (green or red tabs)
00241 void ST7735::initR(uint8_t options) {
00242   commonInit(Rcmd1);
00243   if(options == INITR_GREENTAB) {
00244     commandList(Rcmd2green);
00245     colstart = 2;
00246     rowstart = 1;
00247   } else {
00248     // colstart, rowstart left at default '0' values
00249     commandList(Rcmd2red);
00250   }
00251   commandList(Rcmd3);
00252 
00253   // if black, change MADCTL color filter
00254   if (options == INITR_BLACKTAB) {
00255     writecommand(ST7735_MADCTL);
00256     writedata(0xC0);
00257   }
00258 
00259   tabcolor = options;
00260 }
00261 
00262 void ST7735::setRotation(uint8_t m) {
00263 
00264   writecommand(ST7735_MADCTL);
00265   rotation = m % 4; // can't be higher than 3
00266   switch (rotation) {
00267    case 0:
00268      if (tabcolor == INITR_BLACKTAB) {
00269        writedata(MADCTL_MX | MADCTL_MY | MADCTL_RGB);
00270      } else {
00271        writedata(MADCTL_MX | MADCTL_MY | MADCTL_BGR);
00272      }
00273      _width  = ST7735_TFTWIDTH;
00274      _height = ST7735_TFTHEIGHT;
00275      break;
00276    case 1:
00277      if (tabcolor == INITR_BLACKTAB) {
00278        writedata(MADCTL_MY | MADCTL_MV | MADCTL_RGB);
00279      } else {
00280        writedata(MADCTL_MY | MADCTL_MV | MADCTL_BGR);
00281      }
00282      _width  = ST7735_TFTHEIGHT;
00283      _height = ST7735_TFTWIDTH;
00284      break;
00285   case 2:
00286      if (tabcolor == INITR_BLACKTAB) {
00287        writedata(MADCTL_RGB);
00288      } else {
00289        writedata(MADCTL_BGR);
00290      }
00291      _width  = ST7735_TFTWIDTH;
00292      _height = ST7735_TFTHEIGHT;
00293     break;
00294    case 3:
00295      if (tabcolor == INITR_BLACKTAB) {
00296        writedata(MADCTL_MX | MADCTL_MV | MADCTL_RGB);
00297      } else {
00298        writedata(MADCTL_MX | MADCTL_MV | MADCTL_BGR);
00299      }
00300      _width  = ST7735_TFTHEIGHT;
00301      _height = ST7735_TFTWIDTH;
00302      break;
00303   }
00304 }
00305 
00306 void ST7735::fillScreen(uint16_t color) {
00307   fillRect(0, 0,  _width, _height, color);
00308 }
00309 
00310 
00311 
00312 void ST7735::pushColor(uint16_t color) {
00313   dc->write(1);
00314   ce->write(0);
00315   spi->write(color >> 8);
00316   spi->write(color);
00317   ce->write(1);
00318 }
00319 
00320 // fill a rectangle
00321 void ST7735::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
00322 
00323   // rudimentary clipping (drawChar w/big text requires this)
00324   if((x >= _width) || (y >= _height)) return;
00325   if((x + w - 1) >= _width)  w = _width  - x;
00326   if((y + h - 1) >= _height) h = _height - y;
00327 
00328   setAddrWindow(x, y, x+w-1, y+h-1);
00329 
00330   uint8_t hi = color >> 8, lo = color;
00331 
00332   dc->write(1);
00333   ce->write(0);
00334 
00335   for(y=h; y>0; y--) {
00336     for(x=w; x>0; x--) {
00337       spi->write(hi);
00338       spi->write(lo);
00339     }
00340   }
00341  ce->write(1);
00342 }
00343 
00344 
00345 
00346 void ST7735::invertDisplay(bool i) {
00347   writecommand(i ? ST7735_INVON : ST7735_INVOFF);
00348 }
00349 
00350 void ST7735::drawPixel(int16_t x, int16_t y, uint16_t color) {
00351 
00352   if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
00353 
00354   setAddrWindow(x,y,x+1,y+1);
00355   dc->write(1);
00356   ce->write(0);
00357   spi->write(color >> 8);
00358   spi->write(color);
00359   ce->write(1);
00360 }
00361 
00362 void ST7735::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
00363 
00364   // Rudimentary clipping
00365   if((x >= _width) || (y >= _height)) return;
00366   if((y+h-1) >= _height) h = _height-y;
00367   setAddrWindow(x, y, x, y+h-1);
00368 
00369   uint8_t hi = color >> 8, lo = color;
00370 
00371   dc->write(1);
00372   ce->write(0);
00373     while (h--) {
00374       spi->write(hi);
00375       spi->write(lo);
00376     }
00377   ce->write(1);
00378 }
00379 
00380 void ST7735::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
00381 
00382   // Rudimentary clipping
00383   if((x >= _width) || (y >= _height)) return;
00384   if((x+w-1) >= _width)  w = _width-x;
00385   setAddrWindow(x, y, x+w-1, y);
00386   uint8_t hi = color >> 8, lo = color;
00387 
00388   dc->write(1);;
00389   ce->write(0);;
00390 
00391   while (w--) {
00392     spi->write(hi);
00393     spi->write(lo);
00394   }
00395 
00396   ce->write(1);
00397 }
00398 
00399 // Pass 8-bit (each) R,G,B, get back 16-bit packed color
00400 uint16_t ST7735::Color565(uint8_t r, uint8_t g, uint8_t b) {
00401   return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
00402 }
00403 
00404 // Bresenham's algorithm - thx wikpedia
00405 void ST7735::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) {
00406   int16_t steep = abs(y1 - y0) > abs(x1 - x0);
00407   if (steep) {
00408     swap(x0, y0);
00409     swap(x1, y1);
00410   }
00411 
00412   if (x0 > x1) {
00413     swap(x0, x1);
00414     swap(y0, y1);
00415   }
00416 
00417   int16_t dx, dy;
00418   dx = x1 - x0;
00419   dy = abs(y1 - y0);
00420 
00421   int16_t err = dx / 2;
00422   int16_t ystep;
00423 
00424   if (y0 < y1) {
00425     ystep = 1;
00426   } else {
00427     ystep = -1;
00428   }
00429 
00430   for (; x0<=x1; x0++) {
00431     if (steep) {
00432       drawPixel(y0, x0, color);
00433     } else {
00434       drawPixel(x0, y0, color);
00435     }
00436     err -= dy;
00437     if (err < 0) {
00438       y0 += ystep;
00439       err += dx;
00440     }
00441   }
00442 }
00443 
00444 // Draw a rectangle
00445 void ST7735::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
00446   drawFastHLine(x, y, w, color);
00447   drawFastHLine(x, y+h-1, w, color);
00448   drawFastVLine(x, y, h, color);
00449   drawFastVLine(x+w-1, y, h, color);
00450 }
00451 
00452 // Draw a circle outline
00453 void ST7735::drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color) {
00454   int16_t f = 1 - r;
00455   int16_t ddF_x = 1;
00456   int16_t ddF_y = -2 * r;
00457   int16_t x = 0;
00458   int16_t y = r;
00459 
00460   drawPixel(x0  , y0+r, color);
00461   drawPixel(x0  , y0-r, color);
00462   drawPixel(x0+r, y0  , color);
00463   drawPixel(x0-r, y0  , color);
00464 
00465   while (x<y) {
00466     if (f >= 0) {
00467       y--;
00468       ddF_y += 2;
00469       f += ddF_y;
00470     }
00471     x++;
00472     ddF_x += 2;
00473     f += ddF_x;
00474   
00475     drawPixel(x0 + x, y0 + y, color);
00476     drawPixel(x0 - x, y0 + y, color);
00477     drawPixel(x0 + x, y0 - y, color);
00478     drawPixel(x0 - x, y0 - y, color);
00479     drawPixel(x0 + y, y0 + x, color);
00480     drawPixel(x0 - y, y0 + x, color);
00481     drawPixel(x0 + y, y0 - x, color);
00482     drawPixel(x0 - y, y0 - x, color);
00483   }
00484 }
00485 
00486 void ST7735::drawCircleHelper( int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color) {
00487   int16_t f     = 1 - r;
00488   int16_t ddF_x = 1;
00489   int16_t ddF_y = -2 * r;
00490   int16_t x     = 0;
00491   int16_t y     = r;
00492 
00493   while (x<y) {
00494     if (f >= 0) {
00495       y--;
00496       ddF_y += 2;
00497       f     += ddF_y;
00498     }
00499     x++;
00500     ddF_x += 2;
00501     f     += ddF_x;
00502     if (cornername & 0x4) {
00503       drawPixel(x0 + x, y0 + y, color);
00504       drawPixel(x0 + y, y0 + x, color);
00505     } 
00506     if (cornername & 0x2) {
00507       drawPixel(x0 + x, y0 - y, color);
00508       drawPixel(x0 + y, y0 - x, color);
00509     }
00510     if (cornername & 0x8) {
00511       drawPixel(x0 - y, y0 + x, color);
00512       drawPixel(x0 - x, y0 + y, color);
00513     }
00514     if (cornername & 0x1) {
00515       drawPixel(x0 - y, y0 - x, color);
00516       drawPixel(x0 - x, y0 - y, color);
00517     }
00518   }
00519 }
00520 
00521 void ST7735::fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color) {
00522   drawFastVLine(x0, y0-r, 2*r+1, color);
00523   fillCircleHelper(x0, y0, r, 3, 0, color);
00524 }
00525 
00526 // Used to do circles and roundrects
00527 void ST7735::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, uint16_t color) {
00528 
00529   int16_t f     = 1 - r;
00530   int16_t ddF_x = 1;
00531   int16_t ddF_y = -2 * r;
00532   int16_t x     = 0;
00533   int16_t y     = r;
00534 
00535   while (x<y) {
00536     if (f >= 0) {
00537       y--;
00538       ddF_y += 2;
00539       f     += ddF_y;
00540     }
00541     x++;
00542     ddF_x += 2;
00543     f     += ddF_x;
00544 
00545     if (cornername & 0x1) {
00546       drawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
00547       drawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
00548     }
00549     if (cornername & 0x2) {
00550       drawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
00551       drawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
00552     }
00553   }
00554 }
00555 
00556 
00557 // Draw a triangle
00558 void ST7735::drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) {
00559   drawLine(x0, y0, x1, y1, color);
00560   drawLine(x1, y1, x2, y2, color);
00561   drawLine(x2, y2, x0, y0, color);
00562 }
00563 
00564 // Fill a triangle
00565 void ST7735::fillTriangle ( int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) {
00566 
00567   int16_t a, b, y, last;
00568 
00569   // Sort coordinates by Y order (y2 >= y1 >= y0)
00570   if (y0 > y1) {
00571     swap(y0, y1); swap(x0, x1);
00572   }
00573   if (y1 > y2) {
00574     swap(y2, y1); swap(x2, x1);
00575   }
00576   if (y0 > y1) {
00577     swap(y0, y1); swap(x0, x1);
00578   }
00579 
00580   if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
00581     a = b = x0;
00582     if(x1 < a)      a = x1;
00583     else if(x1 > b) b = x1;
00584     if(x2 < a)      a = x2;
00585     else if(x2 > b) b = x2;
00586     drawFastHLine(a, y0, b-a+1, color);
00587     return;
00588   }
00589 
00590   int16_t
00591     dx01 = x1 - x0,
00592     dy01 = y1 - y0,
00593     dx02 = x2 - x0,
00594     dy02 = y2 - y0,
00595     dx12 = x2 - x1,
00596     dy12 = y2 - y1,
00597     sa   = 0,
00598     sb   = 0;
00599 
00600   // For upper part of triangle, find scanline crossings for segments
00601   // 0-1 and 0-2.  If y1=y2 (flat-bottomed triangle), the scanline y1
00602   // is included here (and second loop will be skipped, avoiding a /0
00603   // error there), otherwise scanline y1 is skipped here and handled
00604   // in the second loop...which also avoids a /0 error here if y0=y1
00605   // (flat-topped triangle).
00606   if(y1 == y2) last = y1;   // Include y1 scanline
00607   else         last = y1-1; // Skip it
00608 
00609   for(y=y0; y<=last; y++) {
00610     a   = x0 + sa / dy01;
00611     b   = x0 + sb / dy02;
00612     sa += dx01;
00613     sb += dx02;
00614     /* longhand:
00615     a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
00616     b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
00617     */
00618     if(a > b) swap(a,b);
00619     drawFastHLine(a, y, b-a+1, color);
00620   }
00621 
00622   // For lower part of triangle, find scanline crossings for segments
00623   // 0-2 and 1-2.  This loop is skipped if y1=y2.
00624   sa = dx12 * (y - y1);
00625   sb = dx02 * (y - y0);
00626   for(; y<=y2; y++) {
00627     a   = x1 + sa / dy12;
00628     b   = x0 + sb / dy02;
00629     sa += dx12;
00630     sb += dx02;
00631     /* longhand:
00632     a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
00633     b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
00634     */
00635     if(a > b) swap(a,b);
00636     drawFastHLine(a, y, b-a+1, color);
00637   }
00638 }
00639 
00640 // Draw a rounded rectangle
00641 void ST7735::drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color) {
00642   // smarter version
00643   drawFastHLine(x+r  , y    , w-2*r, color); // Top
00644   drawFastHLine(x+r  , y+h-1, w-2*r, color); // Bottom
00645   drawFastVLine(x    , y+r  , h-2*r, color); // Left
00646   drawFastVLine(x+w-1, y+r  , h-2*r, color); // Right
00647   // draw four corners
00648   drawCircleHelper(x+r    , y+r    , r, 1, color);
00649   drawCircleHelper(x+w-r-1, y+r    , r, 2, color);
00650   drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
00651   drawCircleHelper(x+r    , y+h-r-1, r, 8, color);
00652 }
00653 
00654 // Fill a rounded rectangle
00655 void ST7735::fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color) {
00656   // smarter version
00657   fillRect(x+r, y, w-2*r, h, color);
00658 
00659   // draw four corners
00660   fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
00661   fillCircleHelper(x+r    , y+r, r, 2, h-2*r-1, color);
00662 }
00663 
00664 void ST7735::setCursor(int16_t x, int16_t y) {
00665   cursor_x = x;
00666   cursor_y = y;
00667 }
00668 
00669 void ST7735::setTextSize(uint8_t s) {
00670   textsize = (s > 0) ? s : 1;
00671 }
00672 
00673 
00674 void ST7735::setTextColor(uint16_t c) {
00675   // For 'transparent' background, we'll set the bg 
00676   // to the same as fg instead of using a flag
00677   textcolor = textbgcolor = c;
00678 }
00679 
00680 void ST7735::setTextColor(uint16_t c, uint16_t b) {
00681   textcolor   = c;
00682   textbgcolor = b; 
00683 }
00684 
00685 void ST7735::setTextWrap(bool w) {
00686   wrap = w;
00687 }
00688 
00689 uint8_t ST7735::getRotation(void) {
00690   return rotation;
00691 }
00692 
00693 void ST7735::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) {
00694 
00695   int16_t i, j, byteWidth = (w + 7) / 8;
00696 
00697   for(j=0; j<h; j++) {
00698     for(i=0; i<w; i++ ) {
00699       if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
00700   drawPixel(x+i, y+j, color);
00701       }
00702     }
00703   }
00704 }
00705 
00706 
00707 /***************************************************************************************
00708 ** Function name:           drawUnicode
00709 ** Descriptions:            draw a unicode
00710 ***************************************************************************************/
00711 int ST7735::drawUnicode(unsigned int uniCode, int x, int y, int font)
00712 {
00713     
00714    if (font) uniCode -= 32;
00715 
00716    unsigned int width = 0;
00717    unsigned int height = 0;
00718    unsigned int flash_address = 0;
00719    int8_t gap = 0;
00720 
00721 //   if (size == 1) {
00722 //     flash_address = pgm_read_word(&chrtbl_f8[uniCode]);
00723 //     width = pgm_read_byte(widtbl_f8+uniCode);
00724 //     height = chr_hgt_f8;
00725 //     gap = 1;
00726 //   }
00727 #ifdef LOAD_FONT2
00728    if (font == 2) {
00729      flash_address = pgm_read_word(&chrtbl_f16[uniCode]);
00730      width = pgm_read_byte(widtbl_f16+uniCode);
00731      height = chr_hgt_f16;
00732      gap = 1;
00733    }
00734 #endif
00735 //   if (font == 3) {
00736 //     flash_address = pgm_read_word(&chrtbl_f24[uniCode]);
00737 //     width = pgm_read_byte(widtbl_f24+uniCode);
00738 //     height = chr_hgt_f24;
00739 //     gap = 0;
00740 //   }
00741 #ifdef LOAD_FONT4
00742    if (font == 4) {
00743      flash_address = pgm_read_word(&chrtbl_f32[uniCode]);
00744      width = pgm_read_byte(widtbl_f32+uniCode);
00745      height = chr_hgt_f32;
00746      gap = -3;
00747    }
00748 #endif
00749 //   if (font == 5) {
00750 //     flash_address = pgm_read_word(&chrtbl_f48[uniCode]);
00751 //     width = pgm_read_byte(widtbl_f48+uniCode);
00752 //     height = chr_hgt_f48;
00753 //     gap = -3;
00754 //   }
00755 #ifdef LOAD_FONT6
00756    if (font == 6) {
00757      flash_address = pgm_read_word(&chrtbl_f64[uniCode]);
00758      width = pgm_read_byte(widtbl_f64+uniCode);
00759      height = chr_hgt_f64;
00760      gap = -3;
00761    }
00762 #endif
00763 #ifdef LOAD_FONT7
00764    if (font == 7) {
00765      flash_address = pgm_read_word(&chrtbl_f7s[uniCode]);
00766      width = pgm_read_byte(widtbl_f7s+uniCode);
00767      height = chr_hgt_f7s;
00768      gap = 2;
00769    }
00770 #endif
00771 #ifdef LOAD_FONT8
00772    if (font == 8) {
00773      flash_address = pgm_read_word(&chrtbl_f72[uniCode]);
00774      width = pgm_read_byte(widtbl_f72+uniCode);
00775      height = chr_hgt_f72;
00776      gap = 2;
00777    }
00778 #endif
00779 
00780 
00781 int w = (width+7)/8;
00782 int pX      = 0;
00783 int pY      = y;
00784 //int color   = 0;
00785 char line = 0;
00786 
00787 //fillRect(x,pY,width+gap,height,textbgcolor);
00788 
00789 for(int i=0; i<height; i++)
00790 {
00791   if (textcolor != textbgcolor) {
00792     if (textsize == 1) drawFastHLine(x, pY, width+gap, textbgcolor);
00793     else fillRect(x, pY, (width+gap)*textsize, textsize, textbgcolor);
00794   }
00795   for (int k = 0;k < w; k++)
00796   { 
00797     line = pgm_read_byte(flash_address+w*i+k);
00798     if(line) {
00799       if (textsize==1){
00800         pX = x + k*8;
00801         if(line & 0x80) drawPixel(pX, pY, textcolor);
00802         if(line & 0x40) drawPixel(pX+1, pY, textcolor);
00803         if(line & 0x20) drawPixel(pX+2, pY, textcolor);
00804         if(line & 0x10) drawPixel(pX+3, pY, textcolor);
00805         if(line & 0x8) drawPixel(pX+4, pY, textcolor);
00806         if(line & 0x4) drawPixel(pX+5, pY, textcolor);
00807         if(line & 0x2) drawPixel(pX+6, pY, textcolor);
00808         if(line & 0x1) drawPixel(pX+7, pY, textcolor);
00809       }
00810        else {
00811         pX = x + k*8*textsize;
00812         if(line & 0x80) fillRect(pX, pY, textsize, textsize, textcolor);
00813         if(line & 0x40) fillRect(pX+textsize, pY, textsize, textsize, textcolor);
00814         if(line & 0x20) fillRect(pX+2*textsize, pY, textsize, textsize, textcolor);
00815         if(line & 0x10) fillRect(pX+3*textsize, pY, textsize, textsize, textcolor);
00816         if(line & 0x8) fillRect(pX+4*textsize, pY, textsize, textsize, textcolor);
00817         if(line & 0x4) fillRect(pX+5*textsize, pY, textsize, textsize, textcolor);
00818         if(line & 0x2) fillRect(pX+6*textsize, pY, textsize, textsize, textcolor);
00819         if(line & 0x1) fillRect(pX+7*textsize, pY, textsize, textsize, textcolor);
00820       }
00821     }
00822   }
00823   pY+=textsize;
00824 }
00825 return (width+gap)*textsize;        // x +
00826 }
00827 
00828 /***************************************************************************************
00829 ** Function name:           drawNumber unsigned with size
00830 ** Descriptions:            drawNumber
00831 ***************************************************************************************/
00832 int ST7735::drawNumber(long long_num,int poX, int poY, int font)
00833 {
00834     char tmp[10];
00835     if (long_num < 0) sprintf(tmp, "%li", long_num);
00836     else sprintf(tmp, "%lu", long_num);
00837     return drawString(tmp, poX, poY, font);
00838 }
00839 
00840 /***************************************************************************************
00841 ** Function name:           drawChar
00842 ** Descriptions:            draw char
00843 ***************************************************************************************/
00844 int ST7735::drawChar(char c, int x, int y, int font)
00845 {
00846     return drawUnicode(c, x, y, font);
00847 }
00848 
00849 /***************************************************************************************
00850 ** Function name:           drawString
00851 ** Descriptions:            draw string
00852 ***************************************************************************************/
00853 int ST7735::drawString(char *string, int poX, int poY, int font)
00854 {
00855     int sumX = 0;
00856 
00857     while(*string)
00858     {
00859         int xPlus = drawChar(*string, poX, poY, font);
00860         sumX += xPlus;
00861         *string++;
00862         poX += xPlus;                            /* Move cursor right       */
00863     }
00864     return sumX;
00865 }
00866 
00867 /***************************************************************************************
00868 ** Function name:           drawCentreString
00869 ** Descriptions:            draw string across centre
00870 ***************************************************************************************/
00871 int ST7735::drawCentreString(char *string, int dX, int poY, int font)
00872 {
00873     int sumX = 0;
00874     int len = 0;
00875     char *pointer = string;
00876     char ascii;
00877 
00878     while(*pointer)
00879     {
00880         ascii = *pointer;
00881         //if (font==0)len += 1+pgm_read_byte(widtbl_log+ascii);
00882         //if (font==1)len += 1+pgm_read_byte(widtbl_f8+ascii-32);
00883 #ifdef LOAD_FONT2
00884         if (font==2)len += 1+pgm_read_byte(widtbl_f16+ascii-32);
00885 #endif
00886         //if (font==3)len += 1+pgm_read_byte(widtbl_f48+ascii-32)/2;
00887 #ifdef LOAD_FONT4
00888         if (font==4)len += pgm_read_byte(widtbl_f32+ascii-32)-3;
00889 #endif
00890         //if (font==5) len += pgm_read_byte(widtbl_f48+ascii-32)-3;
00891 #ifdef LOAD_FONT6
00892         if (font==6) len += pgm_read_byte(widtbl_f64+ascii-32)-3;
00893 #endif
00894 #ifdef LOAD_FONT7
00895         if (font==7) len += pgm_read_byte(widtbl_f7s+ascii-32)+2;
00896 #endif
00897 #ifdef LOAD_FONT8
00898         if (font==8) len += pgm_read_byte(widtbl_f72+ascii-32)+2;
00899 #endif
00900         *pointer++;
00901     }
00902     len = len*textsize;
00903     int poX = dX - len/2;
00904 
00905     if (poX < 0) poX = 0;
00906 
00907     while(*string)
00908     {
00909         
00910         int xPlus = drawChar(*string, poX, poY, font);
00911         sumX += xPlus;
00912         *string++;
00913         poX += xPlus;                  /* Move cursor right            */
00914     }
00915     
00916     return sumX;
00917 }
00918 
00919 /***************************************************************************************
00920 ** Function name:           drawRightString
00921 ** Descriptions:            draw string right justified
00922 ***************************************************************************************/
00923 int ST7735::drawRightString(char *string, int dX, int poY, int font)
00924 {
00925     int sumX = 0;
00926     int len = 0;
00927     char *pointer = string;
00928     char ascii;
00929 
00930     while(*pointer)
00931     {
00932         ascii = *pointer;
00933         //if (font==0)len += 1+pgm_read_byte(widtbl_log+ascii);
00934         //if (font==1)len += 1+pgm_read_byte(widtbl_f8+ascii-32);
00935 #ifdef LOAD_FONT2
00936         if (font==2)len += 1+pgm_read_byte(widtbl_f16+ascii-32);
00937 #endif
00938         //if (font==3)len += 1+pgm_read_byte(widtbl_f48+ascii-32)/2;
00939 #ifdef LOAD_FONT4
00940         if (font==4)len += pgm_read_byte(widtbl_f32+ascii-32)-3;
00941 #endif
00942         //if (font==5) len += pgm_read_byte(widtbl_f48+ascii-32)-3;
00943 #ifdef LOAD_FONT6
00944         if (font==6) len += pgm_read_byte(widtbl_f64+ascii-32)-3;
00945 #endif
00946 #ifdef LOAD_FONT7
00947         if (font==7) len += pgm_read_byte(widtbl_f7s+ascii-32)+2;
00948 #endif
00949 #ifdef LOAD_FONT8
00950         if (font==8) len += pgm_read_byte(widtbl_f72+ascii-32)+2;
00951 #endif
00952         *pointer++;
00953     }
00954     
00955     len = len*textsize;
00956     int poX = dX - len;
00957 
00958     if (poX < 0) poX = 0;
00959 
00960     while(*string)
00961     {
00962         
00963         int xPlus = drawChar(*string, poX, poY, font);
00964         sumX += xPlus;
00965         *string++;
00966         poX += xPlus;          /* Move cursor right            */
00967     }
00968     
00969     return sumX;
00970 }
00971 
00972 /***************************************************************************************
00973 ** Function name:           drawFloat
00974 ** Descriptions:            drawFloat
00975 ***************************************************************************************/
00976 int ST7735::drawFloat(float floatNumber, int decimal, int poX, int poY, int font)
00977 {
00978     unsigned long temp=0;
00979     float decy=0.0;
00980     float rounding = 0.5;
00981     
00982     float eep = 0.000001;
00983     
00984     int sumX    = 0;
00985     int xPlus   = 0;
00986     
00987     if(floatNumber-0.0 < eep)       // floatNumber < 0
00988     {
00989         xPlus = drawChar('-',poX, poY, font);
00990         floatNumber = -floatNumber;
00991 
00992         poX  += xPlus; 
00993         sumX += xPlus;
00994     }
00995     
00996     for (unsigned char i=0; i<decimal; ++i)
00997     {
00998         rounding /= 10.0;
00999     }
01000     
01001     floatNumber += rounding;
01002 
01003     temp = (long)floatNumber;
01004     
01005     
01006     xPlus = drawNumber(temp,poX, poY, font);
01007 
01008     poX  += xPlus; 
01009     sumX += xPlus;
01010 
01011     if(decimal>0)
01012     {
01013         xPlus = drawChar('.',poX, poY, font);
01014         poX += xPlus;                            /* Move cursor right            */
01015         sumX += xPlus;
01016     }
01017     else
01018     {
01019         return sumX;
01020     }
01021     
01022     decy = floatNumber - temp;
01023     for(unsigned char i=0; i<decimal; i++)                                      
01024     {
01025         decy *= 10;                                /* for the next decimal         */
01026         temp = decy;                               /* get the decimal              */
01027         xPlus = drawNumber(temp,poX, poY, font);
01028         
01029         poX += xPlus;                              /* Move cursor right            */
01030         sumX += xPlus;
01031         decy -= temp;
01032     }
01033     return sumX;
01034 }
01035 
01036 void ST7735::setAddrWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) {
01037 
01038   writecommand(ST7735_CASET); // Column addr set
01039   writedata(0x00);
01040   writedata(x0+colstart);     // XSTART 
01041   writedata(0x00);
01042   writedata(x1+colstart);     // XEND
01043 
01044   writecommand(ST7735_RASET); // Row addr set
01045   writedata(0x00);
01046   writedata(y0+rowstart);     // YSTART
01047   writedata(0x00);
01048   writedata(y1+rowstart);     // YEND
01049 
01050   writecommand(ST7735_RAMWR); // write to RAM
01051 }
01052 
01053