Modified to work with two displays

Dependents:   touch2 default CANary_9341_test CANary_merge

Fork of SPI_TFT by Peter Drescher

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPI_TFTx2.cpp Source File

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