Lib for the new LCD Display with ILI9341 controller

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPI_TFT_ILI9341_NUCLEO.cpp Source File

SPI_TFT_ILI9341_NUCLEO.cpp

00001 /* mbed library for 240*320 pixel display TFT based on ILI9341 LCD Controller
00002  * Copyright (c) 2013, 2014 Peter Drescher - DC2PD
00003  * Special version for STM Nucleo -L152
00004  *
00005  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00006  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00007  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00008  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00009  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00010  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00011  * THE SOFTWARE.
00012  */
00013 
00014  // 24.06.14   initial version
00015  // 25.06.14   add Nucleo F103RB 
00016 
00017 // only include this file if target is L152 or F103RB : 
00018 #if defined TARGET_NUCLEO_L152RE || defined TARGET_NUCLEO_F103RB
00019 
00020 #include "SPI_TFT_ILI9341.h"
00021 #include "mbed.h"
00022 
00023 #if defined TARGET_NUCLEO_L152RE
00024 #include "stm32l1xx_dma.h"
00025 #define use_ram
00026 #endif
00027 
00028 #if defined TARGET_NUCLEO_F103RB
00029 #include "stm32f10x_dma.h"
00030 #endif
00031 
00032 #define BPP         16                  // Bits per pixel
00033 
00034 //extern Serial pc;
00035 //extern DigitalOut xx;     // debug !!
00036 
00037 DMA_InitTypeDef DMA_InitStructure; 
00038 
00039 
00040 SPI_TFT_ILI9341::SPI_TFT_ILI9341(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset, PinName dc, const char *name)
00041     : GraphicsDisplay(name), SPI(mosi,miso,sclk,NC), _cs(cs), _reset(reset), _dc(dc)
00042 {
00043 
00044     format(8,3);                 // 8 bit spi mode 3
00045     frequency(10000000);         // 10 Mhz SPI clock : result 2 / 4 = 8
00046     orientation = 0;
00047     char_x = 0;
00048     if(_spi.spi == SPI_1){       // test which SPI is in use
00049          spi_num = 1;
00050     }
00051     if(_spi.spi == SPI_2){
00052          spi_num = 2;
00053     }
00054     #ifdef SPI_3                // there is no SPI 3 on all devices
00055     if(_spi.spi == SPI_3){
00056          spi_num = 3;
00057     }
00058     #endif
00059     tft_reset();
00060 }
00061 
00062 // we define a fast write to the SPI port
00063 // we use the bit banding address to get the flag without masking
00064 
00065 #define bit_SPI1_txe  *((volatile unsigned int *)0x42260104)
00066 #define SPI1_DR       *((volatile unsigned int *)0x4001300C)
00067 #define bit_SPI2_txe  *((volatile unsigned int *)0x42070104)
00068 #define SPI2_DR       *((volatile unsigned int *)0x4000380C)
00069 #define bit_SPI3_txe  *((volatile unsigned int *)0x42078104)
00070 #define SPI3_DR       *((volatile unsigned int *)0x40003C0C)
00071 
00072 void SPI_TFT_ILI9341::f_write(int data){
00073 
00074 switch(spi_num){  // used SPI port
00075 case (1):
00076     while(bit_SPI1_txe == 0);  // wait for SPI1->SR TXE flag
00077     SPI1_DR = data;
00078     break;
00079 
00080 case (2):
00081     while( bit_SPI2_txe  == 0);  // wait for SPI2->SR TXE flag
00082     SPI2_DR = data;
00083     break;
00084 
00085 case (3):
00086     while( bit_SPI3_txe == 0);  // wait for SPI3->SR TXE flag
00087     SPI3_DR = data;
00088     break;
00089 
00090     }
00091 }
00092 
00093 // wait for SPI not busy
00094 // we have to wait for the last bit to switch the cs off
00095 // we use the bit banding address to get the flag without masking
00096 
00097 #define bit_SPI1_bsy  *((volatile unsigned int *)0x4226011C)
00098 #define bit_SPI2_bsy  *((volatile unsigned int *)0x4207011C)
00099 #define bit_SPI3_bsy  *((volatile unsigned int *)0x4207811C)
00100 
00101 void inline SPI_TFT_ILI9341::spi_bsy(void){    
00102 switch(spi_num){        // decide which SPI is to use
00103 case (1):
00104     while(bit_SPI1_bsy == 1);   // SPI1->SR bit 7
00105     break;
00106 
00107 case (2):
00108     while(bit_SPI2_bsy == 1);   // SPI2->SR bit 7
00109     break;
00110 
00111 case (3):
00112     while(bit_SPI3_bsy == 1);   // SPI2->SR bit 7
00113     break;
00114     }
00115 }
00116 
00117 
00118 // switch fast between 8 and 16 bit mode
00119 #define bit_SPI1_dff  *((volatile unsigned int *)0x4226002C)
00120 #define bit_SPI2_dff  *((volatile unsigned int *)0x4207002C)
00121 #define bit_SPI3_dff  *((volatile unsigned int *)0x4207802C)
00122 void SPI_TFT_ILI9341::spi_16(bool s){
00123 switch(spi_num){        // decide which SPI is to use
00124 case(1):
00125     if(s) bit_SPI1_dff = 1; // switch to 16 bit Mode
00126     else  bit_SPI1_dff = 0; // switch to 8  bit Mode
00127     break;
00128 
00129 case(2):
00130     if(s) bit_SPI2_dff = 1; // switch to 16 bit Mode
00131     else  bit_SPI2_dff = 0; // switch to 8  bit Mode
00132     break;
00133 
00134 case(3):
00135     if(s) bit_SPI3_dff = 1; // switch to 16 bit Mode
00136     else  bit_SPI3_dff = 0; // switch to 8  bit Mode
00137     break;
00138     }
00139 }
00140 
00141 
00142 int SPI_TFT_ILI9341::width()
00143 {
00144     if (orientation == 0 || orientation == 2) return 240;
00145     else return 320;
00146 }
00147 
00148 
00149 int SPI_TFT_ILI9341::height()
00150 {
00151     if (orientation == 0 || orientation == 2) return 320;
00152     else return 240;
00153 }
00154 
00155 
00156 void SPI_TFT_ILI9341::set_orientation(unsigned int o)
00157 {
00158     orientation = o;
00159     wr_cmd(0x36);                     // MEMORY_ACCESS_CONTROL
00160     switch (orientation) {
00161         case 0:
00162             f_write(0x48);
00163             break;
00164         case 1:
00165             f_write(0x28);
00166             break;
00167         case 2:
00168             f_write(0x88);
00169             break;
00170         case 3:
00171             f_write(0xE8);
00172             break;
00173     }
00174     spi_bsy();    // wait for end of transfer
00175     _cs = 1;
00176     WindowMax();
00177 }
00178 
00179 
00180 // write command to tft register
00181 // use fast command
00182 void SPI_TFT_ILI9341::wr_cmd(unsigned char cmd)
00183 {
00184     _dc = 0;
00185     _cs = 0;
00186     f_write(cmd);
00187     spi_bsy();
00188     _dc = 1;
00189 }
00190 
00191 void SPI_TFT_ILI9341::wr_dat(unsigned char dat)
00192 {
00193    f_write(dat);
00194    spi_bsy();  // wait for SPI send
00195 }
00196 
00197 // the ILI9341 can read
00198 char SPI_TFT_ILI9341::rd_byte(unsigned char cmd)
00199 {
00200     // has to change !!
00201     return(0);
00202 }
00203 
00204 // read 32 bit
00205 int SPI_TFT_ILI9341::rd_32(unsigned char cmd)
00206 {
00207     // has to change !!!
00208     return(0);
00209 }
00210 
00211 int  SPI_TFT_ILI9341::Read_ID(void){
00212     int r;
00213     r = rd_byte(0x0A);
00214     r = rd_byte(0x0A);
00215     r = rd_byte(0x0A);
00216     r = rd_byte(0x0A);
00217     return(r);
00218 }
00219 
00220 
00221 // Init code based on MI0283QT datasheet
00222 // this code is called only at start
00223 // no need to be optimized
00224 
00225 void SPI_TFT_ILI9341::tft_reset()
00226 {
00227     _cs = 1;                           // cs high
00228     _dc = 1;                           // dc high
00229     _reset = 0;                        // display reset
00230 
00231     wait_us(50);
00232     _reset = 1;                       // end hardware reset
00233     wait_ms(5);
00234 
00235     wr_cmd(0x01);                     // SW reset
00236     wait_ms(5);
00237     wr_cmd(0x28);                     // display off
00238 
00239     /* Start Initial Sequence ----------------------------------------------------*/
00240     wr_cmd(0xCF);
00241     f_write(0x00);
00242     f_write(0x83);
00243     f_write(0x30);
00244     spi_bsy();
00245      _cs = 1;
00246 
00247      wr_cmd(0xED);
00248      f_write(0x64);
00249      f_write(0x03);
00250      f_write(0x12);
00251      f_write(0x81);
00252      spi_bsy();
00253      _cs = 1;
00254 
00255      wr_cmd(0xE8);
00256      f_write(0x85);
00257      f_write(0x01);
00258      f_write(0x79);
00259      spi_bsy();
00260      _cs = 1;
00261 
00262      wr_cmd(0xCB);
00263      f_write(0x39);
00264      f_write(0x2C);
00265      f_write(0x00);
00266      f_write(0x34);
00267      f_write(0x02);
00268      spi_bsy();
00269      _cs = 1;
00270 
00271      wr_cmd(0xF7);
00272      f_write(0x20);
00273      spi_bsy();
00274      _cs = 1;
00275 
00276      wr_cmd(0xEA);
00277      f_write(0x00);
00278      f_write(0x00);
00279      spi_bsy();
00280      _cs = 1;
00281 
00282      wr_cmd(0xC0);                     // POWER_CONTROL_1
00283      f_write(0x26);
00284      spi_bsy();
00285      _cs = 1;
00286 
00287      wr_cmd(0xC1);                     // POWER_CONTROL_2
00288      f_write(0x11);
00289      spi_bsy();
00290      _cs = 1;
00291 
00292      wr_cmd(0xC5);                     // VCOM_CONTROL_1
00293      f_write(0x35);
00294      f_write(0x3E);
00295      spi_bsy();
00296      _cs = 1;
00297 
00298      wr_cmd(0xC7);                     // VCOM_CONTROL_2
00299      f_write(0xBE);
00300      spi_bsy();
00301      _cs = 1;
00302 
00303      wr_cmd(0x36);                     // MEMORY_ACCESS_CONTROL
00304      f_write(0x48);
00305      spi_bsy();
00306      _cs = 1;
00307 
00308      wr_cmd(0x3A);                     // COLMOD_PIXEL_FORMAT_SET
00309      f_write(0x55);                 // 16 bit pixel
00310      spi_bsy();
00311      _cs = 1;
00312 
00313      wr_cmd(0xB1);                     // Frame Rate
00314      f_write(0x00);
00315      f_write(0x1B);
00316      spi_bsy();
00317      _cs = 1;
00318 
00319      wr_cmd(0xF2);                     // Gamma Function Disable
00320      f_write(0x08);
00321      spi_bsy();
00322      _cs = 1;
00323 
00324      wr_cmd(0x26);
00325      f_write(0x01);                 // gamma set for curve 01/2/04/08
00326      spi_bsy();
00327      _cs = 1;
00328 
00329      wr_cmd(0xE0);                     // positive gamma correction
00330      f_write(0x1F);
00331      f_write(0x1A);
00332      f_write(0x18);
00333      f_write(0x0A);
00334      f_write(0x0F);
00335      f_write(0x06);
00336      f_write(0x45);
00337      f_write(0x87);
00338      f_write(0x32);
00339      f_write(0x0A);
00340      f_write(0x07);
00341      f_write(0x02);
00342      f_write(0x07);
00343      f_write(0x05);
00344      f_write(0x00);
00345      spi_bsy();
00346      _cs = 1;
00347 
00348      wr_cmd(0xE1);                     // negativ gamma correction
00349      f_write(0x00);
00350      f_write(0x25);
00351      f_write(0x27);
00352      f_write(0x05);
00353      f_write(0x10);
00354      f_write(0x09);
00355      f_write(0x3A);
00356      f_write(0x78);
00357      f_write(0x4D);
00358      f_write(0x05);
00359      f_write(0x18);
00360      f_write(0x0D);
00361      f_write(0x38);
00362      f_write(0x3A);
00363      f_write(0x1F);
00364      spi_bsy();
00365      _cs = 1;
00366 
00367      WindowMax ();
00368 
00369      //wr_cmd(0x34);                     // tearing effect off
00370      //_cs = 1;
00371 
00372      //wr_cmd(0x35);                     // tearing effect on
00373      //_cs = 1;
00374 
00375      wr_cmd(0xB7);                       // entry mode
00376      f_write(0x07);
00377      spi_bsy();
00378      _cs = 1;
00379 
00380      wr_cmd(0xB6);                       // display function control
00381      f_write(0x0A);
00382      f_write(0x82);
00383      f_write(0x27);
00384      f_write(0x00);
00385      spi_bsy();
00386      _cs = 1;
00387 
00388      wr_cmd(0x11);                     // sleep out
00389      spi_bsy();
00390      _cs = 1;
00391 
00392      wait_ms(100);
00393 
00394      wr_cmd(0x29);                     // display on
00395      spi_bsy();
00396      _cs = 1;
00397 
00398      wait_ms(100);
00399 
00400     //    Configure the DMA controller init-structure
00401     DMA_StructInit(&DMA_InitStructure);
00402     switch(spi_num){        // decide which SPI is to use
00403     case (1):
00404         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);    // SPI1 and SPI2 are using DMA 1
00405         DMA_InitStructure.DMA_PeripheralBaseAddr  = (uint32_t) &(SPI1->DR);
00406         break;
00407     case (2):
00408         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);    // SPI1 and SPI2 are using DMA 1
00409         DMA_InitStructure.DMA_PeripheralBaseAddr  = (uint32_t) &(SPI2->DR);
00410         break;
00411     case (3):
00412         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);    // SPI3 is using DMA 2
00413         DMA_InitStructure.DMA_PeripheralBaseAddr  = (uint32_t) &(SPI3->DR);
00414         break;
00415     }
00416     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
00417     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
00418     DMA_InitStructure.DMA_BufferSize  = 0;
00419     DMA_InitStructure.DMA_PeripheralInc  = DMA_PeripheralInc_Disable;
00420     DMA_InitStructure.DMA_PeripheralDataSize  = DMA_PeripheralDataSize_HalfWord;
00421     DMA_InitStructure.DMA_MemoryDataSize  = DMA_MemoryDataSize_HalfWord;
00422     DMA_InitStructure.DMA_Mode  = DMA_Mode_Normal;
00423     DMA_InitStructure.DMA_Priority  = DMA_Priority_High;
00424  }
00425 
00426 
00427 // speed optimized
00428 // write direct to SPI1 register !
00429 void SPI_TFT_ILI9341::pixel(int x, int y, int color)
00430 {
00431     wr_cmd(0x2A);
00432     spi_16(1);         // switch to 8 bit Mode
00433     f_write(x);
00434     spi_bsy();
00435     _cs = 1;
00436 
00437     spi_16(0);        // switch to 8 bit Mode
00438     wr_cmd(0x2B);
00439     spi_16(1);
00440     f_write(y);
00441     spi_bsy();
00442     _cs = 1;
00443     spi_16(0);
00444 
00445     wr_cmd(0x2C); // send pixel
00446     spi_16(1);
00447     f_write(color);
00448     spi_bsy();
00449     _cs = 1;
00450     spi_16(0);
00451 }
00452 
00453 // optimized
00454 // write direct to SPI1 register !
00455 void SPI_TFT_ILI9341::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h)
00456 {
00457     wr_cmd(0x2A);
00458     spi_16(1);
00459     f_write(x);
00460     f_write(x+w-1);
00461     spi_bsy();
00462     _cs = 1;
00463     spi_16(0);
00464 
00465     wr_cmd(0x2B);
00466     spi_16(1);
00467     f_write(y) ;
00468     f_write(y+h-1);
00469     spi_bsy();
00470     _cs = 1;
00471     spi_16(0);
00472 }
00473 
00474 
00475 void SPI_TFT_ILI9341::WindowMax (void)
00476 {
00477     window (0, 0, width(),  height());
00478 }
00479 
00480 // optimized
00481 // use DMA to transfer pixel data to the screen
00482 void SPI_TFT_ILI9341::cls (void)
00483 {
00484     // we can use the fillrect function 
00485    fillrect(0,0,width()-1,height()-1,_background);
00486 }    
00487 
00488 void SPI_TFT_ILI9341::circle(int x0, int y0, int r, int color)
00489 {
00490 
00491     int x = -r, y = 0, err = 2-2*r, e2;
00492     do {
00493         pixel(x0-x, y0+y,color);
00494         pixel(x0+x, y0+y,color);
00495         pixel(x0+x, y0-y,color);
00496         pixel(x0-x, y0-y,color);
00497         e2 = err;
00498         if (e2 <= y) {
00499             err += ++y*2+1;
00500             if (-x == y && e2 <= x) e2 = 0;
00501         }
00502         if (e2 > x) err += ++x*2+1;
00503     } while (x <= 0);
00504 }
00505 
00506 void SPI_TFT_ILI9341::fillcircle(int x0, int y0, int r, int color)
00507 {
00508     int x = -r, y = 0, err = 2-2*r, e2;
00509     do {
00510         vline(x0-x, y0-y, y0+y, color);
00511         vline(x0+x, y0-y, y0+y, color);
00512         e2 = err;
00513         if (e2 <= y) {
00514             err += ++y*2+1;
00515             if (-x == y && e2 <= x) e2 = 0;
00516         }
00517         if (e2 > x) err += ++x*2+1;
00518     } while (x <= 0);
00519 }
00520 
00521 
00522 // optimized for speed
00523 void SPI_TFT_ILI9341::hline(int x0, int x1, int y, int color)
00524 {
00525     int w,j;
00526     w = x1 - x0 + 1;
00527     window(x0,y,w,1);
00528     _dc = 0;
00529     _cs = 0;
00530     f_write(0x2C); // send pixel
00531     spi_bsy();
00532     _dc = 1;
00533     spi_16(1);
00534 
00535     for (j=0; j<w; j++) {
00536         f_write(color);
00537     }
00538     spi_bsy();
00539     spi_16(0);
00540     _cs = 1;
00541     WindowMax();
00542     return;
00543 }
00544 
00545 // optimized for speed
00546 void SPI_TFT_ILI9341::vline(int x, int y0, int y1, int color)
00547 {
00548     int h,y;
00549     h = y1 - y0 + 1;
00550     window(x,y0,1,h);
00551     _dc = 0;
00552     _cs = 0;
00553     f_write(0x2C); // send pixel
00554     spi_bsy();
00555     _dc = 1;
00556     spi_16(1);
00557                 // switch to 16 bit Mode 3
00558     for (y=0; y<h; y++) {
00559         f_write(color);
00560     }
00561     spi_bsy();
00562     spi_16(0);
00563     _cs = 1;
00564     WindowMax();
00565     return;
00566 }
00567 
00568 
00569 void SPI_TFT_ILI9341::line(int x0, int y0, int x1, int y1, int color)
00570 {
00571     //WindowMax();
00572     int   dx = 0, dy = 0;
00573     int   dx_sym = 0, dy_sym = 0;
00574     int   dx_x2 = 0, dy_x2 = 0;
00575     int   di = 0;
00576 
00577     dx = x1-x0;
00578     dy = y1-y0;
00579 
00580     if (dx == 0) {        /* vertical line */
00581         if (y1 > y0) vline(x0,y0,y1,color);
00582         else vline(x0,y1,y0,color);
00583         return;
00584     }
00585 
00586     if (dx > 0) {
00587         dx_sym = 1;
00588     } else {
00589         dx_sym = -1;
00590     }
00591     if (dy == 0) {        /* horizontal line */
00592         if (x1 > x0) hline(x0,x1,y0,color);
00593         else  hline(x1,x0,y0,color);
00594         return;
00595     }
00596 
00597     if (dy > 0) {
00598         dy_sym = 1;
00599     } else {
00600         dy_sym = -1;
00601     }
00602 
00603     dx = dx_sym*dx;
00604     dy = dy_sym*dy;
00605 
00606     dx_x2 = dx*2;
00607     dy_x2 = dy*2;
00608 
00609     if (dx >= dy) {
00610         di = dy_x2 - dx;
00611         while (x0 != x1) {
00612 
00613             pixel(x0, y0, color);
00614             x0 += dx_sym;
00615             if (di<0) {
00616                 di += dy_x2;
00617             } else {
00618                 di += dy_x2 - dx_x2;
00619                 y0 += dy_sym;
00620             }
00621         }
00622         pixel(x0, y0, color);
00623     } else {
00624         di = dx_x2 - dy;
00625         while (y0 != y1) {
00626             pixel(x0, y0, color);
00627             y0 += dy_sym;
00628             if (di < 0) {
00629                 di += dx_x2;
00630             } else {
00631                 di += dx_x2 - dy_x2;
00632                 x0 += dx_sym;
00633             }
00634         }
00635         pixel(x0, y0, color);
00636     }
00637     return;
00638 }
00639 
00640 
00641 void SPI_TFT_ILI9341::rect(int x0, int y0, int x1, int y1, int color)
00642 {
00643 
00644     if (x1 > x0) hline(x0,x1,y0,color);
00645     else  hline(x1,x0,y0,color);
00646 
00647     if (y1 > y0) vline(x0,y0,y1,color);
00648     else vline(x0,y1,y0,color);
00649 
00650     if (x1 > x0) hline(x0,x1,y1,color);
00651     else  hline(x1,x0,y1,color);
00652 
00653     if (y1 > y0) vline(x1,y0,y1,color);
00654     else vline(x1,y1,y0,color);
00655 
00656     return;
00657 }
00658 
00659 
00660 
00661 // optimized for speed
00662 // use DMA
00663 void SPI_TFT_ILI9341::fillrect(int x0, int y0, int x1, int y1, int color)
00664 {
00665 
00666     int h = y1 - y0 + 1;
00667     int w = x1 - x0 + 1;
00668     int pixel = h * w;
00669     unsigned int dma_transfer;
00670     window(x0,y0,w,h);
00671 
00672     wr_cmd(0x2C);  // send pixel
00673     spi_16(1);
00674     DMA_InitStructure.DMA_MemoryBaseAddr  = (uint32_t) &color;
00675     DMA_InitStructure.DMA_MemoryInc  = DMA_MemoryInc_Disable;
00676 
00677     switch(spi_num){        // decide which SPI is to use
00678     case (1):
00679         DMA_Init(DMA1_Channel3, &DMA_InitStructure);  // init the DMA
00680         do{
00681             if(pixel < 0x10000) {
00682                 dma_transfer = pixel;
00683                 pixel = 0;
00684             }
00685             else {
00686                 dma_transfer = 0xffff;
00687                 pixel = pixel - 0xffff;
00688             }
00689             DMA_SetCurrDataCounter(DMA1_Channel3, dma_transfer);
00690             SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx,ENABLE);
00691             DMA_Cmd(DMA1_Channel3, ENABLE);
00692             while(DMA_GetCurrDataCounter(DMA1_Channel3) != 0);     // wait for end of transfer
00693             DMA_Cmd(DMA1_Channel3, DISABLE);
00694         }while(pixel > 0);
00695         break;
00696 
00697     case (2):
00698         DMA_Init(DMA1_Channel5, &DMA_InitStructure);  // init the DMA
00699         do{
00700             if(pixel < 0x10000) {
00701                 dma_transfer = pixel;
00702                 pixel = 0;
00703             }
00704             else {
00705                 dma_transfer = 0xffff;
00706                 pixel = pixel - 0xffff;
00707             }
00708             DMA_SetCurrDataCounter(DMA1_Channel5, dma_transfer);
00709             SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx,ENABLE);
00710             DMA_Cmd(DMA1_Channel5, ENABLE);
00711             while(DMA_GetCurrDataCounter(DMA1_Channel5) != 0);     // wait for end of transfer
00712             DMA_Cmd(DMA1_Channel5, DISABLE);
00713         }while(pixel > 0);
00714         break;
00715 
00716     case (3):
00717         DMA_Init(DMA2_Channel2, &DMA_InitStructure);  // init the DMA
00718         do{
00719             if(pixel < 0x10000) {
00720                 dma_transfer = pixel;
00721                 pixel = 0;
00722             }
00723             else {
00724                 dma_transfer = 0xffff;
00725                 pixel = pixel - 0xffff;
00726             }
00727             DMA_SetCurrDataCounter(DMA2_Channel2, dma_transfer);
00728             SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx,ENABLE);
00729             DMA_Cmd(DMA2_Channel2, ENABLE);
00730             while(DMA_GetCurrDataCounter(DMA2_Channel2) != 0);     // wait for end of transfer
00731             DMA_Cmd(DMA2_Channel2, DISABLE);
00732         }while(pixel > 0);
00733         break;
00734     }
00735     spi_bsy();
00736     spi_16(0);
00737     _cs = 1;
00738     WindowMax();
00739     return;
00740 }
00741 
00742 void SPI_TFT_ILI9341::locate(int x, int y)
00743 {
00744     char_x = x;
00745     char_y = y;
00746 }
00747 
00748 int SPI_TFT_ILI9341::columns()
00749 {
00750     return width() / font[1];
00751 }
00752 
00753 
00754 int SPI_TFT_ILI9341::rows()
00755 {
00756     return height() / font[2];
00757 }
00758 
00759 
00760 int SPI_TFT_ILI9341::_putc(int value)
00761 {
00762     if (value == '\n') {    // new line
00763         char_x = 0;
00764         char_y = char_y + font[2];
00765         if (char_y >= height() - font[2]) {
00766             char_y = 0;
00767         }
00768     } else {
00769         character(char_x, char_y, value);
00770     }
00771     return value;
00772 }
00773 
00774 
00775 // speed optimized
00776 // will use dma
00777 void SPI_TFT_ILI9341::character(int x, int y, int c)
00778 {
00779     unsigned int hor,vert,offset,bpl,j,i,b;
00780     unsigned char* zeichen;
00781     unsigned char z,w;
00782     #ifdef use_ram
00783     unsigned int pixel;
00784     unsigned int p;
00785     unsigned int dma_count,dma_off;
00786     uint16_t *buffer;
00787     #endif
00788 
00789     if ((c < 31) || (c > 127)) return;   // test char range
00790 
00791     // read font parameter from start of array
00792     offset = font[0];                    // bytes / char
00793     hor = font[1];                       // get hor size of font
00794     vert = font[2];                      // get vert size of font
00795     bpl = font[3];                       // bytes per line
00796 
00797     if (char_x + hor > width()) {
00798         char_x = 0;
00799         char_y = char_y + vert;
00800         if (char_y >= height() - font[2]) {
00801             char_y = 0;
00802         }
00803     }
00804     window(char_x, char_y,hor,vert);           // setup char box
00805     wr_cmd(0x2C);
00806     spi_16(1);                                 // switch to 16 bit Mode
00807     #ifdef use_ram
00808     pixel = hor * vert;                        // calculate buffer size
00809     buffer = (uint16_t *) malloc (2*pixel);    // we need a buffer for the font
00810     if(buffer != NULL) {                       // there is memory space -> use dma
00811         zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap
00812         w = zeichen[0];                          // width of actual char
00813         p = 0;
00814         // construct the font into the buffer
00815         for (j=0; j<vert; j++) {            //  vert line
00816             for (i=0; i<hor; i++) {         //  horz line
00817                 z =  zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
00818                 b = 1 << (j & 0x07);
00819                 if (( z & b ) == 0x00) {
00820                     buffer[p] = _background;
00821                 } else {
00822                     buffer[p] = _foreground;
00823                 }
00824                 p++;
00825             }
00826         }
00827         // copy the buffer with DMA SPI to display
00828         dma_off = 0;  // offset for DMA transfer
00829         DMA_InitStructure.DMA_MemoryBaseAddr  = (uint32_t)  (buffer + dma_off);
00830         DMA_InitStructure.DMA_MemoryInc  = DMA_MemoryInc_Enable;
00831 
00832         switch(spi_num){        // decide which SPI is to use
00833         case (1):
00834         DMA_Init(DMA1_Channel3, &DMA_InitStructure);  // init the DMA
00835         // start DMA
00836          do {
00837             if (pixel > 0X10000) {         // this is a giant font !
00838                 dma_count = 0Xffff;
00839                 pixel = pixel - 0Xffff;
00840             } else {
00841                 dma_count = pixel;
00842                 pixel = 0;
00843             }
00844             DMA_SetCurrDataCounter(DMA1_Channel3, dma_count);
00845             SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx,ENABLE);
00846             DMA_Cmd(DMA1_Channel3, ENABLE);
00847             while(DMA_GetCurrDataCounter(DMA1_Channel3) != 0);     // wait for end of transfer
00848             DMA_Cmd(DMA1_Channel3, DISABLE);
00849         }while(pixel > 0);
00850         break;
00851 
00852         case (2):
00853         DMA_Init(DMA1_Channel5, &DMA_InitStructure);  // init the DMA
00854         // start DMA
00855          do {
00856             if (pixel > 0X10000) {         // this is a giant font !
00857                 dma_count = 0Xffff;
00858                 pixel = pixel - 0Xffff;
00859             } else {
00860                 dma_count = pixel;
00861                 pixel = 0;
00862             }
00863             DMA_SetCurrDataCounter(DMA1_Channel5, dma_count);
00864             SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx,ENABLE);
00865             DMA_Cmd(DMA1_Channel5, ENABLE);
00866             while(DMA_GetCurrDataCounter(DMA1_Channel5) != 0);     // wait for end of transfer
00867             DMA_Cmd(DMA1_Channel5, DISABLE);
00868         }while(pixel > 0);
00869         break;
00870 
00871         case (3):
00872         DMA_Init(DMA2_Channel2, &DMA_InitStructure);  // init the DMA
00873         // start DMA
00874          do {
00875             if (pixel > 0X10000) {         // this is a giant font !
00876                 dma_count = 0Xffff;
00877                 pixel = pixel - 0Xffff;
00878             } else {
00879                 dma_count = pixel;
00880                 pixel = 0;
00881             }
00882             DMA_SetCurrDataCounter(DMA2_Channel2, dma_count);
00883             SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx,ENABLE);
00884             DMA_Cmd(DMA2_Channel2, ENABLE);
00885             while(DMA_GetCurrDataCounter(DMA2_Channel2) != 0);     // wait for end of transfer
00886             DMA_Cmd(DMA2_Channel2, DISABLE);
00887         }while(pixel > 0);
00888         break;
00889 
00890         }
00891         spi_bsy();
00892         free ((uint16_t *) buffer);
00893         spi_16(0);
00894     }
00895     
00896     else{
00897         #endif
00898         zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap
00899         w = zeichen[0];                          // width of actual char
00900         for (j=0; j<vert; j++) {  //  vert line
00901             for (i=0; i<hor; i++) {   //  horz line
00902                 z =  zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
00903                 b = 1 << (j & 0x07);
00904                 if (( z & b ) == 0x00) {
00905                   f_write(_background);
00906                 } else {
00907                   f_write(_foreground);
00908                 }
00909             }
00910         }
00911         spi_bsy();
00912         _cs = 1;
00913         spi_16(0);
00914     #ifdef use_ram   
00915     }
00916     #endif    
00917     _cs = 1;
00918     WindowMax();
00919     if ((w + 2) < hor) {                   // x offset to next char
00920         char_x += w + 2;
00921     } else char_x += hor;
00922 }
00923 
00924 
00925 void SPI_TFT_ILI9341::set_font(unsigned char* f)
00926 {
00927     font = f;
00928 }
00929 
00930 
00931 void SPI_TFT_ILI9341::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap)
00932 {
00933     unsigned int  j;
00934     int padd;
00935     unsigned short *bitmap_ptr = (unsigned short *)bitmap;
00936 
00937     unsigned int i;
00938 
00939     // the lines are padded to multiple of 4 bytes in a bitmap
00940     padd = -1;
00941     do {
00942         padd ++;
00943     } while (2*(w + padd)%4 != 0);
00944     window(x, y, w, h);
00945     bitmap_ptr += ((h - 1)* (w + padd));
00946     wr_cmd(0x2C);  // send pixel
00947     spi_16(1);
00948     for (j = 0; j < h; j++) {         //Lines
00949         for (i = 0; i < w; i++) {     // one line
00950                 f_write(*bitmap_ptr);    // one line
00951                 bitmap_ptr++;
00952         }
00953         bitmap_ptr -= 2*w;
00954         bitmap_ptr -= padd;
00955     }
00956     spi_bsy();
00957     _cs = 1;
00958     spi_16(0);
00959     WindowMax();
00960 }
00961 
00962 
00963 // local filesystem is not implemented but you can add a SD card to a different SPI
00964 
00965 int SPI_TFT_ILI9341::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP)
00966 {
00967 
00968 #define OffsetPixelWidth    18
00969 #define OffsetPixelHeigh    22
00970 #define OffsetFileSize      34
00971 #define OffsetPixData       10
00972 #define OffsetBPP           28
00973 
00974     char filename[50];
00975     unsigned char BMP_Header[54];
00976     unsigned short BPP_t;
00977     unsigned int PixelWidth,PixelHeigh,start_data;
00978     unsigned int    i,off;
00979     int padd,j;
00980     unsigned short *line;
00981 
00982     // get the filename
00983     i=0;
00984     while (*Name_BMP!='\0') {
00985         filename[i++]=*Name_BMP++;
00986     }
00987     filename[i] = 0;
00988 
00989     FILE *Image = fopen((const char *)&filename[0], "rb");  // open the bmp file
00990     if (!Image) {
00991         return(0);      // error file not found !
00992     }
00993 
00994     fread(&BMP_Header[0],1,54,Image);      // get the BMP Header
00995 
00996     if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) {  // check magic byte
00997         fclose(Image);
00998         return(-1);     // error no BMP file
00999     }
01000 
01001     BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8);
01002     if (BPP_t != 0x0010) {
01003         fclose(Image);
01004         return(-2);     // error no 16 bit BMP
01005     }
01006 
01007     PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24);
01008     PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24);
01009     if (PixelHeigh > height() + y || PixelWidth > width() + x) {
01010         fclose(Image);
01011         return(-3);      // to big
01012     }
01013 
01014     start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
01015 
01016     line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line
01017     if (line == NULL) {
01018         return(-4);         // error no memory
01019     }
01020 
01021     // the bmp lines are padded to multiple of 4 bytes
01022     padd = -1;
01023     do {
01024         padd ++;
01025     } while ((PixelWidth * 2 + padd)%4 != 0);
01026 
01027     window(x, y,PixelWidth ,PixelHeigh);
01028     wr_cmd(0x2C);  // send pixel
01029     spi_16(1);
01030     for (j = PixelHeigh - 1; j >= 0; j--) {               //Lines bottom up
01031         off = j * (PixelWidth  * 2 + padd) + start_data;   // start of line
01032         fseek(Image, off ,SEEK_SET);
01033         fread(line,1,PixelWidth * 2,Image);       // read a line - slow
01034         for (i = 0; i < PixelWidth; i++) {        // copy pixel data to TFT
01035             f_write(line[i]);                  // one 16 bit pixel
01036         }
01037      }
01038     spi_bsy();
01039     _cs = 1;
01040     spi_16(0);
01041     free (line);
01042     fclose(Image);
01043     WindowMax();
01044     return(1);
01045 }
01046 
01047 #endif
01048