This is a mbed library for a 1.8 inch 128x160 pixel SPI TFT display

Dependents:   ST7735_Pong ST7735_TFT SPI18TFT_FRDM-KL25Z SPI18TFT ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ST7735_TFT.cpp Source File

ST7735_TFT.cpp

00001  /* mbed library for 128*160 pixel display TFT based on ST7735 LCD Controller
00002  * ST7735 specific routines (initialization, window addressing, pixel output) 
00003  * Copyright (c) 2011 Jonne Valola
00004  *
00005  * WARNING !! WORK IN PROGRESS !!!
00006  *
00007  * Graphics routines and SPI routines derived work used with permission from:
00008  * mbed library for 240*320 pixel display TFT based on HX8347D LCD Controller
00009  * Copyright (c) 2011 Peter Drescher - DC2PD
00010  *
00011  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00012  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00013  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00014  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00015  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00017  * THE SOFTWARE.
00018  */
00019 
00020 
00021 #include "ST7735_TFT.h"
00022 #include "mbed.h"
00023 
00024 #define BPP         16                  // Bits per pixel                
00025 
00026 ST7735_TFT::ST7735_TFT(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName rs, PinName reset, const char *name)
00027         : _spi(mosi, miso, sclk), _cs(cs), _rs(rs), _reset(reset),GraphicsDisplay(name) {
00028     tft_reset();
00029     orientation = 2;
00030     char_x = 0;
00031 }
00032 
00033 
00034 int ST7735_TFT::width() {
00035     if (orientation == 0 || orientation == 2) return 128;
00036     else return 160; 
00037 }
00038 
00039 
00040 int ST7735_TFT::height() {
00041     if (orientation == 0 || orientation == 2) return 160;
00042     else return 128; 
00043 }
00044 
00045 
00046 void ST7735_TFT::set_orientation(unsigned int o) {
00047     orientation = o;
00048     switch (orientation) {
00049         case 0:
00050             wr_reg(ST7735_MADCTL, 0x0008);
00051             break;
00052         case 1:
00053             wr_reg(ST7735_MADCTL, 0x0068);
00054             break;
00055         case 2:
00056             wr_reg(ST7735_MADCTL, 0x00C8);
00057             break;
00058         case 3:
00059             wr_reg(ST7735_MADCTL, 0x00A8);
00060             break;
00061     }
00062 }
00063 
00064 
00065 
00066 void ST7735_TFT::wr_cmd(int cmd) {
00067     _rs = 0; // rs low, cs low for transmitting command
00068     _cs = 0;
00069     _spi.write(cmd);
00070     _cs = 1;
00071 }
00072 
00073 
00074 
00075 void ST7735_TFT::wr_dat(int dat) {
00076     _rs = 1; // rs high, cs low for transmitting data
00077     _cs = 0;                         
00078     _spi.write(dat);                                                           
00079     _cs = 1;
00080 }
00081 
00082 
00083 
00084 void ST7735_TFT::wr_dat_start(void) {
00085     _rs = 1; //  rs high, cs low for transmitting data
00086     _cs = 0;
00087 }
00088 
00089 
00090 
00091 void ST7735_TFT::wr_dat_stop (void) {
00092     _cs = 1;
00093 }
00094 
00095 
00096 
00097 void ST7735_TFT::wr_dat_only (unsigned short dat) {  
00098     _spi.write(dat);                                            
00099 }
00100 
00101 
00102 unsigned short ST7735_TFT::rd_dat (void) {
00103     unsigned short val = 0;
00104     _cs = 0;
00105     _spi.write(0);                                /* Dummy read 1                 */
00106     val   = _spi.write(0);                        /* Read D8..D15                 */
00107     val <<= 8;
00108     val  |= _spi.write(0);                        /* Read D0..D7                  */
00109     _cs = 1;
00110     return (val);
00111 }
00112 
00113 void ST7735_TFT::wr_reg (unsigned char reg, unsigned short val) {
00114 
00115     wr_cmd(reg);
00116     wr_dat(val);
00117 }
00118 
00119 
00120 unsigned short ST7735_TFT::rd_reg (unsigned char reg) {
00121 
00122     wr_cmd(reg);
00123     return(rd_dat());
00124 }
00125 
00126 void ST7735_TFT::read_area(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *buffer) {
00127     // BEWARE !
00128     // DOES NOT WORK CORRECTLY YET !!!
00129     int val;
00130     window(x,y,w,h);
00131     wr_cmd(ST7735_RAMRD);  // write to RAM
00132     _cs = 0;
00133     _rs = 1;
00134     _spi.write(0);                                /* Dummy read 1                 */
00135     
00136     val   = _spi.write(0);                        /* Read D8..D15                 */
00137     val <<= 8;
00138     val  |= _spi.write(0);                        /* Read D0..D7                  */
00139     _cs = 1;
00140 }
00141 
00142 int ST7735_TFT::getpixel(unsigned int x, unsigned int y) {
00143     // BEWARE !
00144     // DOES NOT WORK CORRECTLY YET !!!
00145     int val;
00146     _spi.format(8,3);
00147     wr_cmd(ST7735_CASET);  // column addr set
00148     wr_dat(0x00);
00149     wr_dat(x+2);   // XSTART 
00150     wr_dat(0x00);
00151     wr_dat(x+2+2);   // XEND
00152 
00153     wr_cmd(ST7735_RASET);  // row addr set
00154     wr_dat(0x00);
00155     wr_dat(y+1);    // YSTART
00156     wr_dat(0x00);
00157     wr_dat(y+1+1);    // YEND
00158     
00159     _rs = 0; // rs low, cs low for transmitting command
00160     _cs = 0;
00161     _spi.write(0x2E);
00162     _rs = 1;
00163     _spi.write(0x00);                                /* Dummy read 1                 */
00164     
00165     val   = _spi.write(0x00);                        /* Read D8..D15                 */
00166     val <<= 8;
00167     val  |= _spi.write(0x00);                        /* Read D0..D7                  */
00168 
00169     _cs = 1;
00170     return val;
00171 }
00172 
00173 
00174 void ST7735_TFT::tft_reset() {
00175     static unsigned short driverCode;
00176     
00177     // init SPI
00178     _spi.format(8,3);                 // 8 bit spi mode 3
00179     _spi.frequency(16000000);         // 16Mhz SPI clock ... 15Mhz is maximum for display, but it seems to work
00180     
00181     // reset exactly like in Arduino version
00182     _cs = 0;
00183     _reset = 1;                       // reset
00184     wait_ms(500);
00185     _reset = 0;                       // reset
00186     wait_ms(500);
00187     _reset = 1;                       // reset
00188     wait_ms(500);
00189     
00190     /* Start Initial Sequence ----------------------------------------------------*/
00191     wr_cmd(ST7735_SWRESET);                         /* SW Reset                       */
00192     wait_ms(150);
00193     wr_cmd(ST7735_SLPOUT);                         /* Out of sleepmode               */
00194     wait_ms(500);
00195     
00196     wr_cmd(ST7735_FRMCTR1);                         /* Frame rate in normal mode            */
00197     wr_dat(0x01);                              
00198     wr_dat(0x2C);
00199     wr_dat(0x2D);
00200     
00201     wr_cmd(ST7735_FRMCTR2);                         /* Frame rate in idle mode            */
00202     wr_dat(0x01);                              
00203     wr_dat(0x2C);
00204     wr_dat(0x2D);
00205 
00206     wr_cmd(ST7735_FRMCTR3);                         /* Frame rate in partial mode            */
00207     wr_dat(0x01);                              
00208     wr_dat(0x2C);
00209     wr_dat(0x2D);
00210     wr_dat(0x01);   // inversion mode settings                              
00211     wr_dat(0x2C);
00212     wr_dat(0x2D);
00213     
00214     wr_cmd(ST7735_INVCTR);   // Inverted mode off
00215     wr_dat(0x07);   
00216 
00217     wr_cmd(ST7735_PWCTR1);   // POWER CONTROL 1   
00218     wr_dat(0xA2); 
00219     wr_dat(0x02);           // -4.6V
00220     wr_dat(0x84);           // AUTO mode 
00221     
00222     wr_cmd(ST7735_PWCTR2);   // POWER CONTROL 2   
00223     wr_dat(0xC5);            // VGH25 = 2.4C VGSEL =-10 VGH = 3*AVDD
00224     
00225     wr_cmd(ST7735_PWCTR3);  // POWER CONTROL 3   
00226     wr_dat(0x0A);           // Opamp current small
00227     wr_dat(0x00);           // Boost freq
00228 
00229     wr_cmd(ST7735_PWCTR4);   // POWER CONTROL 4   
00230     wr_dat(0x8A);            // BCLK/2, Opamp current small / medium low 
00231     wr_dat(0x2A);            // 
00232   
00233     wr_cmd(ST7735_PWCTR5);   // POWER CONTROL 5   
00234     wr_dat(0x8A);            // BCLK/2, Opamp current small / medium low 
00235     wr_dat(0xEE);            //
00236     
00237     wr_cmd(ST7735_VMCTR1);   // POWER CONTROL 6   
00238     wr_dat(0x0E);            // 
00239 
00240     wr_cmd(ST7735_INVOFF);   // INVOFF
00241     
00242     wr_cmd(ST7735_MADCTL);   // ORIENTATION   
00243     wr_dat(0xC8);   // 
00244     
00245     wr_cmd(ST7735_COLMOD);   // COLOR MODE   
00246     wr_dat(0x05);            //      
00247     
00248     wr_cmd(ST7735_CASET);   // COLUMN ADDR SET   
00249     wr_dat(0x00);   //
00250     wr_dat(0x00);   // xstart = 0
00251     wr_dat(0x00);   //
00252     wr_dat(0x7F);   // xend = 127
00253     
00254     wr_cmd(ST7735_RASET);   // ROW ADDR SET   
00255     wr_dat(0x00);   //
00256     wr_dat(0x00);   // ystart = 0
00257     wr_dat(0x00);   //
00258     wr_dat(0x9F);   // yend = 159            
00259     
00260     /* Gamma settings  -----------------------------------------------------------*/
00261 
00262   wr_cmd(0xE0); // GMCTRP1
00263   wr_dat(0x02);
00264   wr_dat(0x1c);
00265   wr_dat(0x07);
00266   wr_dat(0x12);
00267   wr_dat(0x37);
00268   wr_dat(0x32);
00269   wr_dat(0x29);
00270   wr_dat(0x2d);
00271   wr_dat(0x29);
00272   wr_dat(0x25);
00273   wr_dat(0x2B);
00274   wr_dat(0x39);
00275   wr_dat(0x00);
00276   wr_dat(0x01);
00277   wr_dat(0x03);
00278   wr_dat(0x10);
00279   wr_cmd(0xE1); // GMCTRN1
00280   wr_dat(0x03); 
00281   wr_dat(0x1d); 
00282   wr_dat(0x07); 
00283   wr_dat(0x06); 
00284   wr_dat(0x2E); 
00285   wr_dat(0x2C); 
00286   wr_dat(0x29); 
00287   wr_dat(0x2D); 
00288   wr_dat(0x2E); 
00289   wr_dat(0x2E); 
00290   wr_dat(0x37); 
00291   wr_dat(0x3F); 
00292   wr_dat(0x00); 
00293   wr_dat(0x00); 
00294   wr_dat(0x02); 
00295   wr_dat(0x10); 
00296   
00297   wr_cmd(ST7735_DISPON); // display ON
00298   wait_ms(100);
00299 
00300   wr_cmd(ST7735_NORON);  // normal display on
00301   wait_ms(10);
00302   
00303   switch (orientation) {
00304         case 0:
00305             wr_reg(0xC8, 0x0008);
00306             break;
00307         case 1:
00308             wr_reg(0xC8, 0x0068);
00309             break;
00310         case 2:
00311             wr_reg(0xC8, 0x00C8);
00312             break;
00313         case 3:
00314             wr_reg(0xC8, 0x00A8);
00315             break;
00316     }
00317     WindowMax ();
00318 }
00319 
00320 
00321 void ST7735_TFT::pixel(int x, int y, int color) {
00322   if ((x >= width()) || (y >= height())) return;
00323 
00324   window(x,y,x+1,y+1);
00325   
00326   // setup for data
00327    _rs = 1; 
00328    _cs = 0;
00329   _spi.format(16,3);
00330   _spi.write(color);     
00331   _cs = 1;
00332   _spi.format(8,3);
00333 }
00334 
00335 void ST7735_TFT::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h) {
00336   wr_cmd(ST7735_CASET);  // column addr set
00337   wr_dat(0x00);
00338   wr_dat(x+2);   // XSTART 
00339   wr_dat(0x00);
00340   wr_dat(x+w+1);   // XEND
00341 
00342   wr_cmd(ST7735_RASET);  // row addr set
00343   wr_dat(0x00);
00344   wr_dat(y+1);    // YSTART
00345   wr_dat(0x00);
00346   wr_dat(y+h+1);    // YEND
00347 
00348   wr_cmd(ST7735_RAMWR);  // write to RAM
00349 }
00350 
00351 
00352 void ST7735_TFT::WindowMax (void) {
00353     window (0, 0, width(),  height());
00354 }
00355 
00356 
00357 void ST7735_TFT::cls (void) {
00358     unsigned int i;
00359     WindowMax();
00360     wr_dat_start();
00361     _spi.format(16,3);
00362     for (i = 0; i < ( (width()+1) * (height()+3)); i++) {
00363         _spi.write(_background);    
00364     }
00365     _spi.format(8,3);
00366     wr_dat_stop();
00367 }
00368 
00369 
00370 void ST7735_TFT::circle(int x0, int y0, int r, int color) {
00371 
00372     int draw_x0, draw_y0;
00373     int draw_x1, draw_y1;
00374     int draw_x2, draw_y2;
00375     int draw_x3, draw_y3;
00376     int draw_x4, draw_y4;
00377     int draw_x5, draw_y5;
00378     int draw_x6, draw_y6;
00379     int draw_x7, draw_y7;
00380     int xx, yy;
00381     int di;
00382     WindowMax();
00383     if (r == 0) {       /* no radius */
00384         return;
00385     }
00386 
00387     draw_x0 = draw_x1 = x0;
00388     draw_y0 = draw_y1 = y0 + r;
00389     if (draw_y0 < height()) {
00390         pixel(draw_x0, draw_y0, color);     /* 90 degree */
00391     }
00392 
00393     draw_x2 = draw_x3 = x0;
00394     draw_y2 = draw_y3 = y0 - r;
00395     if (draw_y2 >= 0) {
00396         pixel(draw_x2, draw_y2, color);    /* 270 degree */
00397     }
00398 
00399     draw_x4 = draw_x6 = x0 + r;
00400     draw_y4 = draw_y6 = y0;
00401     if (draw_x4 < width()) {
00402         pixel(draw_x4, draw_y4, color);     /* 0 degree */
00403     }
00404 
00405     draw_x5 = draw_x7 = x0 - r;
00406     draw_y5 = draw_y7 = y0;
00407     if (draw_x5>=0) {
00408         pixel(draw_x5, draw_y5, color);     /* 180 degree */
00409     }
00410 
00411     if (r == 1) {
00412         return;
00413     }
00414 
00415     di = 3 - 2*r;
00416     xx = 0;
00417     yy = r;
00418     while (xx < yy) {
00419 
00420         if (di < 0) {
00421             di += 4*xx + 6;
00422         } else {
00423             di += 4*(xx - yy) + 10;
00424             yy--;
00425             draw_y0--;
00426             draw_y1--;
00427             draw_y2++;
00428             draw_y3++;
00429             draw_x4--;
00430             draw_x5++;
00431             draw_x6--;
00432             draw_x7++;
00433         }
00434         xx++;
00435         draw_x0++;
00436         draw_x1--;
00437         draw_x2++;
00438         draw_x3--;
00439         draw_y4++;
00440         draw_y5++;
00441         draw_y6--;
00442         draw_y7--;
00443 
00444         if ( (draw_x0 <= width()) && (draw_y0>=0) ) {
00445             pixel(draw_x0, draw_y0, color);
00446         }
00447 
00448         if ( (draw_x1 >= 0) && (draw_y1 >= 0) ) {
00449             pixel(draw_x1, draw_y1, color);
00450         }
00451 
00452         if ( (draw_x2 <= width()) && (draw_y2 <= height()) ) {
00453             pixel(draw_x2, draw_y2, color);
00454         }
00455 
00456         if ( (draw_x3 >=0 ) && (draw_y3 <= height()) ) {
00457             pixel(draw_x3, draw_y3, color);
00458         }
00459 
00460         if ( (draw_x4 <= width()) && (draw_y4 >= 0) ) {
00461             pixel(draw_x4, draw_y4, color);
00462         }
00463 
00464         if ( (draw_x5 >= 0) && (draw_y5 >= 0) ) {
00465             pixel(draw_x5, draw_y5, color);
00466         }
00467         if ( (draw_x6 <=width()) && (draw_y6 <= height()) ) {
00468             pixel(draw_x6, draw_y6, color);
00469         }
00470         if ( (draw_x7 >= 0) && (draw_y7 <= height()) ) {
00471             pixel(draw_x7, draw_y7, color);
00472         }
00473     }
00474     return;
00475 }
00476 
00477 void ST7735_TFT::fillcircle(int x, int y, int r, int color) {
00478     int i;
00479     for (i = 0; i <= r; i++)
00480         circle(x,y,i,color);
00481 }
00482 
00483 
00484 
00485 void ST7735_TFT::hline(int x0, int x1, int y, int color) {
00486     int w;
00487     w = x1 - x0 + 1;
00488     window(x0,y,w,1);
00489     wr_cmd(0x2C);
00490     wr_dat_start();
00491     for (int x=0; x<w; x++) {
00492         _spi.write(color);
00493         _spi.write(color >> 8);
00494     }
00495     wr_dat_stop();
00496     return;
00497 }
00498 
00499 
00500 
00501 void ST7735_TFT::vline(int x, int y0, int y1, int color) {
00502     int h;
00503     h = y1 - y0 + 1;
00504     window(x,y0,1,h);
00505     wr_cmd(0x2C);
00506     wr_dat_start();
00507     for (int y=0; y<h; y++) {
00508         _spi.write(color);
00509         _spi.write(color >> 8);
00510     }
00511     wr_dat_stop();
00512     return;
00513 }
00514 
00515 
00516 
00517 void ST7735_TFT::line(int x0, int y0, int x1, int y1, int color) {
00518     WindowMax();
00519     int   dx = 0, dy = 0;
00520     int   dx_sym = 0, dy_sym = 0;
00521     int   dx_x2 = 0, dy_x2 = 0;
00522     int   di = 0;
00523 
00524     dx = x1-x0;
00525     dy = y1-y0;
00526 
00527     if (dx == 0) {        /* vertical line */
00528         if (y1 > y0) vline(x0,y0,y1,color);
00529         else vline(x0,y1,y0,color);
00530         return;
00531     }
00532 
00533     if (dx > 0) {
00534         dx_sym = 1;
00535     } else {
00536         dx_sym = -1;
00537     }
00538     if (dy == 0) {        /* horizontal line */
00539         if (x1 > x0) hline(x0,x1,y0,color);
00540         else  hline(x1,x0,y0,color);
00541         return;
00542     }
00543 
00544     if (dy > 0) {
00545         dy_sym = 1;
00546     } else {
00547         dy_sym = -1;
00548     }
00549 
00550     dx = dx_sym*dx;
00551     dy = dy_sym*dy;
00552 
00553     dx_x2 = dx*2;
00554     dy_x2 = dy*2;
00555 
00556     if (dx >= dy) {
00557         di = dy_x2 - dx;
00558         while (x0 != x1) {
00559 
00560             pixel(x0, y0, color);
00561             x0 += dx_sym;
00562             if (di<0) {
00563                 di += dy_x2;
00564             } else {
00565                 di += dy_x2 - dx_x2;
00566                 y0 += dy_sym;
00567             }
00568         }
00569         pixel(x0, y0, color);
00570     } else {
00571         di = dx_x2 - dy;
00572         while (y0 != y1) {
00573             pixel(x0, y0, color);
00574             y0 += dy_sym;
00575             if (di < 0) {
00576                 di += dx_x2;
00577             } else {
00578                 di += dx_x2 - dy_x2;
00579                 x0 += dx_sym;
00580             }
00581         }
00582         pixel(x0, y0, color);
00583     }
00584     return;
00585 }
00586 
00587 
00588 
00589 
00590 void ST7735_TFT::rect(int x0, int y0, int x1, int y1, int color) {
00591 
00592     if (x1 > x0) hline(x0,x1,y0,color);
00593     else  hline(x1,x0,y0,color);
00594 
00595     if (y1 > y0) vline(x0,y0,y1,color);
00596     else vline(x0,y1,y0,color);
00597 
00598     if (x1 > x0) hline(x0,x1,y1,color);
00599     else  hline(x1,x0,y1,color);
00600 
00601     if (y1 > y0) vline(x1,y0,y1,color);
00602     else vline(x1,y1,y0,color);
00603 
00604     return;
00605 }
00606 
00607 
00608 
00609 void ST7735_TFT::fillrect(int x0, int y0, int x1, int y1, int color) {
00610 
00611     int h = y1 - y0 + 1;
00612     int w = x1 - x0 + 1;
00613     int pixel = h * w;
00614     window(x0,y0,w,h);
00615     wr_cmd(0x2C);
00616     wr_dat_start();
00617     for (int p=0; p<pixel; p++) {
00618         _spi.write(color);
00619         _spi.write(color >> 8);
00620     }
00621     wr_dat_stop();
00622     return;
00623 }
00624 
00625 
00626 
00627 void ST7735_TFT::locate(int x, int y) {
00628     char_x = x;
00629     char_y = y;
00630 }
00631 
00632 
00633 
00634 int ST7735_TFT::columns() {
00635     return width() / font[1];
00636 }
00637 
00638 
00639 
00640 int ST7735_TFT::rows() {
00641     return height() / font[2];
00642 }
00643 
00644 
00645 
00646 int ST7735_TFT::_putc(int value) {
00647     if (value == '\n') {    // new line
00648         char_x = 0;
00649         char_y = char_y + font[2];
00650         if (char_y >= height() - font[2]) {
00651             char_y = 0;
00652         }
00653     } else {
00654         character(char_x, char_y, value);
00655      }
00656     return value;
00657 }
00658 
00659 
00660 
00661 
00662 void ST7735_TFT::character(int x, int y, int c) {
00663     unsigned int hor,vert,offset,bpl,j,i,b;
00664     unsigned char* zeichen;
00665     unsigned char z,w;
00666 
00667     if ((c < 31) || (c > 127)) return;   // test char range
00668 
00669     // read font parameter from start of array
00670     offset = font[0];                    // bytes / char
00671     hor = font[1];                       // get hor size of font
00672     vert = font[2];                      // get vert size of font
00673     bpl = font[3];                       // bytes per line
00674 
00675     if (char_x + hor > width()) {
00676         char_x = 0;
00677         char_y = char_y + vert;
00678        if (char_y >= height() - font[2]) {
00679             char_y = 0;
00680         }
00681     }
00682 
00683     window(char_x, char_y,hor,vert); // char box
00684     wr_cmd(0x2C);
00685     wr_dat_start();
00686     zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap
00687     w = zeichen[0];                          // width of actual char
00688     _spi.format(16,3);                       // pixel are 16 bit
00689 
00690     for (j=0; j<vert; j++) {  //  vert line
00691         for (i=0; i<hor; i++) {   //  horz line
00692             z =  zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
00693             b = 1 << (j & 0x07);
00694             if (( z & b ) == 0x00) {
00695                 _spi.write(_background);
00696             } else {
00697                 _spi.write(_foreground);
00698             }
00699         }
00700     }
00701     _spi.format(8,3);                      // 8 bit
00702     wr_dat_stop();
00703     if ((w + 2) < hor) {                   // x offset to next char
00704         char_x += w + 2;
00705     } else char_x += hor;
00706 }
00707 
00708 
00709 
00710 
00711 
00712 void ST7735_TFT::set_font(unsigned char* f) {
00713     font = f;
00714 }
00715 
00716 
00717 
00718 void ST7735_TFT::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap) {
00719     unsigned int    i,j,value;
00720     unsigned short *bitmap_ptr = (unsigned short *)bitmap;
00721     window(x, y, w, h);
00722     wr_cmd(0x2C);
00723     wr_dat_start();
00724     for (j = 0; j < h; j++) {        //Lines
00725         for (i = 0; i < w; i++) {     // copy pixel data to TFT
00726             _spi.write(*bitmap_ptr);    // one line
00727             _spi.write(*bitmap_ptr >> 8);  
00728             bitmap_ptr++;
00729         }
00730     }
00731     wr_dat_stop();
00732 }
00733 
00734 
00735 int ST7735_TFT::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP) {
00736 // BEWARE !
00737 // NOT TESTED
00738 #define OffsetPixelWidth    18
00739 #define OffsetPixelHeigh    22
00740 #define OffsetFileSize      34
00741 #define OffsetPixData       10
00742 #define OffsetBPP           28
00743 
00744     char filename[50];
00745     unsigned char BMP_Header[54];
00746     unsigned short BPP_t;
00747     unsigned int PixelWidth,PixelHeigh,start_data;
00748     unsigned int    i,off;
00749     int padd,j;
00750     unsigned short *line;
00751 
00752     // get the filename
00753     LocalFileSystem local("local");
00754     sprintf(&filename[0],"/local/");
00755     i=7;
00756     while (*Name_BMP!='\0') {
00757         filename[i++]=*Name_BMP++;
00758     }
00759     FILE *Image = fopen((const char *)&filename[0], "r");  // open the bmp file
00760     if (!Image) {
00761         return(0);      // error file not found !
00762     }
00763 
00764     fread(&BMP_Header[0],1,54,Image);      // get the BMP Header
00765 
00766     if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) {  // check magic byte
00767         fclose(Image);
00768         return(-1);     // error no BMP file
00769     }
00770 
00771     BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8);
00772     if (BPP_t != 0x0010) {
00773         fclose(Image);
00774         return(-2);     // error no 16 bit BMP
00775     }
00776 
00777     PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24);
00778     PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24);
00779     if (PixelHeigh > height() + y || PixelWidth > width() + x) {
00780         fclose(Image);
00781         return(-3);      // to big
00782     }
00783 
00784     start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
00785 
00786     line = (unsigned short *) malloc (PixelWidth); // we need a buffer for a line
00787     if (line == NULL) {
00788         return(-4);         // error no memory
00789     }
00790 
00791     // the lines are padded to multiple of 4 bytes
00792     padd = -1;
00793     do {
00794         padd ++;
00795     } while ((PixelWidth * 2 + padd)%4 != 0);
00796 
00797     window(x, y,PixelWidth,PixelHeigh);
00798     wr_cmd(0x2C);
00799     wr_dat_start();
00800     _spi.format(16,3);    
00801     for (j = PixelHeigh - 1; j >= 0; j--) {               //Lines bottom up
00802         off = j * (PixelWidth * 2 + padd) + start_data;   // start of line
00803         fseek(Image, off ,SEEK_SET);
00804         fread(line,1,PixelWidth * 2,Image);       // read a line - slow !
00805         for (i = 0; i < PixelWidth; i++) {        // copy pixel data to TFT
00806             _spi.write(line[i]);                  // one 16 bit pixel
00807         } 
00808     }
00809     _spi.format(8,3);
00810     wr_dat_stop();
00811     free (line);
00812     fclose(Image);
00813     return(1);
00814 }