Adapted from Peter Dresche's original for Waveshare 2.8inch TFT Touch Shield Board and Mbed 6. RGB order reversed by changing reg 16 commands, spi write code adjusted as there is no reset pin but there is data command pin. Wait commands changed for new thread_sleep style, Stream class explicitly included. Library to control a QVGA TFT connected to SPI. You can use printf to print text The lib can handle different fonts, draw lines, circles, rect and bmp

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPI_TFT.cpp Source File

SPI_TFT.cpp

00001 /* mbed library for 240*320 pixel display TFT based on HX8347D LCD Controller
00002  * Copyright (c) 2011 Peter Drescher - DC2PD
00003  *
00004  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00005  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00006  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00007  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00008  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00009  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00010  * THE SOFTWARE.
00011  */
00012 
00013 
00014 // fix bmp padding for Bitmap function
00015 // speed up pixel
00016 // 30.12.11 fix cls
00017 // 11.03.12 use DMA to speed up
00018 // 15.03.12 use SSEL for TFT CS to enable DMA Register writes
00019 // 06.04.12 fix SSEL CS problem
00020 // 06.04.12 use direct access to the spi register to speed up the library.
00021 // 11.09.12 switch back to using io pin as cs to avoid problems with SSEL CS.
00022 // 21.09.12 fix Bug in BMP_16
00023 // 11.10.12 patch from Hans Bergles to get SPI1 working again
00024 // 03.02.13 add a switch to switch off DMA use for LPC11U24
00025 // 04.03.13 add support for new Kinetis board
00026 // 25.03.13 fix Bug in bitmap for Kinetis board
00027 // 18.10.13 Better Circle function from Michael Ammann
00028 // 2020-2021 Hacked by JHD
00029 
00030 #include "SPI_TFT.h"
00031 #include "mbed.h"
00032 // for fast performance on some STM boards
00033 
00034 
00035 
00036 
00037 #define BPP         16                  // Bits per pixel    
00038 
00039 #if defined TARGET_LPC1768
00040 #define USE_DMA                     // we use dma to speed up
00041 #define NO_MBED_LIB                 // we write direct to the SPI register to speed up  
00042 #endif
00043 
00044 #if defined NO_DMA                      // if LPC1768 user want no DMA
00045 #undef USE_DMA
00046 #endif
00047 
00048 
00049 //extern Serial pc;
00050 //extern DigitalOut xx;     // debug !!
00051 
00052 SPI_TFT::SPI_TFT(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset, const char *name)
00053     : _spi(mosi, miso, sclk), _cs(cs), _reset(reset),GraphicsDisplay(name)
00054 {
00055     orientation = 0;
00056     char_x = 0;
00057     tft_reset();
00058 }
00059 
00060 int SPI_TFT::width()
00061 {
00062     if (orientation == 0 || orientation == 2) return 240;
00063     else return 320;
00064 }
00065 
00066 
00067 int SPI_TFT::height()
00068 {
00069     if (orientation == 0 || orientation == 2) return 320;
00070     else return 240;
00071 }
00072 
00073 
00074 void SPI_TFT::set_orientation(unsigned int o)
00075 {
00076     orientation = o;
00077     switch (orientation) {
00078         case 0:
00079             wr_reg(0x16, 0x08);
00080             break;
00081         case 1:
00082             wr_reg(0x16, 0x68);
00083             break;
00084         case 2:
00085             wr_reg(0x16, 0xC8);
00086             break;
00087         case 3:
00088             wr_reg(0x16, 0xA8);
00089             break;
00090     }
00091     WindowMax();
00092 }
00093 
00094 
00095 // write command to tft register
00096 
00097 void SPI_TFT::wr_cmd(unsigned char cmd)
00098 {
00099     unsigned short spi_d;
00100     spi_d =  0x7000 | cmd ;
00101     _spi.write(spi_d);      // mbed lib
00102 
00103 }
00104 
00105 
00106 // write data to tft register
00107 void SPI_TFT::wr_dat(unsigned char dat)
00108 {
00109     unsigned short spi_d;
00110     spi_d =  0x7200 | dat;
00111     _spi.write(spi_d);      
00112 }
00113 
00114 
00115 
00116 // the HX8347-D controller do not use the MISO (SDO) Signal.
00117 // This is a bug - ?
00118 // A read will return 0 at the moment 
00119 
00120 unsigned short SPI_TFT::rd_dat (void)
00121 {
00122     unsigned short val = 0;
00123 
00124     //val = _spi.write(0x73ff);                /* Dummy read 1           */
00125     //val   = _spi.write(0x0000);              /* Read D8..D15           */
00126     return (val);
00127 }
00128 
00129 // write to a TFT register
00130 void SPI_TFT::wr_reg (unsigned char reg, unsigned char val)
00131 {
00132     _spi.lock();
00133     _spi.format(16,3);  
00134     _cs=0;
00135     _reset=0;
00136     wr_cmd(reg);
00137     _reset=1;
00138     wr_dat(val);
00139     _cs=1;
00140     _spi.unlock();
00141 }
00142 
00143 // read from a TFT register
00144 unsigned short SPI_TFT::rd_reg (unsigned char reg)
00145 {
00146     wr_cmd(reg);
00147     return(rd_dat());
00148 }
00149 
00150 // setup TFT controller - this is called by constructor
00151 void SPI_TFT::tft_reset()
00152 {
00153                            // 16 Bit SPI  
00154     _spi.format(16,3);                 // 16 bit spi mode 3
00155 
00156     _spi.frequency(48000000);          // 48 Mhz SPI clock
00157     _cs = 1;                           // cs high
00158                       // end reset
00159     thread_sleep_for(5);
00160 
00161     /* Start Initial Sequence ----------------------------------------------------*/
00162     wr_reg(0xEA, 0x00);                 /* Reset Power Control 1                */
00163     wr_reg(0xEB, 0x20);                 /* Power Control 2                      */
00164     wr_reg(0xEC, 0x0C);                 /* Power Control 3                      */
00165     wr_reg(0xED, 0xC4);                 /* Power Control 4                      */
00166     wr_reg(0xE8, 0x40);                 /* Source OPON_N                        */
00167     wr_reg(0xE9, 0x38);                 /* Source OPON_I                        */
00168     wr_reg(0xF1, 0x01);                 /*                                      */
00169     wr_reg(0xF2, 0x10);                 /*                                      */
00170     wr_reg(0x27, 0xA3);                 /* Display Control 2                    */
00171 
00172     /* Power On sequence ---------------------------------------------------------*/
00173     wr_reg(0x1B, 0x1B);                 /* Power Control 2                      */
00174     wr_reg(0x1A, 0x01);                 /* Power Control 1                      */
00175     wr_reg(0x24, 0x2F);                 /* Vcom Control 2                       */
00176     wr_reg(0x25, 0x57);                 /* Vcom Control 3                       */
00177     wr_reg(0x23, 0x8D);                 /* Vcom Control 1                       */
00178 
00179     /* Gamma settings  -----------------------------------------------------------*/
00180     wr_reg(0x40,0x00);   //   default setup
00181     wr_reg(0x41,0x00);   //
00182     wr_reg(0x42,0x01);   //
00183     wr_reg(0x43,0x13);   //
00184     wr_reg(0x44,0x10);   //
00185     wr_reg(0x45,0x26);   //
00186     wr_reg(0x46,0x08);   //
00187     wr_reg(0x47,0x51);   //
00188     wr_reg(0x48,0x02);   //
00189     wr_reg(0x49,0x12);   //
00190     wr_reg(0x4A,0x18);   //
00191     wr_reg(0x4B,0x19);   //
00192     wr_reg(0x4C,0x14);   //
00193     wr_reg(0x50,0x19);   //
00194     wr_reg(0x51,0x2F);   //
00195     wr_reg(0x52,0x2C);   //
00196     wr_reg(0x53,0x3E);   //
00197     wr_reg(0x54,0x3F);   //
00198     wr_reg(0x55,0x3F);   //
00199     wr_reg(0x56,0x2E);   //
00200     wr_reg(0x57,0x77);   //
00201     wr_reg(0x58,0x0B);   //
00202     wr_reg(0x59,0x06);   //
00203     wr_reg(0x5A,0x07);   //
00204     wr_reg(0x5B,0x0D);   //
00205     wr_reg(0x5C,0x1D);   //
00206     wr_reg(0x5D,0xCC);   //
00207 
00208     /* Power + Osc ---------------------------------------------------------------*/
00209     wr_reg(0x18, 0x36);                 /* OSC Control 1                        */
00210     wr_reg(0x19, 0x01);                 /* OSC Control 2                        */
00211     wr_reg(0x01, 0x00);                 /* Display Mode Control                 */
00212     wr_reg(0x1F, 0x88);                 /* Power Control 6                      */
00213     thread_sleep_for(5);                          /* Delay 5 ms                           */
00214     wr_reg(0x1F, 0x80);                 /* Power Control 6                      */
00215     thread_sleep_for(5);                         /* Delay 5 ms                           */
00216     wr_reg(0x1F, 0x90);                 /* Power Control 6                      */
00217     thread_sleep_for(5);                          /* Delay 5 ms                           */
00218     wr_reg(0x1F, 0xD0);                 /* Power Control 6                      */
00219     thread_sleep_for(5);                         /* Delay 5 ms                           */
00220 
00221     wr_reg(0x17, 0x05);                 /* Colmod 16Bit/Pixel                   */
00222 
00223     wr_reg(0x36, 0x00);                 /* Panel Characteristic                 */
00224     wr_reg(0x28, 0x38);                 /* Display Control 3                    */
00225     thread_sleep_for(40);
00226     wr_reg(0x28, 0x3C);                 /* Display Control 3                    */
00227     switch (orientation) {
00228         case 0:
00229             wr_reg(0x16, 0x08);
00230             break;
00231         case 2:
00232             wr_reg(0x16, 0xC8);
00233             break;
00234         case 3:
00235             wr_reg(0x16, 0xA8);
00236             break;   
00237          case 1:
00238          default:
00239             wr_reg(0x16, 0x68);
00240             break;   
00241             
00242     }
00243 
00244     WindowMax ();
00245 }
00246 
00247 // Set one pixel
00248 void SPI_TFT::pixel(int x, int y, int color)
00249 {
00250     wr_reg(0x03, (x >> 0));
00251     wr_reg(0x02, (x >> 8));
00252     wr_reg(0x07, (y >> 0));
00253     wr_reg(0x06, (y >> 8));
00254     _spi.lock();
00255     _cs = 0;
00256     _reset=0;
00257     wr_cmd(0x22);
00258     _reset=1;
00259  //   _spi.format(8,3);                             // 8 bit Mode 3
00260  //   _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
00261  //   _spi.format(16,3);                            // switch to 16 bit Mode 3
00262     #ifdef __DIRECTSPI_H_
00263         _spi.directWrite(color);
00264     #else
00265         _spi.write(color);
00266     #endif                          // Write D0..D15
00267     _cs = 1;
00268     _spi.unlock();
00269 }
00270 
00271 // define draw area
00272 void SPI_TFT::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h)
00273 {
00274     wr_reg(0x03, x );
00275     wr_reg(0x02, (x >> 8));
00276     wr_reg(0x05, x+w-1 );
00277     wr_reg(0x04, ((x+w-1) >> 8));
00278     wr_reg(0x07,  y );
00279     wr_reg(0x06, ( y >> 8));
00280     wr_reg(0x09, ( y+h-1 ));
00281     wr_reg(0x08, ( (y+h-1) >> 8));
00282 }
00283 
00284 // set draw area to max
00285 void SPI_TFT::WindowMax (void)
00286 {
00287     window (0, 0, width(),  height());
00288 }
00289 
00290 
00291 // clear screen
00292 void SPI_TFT::cls (void)
00293 {
00294     fprintf(stderr, "CLS \n\r");
00295     int pixel = ( width() * height());
00296     WindowMax();
00297     _spi.lock();
00298     _cs = 0;  
00299     _reset=0;
00300     wr_cmd(0x22);
00301     _reset=1;                       // 16 bit SPI  
00302 //    _spi.format(8,3);                             // 8 bit Mode 3
00303 //    _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
00304 //    _spi.format(16,3);                            // switch back to 16 bit Mode 3
00305     unsigned int i;
00306     for (i = 0; i < ( width() * height()); i++)
00307     #ifdef __DIRECTSPI_H_
00308         _spi.directWrite(_background);
00309     #else
00310         _spi.write(_background);
00311     #endif
00312     _cs = 1;
00313     _spi.unlock();
00314 }
00315 
00316 void SPI_TFT::circle(int x0, int y0, int r, int color)
00317 {  
00318     int x = -r, y = 0, err = 2-2*r, e2;
00319     do {
00320         pixel(x0-x, y0+y,color);
00321         pixel(x0+x, y0+y,color);
00322         pixel(x0+x, y0-y,color);
00323         pixel(x0-x, y0-y,color);
00324         e2 = err;
00325         if (e2 <= y) {
00326             err += ++y*2+1;
00327             if (-x == y && e2 <= x) e2 = 0;
00328         }
00329         if (e2 > x) err += ++x*2+1;
00330     } while (x <= 0);
00331         
00332 }
00333  
00334 void SPI_TFT::fillcircle(int x0, int y0, int r, int color)
00335 {
00336     int x = -r, y = 0, err = 2-2*r, e2;
00337     do {
00338         vline(x0-x, y0-y, y0+y, color);
00339         vline(x0+x, y0-y, y0+y, color);
00340         e2 = err;
00341         if (e2 <= y) {
00342             err += ++y*2+1;
00343             if (-x == y && e2 <= x) e2 = 0;
00344         }
00345         if (e2 > x) err += ++x*2+1;
00346     } while (x <= 0);
00347 }
00348 
00349 
00350 // draw horizontal line
00351 void SPI_TFT::hline(int x0, int x1, int y, int color)
00352 {
00353     int w;
00354     w = x1 - x0 + 1;
00355     window(x0,y,w,1);
00356     _spi.lock();
00357     _cs = 0;  
00358     _reset=0;
00359     wr_cmd(0x22);
00360     _reset=1;   
00361                            // switch back to 16 bit Mode 3
00362             for (int j=0; j<w; j++) {
00363                   #ifdef __DIRECTSPI_H_
00364                     _spi.directWrite(color);
00365                  #else
00366                     _spi.write(color);
00367                  #endif  // one line
00368             }
00369 
00370     _cs = 1;
00371     _spi.unlock();
00372     WindowMax();
00373     return;
00374 }
00375 
00376 // draw vertical line
00377 void SPI_TFT::vline(int x, int y0, int y1, int color)
00378 {
00379     int h;
00380     h = y1 - y0 + 1;
00381     window(x,y0,1,h);
00382     _spi.lock();
00383     _cs = 0;  
00384     _reset=0;
00385     wr_cmd(0x22);
00386     _reset=1;   
00387                // switch to 16 bit Mode 3
00388     for (int y=0; y<h; y++) {
00389                       #ifdef __DIRECTSPI_H_
00390                     _spi.directWrite(color);
00391                  #else
00392                     _spi.write(color);
00393                  #endif  // one line
00394     }
00395 
00396     _cs = 1;
00397     _spi.unlock();
00398     WindowMax();
00399     return;
00400 }
00401 
00402 
00403 // draw line
00404 void SPI_TFT::line(int x0, int y0, int x1, int y1, int color)
00405 {
00406     //WindowMax();
00407     int   dx = 0, dy = 0;
00408     int   dx_sym = 0, dy_sym = 0;
00409     int   dx_x2 = 0, dy_x2 = 0;
00410     int   di = 0;
00411 
00412     dx = x1-x0;
00413     dy = y1-y0;
00414 
00415     if (dx == 0) {        /* vertical line */
00416         if (y1 > y0) vline(x0,y0,y1,color);
00417         else vline(x0,y1,y0,color);
00418         return;
00419     }
00420 
00421     if (dx > 0) {
00422         dx_sym = 1;
00423     } else {
00424         dx_sym = -1;
00425     }
00426     if (dy == 0) {        /* horizontal line */
00427         if (x1 > x0) hline(x0,x1,y0,color);
00428         else  hline(x1,x0,y0,color);
00429         return;
00430     }
00431 
00432     if (dy > 0) {
00433         dy_sym = 1;
00434     } else {
00435         dy_sym = -1;
00436     }
00437 
00438     dx = dx_sym*dx;
00439     dy = dy_sym*dy;
00440 
00441     dx_x2 = dx*2;
00442     dy_x2 = dy*2;
00443 
00444     if (dx >= dy) {
00445         di = dy_x2 - dx;
00446         while (x0 != x1) {
00447 
00448             pixel(x0, y0, color);
00449             x0 += dx_sym;
00450             if (di<0) {
00451                 di += dy_x2;
00452             } else {
00453                 di += dy_x2 - dx_x2;
00454                 y0 += dy_sym;
00455             }
00456         }
00457         pixel(x0, y0, color);
00458     } else {
00459         di = dx_x2 - dy;
00460         while (y0 != y1) {
00461             pixel(x0, y0, color);
00462             y0 += dy_sym;
00463             if (di < 0) {
00464                 di += dx_x2;
00465             } else {
00466                 di += dx_x2 - dy_x2;
00467                 x0 += dx_sym;
00468             }
00469         }
00470         pixel(x0, y0, color);
00471     }
00472     return;
00473 }
00474 
00475 // draw rect
00476 void SPI_TFT::rect(int x0, int y0, int x1, int y1, int color)
00477 {
00478 
00479     if (x1 > x0) hline(x0,x1,y0,color);
00480     else  hline(x1,x0,y0,color);
00481 
00482     if (y1 > y0) vline(x0,y0,y1,color);
00483     else vline(x0,y1,y0,color);
00484 
00485     if (x1 > x0) hline(x0,x1,y1,color);
00486     else  hline(x1,x0,y1,color);
00487 
00488     if (y1 > y0) vline(x1,y0,y1,color);
00489     else vline(x1,y1,y0,color);
00490 
00491     return;
00492 }
00493 
00494 
00495 // fill rect
00496 void SPI_TFT::fillrect(int x0, int y0, int x1, int y1, int color)
00497 {
00498 
00499     int h = y1 - y0 + 1;
00500     int w = x1 - x0 + 1;
00501     int pixel = h * w;
00502     window(x0,y0,w,h);
00503     _spi.lock();
00504     _cs = 0;  
00505     _reset=0;
00506     wr_cmd(0x22);
00507     _reset=1;   
00508 
00509     for (int p=0; p<pixel; p++) {
00510                 #ifdef __DIRECTSPI_H_
00511                     _spi.directWrite(color);
00512                  #else
00513                     _spi.write(color);
00514                  #endif  // one line
00515     }
00516 
00517     _cs = 1;
00518     _spi.unlock();
00519     WindowMax();
00520     return;
00521 }
00522 
00523 // set cursor position
00524 void SPI_TFT::locate(int x, int y)
00525 {
00526     char_x = x;
00527     char_y = y;
00528 }
00529 
00530 
00531 // calculate num of chars in a row
00532 int SPI_TFT::columns()
00533 {
00534     return width() / font[1];
00535 }
00536 
00537 // calculate num of rows on the screen
00538 int SPI_TFT::rows()
00539 {
00540     return height() / font[2];
00541 }
00542 
00543 // print a char on the screen
00544 int SPI_TFT::_putc(int value)
00545 {
00546     if (value == '\n') {    // new line
00547         char_x = 0;
00548         char_y = char_y + font[2];
00549         if (char_y >= height() - font[2]) {
00550             char_y = 0;
00551         }
00552     } else {
00553         character(char_x, char_y, value);
00554     }
00555     return value;
00556 }
00557 
00558 // consrtuct the char out of the font
00559 void SPI_TFT::character(int x, int y, int c)
00560 {
00561     unsigned int hor,vert,offset,bpl,j,i,b;
00562     unsigned char* zeichen;
00563     unsigned char z,w;
00564 
00565     if ((c < 31) || (c > 127)) return;   // test char range
00566 
00567     // read font parameter from start of array
00568     offset = font[0];                    // bytes / char
00569     hor = font[1];                       // get hor size of font
00570     vert = font[2];                      // get vert size of font
00571     bpl = font[3];                       // bytes per line
00572 
00573     if (char_x + hor > width()) {
00574         char_x = 0;
00575         char_y = char_y + vert;
00576         if (char_y >= height() - font[2]) {
00577             char_y = 0;
00578         }
00579     }
00580     window(char_x, char_y,hor,vert); // char box
00581     _spi.lock();
00582     _cs = 0;  
00583     _reset=0;
00584     wr_cmd(0x22);
00585     _reset=1;   
00586 
00587         zeichen = &font[((c -32) * offset) + 4];    // start of char bitmap
00588         w = zeichen[0];                             // width of actual char
00589         for (j=0; j<vert; j++) {  //  vert line
00590             for (i=0; i<hor; i++) {   //  horz line
00591                 z =  zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
00592                 b = 1 << (j & 0x07);
00593                 if (( z & b ) == 0x00) {
00594 
00595                 #ifdef __DIRECTSPI_H_
00596                     _spi.directWrite(_background);
00597                  #else
00598                     _spi.write(_background);
00599                  #endif  // one line
00600 
00601                 } else {
00602                   #ifdef __DIRECTSPI_H_
00603                     _spi.directWrite(_foreground);
00604                  #else
00605                     _spi.write(_foreground);
00606                  #endif  // one line
00607                 }
00608             }
00609         }
00610    
00611     _cs = 1;
00612     _spi.unlock();
00613     WindowMax();
00614     if ((w + 2) < hor) {                   // x offset to next char
00615         char_x += w + 2;
00616     } else char_x += hor;
00617 }
00618 
00619 
00620 void SPI_TFT::set_font(unsigned char* f)
00621 {
00622     font = f;
00623 }
00624 
00625 
00626 void SPI_TFT::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap)
00627 {
00628     unsigned int  j;
00629     int padd;
00630   
00631     unsigned short *bitmap_ptr = (unsigned short *)bitmap;
00632 
00633   
00634     // the lines are padded to multiple of 4 bytes in a bitmap
00635     padd = -1;
00636     do {
00637         padd ++;
00638     } while (2*(w + padd)%4 != 0);
00639     window(x, y, w, h);
00640     _spi.lock();
00641     _cs = 0;  
00642     _reset=0;
00643     wr_cmd(0x22);
00644     _reset=1;   
00645 
00646     bitmap_ptr += ((h - 1)* (w + padd));              
00647     unsigned int i;
00648     for (j = 0; j < h; j++) {        //Lines
00649         for (i = 0; i < w; i++) {     // copy pixel data to TFT
00650 
00651                   #ifdef __DIRECTSPI_H_
00652                     _spi.directWrite(*bitmap_ptr);
00653                  #else
00654                     _spi.write(*bitmap_ptr);
00655                  #endif  // one line
00656                 bitmap_ptr++;
00657   
00658         }
00659         bitmap_ptr -= 2*w;
00660         bitmap_ptr -= padd;
00661      }
00662 
00663     _cs = 1;
00664     _spi.unlock();
00665     WindowMax();
00666 }
00667 
00668 int SPI_TFT::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP)
00669 {
00670  
00671 #define OffsetPixelWidth    18
00672 #define OffsetPixelHeigh    22
00673 #define OffsetFileSize      34
00674 #define OffsetPixData       10
00675 #define OffsetBPP           28
00676  
00677     char filename[50];
00678     unsigned char BMP_Header[54];
00679     unsigned short BPP_t;
00680     int PixelWidth,PixelHeigh;
00681     unsigned int start_data;
00682     unsigned int    i,off;
00683     int padd,j;
00684     unsigned short *line;
00685  
00686     sprintf(&filename[0],"%s",Name_BMP);
00687     
00688     FILE *Image = fopen((const char *)&filename[0], "rb");  // open the bmp file
00689     if (!Image) {
00690         return(0);      // error file not found !
00691     }
00692 
00693     fread(&BMP_Header[0],1,54,Image);      // get the BMP Header
00694 
00695     if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) {  // check magic byte
00696         fclose(Image);
00697         return(-1);     // error no BMP file
00698     }
00699 
00700     BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8);
00701     if (BPP_t != 0x0010) {
00702         fclose(Image);
00703         return(-2);     // error no 16 bit BMP
00704     }
00705   
00706     PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24);
00707     PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24);
00708     if (PixelHeigh > height() + y || PixelWidth > width() + x) {
00709         fclose(Image);
00710         return(-3);      // to big
00711     }
00712 
00713     start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
00714 
00715     line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line
00716     if (line == NULL) {
00717         return(-4);         // error no memory
00718     }
00719  
00720     // the bmp lines are padded to multiple of 4 bytes
00721     padd = -1;
00722     do {
00723         padd ++;
00724     } while ((PixelWidth * 2 + padd)%4 != 0);
00725     int k,l;
00726 
00727     for ( j = PixelHeigh-1 ; j >=0  ; j-- ) {               //Lines bottom up
00728        
00729         off = (j * (PixelWidth  * 2 + padd)) + (start_data);   // start of line
00730         int erra=fseek(Image, off,SEEK_SET);
00731         int errb=fread(line,1,PixelWidth * 2,Image);       // read a line - slow !
00732         window(x, (y+PixelHeigh)-j , PixelWidth ,1);
00733         _spi.lock();
00734         _cs=0;
00735         _reset=0;
00736         wr_cmd(0x22);
00737         _reset=1;
00738         _spi.format(16,3);    
00739                        // switch to 16 bit Mode 3
00740         for (l = PixelWidth - 1; l >= 0 ; l--) {        // copy pixel data to TFT
00741             int out = line[(PixelWidth-1)-l];
00742                   #ifdef __DIRECTSPI_H_
00743                     _spi.directWrite(line[(PixelWidth-1)-l]);
00744                  #else
00745                     _spi.write(ine[(PixelWidth-1)-l]);
00746                  #endif  // one line
00747         }
00748 
00749         _cs=1;
00750         _spi.unlock();
00751 
00752     }
00753 
00754     free (line);
00755     fclose(Image);
00756     WindowMax();
00757     return(1);
00758 }
00759