skydarc meneldoll / Mbed OS test_TFT_11_v5
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ST7735.cpp Source File

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 "ST7735.h"
00021 
00022 Serial output1(USBTX, USBRX);
00023 
00024 //uint16_t table[1028][18] __attribute__((section("AHBSRAM0")));
00025 
00026 inline uint16_t swapcolor(uint16_t x) { 
00027   return (x << 11) | (x & 0x07E0) | (x >> 11);
00028 }
00029 
00030 // Constructor 
00031 ST7735::ST7735(PinName mosi, PinName miso, PinName sck, PinName cs, PinName rs, PinName rst) 
00032         : lcdPort(mosi, miso, sck), _cs(cs), _rs(rs), _rst(rst), GFX(ST7735_TFTWIDTH_128, ST7735_TFTHEIGHT_160) 
00033 { }
00034 
00035 
00036 void ST7735::writecommand(uint8_t c)
00037 {
00038     _rs = 0;
00039     _cs = 0;
00040     lcdPort.write( c );
00041     _cs = 1;
00042 }
00043 
00044 
00045 void ST7735::writedata(uint8_t c)
00046 {
00047     _rs = 1;
00048     _cs = 0;
00049     lcdPort.write( c );
00050 
00051     _cs = 1;
00052 }
00053 
00054 
00055 // Rather than a bazillion writecommand() and writedata() calls, screen
00056 // initialization commands and arguments are organized in these tables
00057 // stored in PROGMEM.  The table may look bulky, but that's mostly the
00058 // formatting -- storage-wise this is hundreds of bytes more compact
00059 // than the equivalent code.  Companion function follows.
00060 #define DELAY 0x80
00061 static unsigned char
00062   Bcmd[] = {                  // 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,
00099     ST7735_GMCTRP1,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,
00103       0x04, 0x05, 0x02, 0x0E,
00104     ST7735_GMCTRN1,16+DELAY,  // 14: Sparkles and rainbows, 16 args + delay:
00105       0x0B, 0x14, 0x08, 0x1E, //     (ditto)
00106       0x22, 0x1D, 0x18, 0x1E,
00107       0x1B, 0x1A, 0x24, 0x2B,
00108       0x06, 0x06, 0x02, 0x0F,
00109       10,                     //     10 ms delay
00110     ST7735_CASET  , 4      ,  // 15: Column addr set, 4 args, no delay:
00111       0x00, 0x02,             //     XSTART = 2
00112       0x00, 0x81,             //     XEND = 129
00113     ST7735_RASET  , 4      ,  // 16: Row addr set, 4 args, no delay:
00114       0x00, 0x02,             //     XSTART = 1
00115       0x00, 0x81,             //     XEND = 160
00116     ST7735_NORON  ,   DELAY,  // 17: Normal display on, no args, w/delay
00117       10,                     //     10 ms delay
00118     ST7735_DISPON ,   DELAY,  // 18: Main screen turn on, no args, w/delay
00119       255 },                  //     255 = 500 ms delay
00120 
00121   Rcmd1[] = {                 // Init for 7735R, part 1 (red or green tab)
00122     15,                       // 15 commands in list:
00123     ST7735_SWRESET,   DELAY,  //  1: Software reset, 0 args, w/delay
00124       150,                    //     150 ms delay
00125     ST7735_SLPOUT ,   DELAY,  //  2: Out of sleep mode, 0 args, w/delay
00126       255,                    //     500 ms delay
00127     ST7735_FRMCTR1, 3      ,  //  3: Frame rate ctrl - normal mode, 3 args:
00128       0x01, 0x2C, 0x2D,       //     Rate = fosc/(1x2+40) * (LINE+2C+2D)
00129     ST7735_FRMCTR2, 3      ,  //  4: Frame rate control - idle mode, 3 args:
00130       0x01, 0x2C, 0x2D,       //     Rate = fosc/(1x2+40) * (LINE+2C+2D)
00131     ST7735_FRMCTR3, 6      ,  //  5: Frame rate ctrl - partial mode, 6 args:
00132       0x01, 0x2C, 0x2D,       //     Dot inversion mode
00133       0x01, 0x2C, 0x2D,       //     Line inversion mode
00134     ST7735_INVCTR , 1      ,  //  6: Display inversion ctrl, 1 arg, no delay:
00135       0x07,                   //     No inversion
00136     ST7735_PWCTR1 , 3      ,  //  7: Power control, 3 args, no delay:
00137       0xA2,
00138       0x02,                   //     -4.6V
00139       0x84,                   //     AUTO mode
00140     ST7735_PWCTR2 , 1      ,  //  8: Power control, 1 arg, no delay:
00141       0xC5,                   //     VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
00142     ST7735_PWCTR3 , 2      ,  //  9: Power control, 2 args, no delay:
00143       0x0A,                   //     Opamp current small
00144       0x00,                   //     Boost frequency
00145     ST7735_PWCTR4 , 2      ,  // 10: Power control, 2 args, no delay:
00146       0x8A,                   //     BCLK/2, Opamp current small & Medium low
00147       0x2A,  
00148     ST7735_PWCTR5 , 2      ,  // 11: Power control, 2 args, no delay:
00149       0x8A, 0xEE,
00150     ST7735_VMCTR1 , 1      ,  // 12: Power control, 1 arg, no delay:
00151       0x0E,
00152     ST7735_INVOFF , 0      ,  // 13: Don't invert display, no args, no delay
00153     ST7735_MADCTL , 1      ,  // 14: Memory access control (directions), 1 arg:
00154       0xC0,                   //     row addr/col addr, bottom to top refresh
00155     ST7735_COLMOD , 1      ,  // 15: set color mode, 1 arg, no delay:
00156       0x05 },                 //     16-bit color
00157 
00158   Rcmd2green[] = {            // Init for 7735R, part 2 (green tab only)
00159     2,                        //  2 commands in list:
00160     ST7735_CASET  , 4      ,  //  1: Column addr set, 4 args, no delay:
00161       0x00, 0x02,             //     XSTART = 0
00162       0x00, 0x7F+0x02,        //     XEND = 127
00163     ST7735_RASET  , 4      ,  //  2: Row addr set, 4 args, no delay:
00164       0x00, 0x01,             //     XSTART = 0
00165       0x00, 0x9F+0x01 },      //     XEND = 159
00166   Rcmd2red[] = {              // Init for 7735R, part 2 (red tab only)
00167     2,                        //  2 commands in list:
00168     ST7735_CASET  , 4      ,  //  1: Column addr set, 4 args, no delay:
00169       0x00, 0x00,             //     XSTART = 0
00170       0x00, 0x7F,             //     XEND = 127
00171     ST7735_RASET  , 4      ,  //  2: Row addr set, 4 args, no delay:
00172       0x00, 0x00,             //     XSTART = 0
00173       0x00, 0x9F },           //     XEND = 159
00174 
00175   Rcmd2green144[] = {              // Init for 7735R, part 2 (green 1.44 tab)
00176     2,                        //  2 commands in list:
00177     ST7735_CASET  , 4      ,  //  1: Column addr set, 4 args, no delay:
00178       0x00, 0x00,             //     XSTART = 0
00179       0x00, 0x7F,             //     XEND = 127
00180     ST7735_RASET  , 4      ,  //  2: Row addr set, 4 args, no delay:
00181       0x00, 0x00,             //     XSTART = 0
00182       0x00, 0x7F },           //     XEND = 127
00183       
00184   Rcmd2green160x80[] = {              // Init for 7735R, part 2 (mini 160x80)
00185     2,                        //  2 commands in list:
00186     ST7735_CASET  , 4      ,  //  1: Column addr set, 4 args, no delay:
00187       0x00, 0x00,             //     XSTART = 0
00188       0x00, 0x7F,             //     XEND = 79
00189     ST7735_RASET  , 4      ,  //  2: Row addr set, 4 args, no delay:
00190       0x00, 0x00,             //     XSTART = 0
00191       0x00, 0x9F+0x01 },           //     XEND = 159
00192 
00193   Rcmd3[] = {                 // Init for 7735R, part 3 (red or green tab)
00194     4,                        //  4 commands in list:
00195     ST7735_GMCTRP1, 16      , //  1: Magical unicorn dust, 16 args, no delay:
00196       0x02, 0x1c, 0x07, 0x12,
00197       0x37, 0x32, 0x29, 0x2d,
00198       0x29, 0x25, 0x2B, 0x39,
00199       0x00, 0x01, 0x03, 0x10,
00200     ST7735_GMCTRN1, 16      , //  2: Sparkles and rainbows, 16 args, no delay:
00201       0x03, 0x1d, 0x07, 0x06,
00202       0x2E, 0x2C, 0x29, 0x2D,
00203       0x2E, 0x2E, 0x37, 0x3F,
00204       0x00, 0x00, 0x02, 0x10,
00205     ST7735_NORON  ,    DELAY, //  3: Normal display on, no args, w/delay
00206       10,                     //     10 ms delay
00207     ST7735_DISPON ,    DELAY, //  4: Main screen turn on, no args w/delay
00208       100 };                  //     100 ms delay
00209 
00210 
00211 // Companion code to the above tables.  Reads and issues
00212 // a series of LCD commands stored in byte array.
00213 void ST7735::commandList(uint8_t *addr)
00214 {
00215     
00216     uint8_t  numCommands, numArgs;
00217     uint16_t ms;
00218 
00219     numCommands = *addr++;   // Number of commands to follow
00220     while(numCommands--) {                 // For each command...
00221         writecommand(*addr++); //   Read, issue command
00222         numArgs  = *addr++;    //   Number of args to follow
00223         ms       = numArgs & DELAY;          //   If hibit set, delay follows args
00224         numArgs &= ~DELAY;                   //   Mask out delay bit
00225         while(numArgs--) {                   //   For each argument...
00226             writedata(*addr++);  //     Read, issue argument
00227         }
00228 
00229         if(ms) {
00230             ms = *addr++; // Read post-command delay time (ms)
00231             if(ms == 255) ms = 500;     // If 255, delay for 500 ms
00232             wait_ms(ms);
00233         }
00234     }
00235 }
00236 
00237 
00238 // Initialization code common to both 'B' and 'R' type displays
00239 void ST7735::commonInit(uint8_t *cmdList)
00240 {
00241 
00242     colstart  = rowstart = 0; // May be overridden in init func
00243 
00244     _rs = 1;
00245     _cs = 1;
00246 
00247     // use default SPI format
00248     lcdPort.format(8,0);
00249     //lcdPort.frequency(16000000);     // Lets try 4MHz
00250     lcdPort.frequency(64000000);     // Lets try 4MHz
00251 
00252     // toggle RST low to reset; CS low so it'll listen to us
00253     _cs = 0;
00254     _rst = 1;
00255     wait_ms(500);
00256     _rst = 0;
00257     wait_ms(500);
00258     _rst = 1;
00259     wait_ms(500);
00260 
00261     if(cmdList) commandList(cmdList);
00262 }
00263 
00264 
00265 // Initialization for ST7735B screens
00266 void ST7735::initB(void)
00267 {
00268     commonInit(Bcmd);
00269 }
00270 
00271 
00272 // Initialization for ST7735R screens (green or red tabs)
00273 void ST7735::initR(uint8_t options) {
00274   commonInit(Rcmd1);
00275   if(options == INITR_GREENTAB) {
00276     commandList(Rcmd2green);
00277     colstart = 2;
00278     rowstart = 1;
00279   } else if(options == INITR_144GREENTAB) {
00280     _height = ST7735_TFTHEIGHT_128;
00281     _width = ST7735_TFTWIDTH_128;
00282     commandList(Rcmd2green144);
00283     colstart = 2;
00284     rowstart = 3;
00285   } else if(options == INITR_MINI160x80) {
00286     _height = ST7735_TFTHEIGHT_160;
00287     _width = ST7735_TFTWIDTH_80;
00288     commandList(Rcmd2green160x80);
00289     colstart = 24;
00290     rowstart = 0;
00291   } else if(options == INITR_MINI160x80_RS) {
00292     _height = ST7735_TFTHEIGHT_160;
00293     _width = ST7735_TFTWIDTH_80;
00294     commandList(Rcmd2green160x80);
00295     writecommand(1 ? ST7735_INVON : ST7735_INVOFF);
00296     colstart = 26;
00297     rowstart = 1;
00298     _tft_type = 2;
00299   } else {
00300     // colstart, rowstart left at default '0' values
00301     commandList(Rcmd2red);
00302   }
00303   commandList(Rcmd3);
00304 
00305   // if black, change MADCTL color filter
00306   if (options == INITR_BLACKTAB) {
00307     writecommand(ST7735_MADCTL);
00308     writedata(0xC0);
00309   }
00310 
00311   tabcolor = options;
00312 }
00313 
00314 void ST7735::setAddrWindow(uint8_t x0, uint8_t y0, uint8_t x1,
00315                                     uint8_t y1)
00316 {
00317 
00318     writecommand(ST7735_CASET); // Column addr set
00319     writedata(0x00);
00320     writedata(x0+xstart);     // XSTART
00321     writedata(0x00);
00322     writedata(x1+xstart);     // XEND
00323 
00324     writecommand(ST7735_RASET); // Row addr set
00325     writedata(0x00);
00326     writedata(y0+ystart);     // YSTART
00327     writedata(0x00);
00328     writedata(y1+ystart);     // YEND
00329 
00330     writecommand(ST7735_RAMWR); // write to RAM
00331 }
00332 
00333 void ST7735::pushColor(uint16_t color)
00334 {
00335     _rs = 1;
00336     _cs = 0;
00337 
00338     lcdPort.write( color >> 8 );
00339     lcdPort.write( color );
00340     _cs = 1;
00341 }
00342 
00343 
00344 void ST7735::drawPixel(int16_t x, int16_t y, uint16_t color)
00345 {
00346 
00347     if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
00348 
00349     setAddrWindow(x,y,x+1,y+1);
00350 
00351     _rs = 1;
00352     _cs = 0;
00353 
00354     lcdPort.write( color >> 8 );
00355     lcdPort.write( color );
00356 
00357     _cs = 1;
00358 }
00359 
00360 
00361 void ST7735::drawFastVLine(int16_t x, int16_t y, int16_t h,
00362                                     uint16_t color)
00363 {
00364 
00365     // Rudimentary clipping
00366     if((x >= _width) || (y >= _height)) return;
00367     if((y+h-1) >= _height) h = _height-y;
00368     setAddrWindow(x, y, x, y+h-1);
00369 
00370     uint8_t hi = color >> 8, lo = color;
00371     _rs = 1;
00372     _cs = 0;
00373     while (h--) {
00374         lcdPort.write( hi );
00375         lcdPort.write( lo );
00376     }
00377     _cs = 1;
00378 }
00379 
00380 
00381 void ST7735::drawFastHLine(int16_t x, int16_t y, int16_t w,
00382                                     uint16_t color)
00383 {
00384 
00385     // Rudimentary clipping
00386     if((x >= _width) || (y >= _height)) return;
00387     if((x+w-1) >= _width)  w = _width-x;
00388     setAddrWindow(x, y, x+w-1, y);
00389 
00390     uint8_t hi = color >> 8, lo = color;
00391     _rs = 1;
00392     _cs = 0;
00393     while (w--) {
00394         lcdPort.write( hi );
00395         lcdPort.write( lo );
00396     }
00397     _cs = 1;
00398 }
00399 
00400 
00401 
00402 void ST7735::fillScreen(uint16_t color)
00403 {
00404     fillRect(-10, -10,  _width+20, _height+20, color);
00405 }
00406 
00407 
00408 // fill a rectangle
00409 void ST7735::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
00410                                uint16_t color)
00411 {
00412     
00413     // rudimentary clipping (drawChar w/big text requires this)
00414     if((x >= _width) || (y >= _height)) return;
00415     if((x + w - 1) >= _width)  w = _width  - x;
00416     if((y + h - 1) >= _height) h = _height - y;
00417 
00418     setAddrWindow(x, y, x+w-1, y+h-1);
00419 
00420     uint8_t hi = color >> 8, lo = color;
00421     _rs = 1;
00422     _cs = 0;
00423     for(y=h; y>0; y--) {
00424         for(x=w; x>0; x--) {
00425             lcdPort.write( hi );
00426             lcdPort.write( lo );
00427         }
00428     }
00429 
00430     _cs = 1;
00431 }
00432 
00433 
00434 // Pass 8-bit (each) R,G,B, get back 16-bit packed color
00435 uint16_t ST7735::Color565(uint8_t r, uint8_t g, uint8_t b)
00436 {
00437     return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
00438 }
00439 
00440 // Pass 8-bit (each) R,G,B, get back 16-bit packed color
00441 char* ST7735::Color565string(uint8_t r, uint8_t g, uint8_t b)
00442 {
00443     uint16_t color;
00444     char colorString[4];
00445     
00446     color = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
00447     
00448     sprintf(colorString, "%04x", color);
00449     
00450     //output1.printf("0x%04x : %s\n", color, colorString);
00451     
00452     return colorString;
00453     //return "test";
00454 }
00455 
00456 
00457 #define MADCTL_MY  0x80
00458 #define MADCTL_MX  0x40
00459 #define MADCTL_MV  0x20
00460 #define MADCTL_ML  0x10
00461 #define MADCTL_RGB 0x00
00462 #define MADCTL_BGR 0x08
00463 #define MADCTL_MH  0x04
00464 
00465 void ST7735::setRotation(uint8_t m) {
00466   _orientation = m;
00467   writecommand(ST7735_MADCTL);
00468   rotation = m % 4; // can't be higher than 3
00469   switch (rotation) {
00470    case 0:
00471      if ((tabcolor == INITR_BLACKTAB) || (tabcolor == INITR_MINI160x80)) {
00472        writedata(MADCTL_MX | MADCTL_MY | MADCTL_RGB);
00473      } else if (tabcolor == INITR_MINI160x80_RS) {
00474        writedata(MADCTL_MX | MADCTL_MY | MADCTL_BGR);
00475      } else {
00476        writedata(MADCTL_MX | MADCTL_MY | MADCTL_BGR);
00477      }
00478 
00479      if (tabcolor == INITR_144GREENTAB) {
00480        _height = ST7735_TFTHEIGHT_128;
00481        _width  = ST7735_TFTWIDTH_128;
00482      } else if ((tabcolor == INITR_MINI160x80) || (tabcolor == INITR_MINI160x80_RS))  {
00483        _height = ST7735_TFTHEIGHT_160;
00484        _width = ST7735_TFTWIDTH_80;
00485      } else {
00486        _height = ST7735_TFTHEIGHT_160;
00487        _width  = ST7735_TFTWIDTH_128;
00488      }
00489      xstart = colstart;
00490      ystart = rowstart;
00491      break;
00492    case 1:
00493      if ((tabcolor == INITR_BLACKTAB) || (tabcolor == INITR_MINI160x80)) {
00494        writedata(MADCTL_MY | MADCTL_MV | MADCTL_RGB);
00495      } else if (tabcolor == INITR_MINI160x80_RS) {
00496        writedata(MADCTL_MY | MADCTL_MV | MADCTL_BGR);
00497      } else {
00498        writedata(MADCTL_MY | MADCTL_MV | MADCTL_BGR);
00499      }
00500 
00501      if (tabcolor == INITR_144GREENTAB)  {
00502        _width = ST7735_TFTHEIGHT_128;
00503        _height = ST7735_TFTWIDTH_128;
00504      } else if ((tabcolor == INITR_MINI160x80) || (tabcolor == INITR_MINI160x80_RS))  {
00505        _width = ST7735_TFTHEIGHT_160;
00506        _height = ST7735_TFTWIDTH_80;
00507      } else {
00508        _width = ST7735_TFTHEIGHT_160;
00509        _height = ST7735_TFTWIDTH_128;
00510      }
00511      ystart = colstart;
00512      xstart = rowstart;
00513      break;
00514   case 2:
00515      if ((tabcolor == INITR_BLACKTAB) || (tabcolor == INITR_MINI160x80)) {
00516        writedata(MADCTL_RGB);
00517      } else if (tabcolor == INITR_MINI160x80_RS) {
00518        writedata(MADCTL_BGR);
00519      } else {
00520        writedata(MADCTL_BGR);
00521      }
00522 
00523      if (tabcolor == INITR_144GREENTAB) {
00524        _height = ST7735_TFTHEIGHT_128;
00525        _width  = ST7735_TFTWIDTH_128;
00526      } else if ((tabcolor == INITR_MINI160x80) || (tabcolor == INITR_MINI160x80_RS))  {
00527        _height = ST7735_TFTHEIGHT_160;
00528        _width = ST7735_TFTWIDTH_80;
00529      } else {
00530        _height = ST7735_TFTHEIGHT_160;
00531        _width  = ST7735_TFTWIDTH_128;
00532      }
00533      xstart = colstart;
00534      ystart = rowstart;
00535      break;
00536    case 3:
00537      if ((tabcolor == INITR_BLACKTAB) || (tabcolor == INITR_MINI160x80)) {
00538        writedata(MADCTL_MX | MADCTL_MV | MADCTL_RGB);
00539      } else if (tabcolor == INITR_MINI160x80_RS) {
00540        writedata(MADCTL_MX | MADCTL_MV | MADCTL_BGR);
00541      } else {
00542        writedata(MADCTL_MX | MADCTL_MV | MADCTL_BGR);
00543      }
00544 
00545      if (tabcolor == INITR_144GREENTAB)  {
00546        _width = ST7735_TFTHEIGHT_128;
00547        _height = ST7735_TFTWIDTH_128;
00548      } else if ((tabcolor == INITR_MINI160x80) || (tabcolor == INITR_MINI160x80_RS))  {
00549        _width = ST7735_TFTHEIGHT_160;
00550        _height = ST7735_TFTWIDTH_80;
00551      } else {
00552        _width = ST7735_TFTHEIGHT_160;
00553        _height = ST7735_TFTWIDTH_128;
00554      }
00555      ystart = colstart;
00556      xstart = rowstart;
00557      break;
00558   }
00559 }
00560 
00561 void ST7735::invertDisplay(boolean i)
00562 {
00563     writecommand(i ? ST7735_INVON : ST7735_INVOFF);
00564 }
00565 
00566 void ST7735::DrawBMP(int offsetx, int offsety, FILE *Image)
00567 {  
00568     uint32_t index = 0, width = 0, height = 0;
00569     int i=0, x, y, byteCour;
00570     
00571     int fpOffset = ftell(Image);
00572     //output1.printf("current cursor : %02x\n", ftell(Image));
00573     //output1.printf("first bytes bmp : %02x\n", fgetc(Image));
00574     
00575     /* Get bitmap data address offset */
00576     fseek(Image, 10+fpOffset , SEEK_SET );
00577     index = fgetc(Image);
00578     //output1.printf("index : 0x%02x ; ", index);
00579     
00580     /* Read bitmap width */
00581     fseek(Image, 18+fpOffset , SEEK_SET );
00582     width = fgetc(Image);
00583     width += fgetc(Image)<<8;
00584     width += fgetc(Image)<<16;
00585     width += fgetc(Image)<<24;
00586     //output1.printf("width : %d ; ", width);
00587     
00588     /* Read bitmap height */
00589     fseek(Image, 22+fpOffset , SEEK_SET );
00590     height = fgetc(Image);
00591     height += fgetc(Image)<<8;
00592     height += fgetc(Image)<<16;
00593     height += fgetc(Image)<<24;
00594     //output1.printf("height : %d\n", height);
00595     
00596     fseek(Image, index+fpOffset , SEEK_SET );
00597     
00598     byteCour = fgetc(Image);
00599     byteCour += fgetc(Image)<<8;
00600 
00601     for (y = height+offsety; offsety < y; y--) {
00602         setAddrWindow(offsetx, y, offsetx+width-1, y);
00603         _rs = 1;
00604         _cs = 0;
00605                 
00606         for (x = 0; x < width; x++) {         
00607             if(x == width-1) fseek(Image, width%2, SEEK_CUR);
00608                     
00609             if(x <= width && y >= 0) {
00610                 lcdPort.write(byteCour>>8);    // one line
00611                 lcdPort.write(byteCour);
00612             }
00613             _cs = 1;
00614             byteCour = fgetc(Image);
00615             byteCour += fgetc(Image)<<8;
00616             _cs = 0;
00617         }
00618     }    
00619     _cs = 1;
00620 }
00621 
00622 // use imageconverter565.exe to generate bitmap array and put it in bitmap.c
00623 void ST7735::DrawRam(unsigned int x, unsigned int y, unsigned int w, unsigned int h, int *Image) {
00624     unsigned int    i,j;
00625     setAddrWindow(x, y, x+w-1, y+h);
00626     _rs = 1;
00627     _cs = 0;
00628     for (j = 0; j < h; j++) {        //Lines
00629         for (i = 0; i < w; i++) {     // copy pixel data to TFT
00630             lcdPort.write(*Image>>8);    // one line
00631             lcdPort.write(*Image);  
00632             *Image++;
00633         }
00634     }
00635     _cs = 1;
00636 }
00637 
00638 void ST7735::DrawGIF(int offsetx, int offsety, FILE *Image) {
00639     
00640     uint32_t width = 0, height = 0;
00641     uint16_t code, preCode, clearCode, endCode, sizePalette;
00642     uint8_t r, v, b, pxl, pxls[256];
00643     int i, j;
00644     int fpOffset = ftell(Image);
00645     
00646     // palette
00647     uint16_t table[750][17];
00648     for(int i = 0; i < 750; i++)
00649         for(int j = 0; j < 17; j++)
00650             table[i][j] = NULL;
00651     
00652     // Read bitmap width
00653     fseek(Image, 6+fpOffset , SEEK_SET );
00654     width = fgetc(Image);
00655     width += fgetc(Image);
00656     //output1.printf("width : %d ; ", width);
00657     
00658     // Read bitmap height
00659     fseek(Image, 8+fpOffset , SEEK_SET );
00660     height = fgetc(Image);
00661     height += fgetc(Image);
00662     //output1.printf("height : %d\n", height);
00663     
00664     // Get size of palette
00665     fseek(Image, 10+fpOffset , SEEK_SET );
00666     sizePalette = fgetc(Image)<<5;
00667     sizePalette = ((uint8_t) sizePalette)>>5;
00668     sizePalette = pow(2, sizePalette+1.0);
00669     
00670     // Get palette
00671     uint16_t palette[sizePalette];
00672     fseek(Image, 13+fpOffset , SEEK_SET );
00673     for(i=0; i < sizePalette; i++) {
00674         r = fgetc(Image);
00675         v = fgetc(Image);
00676         b = fgetc(Image);
00677         
00678         // palette simple
00679         palette[i] = Color565(r, v, b);
00680         table[i][0] = 1;table[i][1] = i;
00681     }
00682     
00683     preCode = i;
00684     table[i][0] = i;
00685     clearCode = i;
00686     table[i+1][0] = i+1;
00687     endCode = i+1;
00688     
00689     // Find Image separator
00690     while(1) {
00691         pxl = fgetc(Image);
00692         if(0x2C == pxl) break;
00693     }
00694     
00695     // Get minimal size of code
00696     fseek(Image, 9 , SEEK_CUR );
00697     uint8_t sizeCode = fgetc(Image);sizeCode++;
00698     
00699     // Get size of block
00700     uint8_t sizeBlock = fgetc(Image);
00701     output1.printf("taille du block : %d\n", sizeBlock);
00702     
00703     setAddrWindow(offsetx, offsety, offsetx+width-1, offsety+height);
00704     _rs = 1;
00705     _cs = 0;
00706     
00707     // image data
00708     uint16_t imgByte = fgetc(Image);
00709     int sizeImgByte = 8;
00710     int16_t index = sizePalette;
00711     for(i=0; i < sizeBlock; ) {
00712         
00713         // ajout d'un octet pour le calcul du prochain code
00714         while(sizeImgByte < sizeCode) {
00715             pxl = fgetc(Image);
00716             i++;
00717             if(sizeBlock == 0xff && i == sizeBlock) {
00718                 i = 0;
00719                 sizeBlock = pxl;
00720                 pxl = fgetc(Image);
00721             }
00722             imgByte = (pxl<<(sizeImgByte)) + bitExtracted(imgByte, sizeImgByte, 1);
00723             sizeImgByte += 8;
00724         }
00725         
00726         // extraction du code
00727         code = bitExtracted(imgByte, sizeCode, 1);
00728         
00729         //output1.printf(">%03x; %03x; %03x; ", code, preCode, index);
00730         
00731         //////////////////////
00732         // traitement image //
00733         //////////////////////
00734         
00735         if(code == clearCode) index = sizePalette;
00736         else if(code == endCode) break;
00737         else {
00738             
00739             // sauf si premier code : chargement du "pixel string" du precode
00740             if(preCode != clearCode){
00741                 for(j=0; j < table[preCode][0];j++)
00742                     pxls[j] = table[preCode][j+1];
00743             }
00744             
00745             // si code connu :
00746             if(code < index) {
00747                 
00748                 for(int k=1; k <= table[code][0];k++) {
00749                     if(k==1) pxls[j] = table[code][k];
00750 
00751                     lcdPort.write((uint8_t) (palette[ table[code][k] ]>>8));
00752                     lcdPort.write((uint8_t) palette[ table[code][k] ]);
00753                 }
00754 
00755                 for(int k=1; k <= j+1; k++)
00756                     table[index][k] = pxls[k-1];
00757 
00758                 table[index][0] = j+1;
00759                 
00760                 
00761             } else {
00762                 
00763                 // add new stream pixel in palette and display
00764                 pxl = pxls[0];
00765                 pxls[j] = pxl;
00766                 for(int k=1; k <= j+1; k++) {
00767                     table[index][k] = pxls[k-1];
00768 
00769                     lcdPort.write((uint8_t) (palette[ pxls[k-1] ]>>8));
00770                     lcdPort.write((uint8_t) palette[ pxls[k-1] ]);
00771                     
00772                 }
00773                 table[index][0] = j+1;
00774             }
00775             
00776             // clear buffer string
00777             for(int k=0; k < 256; k++) pxls[k] = 0;
00778         }
00779         
00780         preCode = code;
00781         
00782         // to compute next code
00783         sizeImgByte -= sizeCode;
00784         imgByte = bitExtracted(imgByte, sizeImgByte, sizeCode+1);
00785         
00786         if( index == (pow(2, sizeCode*1.0)-1)) sizeCode++;
00787         
00788         index++;
00789     }
00790     
00791     _cs = 1;
00792  
00793 }
00794 
00795 void ST7735::DrawANI(int offsetx, int offsety, FILE *Anim, int frame) {
00796     
00797     int i;
00798     char buf[32];
00799     char sizeStr[12];
00800     char *valExit = "error";
00801     char namefile[32];
00802     int size, offset = 0;
00803     
00804     sprintf(namefile, "%d.bmp", frame); 
00805     
00806     while(!feof(Anim)) {
00807         for(i=0; i <= strlen(namefile); i++) buf[i] = fgetc(Anim);
00808         
00809         if(!strcmp(buf, namefile)) {
00810             valExit = "";
00811             break;
00812         }
00813         
00814         fseek(Anim , 124+offset , SEEK_SET);
00815         for(i=0; i < 12; i++) sizeStr[i] = fgetc(Anim);
00816         //printf("size string: %s; octal: %d; dec.: %x\n", sizeStr, atoi(sizeStr), oct2dec(atoi(sizeStr)) );
00817         
00818         size = oct2dec(atoi(sizeStr));
00819         if(offset % 512 != 0) offset += (size/512 + 2)*512;
00820         else offset += (size/512 + 1)*512;
00821         
00822         fseek(Anim , offset , SEEK_SET);  
00823     }
00824     
00825     if(valExit == "error") {
00826         printf("file \"%s\" not find in tar\n", namefile); 
00827         //return NULL;
00828     } else {
00829         fseek(Anim, offset+512 , SEEK_SET);
00830         
00831         DrawBMP(offsetx, offsety, Anim);
00832         
00833         //return 1;
00834     }
00835     
00836     
00837 }
00838 
00839 void ST7735::scrollBmp(uint8_t top_fix_height, uint8_t bottom_fix_height, int _scroll_direction, int *bitmap) {
00840     unsigned int i, startOffset, endOffset;// line = 0; 
00841     float a, b;
00842     
00843     a = 7.7142*pow( 162.0-(top_fix_height+bottom_fix_height), -2.0 );
00844     b = 8.0717*pow( 162.0-(top_fix_height+bottom_fix_height), -1.0 );
00845      
00846     if(!_orientation) _scroll_direction = !_scroll_direction;
00847     
00848     if((_scroll_direction && _orientation == 2) || (!_scroll_direction && !_orientation)) {
00849         for (i = 0; i < 3248; i++) *bitmap++;
00850     }
00851     
00852     if((!_scroll_direction && _orientation == 2) || (_scroll_direction && !_orientation)) {
00853         startOffset = top_fix_height;
00854         endOffset = bottom_fix_height+1;
00855     } else {
00856         startOffset = bottom_fix_height;
00857         endOffset = top_fix_height+1;
00858     }
00859     
00860     if((_scroll_direction && _orientation == 2) || (!_scroll_direction && !_orientation)) setScrollDefinition(bottom_fix_height, top_fix_height+1, _scroll_direction);
00861     else setScrollDefinition(top_fix_height+1, bottom_fix_height, _scroll_direction);
00862     
00863     for( int scroll = 1+startOffset; scroll <= 162-endOffset ; scroll++){
00864       
00865         VerticalScroll(scroll);
00866         
00867         if(scroll >=(53) && scroll <=109) {
00868             if(_orientation == 0){
00869                 if(_scroll_direction) {
00870                     drawFastHLine(0, 162-(scroll)-2, 80, ST7735_BLACK);
00871                     
00872                     for (i = 0; i < 57; i++) {
00873                         drawPixel(57+11-i, 162-(scroll)-2, *bitmap);
00874                         *bitmap++;
00875                     }
00876                 } else {
00877                     drawFastHLine(0, scroll-2, 80, ST7735_BLACK);
00878                 
00879                     for (i = 0; i < 57; i++) { 
00880                         drawPixel(12+i, scroll-2, *bitmap);
00881                         *bitmap--;
00882                     }
00883                 }
00884             } else if(_orientation == 2) {
00885                 if(_scroll_direction) {
00886                     drawFastHLine(0, 162-scroll-1, 80, ST7735_BLACK);
00887                     
00888                     for (i = 0; i < 57; i++) {
00889                         drawPixel(57+10-i,162-scroll-1, *bitmap);
00890                         *bitmap--;
00891                     }
00892                 } else {
00893                     drawFastHLine(0, scroll-1, 80, ST7735_BLACK);
00894                 
00895                     for (i = 0; i < 57; i++) {   
00896                         drawPixel(11+i,scroll-1, *bitmap);
00897                         *bitmap++;
00898                     }
00899                 }
00900             }
00901         }
00902         
00903         float tempo = (a*scroll*scroll)-b*scroll+2.9408;
00904         wait_ms(tempo);
00905         //wait(0.1);
00906     }
00907     if(!_orientation) setRotation(0);
00908     VerticalScroll(0);
00909 }
00910 
00911 int ST7735::oct2dec(int n) /* Function to convert octal to decimal */
00912 {
00913     int decimal=0, i=0, rem;
00914     while (n!=0)
00915     {
00916         rem = n%10;
00917         n/=10;
00918         decimal += rem*pow(8.0,i);
00919         ++i;
00920     }
00921     return decimal;
00922 }
00923 
00924 int ST7735::bitExtracted(int number, int k, int p) 
00925 { 
00926     return (((1 << k) - 1) & (number >> (p - 1))); 
00927 } 
00928 
00929 void ST7735::makeTable(void) {
00930     remove("/sd/table.csv");
00931     remove("/sd/pointers.csv");
00932     FILE *table = fopen("/sd/table.csv", "w");
00933     FILE *pointers = fopen("/sd/pointers.csv", "w");
00934     fclose(table);
00935     fclose(pointers);
00936 } 
00937 
00938 uint16_t ST7735::readTable(unsigned int y, unsigned int x) {
00939     
00940     FILE *table = fopen("/sd/table.csv", "r");
00941     FILE *pointers = fopen("/sd/pointers.csv", "r");
00942     char out[3];
00943     char ptr[17];
00944     
00945     fseek(pointers , y*17 , SEEK_SET);
00946     //output1.printf("%d: ", y);
00947     for(int i=0; i < 17; i++) {
00948         ptr[i] = fgetc(pointers);
00949         //output1.printf("%c", ptr[i]);
00950     }   
00951     //output1.printf("\n%s>>%d\n", ptr, atoi(ptr));
00952     
00953     // utiliser pointers
00954     //for(int i=0; i < y;)
00955         //if(fgetc(table) == 0x0A) i++;
00956     fseek(table , atoi(ptr) , SEEK_SET);
00957         
00958     for(int i=0; i < x;)
00959         if(fgetc(table) == 0x3B) i++;
00960         
00961     out[0] = fgetc(table);
00962     out[1] = fgetc(table);
00963     out[2] = fgetc(table);
00964     
00965     //output1.printf("%s>>%x ", out, atoi(out));
00966     
00967     fclose(table);
00968     fclose(pointers);
00969     return atoi(out);
00970 }
00971 
00972 void ST7735::addrowTable(uint16_t *row) {
00973     
00974     int size;
00975     
00976     FILE *table = fopen("/sd/table.csv", "r"); 
00977     fseek(table , 0 , SEEK_END);
00978     size = ftell(table);
00979     fclose(table);
00980     
00981     table = fopen("/sd/table.csv", "a");
00982     for(int i = 0; i< row[0]+1; i++) 
00983         fprintf(table, "%03d;", row[i]);
00984     fprintf(table, "\n");
00985     
00986     FILE *pointers = fopen("/sd/pointers.csv", "a");
00987     fprintf(pointers, "%16d\n", size);
00988 
00989     fclose(table);
00990     fclose(pointers);
00991 } 
00992 
00993 void ST7735::init_star(STAR* star, int i)
00994     {
00995       /* randomly init stars, generate them around the center of the screen */
00996       
00997       star->xpos =  -10.0 + (20.0 * (rand()/(RAND_MAX+1.0)));
00998       star->ypos =  -10.0 + (20.0 * (rand()/(RAND_MAX+1.0)));
00999       
01000       star->xpos *= 3072.0; /*change viewpoint */
01001       star->ypos *= 3072.0;
01002     
01003       star->zpos =  i;
01004       star->speed =  2 + (int)(2.0 * (rand()/(RAND_MAX+1.0)));
01005     
01006       star->color = i*ST7735_WHITE >> 2; /*the closer to the viewer the brighter*/
01007     }
01008 
01009 void ST7735::DrawStarfield(int centerx, int centery, int acc, int color, int NbrsStars, int duration)
01010 {
01011     int i, j=0, tempx, tempy;  
01012     STAR stars[NbrsStars];
01013     Timer timerStars;
01014     
01015     timerStars.start();
01016     while(timerStars.read() < duration) {
01017         
01018       j++;
01019       
01020       // move and draw stars 
01021        
01022       for (i = 0; i < NbrsStars; i++) {
01023           tempx = (stars[i].xpos / stars[i].zpos) + centerx;
01024           tempy = (stars[i].ypos / stars[i].zpos) + centery;
01025           drawPixel(tempx,tempy, ST7735_BLACK);
01026           
01027             
01028           stars[i].zpos -= stars[i].speed*acc;
01029           
01030           if (stars[i].zpos <= 0) {
01031               init_star(stars + i, i + 1);
01032           }
01033     
01034           //compute 3D position
01035           tempx = (stars[i].xpos / stars[i].zpos) + centerx;
01036           tempy = (stars[i].ypos / stars[i].zpos) + centery;
01037     
01038           if (tempx < 0 || tempx > _width - 1 || tempy < 0 || tempy > _height - 1) { //check if a star leaves the screen
01039         
01040               init_star(stars + i, i + 1);
01041               continue;
01042           }
01043       
01044             if(color) drawPixel(tempx,tempy,color);
01045             else drawPixel(tempx,tempy,stars[i].color);
01046         
01047       }
01048     }
01049     
01050     timerStars.stop();
01051 }
01052 
01053 void ST7735::setScrollDefinition(uint8_t top_fix_height, uint8_t bottom_fix_height, int _scroll_direction){
01054   uint8_t scroll_height;
01055   scroll_height = _height - top_fix_height - bottom_fix_height;
01056   writecommand(ST7735_VSCRDEF);
01057   writedata(0x00);
01058   writedata(top_fix_height);
01059   writedata(0x00);
01060   writedata(scroll_height);
01061   writedata(0x00);
01062   writedata(bottom_fix_height);
01063   writecommand(ST7735_MADCTL);
01064   if(_scroll_direction){
01065     if(_tft_type == 0){
01066       writedata(0xD8);
01067     }
01068     if(_tft_type == 1){
01069       writedata(0xD0);
01070     }
01071     if(_tft_type == 2){
01072       writedata(0x18);
01073     }
01074   }
01075   else{
01076     if(_tft_type == 0){
01077       writedata(0xC8);
01078     }
01079     if(_tft_type == 1){
01080       writedata(0xC0);
01081     }
01082     if(_tft_type == 2){
01083       writedata(0x08);
01084     }
01085   }
01086 }
01087 void ST7735::VerticalScroll(uint8_t _vsp) {
01088   writecommand(ST7735_VSCRSADD);
01089   writedata(0x00);
01090   writedata(_vsp);
01091 }
01092 
01093 //void ST7735::read_area(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned char *buffer) {
01094 void ST7735::read_area(unsigned int x, unsigned int y, unsigned int w, unsigned int h) {
01095     // BEWARE !
01096     // DOES NOT WORK CORRECTLY YET !!!
01097     int val;
01098     setAddrWindow2(x,y,w,h);
01099     writecommand(ST7735_RAMRD);  // write to RAM
01100     _cs = 0;
01101     _rs = 1;
01102     lcdPort.write(0);                                /* Dummy read 1                 */
01103     
01104     val   = lcdPort.write(0);                        /* Read D8..D15                 */
01105     val <<= 8;
01106     val  |= lcdPort.write(0);                        /* Read D0..D7                  */
01107     _cs = 1;                  
01108             output1.printf("%d ", val);
01109         
01110     
01111     
01112 }
01113 
01114 
01115 void ST7735::setAddrWindow2(uint8_t x0, uint8_t y0, uint8_t x1,
01116                                     uint8_t y1)
01117 {
01118 
01119     writecommand(ST7735_CASET); // Column addr set
01120     writedata(0x00);
01121     writedata(x0+xstart);     // XSTART
01122     writedata(0x00);
01123     writedata(x1+xstart);     // XEND
01124 
01125     writecommand(ST7735_RASET); // Row addr set
01126     writedata(0x00);
01127     writedata(y0+ystart);     // YSTART
01128     writedata(0x00);
01129     writedata(y1+ystart);     // YEND
01130 
01131     //writecommand(ST7735_RAMWR); // write to RAM
01132 }
01133 
01134