Hardware testing for M24SR-DISCOVERY demo PCB. as help to others
Set up to use MB1138 M24SR-DISCOVERY PCB http://www.st.com/content/st_com/en/products/evaluation-tools/product-evaluation-tools/st25-nfc-rfid-eval-boards/st25-nfc-rfid-eval-boards/m24sr-discovery.html with MBED system. based on https://developer.mbed.org/users/hudakz/code/STM32F103C8T6_Hello/ code and https://developer.mbed.org/users/wim/notebook/m24sr64-nfcrfid-tag-with-i2c-interface/ Which lead me to look at Peter Drescher's work on ILI9341 LCD controller
https://developer.mbed.org/users/dreschpe/code/SPI_TFT_ILI9341/
Diff: SPI_TFT_ILI9341/SPI_TFT_ILI9341.cpp
- Revision:
- 2:2033db202017
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SPI_TFT_ILI9341/SPI_TFT_ILI9341.cpp Thu Sep 29 11:07:41 2016 +0000 @@ -0,0 +1,1372 @@ +/* mbed library for 240*320 pixel display TFT based on ILI9341 LCD Controller + * Copyright (c) 2013 Peter Drescher - DC2PD + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// 12.06.13 fork from SPI_TFT code because controller is different ... +// 14.07.13 Test with real display and bugfix +// 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 & defines, Fixed typos & warnings, General define for SPI_16 selection + +#include "mbed.h" +#include "SPI_TFT_ILI9341.h" + +//extern Serial pc; +//extern DigitalOut xx; // debug !! + +SPI_TFT_ILI9341::SPI_TFT_ILI9341(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset, PinName dc, const char *name) + : GraphicsDisplay(name), _spi(mosi, miso, sclk), _cs(cs), _dc(dc) +{ + + // The hardware Reset pin is optional. Test and make sure whether it exists or not to prevent illegal access. + if (reset != NC) { + _reset = new DigitalOut(reset, 1); //Construct new pin, Deactivated +// _reset->write(1); //Deactivate + } + else { + // No Hardware Reset pin + _reset = NULL; //Construct dummy pin + } + +//WH clk = sclk; +//WH orientation = 0; + _origin = Origin_LeftTop; + _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(); +} + + +/** Destruct a SPI_TFT LCD object + * + * @param none + * @return none + */ +SPI_TFT_ILI9341::~SPI_TFT_ILI9341() { + if (_reset != NULL) {delete _reset;} // HW Reset pin +} + + + +int SPI_TFT_ILI9341::width() +{ + // if (orientation == 0 || orientation == 2) return 240; + // else return 320; +return 320; + //if (_origin == Origin_LeftTop || _origin == Origin_RightBot) return TFT_WIDTH; + // else return TFT_HEIGHT; +} + + +int SPI_TFT_ILI9341::height() +{ + // if (orientation == 0 || orientation == 2) return 320; + // else return 240; +return 240; + //if (_origin == Origin_LeftTop || _origin == Origin_RightBot) return TFT_HEIGHT; + //else return TFT_WIDTH; +} + +//WH +//#if(0) +void SPI_TFT_ILI9341::set_orientation(unsigned int o) +{ + int orientation = o; + wr_cmd(0x36); // MEMORY_ACCESS_CONTROL + switch (orientation) { + case 0: + _spi.write(0x48); + break; + case 1: + _spi.write(0x28); + break; + case 2: + _spi.write(0x88); + break; + case 3: + _spi.write(0xE8); + break; + } + _cs = 1; + window_max(); +} +//#else +void SPI_TFT_ILI9341::set_origin(Origin origin) { + _origin = origin; + wr_cmd(ILI9341_MAC); // MEMORY_ACCESS_CONTROL + switch (_origin) { + case Origin_LeftTop: /* Left Top of panel is origin */ + _spi.write(0x48); + break; + case Origin_RightTop: /* ok */ + _spi.write(0x28); + break; + case Origin_RightBot: /* ok */ + _spi.write(0x88); + break; + case Origin_LeftBot: /* ok */ + _spi.write(0xE8); + break; + } + _cs = 1; + window_max(); +} +//#endif + + +// background transparancy for characters +void SPI_TFT_ILI9341::set_transparancy(bool state) { + _transparancy = state; +} + +// HW Reset to tft +void SPI_TFT_ILI9341::_hwreset() +{ + // _reset is an optional pin which defaults to NC. Make sure it does not hang mbed lib + if (_reset != NULL) {_reset->write(0);} //Clear _reset pin + wait_us(50); + if (_reset != NULL) {_reset->write(1);} //Set _reset pin + wait_ms(5); +} + + +// write command to tft register +void SPI_TFT_ILI9341::wr_cmd(unsigned char cmd) +{ + _dc = 0; + _cs = 0; + _spi.write(cmd); // mbed lib + _dc = 1; +} + + +// 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 + + +// Read byte +char SPI_TFT_ILI9341::rd_byte(unsigned char cmd) +{ + char r; + _dc = 0; + _cs = 0; + _spi.write(cmd); // mbed lib + _cs = 1; + r = _spi.write(0xff); + _cs = 1; + return(r); +} + +// Read 32 bit +int SPI_TFT_ILI9341::rd_32(unsigned char cmd) +{ + int d; + char r; + _dc = 0; + _cs = 0; + d = cmd; + d = d << 1; + +//Note WH: the 9bit format is not supported for most mbed devices...This wont work. + _spi.format(9,0); // we have to add a dummy clock cycle + + _spi.write(d); + _spi.format(8,0); + _dc = 1; + r = _spi.write(0xff); + d = r; + r = _spi.write(0xff); + d = (d << 8) | r; + r = _spi.write(0xff); + d = (d << 8) | r; + r = _spi.write(0xff); + d = (d << 8) | r; + _cs = 1; + 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); + r = rd_byte(0x0A); + r = rd_byte(0x0A); + r = rd_byte(0x0A); + return(r); +} + + +// Init code based on MI0283QT datasheet +void SPI_TFT_ILI9341::tft_reset() +{ +//WH _spi.format(8,3); // 8 bit spi Mode 3 + _spi.format(8,0); // 8 bit spi, mode 0 + +// _spi.frequency(4000000); // 4 Mhz SPI clock +// _spi.frequency(8000000); // 8 Mhz SPI clock + _spi.frequency(10000000); // 10 Mhz SPI ... works on current version of mbed F103 lib after fix for HSI/HSE... + + _cs = 1; // cs high + _dc = 1; // dc high + + _hwreset(); // HW reset + + wr_cmd(ILI9341_DISPLAY_RST); // SW reset + wait_ms(5); + + wr_cmd(ILI9341_DISPLAY_OFF); // display off + + /* Start Initial Sequence ----------------------------------------------------*/ + wr_cmd(ILI9341_POWERB); /* Power control B register */ + _spi.write(0x00); + _spi.write(0x83); + _spi.write(0x30); + _cs = 1; + + wr_cmd(ILI9341_POWER_SEQ); /* Power on sequence register */ + _spi.write(0x64); + _spi.write(0x03); + _spi.write(0x12); + _spi.write(0x81); + _cs = 1; + + wr_cmd(ILI9341_DTCA); /* Driver timing control A */ + _spi.write(0x85); + _spi.write(0x01); + _spi.write(0x79); + _cs = 1; + + wr_cmd(ILI9341_POWERA); /* Power control A register */ + _spi.write(0x39); + _spi.write(0x2C); + _spi.write(0x00); + _spi.write(0x34); + _spi.write(0x02); + _cs = 1; + + wr_cmd(ILI9341_PRC); /* Pump ratio control register */ + _spi.write(0x20); + _cs = 1; + + wr_cmd(ILI9341_DTCB); /* Driver timing control B */ + _spi.write(0x00); + _spi.write(0x00); + _cs = 1; + + wr_cmd(ILI9341_POWER1); // POWER_CONTROL_1 + _spi.write(0x26); + _cs = 1; + + wr_cmd(ILI9341_POWER2); // POWER_CONTROL_2 + _spi.write(0x11); + _cs = 1; + + wr_cmd(ILI9341_VCOM1); // VCOM_CONTROL_1 + _spi.write(0x35); + _spi.write(0x3E); + _cs = 1; + + wr_cmd(ILI9341_VCOM2); // VCOM_CONTROL_2 + _spi.write(0xBE); + _cs = 1; + + wr_cmd(ILI9341_MAC); // MEMORY_ACCESS_CONTROL + _spi.write(0x48); // my,mx,mv,ml,BGR,mh,0,0 + _cs = 1; + + wr_cmd(ILI9341_PIXEL_FORMAT); /* Pixel Format register */ + _spi.write(0x55); // 16 bit pixel + _cs = 1; + + wr_cmd(ILI9341_FRC); /* Frame Rate Control register */ + _spi.write(0x00); + _spi.write(0x1B); + _cs = 1; + + wr_cmd(ILI9341_3GAMMA_EN); /* 3 Gamma enable register */ + _spi.write(0x08); // Gamma Function Disable + _cs = 1; + + wr_cmd(ILI9341_GAMMA); /* Gamma register */ + _spi.write(0x01); // gamma set for curve 01/2/04/08 + _cs = 1; + + wr_cmd(ILI9341_PGAMMA); /* Positive Gamma Correction register*/ + _spi.write(0x1F); + _spi.write(0x1A); + _spi.write(0x18); + _spi.write(0x0A); + _spi.write(0x0F); + _spi.write(0x06); + _spi.write(0x45); + _spi.write(0x87); + _spi.write(0x32); + _spi.write(0x0A); + _spi.write(0x07); + _spi.write(0x02); + _spi.write(0x07); + _spi.write(0x05); + _spi.write(0x00); + _cs = 1; + + wr_cmd(ILI9341_NGAMMA); /* Negative Gamma Correction register*/ + _spi.write(0x00); + _spi.write(0x25); + _spi.write(0x27); + _spi.write(0x05); + _spi.write(0x10); + _spi.write(0x09); + _spi.write(0x3A); + _spi.write(0x78); + _spi.write(0x4D); + _spi.write(0x05); + _spi.write(0x18); + _spi.write(0x0D); + _spi.write(0x38); + _spi.write(0x3A); + _spi.write(0x1F); + _cs = 1; + + window_max(); + + //wr_cmd(ILI9341_TEAR_OFF); // tearing effect off + //_cs = 1; + + //wr_cmd(ILI9341_TEAR_ON); // tearing effect on + //_cs = 1; + + wr_cmd(ILI9341_ENTRY_MODE); // entry mode + _spi.write(0x07); + _cs = 1; + + wr_cmd(ILI9341_DFC); /* Display Function Control register*/ + _spi.write(0x0A); + _spi.write(0x82); + _spi.write(0x27); + _spi.write(0x00); + _cs = 1; + + wr_cmd(ILI9341_SLEEP_OUT); // sleep out + _cs = 1; + + wait_ms(100); + + wr_cmd(ILI9341_DISPLAY_ON); + _cs = 1; + + wait_ms(100); + + } + + +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(ILI9341_COLUMN_ADDR); + _spi.write(x >> 8); + _spi.write(x); + _spi.write((x+1) >> 8); //WH + _spi.write(x+1); + + _cs = 1; + + 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(ILI9341_GRAM); // send pixel + +// #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 + _spi.format(8,0); // switch back to 8 bit Mode 0 + #else + // 8 Bit SPI + _spi.write(color >> 8); + _spi.write(color & 0xff); + #endif + + _cs = 1; +} + + +void SPI_TFT_ILI9341::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h) +{ + + wr_cmd(ILI9341_COLUMN_ADDR); + _spi.write(x >> 8); + _spi.write(x); + _spi.write((x+w-1) >> 8); + _spi.write(x+w-1); + _cs = 1; + + wr_cmd(ILI9341_PAGE_ADDR); + _spi.write(y >> 8); + _spi.write(y); + _spi.write((y+h-1) >> 8); + _spi.write(y+h-1); + _cs = 1; +} + + +void SPI_TFT_ILI9341::window_max (void) +{ + window (0, 0, width(), height()); +} + + + +/** Fill the screen with _background color + * @param none + * @return none + */ +void SPI_TFT_ILI9341::cls() +{ + fillrect(0, 0, width()-1, height()-1, _background); +} + + +//WH test +void SPI_TFT_ILI9341::newcls (void) +{ + int pixels = height() * width(); + int i; + int color = _background; +#if (SPI_16 != 1) + int msb, lsb; +#endif + + window(0,0,width(),height()); + + wr_cmd(ILI9341_GRAM); // send pixel + +#if (SPI_16 == 1) + // 16 Bit SPI + _spi.format(16,0); // switch to 16 bit Mode 0 + + //unroll loop in chunks of 8 pixels + for (i = 0; i < (pixels>>3); i++) { + _spi.write(color); + _spi.write(color); + _spi.write(color); + _spi.write(color); + + _spi.write(color); + _spi.write(color); + _spi.write(color); + _spi.write(color); + } + + //remainder + for (i = 0; i < (pixels & 0x07); i++) + _spi.write(color); + + _spi.format(8,0); // switch back to 8 bit Mode 0 +#else + // 8 Bit SPI + msb = color >> 8; + lsb = color & 0xff; + + for (i = 0; i < (pixels>>3); i+=8) { + _spi.write(msb); _spi.write(lsb); + _spi.write(msb); _spi.write(lsb); + _spi.write(msb); _spi.write(lsb); + _spi.write(msb); _spi.write(lsb); + + _spi.write(msb); _spi.write(lsb); + _spi.write(msb); _spi.write(lsb); + _spi.write(msb); _spi.write(lsb); + _spi.write(msb); _spi.write(lsb); + } + + for (i = 0; i < (pixels & 0x07); i++) { + _spi.write(msb); _spi.write(lsb); + } +#endif + + _cs = 1; +} + + + + +void SPI_TFT_ILI9341::circle(int x0, int y0, int r, int color) +{ + + int x = -r, y = 0, err = 2-2*r, e2; + do { + pixel(x0-x, y0+y,color); + pixel(x0+x, y0+y,color); + pixel(x0+x, y0-y,color); + pixel(x0-x, y0-y,color); + e2 = err; + if (e2 <= y) { + err += ++y*2+1; + if (-x == y && e2 <= x) e2 = 0; + } + if (e2 > x) err += ++x*2+1; + } while (x <= 0); + +} + +void SPI_TFT_ILI9341::fillcircle(int x0, int y0, int r, int color) +{ + int x = -r, y = 0, err = 2-2*r, e2; + do { + vline(x0-x, y0-y, y0+y, color); + vline(x0+x, y0-y, y0+y, color); + e2 = err; + if (e2 <= y) { + err += ++y*2+1; + if (-x == y && e2 <= x) e2 = 0; + } + if (e2 > x) err += ++x*2+1; + } 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 */ + + +void SPI_TFT_ILI9341::hline(int x0, int x1, int y, int color) +{ + int i, w; +#if (SPI_16 != 1) + int msb, lsb; +#endif + w = x1 - x0 + 1; + window(x0,y,w,1); +// wr_cmd(0x2C); // send pixel + wr_cmd(ILI9341_GRAM); // send pixel + +#if (SPI_16 == 1) + // 16 Bit SPI + _spi.format(16,0); // switch to 16 bit Mode 0 + for (i = 0; i < w; i++) + _spi.write(color); + _spi.format(8,0); // switch back to 8 bit Mode 0 +#else + // 8 Bit SPI + msb = color >> 8; + lsb = color & 0xff; + for (i = 0; i < w; i++){ + _spi.write(msb); + _spi.write(lsb); + } +#endif + + _cs = 1; + window_max(); +} + + + +void SPI_TFT_ILI9341::vline(int x, int y0, int y1, int color) +{ + int i, h; +#if (SPI_16 != 1) + int msb, lsb; +#endif + + h = y1 - y0 + 1; + window(x,y0,1,h); +// wr_cmd(0x2C); // send pixel + wr_cmd(ILI9341_GRAM); // send pixel + +#if (SPI_16 == 1) + // 16 Bit SPI + _spi.format(16,0); // switch to 16 bit Mode 0 + for (i = 0; i < h; i++) + _spi.write(color); + _spi.format(8,0); // switch back to 8 bit Mode 0 +#else + // 8 Bit SPI + msb = color >> 8; + lsb = color & 0xff; + for (i = 0; i < h; i++){ + _spi.write(msb); + _spi.write(lsb); + } +#endif + + _cs = 1; + window_max(); +} + +void SPI_TFT_ILI9341::line(int x0, int y0, int x1, int y1, int color) +{ + //window_max(); + int dx = 0, dy = 0; + int dx_sym = 0, dy_sym = 0; + int dx_x2 = 0, dy_x2 = 0; + int di = 0; + + dx = x1-x0; + dy = y1-y0; + + if (dx == 0) { /* vertical line */ + if (y1 > y0) vline(x0,y0,y1,color); + else vline(x0,y1,y0,color); + return; + } + + if (dx > 0) { + dx_sym = 1; + } else { + dx_sym = -1; + } + if (dy == 0) { /* horizontal line */ + if (x1 > x0) hline(x0,x1,y0,color); + else hline(x1,x0,y0,color); + return; + } + + if (dy > 0) { + dy_sym = 1; + } else { + dy_sym = -1; + } + + dx = dx_sym*dx; + dy = dy_sym*dy; + + dx_x2 = dx*2; + dy_x2 = dy*2; + + if (dx >= dy) { + di = dy_x2 - dx; + while (x0 != x1) { + + pixel(x0, y0, color); + x0 += dx_sym; + if (di<0) { + di += dy_x2; + } else { + di += dy_x2 - dx_x2; + y0 += dy_sym; + } + } + pixel(x0, y0, color); + } else { + di = dx_x2 - dy; + while (y0 != y1) { + pixel(x0, y0, color); + y0 += dy_sym; + if (di < 0) { + di += dx_x2; + } else { + di += dx_x2 - dy_x2; + x0 += dx_sym; + } + } + pixel(x0, y0, color); + } +//WH return; +} + + +void SPI_TFT_ILI9341::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); + + if (y1 > y0) vline(x0,y0,y1,color); + else vline(x0,y1,y0,color); + + if (x1 > x0) hline(x0,x1,y1,color); + else hline(x1,x0,y1,color); + + if (y1 > y0) vline(x1,y0,y1,color); + else vline(x1,y1,y0,color); + +//WH return; +} + + +void SPI_TFT_ILI9341::fillrect(int x0, int y0, int x1, int y1, int color) +{ + //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; +#if (SPI_16 != 1) + int msb, lsb; +#endif + + window(x0,y0,w,h); +// wr_cmd(0x2C); // send pixel + wr_cmd(ILI9341_GRAM); // send pixel + +#if (SPI_16 == 1) + // 16 Bit SPI + _spi.format(16,0); // switch to 16 bit Mode 0 + + for (i = 0; i < pixels; i++) + _spi.write(color); + + _spi.format(8,0); // switch back to 8 bit Mode 0 +#else + // 8 Bit SPI + msb = color >> 8; + lsb = color & 0xff; + for (i = 0; i < pixels; i++){ + _spi.write(msb); + _spi.write(lsb); + } +#endif + + _cs = 1; +} + + +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; +} + + + +int SPI_TFT_ILI9341::columns() +{ + return width() / _font[1]; +} + + + +int SPI_TFT_ILI9341::rows() +{ + return height() / _font[2]; +} + + + +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; + } + } else { + character(_char_x, _char_y, value); + } + return value; +} + +//WH +#if(0) +void SPI_TFT_ILI9341::character(int x, int y, int c) +{ + unsigned int hor,vert,offset,bpl,j,i,b; + unsigned char* zeichen; + 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() - _font[2]) { + _char_y = 0; + } + } + window(_char_x, _char_y,hor,vert); // char box + wr_cmd(0x2C); // send pixel + #ifndef TARGET_KL25Z // 16 Bit SPI + _spi.format(16,0); + #endif // switch to 16 bit Mode 0 + 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) { + #ifndef TARGET_KL25Z // 16 Bit SPI + _spi.write(_background); + #else + _spi.write(_background >> 8); + _spi.write(_background & 0xff); + #endif + } else { + #ifndef TARGET_KL25Z // 16 Bit SPI + _spi.write(_foreground); + #else + _spi.write(_foreground >> 8); + _spi.write(_foreground & 0xff); + #endif + } + } + } + _cs = 1; + #ifndef TARGET_KL25Z // 16 Bit SPI + _spi.format(8,0); + #endif + window_max(); + if ((w + 2) < hor) { // x offset to next char + __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; + 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; + } + } + + 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 + + #if (SPI_16 == 1) + // 16 Bit SPI + _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 (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 (SPI_16 == 1) + // 16 Bit SPI + _spi.write(_background); + #else + // 8 Bit SPI + _spi.write(_background >> 8); + _spi.write(_background & 0xff); + #endif + } + else { + // bit is 1, write _foreground color + #if (SPI_16 == 1) + // 16 Bit SPI + _spi.write(_foreground); + #else + // 8 Bit SPI + _spi.write(_foreground >> 8); + _spi.write(_foreground & 0xff); + #endif + } // if bit + } // for i + } // for j + + _cs = 1; + #if (SPI_16 == 1) // 16 Bit SPI + _spi.format(8,0); // switch back to 8 bit Mode 0 + #endif + window_max(); + + if ((w + 2) < hor) { // x offset to next char + _char_x += w + 2; + } else _char_x += hor; +} +#endif + +#endif + + +void SPI_TFT_ILI9341::set_font(unsigned char* f) +{ + _font = f; +} + + + +void SPI_TFT_ILI9341::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; + #if (SPI_16 != 1) // 16 Bit SPI + unsigned short pix_temp; + #endif + + unsigned int i; + + // the lines are padded to multiple of 4 bytes in a bitmap + padd = -1; + do { + padd ++; + } while (2*(w + padd)%4 != 0); + window(x, y, w, h); + bitmap_ptr += ((h - 1)* (w + padd)); +// wr_cmd(0x2C); // send pixel + wr_cmd(ILI9341_GRAM); // send pixel + + #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 (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++; + #endif + } + bitmap_ptr -= 2*w; + bitmap_ptr -= padd; + } + _cs = 1; + + #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 an SD card + +int SPI_TFT_ILI9341::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP) +{ + +#define OffsetPixelWidth 18 +#define OffsetPixelHeigh 22 +#define OffsetFileSize 34 +#define OffsetPixData 10 +#define OffsetBPP 28 + + char filename[50]; + unsigned char BMP_Header[54]; + unsigned short BPP_t; + unsigned int PixelWidth,PixelHeigh,start_data; + unsigned int i,off; + int padd,j; + unsigned short *line; + + // get the filename + i=0; + while (*Name_BMP!='\0') { + filename[i++]=*Name_BMP++; + } + filename[i] = 0; + + FILE *Image = fopen((const char *)&filename[0], "rb"); // open the bmp file + if (!Image) { + return(0); // error file not found ! + } + + fread(&BMP_Header[0],1,54,Image); // get the BMP Header + + if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) { // check magic byte + fclose(Image); + return(-1); // error no BMP file + } + + BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8); + if (BPP_t != 0x0010) { + fclose(Image); + return(-2); // error no 16 bit BMP + } + + PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24); + PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24); + if (PixelHeigh > height() + y || PixelWidth > width() + x) { + fclose(Image); + return(-3); // to big + } + + 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 + } + + // the bmp lines are padded to multiple of 4 bytes + padd = -1; + do { + padd ++; + } while ((PixelWidth * 2 + padd)%4 != 0); + + window(x, y,PixelWidth ,PixelHeigh); +// wr_cmd(0x2C); // send pixel + wr_cmd(ILI9341_GRAM); // send pixel + + #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 + #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; + + #if (SPI_16 == 1) + _spi.format(8,0); // switch back to 8 bit Mode 0 + #endif + + free (line); + fclose(Image); + window_max(); + return(1); +} + + +/******************************************************************************* +* Function Name : WriteBMP_FAT +* @brief Displays a bitmap picture loaded in Flash. +* @param Xpos: specifies the X position. +* @param Ypos: specifies the Y position. +* @param BmpAddress: Bmp picture address in Flash. +* @return None +*******************************************************************************/ +void SPI_TFT_ILI9341::WriteBMP_FAT(uint16_t Xpos, uint16_t Ypos, const char* BmpName) +{ + uint32_t index = 0, size = 0, width=0, height=0; + uint16_t *pBmpWord=0; +// uint16_t data; + + /* Read bitmap width*/ + width = BmpName[0]+1; + /* Read bitmap height*/ + height = BmpName[1]+1; + /* Read bitmap size */ + size = width * height; /* nb of 16 bits */ + + window(Xpos, Ypos, width , height); + +// wr_cmd(0x2C); // send pixel + wr_cmd(ILI9341_GRAM); // send pixel + + /* Set WRX to send data */ +//WH _dc = 1; + + #if (SPI_16 == 1) + _spi.format(16,0); // switch to 16 bit Mode 0 + #endif + + pBmpWord = (uint16_t *) (&BmpName[5]); + /* Send to the screen */ + for(index = 0; index < size; index++) + { + #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(); +} + +