The code from https://github.com/vpcola/Nucleo

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