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

See http://mbed.org/cookbook/SPI-driven-QVGA-TFT for details.

Revision:
3:7f1d793b90df
Parent:
2:f30ea1eb3681
Child:
4:824715115046
diff -r f30ea1eb3681 -r 7f1d793b90df SPI_TFT.cpp
--- a/SPI_TFT.cpp	Tue Sep 11 20:37:13 2012 +0000
+++ b/SPI_TFT.cpp	Thu Sep 20 23:24:43 2012 +0000
@@ -18,8 +18,8 @@
 // 15.03.12 use SSEL for TFT CS to enable DMA Register writes
 // 06.04.12 fix SSEL CS problem
 // 06.04.12 use direct access to the spi register to speed up the library.
-// 11.09.12 switch back to using io pin as cs to avoid problems with SSEL CS. 
- 
+// 11.09.12 switch back to using io pin as cs to avoid problems with SSEL CS.
+
 
 #include "SPI_TFT.h"
 #include "mbed.h"
@@ -28,11 +28,12 @@
 #define BPP         16                  // Bits per pixel                
 
 
-//extern Serial pc;
+extern Serial pc;
 //extern DigitalOut xx;     // debug !!
 
 SPI_TFT::SPI_TFT(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset, const char *name)
-        : _spi(mosi, miso, sclk), _cs(cs), _reset(reset),GraphicsDisplay(name) {
+    : _spi(mosi, miso, sclk), _cs(cs), _reset(reset),GraphicsDisplay(name)
+{
     tft_reset();
     orientation = 0;
     char_x = 0;
@@ -40,19 +41,22 @@
     else spi_port = 1;
 }
 
-int SPI_TFT::width() {
+int SPI_TFT::width()
+{
     if (orientation == 0 || orientation == 2) return 240;
     else return 320;
 }
 
 
-int SPI_TFT::height() {
+int SPI_TFT::height()
+{
     if (orientation == 0 || orientation == 2) return 320;
     else return 240;
 }
 
 
-void SPI_TFT::set_orientation(unsigned int o) {
+void SPI_TFT::set_orientation(unsigned int o)
+{
     orientation = o;
     switch (orientation) {
         case 0:
@@ -74,7 +78,8 @@
 
 // write command to tft register
 
-void SPI_TFT::wr_cmd(unsigned char cmd) {
+void SPI_TFT::wr_cmd(unsigned char cmd)
+{
     unsigned short spi_d;
     spi_d =  0x7000 | cmd ;
     _cs = 0;
@@ -93,7 +98,8 @@
 
 
 
-void SPI_TFT::wr_dat(unsigned char dat) {
+void SPI_TFT::wr_dat(unsigned char dat)
+{
     unsigned short spi_d;
     spi_d =  0x7200 | dat;
     _cs = 0;
@@ -116,7 +122,8 @@
 // This is a bug - ?
 // A read will return 0 at the moment
 
-unsigned short SPI_TFT::rd_dat (void) {
+unsigned short SPI_TFT::rd_dat (void)
+{
     unsigned short val = 0;
 
     //val = _spi.write(0x73ff);                /* Dummy read 1           */
@@ -124,30 +131,26 @@
     return (val);
 }
 
-void SPI_TFT::wr_reg (unsigned char reg, unsigned char val) {
+void SPI_TFT::wr_reg (unsigned char reg, unsigned char val)
+{
     wr_cmd(reg);
     wr_dat(val);
 }
 
-unsigned short SPI_TFT::rd_reg (unsigned char reg) {
+unsigned short SPI_TFT::rd_reg (unsigned char reg)
+{
     wr_cmd(reg);
     return(rd_dat());
 }
 
-void SPI_TFT::tft_reset() {
+void SPI_TFT::tft_reset()
+{
     //static unsigned short driverCode;
     _spi.format(16,3);                 // 16 bit spi mode 3
     _spi.frequency(48000000);          // 48 Mhz SPI clock
     _cs = 1;                           // cs high
     _reset = 0;                        // display reset
-   // 
-   // if (spi_port == 0) {    // TFT on SSP0
-        // Set up SSEL0 for CS
-   //     LPC_PINCON->PINSEL1 |= (1UL << 1);
-   // } else {
-   //     // Set up SSEL1
-   //     LPC_PINCON->PINSEL0 |= (1UL << 13);
-   // }
+
     wait_us(50);
     _reset = 1;                       // end reset
     wait_ms(5);
@@ -246,7 +249,8 @@
 }
 
 
-void SPI_TFT::pixel(int x, int y, int color) {
+void SPI_TFT::pixel(int x, int y, int color)
+{
     unsigned char u,l;
     wr_reg(0x03, (x >> 0));
     wr_reg(0x02, (x >> 8));
@@ -255,7 +259,7 @@
     wr_cmd(0x22);
     u = color  >> 8;
     l = color & 0xff;
-    _cs = 0;  
+    _cs = 0;
     if (spi_port == 0) {    // TFT on SSP0
         LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
         LPC_SSP0->DR = 0x72;        // start Data
@@ -279,7 +283,8 @@
 }
 
 
-void SPI_TFT::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h) {
+void SPI_TFT::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h)
+{
     wr_reg(0x03, x );
     wr_reg(0x02, (x >> 8));
     wr_reg(0x05, x+w-1 );
@@ -291,12 +296,14 @@
 }
 
 
-void SPI_TFT::WindowMax (void) {
+void SPI_TFT::WindowMax (void)
+{
     window (0, 0, width(),  height());
 }
 
 
-void SPI_TFT::cls (void) {
+void SPI_TFT::cls (void)
+{
     //unsigned int i
 
     int pixel = ( width() * height());
@@ -308,7 +315,7 @@
     // The SSEL signal is held low until the spi FIFO is emty.
     // We have to lower the SPI clock for the 8 bit start to get the spi running
     // until the next data word
-    
+
     LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)&color;
 
     _cs = 0;
@@ -326,7 +333,7 @@
         LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
         LPC_SSP1->DR = 0x72;        // start Data
         LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
-     }
+    }
 
     // start DMA
     do {
@@ -362,7 +369,8 @@
 }
 
 
-void SPI_TFT::circle(int x0, int y0, int r, int color) {
+void SPI_TFT::circle(int x0, int y0, int r, int color)
+{
 
     int draw_x0, draw_y0;
     int draw_x1, draw_y1;
@@ -469,7 +477,8 @@
     return;
 }
 
-void SPI_TFT::fillcircle(int x, int y, int r, int color) {
+void SPI_TFT::fillcircle(int x, int y, int r, int color)
+{
     int i;
     for (i = 0; i <= r; i++)
         circle(x,y,i,color);
@@ -477,7 +486,8 @@
 
 
 
-void SPI_TFT::hline(int x0, int x1, int y, int color) {
+void SPI_TFT::hline(int x0, int x1, int y, int color)
+{
     int w;
     w = x1 - x0 + 1;
     window(x0,y,w,1);
@@ -519,7 +529,8 @@
     return;
 }
 
-void SPI_TFT::vline(int x, int y0, int y1, int color) {
+void SPI_TFT::vline(int x, int y0, int y1, int color)
+{
     int h;
     h = y1 - y0 + 1;
     window(x,y0,1,h);
@@ -532,7 +543,7 @@
         LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
         LPC_SSP0->DR = 0x72;        // start Data
         LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
-     } else {
+    } else {
         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
         /* Enable SSP1 for DMA. */
         LPC_SSP1->DMACR = 0x2;
@@ -564,7 +575,8 @@
 
 
 
-void SPI_TFT::line(int x0, int y0, int x1, int y1, int color) {
+void SPI_TFT::line(int x0, int y0, int x1, int y1, int color)
+{
     //WindowMax();
     int   dx = 0, dy = 0;
     int   dx_sym = 0, dy_sym = 0;
@@ -635,7 +647,8 @@
 }
 
 
-void SPI_TFT::rect(int x0, int y0, int x1, int y1, int color) {
+void SPI_TFT::rect(int x0, int y0, int x1, int y1, int color)
+{
 
     if (x1 > x0) hline(x0,x1,y0,color);
     else  hline(x1,x0,y0,color);
@@ -654,7 +667,8 @@
 
 
 
-void SPI_TFT::fillrect(int x0, int y0, int x1, int y1, int color) {
+void SPI_TFT::fillrect(int x0, int y0, int x1, int y1, int color)
+{
 
     int h = y1 - y0 + 1;
     int w = x1 - x0 + 1;
@@ -670,7 +684,7 @@
         LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
         LPC_SSP0->DR = 0x72;        // start Data
         LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
-     } else {
+    } else {
         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
         /* Enable SSP1 for DMA. */
         LPC_SSP1->DMACR = 0x2;
@@ -711,26 +725,30 @@
 }
 
 
-void SPI_TFT::locate(int x, int y) {
+void SPI_TFT::locate(int x, int y)
+{
     char_x = x;
     char_y = y;
 }
 
 
 
-int SPI_TFT::columns() {
+int SPI_TFT::columns()
+{
     return width() / font[1];
 }
 
 
 
-int SPI_TFT::rows() {
+int SPI_TFT::rows()
+{
     return height() / font[2];
 }
 
 
 
-int SPI_TFT::_putc(int value) {
+int SPI_TFT::_putc(int value)
+{
     if (value == '\n') {    // new line
         char_x = 0;
         char_y = char_y + font[2];
@@ -746,7 +764,8 @@
 
 
 
-void SPI_TFT::character(int x, int y, int c) {
+void SPI_TFT::character(int x, int y, int c)
+{
     unsigned int hor,vert,offset,bpl,j,i,b,p;
     unsigned char* zeichen;
     unsigned char z,w;
@@ -860,13 +879,15 @@
 }
 
 
-void SPI_TFT::set_font(unsigned char* f) {
+void SPI_TFT::set_font(unsigned char* f)
+{
     font = f;
 }
 
 
 
-void SPI_TFT::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap) {
+void SPI_TFT::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap)
+{
     unsigned int    j;
     int padd;
     unsigned short *bitmap_ptr = (unsigned short *)bitmap;
@@ -880,19 +901,22 @@
     _cs = 0;
     if (spi_port == 0) {    // TFT on SSP0
         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
-        /* Enable SSP0 for DMA. */
-        LPC_SSP0->DMACR = 0x2;
         LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
         LPC_SSP0->DR = 0x72;        // start Data
         LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
+        /* Enable SSP0 for DMA. */
+        LPC_SSP0->DMACR = 0x2;
+
     } else {
         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
+        LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
+        LPC_SSP1->DR = 0x72;        // start Data command
+        LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
         /* Enable SSP1 for DMA. */
         LPC_SSP1->DMACR = 0x2;
-        LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
-        LPC_SSP1->DR = 0x72;        // start Data
-        LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
+
     }
+
     bitmap_ptr += ((h - 1)* (w + padd));
     for (j = 0; j < h; j++) {        //Lines
         LPC_GPDMA->DMACIntTCClear = 0x1;
@@ -920,7 +944,8 @@
 }
 
 
-int SPI_TFT::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP) {
+int SPI_TFT::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP)
+{
 
 #define OffsetPixelWidth    18
 #define OffsetPixelHeigh    22
@@ -946,7 +971,7 @@
 
     fprintf(stderr, "filename : %s \n\r",filename);
 
-    FILE *Image = fopen((const char *)&filename[0], "r");  // open the bmp file
+    FILE *Image = fopen((const char *)&filename[0], "rb");  // open the bmp file
     if (!Image) {
         return(0);      // error file not found !
     }
@@ -972,7 +997,7 @@
     }
 
     start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
-    
+
     line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line
     if (line == NULL) {
         return(-4);         // error no memory
@@ -984,28 +1009,37 @@
         padd ++;
     } while ((PixelWidth * 2 + padd)%4 != 0);
 
-    window(x, y,PixelWidth+1,PixelHeigh);
+
+    pc.printf("width = %d \n\r",PixelWidth);
+    pc.printf("heigh = %d \n\r",PixelHeigh);
+    pc.printf("padd = %d \n\r",padd);
+    pc.printf("start = 0x%x \n\r",start_data);
+
+//fseek(Image, 70 ,SEEK_SET);
+    window(x, y,PixelWidth ,PixelHeigh);
     wr_cmd(0x22);
     _cs = 0;
+
+    if (spi_port == 0) {    // TFT on SSP0
+        LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
+        LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
+        LPC_SSP0->DR = 0x72;        // start Data
+        LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
+        /* Enable SSP0 for DMA. */
+        LPC_SSP0->DMACR = 0x2;
+
+    } else {
+        LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
+        LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
+        LPC_SSP1->DR = 0x72;        // start Data
+        LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
+        /* Enable SSP1 for DMA. */
+        LPC_SSP1->DMACR = 0x2;
+    }
     for (j = PixelHeigh - 1; j >= 0; j--) {               //Lines bottom up
-        off = j * (PixelWidth * 2 + padd) + start_data;   // start of line
+        off = j * (PixelWidth  * 2 + padd) + start_data;   // start of line
         fseek(Image, off ,SEEK_SET);
         fread(line,1,PixelWidth * 2,Image);       // read a line - slow !
-        if (spi_port == 0) {    // TFT on SSP0
-            LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
-            /* Enable SSP0 for DMA. */
-            LPC_SSP0->DMACR = 0x2;
-            LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
-            LPC_SSP0->DR = 0x72;        // start Data
-            LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
-         } else {
-            LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
-            /* Enable SSP1 for DMA. */
-            LPC_SSP1->DMACR = 0x2;
-            LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
-            LPC_SSP1->DR = 0x72;        // start Data
-            LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
-         }
 
         LPC_GPDMA->DMACIntTCClear = 0x1;
         LPC_GPDMA->DMACIntErrClr = 0x1;