SPI Library for 240x320 TFT LCD with ILI9320, ILI9325 and ILI9328 chip

Dependencies:   BurstSPI

Dependents:   KL25Z_ILI9320_Demo Mini-DK

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     uint16_t DeviceID;
00152     _spi.format(8,3);                                   // 8 bit spi mode 3
00153     DeviceID = Read_ID();
00154     _spi.frequency(SPI_F_HI);                           // 48 Mhz SPI clock
00155     if(DeviceID == 0x9320 || DeviceID == 0x9300)
00156     {
00157         wr_reg(0x00,0x0000);
00158         wr_reg(0x01,0x0100);                                // Driver Output Control
00159         wr_reg(0x02,0x0700);                                // LCD Driver Waveform Control
00160         wr_reg(0x03,0x1030);                                // Set the scan mode
00161         wr_reg(0x04,0x0000);                                // Scaling Control
00162         wr_reg(0x08,0x0202);                                // Display Control 2
00163         wr_reg(0x09,0x0000);                                // Display Control 3
00164         wr_reg(0x0a,0x0000);                                // Frame Cycle Contal
00165         wr_reg(0x0c,(1<<0));                                // Extern Display Interface Control 1
00166         wr_reg(0x0d,0x0000);                                // Frame Maker Position
00167         wr_reg(0x0f,0x0000);                                // Extern Display Interface Control 2
00168 
00169         wait_ms(50);
00170 
00171         wr_reg(0x07,0x0101);                                // Display Control
00172 
00173         wait_ms(50);
00174 
00175         wr_reg(0x10,(1<<12)|(0<<8)|(1<<7)|(1<<6)|(0<<4));   // Power Control 1
00176         wr_reg(0x11,0x0007);                                // Power Control 2
00177         wr_reg(0x12,(1<<8)|(1<<4)|(0<<0));                  // Power Control 3
00178         wr_reg(0x13,0x0b00);                                // Power Control 4
00179         wr_reg(0x29,0x0000);                                // Power Control 7
00180         wr_reg(0x2b,(1<<14)|(1<<4));
00181 
00182         wr_reg(0x50,0);                                     // Set X Start
00183         wr_reg(0x51,239);                                   // Set X End
00184         wr_reg(0x52,0);                                     // Set Y Start
00185         wr_reg(0x53,319);                                   // Set Y End
00186 
00187         wait_ms(50);
00188 
00189         wr_reg(0x60,0x2700);                                // Driver Output Control
00190         wr_reg(0x61,0x0001);                                // Driver Output Control
00191         wr_reg(0x6a,0x0000);                                // Vertical Srcoll Control
00192 
00193         wr_reg(0x80,0x0000);                                // Display Position Partial Display 1
00194         wr_reg(0x81,0x0000);                                // RAM Address Start Partial Display 1
00195         wr_reg(0x82,0x0000);                                // RAM Address End-Partial Display 1
00196         wr_reg(0x83,0x0000);                                // Displsy Position Partial Display 2
00197         wr_reg(0x84,0x0000);                                // RAM Address Start Partial Display 2
00198         wr_reg(0x85,0x0000);                                // RAM Address End Partial Display 2
00199 
00200         wr_reg(0x90,(0<<7)|(16<<0));                        // Frame Cycle Control
00201         wr_reg(0x92,0x0000);                                // Panel Interface Control 2
00202         wr_reg(0x93,0x0001);                                // Panel Interface Control 3
00203         wr_reg(0x95,0x0110);                                // Frame Cycle Control
00204         wr_reg(0x97,(0<<8));
00205         wr_reg(0x98,0x0000);                                // Frame Cycle Control
00206         wr_reg(0x07,0x0133);
00207     }
00208     if(DeviceID == 0x9325 || DeviceID == 0x9328)  
00209     {
00210         wr_reg(0xe7,0x0010);      
00211         wr_reg(0x00,0x0001);                                // start internal osc
00212         wr_reg(0x01,0x0100);     
00213         wr_reg(0x02,0x0700);                                // power on sequence
00214         wr_reg(0x03,(1<<12)|(1<<5)|(1<<4)|(0<<3) );         // importance
00215         wr_reg(0x04,0x0000);                                   
00216         wr_reg(0x08,0x0207);               
00217         wr_reg(0x09,0x0000);         
00218         wr_reg(0x0a,0x0000);                                // display setting
00219         wr_reg(0x0c,0x0001);                                // display setting
00220         wr_reg(0x0d,0x0000);                    
00221         wr_reg(0x0f,0x0000);
00222         wr_reg(0x10,0x0000);                                // Power On sequence
00223         wr_reg(0x11,0x0007);
00224         wr_reg(0x12,0x0000);                                                                 
00225         wr_reg(0x13,0x0000);                 
00226 
00227         wait_ms(50);
00228 
00229         wr_reg(0x10,0x1590);   
00230         wr_reg(0x11,0x0227);
00231 
00232         wait_ms(50);
00233 
00234         wr_reg(0x12,0x009c);                  
00235 
00236         wait_ms(50);
00237 
00238         wr_reg(0x13,0x1900);   
00239         wr_reg(0x29,0x0023);
00240         wr_reg(0x2b,0x000e);
00241 
00242         wait_ms(50);
00243 
00244         wr_reg(0x20,0x0000);                                                            
00245         wr_reg(0x21,0x0000);           
00246 
00247         wait_ms(50);
00248 
00249         wr_reg(0x30,0x0007); 
00250         wr_reg(0x31,0x0707);   
00251         wr_reg(0x32,0x0006);
00252         wr_reg(0x35,0x0704);
00253         wr_reg(0x36,0x1f04); 
00254         wr_reg(0x37,0x0004);
00255         wr_reg(0x38,0x0000);        
00256         wr_reg(0x39,0x0706);     
00257         wr_reg(0x3c,0x0701);
00258         wr_reg(0x3d,0x000f);
00259 
00260         wait_ms(50);
00261 
00262         wr_reg(0x50,0x0000);        
00263         wr_reg(0x51,0x00ef);   
00264         wr_reg(0x52,0x0000);     
00265         wr_reg(0x53,0x013f);
00266         wr_reg(0x60,0xa700);        
00267         wr_reg(0x61,0x0001); 
00268         wr_reg(0x6a,0x0000);
00269         wr_reg(0x80,0x0000);
00270         wr_reg(0x81,0x0000);
00271         wr_reg(0x82,0x0000);
00272         wr_reg(0x83,0x0000);
00273         wr_reg(0x84,0x0000);
00274         wr_reg(0x85,0x0000);
00275           
00276         wr_reg(0x90,0x0010);     
00277         wr_reg(0x92,0x0000);  
00278         wr_reg(0x93,0x0003);
00279         wr_reg(0x95,0x0110);
00280         wr_reg(0x97,0x0000);        
00281         wr_reg(0x98,0x0000);  
00282         
00283         wr_reg(0x07,0x0133);                          // display on sequence
00284         
00285         wr_reg(0x20,0x0000);         
00286         wr_reg(0x21,0x0000);
00287     }   
00288     wait_ms(100);
00289     WindowMax();
00290 }
00291 
00292 
00293 void SPI_TFT::pixel(int x, int y, int color)
00294 {
00295     switch (orientation) {
00296         case 0:
00297             wr_reg(0x20, x);
00298             wr_reg(0x21, y);
00299             break;
00300         case 1:
00301             wr_reg(0x20, 239-y);
00302             wr_reg(0x21, x);
00303             break;
00304         case 2:
00305             wr_reg(0x20, 239-x);
00306             wr_reg(0x21, 319-y);
00307             break;
00308         case 3:
00309             wr_reg(0x20, y);
00310             wr_reg(0x21, 319-x);
00311             break;
00312     }
00313     wr_cmd(0x22);
00314     wr_dat(color);
00315 }
00316 
00317 
00318 void SPI_TFT::window(int x, int y, int w, int h)
00319 {
00320     unsigned int xw1, yh1;
00321     xw1 = x + w - 1;
00322     yh1 = y + h - 1;
00323     wr_reg(0x20, x);
00324     wr_reg(0x21, y);
00325     switch (orientation) {
00326         case 0:
00327             wr_reg(0x50, x);
00328             wr_reg(0x51, xw1);
00329             wr_reg(0x52, y);
00330             wr_reg(0x53, yh1);
00331             break;
00332         case 1:
00333             wr_reg(0x50, 239 - yh1);
00334             wr_reg(0x51, 239 - y);
00335             wr_reg(0x52, x);
00336             wr_reg(0x53, xw1);
00337             break;
00338         case 2:
00339             wr_reg(0x50, 239 - xw1);
00340             wr_reg(0x51, 239 - x);
00341             wr_reg(0x52, 319 - yh1);
00342             wr_reg(0x53, 319 - y);
00343             break;
00344         case 3:
00345             wr_reg(0x50, y);
00346             wr_reg(0x51, yh1);
00347             wr_reg(0x52, 319 - xw1);
00348             wr_reg(0x53, 319 - x);
00349             break;
00350     }
00351 }
00352 
00353 
00354 void SPI_TFT::WindowMax(void)
00355 {
00356     window(0, 0, width(),  height());
00357 }
00358 
00359 
00360 void SPI_TFT::cls (void)
00361 {
00362     if (backgroundimage == false) {
00363     unsigned long int index=0;
00364     wr_reg(0x03, 0x1030);
00365     WindowMax();
00366     SetCursor(0,0);
00367     wr_cmd(0x22);
00368     _cs = 0;
00369     wr_dat_start();
00370     #ifndef SPI_8BIT
00371     _spi.format(16,3);
00372     #endif
00373     int num = width()*height();
00374 
00375     for( index = 0; index<num; index++ ) {
00376         #ifndef SPI_8BIT
00377         _spi.fastWrite(_background);
00378         #else
00379         _spi.fastWrite(_background >> 8);
00380         _spi.fastWrite(_background & 0xFF);
00381         #endif
00382     }
00383     _spi.clearRX();
00384 
00385     #ifndef SPI_8BIT
00386     _spi.format(8,3);
00387     #endif
00388     _cs = 1;
00389     }
00390     #ifndef NO_FLASH_BUFFER
00391     else {
00392         int _orientation=orientation;
00393         set_orientation(backgroundOrientation);
00394         Bitmap(0,0,width(),height(),(unsigned char*) sector_start_adress[ 25 ]);
00395         set_orientation(_orientation);
00396         }
00397     #endif
00398 }
00399 
00400 void SPI_TFT::hline(int x0, int x1, int y, int color)
00401 {
00402     unsigned int index=0;
00403     int w;
00404     w = x1 - x0 + 1;
00405     mod_orientation();
00406     window(x0,y,w,1);
00407     wr_cmd(0x22);
00408     _cs = 0;
00409     wr_dat_start();
00410 
00411     #ifndef SPI_8BIT
00412     _spi.format(16,3);
00413     #endif
00414     int num = x1-x0;
00415     for( index = 0; index<num; index++ ) {
00416         #ifndef SPI_8BIT
00417         _spi.fastWrite(color);
00418         #else
00419         _spi.fastWrite(color >> 8);
00420         _spi.fastWrite(color & 0xFF);
00421         #endif
00422     }
00423     _spi.clearRX();
00424 
00425     #ifndef SPI_8BIT
00426     _spi.format(8,3);
00427     #endif
00428     _cs = 1;
00429     return;
00430 }
00431 
00432 void SPI_TFT::vline(int x, int y0, int y1, int color)
00433 {
00434     unsigned int index=0;
00435     int h;
00436     h = y1 - y0 + 1;
00437     mod_orientation();
00438     window(x,y0,1,h);
00439     wr_cmd(0x22);
00440     _cs = 0;
00441     wr_dat_start();
00442     #ifndef SPI_8BIT
00443     _spi.format(16,3);
00444     #endif
00445     int num = y1-y0;
00446     for( index = 0; index<num; index++ ) {
00447         #ifndef SPI_8BIT
00448         _spi.fastWrite(color);
00449         #else
00450         _spi.fastWrite(color >> 8);
00451         _spi.fastWrite(color & 0xFF);
00452         #endif
00453     }
00454     _spi.clearRX();
00455     #ifndef SPI_8BIT
00456     _spi.format(8,3);
00457     #endif
00458     _cs = 1;
00459     return;
00460 }
00461 
00462 void SPI_TFT::line(int x0, int y0, int x1, int y1, int color)
00463 {
00464     wr_reg(0x03, 0x1030);
00465     WindowMax();
00466     int   dx = 0, dy = 0;
00467     int   dx_sym = 0, dy_sym = 0;
00468     int   dx_x2 = 0, dy_x2 = 0;
00469     int   di = 0;
00470 
00471     dx = x1-x0;
00472     dy = y1-y0;
00473 
00474     if (dx == 0) {                          // vertical line
00475         if (y1 > y0) vline(x0,y0,y1,color);
00476         else vline(x0,y1,y0,color);
00477         return;
00478     }
00479 
00480     if (dx > 0) {
00481         dx_sym = 1;
00482     } else {
00483         dx_sym = -1;
00484     }
00485     if (dy == 0) {                          // horizontal line
00486         if (x1 > x0) hline(x0,x1,y0,color);
00487         else  hline(x1,x0,y0,color);
00488         return;
00489     }
00490 
00491     if (dy > 0) {
00492         dy_sym = 1;
00493     } else {
00494         dy_sym = -1;
00495     }
00496 
00497     dx = dx_sym*dx;
00498     dy = dy_sym*dy;
00499 
00500     dx_x2 = dx*2;
00501     dy_x2 = dy*2;
00502 
00503     if (dx >= dy) {
00504         di = dy_x2 - dx;
00505         while (x0 != x1) {
00506 
00507             pixel(x0, y0, color);
00508             x0 += dx_sym;
00509             if (di<0) {
00510                 di += dy_x2;
00511             } else {
00512                 di += dy_x2 - dx_x2;
00513                 y0 += dy_sym;
00514             }
00515         }
00516         pixel(x0, y0, color);
00517     } else {
00518         di = dx_x2 - dy;
00519         while (y0 != y1) {
00520             pixel(x0, y0, color);
00521             y0 += dy_sym;
00522             if (di < 0) {
00523                 di += dx_x2;
00524             } else {
00525                 di += dx_x2 - dy_x2;
00526                 x0 += dx_sym;
00527             }
00528         }
00529         pixel(x0, y0, color);
00530     }
00531     return;
00532 }
00533 
00534 
00535 void SPI_TFT::rect(int x0, int y0, int w, int h, int color)
00536 {
00537     hline(x0,x0+w,y0,color);
00538     vline(x0,y0,y0+h,color);
00539     hline(x0,x0+w,y0+h,color);
00540     vline(x0+w,y0,y0+h,color);
00541 
00542     return;
00543 }
00544 
00545 void SPI_TFT::fillrect(int x0, int y0, int w, int h, int color)
00546 {
00547     unsigned long int index=0;
00548     if (w < 0) {
00549         x0 = x0 + w;
00550         w = -w;
00551     }
00552     if (h < 0) {
00553         y0 = y0 + h;
00554         h = -h;
00555     }
00556     mod_orientation();
00557     window(x0,y0,w,h);
00558     wr_cmd(0x22);
00559     _cs = 0;
00560     wr_dat_start();
00561     #ifndef SPI_8BIT
00562     _spi.format(16,3);
00563     #endif
00564     int num = h*w;
00565     for( index = 0; index<num; index++ ) {
00566         #ifndef SPI_8BIT
00567         _spi.fastWrite(color);
00568         #else
00569         _spi.fastWrite(color >> 8);
00570         _spi.fastWrite(color & 0xFF);
00571         #endif
00572     }
00573     _spi.clearRX();
00574     #ifndef SPI_8BIT
00575     _spi.format(8,3);
00576     #endif
00577     _cs = 1;
00578     return;
00579 }
00580 
00581 void SPI_TFT::draw_ellipse(int xc, int yc, int a, int b, unsigned int color)
00582 {
00583     /* e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 */
00584     wr_reg(0x03, 0x1030);
00585     WindowMax();
00586     int x = 0, y = b;
00587     long a2 = (long)a*a, b2 = (long)b*b;
00588     long crit1 = -(a2/4 + a%2 + b2);
00589     long crit2 = -(b2/4 + b%2 + a2);
00590     long crit3 = -(b2/4 + b%2);
00591     long t = -a2*y;                         // e(x+1/2,y-1/2) - (a^2+b^2)/4
00592     long dxt = 2*b2*x, dyt = -2*a2*y;
00593     long d2xt = 2*b2, d2yt = 2*a2;
00594 
00595     while (y>=0 && x<=a) {
00596         pixel(xc+x, yc+y, color);
00597         if (x!=0 || y!=0)
00598             pixel(xc-x, yc-y, color);
00599         if (x!=0 && y!=0) {
00600             pixel(xc+x, yc-y, color);
00601             pixel(xc-x, yc+y, color);
00602         }
00603         if (t + b2*x <= crit1 ||            // e(x+1,y-1/2) <= 0
00604                 t + a2*y <= crit3)          // e(x+1/2,y) <= 0
00605             incx();
00606         else if (t - a2*y > crit2)          // e(x+1/2,y-1) > 0
00607             incy();
00608         else {
00609             incx();
00610             incy();
00611         }
00612     }
00613 }
00614 
00615 void SPI_TFT::fill_ellipse(int xc, int yc, int a, int b, unsigned int color)
00616 {
00617     /* e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 */
00618     int x = 0, y = b;
00619     int rx = x, ry = y;
00620     unsigned int width = 1;
00621     unsigned int height = 1;
00622     long a2 = (long)a*a, b2 = (long)b*b;
00623     long crit1 = -(a2/4 + a%2 + b2);
00624     long crit2 = -(b2/4 + b%2 + a2);
00625     long crit3 = -(b2/4 + b%2);
00626     long t = -a2*y;                         // e(x+1/2,y-1/2) - (a^2+b^2)/4
00627     long dxt = 2*b2*x, dyt = -2*a2*y;
00628     long d2xt = 2*b2, d2yt = 2*a2;
00629 
00630     if (b == 0) {
00631         fillrect(xc-a, yc, 2*a+1, 1, color);
00632         return;
00633     }
00634 
00635     while (y>=0 && x<=a) {
00636         if (t + b2*x <= crit1 ||            // e(x+1,y-1/2) <= 0
00637                 t + a2*y <= crit3) {        // e(x+1/2,y) <= 0
00638             if (height == 1)
00639                 ;                           // draw nothing
00640             else if (ry*2+1 > (height-1)*2) {
00641                 fillrect(xc-rx, yc-ry, width, height-1, color);
00642                 fillrect(xc-rx, yc+ry+1, width, 1-height, color);
00643                 ry -= height-1;
00644                 height = 1;
00645             } else {
00646                 fillrect(xc-rx, yc-ry, width, ry*2+1, color);
00647                 ry -= ry;
00648                 height = 1;
00649             }
00650             incx();
00651             rx++;
00652             width += 2;
00653         } else if (t - a2*y > crit2) {      // e(x+1/2,y-1) > 0
00654             incy();
00655             height++;
00656         } else {
00657             if (ry*2+1 > height*2) {
00658                 fillrect(xc-rx, yc-ry, width, height, color);
00659                 fillrect(xc-rx, yc+ry+1, width, -height, color);
00660             } else {
00661                 fillrect(xc-rx, yc-ry, width, ry*2+1, color);
00662             }
00663             incx();
00664             incy();
00665             rx++;
00666             width += 2;
00667             ry -= height;
00668             height = 1;
00669         }
00670     }
00671 
00672     if (ry > height) {
00673         fillrect(xc-rx, yc-ry, width, height, color);
00674         fillrect(xc-rx, yc+ry+1, width, -height, color);
00675     } else {
00676         fillrect(xc-rx, yc-ry, width, ry*2+1, color);
00677     }
00678 }
00679 
00680 
00681 void SPI_TFT::locate(int x, int y)
00682 {
00683     char_x = x;
00684     char_y = y;
00685 }
00686 
00687 int SPI_TFT::columns()
00688 {
00689     return width() / font[1];
00690 }
00691 
00692 int SPI_TFT::rows()
00693 {
00694     return height() / font[2];
00695 }
00696 
00697 int SPI_TFT::_putc(int value)
00698 {
00699     if (value == '\n') {                    // new line
00700         char_x = 0;
00701         char_y = char_y + font[2];
00702         if (char_y >= height() - font[2]) {
00703             char_y = 0;
00704         }
00705     } else {
00706         character(char_x, char_y, value);
00707     }
00708     return value;
00709 }
00710 
00711 void SPI_TFT::character(int x, int y, int c)
00712 {
00713     unsigned int hor,vert,offset,bpl,j,i,b;
00714     unsigned char* bitmap_char;
00715     unsigned char z,w;
00716 
00717     if ((c < 31) || (c > 127)) return;      // test char range
00718 
00719     // read font parameter from start of array
00720     offset = font[0];                       // bytes / char
00721     hor = font[1];                          // get hor size of font
00722     vert = font[2];                         // get vert size of font
00723     bpl = font[3];                          // bytes per line
00724 
00725     if (char_x + hor > width()) {
00726         char_x = 0;
00727         char_y = char_y + vert;
00728         if (char_y >= height() - font[2]) {
00729             char_y = 0;
00730         }
00731     }
00732     mod_orientation();
00733 
00734     bitmap_char = &font[((c -32) * offset) + 4];    // start of char bitmap
00735     w = bitmap_char[0];                             // width of actual char
00736     window(char_x, char_y,hor,vert); // char box
00737     wr_cmd(0x22);
00738     _cs = 0;
00739     wr_dat_start();
00740     #ifndef SPI_8BIT
00741     _spi.format(16,3);
00742     #endif
00743     for (j=0; j<vert; j++) {                        //  vert line
00744         for (i=0; i<hor; i++) {                       //  horz line
00745             z =  bitmap_char[bpl * i + ((j & 0xF8) >> 3)+1];
00746             b = 1 << (j & 0x07);
00747             if (( z & b ) == 0x00) {
00748                 #ifndef NO_FLASH_BUFFER
00749                 if (backgroundimage==false)
00750                 {
00751                 #endif
00752                     #ifndef SPI_8BIT
00753                     _spi.fastWrite(_background);
00754                     #else
00755                     _spi.fastWrite(_background >> 8);
00756                     _spi.fastWrite(_background & 0xFF);
00757                     #endif
00758                 #ifndef NO_FLASH_BUFFER
00759                 }
00760                 else
00761                 {
00762                     unsigned short *bitmap_ptr = (unsigned short *)sector_start_adress[ 25 ];
00763                     int angle = (orientation - backgroundOrientation)%4; //Get the difference in orientation between background and current
00764                     switch (angle) {
00765                         case 0:         //Same orientation
00766                             bitmap_ptr += width() * (height()-(y+j+1))+x+i;
00767                         break;
00768                         case 1:         //Rotated 1 (don't ask me which direction)
00769                             bitmap_ptr += height() * (width()-(x+i+1))+height()-(y+j + 1);
00770                         break;
00771                         case 2:         //Upside down
00772                             bitmap_ptr += width() * (y+j)+width() - (x+i + 1);
00773                         break; 
00774                         case 3:         //Rotated 3
00775                             bitmap_ptr += height() * (x+i)+y+j;                            
00776                         break;
00777                         default:
00778                         break;
00779                     }
00780                     
00781                     #ifndef SPI_8BIT
00782                     _spi.fastWrite(*bitmap_ptr);
00783                     #else
00784                     _spi.fastWrite((*bitmap_ptr) >> 8);
00785                     _spi.fastWrite((*bitmap_ptr) & 0xFF);
00786                     #endif
00787                 }
00788                 #endif    
00789             } else {
00790                 #ifndef SPI_8BIT
00791                 _spi.fastWrite(_foreground);
00792                 #else
00793                 _spi.fastWrite(_foreground >> 8);
00794                 _spi.fastWrite(_foreground & 0xFF);
00795                 #endif
00796             }
00797         }
00798     }
00799     _spi.clearRX();
00800     #ifndef SPI_8BIT
00801     _spi.format(8,3);
00802     #endif
00803     _cs = 1;
00804     if ((w + 2) < hor) {                 // x offset to next char
00805         char_x += w + 2;
00806     } else char_x += hor;
00807 }
00808 
00809 void SPI_TFT::set_font(unsigned char* f)
00810 {
00811     font = f;
00812 }
00813 
00814 
00815 void SPI_TFT::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap)
00816 {
00817     unsigned int    i,j;
00818     unsigned short *bitmap_ptr = (unsigned short *)bitmap;
00819     mod_orientation();
00820     window(x, y, w, h);
00821     wr_cmd(0x22);
00822     _cs = 0;
00823     wr_dat_start();
00824     #ifndef SPI_8BIT
00825     _spi.format(16,3);
00826     #endif
00827     bitmap_ptr += ((h - 1)*w);
00828     for (j = 0; j < h; j++) {               //Lines
00829         for (i = 0; i < w; i++) {           // copy pixel data to TFT
00830             #ifndef SPI_8BIT
00831             _spi.fastWrite(*bitmap_ptr);    // one line
00832             #else
00833             _spi.fastWrite((*bitmap_ptr) >> 8);
00834             _spi.fastWrite((*bitmap_ptr) & 0xFF);
00835             #endif
00836             bitmap_ptr++;
00837         }
00838         bitmap_ptr -= 2*w;
00839     }
00840     _spi.clearRX();
00841     #ifndef SPI_8BIT
00842     _spi.format(8,3);
00843     #endif
00844     _cs = 1;
00845 }
00846 
00847 int SPI_TFT::Bitmap(unsigned int x, unsigned int y, const char *Name_BMP)
00848 {
00849     #define RGB565CONVERT(red, green, blue) (uint16_t)( (( red   >> 3 ) << 11 ) | (( green >> 2 ) << 5  ) | ( blue  >> 3 ))
00850     mod_orientation();
00851     
00852     bitmapData bmp = getBitmapData(Name_BMP);
00853     if (bmp.return_code != 1)
00854         return bmp.return_code;
00855     
00856 
00857     unsigned char *line = (unsigned char *) malloc (bmp.bits/8 * bmp.width);    // we need a buffer for a line
00858     unsigned short *line_short = (unsigned short*) (line);                      // Same one, addressed as short
00859 
00860 
00861     if ((bmp.height > height()+y) || (bmp.width > width()+x))
00862         return -3;          //Size mismatch
00863 
00864     if (line == NULL)
00865         return(-4);         // error no memory
00866 
00867 
00868     for (int j = bmp.height-1; j >= 0; j--) {                                   //Lines bottom up
00869         int off = j * (bmp.width  * bmp.bits/8 + bmp.pad) + bmp.start_data;     // start of line
00870         fseek(bmp.file, off ,SEEK_SET);
00871         fread(line,1,bmp.width * bmp.bits/8,bmp.file);                          // read a line - slow !
00872         
00873         //If 24 bit format, convert to 565
00874         if (bmp.bits == 24) {
00875             for (int i = 0; i<bmp.width; i++) {
00876                 line_short[i] = RGB565CONVERT(line[3*i+2], line[3*i+1], line[3*i]);
00877             }
00878         }
00879 
00880         window(x, y+bmp.height - 1 - j,bmp.width ,1);
00881         wr_cmd(0x22);
00882 
00883         _cs = 0;
00884         wr_dat_start();
00885         #ifndef SPI_8BIT
00886         _spi.format(16,3);
00887         #endif
00888         _spi.setFormat();
00889 
00890         for (int i = 0; i < bmp.width; i++) {       // copy pixel data to TFT
00891             #ifndef SPI_8BIT
00892             _spi.fastWrite(line_short[i]);          // one line
00893             #else
00894             _spi.fastWrite(line_short[i] >> 8);
00895             _spi.fastWrite(line_short[i] & 0xFF);
00896             #endif
00897         }
00898 
00899         _spi.clearRX();
00900         #ifndef SPI_8BIT
00901         _spi.format(8,3);
00902         #endif
00903         _cs = 1;
00904 
00905     }
00906 
00907 
00908     free (line);
00909     fclose(bmp.file);
00910     WindowMax();
00911 
00912     return(1);
00913 }
00914 
00915 #ifndef NO_FLASH_BUFFER
00916 
00917 int SPI_TFT::fileToFlash(const char *Name_BMP)
00918 {
00919     #define RGB565CONVERT(red, green, blue) (uint16_t)( (( red   >> 3 ) << 11 ) | (( green >> 2 ) << 5  ) | ( blue  >> 3 ))
00920    
00921     mod_orientation();
00922     
00923     bitmapData bmp = getBitmapData(Name_BMP);
00924     if (bmp.return_code != 1)
00925         return bmp.return_code;
00926     
00927 
00928     unsigned char *line = (unsigned char *) malloc (bmp.bits/8 * bmp.width);    // we need a buffer for a line
00929     unsigned short *line_short = (unsigned short*) (line);                      // Same one, addressed as short
00930 
00931     unsigned short *flashSector = (unsigned short *) malloc (256);              //And one to send to flash
00932 
00933     if ((bmp.height != height()) || (bmp.width != width()))
00934         return -3;          //Size mismatch
00935 
00936     if ((line == NULL) || (flashSector == NULL))
00937         return(-4);         // error no memory
00938     
00939 
00940     int flashPointer = 0, flashWrites = 0;
00941 
00942     //Erase Flash that will be used:
00943     if ( iap.blank_check( 25, 29 ) == SECTOR_NOT_BLANK ) {
00944         iap.prepare( 25, 29 );
00945         iap.erase( 25, 29 );
00946     }
00947 
00948     for (int j = 0; j < bmp.height; j++) {                                      //Lines bottom up
00949         int off = j * (bmp.width  * bmp.bits/8 + bmp.pad) + bmp.start_data;     // start of line
00950         fseek(bmp.file, off ,SEEK_SET);
00951         fread(line,1,bmp.width * bmp.bits/8,bmp.file);                          // read a line - slow !
00952 
00953         //If 24 bit format, do some processing
00954         if (bmp.bits == 24) {
00955             for (int i = 0; i<bmp.width; i++) {
00956                 line_short[i] = RGB565CONVERT(line[3*i+2], line[3*i+1], line[3*i]);
00957             }
00958         }
00959 
00960 
00961         for (int i = 0; i < bmp.width; i++) {               // copy pixel data to TFT
00962             flashSector[flashPointer] = line_short[i];      // one line
00963             flashPointer++;
00964 
00965             //If flashpointer reached the end, write to flash
00966             if (flashPointer == 128) {
00967                 iap.prepare( 25, 29 );
00968                 iap.write((char *)flashSector, sector_start_adress[ 25 ] + 256 * flashWrites, 256);
00969                 flashPointer = 0;
00970                 flashWrites++;
00971                 if (flashWrites == 1000)
00972                     error("Too many flashwrites");
00973             }
00974         }
00975     }
00976     //write remaining data
00977     if (flashPointer!=0) {
00978         iap.prepare( 25, 29 );
00979         iap.write((char*)flashSector, sector_start_adress[ 25 ] + 256 * flashWrites, 256);
00980         flashPointer = 0;
00981         flashWrites++;
00982         if (flashWrites == 1000)
00983             error("Too many flashwrites");
00984     }
00985 
00986 
00987 
00988     free (line);
00989     fclose(bmp.file);
00990     backgroundImage(true);
00991     backgroundOrientation = orientation;
00992     return(1);
00993 }
00994 
00995 void SPI_TFT::backgroundImage( bool active) {
00996     backgroundimage = active;
00997 }
00998 #endif
00999 
01000 
01001 SPI_TFT::bitmapData SPI_TFT::getBitmapData(const char *Name_BMP){
01002     #define OffsetPixelWidth    18
01003     #define OffsetPixelHeigh    22
01004     #define OffsetFileSize      34
01005     #define OffsetPixData       10
01006     #define OffsetBPP           28
01007     
01008 
01009     bitmapData retval;
01010     retval.return_code = 1;
01011     unsigned char BMP_Header[54];
01012 
01013     retval.file = fopen(Name_BMP, "rb");                    // open the bmp file
01014     if (!retval.file) {
01015         retval.return_code = 0;
01016         return(retval);                                     // error file not found !
01017     }
01018 
01019     fread(&BMP_Header[0],1,54,retval.file);                 // get the BMP Header
01020 
01021     if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) {   // check magic byte
01022         fclose(retval.file);
01023         retval.return_code = -1;
01024         return(retval);                                     // error not a BMP file
01025     }
01026 
01027     int BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8);
01028     if (BPP_t == 0x0010)
01029         retval.bits = 16;
01030     else if (BPP_t == 0x0018)
01031         retval.bits = 24;
01032     else {
01033         fclose(retval.file);
01034         retval.return_code = -2;
01035         return(retval);                                     // error no 16/24 bit BMP
01036     }
01037 
01038     retval.height = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24);
01039     retval.width = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24);
01040     if (retval.height > height()|| retval.width > width()) {
01041         fclose(retval.file);
01042         retval.return_code = -3;
01043         return(retval);                                     // too big
01044     }
01045 
01046 
01047     retval.start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
01048 
01049     // the bmp lines are padded to multiple of 4 bytes
01050     retval.pad = -1;
01051     do {
01052         retval.pad ++;
01053     } while ((retval.width * retval.bits/8 + retval.pad)%4 != 0);
01054     return retval;
01055 
01056 }