I simplified the library "ILI9225_TFT" provided by Arman Safikhani to better suit my needs in implementing a simple sliding puzzle game.
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 }
Generated on Thu Jul 14 2022 22:45:10 by
1.7.2