Lib for the new LCD Display with ILI9341 controller

Dependents:   TFT_Test_ILI9341 touch_piirto TFT_banggood TFT_Test_ILI9341-a-fish ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPI_TFT_ILI9341.cpp Source File

SPI_TFT_ILI9341.cpp

00001 /* mbed library for 240*320 pixel display TFT based on ILI9341 LCD Controller
00002  * Copyright (c) 2013 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 // 12.06.13 fork from SPI_TFT code because controller is different ...
00014 // 14.07.13 Test with real display and bugfix 
00015 // 18.10.13 Better Circle function from Michael Ammann
00016 // 22.10.13 Fixes for Kinetis Board - 8 bit spi
00017 // 26.01.14 Change interface for BMP_16 to also use SD-cards
00018 // 23.06.14 switch back to old Version - fork for L152 
00019 // 24.06.14 Add compiler flag for optimized L152 version
00020 // 25.06.14 Add optimized F103 version
00021 
00022 // exclude this file for platforms with optimized version
00023 #if defined TARGET_NUCLEO_L152RE || defined TARGET_NUCLEO_F103RB || defined TARGET_LPC1768
00024 // this platforms are supported by special version in different source file
00025 #else
00026 
00027 #include "SPI_TFT_ILI9341.h"
00028 #include "mbed.h"
00029 
00030 #define BPP         16                  // Bits per pixel    
00031          
00032 //extern Serial pc;
00033 //extern DigitalOut xx;     // debug !!
00034 
00035 SPI_TFT_ILI9341::SPI_TFT_ILI9341(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset, PinName dc, const char *name)
00036     : GraphicsDisplay(name), SPI(mosi, miso, sclk,NC), _cs(cs), _reset(reset), _dc(dc)
00037 {
00038     
00039     orientation = 0;
00040     char_x = 0;
00041     SPI::format(8,3);                  // 8 bit spi mode 3
00042     SPI::frequency(10000000);          // 10 Mhz SPI clock
00043     tft_reset();
00044 }
00045 
00046 int SPI_TFT_ILI9341::width()
00047 {
00048     if (orientation == 0 || orientation == 2) return 240;
00049     else return 320;
00050 }
00051 
00052 
00053 int SPI_TFT_ILI9341::height()
00054 {
00055     if (orientation == 0 || orientation == 2) return 320;
00056     else return 240;
00057 }
00058 
00059 
00060 void SPI_TFT_ILI9341::set_orientation(unsigned int o)
00061 {
00062     orientation = o;
00063     wr_cmd(0x36);                     // MEMORY_ACCESS_CONTROL
00064     switch (orientation) {
00065         case 0:
00066             SPI::write(0x48);
00067             break;
00068         case 1:
00069             SPI::write(0x28);
00070             break;
00071         case 2:
00072             SPI::write(0x88);
00073             break;
00074         case 3:
00075             SPI::write(0xE8);
00076             break;
00077     }
00078     _cs = 1; 
00079     WindowMax();
00080 } 
00081 
00082 
00083 // write command to tft register
00084 
00085 void SPI_TFT_ILI9341::wr_cmd(unsigned char cmd)
00086 {
00087     _dc = 0;
00088     _cs = 0;
00089     SPI::write(cmd);      // mbed lib
00090     _dc = 1;
00091 }
00092 
00093 
00094 
00095 void SPI_TFT_ILI9341::wr_dat(unsigned char dat)
00096 {
00097    SPI::write(dat);      // mbed lib
00098 }
00099 
00100 
00101 
00102 // the ILI9341 can read 
00103 
00104 char SPI_TFT_ILI9341::rd_byte(unsigned char cmd)
00105 {
00106     char r;
00107     _dc = 0;
00108     _cs = 0;
00109     SPI::write(cmd);      // mbed lib
00110     _cs = 1;
00111     r = SPI::write(0xff);
00112     _cs = 1;    
00113     return(r);
00114 }
00115 
00116 // read 32 bit
00117 int SPI_TFT_ILI9341::rd_32(unsigned char cmd)
00118 {
00119     int d;
00120     char r;
00121     _dc = 0;
00122     _cs = 0;
00123     d = cmd;
00124     d = d << 1;
00125     SPI::format(9,3);    // we have to add a dummy clock cycle
00126     SPI::write(d);
00127     SPI::format(8,3);   
00128     _dc = 1;
00129     r = SPI::write(0xff);
00130     d = r;
00131     r = SPI::write(0xff);
00132     d = (d << 8) | r;
00133     r = SPI::write(0xff);
00134     d = (d << 8) | r;
00135     r = SPI::write(0xff);
00136     d = (d << 8) | r;
00137     _cs = 1;    
00138     return(d);
00139 }
00140 
00141 int  SPI_TFT_ILI9341::Read_ID(void){
00142     int r;
00143     r = rd_byte(0x0A);
00144     r = rd_byte(0x0A);
00145     r = rd_byte(0x0A);
00146     r = rd_byte(0x0A);
00147     return(r);
00148 }
00149 
00150 
00151 // Init code based on MI0283QT datasheet
00152 
00153 void SPI_TFT_ILI9341::tft_reset()
00154 {
00155     _cs = 1;                           // cs high
00156     _dc = 1;                           // dc high 
00157     _reset = 0;                        // display reset
00158 
00159     wait_us(50);
00160     _reset = 1;                       // end hardware reset
00161     wait_ms(5);
00162      
00163     wr_cmd(0x01);                     // SW reset  
00164     wait_ms(5);
00165     wr_cmd(0x28);                     // display off  
00166 
00167     /* Start Initial Sequence ----------------------------------------------------*/
00168      wr_cmd(0xCF);                     
00169      SPI::write(0x00);
00170      SPI::write(0x83);
00171      SPI::write(0x30);
00172      _cs = 1;
00173      
00174      wr_cmd(0xED);                     
00175      SPI::write(0x64);
00176      SPI::write(0x03);
00177      SPI::write(0x12);
00178      SPI::write(0x81);
00179      _cs = 1;
00180      
00181      wr_cmd(0xE8);                     
00182      SPI::write(0x85);
00183      SPI::write(0x01);
00184      SPI::write(0x79);
00185      _cs = 1;
00186      
00187      wr_cmd(0xCB);                     
00188      SPI::write(0x39);
00189      SPI::write(0x2C);
00190      SPI::write(0x00);
00191      SPI::write(0x34);
00192      SPI::write(0x02);
00193      _cs = 1;
00194            
00195      wr_cmd(0xF7);                     
00196      SPI::write(0x20);
00197      _cs = 1;
00198            
00199      wr_cmd(0xEA);                     
00200      SPI::write(0x00);
00201      SPI::write(0x00);
00202      _cs = 1;
00203      
00204      wr_cmd(0xC0);                     // POWER_CONTROL_1
00205      SPI::write(0x26);
00206      _cs = 1;
00207  
00208      wr_cmd(0xC1);                     // POWER_CONTROL_2
00209      SPI::write(0x11);
00210      _cs = 1;
00211      
00212      wr_cmd(0xC5);                     // VCOM_CONTROL_1
00213      SPI::write(0x35);
00214      SPI::write(0x3E);
00215      _cs = 1;
00216      
00217      wr_cmd(0xC7);                     // VCOM_CONTROL_2
00218      SPI::write(0xBE);
00219      _cs = 1; 
00220      
00221      wr_cmd(0x36);                     // MEMORY_ACCESS_CONTROL
00222      SPI::write(0x48);
00223      _cs = 1; 
00224      
00225      wr_cmd(0x3A);                     // COLMOD_PIXEL_FORMAT_SET
00226      SPI::write(0x55);                 // 16 bit pixel 
00227      _cs = 1;
00228      
00229      wr_cmd(0xB1);                     // Frame Rate
00230      SPI::write(0x00);
00231      SPI::write(0x1B);               
00232      _cs = 1;
00233      
00234      wr_cmd(0xF2);                     // Gamma Function Disable
00235      SPI::write(0x08);
00236      _cs = 1; 
00237      
00238      wr_cmd(0x26);                     
00239      SPI::write(0x01);                 // gamma set for curve 01/2/04/08
00240      _cs = 1; 
00241      
00242      wr_cmd(0xE0);                     // positive gamma correction
00243      SPI::write(0x1F); 
00244      SPI::write(0x1A); 
00245      SPI::write(0x18); 
00246      SPI::write(0x0A); 
00247      SPI::write(0x0F); 
00248      SPI::write(0x06); 
00249      SPI::write(0x45); 
00250      SPI::write(0x87); 
00251      SPI::write(0x32); 
00252      SPI::write(0x0A); 
00253      SPI::write(0x07); 
00254      SPI::write(0x02); 
00255      SPI::write(0x07);
00256      SPI::write(0x05); 
00257      SPI::write(0x00);
00258      _cs = 1;
00259      
00260      wr_cmd(0xE1);                     // negativ gamma correction
00261      SPI::write(0x00); 
00262      SPI::write(0x25); 
00263      SPI::write(0x27); 
00264      SPI::write(0x05); 
00265      SPI::write(0x10); 
00266      SPI::write(0x09); 
00267      SPI::write(0x3A); 
00268      SPI::write(0x78); 
00269      SPI::write(0x4D); 
00270      SPI::write(0x05); 
00271      SPI::write(0x18); 
00272      SPI::write(0x0D); 
00273      SPI::write(0x38);
00274      SPI::write(0x3A); 
00275      SPI::write(0x1F);
00276      _cs = 1;
00277      
00278      WindowMax ();
00279      
00280      //wr_cmd(0x34);                     // tearing effect off
00281      //_cs = 1;
00282      
00283      //wr_cmd(0x35);                     // tearing effect on
00284      //_cs = 1;
00285       
00286      wr_cmd(0xB7);                       // entry mode
00287      SPI::write(0x07);
00288      _cs = 1;
00289      
00290      wr_cmd(0xB6);                       // display function control
00291      SPI::write(0x0A);
00292      SPI::write(0x82);
00293      SPI::write(0x27);
00294      SPI::write(0x00);
00295      _cs = 1;
00296      
00297      wr_cmd(0x11);                     // sleep out
00298      _cs = 1;
00299      
00300      wait_ms(100);
00301      
00302      wr_cmd(0x29);                     // display on
00303      _cs = 1;
00304      
00305      wait_ms(100);
00306      
00307  }
00308 
00309 
00310 void SPI_TFT_ILI9341::pixel(int x, int y, int color)
00311 {
00312     wr_cmd(0x2A);
00313     SPI::write(x >> 8);
00314     SPI::write(x);
00315     _cs = 1;
00316     wr_cmd(0x2B);
00317     SPI::write(y >> 8);
00318     SPI::write(y);
00319     _cs = 1;
00320     wr_cmd(0x2C);  // send pixel
00321     #if defined TARGET_KL25Z  // 8 Bit SPI
00322     SPI::write(color >> 8);
00323     SPI::write(color & 0xff);
00324     #else 
00325     SPI::format(16,3);                            // switch to 16 bit Mode 3
00326     SPI::write(color);                              // Write D0..D15
00327     SPI::format(8,3);
00328     #endif
00329     _cs = 1;
00330 }
00331 
00332 
00333 void SPI_TFT_ILI9341::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h)
00334 {
00335     wr_cmd(0x2A);
00336     SPI::write(x >> 8);
00337     SPI::write(x);
00338     SPI::write((x+w-1) >> 8);
00339     SPI::write(x+w-1);
00340     
00341     _cs = 1;
00342     wr_cmd(0x2B);
00343     SPI::write(y >> 8);
00344     SPI::write(y);
00345     SPI::write((y+h-1) >> 8);
00346     SPI::write(y+h-1);
00347     _cs = 1;
00348 }
00349 
00350 
00351 void SPI_TFT_ILI9341::WindowMax (void)
00352 {
00353     window (0, 0, width(),  height());
00354 }
00355 
00356 
00357 
00358 void SPI_TFT_ILI9341::cls (void)
00359 {
00360    // we can use the fillrect function 
00361    fillrect(0,0,width()-1,height()-1,_background);
00362 }
00363 
00364 
00365 void SPI_TFT_ILI9341::circle(int x0, int y0, int r, int color)
00366 {
00367 
00368     int x = -r, y = 0, err = 2-2*r, e2;
00369     do {
00370         pixel(x0-x, y0+y,color);
00371         pixel(x0+x, y0+y,color);
00372         pixel(x0+x, y0-y,color);
00373         pixel(x0-x, y0-y,color);
00374         e2 = err;
00375         if (e2 <= y) {
00376             err += ++y*2+1;
00377             if (-x == y && e2 <= x) e2 = 0;
00378         }
00379         if (e2 > x) err += ++x*2+1;
00380     } while (x <= 0);
00381 
00382 }
00383 
00384 void SPI_TFT_ILI9341::fillcircle(int x0, int y0, int r, int color)
00385 {
00386     int x = -r, y = 0, err = 2-2*r, e2;
00387     do {
00388         vline(x0-x, y0-y, y0+y, color);
00389         vline(x0+x, y0-y, y0+y, color);
00390         e2 = err;
00391         if (e2 <= y) {
00392             err += ++y*2+1;
00393             if (-x == y && e2 <= x) e2 = 0;
00394         }
00395         if (e2 > x) err += ++x*2+1;
00396     } while (x <= 0);
00397 }
00398 
00399 
00400 void SPI_TFT_ILI9341::hline(int x0, int x1, int y, int color)
00401 {
00402     int w;
00403     w = x1 - x0 + 1;
00404     window(x0,y,w,1);
00405     wr_cmd(0x2C);  // send pixel
00406     #if defined TARGET_KL25Z  // 8 Bit SPI
00407     int j;
00408     for (j=0; j<w; j++) {
00409         SPI::write(color >> 8);
00410         SPI::write(color & 0xff);
00411     } 
00412     #else 
00413     SPI::format(16,3);                            // switch to 16 bit Mode 3
00414     int j;
00415     for (j=0; j<w; j++) {
00416         SPI::write(color);
00417     }
00418     SPI::format(8,3);
00419     #endif
00420     _cs = 1;
00421     WindowMax();
00422     return;
00423 }
00424 
00425 void SPI_TFT_ILI9341::vline(int x, int y0, int y1, int color)
00426 {
00427     int h;
00428     h = y1 - y0 + 1;
00429     window(x,y0,1,h);
00430     wr_cmd(0x2C);  // send pixel
00431     #if defined TARGET_KL25Z  // 8 Bit SPI
00432     for (int y=0; y<h; y++) {
00433         SPI::write(color >> 8);
00434         SPI::write(color & 0xff);
00435     } 
00436     #else 
00437     SPI::format(16,3);                            // switch to 16 bit Mode 3
00438     for (int y=0; y<h; y++) {
00439         SPI::write(color);
00440     }
00441     SPI::format(8,3);
00442     #endif
00443     _cs = 1;
00444     WindowMax();
00445     return;
00446 }
00447 
00448 
00449 
00450 void SPI_TFT_ILI9341::line(int x0, int y0, int x1, int y1, int color)
00451 {
00452     //WindowMax();
00453     int   dx = 0, dy = 0;
00454     int   dx_sym = 0, dy_sym = 0;
00455     int   dx_x2 = 0, dy_x2 = 0;
00456     int   di = 0;
00457 
00458     dx = x1-x0;
00459     dy = y1-y0;
00460 
00461     if (dx == 0) {        /* vertical line */
00462         if (y1 > y0) vline(x0,y0,y1,color);
00463         else vline(x0,y1,y0,color);
00464         return;
00465     }
00466 
00467     if (dx > 0) {
00468         dx_sym = 1;
00469     } else {
00470         dx_sym = -1;
00471     }
00472     if (dy == 0) {        /* horizontal line */
00473         if (x1 > x0) hline(x0,x1,y0,color);
00474         else  hline(x1,x0,y0,color);
00475         return;
00476     }
00477 
00478     if (dy > 0) {
00479         dy_sym = 1;
00480     } else {
00481         dy_sym = -1;
00482     }
00483 
00484     dx = dx_sym*dx;
00485     dy = dy_sym*dy;
00486 
00487     dx_x2 = dx*2;
00488     dy_x2 = dy*2;
00489 
00490     if (dx >= dy) {
00491         di = dy_x2 - dx;
00492         while (x0 != x1) {
00493 
00494             pixel(x0, y0, color);
00495             x0 += dx_sym;
00496             if (di<0) {
00497                 di += dy_x2;
00498             } else {
00499                 di += dy_x2 - dx_x2;
00500                 y0 += dy_sym;
00501             }
00502         }
00503         pixel(x0, y0, color);
00504     } else {
00505         di = dx_x2 - dy;
00506         while (y0 != y1) {
00507             pixel(x0, y0, color);
00508             y0 += dy_sym;
00509             if (di < 0) {
00510                 di += dx_x2;
00511             } else {
00512                 di += dx_x2 - dy_x2;
00513                 x0 += dx_sym;
00514             }
00515         }
00516         pixel(x0, y0, color);
00517     }
00518     return;
00519 }
00520 
00521 
00522 void SPI_TFT_ILI9341::rect(int x0, int y0, int x1, int y1, int color)
00523 {
00524 
00525     if (x1 > x0) hline(x0,x1,y0,color);
00526     else  hline(x1,x0,y0,color);
00527 
00528     if (y1 > y0) vline(x0,y0,y1,color);
00529     else vline(x0,y1,y0,color);
00530 
00531     if (x1 > x0) hline(x0,x1,y1,color);
00532     else  hline(x1,x0,y1,color);
00533 
00534     if (y1 > y0) vline(x1,y0,y1,color);
00535     else vline(x1,y1,y0,color);
00536 
00537     return;
00538 }
00539 
00540 
00541 
00542 void SPI_TFT_ILI9341::fillrect(int x0, int y0, int x1, int y1, int color)
00543 {
00544 
00545     int h = y1 - y0 + 1;
00546     int w = x1 - x0 + 1;
00547     int pixel = h * w;
00548     window(x0,y0,w,h);
00549     wr_cmd(0x2C);  // send pixel 
00550     #if defined TARGET_KL25Z  // 8 Bit SPI
00551     for (int p=0; p<pixel; p++) {
00552         SPI::write(color >> 8);
00553         SPI::write(color & 0xff);
00554     }
00555    #else
00556     SPI::format(16,3);                            // switch to 16 bit Mode 3
00557     for (int p=0; p<pixel; p++) {
00558         SPI::write(color);
00559     }
00560     SPI::format(8,3);
00561     #endif
00562     _cs = 1;
00563     WindowMax();
00564     return;
00565 }
00566 
00567 
00568 void SPI_TFT_ILI9341::locate(int x, int y)
00569 {
00570     char_x = x;
00571     char_y = y;
00572 }
00573 
00574 
00575 
00576 int SPI_TFT_ILI9341::columns()
00577 {
00578     return width() / font[1];
00579 }
00580 
00581 
00582 
00583 int SPI_TFT_ILI9341::rows()
00584 {
00585     return height() / font[2];
00586 }
00587 
00588 
00589 
00590 int SPI_TFT_ILI9341::_putc(int value)
00591 {
00592     if (value == '\n') {    // new line
00593         char_x = 0;
00594         char_y = char_y + font[2];
00595         if (char_y >= height() - font[2]) {
00596             char_y = 0;
00597         }
00598     } else {
00599         character(char_x, char_y, value);
00600     }
00601     return value;
00602 }
00603 
00604 
00605 void SPI_TFT_ILI9341::character(int x, int y, int c)
00606 {
00607     unsigned int hor,vert,offset,bpl,j,i,b;
00608     unsigned char* zeichen;
00609     unsigned char z,w;
00610 
00611     if ((c < 31) || (c > 127)) return;   // test char range
00612 
00613     // read font parameter from start of array
00614     offset = font[0];                    // bytes / char
00615     hor = font[1];                       // get hor size of font
00616     vert = font[2];                      // get vert size of font
00617     bpl = font[3];                       // bytes per line
00618 
00619     if (char_x + hor > width()) {
00620         char_x = 0;
00621         char_y = char_y + vert;
00622         if (char_y >= height() - font[2]) {
00623             char_y = 0;
00624         }
00625     }
00626     window(char_x, char_y,hor,vert); // char box
00627     wr_cmd(0x2C);  // send pixel
00628     #ifndef TARGET_KL25Z  // 16 Bit SPI 
00629     SPI::format(16,3);   
00630     #endif                         // switch to 16 bit Mode 3
00631     zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap
00632     w = zeichen[0];                          // width of actual char
00633      for (j=0; j<vert; j++) {  //  vert line
00634         for (i=0; i<hor; i++) {   //  horz line
00635             z =  zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
00636             b = 1 << (j & 0x07);
00637             if (( z & b ) == 0x00) {
00638                #ifndef TARGET_KL25Z  // 16 Bit SPI 
00639                 SPI::write(_background);
00640                #else
00641                 SPI::write(_background >> 8);
00642                 SPI::write(_background & 0xff);
00643                 #endif
00644             } else {
00645                 #ifndef TARGET_KL25Z  // 16 Bit SPI
00646                 SPI::write(_foreground);
00647                 #else
00648                 SPI::write(_foreground >> 8);
00649                 SPI::write(_foreground & 0xff);
00650                 #endif
00651             }
00652         }
00653     }
00654     _cs = 1;
00655     #ifndef TARGET_KL25Z  // 16 Bit SPI
00656     SPI::format(8,3);
00657     #endif
00658     WindowMax();
00659     if ((w + 2) < hor) {                   // x offset to next char
00660         char_x += w + 2;
00661     } else char_x += hor;
00662 }
00663 
00664 
00665 void SPI_TFT_ILI9341::set_font(unsigned char* f)
00666 {
00667     font = f;
00668 }
00669 
00670 
00671 
00672 void SPI_TFT_ILI9341::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap)
00673 {
00674     unsigned int  j;
00675     int padd;
00676     unsigned short *bitmap_ptr = (unsigned short *)bitmap;
00677     #if defined TARGET_KL25Z  // 8 Bit SPI
00678         unsigned short pix_temp;
00679     #endif
00680     
00681     unsigned int i;
00682     
00683     // the lines are padded to multiple of 4 bytes in a bitmap
00684     padd = -1;
00685     do {
00686         padd ++;
00687     } while (2*(w + padd)%4 != 0);
00688     window(x, y, w, h);
00689     bitmap_ptr += ((h - 1)* (w + padd));
00690     wr_cmd(0x2C);  // send pixel
00691     #ifndef TARGET_KL25Z  // 16 Bit SPI 
00692     SPI::format(16,3);
00693     #endif                            // switch to 16 bit Mode 3
00694     for (j = 0; j < h; j++) {         //Lines
00695         for (i = 0; i < w; i++) {     // one line
00696             #if defined TARGET_KL25Z  // 8 Bit SPI
00697                 pix_temp = *bitmap_ptr;
00698                 SPI::write(pix_temp >> 8);
00699                 SPI::write(pix_temp);
00700                 bitmap_ptr++;
00701             #else
00702                 SPI::write(*bitmap_ptr);    // one line
00703                 bitmap_ptr++;
00704             #endif
00705         }
00706         bitmap_ptr -= 2*w;
00707         bitmap_ptr -= padd;
00708     }
00709     _cs = 1;
00710     #ifndef TARGET_KL25Z  // 16 Bit SPI 
00711     SPI::format(8,3);
00712     #endif
00713     WindowMax();
00714 }
00715 
00716 
00717 // local filesystem is not implemented in kinetis board , but you can add a SD card
00718 
00719 int SPI_TFT_ILI9341::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP)
00720 {
00721 
00722 #define OffsetPixelWidth    18
00723 #define OffsetPixelHeigh    22
00724 #define OffsetFileSize      34
00725 #define OffsetPixData       10
00726 #define OffsetBPP           28
00727 
00728     char filename[50];
00729     unsigned char BMP_Header[54];
00730     unsigned short BPP_t;
00731     unsigned int PixelWidth,PixelHeigh,start_data;
00732     unsigned int    i,off;
00733     int padd,j;
00734     unsigned short *line;
00735 
00736     // get the filename
00737     i=0;
00738     while (*Name_BMP!='\0') {
00739         filename[i++]=*Name_BMP++;
00740     }
00741     filename[i] = 0;  
00742     
00743     FILE *Image = fopen((const char *)&filename[0], "rb");  // open the bmp file
00744     if (!Image) {
00745         return(0);      // error file not found !
00746     }
00747 
00748     fread(&BMP_Header[0],1,54,Image);      // get the BMP Header
00749 
00750     if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) {  // check magic byte
00751         fclose(Image);
00752         return(-1);     // error no BMP file
00753     }
00754 
00755     BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8);
00756     if (BPP_t != 0x0010) {
00757         fclose(Image);
00758         return(-2);     // error no 16 bit BMP
00759     }
00760 
00761     PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24);
00762     PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24);
00763     if (PixelHeigh > height() + y || PixelWidth > width() + x) {
00764         fclose(Image);
00765         return(-3);      // to big
00766     }
00767 
00768     start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
00769 
00770     line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line
00771     if (line == NULL) {
00772         return(-4);         // error no memory
00773     }
00774 
00775     // the bmp lines are padded to multiple of 4 bytes
00776     padd = -1;
00777     do {
00778         padd ++;
00779     } while ((PixelWidth * 2 + padd)%4 != 0);
00780 
00781     window(x, y,PixelWidth ,PixelHeigh);
00782     wr_cmd(0x2C);  // send pixel
00783     #ifndef TARGET_KL25Z // only 8 Bit SPI 
00784     SPI::format(16,3);  
00785     #endif                          // switch to 16 bit Mode 3
00786     for (j = PixelHeigh - 1; j >= 0; j--) {               //Lines bottom up
00787         off = j * (PixelWidth  * 2 + padd) + start_data;   // start of line
00788         fseek(Image, off ,SEEK_SET);
00789         fread(line,1,PixelWidth * 2,Image);       // read a line - slow 
00790         for (i = 0; i < PixelWidth; i++) {        // copy pixel data to TFT
00791         #ifndef TARGET_KL25Z // only 8 Bit SPI
00792             SPI::write(line[i]);                  // one 16 bit pixel
00793         #else  
00794             SPI::write(line[i] >> 8);
00795             SPI::write(line[i]);
00796         #endif    
00797         } 
00798      }
00799     _cs = 1;
00800     SPI::format(8,3);
00801     free (line);
00802     fclose(Image);
00803     WindowMax();
00804     return(1);
00805 }
00806 
00807 #endif