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

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