Library to control a QVGA TFT connected to SPI. You can use printf to print text The lib can handle different fonts, draw lines, circles, rect and bmp

Dependents:   TFT_Test1 SourceCodePro31-SB Mandelbrot Mindwave-screen ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPI_TFT.cpp Source File

SPI_TFT.cpp

00001 /* mbed library for 240*320 pixel display TFT based on HX8347D LCD Controller
00002  * Copyright (c) 2011 Peter Drescher - DC2PD
00003  *
00004  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00005  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00006  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00007  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00008  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00009  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00010  * THE SOFTWARE.
00011  */
00012 
00013 
00014 // fix bmp padding for Bitmap function
00015 // speed up pixel
00016 // 30.12.11 fix cls
00017 // 11.03.12 use DMA to speed up
00018 // 15.03.12 use SSEL for TFT CS to enable DMA Register writes
00019 // 06.04.12 fix SSEL CS problem
00020 // 06.04.12 use direct access to the spi register to speed up the library.
00021 // 11.09.12 switch back to using io pin as cs to avoid problems with SSEL CS.
00022 // 21.09.12 fix Bug in BMP_16
00023 // 11.10.12 patch from Hans Bergles to get SPI1 working again
00024 // 03.02.13 add a switch to switch off DMA use for LPC11U24
00025 // 04.03.13 add support for new Kinetis board
00026 // 25.03.13 fix Bug in bitmap for Kinetis board
00027 // 18.10.13 Better Circle function from Michael Ammann
00028 
00029 #include "SPI_TFT.h"
00030 #include "mbed.h"
00031 
00032 #define BPP         16                  // Bits per pixel    
00033 
00034 #if defined TARGET_LPC1768
00035 #define USE_DMA                     // we use dma to speed up
00036 #define NO_MBED_LIB                 // we write direct to the SPI register to speed up  
00037 #endif
00038 
00039 #if defined NO_DMA                      // if LPC1768 user want no DMA
00040 #undef USE_DMA
00041 #endif
00042 
00043 
00044 //extern Serial pc;
00045 //extern DigitalOut xx;     // debug !!
00046 
00047 SPI_TFT::SPI_TFT(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset, const char *name)
00048     : _spi(mosi, miso, sclk), _cs(cs), _reset(reset),GraphicsDisplay(name)
00049 {
00050     orientation = 0;
00051     char_x = 0;
00052     #if defined TARGET_LPC1768
00053         if (mosi == p11 || mosi == P0_18){
00054             spi_port = 0;  // we must know the used SPI port to setup the DMA
00055             }
00056         else {
00057             spi_port = 1;
00058             }
00059     #endif
00060     tft_reset();
00061 }
00062 
00063 int SPI_TFT::width()
00064 {
00065     if (orientation == 0 || orientation == 2) return 240;
00066     else return 320;
00067 }
00068 
00069 
00070 int SPI_TFT::height()
00071 {
00072     if (orientation == 0 || orientation == 2) return 320;
00073     else return 240;
00074 }
00075 
00076 
00077 void SPI_TFT::set_orientation(unsigned int o)
00078 {
00079     orientation = o;
00080     switch (orientation) {
00081         case 0:
00082             wr_reg(0x16, 0x08);
00083             break;
00084         case 1:
00085             wr_reg(0x16, 0x68);
00086             break;
00087         case 2:
00088             wr_reg(0x16, 0xC8);
00089             break;
00090         case 3:
00091             wr_reg(0x16, 0xA8);
00092             break;
00093     }
00094     WindowMax();
00095 }
00096 
00097 
00098 // write command to tft register
00099 
00100 void SPI_TFT::wr_cmd(unsigned char cmd)
00101 {
00102     _cs = 0;
00103     #if defined NO_MBED_LIB
00104         unsigned short spi_d;
00105         spi_d =  0x7000 | cmd ;
00106         if (spi_port == 0) {    // TFT on SSP0
00107             LPC_SSP0->DR = spi_d;
00108             // we have to wait for SPI IDLE to set CS back to high
00109             do {
00110             } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI0 not idle
00111         } else {
00112             LPC_SSP1->DR = spi_d;
00113             do {
00114             } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI1 not idle
00115         }
00116     #else  // use mbed lib
00117         #if defined TARGET_KL25Z  // 8 Bit SPI
00118             _spi.write(0x70);
00119             _spi.write(cmd);
00120         #else                     // 16 Bit SPI  
00121             unsigned short spi_d;
00122             spi_d =  0x7000 | cmd ;
00123             _spi.write(spi_d);      // mbed lib
00124         #endif
00125     #endif
00126     _cs = 1;
00127 }
00128 
00129 
00130 // write data to tft register
00131 void SPI_TFT::wr_dat(unsigned char dat)
00132 {
00133     _cs = 0;    
00134     #if defined NO_MBED_LIB
00135         unsigned short spi_d;
00136         spi_d =  0x7200 | dat;
00137         if (spi_port == 0) {    // TFT on SSP0
00138             LPC_SSP0->DR = spi_d;
00139             // we have to wait for SPI IDLE to set CS back to high
00140             do {
00141             } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI0 not idle
00142         } else {
00143             LPC_SSP1->DR = spi_d;
00144             do {
00145             } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI1 not idle
00146         }
00147     #else    // use mbed lib
00148         #if defined TARGET_KL25Z  // 8 Bit SPI
00149             _spi.write(0x72);
00150             _spi.write(dat);
00151         #else                     // 16 Bit SPI
00152             unsigned short spi_d;
00153             spi_d =  0x7200 | dat;
00154             _spi.write(spi_d);      
00155         #endif
00156     #endif
00157     _cs = 1;
00158 }
00159 
00160 
00161 
00162 // the HX8347-D controller do not use the MISO (SDO) Signal.
00163 // This is a bug - ?
00164 // A read will return 0 at the moment 
00165 
00166 unsigned short SPI_TFT::rd_dat (void)
00167 {
00168     unsigned short val = 0;
00169 
00170     //val = _spi.write(0x73ff);                /* Dummy read 1           */
00171     //val   = _spi.write(0x0000);              /* Read D8..D15           */
00172     return (val);
00173 }
00174 
00175 // write to a TFT register
00176 void SPI_TFT::wr_reg (unsigned char reg, unsigned char val)
00177 {
00178     wr_cmd(reg);
00179     wr_dat(val);
00180 }
00181 
00182 // read from a TFT register
00183 unsigned short SPI_TFT::rd_reg (unsigned char reg)
00184 {
00185     wr_cmd(reg);
00186     return(rd_dat());
00187 }
00188 
00189 // setup TFT controller - this is called by constructor
00190 void SPI_TFT::tft_reset()
00191 {
00192 #if defined TARGET_KL25Z           // 8 Bit SPI
00193     _spi.format(8,3);
00194 #else                              // 16 Bit SPI  
00195     _spi.format(16,3);                 // 16 bit spi mode 3
00196 #endif
00197     _spi.frequency(48000000);          // 48 Mhz SPI clock
00198     _cs = 1;                           // cs high
00199     _reset = 0;                        // display reset
00200 
00201     wait_us(50);
00202     _reset = 1;                       // end reset
00203     wait_ms(5);
00204 
00205     /* Start Initial Sequence ----------------------------------------------------*/
00206     wr_reg(0xEA, 0x00);                 /* Reset Power Control 1                */
00207     wr_reg(0xEB, 0x20);                 /* Power Control 2                      */
00208     wr_reg(0xEC, 0x0C);                 /* Power Control 3                      */
00209     wr_reg(0xED, 0xC4);                 /* Power Control 4                      */
00210     wr_reg(0xE8, 0x40);                 /* Source OPON_N                        */
00211     wr_reg(0xE9, 0x38);                 /* Source OPON_I                        */
00212     wr_reg(0xF1, 0x01);                 /*                                      */
00213     wr_reg(0xF2, 0x10);                 /*                                      */
00214     wr_reg(0x27, 0xA3);                 /* Display Control 2                    */
00215 
00216     /* Power On sequence ---------------------------------------------------------*/
00217     wr_reg(0x1B, 0x1B);                 /* Power Control 2                      */
00218     wr_reg(0x1A, 0x01);                 /* Power Control 1                      */
00219     wr_reg(0x24, 0x2F);                 /* Vcom Control 2                       */
00220     wr_reg(0x25, 0x57);                 /* Vcom Control 3                       */
00221     wr_reg(0x23, 0x8D);                 /* Vcom Control 1                       */
00222 
00223     /* Gamma settings  -----------------------------------------------------------*/
00224     wr_reg(0x40,0x00);   //   default setup
00225     wr_reg(0x41,0x00);   //
00226     wr_reg(0x42,0x01);   //
00227     wr_reg(0x43,0x13);   //
00228     wr_reg(0x44,0x10);   //
00229     wr_reg(0x45,0x26);   //
00230     wr_reg(0x46,0x08);   //
00231     wr_reg(0x47,0x51);   //
00232     wr_reg(0x48,0x02);   //
00233     wr_reg(0x49,0x12);   //
00234     wr_reg(0x4A,0x18);   //
00235     wr_reg(0x4B,0x19);   //
00236     wr_reg(0x4C,0x14);   //
00237     wr_reg(0x50,0x19);   //
00238     wr_reg(0x51,0x2F);   //
00239     wr_reg(0x52,0x2C);   //
00240     wr_reg(0x53,0x3E);   //
00241     wr_reg(0x54,0x3F);   //
00242     wr_reg(0x55,0x3F);   //
00243     wr_reg(0x56,0x2E);   //
00244     wr_reg(0x57,0x77);   //
00245     wr_reg(0x58,0x0B);   //
00246     wr_reg(0x59,0x06);   //
00247     wr_reg(0x5A,0x07);   //
00248     wr_reg(0x5B,0x0D);   //
00249     wr_reg(0x5C,0x1D);   //
00250     wr_reg(0x5D,0xCC);   //
00251 
00252     /* Power + Osc ---------------------------------------------------------------*/
00253     wr_reg(0x18, 0x36);                 /* OSC Control 1                        */
00254     wr_reg(0x19, 0x01);                 /* OSC Control 2                        */
00255     wr_reg(0x01, 0x00);                 /* Display Mode Control                 */
00256     wr_reg(0x1F, 0x88);                 /* Power Control 6                      */
00257     wait_ms(5);                           /* Delay 5 ms                           */
00258     wr_reg(0x1F, 0x80);                 /* Power Control 6                      */
00259     wait_ms(5);                         /* Delay 5 ms                           */
00260     wr_reg(0x1F, 0x90);                 /* Power Control 6                      */
00261     wait_ms(5);                           /* Delay 5 ms                           */
00262     wr_reg(0x1F, 0xD0);                 /* Power Control 6                      */
00263     wait_ms(5);                           /* Delay 5 ms                           */
00264 
00265     wr_reg(0x17, 0x05);                 /* Colmod 16Bit/Pixel                   */
00266 
00267     wr_reg(0x36, 0x00);                 /* Panel Characteristic                 */
00268     wr_reg(0x28, 0x38);                 /* Display Control 3                    */
00269     wait_ms(40);
00270     wr_reg(0x28, 0x3C);                 /* Display Control 3                    */
00271     switch (orientation) {
00272         case 0:
00273             wr_reg(0x16, 0x08);
00274             break;
00275         case 2:
00276             wr_reg(0x16, 0xC8);
00277             break;
00278         case 3:
00279             wr_reg(0x16, 0xA8);
00280             break;   
00281          case 1:
00282          default:
00283             wr_reg(0x16, 0x68);
00284             break;   
00285             
00286     }
00287 #if defined USE_DMA                     // setup DMA channel 0
00288     LPC_SC->PCONP |= (1UL << 29);       // Power up the GPDMA.
00289     LPC_GPDMA->DMACConfig = 1;          // enable DMA controller
00290     LPC_GPDMA->DMACIntTCClear = 0x1;    // Reset the Interrupt status
00291     LPC_GPDMA->DMACIntErrClr = 0x1;
00292     LPC_GPDMACH0->DMACCLLI      = 0;
00293 #endif
00294     WindowMax ();
00295 }
00296 
00297 // Set one pixel
00298 void SPI_TFT::pixel(int x, int y, int color)
00299 {
00300     wr_reg(0x03, (x >> 0));
00301     wr_reg(0x02, (x >> 8));
00302     wr_reg(0x07, (y >> 0));
00303     wr_reg(0x06, (y >> 8));
00304     wr_cmd(0x22);
00305     _cs = 0;
00306     #if defined NO_MBED_LIB
00307         if (spi_port == 0) {    // TFT on SSP0
00308             LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
00309             LPC_SSP0->DR = 0x72;        // start Data
00310             LPC_SSP0->CR0 |= 0x08UL;    // set back to 16 bit
00311             LPC_SSP0->DR = color;       // Pixel
00312             // we have to wait for SPI IDLE to set CS back to high
00313             do {
00314             } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI0 not idle
00315         } else {       // TFT on SSP1
00316             LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
00317             LPC_SSP1->DR = 0x72;        // start Data
00318             LPC_SSP1->CR0 |= 0x08UL;    // set back to 16 bit
00319             LPC_SSP1->DR = color;
00320             // we have to wait for SPI IDLE to set CS back to high
00321             do {
00322             } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI1 not idle
00323         }
00324     #else    // use mbed lib
00325         
00326         #if defined TARGET_KL25Z                          // 8 Bit SPI
00327             _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
00328             _spi.write(color >> 8);
00329             _spi.write(color & 0xff);
00330         #else
00331             _spi.format(8,3);                             // 8 bit Mode 3
00332             _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
00333             _spi.format(16,3);                            // switch to 16 bit Mode 3
00334             _spi.write(color);                            // Write D0..D15
00335         #endif
00336     #endif
00337     _cs = 1;
00338 }
00339 
00340 // define draw area
00341 void SPI_TFT::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h)
00342 {
00343     wr_reg(0x03, x );
00344     wr_reg(0x02, (x >> 8));
00345     wr_reg(0x05, x+w-1 );
00346     wr_reg(0x04, (x+w-1 >> 8));
00347     wr_reg(0x07,  y );
00348     wr_reg(0x06, ( y >> 8));
00349     wr_reg(0x09, ( y+h-1 ));
00350     wr_reg(0x08, ( y+h-1 >> 8));
00351 }
00352 
00353 // set draw area to max
00354 void SPI_TFT::WindowMax (void)
00355 {
00356     window (0, 0, width(),  height());
00357 }
00358 
00359 
00360 // clear screen
00361 void SPI_TFT::cls (void)
00362 {
00363     fprintf(stderr, "CLS \n\r");
00364     int pixel = ( width() * height());
00365     #if defined USE_DMA
00366         int dma_count;
00367         int color = _background;
00368     #endif
00369     WindowMax();
00370     wr_cmd(0x22);
00371 
00372     #if defined NO_MBED_LIB
00373         #if defined USE_DMA
00374             LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)&color;
00375         #endif
00376         _cs = 0;
00377         if (spi_port == 0) {    // TFT on SSP0
00378             #if defined USE_DMA
00379                 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
00380                 /* Enable SSP0 for DMA. */
00381                 LPC_SSP0->DMACR = 0x2;
00382             #endif
00383             LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
00384             LPC_SSP0->DR = 0x72;        // start byte
00385             LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
00386         } else {    // TFT on SSP1
00387             #if defined USE_DMA
00388                 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
00389                 /* Enable SSP1 for DMA. */
00390                 LPC_SSP1->DMACR = 0x2;
00391             #endif
00392             LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
00393             LPC_SSP1->DR = 0x72;        // start Data
00394             LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
00395         }
00396 
00397         #if defined USE_DMA
00398             // start DMA
00399             do {
00400                 if (pixel > 4095) {
00401                     dma_count = 4095;
00402                     pixel = pixel - 4095;
00403                 } else {
00404                     dma_count = pixel;
00405                     pixel = 0;
00406                 }
00407                 LPC_GPDMA->DMACIntTCClear = 0x1;
00408                 LPC_GPDMA->DMACIntErrClr = 0x1;
00409                 LPC_GPDMACH0->DMACCControl = dma_count | (1UL << 18) | (1UL << 21) | (1UL << 31) ; // 16 bit transfer , no address increment, interrupt
00410                 LPC_GPDMACH0->DMACCConfig  = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX);
00411                 LPC_GPDMA->DMACSoftSReq = 0x1;   // DMA request
00412                 do {
00413                     } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running
00414             } while (pixel > 0);
00415             if (spi_port == 0) {    // TFT on SSP0
00416                 do {
00417                 } while ((0x0010 & LPC_SSP0->SR) == 0x10); // SPI FIFO not empty
00418                 /* disable SSP0 for DMA. */
00419                 LPC_SSP0->DMACR = 0x0;
00420             } else {  // TFT on SSP1
00421                 do {
00422                     } while ((0x0010 & LPC_SSP1->SR) == 0x10); // SPI FIFO not empty
00423                 /* disable SSP1 for DMA. */
00424                 LPC_SSP1->DMACR = 0x0;
00425             }
00426 
00427         #else  // no DMA
00428             unsigned int i;
00429             for (i = 0; i < ( width() * height()); i++)
00430                 _spi.write(_background);
00431         #endif
00432 
00433     #else  // use mbed lib
00434         _cs = 0;
00435         #if defined TARGET_KL25Z                          // 8 Bit SPI    
00436             _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
00437             unsigned int i;
00438             for (i = 0; i < ( width() * height()); i++) {
00439                 _spi.write(_background >> 8);
00440                 _spi.write(_background & 0xff);
00441             }
00442         #else                                             // 16 bit SPI  
00443             _spi.format(8,3);                             // 8 bit Mode 3
00444             _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
00445             _spi.format(16,3);                            // switch back to 16 bit Mode 3
00446             unsigned int i;
00447             for (i = 0; i < ( width() * height()); i++)
00448                 _spi.write(_background);
00449         #endif
00450     #endif
00451     _cs = 1;
00452 }
00453 
00454 void SPI_TFT::circle(int x0, int y0, int r, int color)
00455 {  
00456     int x = -r, y = 0, err = 2-2*r, e2;
00457     do {
00458         pixel(x0-x, y0+y,color);
00459         pixel(x0+x, y0+y,color);
00460         pixel(x0+x, y0-y,color);
00461         pixel(x0-x, y0-y,color);
00462         e2 = err;
00463         if (e2 <= y) {
00464             err += ++y*2+1;
00465             if (-x == y && e2 <= x) e2 = 0;
00466         }
00467         if (e2 > x) err += ++x*2+1;
00468     } while (x <= 0);
00469         
00470 }
00471  
00472 void SPI_TFT::fillcircle(int x0, int y0, int r, int color)
00473 {
00474     int x = -r, y = 0, err = 2-2*r, e2;
00475     do {
00476         vline(x0-x, y0-y, y0+y, color);
00477         vline(x0+x, y0-y, y0+y, color);
00478         e2 = err;
00479         if (e2 <= y) {
00480             err += ++y*2+1;
00481             if (-x == y && e2 <= x) e2 = 0;
00482         }
00483         if (e2 > x) err += ++x*2+1;
00484     } while (x <= 0);
00485 }
00486 
00487 
00488 // draw horizontal line
00489 void SPI_TFT::hline(int x0, int x1, int y, int color)
00490 {
00491     int w;
00492     w = x1 - x0 + 1;
00493     window(x0,y,w,1);
00494     wr_cmd(0x22);
00495     _cs = 0;
00496     #if defined NO_MBED_LIB
00497         if (spi_port == 0) {    // TFT on SSP0
00498             #if defined USE_DMA
00499                 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
00500                 /* Enable SSP0 for DMA. */
00501                 LPC_SSP0->DMACR = 0x2;
00502             #endif
00503             LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
00504             LPC_SSP0->DR = 0x72;        // start Data
00505             LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
00506         } else {        // TFT on SSP1
00507             #if defined USE_DMA
00508                 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
00509                 /* Enable SSP1 for DMA. */
00510                 LPC_SSP1->DMACR = 0x2;
00511             #endif
00512             LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
00513             LPC_SSP1->DR = 0x72;        // start Data
00514             LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
00515         }
00516         #if defined USE_DMA
00517             LPC_GPDMA->DMACIntTCClear = 0x1;
00518             LPC_GPDMA->DMACIntErrClr = 0x1;
00519             LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)&color;
00520             LPC_GPDMACH0->DMACCControl = w | (1UL << 18) | (1UL << 21) | (1UL << 31) ; // 16 bit transfer , no address increment, interrupt
00521             LPC_GPDMACH0->DMACCConfig  = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX);
00522             LPC_GPDMA->DMACSoftSReq = 0x1;   // start DMA
00523             do {
00524                 } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running
00525             if (spi_port == 0) {    // TFT on SSP0
00526                 do {
00527                     } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI FIFO not empty
00528             } else {  // TFT on SSP1
00529                 do {
00530                     } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
00531             }
00532         #else // no DMA
00533             int i;
00534             for (i=0; i<w; i++) {
00535                 _spi.write(color);
00536             }
00537         #endif
00538     #else  // use mbed lib    
00539         #if defined TARGET_KL25Z                          // 8 Bit SPI    
00540             _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
00541             for (int j=0; j<w; j++) {
00542                 _spi.write(color >> 8);
00543                 _spi.write(color & 0xff);
00544             }
00545         #else                                             // 16 Bit SPI  
00546             _spi.format(8,3);                             // 8 bit Mode 3
00547             _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
00548             _spi.format(16,3);                            // switch back to 16 bit Mode 3
00549             for (int j=0; j<w; j++) {
00550                 _spi.write(color);
00551             }
00552         #endif
00553     #endif
00554     _cs = 1;
00555     WindowMax();
00556     return;
00557 }
00558 
00559 // draw vertical line
00560 void SPI_TFT::vline(int x, int y0, int y1, int color)
00561 {
00562     int h;
00563     h = y1 - y0 + 1;
00564     window(x,y0,1,h);
00565     wr_cmd(0x22);
00566     _cs = 0;
00567     #if defined NO_MBED_LIB
00568         if (spi_port == 0) {    // TFT on SSP0
00569             #if defined USE_DMA
00570                 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
00571                 /* Enable SSP0 for DMA. */
00572                 LPC_SSP0->DMACR = 0x2;
00573             #endif
00574             LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
00575             LPC_SSP0->DR = 0x72;        // start Data
00576             LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
00577         } else { // TFT on SSP1
00578             #if defined USE_DMA
00579                 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
00580                 /* Enable SSP1 for DMA. */
00581                 LPC_SSP1->DMACR = 0x2;
00582             #endif
00583             LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
00584             LPC_SSP1->DR = 0x72;        // start Data
00585             LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
00586         }
00587         #if defined USE_DMA
00588             LPC_GPDMA->DMACIntTCClear = 0x1;
00589             LPC_GPDMA->DMACIntErrClr = 0x1;
00590             LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)&color;
00591             LPC_GPDMACH0->DMACCControl = h | (1UL << 18) | (1UL << 21) | (1UL << 31) ; // 16 bit transfer , no address increment, interrupt
00592             LPC_GPDMACH0->DMACCConfig  = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX);
00593             LPC_GPDMA->DMACSoftSReq = 0x1;
00594             do {
00595                 } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running
00596 
00597             if (spi_port == 0) {    // TFT on SSP0
00598                 do {
00599                     } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI FIFO not empty
00600             } else { // TFT on SSP1
00601                  do {
00602                     } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
00603             }
00604         #else   // no DMA
00605             for (int y=0; y<h; y++) {
00606                 _spi.write(color);
00607             }
00608         #endif
00609     #else     // use mbed lib
00610         #if defined TARGET_KL25Z                          // 8 Bit SPI
00611             _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
00612             for (int y=0; y<h; y++) {
00613                 _spi.write(color >> 8);
00614                 _spi.write(color & 0xff);
00615             }
00616         #else                                             // 16 bit SPI  
00617             _spi.format(8,3);                             // 8 bit Mode 3
00618             _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
00619             _spi.format(16,3);                            // switch to 16 bit Mode 3
00620             for (int y=0; y<h; y++) {
00621                 _spi.write(color);
00622             }
00623         #endif
00624     #endif
00625     _cs = 1;
00626     WindowMax();
00627     return;
00628 }
00629 
00630 
00631 // draw line
00632 void SPI_TFT::line(int x0, int y0, int x1, int y1, int color)
00633 {
00634     //WindowMax();
00635     int   dx = 0, dy = 0;
00636     int   dx_sym = 0, dy_sym = 0;
00637     int   dx_x2 = 0, dy_x2 = 0;
00638     int   di = 0;
00639 
00640     dx = x1-x0;
00641     dy = y1-y0;
00642 
00643     if (dx == 0) {        /* vertical line */
00644         if (y1 > y0) vline(x0,y0,y1,color);
00645         else vline(x0,y1,y0,color);
00646         return;
00647     }
00648 
00649     if (dx > 0) {
00650         dx_sym = 1;
00651     } else {
00652         dx_sym = -1;
00653     }
00654     if (dy == 0) {        /* horizontal line */
00655         if (x1 > x0) hline(x0,x1,y0,color);
00656         else  hline(x1,x0,y0,color);
00657         return;
00658     }
00659 
00660     if (dy > 0) {
00661         dy_sym = 1;
00662     } else {
00663         dy_sym = -1;
00664     }
00665 
00666     dx = dx_sym*dx;
00667     dy = dy_sym*dy;
00668 
00669     dx_x2 = dx*2;
00670     dy_x2 = dy*2;
00671 
00672     if (dx >= dy) {
00673         di = dy_x2 - dx;
00674         while (x0 != x1) {
00675 
00676             pixel(x0, y0, color);
00677             x0 += dx_sym;
00678             if (di<0) {
00679                 di += dy_x2;
00680             } else {
00681                 di += dy_x2 - dx_x2;
00682                 y0 += dy_sym;
00683             }
00684         }
00685         pixel(x0, y0, color);
00686     } else {
00687         di = dx_x2 - dy;
00688         while (y0 != y1) {
00689             pixel(x0, y0, color);
00690             y0 += dy_sym;
00691             if (di < 0) {
00692                 di += dx_x2;
00693             } else {
00694                 di += dx_x2 - dy_x2;
00695                 x0 += dx_sym;
00696             }
00697         }
00698         pixel(x0, y0, color);
00699     }
00700     return;
00701 }
00702 
00703 // draw rect
00704 void SPI_TFT::rect(int x0, int y0, int x1, int y1, int color)
00705 {
00706 
00707     if (x1 > x0) hline(x0,x1,y0,color);
00708     else  hline(x1,x0,y0,color);
00709 
00710     if (y1 > y0) vline(x0,y0,y1,color);
00711     else vline(x0,y1,y0,color);
00712 
00713     if (x1 > x0) hline(x0,x1,y1,color);
00714     else  hline(x1,x0,y1,color);
00715 
00716     if (y1 > y0) vline(x1,y0,y1,color);
00717     else vline(x1,y1,y0,color);
00718 
00719     return;
00720 }
00721 
00722 
00723 // fill rect
00724 void SPI_TFT::fillrect(int x0, int y0, int x1, int y1, int color)
00725 {
00726 
00727     int h = y1 - y0 + 1;
00728     int w = x1 - x0 + 1;
00729     int pixel = h * w;
00730     #if defined USE_DMA
00731         int dma_count;
00732     #endif
00733     window(x0,y0,w,h);
00734     wr_cmd(0x22);
00735     _cs = 0;
00736     #if defined NO_MBED_LIB
00737         if (spi_port == 0) {    // TFT on SSP0
00738             #if defined USE_DMA
00739                 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
00740                 /* Enable SSP0 for DMA. */
00741                 LPC_SSP0->DMACR = 0x2;
00742             #endif
00743             LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
00744             LPC_SSP0->DR = 0x72;        // start Data
00745             LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
00746         } else {  // TFT on SSP1
00747             #if defined USE_DMA
00748                 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
00749                 /* Enable SSP1 for DMA. */
00750                 LPC_SSP1->DMACR = 0x2;
00751             #endif
00752             LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
00753             LPC_SSP1->DR = 0x72;        // start Data
00754             LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
00755         }
00756         #if defined USE_DMA
00757             do {
00758                 if (pixel > 4095) {
00759                     dma_count = 4095;
00760                     pixel = pixel - 4095;
00761                 } else {
00762                     dma_count = pixel;
00763                     pixel = 0;
00764                 }
00765                 LPC_GPDMA->DMACIntTCClear = 0x1;
00766                 LPC_GPDMA->DMACIntErrClr = 0x1;
00767                 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)&color;
00768                 LPC_GPDMACH0->DMACCControl = dma_count | (1UL << 18) | (1UL << 21) | (1UL << 31) ; // 16 bit transfer , no address increment, interrupt
00769                 LPC_GPDMACH0->DMACCConfig  = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX);
00770                 LPC_GPDMA->DMACSoftSReq = 0x1;
00771                 do {
00772                     } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running
00773 
00774                 } while (pixel > 0);
00775 
00776             if (spi_port == 0) {    // TFT on SSP0
00777                 do {
00778                     } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI FIFO not empty
00779             } else {   // TFT on SSP1
00780                 do {
00781                     } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
00782             }
00783 
00784         #else  // no DMA 
00785             for (int p=0; p<pixel; p++) {
00786             _spi.write(color);
00787             }
00788         #endif
00789 
00790     #else // use mbed lib
00791         #if defined TARGET_KL25Z                          // 8 Bit SPI
00792             _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
00793             for (int p=0; p<pixel; p++) {
00794                 _spi.write(color >> 8);
00795                 _spi.write(color & 0xff);
00796             }
00797 
00798         #else                                             // 16 bit SPI
00799             _spi.format(8,3);                             // 8 bit Mode 3
00800             _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
00801             _spi.format(16,3);                            // switch to 16 bit Mode 3
00802             for (int p=0; p<pixel; p++) {
00803                 _spi.write(color);
00804             }
00805         #endif
00806     #endif
00807     _cs = 1;
00808     WindowMax();
00809     return;
00810 }
00811 
00812 // set cursor position
00813 void SPI_TFT::locate(int x, int y)
00814 {
00815     char_x = x;
00816     char_y = y;
00817 }
00818 
00819 
00820 // calculate num of chars in a row
00821 int SPI_TFT::columns()
00822 {
00823     return width() / font[1];
00824 }
00825 
00826 // calculate num of rows on the screen
00827 int SPI_TFT::rows()
00828 {
00829     return height() / font[2];
00830 }
00831 
00832 // print a char on the screen
00833 int SPI_TFT::_putc(int value)
00834 {
00835     if (value == '\n') {    // new line
00836         char_x = 0;
00837         char_y = char_y + font[2];
00838         if (char_y >= height() - font[2]) {
00839             char_y = 0;
00840         }
00841     } else {
00842         character(char_x, char_y, value);
00843     }
00844     return value;
00845 }
00846 
00847 // consrtuct the char out of the font
00848 void SPI_TFT::character(int x, int y, int c)
00849 {
00850     unsigned int hor,vert,offset,bpl,j,i,b;
00851     unsigned char* zeichen;
00852     unsigned char z,w;
00853     #if defined USE_DMA
00854         unsigned int pixel;
00855         unsigned int p;
00856         unsigned int dma_count,dma_off;
00857         uint16_t *buffer;
00858     #endif
00859 
00860     if ((c < 31) || (c > 127)) return;   // test char range
00861 
00862     // read font parameter from start of array
00863     offset = font[0];                    // bytes / char
00864     hor = font[1];                       // get hor size of font
00865     vert = font[2];                      // get vert size of font
00866     bpl = font[3];                       // bytes per line
00867 
00868     if (char_x + hor > width()) {
00869         char_x = 0;
00870         char_y = char_y + vert;
00871         if (char_y >= height() - font[2]) {
00872             char_y = 0;
00873         }
00874     }
00875     window(char_x, char_y,hor,vert); // char box
00876     wr_cmd(0x22);
00877 
00878     #if defined USE_DMA
00879         pixel = hor * vert;  // calculate buffer size
00880 
00881         buffer = (uint16_t *) malloc (2*pixel); // we need a buffer for the 16 bit
00882         if (buffer == NULL) {
00883             //led = 1;
00884             //pc.printf("Malloc error !\n\r");
00885             return;         // error no memory
00886         }
00887 
00888         zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap
00889         w = zeichen[0];                          // width of actual char
00890         p = 0;
00891         // construct the char into the buffer
00892         for (j=0; j<vert; j++) {  //  vert line
00893             for (i=0; i<hor; i++) {   //  horz line
00894                 z =  zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
00895                 b = 1 << (j & 0x07);
00896                 if (( z & b ) == 0x00) {
00897                     buffer[p] = _background;
00898                 } else {
00899                     buffer[p] = _foreground;
00900                 }
00901                 p++;
00902             }
00903         }
00904 
00905         // copy the buffer with DMA SPI to display
00906         dma_off = 0;  // offset for DMA transfer
00907         _cs = 0;
00908         if (spi_port == 0) {    // TFT on SSP0
00909             LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
00910             /* Enable SSP0 for DMA. */
00911             LPC_SSP0->DMACR = 0x2;
00912             LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
00913             LPC_SSP0->DR = 0x72;        // start Data
00914             LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
00915         } else { // TFT on SSP1
00916             LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
00917             /* Enable SSP1 for DMA. */
00918             LPC_SSP1->DMACR = 0x2;
00919             LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
00920             LPC_SSP1->DR = 0x72;        // start Data
00921             LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
00922         }
00923 
00924         // start DMA
00925         do {
00926             if (pixel > 4095) {         // this is a giant font !
00927                 dma_count = 4095;
00928                 pixel = pixel - 4095;
00929             } else {
00930                 dma_count = pixel;
00931                 pixel = 0;
00932             }
00933             LPC_GPDMA->DMACIntTCClear = 0x1;
00934             LPC_GPDMA->DMACIntErrClr = 0x1;
00935             LPC_GPDMACH0->DMACCSrcAddr = (uint32_t) (buffer + dma_off);
00936             LPC_GPDMACH0->DMACCControl = dma_count | (1UL << 18) | (1UL << 21) | (1UL << 31) |  DMA_CHANNEL_SRC_INC ; // 16 bit transfer , address increment, interrupt
00937             LPC_GPDMACH0->DMACCConfig  = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX);
00938             LPC_GPDMA->DMACSoftSReq = 0x1;
00939             do {
00940                 } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running
00941             dma_off = dma_off + dma_count;
00942         } while (pixel > 0);
00943 
00944         free ((uint16_t *) buffer);
00945 
00946         if (spi_port == 0) {    // TFT on SSP0
00947             do {
00948                 } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI0 not idle
00949             /* disable SSP0 for DMA. */
00950             LPC_SSP0->DMACR = 0x0;
00951         } else {  // TFT on SSP1
00952             do {
00953                 } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI1 not idle
00954             /* disable SSP1 for DMA. */
00955             LPC_SSP1->DMACR = 0x0;
00956         }
00957 
00958     #else  // no dma
00959         _cs = 0;
00960         #if defined NO_MBED_LIB
00961             if (spi_port == 0) {    // TFT on SSP0
00962                 LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
00963                 LPC_SSP0->DR = 0x72;        // start Data
00964                 LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
00965             } else { // TFT on SSP1
00966                 LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
00967                 LPC_SSP1->DR = 0x72;        // start Data
00968                 LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
00969             }
00970         #else // mbed lib
00971             #if defined TARGET_KL25Z                          // 8 Bit SPI
00972                 _spi.write(SPI_START | SPI_WR | SPI_DATA);   // Write : RS = 1, RW = 0
00973             #else                                             // 16 bit SPI  
00974                 _spi.format(8,3);                             // 8 bit Mode 3
00975                 _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
00976                 _spi.format(16,3);                            // switch back to 16 bit Mode 3
00977             #endif
00978         #endif
00979     
00980         zeichen = &font[((c -32) * offset) + 4];    // start of char bitmap
00981         w = zeichen[0];                             // width of actual char
00982         for (j=0; j<vert; j++) {  //  vert line
00983             for (i=0; i<hor; i++) {   //  horz line
00984                 z =  zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
00985                 b = 1 << (j & 0x07);
00986                 if (( z & b ) == 0x00) {
00987                     #if defined TARGET_KL25Z  // 8 Bit SPI
00988                         _spi.write(_background >> 8);
00989                         _spi.write(_background & 0xff);
00990                     #else
00991                         _spi.write(_background);
00992                     #endif
00993                 } else {
00994                     #if defined TARGET_KL25Z  // 8 Bit SPI
00995                         _spi.write(_foreground >> 8);
00996                         _spi.write(_foreground & 0xff);
00997                     #else
00998                         _spi.write(_foreground);
00999                     #endif
01000                 }
01001             }
01002         }
01003     #endif  // no DMA    
01004     _cs = 1;
01005     WindowMax();
01006     if ((w + 2) < hor) {                   // x offset to next char
01007         char_x += w + 2;
01008     } else char_x += hor;
01009 }
01010 
01011 
01012 void SPI_TFT::set_font(unsigned char* f)
01013 {
01014     font = f;
01015 }
01016 
01017 
01018 void SPI_TFT::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap)
01019 {
01020     unsigned int  j;
01021     int padd;
01022   
01023     unsigned short *bitmap_ptr = (unsigned short *)bitmap;
01024     #if defined TARGET_KL25Z  // 8 Bit SPI
01025         unsigned short pix_temp;
01026     #endif
01027   
01028     // the lines are padded to multiple of 4 bytes in a bitmap
01029     padd = -1;
01030     do {
01031         padd ++;
01032     } while (2*(w + padd)%4 != 0);
01033     window(x, y, w, h);
01034     wr_cmd(0x22);
01035     _cs = 0;
01036 #if defined NO_MBED_LIB
01037     if (spi_port == 0) {    // TFT on SSP0
01038     #if defined USE_DMA
01039         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
01040         /* Enable SSP0 for DMA. */
01041         LPC_SSP0->DMACR = 0x2;
01042     #endif
01043     LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
01044     LPC_SSP0->DR = 0x72;        // start Data
01045     LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
01046 
01047     } else {
01048     #if defined USE_DMA
01049         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
01050         /* Enable SSP1 for DMA. */
01051         LPC_SSP1->DMACR = 0x2;
01052     #endif
01053     LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
01054     LPC_SSP1->DR = 0x72;        // start Data command
01055     LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
01056     }
01057 
01058     bitmap_ptr += ((h - 1)* (w + padd));
01059     #if defined USE_DMA
01060         for (j = 0; j < h; j++) {        //Lines
01061             LPC_GPDMA->DMACIntTCClear = 0x1;
01062             LPC_GPDMA->DMACIntErrClr = 0x1;
01063             LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)bitmap_ptr;
01064             LPC_GPDMACH0->DMACCControl = w | (1UL << 18) | (1UL << 21) | (1UL << 31) |  DMA_CHANNEL_SRC_INC ; // 16 bit transfer , address increment, interrupt
01065             LPC_GPDMACH0->DMACCConfig  = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX);
01066             LPC_GPDMA->DMACSoftSReq = 0x1;
01067             do {
01068             } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running
01069 
01070             bitmap_ptr -= w;
01071             bitmap_ptr -= padd;
01072         }
01073     #else
01074         unsigned int i;
01075         for (j = 0; j < h; j++) {        //Lines
01076             for (i = 0; i < w; i++) {     // copy pixel data to TFT
01077                 _spi.write(*bitmap_ptr);    // one line
01078                 bitmap_ptr++;
01079             }
01080             bitmap_ptr -= 2*w;
01081             bitmap_ptr -= padd;
01082         }
01083     #endif
01084     if (spi_port == 0) {    // TFT on SSP0
01085         do {
01086         } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI FIFO not empty
01087     } else {
01088         do {
01089         } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
01090     }
01091 #else // use mbed lib
01092     #if defined TARGET_KL25Z  // 8 Bit SPI
01093         _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
01094     #else
01095         _spi.format(8,3);                             // 8 bit Mode 3
01096         _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
01097         _spi.format(16,3);                            // switch to 16 bit Mode 3
01098     #endif    
01099     bitmap_ptr += ((h - 1)* (w + padd));              
01100     unsigned int i;
01101     for (j = 0; j < h; j++) {        //Lines
01102         for (i = 0; i < w; i++) {     // copy pixel data to TFT
01103             #if defined TARGET_KL25Z  // 8 Bit SPI
01104                 pix_temp = *bitmap_ptr;
01105                 _spi.write(pix_temp >> 8);
01106                 _spi.write(pix_temp);
01107                 bitmap_ptr++;
01108             #else
01109                 _spi.write(*bitmap_ptr);    // one line
01110                 bitmap_ptr++;
01111             #endif
01112         }
01113         bitmap_ptr -= 2*w;
01114         bitmap_ptr -= padd;
01115      }
01116 #endif // USE MBED LIB
01117     _cs = 1;
01118     WindowMax();
01119 }
01120 
01121 
01122 // local filesystem is not implemented in kinetis board
01123 #if defined TARGET_LPC1768  || defined TARGET_LPC11U24
01124 
01125 
01126 int SPI_TFT::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP)
01127 {
01128 
01129 #define OffsetPixelWidth    18
01130 #define OffsetPixelHeigh    22
01131 #define OffsetFileSize      34
01132 #define OffsetPixData       10
01133 #define OffsetBPP           28
01134 
01135     char filename[50];
01136     unsigned char BMP_Header[54];
01137     unsigned short BPP_t;
01138     unsigned int PixelWidth,PixelHeigh,start_data;
01139     unsigned int    i,off;
01140     int padd,j;
01141     unsigned short *line;
01142 
01143     // get the filename
01144     LocalFileSystem local("local");
01145     sprintf(&filename[0],"/local/");
01146     i=7;
01147     while (*Name_BMP!='\0') {
01148         filename[i++]=*Name_BMP++;
01149     }
01150 
01151     fprintf(stderr, "filename : %s \n\r",filename);
01152 
01153     FILE *Image = fopen((const char *)&filename[0], "rb");  // open the bmp file
01154     if (!Image) {
01155         return(0);      // error file not found !
01156     }
01157 
01158     fread(&BMP_Header[0],1,54,Image);      // get the BMP Header
01159 
01160     if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) {  // check magic byte
01161         fclose(Image);
01162         return(-1);     // error no BMP file
01163     }
01164 
01165     BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8);
01166     if (BPP_t != 0x0010) {
01167         fclose(Image);
01168         return(-2);     // error no 16 bit BMP
01169     }
01170 
01171     PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24);
01172     PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24);
01173     if (PixelHeigh > height() + y || PixelWidth > width() + x) {
01174         fclose(Image);
01175         return(-3);      // to big
01176     }
01177 
01178     start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
01179 
01180     line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line
01181     if (line == NULL) {
01182         return(-4);         // error no memory
01183     }
01184 
01185     // the bmp lines are padded to multiple of 4 bytes
01186     padd = -1;
01187     do {
01188         padd ++;
01189     } while ((PixelWidth * 2 + padd)%4 != 0);
01190 
01191 
01192 //fseek(Image, 70 ,SEEK_SET);
01193     window(x, y,PixelWidth ,PixelHeigh);
01194     wr_cmd(0x22);
01195     _cs = 0;
01196 #if defined NO_MBED_LIB
01197     if (spi_port == 0) {    // TFT on SSP0
01198 #if defined USE_DMA
01199         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
01200         /* Enable SSP0 for DMA. */
01201         LPC_SSP0->DMACR = 0x2;
01202 #endif
01203         LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
01204         LPC_SSP0->DR = 0x72;        // start Data
01205         LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
01206 
01207     } else {
01208 #if defined USE_DMA
01209         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
01210         /* Enable SSP1 for DMA. */
01211         LPC_SSP1->DMACR = 0x2;
01212 #endif
01213         LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
01214         LPC_SSP1->DR = 0x72;        // start Data
01215         LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
01216     }
01217     for (j = PixelHeigh - 1; j >= 0; j--) {               //Lines bottom up
01218         off = j * (PixelWidth  * 2 + padd) + start_data;   // start of line
01219         fseek(Image, off ,SEEK_SET);
01220         fread(line,1,PixelWidth * 2,Image);       // read a line - slow !
01221 #if defined USE_DMA
01222         LPC_GPDMA->DMACIntTCClear = 0x1;
01223         LPC_GPDMA->DMACIntErrClr = 0x1;
01224         LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)line;
01225         LPC_GPDMACH0->DMACCControl = PixelWidth | (1UL << 18) | (1UL << 21) | (1UL << 31) |  DMA_CHANNEL_SRC_INC ; // 16 bit transfer , address increment, interrupt
01226         LPC_GPDMACH0->DMACCConfig  = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX);
01227         LPC_GPDMA->DMACSoftSReq = 0x1;
01228         do {
01229         } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running
01230 #else
01231         for (i = 0; i < PixelWidth; i++) {        // copy pixel data to TFT
01232             _spi.write(line[i]);                  // one 16 bit pixel
01233         }
01234 #endif
01235     }
01236     if (spi_port == 0) {    // TFT on SSP0
01237         do {
01238         } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI FIFO not empty
01239     } else {
01240         do {
01241         } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
01242     }
01243 
01244 #else // use mbed lib
01245     _spi.format(8,3);                             // 8 bit Mode 3
01246     _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
01247     _spi.format(16,3);                            // switch to 16 bit Mode 3
01248     for (j = PixelHeigh - 1; j >= 0; j--) {               //Lines bottom up
01249         off = j * (PixelWidth  * 2 + padd) + start_data;   // start of line
01250         fseek(Image, off ,SEEK_SET);
01251         fread(line,1,PixelWidth * 2,Image);       // read a line - slow !
01252         for (i = 0; i < PixelWidth; i++) {        // copy pixel data to TFT
01253             _spi.write(line[i]);                  // one 16 bit pixel
01254         }
01255     }
01256 #endif
01257     _cs = 1;
01258     free (line);
01259     fclose(Image);
01260     WindowMax();
01261     return(1);
01262 }
01263 
01264 #endif