Added methods and features

Fork of SPI_TFT_ILI9341 by Peter Drescher

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 // 30.03.14 WH Added some methods & defines, Fixed typos & warnings, General define for SPI_16 selection
00019 
00020 #include "mbed.h"
00021 #include "SPI_TFT_ILI9341.h"
00022 
00023 //extern Serial pc;
00024 //extern DigitalOut xx;     // debug !!
00025 
00026 SPI_TFT_ILI9341::SPI_TFT_ILI9341(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset, PinName dc, const char *name)
00027     : GraphicsDisplay(name), _spi(mosi, miso, sclk), _cs(cs), _dc(dc) 
00028 {
00029 
00030   // The hardware Reset pin is optional. Test and make sure whether it exists or not to prevent illegal access.
00031   if (reset != NC) {
00032     _reset = new DigitalOut(reset, 1);   //Construct new pin, Deactivated 
00033 //    _reset->write(1);                 //Deactivate    
00034   }
00035   else {
00036     // No Hardware Reset pin       
00037     _reset = NULL;                 //Construct dummy pin     
00038   }  
00039 
00040 //WH    clk = sclk;
00041 //WH    orientation = 0;
00042     _origin = Origin_LeftTop;  
00043     _char_x = 0;
00044     _char_y = 0;
00045     _transparancy = false;    
00046 //    set_font(Arial12x12); //Default font    
00047 //    set_font(FONT8x8); //Default font, shame it doesnt fit format.. waste of flash space at moment
00048   
00049     tft_reset();
00050 }
00051 
00052 
00053 /** Destruct a SPI_TFT LCD object
00054   *
00055   * @param  none
00056   * @return none
00057   */ 
00058 SPI_TFT_ILI9341::~SPI_TFT_ILI9341() {
00059   if (_reset != NULL) {delete _reset;}  // HW Reset pin
00060 }
00061 
00062 
00063 
00064 int SPI_TFT_ILI9341::width()
00065 {
00066 //    if (orientation == 0 || orientation == 2) return 240;
00067 //    else return 320;
00068 
00069     if (_origin == Origin_LeftTop || _origin == Origin_RightBot) return TFT_WIDTH;
00070     else return TFT_HEIGHT;
00071 }
00072 
00073 
00074 int SPI_TFT_ILI9341::height()
00075 {
00076 //    if (orientation == 0 || orientation == 2) return 320;
00077 //    else return 240;
00078 
00079     if (_origin == Origin_LeftTop || _origin == Origin_RightBot) return TFT_HEIGHT;
00080     else return TFT_WIDTH;
00081 }
00082 
00083 //WH
00084 #if(0)
00085 void SPI_TFT_ILI9341::set_orientation(unsigned int o)
00086 {
00087     orientation = o;
00088     wr_cmd(0x36);                     // MEMORY_ACCESS_CONTROL
00089     switch (orientation) {
00090         case 0:
00091             _spi.write(0x48);
00092             break;
00093         case 1:
00094             _spi.write(0x28);
00095             break;
00096         case 2:
00097             _spi.write(0x88);
00098             break;
00099         case 3:
00100             _spi.write(0xE8);
00101             break;
00102     }
00103     _cs = 1; 
00104     window_max();
00105 } 
00106 #else
00107 void SPI_TFT_ILI9341::set_origin(Origin origin) {
00108     _origin = origin;
00109     wr_cmd(ILI9341_MAC);             // MEMORY_ACCESS_CONTROL
00110     switch (_origin) {
00111         case Origin_LeftTop:         /* Left Top of panel is origin */    
00112             _spi.write(0x48);
00113             break;
00114         case Origin_RightTop:        /* ok */ 
00115             _spi.write(0x28);
00116             break;
00117         case Origin_RightBot:        /* ok */ 
00118             _spi.write(0x88);
00119             break;
00120         case Origin_LeftBot:        /* ok */ 
00121             _spi.write(0xE8);
00122             break;
00123     }
00124     _cs = 1; 
00125     window_max();
00126 } 
00127 #endif
00128 
00129 
00130 // background transparancy for characters 
00131 void SPI_TFT_ILI9341::set_transparancy(bool state) {
00132   _transparancy = state;  
00133 }
00134 
00135 // HW Reset to tft
00136 void SPI_TFT_ILI9341::_hwreset()
00137 {
00138   // _reset is an optional pin which defaults to NC. Make sure it does not hang mbed lib
00139   if (_reset != NULL) {_reset->write(0);}  //Clear _reset pin
00140   wait_us(50);
00141   if (_reset != NULL) {_reset->write(1);}  //Set _reset pin  
00142   wait_ms(5);
00143 }
00144 
00145 
00146 // write command to tft register
00147 void SPI_TFT_ILI9341::wr_cmd(unsigned char cmd)
00148 {
00149     _dc = 0;
00150     _cs = 0;
00151     _spi.write(cmd);      // mbed lib
00152     _dc = 1;
00153 }
00154 
00155 
00156 // write data to tft
00157 void SPI_TFT_ILI9341::wr_dat(unsigned char dat)
00158 {
00159    _spi.write(dat);      // mbed lib
00160 }
00161 
00162 //WH
00163 // The ILI9341 can be read 
00164 // Read not supported in M24SR
00165 
00166 
00167 // Read byte
00168 char SPI_TFT_ILI9341::rd_byte(unsigned char cmd)
00169 {
00170     char r;
00171     _dc = 0;
00172     _cs = 0;
00173     _spi.write(cmd);      // mbed lib
00174     _cs = 1;
00175     r = _spi.write(0xff);
00176     _cs = 1;    
00177     return(r);
00178 }
00179 
00180 // Read 32 bit
00181 int SPI_TFT_ILI9341::rd_32(unsigned char cmd)
00182 {
00183     int d;
00184     char r;
00185     _dc = 0;
00186     _cs = 0;
00187     d = cmd;
00188     d = d << 1;
00189 
00190 //Note WH: the 9bit format is not supported for most mbed devices...This wont work.
00191     _spi.format(9,0);    // we have to add a dummy clock cycle
00192      
00193     _spi.write(d);
00194     _spi.format(8,0);   
00195     _dc = 1;
00196     r = _spi.write(0xff);
00197     d = r;
00198     r = _spi.write(0xff);
00199     d = (d << 8) | r;
00200     r = _spi.write(0xff);
00201     d = (d << 8) | r;
00202     r = _spi.write(0xff);
00203     d = (d << 8) | r;
00204     _cs = 1;    
00205     return(d);
00206 }
00207 
00208 //This may be not supported on some revisions of IL9341
00209 int  SPI_TFT_ILI9341::Read_ID(void){
00210     int r;
00211     r = rd_byte(0x0A);
00212     r = rd_byte(0x0A);
00213     r = rd_byte(0x0A);
00214     r = rd_byte(0x0A);
00215     return(r);
00216 }
00217 
00218 
00219 // Init code based on MI0283QT datasheet
00220 void SPI_TFT_ILI9341::tft_reset()
00221 {
00222 //WH    _spi.format(8,3);                  // 8 bit spi Mode 3
00223     _spi.format(8,0);                  // 8 bit spi, mode 0    
00224     
00225 //    _spi.frequency(4000000);          // 4 Mhz SPI clock
00226 //    _spi.frequency(8000000);          // 8 Mhz SPI clock
00227     _spi.frequency(10000000);           // 10 Mhz SPI ... works on current version of mbed F103 lib after fix for HSI/HSE...
00228         
00229     _cs = 1;                           // cs high
00230     _dc = 1;                           // dc high 
00231 
00232     _hwreset();                        // HW reset 
00233          
00234     wr_cmd(ILI9341_DISPLAY_RST);      // SW reset      
00235     wait_ms(5);
00236 
00237     wr_cmd(ILI9341_DISPLAY_OFF);      // display off      
00238 
00239     /* Start Initial Sequence ----------------------------------------------------*/
00240      wr_cmd(ILI9341_POWERB);    /* Power control B register */
00241      _spi.write(0x00);
00242      _spi.write(0x83);
00243      _spi.write(0x30);
00244      _cs = 1;
00245      
00246      wr_cmd(ILI9341_POWER_SEQ); /* Power on sequence register */
00247      _spi.write(0x64);
00248      _spi.write(0x03);
00249      _spi.write(0x12);
00250      _spi.write(0x81);
00251      _cs = 1;
00252      
00253      wr_cmd(ILI9341_DTCA);      /* Driver timing control A */                      
00254      _spi.write(0x85);
00255      _spi.write(0x01);
00256      _spi.write(0x79);
00257      _cs = 1;
00258      
00259      wr_cmd(ILI9341_POWERA);    /* Power control A register */                     
00260      _spi.write(0x39);
00261      _spi.write(0x2C);
00262      _spi.write(0x00);
00263      _spi.write(0x34);
00264      _spi.write(0x02);
00265      _cs = 1;
00266            
00267      wr_cmd(ILI9341_PRC);       /* Pump ratio control register */                   
00268      _spi.write(0x20);
00269      _cs = 1;
00270            
00271      wr_cmd(ILI9341_DTCB);      /* Driver timing control B */                          
00272      _spi.write(0x00);
00273      _spi.write(0x00);
00274      _cs = 1;
00275      
00276      wr_cmd(ILI9341_POWER1);    // POWER_CONTROL_1   
00277      _spi.write(0x26);
00278      _cs = 1;
00279  
00280      wr_cmd(ILI9341_POWER2);    // POWER_CONTROL_2
00281      _spi.write(0x11);
00282      _cs = 1;
00283      
00284      wr_cmd(ILI9341_VCOM1);     // VCOM_CONTROL_1     
00285      _spi.write(0x35);
00286      _spi.write(0x3E);
00287      _cs = 1;
00288      
00289      wr_cmd(ILI9341_VCOM2);     // VCOM_CONTROL_2     
00290      _spi.write(0xBE);
00291      _cs = 1; 
00292      
00293      wr_cmd(ILI9341_MAC);       // MEMORY_ACCESS_CONTROL     
00294      _spi.write(0x48);            // my,mx,mv,ml,BGR,mh,0,0
00295      _cs = 1; 
00296      
00297      wr_cmd(ILI9341_PIXEL_FORMAT); /* Pixel Format register */
00298      _spi.write(0x55);                 // 16 bit pixel 
00299      _cs = 1;
00300      
00301      wr_cmd(ILI9341_FRC);          /* Frame Rate Control register */
00302      _spi.write(0x00);
00303      _spi.write(0x1B);               
00304      _cs = 1;
00305      
00306      wr_cmd(ILI9341_3GAMMA_EN);    /* 3 Gamma enable register */     
00307      _spi.write(0x08);             // Gamma Function Disable
00308      _cs = 1; 
00309      
00310      wr_cmd(ILI9341_GAMMA);        /* Gamma register */
00311      _spi.write(0x01);                 // gamma set for curve 01/2/04/08
00312      _cs = 1; 
00313      
00314      wr_cmd(ILI9341_PGAMMA);       /* Positive Gamma Correction register*/     
00315      _spi.write(0x1F); 
00316      _spi.write(0x1A); 
00317      _spi.write(0x18); 
00318      _spi.write(0x0A); 
00319      _spi.write(0x0F); 
00320      _spi.write(0x06); 
00321      _spi.write(0x45); 
00322      _spi.write(0x87); 
00323      _spi.write(0x32); 
00324      _spi.write(0x0A); 
00325      _spi.write(0x07); 
00326      _spi.write(0x02); 
00327      _spi.write(0x07);
00328      _spi.write(0x05); 
00329      _spi.write(0x00);
00330      _cs = 1;
00331      
00332      wr_cmd(ILI9341_NGAMMA);       /* Negative Gamma Correction register*/
00333      _spi.write(0x00); 
00334      _spi.write(0x25); 
00335      _spi.write(0x27); 
00336      _spi.write(0x05); 
00337      _spi.write(0x10); 
00338      _spi.write(0x09); 
00339      _spi.write(0x3A); 
00340      _spi.write(0x78); 
00341      _spi.write(0x4D); 
00342      _spi.write(0x05); 
00343      _spi.write(0x18); 
00344      _spi.write(0x0D); 
00345      _spi.write(0x38);
00346      _spi.write(0x3A); 
00347      _spi.write(0x1F);
00348      _cs = 1;
00349      
00350      window_max();
00351 
00352      //wr_cmd(ILI9341_TEAR_OFF);           // tearing effect off
00353      //_cs = 1;
00354      
00355      //wr_cmd(ILI9341_TEAR_ON);            // tearing effect on
00356      //_cs = 1;
00357       
00358      wr_cmd(ILI9341_ENTRY_MODE);          // entry mode         
00359      _spi.write(0x07);
00360      _cs = 1;
00361      
00362      wr_cmd(ILI9341_DFC);                /* Display Function Control register*/     
00363      _spi.write(0x0A);
00364      _spi.write(0x82);
00365      _spi.write(0x27);
00366      _spi.write(0x00);
00367      _cs = 1;
00368      
00369      wr_cmd(ILI9341_SLEEP_OUT);          // sleep out     
00370      _cs = 1;
00371      
00372      wait_ms(100);
00373      
00374      wr_cmd(ILI9341_DISPLAY_ON); 
00375      _cs = 1;
00376      
00377      wait_ms(100);
00378      
00379  }
00380 
00381 
00382 void SPI_TFT_ILI9341::tft_on(bool on)
00383 {
00384   if (on) {
00385     wr_cmd(ILI9341_DISPLAY_ON); 
00386   }  
00387   else {
00388     wr_cmd(ILI9341_DISPLAY_OFF); 
00389   }  
00390   _cs = 1;
00391 }
00392 
00393 void SPI_TFT_ILI9341::pixel(int x, int y, int color)
00394 {
00395     wr_cmd(ILI9341_COLUMN_ADDR);
00396     _spi.write(x >> 8);
00397     _spi.write(x);
00398     _spi.write((x+1) >> 8);  //WH
00399     _spi.write(x+1);   
00400     
00401     _cs = 1;
00402     
00403     wr_cmd(ILI9341_PAGE_ADDR);
00404     _spi.write(y >> 8);
00405     _spi.write(y);
00406     _spi.write((y+1) >> 8); //WH
00407     _spi.write(y+1);
00408     
00409     _cs = 1;
00410 
00411     wr_cmd(ILI9341_GRAM);  // send pixel     
00412 
00413 //    #if (SPI_16 == 1)
00414     #if(0)   // dont bother switching for only one pixel
00415     // 16 Bit SPI
00416     _spi.format(16,0);                            // switch to 16 bit Mode 0
00417     _spi.write(color);                            // Write D0..D15
00418     _spi.format(8,0);                             // switch back to 8 bit Mode 0
00419     #else 
00420     // 8 Bit SPI
00421     _spi.write(color >> 8);
00422     _spi.write(color & 0xff);   
00423     #endif
00424 
00425     _cs = 1;
00426 }
00427 
00428 
00429 void SPI_TFT_ILI9341::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h)
00430 {
00431 
00432     wr_cmd(ILI9341_COLUMN_ADDR);
00433     _spi.write(x >> 8);
00434     _spi.write(x);
00435     _spi.write((x+w-1) >> 8);
00436     _spi.write(x+w-1);   
00437     _cs = 1;
00438 
00439     wr_cmd(ILI9341_PAGE_ADDR);  
00440     _spi.write(y >> 8);
00441     _spi.write(y);
00442     _spi.write((y+h-1) >> 8);
00443     _spi.write(y+h-1);
00444     _cs = 1;
00445 }
00446 
00447 
00448 void SPI_TFT_ILI9341::window_max (void)
00449 {
00450   window (0, 0, width(),  height());
00451 }
00452 
00453 
00454 
00455 /** Fill the screen with _background color
00456   *  @param none
00457   *  @return none
00458   */  
00459 void SPI_TFT_ILI9341::cls()
00460 {  
00461   fillrect(0, 0, width()-1, height()-1, _background);
00462 }    
00463 
00464 
00465 //WH test
00466 void SPI_TFT_ILI9341::newcls (void)
00467 {  
00468     int pixels = height() * width();
00469     int i;
00470     int color = _background;
00471 #if (SPI_16 != 1)    
00472     int msb, lsb;        
00473 #endif    
00474  
00475     window(0,0,width(),height());
00476 
00477     wr_cmd(ILI9341_GRAM);  // send pixel         
00478 
00479 #if (SPI_16 == 1)    
00480     // 16 Bit SPI
00481     _spi.format(16,0);   // switch to 16 bit Mode 0
00482 
00483     //unroll loop in chunks of 8 pixels
00484     for (i = 0; i < (pixels>>3); i++) {
00485       _spi.write(color);
00486       _spi.write(color);
00487       _spi.write(color);
00488       _spi.write(color); 
00489       
00490       _spi.write(color);
00491       _spi.write(color);
00492       _spi.write(color);
00493       _spi.write(color);                                          
00494     }  
00495 
00496     //remainder
00497     for (i = 0; i < (pixels & 0x07); i++)
00498       _spi.write(color);
00499 
00500     _spi.format(8,0);    // switch back to 8 bit Mode 0 
00501 #else
00502     // 8 Bit SPI
00503     msb = color >> 8;
00504     lsb = color & 0xff;
00505 
00506     for (i = 0; i < (pixels>>3); i+=8) {
00507       _spi.write(msb); _spi.write(lsb);
00508       _spi.write(msb); _spi.write(lsb);
00509       _spi.write(msb); _spi.write(lsb);
00510       _spi.write(msb); _spi.write(lsb);
00511       
00512       _spi.write(msb); _spi.write(lsb);
00513       _spi.write(msb); _spi.write(lsb);
00514       _spi.write(msb); _spi.write(lsb);
00515       _spi.write(msb); _spi.write(lsb);                                          
00516     }
00517     
00518     for (i = 0; i < (pixels & 0x07); i++) {
00519       _spi.write(msb); _spi.write(lsb);
00520     }    
00521 #endif        
00522 
00523     _cs = 1; 
00524 }
00525 
00526 
00527 
00528 
00529 void SPI_TFT_ILI9341::circle(int x0, int y0, int r, int color)
00530 {
00531 
00532     int x = -r, y = 0, err = 2-2*r, e2;
00533     do {
00534         pixel(x0-x, y0+y,color);
00535         pixel(x0+x, y0+y,color);
00536         pixel(x0+x, y0-y,color);
00537         pixel(x0-x, y0-y,color);
00538         e2 = err;
00539         if (e2 <= y) {
00540             err += ++y*2+1;
00541             if (-x == y && e2 <= x) e2 = 0;
00542         }
00543         if (e2 > x) err += ++x*2+1;
00544     } while (x <= 0);
00545 
00546 }
00547 
00548 void SPI_TFT_ILI9341::fillcircle(int x0, int y0, int r, int color)
00549 {
00550     int x = -r, y = 0, err = 2-2*r, e2;
00551     do {
00552         vline(x0-x, y0-y, y0+y, color);
00553         vline(x0+x, y0-y, y0+y, color);
00554         e2 = err;
00555         if (e2 <= y) {
00556             err += ++y*2+1;
00557             if (-x == y && e2 <= x) e2 = 0;
00558         }
00559         if (e2 > x) err += ++x*2+1;
00560     } while (x <= 0);
00561 }
00562 
00563 
00564 void SPI_TFT_ILI9341::oval ( int x, int y, int b, int color, float aspect )
00565 {  
00566   /* local variables */
00567   int   col;               /* Column. */
00568   int   row;               /* Row. */
00569   float aspect_square;
00570   int   a_square;
00571   int   b_square;
00572   int   two_a_square;
00573   int   two_b_square;
00574   int   four_a_square;
00575   int   four_b_square;
00576   int   d; 
00577 
00578   aspect_square = aspect * aspect;  
00579   
00580   b_square = b * b;
00581   a_square = b_square / aspect_square; 
00582   row = b;
00583   col = 0;
00584   two_a_square = a_square << 1;
00585   four_a_square = a_square << 2;
00586   four_b_square = b_square << 2;
00587   two_b_square = b_square << 1;
00588   d = two_a_square * ((row - 1) * (row)) + a_square + two_b_square * (1 - a_square);
00589       
00590   while (a_square * (row) > b_square * col ) {
00591     pixel( x + col, y + row, color );    
00592     pixel( x + col, y - row, color );    
00593     pixel( x - col, y + row, color );    
00594     pixel( x - col, y - row, color );    
00595     if ( d >= 0 ) {
00596       row--;
00597       d -= four_a_square * row;
00598     }
00599     d += two_b_square * (3 + (col << 1));
00600     col++;
00601   }
00602   
00603   d = two_b_square * (col + 1) * col + two_a_square * (row * (row - 2) + 1) + (1 - two_a_square) * b_square;    
00604   
00605   while ( row + 1 ) {
00606     pixel( x + col, y + row, color );    
00607     pixel( x + col, y - row, color );    
00608     pixel( x - col, y + row, color );    
00609     pixel( x - col, y - row, color );    
00610     if ( d <= 0 ) {
00611       col++;
00612       d += four_b_square * col;
00613     }
00614     row--;
00615     d += two_a_square * (3 - (row << 1));
00616   }
00617 
00618 } /* End oval */
00619 
00620 
00621 void SPI_TFT_ILI9341::filloval ( int x, int y, int b, int color, float aspect )
00622 {  
00623   /* local variables */
00624   int   col;               /* Column. */
00625   int   row;               /* Row. */
00626   float aspect_square;
00627   int   a_square;
00628   int   b_square;
00629   int   two_a_square;
00630   int   two_b_square;
00631   int   four_a_square;
00632   int   four_b_square;
00633   int   d; 
00634 
00635   aspect_square = aspect * aspect;  
00636   
00637   b_square = b * b;
00638   a_square = b_square / aspect_square; 
00639   row = b;
00640   col = 0;
00641   two_a_square = a_square << 1;
00642   four_a_square = a_square << 2;
00643   four_b_square = b_square << 2;
00644   two_b_square = b_square << 1;
00645   d = two_a_square * ((row - 1) * (row)) + a_square + two_b_square * (1 - a_square);
00646       
00647   while (a_square * (row) > b_square * col ) {
00648     vline(x - col, y - row, y + row, color);    
00649     vline(x + col, y - row, y + row, color);           
00650 
00651     if ( d >= 0 ) {
00652       row--;
00653       d -= four_a_square * row;
00654     }
00655     d += two_b_square * (3 + (col << 1));
00656     col++;
00657   }
00658   
00659   d = two_b_square * (col + 1) * col + two_a_square * (row * (row - 2) + 1) + (1 - two_a_square) * b_square;    
00660   
00661   while ( row + 1 ) {
00662     vline(x - col, y - row, y + row, color);    
00663     vline(x + col, y - row, y + row, color);           
00664    
00665     if ( d <= 0 ) {
00666       col++;
00667       d += four_b_square * col;
00668     }
00669     row--;
00670     d += two_a_square * (3 - (row << 1));
00671   }
00672 
00673 } /* End filloval */
00674 
00675 
00676 void SPI_TFT_ILI9341::hline(int x0, int x1, int y, int color)
00677 {
00678     int i, w;
00679 #if (SPI_16 != 1)    
00680     int msb, lsb;
00681 #endif    
00682     w = x1 - x0 + 1;
00683     window(x0,y,w,1);
00684 //    wr_cmd(0x2C);  // send pixel
00685     wr_cmd(ILI9341_GRAM);  // send pixel         
00686     
00687 #if (SPI_16 == 1)
00688     // 16 Bit SPI
00689     _spi.format(16,0);   // switch to 16 bit Mode 0
00690     for (i = 0; i < w; i++)
00691       _spi.write(color);
00692     _spi.format(8,0);    // switch back to 8 bit Mode 0 
00693 #else
00694     // 8 Bit SPI
00695     msb = color >> 8;
00696     lsb = color & 0xff;
00697     for (i = 0; i < w; i++){
00698       _spi.write(msb);
00699       _spi.write(lsb);
00700     }
00701 #endif        
00702 
00703     _cs = 1;
00704     window_max();
00705 }
00706 
00707 
00708 
00709 void SPI_TFT_ILI9341::vline(int x, int y0, int y1, int color)
00710 {
00711     int i, h;
00712 #if (SPI_16 != 1)    
00713     int msb, lsb;
00714 #endif    
00715     
00716     h = y1 - y0 + 1;
00717     window(x,y0,1,h);
00718 //    wr_cmd(0x2C);  // send pixel
00719     wr_cmd(ILI9341_GRAM);  // send pixel         
00720 
00721 #if (SPI_16 == 1)
00722     // 16 Bit SPI
00723     _spi.format(16,0);   // switch to 16 bit Mode 0
00724     for (i = 0; i < h; i++)
00725       _spi.write(color);
00726     _spi.format(8,0);    // switch back to 8 bit Mode 0 
00727 #else
00728     // 8 Bit SPI
00729     msb = color >> 8;
00730     lsb = color & 0xff;
00731     for (i = 0; i < h; i++){
00732       _spi.write(msb);
00733       _spi.write(lsb);
00734     }
00735 #endif        
00736   
00737     _cs = 1;
00738     window_max();
00739 }
00740 
00741 void SPI_TFT_ILI9341::line(int x0, int y0, int x1, int y1, int color)
00742 {
00743     //window_max();
00744     int   dx = 0, dy = 0;
00745     int   dx_sym = 0, dy_sym = 0;
00746     int   dx_x2 = 0, dy_x2 = 0;
00747     int   di = 0;
00748 
00749     dx = x1-x0;
00750     dy = y1-y0;
00751 
00752     if (dx == 0) {        /* vertical line */
00753         if (y1 > y0) vline(x0,y0,y1,color);
00754         else vline(x0,y1,y0,color);
00755         return;
00756     }
00757 
00758     if (dx > 0) {
00759         dx_sym = 1;
00760     } else {
00761         dx_sym = -1;
00762     }
00763     if (dy == 0) {        /* horizontal line */
00764         if (x1 > x0) hline(x0,x1,y0,color);
00765         else  hline(x1,x0,y0,color);
00766         return;
00767     }
00768 
00769     if (dy > 0) {
00770         dy_sym = 1;
00771     } else {
00772         dy_sym = -1;
00773     }
00774 
00775     dx = dx_sym*dx;
00776     dy = dy_sym*dy;
00777 
00778     dx_x2 = dx*2;
00779     dy_x2 = dy*2;
00780 
00781     if (dx >= dy) {
00782         di = dy_x2 - dx;
00783         while (x0 != x1) {
00784 
00785             pixel(x0, y0, color);
00786             x0 += dx_sym;
00787             if (di<0) {
00788                 di += dy_x2;
00789             } else {
00790                 di += dy_x2 - dx_x2;
00791                 y0 += dy_sym;
00792             }
00793         }
00794         pixel(x0, y0, color);
00795     } else {
00796         di = dx_x2 - dy;
00797         while (y0 != y1) {
00798             pixel(x0, y0, color);
00799             y0 += dy_sym;
00800             if (di < 0) {
00801                 di += dx_x2;
00802             } else {
00803                 di += dx_x2 - dy_x2;
00804                 x0 += dx_sym;
00805             }
00806         }
00807         pixel(x0, y0, color);
00808     }
00809 //WH    return;
00810 }
00811 
00812 
00813 void SPI_TFT_ILI9341::rect(int x0, int y0, int x1, int y1, int color)
00814 {
00815 
00816     if (x1 > x0) hline(x0,x1,y0,color);
00817     else  hline(x1,x0,y0,color);
00818 
00819     if (y1 > y0) vline(x0,y0,y1,color);
00820     else vline(x0,y1,y0,color);
00821 
00822     if (x1 > x0) hline(x0,x1,y1,color);
00823     else  hline(x1,x0,y1,color);
00824 
00825     if (y1 > y0) vline(x1,y0,y1,color);
00826     else vline(x1,y1,y0,color);
00827 
00828 //WH    return;
00829 }
00830 
00831 
00832 void SPI_TFT_ILI9341::fillrect(int x0, int y0, int x1, int y1, int color)
00833 {  
00834     //sanity check
00835     if ( x0 > x1 ) swap( int, x0, x1 )
00836     if ( y0 > y1 ) swap( int, y0, y1 )
00837 
00838     int h = y1 - y0 + 1; 
00839     int w = x1 - x0 + 1; 
00840     int pixels = h * w;
00841     int i;
00842 #if (SPI_16 != 1)    
00843     int msb, lsb;        
00844 #endif    
00845  
00846     window(x0,y0,w,h);
00847 //    wr_cmd(0x2C);  // send pixel
00848     wr_cmd(ILI9341_GRAM);  // send pixel         
00849 
00850 #if (SPI_16 == 1)    
00851     // 16 Bit SPI
00852     _spi.format(16,0);   // switch to 16 bit Mode 0
00853 
00854     for (i = 0; i < pixels; i++)
00855       _spi.write(color);
00856 
00857     _spi.format(8,0);    // switch back to 8 bit Mode 0 
00858 #else
00859     // 8 Bit SPI
00860     msb = color >> 8;
00861     lsb = color & 0xff;
00862     for (i = 0; i < pixels; i++){
00863       _spi.write(msb);
00864       _spi.write(lsb);
00865     }
00866 #endif        
00867 
00868     _cs = 1; 
00869 }
00870 
00871 
00872 void SPI_TFT_ILI9341::roundrect( int x1, int y1, int x2, int y2, int color )
00873 {
00874     //sanity check      
00875     if ( x1 > x2 ) swap( int, x1, x2 )
00876     if ( y1 > y2 ) swap( int, y1, y2 )
00877  
00878     if ( ( x2 - x1 ) > 4 && ( y2 - y1 ) > 4 )
00879     {
00880         pixel( x1 + 1, y1 + 1, color );
00881         pixel( x2 - 1, y1 + 1, color );
00882         pixel( x1 + 1, y2 - 1, color );
00883         pixel( x2 - 1, y2 - 1, color );
00884 //x0, x1, y
00885         hline( x1 + 2, x2 - 2 ,y1, color );
00886         hline( x1 + 2, x2 - 2, y2, color );     
00887 //y0, y1, x        
00888         vline( y1 + 2, y2 - 2, x1, color );
00889         vline( y1 + 2, y2 - 2, x2, color );
00890     }
00891 }
00892 
00893  
00894 void SPI_TFT_ILI9341::fillroundrect( int x1, int y1, int x2, int y2, int color )
00895 {
00896     //sanity check
00897     if ( x1 > x2 ) swap( int, x1, x2 )
00898     if ( y1 > y2 ) swap( int, y1, y2 )
00899  
00900     if ( ( x2 - x1 ) > 4 && ( y2 - y1 ) > 4 )
00901     {
00902         for ( int i = 0; i < ( ( y2 - y1 ) / 2 ) + 1; i++ )
00903         {
00904             switch ( i )
00905             {
00906                 case 0:
00907                     hline( x1 + 2, x2 - 2, y1 + i, color );
00908                     hline( x1 + 2, x2 - 2, y2 - i, color );
00909                     break;
00910  
00911                 case 1:
00912                     hline( x1 + 1, x2 - 1, y1 + i, color );
00913                     hline( x1 + 1, x2 - 1, y2 - i, color );
00914                     break;
00915  
00916                 default:
00917                     hline( x1, x2, y1 + i, color );
00918                     hline( x1, x2, y2 - i, color );
00919                     break;
00920             }
00921         }
00922     }
00923 }
00924 
00925 
00926 
00927 void SPI_TFT_ILI9341::locate(int x, int y)
00928 {
00929     _char_x = x;
00930     _char_y = y;
00931 }
00932 
00933 
00934 
00935 int SPI_TFT_ILI9341::columns()
00936 {
00937     return width() / _font[1];
00938 }
00939 
00940 
00941 
00942 int SPI_TFT_ILI9341::rows()
00943 {
00944     return height() / _font[2];
00945 }
00946 
00947 
00948 
00949 int SPI_TFT_ILI9341::_putc(int value)
00950 {
00951     if (value == '\n') {    // new line
00952         _char_x = 0;
00953         _char_y = _char_y + _font[2];
00954         if (_char_y >= height() - _font[2]) {
00955             _char_y = 0;
00956         }
00957     } else {
00958         character(_char_x, _char_y, value);
00959     }
00960     return value;
00961 }
00962 
00963 //WH
00964 #if(0)
00965 void SPI_TFT_ILI9341::character(int x, int y, int c)
00966 {
00967     unsigned int hor,vert,offset,bpl,j,i,b;
00968     unsigned char* zeichen;
00969     unsigned char z,w;
00970 
00971     if ((c < 31) || (c > 127)) return;   // test char range
00972 
00973     // read font parameter from start of array
00974     offset = _font[0];                   // bytes / char
00975     hor    = _font[1];                   // get hor size of font
00976     vert   = _font[2];                   // get vert size of font
00977     bpl    = _font[3];                   // bytes per line
00978 
00979     if (_char_x + hor > width()) {
00980         _char_x = 0;
00981         _char_y = _char_y + vert;
00982         if (_char_y >= height() - _font[2]) {
00983             _char_y = 0;
00984         }
00985     }
00986     window(_char_x, _char_y,hor,vert); // char box
00987     wr_cmd(0x2C);  // send pixel
00988     #ifndef TARGET_KL25Z  // 16 Bit SPI 
00989     _spi.format(16,0);   
00990     #endif                         // switch to 16 bit Mode 0
00991     zeichen = &_font[((c -32) * offset) + 4]; // start of char bitmap
00992     w = zeichen[0];                          // width of actual char
00993      for (j=0; j<vert; j++) {  //  vert line
00994         for (i=0; i<hor; i++) {   //  horz line
00995             z =  zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
00996             b = 1 << (j & 0x07);
00997             if (( z & b ) == 0x00) {
00998                #ifndef TARGET_KL25Z  // 16 Bit SPI 
00999                 _spi.write(_background);
01000                #else
01001                 _spi.write(_background >> 8);
01002                 _spi.write(_background & 0xff);
01003                 #endif
01004             } else {
01005                 #ifndef TARGET_KL25Z  // 16 Bit SPI
01006                 _spi.write(_foreground);
01007                 #else
01008                 _spi.write(_foreground >> 8);
01009                 _spi.write(_foreground & 0xff);
01010                 #endif
01011             }
01012         }
01013     }
01014     _cs = 1;
01015     #ifndef TARGET_KL25Z  // 16 Bit SPI
01016     _spi.format(8,0);
01017     #endif
01018     window_max();
01019     if ((w + 2) < hor) {                   // x offset to next char
01020         __char_x += w + 2;
01021     } else __char_x += hor;
01022 }
01023 #else
01024 
01025 #if (TRANSPARANCY == 1)
01026 //WH write foreground, write background only when not transparant mode
01027 void SPI_TFT_ILI9341::character(int x, int y, int c)
01028 {
01029     unsigned int hor,vert,offset,bpl,j,i,b;
01030     unsigned char* symbol;
01031     unsigned char z,w;
01032 
01033     if ((c < 31) || (c > 127)) return;   // test char range
01034 
01035     // read font parameter from start of array
01036     offset = _font[0];                   // bytes / char
01037     hor    = _font[1];                   // get hor size of font
01038     vert   = _font[2];                   // get vert size of font
01039     bpl    = _font[3];                   // bytes per line
01040 
01041     if (_char_x + hor > width()) {
01042         _char_x = 0;
01043         _char_y = _char_y + vert;
01044         if (_char_y >= height() - vert) {
01045             _char_y = 0;
01046         }
01047     }
01048   
01049     symbol = &_font[((c - 32) * offset) + 4]; // start of char bitmap
01050     w = symbol[0];                            // width of actual char (proportional font)
01051     for (j=0; j<vert; j++) {  //  vert line
01052       for (i=0; i<hor; i++) {   //  horz line
01053         z =  symbol[bpl * i + ((j & 0xF8) >> 3) + 1];
01054         b = 1 << (j & 0x07);
01055         
01056         // Test bit in character bitmap to write either _foreground or _background color
01057         if (( z & b ) == 0x00) {
01058           // bit is 0, write _background color
01059           if (!_transparancy) { // write background color only when transparancy is 'off'  
01060             pixel(_char_x+i, _char_y+j, _background);
01061           }  
01062         }
01063         else {
01064           // bit is 1, write _foreground color          
01065           pixel(_char_x+i, _char_y+j, _foreground);
01066         } // if bit
01067       } // for i
01068     } // for j
01069 
01070     window_max();
01071 
01072     if ((w + 2) < hor) {                   // x offset to next char
01073         _char_x += w + 2;
01074     } else _char_x += hor;
01075 }
01076 
01077 #else
01078 
01079 //WH write foreground and background
01080 void SPI_TFT_ILI9341::character(int x, int y, int c)
01081 {
01082     unsigned int hor,vert,offset,bpl,j,i,b;
01083     unsigned char* symbol;
01084     unsigned char z,w;
01085 
01086     if ((c < 31) || (c > 127)) return;   // test char range
01087 
01088     // read font parameter from start of array
01089     offset = _font[0];                   // bytes / char
01090     hor    = _font[1];                   // get hor size of font
01091     vert   = _font[2];                   // get vert size of font
01092     bpl    = _font[3];                   // bytes per line
01093 
01094     if (_char_x + hor > width()) {
01095         _char_x = 0;
01096         _char_y = _char_y + vert;
01097         if (_char_y >= height() - vert) {
01098             _char_y = 0;
01099         }
01100     }
01101     window(_char_x, _char_y, hor, vert); // char box
01102 //    wr_cmd(0x2C);  // send pixel
01103     wr_cmd(ILI9341_GRAM);  // send pixel         
01104     
01105     #if (SPI_16 == 1)
01106     // 16 Bit SPI 
01107     _spi.format(16,0);   // switch to 16 bit Mode 0
01108     #endif                         
01109     symbol = &_font[((c - 32) * offset) + 4]; // start of char bitmap
01110     w = symbol[0];                            // width of actual char (proportional font)
01111     for (j=0; j<vert; j++) {  //  vert line
01112       for (i=0; i<hor; i++) {   //  horz line
01113         z =  symbol[bpl * i + ((j & 0xF8) >> 3) + 1];
01114         b = 1 << (j & 0x07);
01115         
01116         // Test bit in character bitmap to write either _foreground or _background color
01117         if (( z & b ) == 0x00) {
01118           // bit is 0, write _background color
01119           #if (SPI_16 == 1)
01120           // 16 Bit SPI 
01121           _spi.write(_background);
01122           #else
01123           // 8 Bit SPI           
01124           _spi.write(_background >> 8);
01125           _spi.write(_background & 0xff);
01126           #endif
01127         }
01128         else {
01129           // bit is 1, write _foreground color          
01130           #if (SPI_16 == 1)
01131           // 16 Bit SPI
01132           _spi.write(_foreground);
01133           #else
01134           // 8 Bit SPI                     
01135           _spi.write(_foreground >> 8);
01136           _spi.write(_foreground & 0xff);
01137           #endif
01138         } // if bit
01139       } // for i
01140     } // for j
01141 
01142     _cs = 1;
01143     #if (SPI_16 == 1)  // 16 Bit SPI
01144     _spi.format(8,0);  // switch back to 8 bit Mode 0
01145     #endif
01146     window_max();
01147 
01148     if ((w + 2) < hor) {                   // x offset to next char
01149         _char_x += w + 2;
01150     } else _char_x += hor;
01151 }
01152 #endif
01153 
01154 #endif
01155 
01156 
01157 void SPI_TFT_ILI9341::set_font(unsigned char* f)
01158 {
01159   _font = f;
01160 }
01161 
01162 
01163 
01164 void SPI_TFT_ILI9341::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap)
01165 {
01166     unsigned int  j;
01167     int padd;
01168     unsigned short *bitmap_ptr = (unsigned short *)bitmap;
01169     #if (SPI_16 != 1)  // 16 Bit SPI    
01170     unsigned short pix_temp;
01171     #endif
01172     
01173     unsigned int i;
01174     
01175     // the lines are padded to multiple of 4 bytes in a bitmap
01176     padd = -1;
01177     do {
01178         padd ++;
01179     } while (2*(w + padd)%4 != 0);
01180     window(x, y, w, h);
01181     bitmap_ptr += ((h - 1)* (w + padd));
01182 //    wr_cmd(0x2C);  // send pixel
01183     wr_cmd(ILI9341_GRAM);  // send pixel     
01184         
01185     #if (SPI_16 == 1)  // 16 Bit SPI
01186     _spi.format(16,0); // switch to 16 bit Mode 0
01187     #endif                            
01188     for (j = 0; j < h; j++) {         //Lines
01189         for (i = 0; i < w; i++) {     // one line
01190             #if (SPI_16 == 1)
01191                 // 16 Bit SPI            
01192                 _spi.write(*bitmap_ptr);    // one line
01193                 bitmap_ptr++;
01194             #else                
01195                // 8 Bit SPI
01196                 pix_temp = *bitmap_ptr;
01197                 _spi.write(pix_temp >> 8);
01198                 _spi.write(pix_temp);
01199                 bitmap_ptr++;
01200             #endif
01201         }
01202         bitmap_ptr -= 2*w;
01203         bitmap_ptr -= padd;
01204     }
01205     _cs = 1;
01206 
01207     #if (SPI_16 == 1)    
01208     _spi.format(8,0); // switch back to 8 bit Mode 0
01209     #endif
01210     window_max();
01211 }
01212 
01213 
01214 // local filesystem is not implemented in kinetis board, but you can add an SD card
01215 
01216 int SPI_TFT_ILI9341::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP)
01217 {
01218 
01219 #define OffsetPixelWidth    18
01220 #define OffsetPixelHeigh    22
01221 #define OffsetFileSize      34
01222 #define OffsetPixData       10
01223 #define OffsetBPP           28
01224 
01225     char filename[50];
01226     unsigned char BMP_Header[54];
01227     unsigned short BPP_t;
01228     unsigned int PixelWidth,PixelHeigh,start_data;
01229     unsigned int    i,off;
01230     int padd,j;
01231     unsigned short *line;
01232 
01233     // get the filename
01234     i=0;
01235     while (*Name_BMP!='\0') {
01236         filename[i++]=*Name_BMP++;
01237     }
01238     filename[i] = 0;  
01239     
01240     FILE *Image = fopen((const char *)&filename[0], "rb");  // open the bmp file
01241     if (!Image) {
01242         return(0);      // error file not found !
01243     }
01244 
01245     fread(&BMP_Header[0],1,54,Image);      // get the BMP Header
01246 
01247     if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) {  // check magic byte
01248         fclose(Image);
01249         return(-1);     // error no BMP file
01250     }
01251 
01252     BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8);
01253     if (BPP_t != 0x0010) {
01254         fclose(Image);
01255         return(-2);     // error no 16 bit BMP
01256     }
01257 
01258     PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24);
01259     PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24);
01260     if (PixelHeigh > height() + y || PixelWidth > width() + x) {
01261         fclose(Image);
01262         return(-3);      // to big
01263     }
01264 
01265     start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
01266 
01267     line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line
01268     if (line == NULL) {
01269         return(-4);         // error no memory
01270     }
01271 
01272     // the bmp lines are padded to multiple of 4 bytes
01273     padd = -1;
01274     do {
01275         padd ++;
01276     } while ((PixelWidth * 2 + padd)%4 != 0);
01277 
01278     window(x, y,PixelWidth ,PixelHeigh);
01279 //    wr_cmd(0x2C);  // send pixel
01280     wr_cmd(ILI9341_GRAM);  // send pixel         
01281     
01282     #if (SPI_16 == 1)        
01283     _spi.format(16,0);   // switch to 16 bit Mode 0
01284     #endif                          
01285     for (j = PixelHeigh - 1; j >= 0; j--) {               //Lines bottom up
01286         off = j * (PixelWidth  * 2 + padd) + start_data;   // start of line
01287         fseek(Image, off ,SEEK_SET);
01288         fread(line,1,PixelWidth * 2,Image);       // read a line - slow 
01289         for (i = 0; i < PixelWidth; i++) {        // copy pixel data to TFT
01290         #if (SPI_16 == 1)
01291         // one 16 bit pixel                                                   
01292         _spi.write(line[i]);
01293         #else              
01294         // only 8 Bit SPI
01295         _spi.write(line[i] >> 8);
01296         _spi.write(line[i]);
01297         #endif    
01298         } 
01299      }
01300     _cs = 1;
01301     
01302     #if (SPI_16 == 1)            
01303     _spi.format(8,0);    // switch back to 8 bit Mode 0
01304     #endif
01305     
01306     free (line);
01307     fclose(Image);
01308     window_max();
01309     return(1);
01310 }
01311 
01312 
01313 /*******************************************************************************
01314 * Function Name  : WriteBMP_FAT
01315 * @brief Displays a bitmap picture loaded in Flash.
01316 * @param Xpos: specifies the X position.
01317 * @param Ypos: specifies the Y position.
01318 * @param BmpAddress: Bmp picture address in Flash.
01319 * @return None
01320 *******************************************************************************/
01321 void SPI_TFT_ILI9341::WriteBMP_FAT(uint16_t Xpos, uint16_t Ypos, const char* BmpName)
01322 {
01323   uint32_t index = 0, size = 0, width=0, height=0;
01324   uint16_t *pBmpWord=0;
01325 //  uint16_t data;
01326  
01327   /* Read bitmap width*/
01328   width = BmpName[0]+1; 
01329   /* Read bitmap height*/
01330   height = BmpName[1]+1; 
01331   /* Read bitmap size */
01332   size   = width * height;  /* nb of 16 bits */
01333     
01334   window(Xpos, Ypos, width , height);    
01335 
01336 //  wr_cmd(0x2C);  // send pixel
01337   wr_cmd(ILI9341_GRAM);  // send pixel       
01338 
01339   /* Set WRX to send data */
01340 //WH  _dc = 1;
01341 
01342   #if (SPI_16 == 1)        
01343   _spi.format(16,0);   // switch to 16 bit Mode 0
01344   #endif                          
01345 
01346   pBmpWord = (uint16_t *) (&BmpName[5]);
01347   /* Send to the screen */
01348   for(index = 0; index < size; index++)
01349   {
01350     #if (SPI_16 == 1)
01351     // one 16 bit pixel                                                   
01352     _spi.write(*pBmpWord);    
01353     #else              
01354     // only 8 Bit SPI
01355     _spi.write(*pBmpWord & 0xFF);
01356     _spi.write((*pBmpWord>>8) & 0xFF);   
01357     #endif       
01358                   
01359     pBmpWord++;
01360   } 
01361 
01362   /* Set LCD control line(/CS) */
01363   _cs = 1;  
01364 
01365   #if (SPI_16 == 1)            
01366   _spi.format(8,0);    // switch back to 8 bit Mode 0
01367   #endif
01368         
01369   window_max();
01370 }
01371 
01372