A web server for monitoring and controlling a MakerBot Replicator over the USB host and ethernet.

Dependencies:   IAP NTPClient RTC mbed-rtos mbed Socket lwip-sys lwip BurstSPI

Fork of LPC1768_Mini-DK by Frank Vannieuwkerke

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPI_TFT_ILI9320.cpp Source File

SPI_TFT_ILI9320.cpp

00001 /**************************************************************************************************
00002  *****                                                                                        *****
00003  *****  Name: SPI_TFT.cpp                                                                     *****
00004  *****  Ver.: 1.0                                                                             *****
00005  *****  Date: 04/01/2013                                                                      *****
00006  *****  Auth: Frank Vannieuwkerke                                                             *****
00007  *****        Erik Olieman                                                                    *****
00008  *****  Func: library for 240*320 pixel TFT with ILI9320 LCD Controller                       *****
00009  *****                                                                                        *****
00010  *****  Rewrite from Peter Drescher code - http://mbed.org/cookbook/SPI-driven-QVGA-TFT       *****
00011  *****                                                                                        *****
00012  **************************************************************************************************/
00013 
00014 #include "SPI_TFT_ILI9320.h"
00015 #include "mbed.h"
00016 
00017 
00018 #define BPP         16                  // Bits per pixel
00019 
00020 
00021 SPI_TFT::SPI_TFT(PinName mosi, PinName miso, PinName sclk, PinName cs, const char *name)
00022     : GraphicsDisplay(name), _spi(mosi, miso, sclk), _cs(cs)
00023 {
00024     char_x = 0;
00025     tft_reset();
00026     set_orientation(0);
00027     backgroundimage = false;
00028     #ifndef NO_FLASH_BUFFER
00029     backgroundOrientation = 0;
00030     #endif
00031 }
00032 
00033 int SPI_TFT::width()
00034 {
00035     if (orientation == 0 || orientation == 2) return 240;
00036     else return 320;
00037 }
00038 
00039 int SPI_TFT::height()
00040 {
00041     if (orientation == 0 || orientation == 2) return 320;
00042     else return 240;
00043 }
00044 
00045 void SPI_TFT::set_orientation(unsigned int o)
00046 {
00047     orientation = o;
00048     WindowMax();
00049 }
00050 
00051 void SPI_TFT::mod_orientation(void)
00052 {
00053     switch (orientation) {
00054         case 0:
00055             wr_reg(0x03, 0x10b0);        // ID1 = 1, ID0 = 1, AM = 0 - Portrait
00056             break;
00057         case 1:
00058             wr_reg(0x03, 0x10a8);        // ID1 = 1, ID0 = 0, AM = 0 - Landscape
00059             break;
00060         case 2:
00061             wr_reg(0x03, 0x1080);        // ID1 = 0, ID0 = 0, AM = 1 - Portrait upside down
00062             break;
00063         case 3:
00064             wr_reg(0x03, 0x1098);        // ID1 = 0, ID0 = 1, AM = 1 - Landscape upside down
00065             break;
00066     }
00067 }
00068 
00069 void SPI_TFT::wr_cmd(unsigned char cmd)
00070 {
00071     _cs = 0;
00072     _spi.write(0x70);
00073     _spi.write(0x00);
00074     _spi.write(cmd);
00075     _cs = 1;
00076 }
00077 
00078 void SPI_TFT::wr_dat(unsigned short dat)
00079 {
00080     unsigned char u,l;
00081     u = (dat >> 0x08);
00082     l = (dat & 0xff);
00083     _cs = 0;
00084     _spi.write(0x72);
00085     _spi.write(u);
00086     _spi.write(l);
00087     _cs = 1;
00088 }
00089 
00090 void SPI_TFT::wr_dat_start(void)
00091 {
00092     _spi.write(0x72);
00093 }
00094 
00095 unsigned short SPI_TFT::rd_dat(void)              // IMPORTANT : SPI frequency needs to be lowered when reading
00096 {
00097     unsigned short val = 0;
00098     _cs = 0;
00099     _spi.frequency(SPI_F_LO);
00100     _spi.write(0x73);
00101     _spi.write(0x00);
00102     val = _spi.write(0x00);                          // Dummy read
00103     val = _spi.write(0x00);                          // Read D8..D15
00104     val <<= 8;
00105     val |= _spi.write(0x00);                         // Read D0..D7
00106     _cs = 1;
00107     _spi.frequency(SPI_F_HI);
00108     return (val);
00109 }
00110 
00111 void SPI_TFT::wr_reg(unsigned char reg, unsigned short val)
00112 {
00113     wr_cmd(reg);
00114     wr_dat(val);
00115 }
00116 
00117 unsigned short SPI_TFT::rd_reg(unsigned char reg)
00118 {
00119     wr_cmd(reg);
00120     return(rd_dat());
00121 }
00122 
00123 unsigned short SPI_TFT::Read_ID(void)             // IMPORTANT : SPI frequency needs to be lowered when reading
00124 {
00125     unsigned short val = 0;
00126     _cs = 0;
00127     _spi.write(0x70);
00128     _spi.write(0x00);
00129     _spi.write(0x00);
00130     _cs = 1;
00131     _spi.frequency(SPI_F_LO);
00132     _cs = 0;
00133     _spi.write(0x73);
00134     val = _spi.write(0x00);                       // Dummy read
00135     val = _spi.write(0x00);                       // Read D8..D15
00136     val <<= 8;
00137     val |= _spi.write(0x00);                      // Read D0..D7
00138     _cs = 1;
00139     _spi.frequency(SPI_F_HI);
00140     return (val);
00141 }
00142 
00143 void SPI_TFT::SetCursor( unsigned short Xpos, unsigned short Ypos )
00144 {
00145     wr_reg(0x20, Xpos );
00146     wr_reg(0x21, Ypos );
00147 }
00148 
00149 void SPI_TFT::tft_reset()
00150 {
00151     _spi.format(8,3);                                   // 8 bit spi mode 3
00152     _spi.frequency(SPI_F_HI);                           // 48 Mhz SPI clock
00153 
00154     wr_reg(0x00,0x0000);
00155     wr_reg(0x01,0x0100);                                // Driver Output Control
00156     wr_reg(0x02,0x0700);                                // LCD Driver Waveform Control
00157     wr_reg(0x03,0x1030);                                // Set the scan mode
00158     wr_reg(0x04,0x0000);                                // Scaling Control
00159     wr_reg(0x08,0x0202);                                // Display Control 2
00160     wr_reg(0x09,0x0000);                                // Display Control 3
00161     wr_reg(0x0a,0x0000);                                // Frame Cycle Contal
00162     wr_reg(0x0c,(1<<0));                                // Extern Display Interface Control 1
00163     wr_reg(0x0d,0x0000);                                // Frame Maker Position
00164     wr_reg(0x0f,0x0000);                                // Extern Display Interface Control 2
00165 
00166     wait_ms(50);
00167 
00168     wr_reg(0x07,0x0101);                                // Display Control
00169 
00170     wait_ms(50);
00171 
00172     wr_reg(0x10,(1<<12)|(0<<8)|(1<<7)|(1<<6)|(0<<4));   // Power Control 1
00173     wr_reg(0x11,0x0007);                                // Power Control 2
00174     wr_reg(0x12,(1<<8)|(1<<4)|(0<<0));                  // Power Control 3
00175     wr_reg(0x13,0x0b00);                                // Power Control 4
00176     wr_reg(0x29,0x0000);                                // Power Control 7
00177     wr_reg(0x2b,(1<<14)|(1<<4));
00178 
00179     wr_reg(0x50,0);                                     // Set X Start
00180     wr_reg(0x51,239);                                   // Set X End
00181     wr_reg(0x52,0);                                     // Set Y Start
00182     wr_reg(0x53,319);                                   // Set Y End
00183 
00184     wait_ms(50);
00185 
00186     wr_reg(0x60,0x2700);                                // Driver Output Control
00187     wr_reg(0x61,0x0001);                                // Driver Output Control
00188     wr_reg(0x6a,0x0000);                                // Vertical Srcoll Control
00189 
00190     wr_reg(0x80,0x0000);                                // Display Position Partial Display 1
00191     wr_reg(0x81,0x0000);                                // RAM Address Start Partial Display 1
00192     wr_reg(0x82,0x0000);                                // RAM Address End-Partial Display 1
00193     wr_reg(0x83,0x0000);                                // Displsy Position Partial Display 2
00194     wr_reg(0x84,0x0000);                                // RAM Address Start Partial Display 2
00195     wr_reg(0x85,0x0000);                                // RAM Address End Partial Display 2
00196 
00197     wr_reg(0x90,(0<<7)|(16<<0));                        // Frame Cycle Control
00198     wr_reg(0x92,0x0000);                                // Panel Interface Control 2
00199     wr_reg(0x93,0x0001);                                // Panel Interface Control 3
00200     wr_reg(0x95,0x0110);                                // Frame Cycle Control
00201     wr_reg(0x97,(0<<8));
00202     wr_reg(0x98,0x0000);                                // Frame Cycle Control
00203     wr_reg(0x07,0x0133);
00204 
00205     wait_ms(100);
00206     WindowMax();
00207 }
00208 
00209 
00210 void SPI_TFT::pixel(int x, int y, int color)
00211 {
00212     switch (orientation) {
00213         case 0:
00214             wr_reg(0x20, x);
00215             wr_reg(0x21, y);
00216             break;
00217         case 1:
00218             wr_reg(0x20, 239-y);
00219             wr_reg(0x21, x);
00220             break;
00221         case 2:
00222             wr_reg(0x20, 239-x);
00223             wr_reg(0x21, 319-y);
00224             break;
00225         case 3:
00226             wr_reg(0x20, y);
00227             wr_reg(0x21, 319-x);
00228             break;
00229     }
00230     wr_cmd(0x22);
00231     wr_dat(color);
00232 }
00233 
00234 
00235 void SPI_TFT::window(int x, int y, int w, int h)
00236 {
00237     unsigned int xw1, yh1;
00238     xw1 = x + w - 1;
00239     yh1 = y + h - 1;
00240     wr_reg(0x20, x);
00241     wr_reg(0x21, y);
00242     switch (orientation) {
00243         case 0:
00244             wr_reg(0x50, x);
00245             wr_reg(0x51, xw1);
00246             wr_reg(0x52, y);
00247             wr_reg(0x53, yh1);
00248             break;
00249         case 1:
00250             wr_reg(0x50, 239 - yh1);
00251             wr_reg(0x51, 239 - y);
00252             wr_reg(0x52, x);
00253             wr_reg(0x53, xw1);
00254             break;
00255         case 2:
00256             wr_reg(0x50, 239 - xw1);
00257             wr_reg(0x51, 239 - x);
00258             wr_reg(0x52, 319 - yh1);
00259             wr_reg(0x53, 319 - y);
00260             break;
00261         case 3:
00262             wr_reg(0x50, y);
00263             wr_reg(0x51, yh1);
00264             wr_reg(0x52, 319 - xw1);
00265             wr_reg(0x53, 319 - x);
00266             break;
00267     }
00268 }
00269 
00270 
00271 void SPI_TFT::WindowMax(void)
00272 {
00273     window(0, 0, width(),  height());
00274 }
00275 
00276 
00277 void SPI_TFT::cls (void)
00278 {
00279     if (backgroundimage == false) {
00280     unsigned long int index=0;
00281     wr_reg(0x03, 0x1030);
00282     WindowMax();
00283     SetCursor(0,0);
00284     wr_cmd(0x22);
00285     _cs = 0;
00286     wr_dat_start();
00287     _spi.format(16,3);
00288     int num = width()*height();
00289 
00290     for( index = 0; index<num; index++ ) {
00291         _spi.fastWrite(_background);
00292     }
00293     _spi.clearRX();
00294 
00295     _spi.format(8,3);
00296     _cs = 1;
00297     }
00298     #ifndef NO_FLASH_BUFFER
00299     else {
00300         int _orientation=orientation;
00301         set_orientation(backgroundOrientation);
00302         Bitmap(0,0,width(),height(),(unsigned char*) sector_start_adress[ 25 ]);
00303         set_orientation(_orientation);
00304         }
00305     #endif
00306 }
00307 
00308 void SPI_TFT::hline(int x0, int x1, int y, int color)
00309 {
00310     unsigned int index=0;
00311     int w;
00312     w = x1 - x0 + 1;
00313     mod_orientation();
00314     window(x0,y,w,1);
00315     wr_cmd(0x22);
00316     _cs = 0;
00317     wr_dat_start();
00318 
00319     _spi.format(16,3);
00320     int num = x1-x0;
00321     for( index = 0; index<num; index++ ) {
00322         _spi.fastWrite(color);
00323     }
00324     _spi.clearRX();
00325 
00326     _spi.format(8,3);
00327     _cs = 1;
00328     return;
00329 }
00330 
00331 void SPI_TFT::vline(int x, int y0, int y1, int color)
00332 {
00333     unsigned int index=0;
00334     int h;
00335     h = y1 - y0 + 1;
00336     mod_orientation();
00337     window(x,y0,1,h);
00338     wr_cmd(0x22);
00339     _cs = 0;
00340     wr_dat_start();
00341     _spi.format(16,3);
00342     int num = y1-y0;
00343     for( index = 0; index<num; index++ ) {
00344         _spi.fastWrite(color);
00345     }
00346     _spi.clearRX();
00347     _spi.format(8,3);
00348     _cs = 1;
00349     return;
00350 }
00351 
00352 void SPI_TFT::line(int x0, int y0, int x1, int y1, int color)
00353 {
00354     wr_reg(0x03, 0x1030);
00355     WindowMax();
00356     int   dx = 0, dy = 0;
00357     int   dx_sym = 0, dy_sym = 0;
00358     int   dx_x2 = 0, dy_x2 = 0;
00359     int   di = 0;
00360 
00361     dx = x1-x0;
00362     dy = y1-y0;
00363 
00364     if (dx == 0) {                          // vertical line
00365         if (y1 > y0) vline(x0,y0,y1,color);
00366         else vline(x0,y1,y0,color);
00367         return;
00368     }
00369 
00370     if (dx > 0) {
00371         dx_sym = 1;
00372     } else {
00373         dx_sym = -1;
00374     }
00375     if (dy == 0) {                          // horizontal line
00376         if (x1 > x0) hline(x0,x1,y0,color);
00377         else  hline(x1,x0,y0,color);
00378         return;
00379     }
00380 
00381     if (dy > 0) {
00382         dy_sym = 1;
00383     } else {
00384         dy_sym = -1;
00385     }
00386 
00387     dx = dx_sym*dx;
00388     dy = dy_sym*dy;
00389 
00390     dx_x2 = dx*2;
00391     dy_x2 = dy*2;
00392 
00393     if (dx >= dy) {
00394         di = dy_x2 - dx;
00395         while (x0 != x1) {
00396 
00397             pixel(x0, y0, color);
00398             x0 += dx_sym;
00399             if (di<0) {
00400                 di += dy_x2;
00401             } else {
00402                 di += dy_x2 - dx_x2;
00403                 y0 += dy_sym;
00404             }
00405         }
00406         pixel(x0, y0, color);
00407     } else {
00408         di = dx_x2 - dy;
00409         while (y0 != y1) {
00410             pixel(x0, y0, color);
00411             y0 += dy_sym;
00412             if (di < 0) {
00413                 di += dx_x2;
00414             } else {
00415                 di += dx_x2 - dy_x2;
00416                 x0 += dx_sym;
00417             }
00418         }
00419         pixel(x0, y0, color);
00420     }
00421     return;
00422 }
00423 
00424 
00425 void SPI_TFT::rect(int x0, int y0, int w, int h, int color)
00426 {
00427     hline(x0,x0+w,y0,color);
00428     vline(x0,y0,y0+h,color);
00429     hline(x0,x0+w,y0+h,color);
00430     vline(x0+w,y0,y0+h,color);
00431 
00432     return;
00433 }
00434 
00435 void SPI_TFT::fillrect(int x0, int y0, int w, int h, int color)
00436 {
00437     unsigned long int index=0;
00438     if (w < 0) {
00439         x0 = x0 + w;
00440         w = -w;
00441     }
00442     if (h < 0) {
00443         y0 = y0 + h;
00444         h = -h;
00445     }
00446     mod_orientation();
00447     window(x0,y0,w,h);
00448     wr_cmd(0x22);
00449     _cs = 0;
00450     wr_dat_start();
00451     _spi.format(16,3);
00452     int num = h*w;
00453     for( index = 0; index<num; index++ ) {
00454         _spi.fastWrite(color);
00455     }
00456     _spi.clearRX();
00457     _spi.format(8,3);
00458     _cs = 1;
00459     return;
00460 }
00461 
00462 void SPI_TFT::draw_ellipse(int xc, int yc, int a, int b, unsigned int color)
00463 {
00464     /* e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 */
00465     wr_reg(0x03, 0x1030);
00466     WindowMax();
00467     int x = 0, y = b;
00468     long a2 = (long)a*a, b2 = (long)b*b;
00469     long crit1 = -(a2/4 + a%2 + b2);
00470     long crit2 = -(b2/4 + b%2 + a2);
00471     long crit3 = -(b2/4 + b%2);
00472     long t = -a2*y;                         // e(x+1/2,y-1/2) - (a^2+b^2)/4
00473     long dxt = 2*b2*x, dyt = -2*a2*y;
00474     long d2xt = 2*b2, d2yt = 2*a2;
00475 
00476     while (y>=0 && x<=a) {
00477         pixel(xc+x, yc+y, color);
00478         if (x!=0 || y!=0)
00479             pixel(xc-x, yc-y, color);
00480         if (x!=0 && y!=0) {
00481             pixel(xc+x, yc-y, color);
00482             pixel(xc-x, yc+y, color);
00483         }
00484         if (t + b2*x <= crit1 ||            // e(x+1,y-1/2) <= 0
00485                 t + a2*y <= crit3)          // e(x+1/2,y) <= 0
00486             incx();
00487         else if (t - a2*y > crit2)          // e(x+1/2,y-1) > 0
00488             incy();
00489         else {
00490             incx();
00491             incy();
00492         }
00493     }
00494 }
00495 
00496 void SPI_TFT::fill_ellipse(int xc, int yc, int a, int b, unsigned int color)
00497 {
00498     /* e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 */
00499     int x = 0, y = b;
00500     int rx = x, ry = y;
00501     unsigned int width = 1;
00502     unsigned int height = 1;
00503     long a2 = (long)a*a, b2 = (long)b*b;
00504     long crit1 = -(a2/4 + a%2 + b2);
00505     long crit2 = -(b2/4 + b%2 + a2);
00506     long crit3 = -(b2/4 + b%2);
00507     long t = -a2*y;                         // e(x+1/2,y-1/2) - (a^2+b^2)/4
00508     long dxt = 2*b2*x, dyt = -2*a2*y;
00509     long d2xt = 2*b2, d2yt = 2*a2;
00510 
00511     if (b == 0) {
00512         fillrect(xc-a, yc, 2*a+1, 1, color);
00513         return;
00514     }
00515 
00516     while (y>=0 && x<=a) {
00517         if (t + b2*x <= crit1 ||            // e(x+1,y-1/2) <= 0
00518                 t + a2*y <= crit3) {        // e(x+1/2,y) <= 0
00519             if (height == 1)
00520                 ;                           // draw nothing
00521             else if (ry*2+1 > (height-1)*2) {
00522                 fillrect(xc-rx, yc-ry, width, height-1, color);
00523                 fillrect(xc-rx, yc+ry+1, width, 1-height, color);
00524                 ry -= height-1;
00525                 height = 1;
00526             } else {
00527                 fillrect(xc-rx, yc-ry, width, ry*2+1, color);
00528                 ry -= ry;
00529                 height = 1;
00530             }
00531             incx();
00532             rx++;
00533             width += 2;
00534         } else if (t - a2*y > crit2) {      // e(x+1/2,y-1) > 0
00535             incy();
00536             height++;
00537         } else {
00538             if (ry*2+1 > height*2) {
00539                 fillrect(xc-rx, yc-ry, width, height, color);
00540                 fillrect(xc-rx, yc+ry+1, width, -height, color);
00541             } else {
00542                 fillrect(xc-rx, yc-ry, width, ry*2+1, color);
00543             }
00544             incx();
00545             incy();
00546             rx++;
00547             width += 2;
00548             ry -= height;
00549             height = 1;
00550         }
00551     }
00552 
00553     if (ry > height) {
00554         fillrect(xc-rx, yc-ry, width, height, color);
00555         fillrect(xc-rx, yc+ry+1, width, -height, color);
00556     } else {
00557         fillrect(xc-rx, yc-ry, width, ry*2+1, color);
00558     }
00559 }
00560 
00561 
00562 void SPI_TFT::locate(int x, int y)
00563 {
00564     char_x = x;
00565     char_y = y;
00566 }
00567 
00568 int SPI_TFT::columns()
00569 {
00570     return width() / font[1];
00571 }
00572 
00573 int SPI_TFT::rows()
00574 {
00575     return height() / font[2];
00576 }
00577 
00578 int SPI_TFT::_putc(int value)
00579 {
00580     if (value == '\n') {                    // new line
00581         char_x = 0;
00582         char_y = char_y + font[2];
00583         if (char_y >= height() - font[2]) {
00584             char_y = 0;
00585         }
00586     } else {
00587         character(char_x, char_y, value);
00588     }
00589     return value;
00590 }
00591 
00592 void SPI_TFT::character(int x, int y, int c)
00593 {
00594     unsigned int hor,vert,offset,bpl,j,i,b;
00595     unsigned char* bitmap_char;
00596     unsigned char z,w;
00597 
00598     if ((c < 31) || (c > 127)) return;      // test char range
00599 
00600     // read font parameter from start of array
00601     offset = font[0];                       // bytes / char
00602     hor = font[1];                          // get hor size of font
00603     vert = font[2];                         // get vert size of font
00604     bpl = font[3];                          // bytes per line
00605 
00606     if (char_x + hor > width()) {
00607         char_x = 0;
00608         char_y = char_y + vert;
00609         if (char_y >= height() - font[2]) {
00610             char_y = 0;
00611         }
00612     }
00613     mod_orientation();
00614 
00615     bitmap_char = &font[((c -32) * offset) + 4];    // start of char bitmap
00616     w = bitmap_char[0];                             // width of actual char
00617     window(char_x, char_y,hor,vert); // char box
00618     wr_cmd(0x22);
00619     _cs = 0;
00620     wr_dat_start();
00621     _spi.format(16,3);
00622     for (j=0; j<vert; j++) {                        //  vert line
00623         for (i=0; i<hor; i++) {                       //  horz line
00624             z =  bitmap_char[bpl * i + ((j & 0xF8) >> 3)+1];
00625             b = 1 << (j & 0x07);
00626             if (( z & b ) == 0x00) {
00627                 #ifndef NO_FLASH_BUFFER
00628                 if (backgroundimage==false)
00629                 #endif
00630                     _spi.fastWrite(_background);
00631                 #ifndef NO_FLASH_BUFFER
00632                 else
00633                 {
00634                     unsigned short *bitmap_ptr = (unsigned short *)sector_start_adress[ 25 ];
00635                     int angle = (orientation - backgroundOrientation)%4; //Get the difference in orientation between background and current
00636                     switch (angle) {
00637                         case 0:         //Same orientation
00638                             bitmap_ptr += width() * (height()-(y+j+1))+x+i;
00639                         break;
00640                         case 1:         //Rotated 1 (don't ask me which direction)
00641                             bitmap_ptr += height() * (width()-(x+i+1))+height()-(y+j + 1);
00642                         break;
00643                         case 2:         //Upside down
00644                             bitmap_ptr += width() * (y+j)+width() - (x+i + 1);
00645                         break; 
00646                         case 3:         //Rotated 3
00647                             bitmap_ptr += height() * (x+i)+y+j;                            
00648                         break;
00649                         default:
00650                         break;
00651                     }
00652                     
00653                     _spi.fastWrite(*bitmap_ptr);
00654                 }
00655                 #endif    
00656             } else {
00657                 _spi.fastWrite(_foreground);
00658             }
00659         }
00660     }
00661     _spi.clearRX();
00662     _spi.format(8,3);
00663     _cs = 1;
00664     if ((w + 2) < hor) {                 // x offset to next char
00665         char_x += w + 2;
00666     } else char_x += hor;
00667 }
00668 
00669 void SPI_TFT::set_font(unsigned char* f)
00670 {
00671     font = f;
00672 }
00673 
00674 
00675 void SPI_TFT::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap)
00676 {
00677     unsigned int    i,j;
00678     unsigned short *bitmap_ptr = (unsigned short *)bitmap;
00679     mod_orientation();
00680     window(x, y, w, h);
00681     wr_cmd(0x22);
00682     _cs = 0;
00683     wr_dat_start();
00684     _spi.format(16,3);
00685     bitmap_ptr += ((h - 1)*w);
00686     for (j = 0; j < h; j++) {               //Lines
00687         for (i = 0; i < w; i++) {           // copy pixel data to TFT
00688             _spi.fastWrite(*bitmap_ptr);    // one line
00689             bitmap_ptr++;
00690         }
00691         bitmap_ptr -= 2*w;
00692     }
00693     _spi.clearRX();
00694     _spi.format(8,3);
00695     _cs = 1;
00696 }
00697 
00698 int SPI_TFT::Bitmap(unsigned int x, unsigned int y, const char *Name_BMP)
00699 {
00700     #define RGB565CONVERT(red, green, blue) (uint16_t)( (( red   >> 3 ) << 11 ) | (( green >> 2 ) << 5  ) | ( blue  >> 3 ))
00701     mod_orientation();
00702     
00703     bitmapData bmp = getBitmapData(Name_BMP);
00704     if (bmp.return_code != 1)
00705         return bmp.return_code;
00706     
00707 
00708     unsigned char *line = (unsigned char *) malloc (bmp.bits/8 * bmp.width);    // we need a buffer for a line
00709     unsigned short *line_short = (unsigned short*) (line);                      // Same one, addressed as short
00710 
00711 
00712     if ((bmp.height > height()+y) || (bmp.width > width()+x))
00713         return -3;          //Size mismatch
00714 
00715     if (line == NULL)
00716         return(-4);         // error no memory
00717 
00718 
00719     for (int j = bmp.height-1; j >= 0; j--) {                                   //Lines bottom up
00720         int off = j * (bmp.width  * bmp.bits/8 + bmp.pad) + bmp.start_data;     // start of line
00721         fseek(bmp.file, off ,SEEK_SET);
00722         fread(line,1,bmp.width * bmp.bits/8,bmp.file);                          // read a line - slow !
00723         
00724         //If 24 bit format, convert to 565
00725         if (bmp.bits == 24) {
00726             for (int i = 0; i<bmp.width; i++) {
00727                 line_short[i] = RGB565CONVERT(line[3*i+2], line[3*i+1], line[3*i]);
00728             }
00729         }
00730 
00731         window(x, y+bmp.height - 1 - j,bmp.width ,1);
00732         wr_cmd(0x22);
00733 
00734         _cs = 0;
00735         wr_dat_start();
00736         _spi.format(16, 3);
00737         _spi.setFormat();
00738 
00739         for (int i = 0; i < bmp.width; i++) {       // copy pixel data to TFT
00740             _spi.fastWrite(line_short[i]);          // one line
00741         }
00742 
00743         _spi.clearRX();
00744         _spi.format(8,3);
00745         _cs = 1;
00746 
00747     }
00748 
00749 
00750     free (line);
00751     fclose(bmp.file);
00752     WindowMax();
00753 
00754     return(1);
00755 }
00756 
00757 #ifndef NO_FLASH_BUFFER
00758 
00759 int SPI_TFT::fileToFlash(const char *Name_BMP)
00760 {
00761     #define RGB565CONVERT(red, green, blue) (uint16_t)( (( red   >> 3 ) << 11 ) | (( green >> 2 ) << 5  ) | ( blue  >> 3 ))
00762    
00763     mod_orientation();
00764     
00765     bitmapData bmp = getBitmapData(Name_BMP);
00766     if (bmp.return_code != 1)
00767         return bmp.return_code;
00768     
00769 
00770     unsigned char *line = (unsigned char *) malloc (bmp.bits/8 * bmp.width);    // we need a buffer for a line
00771     unsigned short *line_short = (unsigned short*) (line);                      // Same one, addressed as short
00772 
00773     unsigned short *flashSector = (unsigned short *) malloc (256);              //And one to send to flash
00774 
00775     if ((bmp.height != height()) || (bmp.width != width()))
00776         return -3;          //Size mismatch
00777 
00778     if ((line == NULL) || (flashSector == NULL))
00779         return(-4);         // error no memory
00780     
00781 
00782     int flashPointer = 0, flashWrites = 0;
00783 
00784     //Erase Flash that will be used:
00785     if ( iap.blank_check( 25, 29 ) == SECTOR_NOT_BLANK ) {
00786         iap.prepare( 25, 29 );
00787         iap.erase( 25, 29 );
00788     }
00789 
00790     for (int j = 0; j < bmp.height; j++) {                                      //Lines bottom up
00791         int off = j * (bmp.width  * bmp.bits/8 + bmp.pad) + bmp.start_data;     // start of line
00792         fseek(bmp.file, off ,SEEK_SET);
00793         fread(line,1,bmp.width * bmp.bits/8,bmp.file);                          // read a line - slow !
00794 
00795         //If 24 bit format, do some processing
00796         if (bmp.bits == 24) {
00797             for (int i = 0; i<bmp.width; i++) {
00798                 line_short[i] = RGB565CONVERT(line[3*i+2], line[3*i+1], line[3*i]);
00799             }
00800         }
00801 
00802 
00803         for (int i = 0; i < bmp.width; i++) {               // copy pixel data to TFT
00804             flashSector[flashPointer] = line_short[i];      // one line
00805             flashPointer++;
00806 
00807             //If flashpointer reached the end, write to flash
00808             if (flashPointer == 128) {
00809                 iap.prepare( 25, 29 );
00810                 iap.write((char *)flashSector, sector_start_adress[ 25 ] + 256 * flashWrites, 256);
00811                 flashPointer = 0;
00812                 flashWrites++;
00813                 if (flashWrites == 1000)
00814                     error("Too many flashwrites");
00815             }
00816         }
00817     }
00818     //write remaining data
00819     if (flashPointer!=0) {
00820         iap.prepare( 25, 29 );
00821         iap.write((char*)flashSector, sector_start_adress[ 25 ] + 256 * flashWrites, 256);
00822         flashPointer = 0;
00823         flashWrites++;
00824         if (flashWrites == 1000)
00825             error("Too many flashwrites");
00826     }
00827 
00828 
00829 
00830     free (line);
00831     fclose(bmp.file);
00832     backgroundImage(true);
00833     backgroundOrientation = orientation;
00834     return(1);
00835 }
00836 
00837 void SPI_TFT::backgroundImage( bool active) {
00838     backgroundimage = active;
00839 }
00840 #endif
00841 
00842 
00843 SPI_TFT::bitmapData SPI_TFT::getBitmapData(const char *Name_BMP){
00844     #define OffsetPixelWidth    18
00845     #define OffsetPixelHeigh    22
00846     #define OffsetFileSize      34
00847     #define OffsetPixData       10
00848     #define OffsetBPP           28
00849     
00850 
00851     bitmapData retval;
00852     retval.return_code = 1;
00853     unsigned char BMP_Header[54];
00854 
00855     retval.file = fopen(Name_BMP, "rb");                    // open the bmp file
00856     if (!retval.file) {
00857         retval.return_code = 0;
00858         return(retval);                                     // error file not found !
00859     }
00860 
00861     fread(&BMP_Header[0],1,54,retval.file);                 // get the BMP Header
00862 
00863     if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) {   // check magic byte
00864         fclose(retval.file);
00865         retval.return_code = -1;
00866         return(retval);                                     // error not a BMP file
00867     }
00868 
00869     int BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8);
00870     if (BPP_t == 0x0010)
00871         retval.bits = 16;
00872     else if (BPP_t == 0x0018)
00873         retval.bits = 24;
00874     else {
00875         fclose(retval.file);
00876         retval.return_code = -2;
00877         return(retval);                                     // error no 16/24 bit BMP
00878     }
00879 
00880     retval.height = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24);
00881     retval.width = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24);
00882     if (retval.height > height()|| retval.width > width()) {
00883         fclose(retval.file);
00884         retval.return_code = -3;
00885         return(retval);                                     // too big
00886     }
00887 
00888 
00889     retval.start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
00890 
00891     // the bmp lines are padded to multiple of 4 bytes
00892     retval.pad = -1;
00893     do {
00894         retval.pad ++;
00895     } while ((retval.width * retval.bits/8 + retval.pad)%4 != 0);
00896     return retval;
00897 
00898 }