Added methods and features

Fork of SPI_TFT_ILI9341 by Peter Drescher

Revision:
9:6d30a225a5c7
Parent:
8:8593d3668153
Child:
10:2d505d14b7eb
--- a/SPI_TFT_ILI9341.cpp	Wed Apr 02 19:20:09 2014 +0000
+++ b/SPI_TFT_ILI9341.cpp	Mon Apr 07 20:25:09 2014 +0000
@@ -15,13 +15,11 @@
 // 18.10.13 Better Circle function from Michael Ammann
 // 22.10.13 Fixes for Kinetis Board - 8 bit spi
 // 26.01.14 Change interface for BMP_16 to also use SD-cards
-// 30.03.14 WH Added some methods for M24SR F103, Fixed typos & warnings, General define for SPI_16 selection
+// 30.03.14 WH Added some methods & defines, Fixed typos & warnings, General define for SPI_16 selection
 
-#include "SPI_TFT_ILI9341.h"
 #include "mbed.h"
+#include "SPI_TFT_ILI9341.h"
 
-#define BPP         16                  // Bits per pixel    
-         
 //extern Serial pc;
 //extern DigitalOut xx;     // debug !!
 
@@ -32,7 +30,12 @@
 //WH    clk = sclk;
 //WH    orientation = 0;
     _origin = Origin_LeftTop;  
-    char_x = 0;
+    _char_x = 0;
+    _char_y = 0;
+    _transparancy = false;    
+//    set_font(Arial12x12); //Default font    
+//    set_font(FONT8x8); //Default font, shame it doesnt fit format.. waste of flash space at moment
+    
     tft_reset();
 }
 
@@ -86,13 +89,13 @@
         case Origin_LeftTop:         /* Left Top of panel is origin */    
             _spi.write(0x48);
             break;
-        case Origin_RightTop:
+        case Origin_RightTop:        /* ok */ 
             _spi.write(0x28);
             break;
-        case Origin_RightBot:
+        case Origin_RightBot:        /* ok */ 
             _spi.write(0x88);
             break;
-        case Origin_LeftBot:
+        case Origin_LeftBot:        /* ok */ 
             _spi.write(0xE8);
             break;
     }
@@ -102,8 +105,13 @@
 #endif
 
 
+// background transparancy for characters 
+void SPI_TFT_ILI9341::set_transparancy(bool state) {
+  _transparancy = state;  
+}
+
+
 // write command to tft register
-
 void SPI_TFT_ILI9341::wr_cmd(unsigned char cmd)
 {
     _dc = 0;
@@ -113,18 +121,18 @@
 }
 
 
-
+// write data to tft
 void SPI_TFT_ILI9341::wr_dat(unsigned char dat)
 {
    _spi.write(dat);      // mbed lib
 }
 
+//WH
+// The ILI9341 can be read 
+// Read not supported in M24SR
 
-//WH
-//Read not supported in M24SR
-#if(0)
-// the ILI9341 can read 
 
+// Read byte
 char SPI_TFT_ILI9341::rd_byte(unsigned char cmd)
 {
     char r;
@@ -137,7 +145,7 @@
     return(r);
 }
 
-// read 32 bit
+// Read 32 bit
 int SPI_TFT_ILI9341::rd_32(unsigned char cmd)
 {
     int d;
@@ -162,6 +170,7 @@
     return(d);
 }
 
+//This may be not supported on some revisions of IL9341
 int  SPI_TFT_ILI9341::Read_ID(void){
     int r;
     r = rd_byte(0x0A);
@@ -170,33 +179,30 @@
     r = rd_byte(0x0A);
     return(r);
 }
-#endif
-
 
 
 // Init code based on MI0283QT datasheet
-
 void SPI_TFT_ILI9341::tft_reset()
 {
-//WH    _spi.format(8,0);                  // 8 bit spi Mode 0
+//WH    _spi.format(8,3);                  // 8 bit spi Mode 3
     _spi.format(8,0);                  // 8 bit spi mode 0    
     
-//WH    _spi.frequency(10000000);          // 10 Mhz SPI doesnt work on current version of mbed F103 lib due to issue with HSI/HSE...
-//    _spi.frequency(4000000);          // 4 Mhz SPI clock ==> 2.2Mhz
-    _spi.frequency(8000000);          // 8 Mhz SPI clock ==> Mhz
-
+    _spi.frequency(10000000);           // 10 Mhz SPI ... should work on current version of mbed F103 lib after fix for HSI/HSE...
+//    _spi.frequency(4000000);          // 4 Mhz SPI clock
+//    _spi.frequency(8000000);          // 8 Mhz SPI clock
     
     _cs = 1;                           // cs high
     _dc = 1;                           // dc high 
+
     _reset = 0;                        // display reset
-
     wait_us(50);
-    _reset = 1;                       // end hardware reset
+    _reset = 1;                        // end hardware reset
     wait_ms(5);
      
 //WH    wr_cmd(0x01);                     // SW reset  
     wr_cmd(ILI9341_DISPLAY_RST);      // SW reset      
     wait_ms(5);
+
 //WH    wr_cmd(0x28);                     // display off  
     wr_cmd(ILI9341_DISPLAY_OFF);      // display off      
 
@@ -266,7 +272,7 @@
      
 //     wr_cmd(0x36);                     // MEMORY_ACCESS_CONTROL
      wr_cmd(ILI9341_MAC);       // MEMORY_ACCESS_CONTROL     
-     _spi.write(0x48);
+     _spi.write(0x48);            // my,mx,mv,ml,BGR,mh,0,0
      _cs = 1; 
      
 //     wr_cmd(0x3A);                     // COLMOD_PIXEL_FORMAT_SET
@@ -364,18 +370,35 @@
  }
 
 
+void SPI_TFT_ILI9341::tft_on(bool on)
+{
+  if (on) {
+    wr_cmd(ILI9341_DISPLAY_ON); 
+  }  
+  else {
+    wr_cmd(ILI9341_DISPLAY_OFF); 
+  }  
+  _cs = 1;
+}
+
 void SPI_TFT_ILI9341::pixel(int x, int y, int color)
 {
 //    wr_cmd(0x2A);
     wr_cmd(ILI9341_COLUMN_ADDR);
     _spi.write(x >> 8);
     _spi.write(x);
+    _spi.write((x+1) >> 8);  //WH
+    _spi.write(x+1);   
+    
     _cs = 1;
     
 //    wr_cmd(0x2B);
     wr_cmd(ILI9341_PAGE_ADDR);
     _spi.write(y >> 8);
     _spi.write(y);
+    _spi.write((y+1) >> 8); //WH
+    _spi.write(y+1);
+    
     _cs = 1;
 
 //    wr_cmd(0x2C);  // send pixel
@@ -393,7 +416,8 @@
     #endif
 #endif
 
-    #if (SPI_16 == 1)
+//    #if (SPI_16 == 1)
+    #if(0)   // dont bother switching for only one pixel
     // 16 Bit SPI
     _spi.format(16,0);                            // switch to 16 bit Mode 0
     _spi.write(color);                            // Write D0..D15
@@ -505,6 +529,120 @@
     } while (x <= 0);
 }
 
+
+void SPI_TFT_ILI9341::oval ( int x, int y, int b, int color, float aspect )
+{  
+  /* local variables */
+  int   col;               /* Column. */
+  int   row;               /* Row. */
+  float aspect_square;
+  int   a_square;
+  int   b_square;
+  int   two_a_square;
+  int   two_b_square;
+  int   four_a_square;
+  int   four_b_square;
+  int   d; 
+
+  aspect_square = aspect * aspect;  
+  
+  b_square = b * b;
+  a_square = b_square / aspect_square; 
+  row = b;
+  col = 0;
+  two_a_square = a_square << 1;
+  four_a_square = a_square << 2;
+  four_b_square = b_square << 2;
+  two_b_square = b_square << 1;
+  d = two_a_square * ((row - 1) * (row)) + a_square + two_b_square * (1 - a_square);
+      
+  while (a_square * (row) > b_square * col ) {
+    pixel( x + col, y + row, color );    
+    pixel( x + col, y - row, color );    
+    pixel( x - col, y + row, color );    
+    pixel( x - col, y - row, color );    
+    if ( d >= 0 ) {
+      row--;
+      d -= four_a_square * row;
+    }
+    d += two_b_square * (3 + (col << 1));
+    col++;
+  }
+  
+  d = two_b_square * (col + 1) * col + two_a_square * (row * (row - 2) + 1) + (1 - two_a_square) * b_square;    
+  
+  while ( row + 1 ) {
+    pixel( x + col, y + row, color );    
+    pixel( x + col, y - row, color );    
+    pixel( x - col, y + row, color );    
+    pixel( x - col, y - row, color );    
+    if ( d <= 0 ) {
+      col++;
+      d += four_b_square * col;
+    }
+    row--;
+    d += two_a_square * (3 - (row << 1));
+  }
+
+} /* End oval */
+
+
+void SPI_TFT_ILI9341::filloval ( int x, int y, int b, int color, float aspect )
+{  
+  /* local variables */
+  int   col;               /* Column. */
+  int   row;               /* Row. */
+  float aspect_square;
+  int   a_square;
+  int   b_square;
+  int   two_a_square;
+  int   two_b_square;
+  int   four_a_square;
+  int   four_b_square;
+  int   d; 
+
+  aspect_square = aspect * aspect;  
+  
+  b_square = b * b;
+  a_square = b_square / aspect_square; 
+  row = b;
+  col = 0;
+  two_a_square = a_square << 1;
+  four_a_square = a_square << 2;
+  four_b_square = b_square << 2;
+  two_b_square = b_square << 1;
+  d = two_a_square * ((row - 1) * (row)) + a_square + two_b_square * (1 - a_square);
+      
+  while (a_square * (row) > b_square * col ) {
+    vline(x - col, y - row, y + row, color);    
+    vline(x + col, y - row, y + row, color);           
+
+    if ( d >= 0 ) {
+      row--;
+      d -= four_a_square * row;
+    }
+    d += two_b_square * (3 + (col << 1));
+    col++;
+  }
+  
+  d = two_b_square * (col + 1) * col + two_a_square * (row * (row - 2) + 1) + (1 - two_a_square) * b_square;    
+  
+  while ( row + 1 ) {
+    vline(x - col, y - row, y + row, color);    
+    vline(x + col, y - row, y + row, color);           
+   
+    if ( d <= 0 ) {
+      col++;
+      d += four_b_square * col;
+    }
+    row--;
+    d += two_a_square * (3 - (row << 1));
+  }
+
+} /* End filloval */
+
+
+
 //WH
 #if(0)
 void SPI_TFT_ILI9341::hline(int x0, int x1, int y, int color)
@@ -741,8 +879,12 @@
 
 void SPI_TFT_ILI9341::fillrect(int x0, int y0, int x1, int y1, int color)
 {  
-    int h = y1 - y0 + 1;  //may want to add a sanity check on y1 > y0
-    int w = x1 - x0 + 1;  //may want to add a sanity check on x1 > x0
+    //sanity check
+    if ( x0 > x1 ) swap( int, x0, x1 )
+    if ( y0 > y1 ) swap( int, y0, y1 )
+
+    int h = y1 - y0 + 1; 
+    int w = x1 - x0 + 1; 
     int pixels = h * w;
     int i, msb, lsb;        
  
@@ -770,12 +912,65 @@
 }
 #endif
 
+void SPI_TFT_ILI9341::roundrect( int x1, int y1, int x2, int y2, int color )
+{
+    //sanity check      
+    if ( x1 > x2 ) swap( int, x1, x2 )
+    if ( y1 > y2 ) swap( int, y1, y2 )
+ 
+    if ( ( x2 - x1 ) > 4 && ( y2 - y1 ) > 4 )
+    {
+        pixel( x1 + 1, y1 + 1, color );
+        pixel( x2 - 1, y1 + 1, color );
+        pixel( x1 + 1, y2 - 1, color );
+        pixel( x2 - 1, y2 - 1, color );
+//x0, x1, y
+        hline( x1 + 2, x2 - 2 ,y1, color );
+        hline( x1 + 2, x2 - 2, y2, color );     
+//y0, y1, x        
+        vline( y1 + 2, y2 - 2, x1, color );
+        vline( y1 + 2, y2 - 2, x2, color );
+    }
+}
+
+ 
+void SPI_TFT_ILI9341::fillroundrect( int x1, int y1, int x2, int y2, int color )
+{
+    //sanity check
+    if ( x1 > x2 ) swap( int, x1, x2 )
+    if ( y1 > y2 ) swap( int, y1, y2 )
+ 
+    if ( ( x2 - x1 ) > 4 && ( y2 - y1 ) > 4 )
+    {
+        for ( int i = 0; i < ( ( y2 - y1 ) / 2 ) + 1; i++ )
+        {
+            switch ( i )
+            {
+                case 0:
+                    hline( x1 + 2, x2 - 2, y1 + i, color );
+                    hline( x1 + 2, x2 - 2, y2 - i, color );
+                    break;
+ 
+                case 1:
+                    hline( x1 + 1, x2 - 1, y1 + i, color );
+                    hline( x1 + 1, x2 - 1, y2 - i, color );
+                    break;
+ 
+                default:
+                    hline( x1, x2, y1 + i, color );
+                    hline( x1, x2, y2 - i, color );
+                    break;
+            }
+        }
+    }
+}
+
 
 
 void SPI_TFT_ILI9341::locate(int x, int y)
 {
-    char_x = x;
-    char_y = y;
+    _char_x = x;
+    _char_y = y;
 }
 
 
@@ -797,13 +992,13 @@
 int SPI_TFT_ILI9341::_putc(int value)
 {
     if (value == '\n') {    // new line
-        char_x = 0;
-        char_y = char_y + _font[2];
-        if (char_y >= height() - _font[2]) {
-            char_y = 0;
+        _char_x = 0;
+        _char_y = _char_y + _font[2];
+        if (_char_y >= height() - _font[2]) {
+            _char_y = 0;
         }
     } else {
-        character(char_x, char_y, value);
+        character(_char_x, _char_y, value);
     }
     return value;
 }
@@ -824,14 +1019,14 @@
     vert   = _font[2];                   // get vert size of font
     bpl    = _font[3];                   // bytes per line
 
-    if (char_x + hor > width()) {
-        char_x = 0;
-        char_y = char_y + vert;
-        if (char_y >= height() - _font[2]) {
-            char_y = 0;
+    if (_char_x + hor > width()) {
+        _char_x = 0;
+        _char_y = _char_y + vert;
+        if (_char_y >= height() - _font[2]) {
+            _char_y = 0;
         }
     }
-    window(char_x, char_y,hor,vert); // char box
+    window(_char_x, _char_y,hor,vert); // char box
     wr_cmd(0x2C);  // send pixel
     #ifndef TARGET_KL25Z  // 16 Bit SPI 
     _spi.format(16,0);   
@@ -865,10 +1060,13 @@
     #endif
     window_max();
     if ((w + 2) < hor) {                   // x offset to next char
-        char_x += w + 2;
-    } else char_x += hor;
+        __char_x += w + 2;
+    } else __char_x += hor;
 }
 #else
+
+#if (TRANSPARANCY == 1)
+//WH write foreground, write background only when not transparant mode
 void SPI_TFT_ILI9341::character(int x, int y, int c)
 {
     unsigned int hor,vert,offset,bpl,j,i,b;
@@ -883,14 +1081,67 @@
     vert   = _font[2];                   // get vert size of font
     bpl    = _font[3];                   // bytes per line
 
-    if (char_x + hor > width()) {
-        char_x = 0;
-        char_y = char_y + vert;
-        if (char_y >= height() - _font[2]) {
-            char_y = 0;
+    if (_char_x + hor > width()) {
+        _char_x = 0;
+        _char_y = _char_y + vert;
+        if (_char_y >= height() - vert) {
+            _char_y = 0;
         }
     }
-    window(char_x, char_y, hor, vert); // char box
+  
+    symbol = &_font[((c - 32) * offset) + 4]; // start of char bitmap
+    w = symbol[0];                            // width of actual char (proportional font)
+    for (j=0; j<vert; j++) {  //  vert line
+      for (i=0; i<hor; i++) {   //  horz line
+        z =  symbol[bpl * i + ((j & 0xF8) >> 3) + 1];
+        b = 1 << (j & 0x07);
+        
+        // Test bit in character bitmap to write either _foreground or _background color
+        if (( z & b ) == 0x00) {
+          // bit is 0, write _background color
+          if (!_transparancy) { // write background color only when transparancy is 'off'  
+            pixel(_char_x+i, _char_y+j, _background);
+          }  
+        }
+        else {
+          // bit is 1, write _foreground color          
+          pixel(_char_x+i, _char_y+j, _foreground);
+        } // if bit
+      } // for i
+    } // for j
+
+    window_max();
+
+    if ((w + 2) < hor) {                   // x offset to next char
+        _char_x += w + 2;
+    } else _char_x += hor;
+}
+
+#else
+
+//WH write foreground and background
+void SPI_TFT_ILI9341::character(int x, int y, int c)
+{
+    unsigned int hor,vert,offset,bpl,j,i,b;
+    unsigned char* symbol;
+    unsigned char z,w;
+
+    if ((c < 31) || (c > 127)) return;   // test char range
+
+    // read font parameter from start of array
+    offset = _font[0];                   // bytes / char
+    hor    = _font[1];                   // get hor size of font
+    vert   = _font[2];                   // get vert size of font
+    bpl    = _font[3];                   // bytes per line
+
+    if (_char_x + hor > width()) {
+        _char_x = 0;
+        _char_y = _char_y + vert;
+        if (_char_y >= height() - vert) {
+            _char_y = 0;
+        }
+    }
+    window(_char_x, _char_y, hor, vert); // char box
 //    wr_cmd(0x2C);  // send pixel
     wr_cmd(ILI9341_GRAM);  // send pixel         
     
@@ -899,12 +1150,15 @@
     _spi.format(16,0);   // switch to 16 bit Mode 0
     #endif                         
     symbol = &_font[((c - 32) * offset) + 4]; // start of char bitmap
-    w = symbol[0];                            // width of actual char
+    w = symbol[0];                            // width of actual char (proportional font)
     for (j=0; j<vert; j++) {  //  vert line
       for (i=0; i<hor; i++) {   //  horz line
-        z =  symbol[bpl * i + ((j & 0xF8) >> 3)+1];
+        z =  symbol[bpl * i + ((j & 0xF8) >> 3) + 1];
         b = 1 << (j & 0x07);
+        
+        // Test bit in character bitmap to write either _foreground or _background color
         if (( z & b ) == 0x00) {
+          // bit is 0, write _background color
           #if (SPI_16 == 1)
           // 16 Bit SPI 
           _spi.write(_background);
@@ -915,6 +1169,7 @@
           #endif
         }
         else {
+          // bit is 1, write _foreground color          
           #if (SPI_16 == 1)
           // 16 Bit SPI
           _spi.write(_foreground);
@@ -923,7 +1178,7 @@
           _spi.write(_foreground >> 8);
           _spi.write(_foreground & 0xff);
           #endif
-        } // if
+        } // if bit
       } // for i
     } // for j
 
@@ -934,9 +1189,12 @@
     window_max();
 
     if ((w + 2) < hor) {                   // x offset to next char
-        char_x += w + 2;
-    } else char_x += hor;
+        _char_x += w + 2;
+    } else _char_x += hor;
 }
+#endif
+
+
 
 #endif
 
@@ -953,8 +1211,8 @@
     unsigned int  j;
     int padd;
     unsigned short *bitmap_ptr = (unsigned short *)bitmap;
-    #if defined TARGET_KL25Z  // 8 Bit SPI
-        unsigned short pix_temp;
+    #if (SPI_16 != 1)  // 16 Bit SPI    
+    unsigned short pix_temp;
     #endif
     
     unsigned int i;
@@ -969,33 +1227,36 @@
 //    wr_cmd(0x2C);  // send pixel
     wr_cmd(ILI9341_GRAM);  // send pixel     
         
-    #ifndef TARGET_KL25Z  // 16 Bit SPI 
-    _spi.format(16,0);
-    #endif                            // switch to 16 bit Mode 0
+    #if (SPI_16 == 1)  // 16 Bit SPI
+    _spi.format(16,0); // switch to 16 bit Mode 0
+    #endif                            
     for (j = 0; j < h; j++) {         //Lines
         for (i = 0; i < w; i++) {     // one line
-            #if defined TARGET_KL25Z  // 8 Bit SPI
+            #if (SPI_16 == 1)
+                // 16 Bit SPI            
+                _spi.write(*bitmap_ptr);    // one line
+                bitmap_ptr++;
+            #else                
+               // 8 Bit SPI
                 pix_temp = *bitmap_ptr;
                 _spi.write(pix_temp >> 8);
                 _spi.write(pix_temp);
                 bitmap_ptr++;
-            #else
-                _spi.write(*bitmap_ptr);    // one line
-                bitmap_ptr++;
             #endif
         }
         bitmap_ptr -= 2*w;
         bitmap_ptr -= padd;
     }
     _cs = 1;
-    #ifndef TARGET_KL25Z  // 16 Bit SPI 
-    _spi.format(8,0);
+
+    #if (SPI_16 == 1)    
+    _spi.format(8,0); // switch back to 8 bit Mode 0
     #endif
     window_max();
 }
 
 
-// local filesystem is not implemented in kinetis board , but you can add a SD card
+// local filesystem is not implemented in kinetis board, but you can add an SD card
 
 int SPI_TFT_ILI9341::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP)
 {
@@ -1063,24 +1324,30 @@
 //    wr_cmd(0x2C);  // send pixel
     wr_cmd(ILI9341_GRAM);  // send pixel         
     
-    #ifndef TARGET_KL25Z // only 8 Bit SPI 
-    _spi.format(16,0);  
-    #endif                          // switch to 16 bit Mode 0
+    #if (SPI_16 == 1)        
+    _spi.format(16,0);   // switch to 16 bit Mode 0
+    #endif                          
     for (j = PixelHeigh - 1; j >= 0; j--) {               //Lines bottom up
         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 
         for (i = 0; i < PixelWidth; i++) {        // copy pixel data to TFT
-        #ifndef TARGET_KL25Z // only 8 Bit SPI
-            _spi.write(line[i]);                  // one 16 bit pixel
-        #else  
-            _spi.write(line[i] >> 8);
-            _spi.write(line[i]);
+        #if (SPI_16 == 1)
+        // one 16 bit pixel                                                   
+        _spi.write(line[i]);
+        #else              
+        // only 8 Bit SPI
+        _spi.write(line[i] >> 8);
+        _spi.write(line[i]);
         #endif    
         } 
      }
     _cs = 1;
-    _spi.format(8,0);
+    
+    #if (SPI_16 == 1)            
+    _spi.format(8,0);    // switch back to 8 bit Mode 0
+    #endif
+    
     free (line);
     fclose(Image);
     window_max();
@@ -1100,7 +1367,7 @@
 {
   uint32_t index = 0, size = 0, width=0, height=0;
   uint16_t *pBmpWord=0;
-  uint16_t data;
+//  uint16_t data;
  
   /* Read bitmap width*/
   width = BmpName[0]+1; 
@@ -1115,27 +1382,34 @@
   wr_cmd(ILI9341_GRAM);  // send pixel       
 
   /* Set WRX to send data */
-  _dc = 1;
+//WH  _dc = 1;
+
+  #if (SPI_16 == 1)        
+  _spi.format(16,0);   // switch to 16 bit Mode 0
+  #endif                          
 
   pBmpWord = (uint16_t *) (&BmpName[5]);
-  /* Send them on the screen */
+  /* Send to the screen */
   for(index = 0; index < size; index++)
   {
-    _cs = 0;       
-
-    data = (*pBmpWord & 0x00FF);
-    _spi.write(data);
-
-    data = (*pBmpWord & 0xFF00)>>8;
-    _spi.write(data);
-           
-    _cs = 1;  
-      
+    #if (SPI_16 == 1)
+    // one 16 bit pixel                                                   
+    _spi.write(*pBmpWord);    
+    #else              
+    // only 8 Bit SPI
+    _spi.write(*pBmpWord & 0xFF);
+    _spi.write((*pBmpWord>>8) & 0xFF);   
+    #endif       
+                  
     pBmpWord++;
   } 
 
   /* Set LCD control line(/CS) */
   _cs = 1;  
+
+  #if (SPI_16 == 1)            
+  _spi.format(8,0);    // switch back to 8 bit Mode 0
+  #endif
         
   window_max();
 }