Library to control a Graphics TFT connected to 4-wire SPI - revised for the Raio RA8875 Display Controller.

Dependents:   FRDM_RA8875_mPaint RA8875_Demo RA8875_KeyPadDemo SignalGenerator ... more

Fork of SPI_TFT by Peter Drescher

See Components - RA8875 Based Display

Enhanced touch-screen support - where it previous supported both the Resistive Touch and Capacitive Touch based on the FT5206 Touch Controller, now it also has support for the GSL1680 Touch Controller.

Offline Help Manual (Windows chm)

/media/uploads/WiredHome/ra8875.zip.bin (download, rename to .zip and unzip)

Files at this revision

API Documentation at this revision

Comitter:
dreschpe
Date:
Tue Mar 05 14:50:51 2013 +0000
Parent:
11:9bb71766cafc
Child:
14:ea3206e8e3bd
Commit message:
Add Freescale KL25Z support

Changed in this revision

SPI_TFT.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/SPI_TFT.cpp	Tue Feb 19 21:49:55 2013 +0000
+++ b/SPI_TFT.cpp	Tue Mar 05 14:50:51 2013 +0000
@@ -19,24 +19,25 @@
 // 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.
-// 21.09.12 fix Bug in BMP_16 
+// 21.09.12 fix Bug in BMP_16
 // 11.10.12 patch from Hans Bergles to get SPI1 working again
 // 03.02.13 add a switch to switch off DMA use for LPC11U24
+// 04.03.13 add support for new Kinetis board
 
 #include "SPI_TFT.h"
 #include "mbed.h"
 
 #define BPP         16                  // Bits per pixel    
-            
-#if defined TARGET_LPC1768 
+
+#if defined TARGET_LPC1768
 #define USE_DMA                         // we use dma to speed up
 #define NO_MBED_LIB                     // we write direct to the SPI register to speed up  
 #endif
 
-#if defined NO_DMA
+#if defined NO_DMA                      // if LPC1768 user want no DMA
 #undef USE_DMA
 #endif
-  
+
 
 //extern Serial pc;
 //extern DigitalOut xx;     // debug !!
@@ -46,8 +47,10 @@
 {
     orientation = 0;
     char_x = 0;
+#if defined TARGET_LPC1768
     if (mosi == p11 || mosi == P0_18) spi_port = 0;  // we must know the used SPI port to setup the DMA
     else spi_port = 1;
+#endif
     tft_reset();
 }
 
@@ -90,8 +93,6 @@
 
 void SPI_TFT::wr_cmd(unsigned char cmd)
 {
-    unsigned short spi_d;
-    spi_d =  0x7000 | cmd ;
     _cs = 0;
 #if defined NO_MBED_LIB
     if (spi_port == 0) {    // TFT on SSP0
@@ -104,18 +105,24 @@
         do {
         } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI1 not idle
     }
-#else 
+#else
+#if defined TARGET_KL25Z  // 8 Bit SPI
+    _spi.write(0x70);
+    _spi.write(cmd);
+#else                     // 16 Bit SPI  
+    unsigned short spi_d;
+    spi_d =  0x7000 | cmd ;
     _spi.write(spi_d);      // mbed lib
-#endif    
+#endif
+#endif
     _cs = 1;
 }
 
 
-
+// write data to tft register
 void SPI_TFT::wr_dat(unsigned char dat)
 {
-    unsigned short spi_d;
-    spi_d =  0x7200 | dat;
+
     _cs = 0;
 #if defined NO_MBED_LIB
     if (spi_port == 0) {    // TFT on SSP0
@@ -128,9 +135,16 @@
         do {
         } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI1 not idle
     }
-#else 
-   _spi.write(spi_d);      // mbed lib
-#endif    
+#else
+#if defined TARGET_KL25Z  // 8 Bit SPI
+    _spi.write(0x72);
+    _spi.write(dat);
+#else                     // 16 Bit SPI
+    unsigned short spi_d;
+    spi_d =  0x7200 | dat;
+    _spi.write(spi_d);      // mbed lib
+#endif
+#endif
     _cs = 1;
 }
 
@@ -149,22 +163,28 @@
     return (val);
 }
 
+// write to a TFT register
 void SPI_TFT::wr_reg (unsigned char reg, unsigned char val)
 {
     wr_cmd(reg);
     wr_dat(val);
 }
 
+// read from a TFT register
 unsigned short SPI_TFT::rd_reg (unsigned char reg)
 {
     wr_cmd(reg);
     return(rd_dat());
 }
 
+// setup TFT controller - this is called by constructor
 void SPI_TFT::tft_reset()
 {
-    //static unsigned short driverCode;
+#if defined TARGET_KL25Z           // 8 Bit SPI
+    _spi.format(8,3);
+#else                              // 16 Bit SPI  
     _spi.format(16,3);                 // 16 bit spi mode 3
+#endif
     _spi.frequency(48000000);          // 48 Mhz SPI clock
     _cs = 1;                           // cs high
     _reset = 0;                        // display reset
@@ -192,7 +212,7 @@
     wr_reg(0x23, 0x8D);                 /* Vcom Control 1                       */
 
     /* Gamma settings  -----------------------------------------------------------*/
-    wr_reg(0x40,0x00);   //
+    wr_reg(0x40,0x00);   //   default setup
     wr_reg(0x41,0x00);   //
     wr_reg(0x42,0x01);   //
     wr_reg(0x43,0x13);   //
@@ -253,20 +273,17 @@
             wr_reg(0x16, 0x00A8);
             break;
     }
-#if defined USE_DMA                     
-    // setup DMA channel 0
-    // Power up the GPDMA.
-    LPC_SC->PCONP |= (1UL << 29);
+#if defined USE_DMA                     // setup DMA channel 0
+    LPC_SC->PCONP |= (1UL << 29);       // Power up the GPDMA.
     LPC_GPDMA->DMACConfig = 1;          // enable DMA controller
-    // Reset the Interrupt status
-    LPC_GPDMA->DMACIntTCClear = 0x1;
+    LPC_GPDMA->DMACIntTCClear = 0x1;    // Reset the Interrupt status
     LPC_GPDMA->DMACIntErrClr = 0x1;
     LPC_GPDMACH0->DMACCLLI      = 0;
 #endif
     WindowMax ();
 }
 
-
+// Set one pixel
 void SPI_TFT::pixel(int x, int y, int color)
 {
     wr_reg(0x03, (x >> 0));
@@ -275,7 +292,7 @@
     wr_reg(0x06, (y >> 8));
     wr_cmd(0x22);
     _cs = 0;
-#if defined NO_MBED_LIB    
+#if defined NO_MBED_LIB
     if (spi_port == 0) {    // TFT on SSP0
         LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
         LPC_SSP0->DR = 0x72;        // start Data
@@ -296,13 +313,18 @@
 #else
     _spi.format(8,3);                             // 8 bit Mode 3
     _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
+#if defined TARGET_KL25Z                          // 8 Bit SPI
+    _spi.write(color >> 8);
+    _spi.write(color & 0xff);
+#else
     _spi.format(16,3);                            // switch to 16 bit Mode 3
     _spi.write(color);                              // Write D0..D15
-#endif        
+#endif
+#endif
     _cs = 1;
 }
 
-
+// define draw area
 void SPI_TFT::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h)
 {
     wr_reg(0x03, x );
@@ -315,14 +337,14 @@
     wr_reg(0x08, ( y+h-1 >> 8));
 }
 
-
+// set draw area to max
 void SPI_TFT::WindowMax (void)
 {
     window (0, 0, width(),  height());
 }
 
 
-
+// clear screen
 void SPI_TFT::cls (void)
 {
     int pixel = ( width() * height());
@@ -394,19 +416,29 @@
     for (i = 0; i < ( width() * height()); i++)
         _spi.write(_background);
 #endif
-#else  // mbed lib
+
+#else  // use mbed lib
     _cs = 0;
+#if defined TARGET_KL25Z                          // 8 Bit SPI    
+    _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
+    unsigned int i;
+    for (i = 0; i < ( width() * height()); i++) {
+        _spi.write(_background >> 8);
+        _spi.write(_background & 0xff);
+    }
+#else                                             // 16 bit SPI  
     _spi.format(8,3);                             // 8 bit Mode 3
     _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
-    _spi.format(16,3);                            // switch to 16 bit Mode 3
+    _spi.format(16,3);                            // switch back to 16 bit Mode 3
     unsigned int i;
     for (i = 0; i < ( width() * height()); i++)
-        _spi.write(_background);                     
+        _spi.write(_background);
+#endif
 #endif
     _cs = 1;
 }
 
-
+// draw circle
 void SPI_TFT::circle(int x0, int y0, int r, int color)
 {
 
@@ -523,7 +555,7 @@
 }
 
 
-
+// draw horizontal line
 void SPI_TFT::hline(int x0, int x1, int y, int color)
 {
     int w;
@@ -531,7 +563,7 @@
     window(x0,y,w,1);
     wr_cmd(0x22);
     _cs = 0;
-#if defined NO_MBED_LIB    
+#if defined NO_MBED_LIB
     if (spi_port == 0) {    // TFT on SSP0
 #if defined USE_DMA
         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
@@ -567,25 +599,35 @@
         do {
         } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
     }
-#else
+#else // USE_DMA
     int i;
     for (i=0; i<w; i++) {
         _spi.write(color);
     }
-#endif    
+#endif
 #else  // use mbed lib    
+#if defined TARGET_KL25Z                          // 8 Bit SPI    
+    _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
+    for (int j=0; j<w; j++) {
+        _spi.write(color >> 8);
+        _spi.write(color & 0xff);
+    }
+
+#else                                             // 16 Bit SPI  
     _spi.format(8,3);                             // 8 bit Mode 3
     _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
-    _spi.format(16,3);                            // switch to 16 bit Mode 3
-    for (i=0; i<w; i++) {
+    _spi.format(16,3);                            // switch back to 16 bit Mode 3
+    for (int j=0; j<w; j++) {
         _spi.write(color);
     }
-#endif    
+#endif
+#endif
     _cs = 1;
     WindowMax();
     return;
 }
 
+// draw vertical line
 void SPI_TFT::vline(int x, int y0, int y1, int color)
 {
     int h;
@@ -593,7 +635,7 @@
     window(x,y0,1,h);
     wr_cmd(0x22);
     _cs = 0;
-#if defined NO_MBED_LIB      
+#if defined NO_MBED_LIB
     if (spi_port == 0) {    // TFT on SSP0
 #if defined USE_DMA
         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
@@ -636,20 +678,28 @@
     }
 #endif
 #else     // use mbed lib
+#if defined TARGET_KL25Z                          // 8 Bit SPI
+    _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
+    for (int y=0; y<h; y++) {
+        _spi.write(color >> 8);
+        _spi.write(color & 0xff);
+    }
+#else                                             // 16 bit SPI  
     _spi.format(8,3);                             // 8 bit Mode 3
     _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
     _spi.format(16,3);                            // switch to 16 bit Mode 3
     for (int y=0; y<h; y++) {
         _spi.write(color);
     }
-#endif    
+#endif
+#endif
     _cs = 1;
     WindowMax();
     return;
 }
 
 
-
+// draw line
 void SPI_TFT::line(int x0, int y0, int x1, int y1, int color)
 {
     //WindowMax();
@@ -721,7 +771,7 @@
     return;
 }
 
-
+// draw rect
 void SPI_TFT::rect(int x0, int y0, int x1, int y1, int color)
 {
 
@@ -741,20 +791,20 @@
 }
 
 
-
+// fill rect
 void SPI_TFT::fillrect(int x0, int y0, int x1, int y1, int color)
 {
 
     int h = y1 - y0 + 1;
     int w = x1 - x0 + 1;
     int pixel = h * w;
-    #if defined USE_DMA
+#if defined USE_DMA
     int dma_count;
-    #endif
+#endif
     window(x0,y0,w,h);
     wr_cmd(0x22);
     _cs = 0;
-#if defined NO_MBED_LIB     
+#if defined NO_MBED_LIB
     if (spi_port == 0) {    // TFT on SSP0
 #if defined USE_DMA
         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
@@ -801,26 +851,36 @@
         do {
         } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
     }
-   
+
 #else  // no DMA 
     for (int p=0; p<pixel; p++) {
         _spi.write(color);
     }
 #endif
+
 #else // use mbed lib
+#if defined TARGET_KL25Z                          // 8 Bit SPI
+    _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
+    for (int p=0; p<pixel; p++) {
+        _spi.write(color >> 8);
+        _spi.write(color & 0xff);
+    }
+
+#else                                             // 16 bit SPI
     _spi.format(8,3);                             // 8 bit Mode 3
     _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
     _spi.format(16,3);                            // switch to 16 bit Mode 3
     for (int p=0; p<pixel; p++) {
         _spi.write(color);
     }
-#endif  
+#endif
+#endif
     _cs = 1;
     WindowMax();
     return;
 }
 
-
+// set cursor position
 void SPI_TFT::locate(int x, int y)
 {
     char_x = x;
@@ -828,21 +888,19 @@
 }
 
 
-
+// calculate num of chars in a row
 int SPI_TFT::columns()
 {
     return width() / font[1];
 }
 
-
-
+// calculate num of rows on the screen
 int SPI_TFT::rows()
 {
     return height() / font[2];
 }
 
-
-
+// print a char on the screen
 int SPI_TFT::_putc(int value)
 {
     if (value == '\n') {    // new line
@@ -857,18 +915,18 @@
     return value;
 }
 
-
+// consrtuct the char out of the font
 void SPI_TFT::character(int x, int y, int c)
 {
     unsigned int hor,vert,offset,bpl,j,i,b;
     unsigned char* zeichen;
     unsigned char z,w;
-    #if defined USE_DMA
+#if defined USE_DMA
     unsigned int pixel;
     unsigned int p;
     unsigned int dma_count,dma_off;
     uint16_t *buffer;
-    #endif
+#endif
 
     if ((c < 31) || (c > 127)) return;   // test char range
 
@@ -967,10 +1025,10 @@
         /* disable SSP1 for DMA. */
         LPC_SSP1->DMACR = 0x0;
     }
-    
+
 #else  // no dma
     _cs = 0;
-#if defined NO_MBED_LIB    
+#if defined NO_MBED_LIB
     if (spi_port == 0) {    // TFT on SSP0
         LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
         LPC_SSP0->DR = 0x72;        // start Data
@@ -981,20 +1039,34 @@
         LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
     }
 #else // mbed lib
+#if defined TARGET_KL25Z                          // 8 Bit SPI
+    _spi.write(SPI_START | SPI_WR | SPI_DATA);   // Write : RS = 1, RW = 0
+#else                                             // 16 bit SPI  
     _spi.format(8,3);                             // 8 bit Mode 3
     _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
-    _spi.format(16,3);                            // switch to 16 bit Mode 3
-#endif        
-    zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap
-    w = zeichen[0];                          // width of actual char
-     for (j=0; j<vert; j++) {  //  vert line
+    _spi.format(16,3);                            // switch back to 16 bit Mode 3
+#endif
+#endif
+    zeichen = &font[((c -32) * offset) + 4];    // start of char bitmap
+    w = zeichen[0];                             // width of actual char
+    for (j=0; j<vert; j++) {  //  vert line
         for (i=0; i<hor; i++) {   //  horz line
             z =  zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
             b = 1 << (j & 0x07);
             if (( z & b ) == 0x00) {
+#if defined TARGET_KL25Z  // 8 Bit SPI
+                _spi.write(_background >> 8);
+                _spi.write(_background & 0xff);
+#else
                 _spi.write(_background);
+#endif
             } else {
+#if defined TARGET_KL25Z  // 8 Bit SPI
+                _spi.write(_foreground >> 8);
+                _spi.write(_foreground & 0xff);
+#else
                 _spi.write(_foreground);
+#endif
             }
         }
     }
@@ -1018,7 +1090,11 @@
 {
     unsigned int  j;
     int padd;
+#if defined TARGET_KL25Z  // 8 Bit SPI
+    unsigned char *bitmap_ptr = (unsigned char *)bitmap;
+#else
     unsigned short *bitmap_ptr = (unsigned short *)bitmap;
+#endif
     // the lines are padded to multiple of 4 bytes in a bitmap
     padd = -1;
     do {
@@ -1027,30 +1103,30 @@
     window(x, y, w, h);
     wr_cmd(0x22);
     _cs = 0;
-#if defined NO_MBED_LIB        
+#if defined NO_MBED_LIB
     if (spi_port == 0) {    // TFT on SSP0
-#if defined USE_DMA    
+#if defined USE_DMA
         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
         /* Enable SSP0 for DMA. */
         LPC_SSP0->DMACR = 0x2;
-#endif        
+#endif
         LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
         LPC_SSP0->DR = 0x72;        // start Data
         LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
 
     } else {
-#if defined USE_DMA    
+#if defined USE_DMA
         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
         /* Enable SSP1 for DMA. */
-        LPC_SSP1->DMACR = 0x2;   
-#endif        
+        LPC_SSP1->DMACR = 0x2;
+#endif
         LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
         LPC_SSP1->DR = 0x72;        // start Data command
         LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
     }
 
     bitmap_ptr += ((h - 1)* (w + padd));
-#if defined USE_DMA      
+#if defined USE_DMA
     for (j = 0; j < h; j++) {        //Lines
         LPC_GPDMA->DMACIntTCClear = 0x1;
         LPC_GPDMA->DMACIntErrClr = 0x1;
@@ -1073,8 +1149,8 @@
         }
         bitmap_ptr -= 2*w;
         bitmap_ptr -= padd;
-    }   
-#endif    
+    }
+#endif
     if (spi_port == 0) {    // TFT on SSP0
         do {
         } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI FIFO not empty
@@ -1083,24 +1159,39 @@
         } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
     }
 #else // use mbed lib
+#if defined TARGET_KL25Z  // 8 Bit SPI
+    _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
+#else
     _spi.format(8,3);                             // 8 bit Mode 3
     _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
     _spi.format(16,3);                            // switch to 16 bit Mode 3
+#endif
     unsigned int i;
     for (j = 0; j < h; j++) {        //Lines
         for (i = 0; i < w; i++) {     // copy pixel data to TFT
+#if defined TARGET_KL25Z  // 8 Bit SPI
+            _spi.write(*bitmap_ptr);
+            bitmap_ptr++;
+            _spi.write(*bitmap_ptr);
+            bitmap_ptr++;
+#else
             _spi.write(*bitmap_ptr);    // one line
             bitmap_ptr++;
+#endif
         }
         bitmap_ptr -= 2*w;
         bitmap_ptr -= padd;
     }
-#endif       
+#endif
     _cs = 1;
     WindowMax();
 }
 
 
+// local filesystem is not implemented in kinetis board
+#if defined TARGET_LPC1768  || defined TARGET_LPC11U24
+
+
 int SPI_TFT::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP)
 {
 
@@ -1171,7 +1262,7 @@
     window(x, y,PixelWidth ,PixelHeigh);
     wr_cmd(0x22);
     _cs = 0;
-#if defined NO_MBED_LIB 
+#if defined NO_MBED_LIB
     if (spi_port == 0) {    // TFT on SSP0
 #if defined USE_DMA
         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
@@ -1183,14 +1274,14 @@
         LPC_SSP0->CR0 |= 0x08UL;    // set to 16 bit
 
     } else {
-#if defined USE_DMA    
+#if defined USE_DMA
         LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
         /* Enable SSP1 for DMA. */
         LPC_SSP1->DMACR = 0x2;
 #endif
         LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
         LPC_SSP1->DR = 0x72;        // start Data
-        LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit     
+        LPC_SSP1->CR0 |= 0x08UL;    // set to 16 bit
     }
     for (j = PixelHeigh - 1; j >= 0; j--) {               //Lines bottom up
         off = j * (PixelWidth  * 2 + padd) + start_data;   // start of line
@@ -1206,10 +1297,10 @@
         do {
         } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running
 #else
-    for (i = 0; i < PixelWidth; i++) {        // copy pixel data to TFT
+        for (i = 0; i < PixelWidth; i++) {        // copy pixel data to TFT
             _spi.write(line[i]);                  // one 16 bit pixel
-        } 
-#endif            
+        }
+#endif
     }
     if (spi_port == 0) {    // TFT on SSP0
         do {
@@ -1218,7 +1309,7 @@
         do {
         } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
     }
-    
+
 #else // use mbed lib
     _spi.format(8,3);                             // 8 bit Mode 3
     _spi.write(SPI_START | SPI_WR | SPI_DATA);    // Write : RS = 1, RW = 0
@@ -1229,12 +1320,14 @@
         fread(line,1,PixelWidth * 2,Image);       // read a line - slow !
         for (i = 0; i < PixelWidth; i++) {        // copy pixel data to TFT
             _spi.write(line[i]);                  // one 16 bit pixel
-        } 
-     }
-#endif        
+        }
+    }
+#endif
     _cs = 1;
     free (line);
     fclose(Image);
     WindowMax();
     return(1);
-}
\ No newline at end of file
+}
+
+#endif