Added methods and features
Fork of SPI_TFT_ILI9341 by
Diff: SPI_TFT_ILI9341.cpp
- 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(); }