I simplified the library "ILI9225_TFT" provided by Arman Safikhani to better suit my needs in implementing a simple sliding puzzle game.
Diff: ILI9225.cpp
- Revision:
- 3:251e4d020501
diff -r cc93245bb6d0 -r 251e4d020501 ILI9225.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ILI9225.cpp Fri Apr 27 07:33:56 2018 +0000 @@ -0,0 +1,535 @@ +#include "ILI9225.h" +#define bitRead(value, bit) (((value) >> (bit)) & 0x01) + +int font_color, x_font, y_font; + +//Global Variables +int x_text = 0, y_text = 0; +int x_base = 0; + +//Constructor when using software SPI. All output pins are configurable. +ILI9225::ILI9225(PinName rst, PinName rs, PinName cs, + PinName sdi, PinName clk, PinName led) : + _rst(rst), _rs(rs), _cs(cs), _sdi(sdi), _clk(clk), spi(sdi, NC, clk), + _led(led), _rstInOut(_rst), _rsInOut(_rs), _csInOut(_cs), _ledInOut(_led), + hwSPI(true) +{} + +void ILI9225::_orientCoordinates(uint16_t &x1, uint16_t &y1) { + switch (_orientation) { + case 0: + break; + case 1: + y1 = _maxY - y1 - 1; + _swap(x1, y1); + break; + case 2: + x1 = _maxX - x1 - 1; + y1 = _maxY - y1 - 1; + break; + case 3: + x1 = _maxX - x1 - 1; + _swap(x1, y1); + break; + } +} + +void ILI9225::_setWindow(uint16_t x0, uint16_t y0, uint16_t x1, + uint16_t y1) { + _orientCoordinates(x0, y0); + _orientCoordinates(x1, y1); + + if (x1 < x0) + _swap(x0, x1); + if (y1 < y0) + _swap(y0, y1); + + _writeRegister(ILI9225_HORIZONTAL_WINDOW_ADDR1, x1); + _writeRegister(ILI9225_HORIZONTAL_WINDOW_ADDR2, x0); + + _writeRegister(ILI9225_VERTICAL_WINDOW_ADDR1, y1); + _writeRegister(ILI9225_VERTICAL_WINDOW_ADDR2, y0); + + _writeRegister(ILI9225_RAM_ADDR_SET1, x0); + _writeRegister(ILI9225_RAM_ADDR_SET2, y0); + + _writeCommand(0x00, 0x22); +} + +void ILI9225::begin() { + //Set up pins + _rsInOut.output(); + _csInOut.output(); + _rstInOut.output(); + + if (_led) + _ledInOut.output(); + if (hwSPI) { //Using hardware SPI + spi.frequency(16000000); + spi.format(8, 0); + } + else { + DigitalInOut _clkInOut(_clk); + _clkInOut.output(); + DigitalInOut _sdiInOut(_sdi); + _sdiInOut.output(); + } + + //Turn on backlight + if (_led) + _ledInOut = 1; + + //Initialization Code + _rstInOut = 1; //Put reset pin high to release ILI9225C from reset status + wait_ms(1); + _rstInOut = 0; //Put reset pin low to reset ILI9225 + wait_ms(10); + _rstInOut = 1; //Put reset pin high to release ILI9225C from reset status + wait_ms(50); + + //Start Initial Sequence + //Set SS bit and direction output from S528 to S1 + _writeRegister(ILI9225_POWER_CTRL1, 0x0000); //Set SAP,DSTB,STB + _writeRegister(ILI9225_POWER_CTRL2, 0x0000); //Set APON,PON,AON,VCI1EN,VC + _writeRegister(ILI9225_POWER_CTRL3, 0x0000); //Set BT,DC1,DC2,DC3 + _writeRegister(ILI9225_POWER_CTRL4, 0x0000); //Set GVDD + _writeRegister(ILI9225_POWER_CTRL5, 0x0000); //Set VCOMH/VCOML voltage + wait_ms(40); + + //Power-on sequence + _writeRegister(ILI9225_POWER_CTRL2, 0x0018); //Set APON,PON,AON,VCI1EN,VC + _writeRegister(ILI9225_POWER_CTRL3, 0x6121); //Set BT,DC1,DC2,DC3 + _writeRegister(ILI9225_POWER_CTRL4, 0x006F); //Set GVDD /*007F 0088 */ + _writeRegister(ILI9225_POWER_CTRL5, 0x495F); //Set VCOMH/VCOML voltage + _writeRegister(ILI9225_POWER_CTRL1, 0x0800); //Set SAP,DSTB,STB + wait_ms(10); + _writeRegister(ILI9225_POWER_CTRL2, 0x103B); //Set APON,PON,AON,VCI1EN,VC + wait_ms(50); + + //Set disp line # & disp dir + _writeRegister(ILI9225_DRIVER_OUTPUT_CTRL, 0x011C); + _writeRegister(ILI9225_LCD_AC_DRIVING_CTRL, 0x0100); //Set 1 line inversion + _writeRegister(ILI9225_ENTRY_MODE, 0x1030); //Set GRAM write dir & BGR=1. + _writeRegister(ILI9225_DISP_CTRL1, 0x0000); //Display off + _writeRegister(ILI9225_BLANK_PERIOD_CTRL1, 0x0808); //Set back & front porch + _writeRegister(ILI9225_FRAME_CYCLE_CTRL, 0x1100); //Set clocks # per line + _writeRegister(ILI9225_INTERFACE_CTRL, 0x0000); //CPU interface + _writeRegister(ILI9225_OSC_CTRL, 0x0D01); //Set Osc /*0e01*/ + _writeRegister(ILI9225_VCI_RECYCLING, 0x0020); //Set VCI recycling + _writeRegister(ILI9225_RAM_ADDR_SET1, 0x0000); //RAM Address + _writeRegister(ILI9225_RAM_ADDR_SET2, 0x0000); //RAM Address + + //Set GRAM area + _writeRegister(ILI9225_GATE_SCAN_CTRL, 0x0000); + _writeRegister(ILI9225_VERTICAL_SCROLL_CTRL1, 0x00DB); + _writeRegister(ILI9225_VERTICAL_SCROLL_CTRL2, 0x0000); + _writeRegister(ILI9225_VERTICAL_SCROLL_CTRL3, 0x0000); + _writeRegister(ILI9225_PARTIAL_DRIVING_POS1, 0x00DB); + _writeRegister(ILI9225_PARTIAL_DRIVING_POS2, 0x0000); + _writeRegister(ILI9225_HORIZONTAL_WINDOW_ADDR1, 0x00AF); + _writeRegister(ILI9225_HORIZONTAL_WINDOW_ADDR2, 0x0000); + _writeRegister(ILI9225_VERTICAL_WINDOW_ADDR1, 0x00DB); + _writeRegister(ILI9225_VERTICAL_WINDOW_ADDR2, 0x0000); + + //Set GAMMA curve + _writeRegister(ILI9225_GAMMA_CTRL1, 0x0000); + _writeRegister(ILI9225_GAMMA_CTRL2, 0x0808); + _writeRegister(ILI9225_GAMMA_CTRL3, 0x080A); + _writeRegister(ILI9225_GAMMA_CTRL4, 0x000A); + _writeRegister(ILI9225_GAMMA_CTRL5, 0x0A08); + _writeRegister(ILI9225_GAMMA_CTRL6, 0x0808); + _writeRegister(ILI9225_GAMMA_CTRL7, 0x0000); + _writeRegister(ILI9225_GAMMA_CTRL8, 0x0A00); + _writeRegister(ILI9225_GAMMA_CTRL9, 0x0710); + _writeRegister(ILI9225_GAMMA_CTRL10, 0x0710); + + _writeRegister(ILI9225_DISP_CTRL1, 0x0012); + wait_ms(50); + _writeRegister(ILI9225_DISP_CTRL1, 0x1017); + + setBacklight(true); + setOrientation(0); + + //Initialize variables + setBackgroundColor(COLOR_BLACK); + + clear(); +} + +void ILI9225::clear() { + uint8_t old = _orientation; + setOrientation(0); + fillRectangle(0, 0, _maxX - 1, _maxY - 1, COLOR_BLACK); + setOrientation(old); + wait_ms(10); +} + +void ILI9225::fill(uint16_t color) { + fillRectangle(0, 0, _maxX - 1, _maxY - 1, color); +} + +void ILI9225::invert(bool flag) { + _writeCommand(0x00, flag ? ILI9225C_INVON : ILI9225C_INVOFF); +} + +void ILI9225::setBacklight(bool flag) { + if (_led) _ledInOut = flag ? 1 : 0; +} + +void ILI9225::setDisplay(bool flag) { + if (flag) { + _writeRegister(0x00ff, 0x0000); + _writeRegister(ILI9225_POWER_CTRL1, 0x0000); + wait_ms(50); + _writeRegister(ILI9225_DISP_CTRL1, 0x1017); + wait_ms(200); + } + else { + _writeRegister(0x00ff, 0x0000); + _writeRegister(ILI9225_DISP_CTRL1, 0x0000); + wait_ms(50); + _writeRegister(ILI9225_POWER_CTRL1, 0x0003); + wait_ms(200); + } +} + +void ILI9225::setOrientation(uint8_t orientation) { + _orientation = orientation % 4; + + switch (_orientation) { + case 0: + _maxX = ILI9225_LCD_WIDTH; + _maxY = ILI9225_LCD_HEIGHT; + break; + case 1: + _maxX = ILI9225_LCD_HEIGHT; + _maxY = ILI9225_LCD_WIDTH; + break; + case 2: + _maxX = ILI9225_LCD_WIDTH; + _maxY = ILI9225_LCD_HEIGHT; + break; + case 3: + _maxX = ILI9225_LCD_HEIGHT; + _maxY = ILI9225_LCD_WIDTH; + break; + } +} + +void ILI9225::drawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, + uint16_t y2, uint16_t color) { + drawLine(x1, y1, x1, y2, color); + drawLine(x1, y1, x2, y1, color); + drawLine(x1, y2, x2, y2, color); + drawLine(x2, y1, x2, y2, color); +} + +void ILI9225::fillRectangle(uint16_t x1, uint16_t y1, uint16_t x2, + uint16_t y2, uint16_t color) { + _setWindow(x1, y1, x2, y2); + + for (uint16_t t = (y2 - y1 + 1) * (x2 - x1 + 1); t > 0; t--) + _writeData(color >> 8, color); +} + +void ILI9225::drawLine(uint16_t x1, uint16_t y1, uint16_t x2, + uint16_t y2, uint16_t color) { + //Bresenham algorithm + int16_t steep = abs(y2 - y1) > abs(x2 - x1); + int16_t dx, dy; + + if (steep) { + _swap(x1, y1); + _swap(x2, y2); + } + + if (x1 > x2) { + _swap(x1, x2); + _swap(y1, y2); + } + + dx = x2 - x1; + dy = abs(y2 - y1); + + int16_t err = dx / 2; + int16_t ystep; + + if (y1 < y2) + ystep = 1; + else + ystep = -1; + + for (; x1 <= x2; x1++) { + if(steep) + drawPixel(y1, x1, color); + else + drawPixel(x1, y1, color); + + err -= dy; + if (err < 0) { + y1 += ystep; + err += dx; + } + } +} + +void ILI9225::drawPixel(uint16_t x1, uint16_t y1, uint16_t color) { + if ((x1 >= _maxX) || (y1 >= _maxY)) + return; + + _setWindow(x1, y1, x1 + 1, y1 + 1); + _orientCoordinates(x1, y1); + _writeData(color >> 8, color); +} + +uint16_t ILI9225::maxX() { + return _maxX; +} + +uint16_t ILI9225::maxY() { + return _maxY; +} + +uint16_t ILI9225::setColor(uint8_t red8, uint8_t green8, uint8_t blue8) { + //RGB16 = red5 green6 blue5 + return (red8 >> 3) << 11 | (green8 >> 2) << 5 | (blue8 >> 3); +} + +void ILI9225::splitColor(uint16_t rgb, uint8_t &red, uint8_t &green, + uint8_t &blue) { + //RGB16 = red5 green6 blue5 + red = (rgb & 0xF800) >> 11 << 3; + green = (rgb & 0x7E0) >> 5 << 2; + blue = (rgb & 0x1F) << 3; +} + +void ILI9225::_swap(uint16_t &a, uint16_t &b) { + uint16_t w = a; + a = b; + b = w; +} + +//Utilities +void ILI9225::_writeCommand(uint8_t HI, uint8_t LO) { + _rsInOut = 0; + _csInOut = 0; + spi.write(HI); + spi.write(LO); + _csInOut = 1; +} + +void ILI9225::_writeData(uint8_t HI, uint8_t LO) { + _rsInOut = 1; + _csInOut = 0; + spi.write(HI); + spi.write(LO); + _csInOut = 1; +} + +void ILI9225::_writeRegister(uint16_t reg, uint16_t data) { + _writeCommand(reg >> 8, reg & 255); + _writeData(data >> 8, data & 255); +} + +void ILI9225::setBackgroundColor(uint16_t color) { + _bgColor = color; +} + +void ILI9225::setFont(const uint8_t* font) { + cfont.font = font; + cfont.width = font[0]; + cfont.height = font[1]; + cfont.offset = font[2]; + cfont.numchars = font[3]; + cfont.nbrows = cfont.height / 8; + + if (cfont.height % 8) + cfont.nbrows++; //Set # of bytes used by font height in multiples of 8. +} + +void ILI9225::drawText(uint16_t x, uint16_t y, char *s, uint16_t color) { + uint16_t currx = x; + + //Print every character in string + for (uint8_t k = 0; k < strlen(s); k++) + currx += drawChar(currx, y, s[k], color) + 1; +} + +uint16_t ILI9225::drawChar(uint16_t x, uint16_t y, uint16_t ch, + uint16_t color) { + uint8_t charData, charWidth; + uint8_t h, i, j; + uint16_t charOffset; + + //Bytes used by each character + charOffset = (cfont.width * cfont.nbrows) + 1; + //Char offset (add 4 for font header) + charOffset = (charOffset * (ch - cfont.offset)) + FONT_HEADER_SIZE; + //Get font width from 1st byte + charWidth = cfont.font[charOffset]; + //Increment pointer to first character data byte + charOffset++; + + //Loop through each font "column" (+1 blank column for spacing) + for (i = 0; i <= charWidth; i++) { + h = 0; //Keep track of char height + for (j = 0; j < cfont.nbrows; j++) { //Each column byte + if (i == charWidth) + charData = (uint8_t)0x0; //Insert blank column + else + charData = cfont.font[charOffset]; + charOffset++; + + //Process every row in font character + for (uint8_t k = 0; k < 8; k++) { + if (h >= cfont.height) + break; //No need to process excess bits + if (bitRead(charData, k)) + drawPixel(x + i, y + (j * 8) + k, color); + else + drawPixel(x + i, y + (j * 8) + k, _bgColor); + h++; + } + } + } + return charWidth; +} + +//------------------------------------------------------------------------------ +//************************************* ECA 2.8 inch LCD Module **************** +//------------------------------------------------------------------------------ +//Description : Draws a beveled figure on the screen. +//Input : x0, y0 - coordinate position of the upper left center +// : x1, y1 - coordinate position of the lower right center +// : rad - defines the redius of the circle, +// : fill - fill yes or no +//------------------------------------------------------------------------------ +void ILI9225::roundRectangle(int x0, int y0, int x1, int y1, int rad, + bool fill, int color) { + signed int a, b, P; + + a = 0; //Increment by 1 + b = rad; //Decrement by 1 using P + P = 1 - rad; + if (fill) { + fillRectangle(x0, y0 + rad, x1, y1 - rad, color); + + do { + fillRectangle(x0 - a + rad, y0 - b + rad, a + x1 - rad, + y0 - b + rad, color); //8 --> 1 + fillRectangle(x0 - b + rad, y0 - a + rad, b + x1 - rad, + y0 - a + rad, color); //7 --> 2 + fillRectangle(x0 - b + rad, a + y1 - rad, b + x1 - rad, + a + y1 - rad, color); //6 --> 3 + fillRectangle(x0 - a + rad, b + y1 - rad, a + x1 - rad, + b + y1 - rad, color); //5 --> 4 + + if (P < 0) + P += 3 + 2 * a++; + else + P += 5 + 2 * (a++ - b--); + + } while (a <= b); + } //Fill + else { + fillRectangle(x0 + rad, y0, x1 - rad, y0, color); //Top + fillRectangle(x0 + rad, y1, x1 - rad, y1, color); //Bottom + fillRectangle(x0, y0 + rad, x0, y1 - rad, color); //Left + fillRectangle(x1, y0 + rad, x1, y1 - rad, color); //Right + + do { + drawPixel(a + x1 - rad, y0 - b + rad, color); // `````` Segment 1 + drawPixel(b + x1 - rad, y0 - a + rad, color); // `````` Segment 2 + + drawPixel(b + x1 - rad, a + y1 - rad, color); // `````` Segment 3 + drawPixel(a + x1 - rad, b + y1 - rad, color); // `````` Segment 4 + + drawPixel(x0 - a + rad, b + y1 - rad, color); // `````` Segment 5 + drawPixel(x0 - b + rad, a + y1 - rad, color); // `````` Segment 6 + + drawPixel(x0 - b + rad, y0 - a + rad, color); // `````` Segment 7 + drawPixel(x0 - a + rad, y0 - b + rad, color); // `````` Segment 8 + + if (P < 0) + P += 3 + 2 * a++; + else + P += 5 + 2 * (a++ - b--); + } while (a <= b); + } //No fill +} //RoundRectangle + +//------------------------------------------------------------------------------ +//************************************* ECA 2.8 inch LCD Module **************** +//------------------------------------------------------------------------------ +//Go to a specific pont for farsi font (x:0..TS_SIZE_X , y:0..TS_SIZE_Y) +//------------------------------------------------------------------------------ +void ILI9225::goToXY(int x, int y) { + if ((x >= _maxX) || (x < 0)) { + x_font = 0; + x_base = 0; + } + else { + x_font = x; + x_base = x; + } + if ((y >= _maxY) || (y < 0)) + y_font = 0; + else + y_font = y; +} + +//------------------------------------------------------------------------------ +//************************************* ECA 2.8 inch LCD Module **************** +//------------------------------------------------------------------------------ +//Make an ascii string from an unicode string +//------------------------------------------------------------------------------ + +void ILI9225::unicode2ascii(char *uni_str, char *ascii_str) { + int counter = 0; + int Uch = 0; + char chl, chh; + + while (*uni_str) { + chl = *uni_str++; + chh = *uni_str++; + + Uch = 0; + Uch = ((Uch | chh) << 8) | chl; + + if (Uch > 1574 && Uch < 1591) + *(ascii_str + counter) = (char)(Uch - 1376); + else if (Uch > 1590 && Uch < 1595) + *(ascii_str + counter) = (char)(Uch - 1375); + else if (Uch > 1600 && Uch < 1603) + *(ascii_str + counter) = (char)(Uch - 1380); + else if (Uch == 1705) + *(ascii_str + counter) = (char)(Uch - 1482); + else if (Uch == 1604) + *(ascii_str + counter) = (char)(Uch - 1379); + else if (Uch > 1604 && Uch < 1609) + *(ascii_str + counter) = (char)(Uch - 1378); + else if (Uch == 1740) + *(ascii_str + counter) = (char)(Uch - 1503); + else if (Uch == 1574) + *(ascii_str + counter) = (char)(Uch - 1381); + else if (Uch == 1662) + *(ascii_str + counter) = (char)(Uch - 1533); + else if (Uch == 1670) + *(ascii_str + counter) = (char)(Uch - 1529); + else if (Uch == 1688) + *(ascii_str + counter) = (char)(Uch - 1546); + else if (Uch == 1711) + *(ascii_str + counter) = (char)(Uch - 1567); + else if (Uch == 1570) + *(ascii_str + counter) = (char)(Uch - 1376); + else if (Uch > 1631 && Uch < 1642) + *(ascii_str + counter) = (char)(Uch - 1584); + else if (Uch == 65536) + *(ascii_str + counter) = NULL; + else + *(ascii_str + counter) = (char)Uch; + + counter++; + } + *(ascii_str + counter) = NULL; +} \ No newline at end of file