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_NXP.cpp Source File

SPI_TFT_ILI9341_NXP.cpp

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