I simplified the library "ILI9225_TFT" provided by Arman Safikhani to better suit my needs in implementing a simple sliding puzzle game.

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ILI9225.cpp Source File

ILI9225.cpp

00001 #include "ILI9225.h"
00002 #define bitRead(value, bit) (((value) >> (bit)) & 0x01)
00003 
00004 int font_color, x_font, y_font;
00005 
00006 //Global Variables
00007 int x_text = 0, y_text = 0;
00008 int x_base = 0;
00009 
00010 //Constructor when using software SPI.  All output pins are configurable.
00011 ILI9225::ILI9225(PinName rst, PinName rs, PinName cs,
00012     PinName sdi, PinName clk, PinName led) :
00013     _rst(rst), _rs(rs), _cs(cs), _sdi(sdi), _clk(clk), spi(sdi, NC, clk),
00014     _led(led), _rstInOut(_rst), _rsInOut(_rs), _csInOut(_cs), _ledInOut(_led),
00015     hwSPI(true)
00016 {}
00017 
00018 void ILI9225::_orientCoordinates(uint16_t &x1, uint16_t &y1) {
00019     switch (_orientation) {
00020     case 0:
00021         break;
00022     case 1:
00023         y1 = _maxY - y1 - 1;
00024         _swap(x1, y1);
00025         break;
00026     case 2:
00027         x1 = _maxX - x1 - 1;
00028         y1 = _maxY - y1 - 1;
00029         break;
00030     case 3:
00031         x1 = _maxX - x1 - 1;
00032         _swap(x1, y1);
00033         break;
00034     }
00035 }
00036 
00037 void ILI9225::_setWindow(uint16_t x0, uint16_t y0, uint16_t x1,
00038     uint16_t y1) {
00039     _orientCoordinates(x0, y0);
00040     _orientCoordinates(x1, y1);
00041 
00042     if (x1 < x0)
00043         _swap(x0, x1);
00044     if (y1 < y0)
00045         _swap(y0, y1);
00046 
00047     _writeRegister(ILI9225_HORIZONTAL_WINDOW_ADDR1, x1);
00048     _writeRegister(ILI9225_HORIZONTAL_WINDOW_ADDR2, x0);
00049 
00050     _writeRegister(ILI9225_VERTICAL_WINDOW_ADDR1, y1);
00051     _writeRegister(ILI9225_VERTICAL_WINDOW_ADDR2, y0);
00052 
00053     _writeRegister(ILI9225_RAM_ADDR_SET1, x0);
00054     _writeRegister(ILI9225_RAM_ADDR_SET2, y0);
00055 
00056     _writeCommand(0x00, 0x22);
00057 }
00058 
00059 void ILI9225::begin() {
00060     //Set up pins
00061     _rsInOut.output();
00062     _csInOut.output();
00063     _rstInOut.output();
00064 
00065     if (_led)
00066         _ledInOut.output();
00067     if (hwSPI) { //Using hardware SPI
00068         spi.frequency(16000000);
00069         spi.format(8, 0);
00070     }
00071     else {
00072         DigitalInOut _clkInOut(_clk);
00073         _clkInOut.output();
00074         DigitalInOut _sdiInOut(_sdi);
00075         _sdiInOut.output();
00076     }
00077 
00078     //Turn on backlight
00079     if (_led)
00080         _ledInOut = 1;
00081 
00082     //Initialization Code
00083     _rstInOut = 1; //Put reset pin high to release ILI9225C from reset status
00084     wait_ms(1);
00085     _rstInOut = 0; //Put reset pin low to reset ILI9225
00086     wait_ms(10);
00087     _rstInOut = 1; //Put reset pin high to release ILI9225C from reset status
00088     wait_ms(50);
00089 
00090     //Start Initial Sequence
00091     //Set SS bit and direction output from S528 to S1
00092     _writeRegister(ILI9225_POWER_CTRL1, 0x0000); //Set SAP,DSTB,STB
00093     _writeRegister(ILI9225_POWER_CTRL2, 0x0000); //Set APON,PON,AON,VCI1EN,VC
00094     _writeRegister(ILI9225_POWER_CTRL3, 0x0000); //Set BT,DC1,DC2,DC3
00095     _writeRegister(ILI9225_POWER_CTRL4, 0x0000); //Set GVDD
00096     _writeRegister(ILI9225_POWER_CTRL5, 0x0000); //Set VCOMH/VCOML voltage
00097     wait_ms(40);
00098 
00099     //Power-on sequence
00100     _writeRegister(ILI9225_POWER_CTRL2, 0x0018); //Set APON,PON,AON,VCI1EN,VC
00101     _writeRegister(ILI9225_POWER_CTRL3, 0x6121); //Set BT,DC1,DC2,DC3
00102     _writeRegister(ILI9225_POWER_CTRL4, 0x006F); //Set GVDD   /*007F 0088 */
00103     _writeRegister(ILI9225_POWER_CTRL5, 0x495F); //Set VCOMH/VCOML voltage
00104     _writeRegister(ILI9225_POWER_CTRL1, 0x0800); //Set SAP,DSTB,STB
00105     wait_ms(10);
00106     _writeRegister(ILI9225_POWER_CTRL2, 0x103B); //Set APON,PON,AON,VCI1EN,VC
00107     wait_ms(50);
00108 
00109     //Set disp line # & disp dir
00110     _writeRegister(ILI9225_DRIVER_OUTPUT_CTRL, 0x011C);
00111     _writeRegister(ILI9225_LCD_AC_DRIVING_CTRL, 0x0100); //Set 1 line inversion
00112     _writeRegister(ILI9225_ENTRY_MODE, 0x1030); //Set GRAM write dir & BGR=1.
00113     _writeRegister(ILI9225_DISP_CTRL1, 0x0000); //Display off
00114     _writeRegister(ILI9225_BLANK_PERIOD_CTRL1, 0x0808); //Set back & front porch
00115     _writeRegister(ILI9225_FRAME_CYCLE_CTRL, 0x1100); //Set clocks # per line
00116     _writeRegister(ILI9225_INTERFACE_CTRL, 0x0000); //CPU interface
00117     _writeRegister(ILI9225_OSC_CTRL, 0x0D01); //Set Osc  /*0e01*/
00118     _writeRegister(ILI9225_VCI_RECYCLING, 0x0020); //Set VCI recycling
00119     _writeRegister(ILI9225_RAM_ADDR_SET1, 0x0000); //RAM Address
00120     _writeRegister(ILI9225_RAM_ADDR_SET2, 0x0000); //RAM Address
00121 
00122     //Set GRAM area
00123     _writeRegister(ILI9225_GATE_SCAN_CTRL, 0x0000);
00124     _writeRegister(ILI9225_VERTICAL_SCROLL_CTRL1, 0x00DB);
00125     _writeRegister(ILI9225_VERTICAL_SCROLL_CTRL2, 0x0000);
00126     _writeRegister(ILI9225_VERTICAL_SCROLL_CTRL3, 0x0000);
00127     _writeRegister(ILI9225_PARTIAL_DRIVING_POS1, 0x00DB);
00128     _writeRegister(ILI9225_PARTIAL_DRIVING_POS2, 0x0000);
00129     _writeRegister(ILI9225_HORIZONTAL_WINDOW_ADDR1, 0x00AF);
00130     _writeRegister(ILI9225_HORIZONTAL_WINDOW_ADDR2, 0x0000);
00131     _writeRegister(ILI9225_VERTICAL_WINDOW_ADDR1, 0x00DB);
00132     _writeRegister(ILI9225_VERTICAL_WINDOW_ADDR2, 0x0000);
00133 
00134     //Set GAMMA curve
00135     _writeRegister(ILI9225_GAMMA_CTRL1, 0x0000);
00136     _writeRegister(ILI9225_GAMMA_CTRL2, 0x0808);
00137     _writeRegister(ILI9225_GAMMA_CTRL3, 0x080A);
00138     _writeRegister(ILI9225_GAMMA_CTRL4, 0x000A);
00139     _writeRegister(ILI9225_GAMMA_CTRL5, 0x0A08);
00140     _writeRegister(ILI9225_GAMMA_CTRL6, 0x0808);
00141     _writeRegister(ILI9225_GAMMA_CTRL7, 0x0000);
00142     _writeRegister(ILI9225_GAMMA_CTRL8, 0x0A00);
00143     _writeRegister(ILI9225_GAMMA_CTRL9, 0x0710);
00144     _writeRegister(ILI9225_GAMMA_CTRL10, 0x0710);
00145 
00146     _writeRegister(ILI9225_DISP_CTRL1, 0x0012);
00147     wait_ms(50);
00148     _writeRegister(ILI9225_DISP_CTRL1, 0x1017);
00149 
00150     setBacklight(true);
00151     setOrientation(0);
00152 
00153     //Initialize variables
00154     setBackgroundColor(COLOR_BLACK);
00155 
00156     clear();
00157 }
00158 
00159 void ILI9225::clear() {
00160     uint8_t old = _orientation;
00161     setOrientation(0);
00162     fillRectangle(0, 0, _maxX - 1, _maxY - 1, COLOR_BLACK);
00163     setOrientation(old);
00164     wait_ms(10);
00165 }
00166 
00167 void ILI9225::fill(uint16_t color) {
00168     fillRectangle(0, 0, _maxX - 1, _maxY - 1, color);
00169 }
00170 
00171 void ILI9225::invert(bool flag) {
00172     _writeCommand(0x00, flag ? ILI9225C_INVON : ILI9225C_INVOFF);
00173 }
00174 
00175 void ILI9225::setBacklight(bool flag) {
00176     if (_led) _ledInOut = flag ? 1 : 0;
00177 }
00178 
00179 void ILI9225::setDisplay(bool flag) {
00180     if (flag) {
00181         _writeRegister(0x00ff, 0x0000);
00182         _writeRegister(ILI9225_POWER_CTRL1, 0x0000);
00183         wait_ms(50);
00184         _writeRegister(ILI9225_DISP_CTRL1, 0x1017);
00185         wait_ms(200);
00186     }
00187     else {
00188         _writeRegister(0x00ff, 0x0000);
00189         _writeRegister(ILI9225_DISP_CTRL1, 0x0000);
00190         wait_ms(50);
00191         _writeRegister(ILI9225_POWER_CTRL1, 0x0003);
00192         wait_ms(200);
00193     }
00194 }
00195 
00196 void ILI9225::setOrientation(uint8_t orientation) {
00197     _orientation = orientation % 4;
00198 
00199     switch (_orientation) {
00200     case 0:
00201         _maxX = ILI9225_LCD_WIDTH;
00202         _maxY = ILI9225_LCD_HEIGHT;
00203         break;
00204     case 1:
00205         _maxX = ILI9225_LCD_HEIGHT;
00206         _maxY = ILI9225_LCD_WIDTH;
00207         break;
00208     case 2:
00209         _maxX = ILI9225_LCD_WIDTH;
00210         _maxY = ILI9225_LCD_HEIGHT;
00211         break;
00212     case 3:
00213         _maxX = ILI9225_LCD_HEIGHT;
00214         _maxY = ILI9225_LCD_WIDTH;
00215         break;
00216     }
00217 }
00218 
00219 void ILI9225::drawRectangle(uint16_t x1, uint16_t y1, uint16_t x2,
00220     uint16_t y2, uint16_t color) {
00221     drawLine(x1, y1, x1, y2, color);
00222     drawLine(x1, y1, x2, y1, color);
00223     drawLine(x1, y2, x2, y2, color);
00224     drawLine(x2, y1, x2, y2, color);
00225 }
00226 
00227 void ILI9225::fillRectangle(uint16_t x1, uint16_t y1, uint16_t x2,
00228     uint16_t y2, uint16_t color) {
00229     _setWindow(x1, y1, x2, y2);
00230 
00231     for (uint16_t t = (y2 - y1 + 1) * (x2 - x1 + 1); t > 0; t--)
00232         _writeData(color >> 8, color);
00233 }
00234 
00235 void ILI9225::drawLine(uint16_t x1, uint16_t y1, uint16_t x2,
00236     uint16_t y2, uint16_t color) {
00237     //Bresenham algorithm
00238     int16_t steep = abs(y2 - y1) > abs(x2 - x1);
00239     int16_t dx, dy;
00240 
00241     if (steep) {
00242         _swap(x1, y1);
00243         _swap(x2, y2);
00244     }
00245 
00246     if (x1 > x2) {
00247         _swap(x1, x2);
00248         _swap(y1, y2);
00249     }
00250 
00251     dx = x2 - x1;
00252     dy = abs(y2 - y1);
00253 
00254     int16_t err = dx / 2;
00255     int16_t ystep;
00256 
00257     if (y1 < y2)
00258         ystep = 1;
00259     else   
00260         ystep = -1;
00261 
00262     for (; x1 <= x2; x1++) {
00263         if(steep)
00264             drawPixel(y1, x1, color);
00265         else
00266             drawPixel(x1, y1, color);
00267 
00268         err -= dy;
00269         if (err < 0) {
00270             y1 += ystep;
00271             err += dx;
00272         }
00273     }
00274 }
00275 
00276 void ILI9225::drawPixel(uint16_t x1, uint16_t y1, uint16_t color) {
00277     if ((x1 >= _maxX) || (y1 >= _maxY))
00278         return;
00279 
00280     _setWindow(x1, y1, x1 + 1, y1 + 1);
00281     _orientCoordinates(x1, y1);
00282     _writeData(color >> 8, color);
00283 }
00284 
00285 uint16_t ILI9225::maxX() {
00286     return _maxX;
00287 }
00288 
00289 uint16_t ILI9225::maxY() {
00290     return _maxY;
00291 }
00292 
00293 uint16_t ILI9225::setColor(uint8_t red8, uint8_t green8, uint8_t blue8) {
00294     //RGB16 = red5 green6 blue5
00295     return (red8 >> 3) << 11 | (green8 >> 2) << 5 | (blue8 >> 3);
00296 }
00297 
00298 void ILI9225::splitColor(uint16_t rgb, uint8_t &red, uint8_t &green,
00299     uint8_t &blue) {
00300     //RGB16 = red5 green6 blue5
00301     red = (rgb & 0xF800) >> 11 << 3;
00302     green = (rgb & 0x7E0) >> 5 << 2;
00303     blue = (rgb & 0x1F) << 3;
00304 }
00305 
00306 void ILI9225::_swap(uint16_t &a, uint16_t &b) {
00307     uint16_t w = a;
00308     a = b;
00309     b = w;
00310 }
00311 
00312 //Utilities
00313 void ILI9225::_writeCommand(uint8_t HI, uint8_t LO) {
00314     _rsInOut = 0;
00315     _csInOut = 0;
00316     spi.write(HI);
00317     spi.write(LO);
00318     _csInOut = 1;
00319 }
00320 
00321 void ILI9225::_writeData(uint8_t HI, uint8_t LO) {
00322     _rsInOut = 1;
00323     _csInOut = 0;
00324     spi.write(HI);
00325     spi.write(LO);
00326     _csInOut = 1;
00327 }
00328 
00329 void ILI9225::_writeRegister(uint16_t reg, uint16_t data) {
00330     _writeCommand(reg >> 8, reg & 255);
00331     _writeData(data >> 8, data & 255);
00332 }
00333 
00334 void ILI9225::setBackgroundColor(uint16_t color) {
00335     _bgColor = color;
00336 }
00337 
00338 void ILI9225::setFont(const uint8_t* font) {
00339     cfont.font = font;
00340     cfont.width = font[0];
00341     cfont.height = font[1];
00342     cfont.offset = font[2];
00343     cfont.numchars = font[3];
00344     cfont.nbrows = cfont.height / 8;
00345 
00346     if (cfont.height % 8)
00347         cfont.nbrows++; //Set # of bytes used by font height in multiples of 8.
00348 }
00349 
00350 void ILI9225::drawText(uint16_t x, uint16_t y, char *s, uint16_t color) {
00351     uint16_t currx = x;
00352 
00353     //Print every character in string
00354     for (uint8_t k = 0; k < strlen(s); k++)
00355         currx += drawChar(currx, y, s[k], color) + 1;
00356 }
00357 
00358 uint16_t ILI9225::drawChar(uint16_t x, uint16_t y, uint16_t ch,
00359     uint16_t color) {
00360     uint8_t charData, charWidth;
00361     uint8_t h, i, j;
00362     uint16_t charOffset;
00363 
00364     //Bytes used by each character
00365     charOffset = (cfont.width * cfont.nbrows) + 1;
00366     //Char offset (add 4 for font header)
00367     charOffset = (charOffset * (ch - cfont.offset)) + FONT_HEADER_SIZE;
00368     //Get font width from 1st byte
00369     charWidth = cfont.font[charOffset];
00370     //Increment pointer to first character data byte
00371     charOffset++;
00372 
00373     //Loop through each font "column" (+1 blank column for spacing)
00374     for (i = 0; i <= charWidth; i++) {
00375         h = 0;  //Keep track of char height
00376         for (j = 0; j < cfont.nbrows; j++) { //Each column byte
00377             if (i == charWidth)
00378                 charData = (uint8_t)0x0; //Insert blank column
00379             else
00380                 charData = cfont.font[charOffset];
00381             charOffset++;
00382 
00383             //Process every row in font character
00384             for (uint8_t k = 0; k < 8; k++) {
00385                 if (h >= cfont.height)
00386                     break;  //No need to process excess bits
00387                 if (bitRead(charData, k))
00388                     drawPixel(x + i, y + (j * 8) + k, color);
00389                 else
00390                     drawPixel(x + i, y + (j * 8) + k, _bgColor);
00391                 h++;
00392             }
00393         }
00394     }
00395     return charWidth;
00396 }
00397 
00398 //------------------------------------------------------------------------------
00399 //************************************* ECA 2.8 inch LCD Module ****************
00400 //------------------------------------------------------------------------------
00401 //Description  : Draws a beveled figure on the screen. 
00402 //Input        : x0, y0 - coordinate position of the upper left center
00403 //             : x1, y1 - coordinate position of the lower right center
00404 //             : rad    - defines the redius of the circle,
00405 //             : fill   - fill yes or no
00406 //------------------------------------------------------------------------------
00407 void ILI9225::roundRectangle(int x0, int y0, int x1, int y1, int rad,
00408     bool fill, int color) {
00409     signed int a, b, P;
00410 
00411     a = 0; //Increment by 1
00412     b = rad; //Decrement by 1 using P
00413     P = 1 - rad;
00414     if (fill) {
00415         fillRectangle(x0, y0 + rad, x1, y1 - rad, color);
00416 
00417         do {
00418             fillRectangle(x0 - a + rad, y0 - b + rad, a + x1 - rad,
00419                 y0 - b + rad, color); //8 --> 1
00420             fillRectangle(x0 - b + rad, y0 - a + rad, b + x1 - rad,
00421                 y0 - a + rad, color); //7 --> 2
00422             fillRectangle(x0 - b + rad, a + y1 - rad, b + x1 - rad,
00423                 a + y1 - rad, color); //6 --> 3
00424             fillRectangle(x0 - a + rad, b + y1 - rad, a + x1 - rad,
00425                 b + y1 - rad, color); //5 --> 4
00426 
00427             if (P < 0)
00428                 P += 3 + 2 * a++;
00429             else
00430                 P += 5 + 2 * (a++ - b--);
00431 
00432         } while (a <= b);
00433     } //Fill
00434     else {
00435         fillRectangle(x0 + rad, y0, x1 - rad, y0, color); //Top
00436         fillRectangle(x0 + rad, y1, x1 - rad, y1, color); //Bottom
00437         fillRectangle(x0, y0 + rad, x0, y1 - rad, color); //Left
00438         fillRectangle(x1, y0 + rad, x1, y1 - rad, color); //Right
00439 
00440         do {
00441             drawPixel(a + x1 - rad, y0 - b + rad, color); // `````` Segment 1
00442             drawPixel(b + x1 - rad, y0 - a + rad, color); // `````` Segment 2
00443 
00444             drawPixel(b + x1 - rad, a + y1 - rad, color); // `````` Segment 3
00445             drawPixel(a + x1 - rad, b + y1 - rad, color); // `````` Segment 4
00446 
00447             drawPixel(x0 - a + rad, b + y1 - rad, color); // `````` Segment 5
00448             drawPixel(x0 - b + rad, a + y1 - rad, color); // `````` Segment 6
00449 
00450             drawPixel(x0 - b + rad, y0 - a + rad, color); // `````` Segment 7
00451             drawPixel(x0 - a + rad, y0 - b + rad, color); // `````` Segment 8
00452 
00453             if (P < 0)
00454                 P += 3 + 2 * a++;
00455             else
00456                 P += 5 + 2 * (a++ - b--);
00457         } while (a <= b);
00458     } //No fill
00459 } //RoundRectangle
00460 
00461 //------------------------------------------------------------------------------
00462 //************************************* ECA 2.8 inch LCD Module ****************
00463 //------------------------------------------------------------------------------
00464 //Go to a specific pont for farsi font (x:0..TS_SIZE_X , y:0..TS_SIZE_Y)
00465 //------------------------------------------------------------------------------
00466 void ILI9225::goToXY(int x, int y) {
00467     if ((x >= _maxX) || (x < 0)) {
00468         x_font = 0;
00469         x_base = 0;
00470     }
00471     else {
00472         x_font = x;
00473         x_base = x;
00474     }
00475     if ((y >= _maxY) || (y < 0))
00476         y_font = 0;
00477     else
00478         y_font = y;
00479 }
00480 
00481 //------------------------------------------------------------------------------
00482 //************************************* ECA 2.8 inch LCD Module ****************
00483 //------------------------------------------------------------------------------
00484 //Make an ascii string from an unicode string 
00485 //------------------------------------------------------------------------------
00486 
00487 void ILI9225::unicode2ascii(char *uni_str, char *ascii_str) {
00488     int counter = 0;
00489     int Uch = 0;
00490     char chl, chh;
00491 
00492     while (*uni_str) {
00493         chl = *uni_str++;
00494         chh = *uni_str++;
00495 
00496         Uch = 0;
00497         Uch = ((Uch | chh) << 8) | chl;
00498 
00499         if (Uch > 1574 && Uch < 1591)
00500             *(ascii_str + counter) = (char)(Uch - 1376);
00501         else if (Uch > 1590 && Uch < 1595)
00502             *(ascii_str + counter) = (char)(Uch - 1375);
00503         else if (Uch > 1600 && Uch < 1603)
00504             *(ascii_str + counter) = (char)(Uch - 1380);
00505         else if (Uch == 1705)
00506             *(ascii_str + counter) = (char)(Uch - 1482);
00507         else if (Uch == 1604)
00508             *(ascii_str + counter) = (char)(Uch - 1379);
00509         else if (Uch > 1604 && Uch < 1609)
00510             *(ascii_str + counter) = (char)(Uch - 1378);
00511         else if (Uch == 1740)
00512             *(ascii_str + counter) = (char)(Uch - 1503);
00513         else if (Uch == 1574)
00514             *(ascii_str + counter) = (char)(Uch - 1381);
00515         else if (Uch == 1662)
00516             *(ascii_str + counter) = (char)(Uch - 1533);
00517         else if (Uch == 1670)
00518             *(ascii_str + counter) = (char)(Uch - 1529);
00519         else if (Uch == 1688)
00520             *(ascii_str + counter) = (char)(Uch - 1546);
00521         else if (Uch == 1711)
00522             *(ascii_str + counter) = (char)(Uch - 1567);
00523         else if (Uch == 1570)
00524             *(ascii_str + counter) = (char)(Uch - 1376);
00525         else if (Uch > 1631 && Uch < 1642)
00526             *(ascii_str + counter) = (char)(Uch - 1584);
00527         else if (Uch == 65536)
00528             *(ascii_str + counter) = NULL;
00529         else
00530             *(ascii_str + counter) = (char)Uch;
00531 
00532         counter++;
00533     }
00534     *(ascii_str + counter) = NULL;
00535 }