Uses the same fonts as the SPI_TFT_ILI9341 Library (I have many, and a html/php font editor for that)

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPI_TFT_ILI9225.cpp Source File

SPI_TFT_ILI9225.cpp

00001 /*
00002 Ported from arduino to mbed platform by Arman Safikhani 31-08-2015
00003 Jack: Many thanks Arman!
00004 
00005 Changed a lot of things by Jack Berkhout 23-11-2016
00006 
00007 Used for 2.2" Serial SPI TFT Color LCD Module for Arduino
00008 176*220 resolution / 11-pin / ILI9225 IC driver
00009 https://www.fasttech.com/product/3842400-2-2-serial-spi-tft-color-lcd-module-for-arduino
00010 
00011 - Some code removed, some added, some changed
00012 - Now uses the same fonts as the SPI_TFT_ILI9341 Library (I have many, and a html/php font editor for that)
00013 - Text line interspacing can be set
00014 - The led backlight is using a PWM output, so it can be adjusted in brightness (from 0.0f = off to 1.0f = full brightness)
00015 - Added formatted printf
00016 - Added claim as standard output on stream
00017 - Orientation definitions are now related to the SD card slot location (front view)
00018 - Fast line functions hline and vline added, also used by outline reactangles, with drastical performance improvement (15 times)
00019 - Performance boost for filled shapes using new vline and hline functions
00020 - Get getStringWidth added
00021 */
00022 
00023 #include "SPI_TFT_ILI9225.h"
00024 
00025 // Constructor when using software SPI.  All output pins are configurable.
00026 TFT_22_ILI9225::TFT_22_ILI9225(PinName sdi, PinName clk, PinName cs, PinName rs, PinName rst, PinName led, const char *name) :
00027     _spi(sdi, NC, clk), _cs(cs), _rs(rs), _rst(rst), _led(led), Stream(name)
00028 {
00029     _spi.frequency(24000000); 
00030     _spi.format(8, 0);
00031 
00032     // PWM output to control backlight
00033     _led.period_ms(10);
00034 
00035     // --- claim ---
00036     _row = 0;
00037     _column = 0;
00038     if (name == NULL) {
00039         _path = NULL;
00040     } else {
00041         _path = new char[strlen(name) + 2];
00042         sprintf(_path, "/%s", name);
00043     }
00044     // --- /claim ---
00045     
00046     init();
00047 }
00048 
00049 void TFT_22_ILI9225::init()
00050 {
00051     // Turn off backlight
00052     setBacklight(0.0f);
00053 
00054     // Initialization Code
00055     _rst = 0;// Pull the reset pin low to reset ILI9225
00056     wait_ms(10);
00057     _rst = 1;// Pull the reset pin high to release the ILI9225C from the reset status
00058     wait_ms(50);
00059 
00060     /* Start Initial Sequence */
00061     /* Set SS bit and direction output from S528 to S1 */
00062     _writeRegister(ILI9225_POWER_CTRL1, 0x0000); // Set SAP,DSTB,STB
00063     _writeRegister(ILI9225_POWER_CTRL2, 0x0000); // Set APON,PON,AON,VCI1EN,VC
00064     _writeRegister(ILI9225_POWER_CTRL3, 0x0000); // Set BT,DC1,DC2,DC3
00065     _writeRegister(ILI9225_POWER_CTRL4, 0x0000); // Set GVDD
00066     _writeRegister(ILI9225_POWER_CTRL5, 0x0000); // Set VCOMH/VCOML voltage
00067     wait_ms(40);
00068 
00069     // Power-on sequence
00070     _writeRegister(ILI9225_POWER_CTRL2, 0x0018); // Set APON,PON,AON,VCI1EN,VC
00071     _writeRegister(ILI9225_POWER_CTRL3, 0x6121); // Set BT,DC1,DC2,DC3
00072     _writeRegister(ILI9225_POWER_CTRL4, 0x006F); // Set GVDD   /*007F 0088 */
00073     _writeRegister(ILI9225_POWER_CTRL5, 0x495F); // Set VCOMH/VCOML voltage
00074     _writeRegister(ILI9225_POWER_CTRL1, 0x0800); // Set SAP,DSTB,STB
00075     wait_ms(10);
00076     _writeRegister(ILI9225_POWER_CTRL2, 0x103B); // Set APON,PON,AON,VCI1EN,VC
00077     wait_ms(50);
00078 
00079     _writeRegister(ILI9225_DRIVER_OUTPUT_CTRL, 0x011C); // set the display line number and display direction
00080     _writeRegister(ILI9225_LCD_AC_DRIVING_CTRL, 0x0100); // set 1 line inversion
00081     _writeRegister(ILI9225_ENTRY_MODE, 0x1030); // set GRAM write direction and BGR=1.
00082     _writeRegister(ILI9225_DISP_CTRL1, 0x0000); // Display off
00083     _writeRegister(ILI9225_BLANK_PERIOD_CTRL1, 0x0808); // set the back porch and front porch
00084     _writeRegister(ILI9225_FRAME_CYCLE_CTRL, 0x1100); // set the clocks number per line
00085     _writeRegister(ILI9225_INTERFACE_CTRL, 0x0000); // CPU interface
00086     _writeRegister(ILI9225_OSC_CTRL, 0x0D01); // Set Osc  /*0e01*/
00087     _writeRegister(ILI9225_VCI_RECYCLING, 0x0020); // Set VCI recycling
00088     _writeRegister(ILI9225_RAM_ADDR_SET1, 0x0000); // RAM Address
00089     _writeRegister(ILI9225_RAM_ADDR_SET2, 0x0000); // RAM Address
00090 
00091                                                    /* Set GRAM area */
00092     _writeRegister(ILI9225_GATE_SCAN_CTRL, 0x0000);
00093     _writeRegister(ILI9225_VERTICAL_SCROLL_CTRL1, 0x00DB);
00094     _writeRegister(ILI9225_VERTICAL_SCROLL_CTRL2, 0x0000);
00095     _writeRegister(ILI9225_VERTICAL_SCROLL_CTRL3, 0x0000);
00096     _writeRegister(ILI9225_PARTIAL_DRIVING_POS1, 0x00DB);
00097     _writeRegister(ILI9225_PARTIAL_DRIVING_POS2, 0x0000);
00098     _writeRegister(ILI9225_HORIZONTAL_WINDOW_ADDR1, 0x00AF);
00099     _writeRegister(ILI9225_HORIZONTAL_WINDOW_ADDR2, 0x0000);
00100     _writeRegister(ILI9225_VERTICAL_WINDOW_ADDR1, 0x00DB);
00101     _writeRegister(ILI9225_VERTICAL_WINDOW_ADDR2, 0x0000);
00102 
00103     /* Set GAMMA curve */
00104     _writeRegister(ILI9225_GAMMA_CTRL1, 0x0000);
00105     _writeRegister(ILI9225_GAMMA_CTRL2, 0x0808);
00106     _writeRegister(ILI9225_GAMMA_CTRL3, 0x080A);
00107     _writeRegister(ILI9225_GAMMA_CTRL4, 0x000A);
00108     _writeRegister(ILI9225_GAMMA_CTRL5, 0x0A08);
00109     _writeRegister(ILI9225_GAMMA_CTRL6, 0x0808);
00110     _writeRegister(ILI9225_GAMMA_CTRL7, 0x0000);
00111     _writeRegister(ILI9225_GAMMA_CTRL8, 0x0A00);
00112     _writeRegister(ILI9225_GAMMA_CTRL9, 0x0710);
00113     _writeRegister(ILI9225_GAMMA_CTRL10, 0x0710);
00114 
00115     _writeRegister(ILI9225_DISP_CTRL1, 0x0012);
00116     wait_ms(50);
00117     _writeRegister(ILI9225_DISP_CTRL1, 0x1017);
00118 
00119     cls();
00120     linespacing(0);
00121     setBacklight(1.0f);
00122     setOrientation(ILI9225_LANDSCAPE_B);
00123     foreground(COLOR_WHITE);
00124     background(COLOR_BLACK);
00125 }
00126 
00127 void TFT_22_ILI9225::cls()
00128 {
00129     setBacklightOff();
00130     _setWindowMax();
00131     _rs = 1;
00132     _cs = 0;
00133     for (uint16_t i = width() * height(); i > 0; i--) {
00134         _spi.write(0x00);
00135         _spi.write(0x00);
00136     }
00137     _cs = 1;
00138     setBacklightOn();
00139     gotoxy(0, 0);
00140 }
00141 
00142 void TFT_22_ILI9225::fill(uint16_t color)
00143 {
00144     fillrect(0, 0, maxX(), maxY(), color);
00145 }
00146 
00147 void TFT_22_ILI9225::invert(bool flag)
00148 {
00149     _writeCommand(0x00, flag ? ILI9225C_INVON : ILI9225C_INVOFF);
00150 }
00151 
00152 void TFT_22_ILI9225::setBacklight(double brightness)
00153 {
00154     // PWM output to control backlight
00155     _brightness = brightness;
00156     _led.write(pow(brightness, 2)); // power(x, 2): For the eye better brightness response
00157 }
00158 
00159 void TFT_22_ILI9225::setBacklightOff(void)
00160 {
00161     _led.write(0.0f);
00162 }
00163 
00164 void TFT_22_ILI9225::setBacklightOn(void)
00165 {
00166     setBacklight(_brightness);
00167 }
00168 
00169 void TFT_22_ILI9225::setDisplay(bool flag)
00170 {
00171     if (flag) {
00172         _writeRegister(0x00ff, 0x0000);
00173         _writeRegister(ILI9225_POWER_CTRL1, 0x0000);
00174         wait_ms(50);
00175         _writeRegister(ILI9225_DISP_CTRL1, 0x1017);
00176         wait_ms(200);
00177     }
00178     else {
00179         _writeRegister(0x00ff, 0x0000);
00180         _writeRegister(ILI9225_DISP_CTRL1, 0x0000);
00181         wait_ms(50);
00182         _writeRegister(ILI9225_POWER_CTRL1, 0x0003);
00183         wait_ms(200);
00184     }
00185 }
00186 
00187 void TFT_22_ILI9225::setOrientation(uint8_t orientation)
00188 {
00189     _orientation = orientation % 4;
00190     // Entry Mode (R03h)
00191     // 0x1000 AM = 0: Horizontal, I/D[1:0] = 00: Horizontal: decrement, Vertical: decrement - ILI9225_PORTRAIT_R
00192     // 0x1010 AM = 0: Horizontal, I/D[1:0] = 01: Horizontal: increment, Vertical: decrement
00193     // 0x1020 AM = 0: Horizontal, I/D[1:0] = 10: Horizontal: decrement, Vertical: increment
00194     // 0x1030 AM = 0: Horizontal, I/D[1:0] = 11: Horizontal: increment, Vertical: increment - ILI9225_PORTRAIT_L
00195     // 0x1008 AM = 1: Vertical,   I/D[1:0] = 00: Horizontal: decrement, Vertical: decrement
00196     // 0x1018 AM = 1: Vertical,   I/D[1:0] = 01: Horizontal: increment, Vertical: decrement - ILI9225_LANDSCAPE_T
00197     // 0x1028 AM = 1: Vertical,   I/D[1:0] = 10: Horizontal: decrement, Vertical: increment - ILI9225_LANDSCAPE_B
00198     // 0x1038 AM = 1: Vertical,   I/D[1:0] = 11: Horizontal: increment, Vertical: increment
00199 
00200     switch (_orientation) {
00201         case ILI9225_PORTRAIT_L:
00202             // 0x1030 AM = 0: Horizontal, I/D[1:0] = 11: Horizontal: increment, Vertical: increment
00203             _entryMode = 0x1030;
00204             _maxX = ILI9225_LCD_WIDTH;
00205             _maxY = ILI9225_LCD_HEIGHT;
00206             break;
00207         case ILI9225_LANDSCAPE_B:
00208             // 0x1028 AM = 1: Vertical,   I/D[1:0] = 10: Horizontal: decrement, Vertical: increment
00209             _entryMode = 0x1028;
00210             _maxX = ILI9225_LCD_HEIGHT;
00211             _maxY = ILI9225_LCD_WIDTH;
00212             break;
00213         case ILI9225_PORTRAIT_R:
00214             // 0x1000 AM = 0: Horizontal, I/D[1:0] = 00: Horizontal: decrement, Vertical: decrement
00215             _entryMode = 0x1000;
00216             _maxX = ILI9225_LCD_WIDTH;
00217             _maxY = ILI9225_LCD_HEIGHT;
00218             break;
00219         case ILI9225_LANDSCAPE_T:
00220             // 0x1018 AM = 1: Vertical,   I/D[1:0] = 01: Horizontal: increment, Vertical: decrement
00221             _entryMode = 0x1018;
00222             _maxX = ILI9225_LCD_HEIGHT;
00223             _maxY = ILI9225_LCD_WIDTH;
00224             break;
00225     }
00226     _writeRegister(ILI9225_ENTRY_MODE, _entryMode); // set GRAM write direction and BGR=1.
00227 }
00228 
00229 uint8_t TFT_22_ILI9225::getOrientation()
00230 {
00231     return _orientation;
00232 }
00233 
00234 
00235 // Graphics functions
00236 
00237 void TFT_22_ILI9225::pixel(uint16_t x1, uint16_t y1, uint16_t color)
00238 {
00239     if ((x1 >= _maxX) || (y1 >= _maxY)) return;
00240 
00241     _setWindow(x1, y1, x1 + 1, y1 + 1);
00242     _orientCoordinates(x1, y1);
00243     _rs = 1;
00244     _cs = 0;
00245     _spi.write(color >> 8);
00246     _spi.write(color & 0xff);
00247     _cs = 1;
00248 }
00249 
00250 void TFT_22_ILI9225::line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
00251 {
00252     // Classic Bresenham algorithm
00253     int16_t steep = abs(y2 - y1) > abs(x2 - x1);
00254     int16_t dx, dy;
00255 
00256     if (steep) {
00257         _swap(x1, y1);
00258         _swap(x2, y2);
00259     }
00260 
00261     if (x1 > x2) {
00262         _swap(x1, x2);
00263         _swap(y1, y2);
00264     }
00265 
00266     dx = x2 - x1;
00267     dy = abs(y2 - y1);
00268 
00269     int16_t err = dx / 2;
00270     int16_t ystep;
00271 
00272     if (y1 < y2) ystep = 1;
00273     else ystep = -1;
00274 
00275 
00276     for (; x1 <= x2; x1++) {
00277         if (steep) pixel(y1, x1, color);
00278         else       pixel(x1, y1, color);
00279 
00280         err -= dy;
00281         if (err < 0) {
00282             y1 += ystep;
00283             err += dx;
00284         }
00285     }
00286 }
00287 
00288 void TFT_22_ILI9225::hline(uint16_t x1, uint16_t x2, uint16_t y, uint16_t color)
00289 {
00290     _writeRegister(ILI9225_ENTRY_MODE, 0x1028); // set GRAM write direction and BGR=1.
00291     _setWindow(x1, y, x2 + 1, y + 1);
00292     if (x2 < x1) {
00293         _swap(x1, x2);
00294     }
00295     _rs = 1;
00296     _cs = 0;
00297     for (uint16_t x = x1; x <= x2; x++) {
00298         _spi.write(color >> 8);
00299         _spi.write(color & 0xff);
00300     } 
00301     _cs = 1;
00302     _writeRegister(ILI9225_ENTRY_MODE, _entryMode); // set GRAM write direction and BGR=1.
00303 }
00304 
00305 void TFT_22_ILI9225::vline(uint16_t x, uint16_t y1, uint16_t y2, uint16_t color)
00306 {
00307     _writeRegister(ILI9225_ENTRY_MODE, 0x1010); // set GRAM write direction and BGR=1.
00308     _setWindow(x, y1, x + 1, y2 + 1);
00309     if (y2 < y1) {
00310         _swap(y1, y2);
00311     }
00312     _rs = 1;
00313     _cs = 0;
00314     for (uint16_t y = y1; y <= y2; y++) {
00315         _spi.write(color >> 8);
00316         _spi.write(color & 0xff);
00317     } 
00318     _cs = 1;
00319     _writeRegister(ILI9225_ENTRY_MODE, _entryMode); // set GRAM write direction and BGR=1.
00320 }
00321 
00322 void TFT_22_ILI9225::rect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) {
00323     
00324     vline(x1, y1, y2, color);
00325     hline(x1, x2, y1, color);
00326     hline(x1, x2, y2, color);
00327     vline(x2, y1, y2, color);
00328 }
00329 
00330 void TFT_22_ILI9225::fillrect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
00331 {
00332     _setWindow(x1, y1, x2, y2);
00333     _startData();
00334     for (uint16_t t = (y2 - y1 + 1) * (x2 - x1 + 1); t > 0; t--) {
00335         _writeData(color);
00336     }
00337     _endData();
00338 }
00339 
00340 void TFT_22_ILI9225::circle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color)
00341 {
00342     int16_t f = 1 - r;
00343     int16_t ddF_x = 1;
00344     int16_t ddF_y = -2 * r;
00345     int16_t x = 0;
00346     int16_t y = r;
00347 
00348     pixel(x0, y0 + r, color);
00349     pixel(x0, y0 - r, color);
00350     pixel(x0 + r, y0, color);
00351     pixel(x0 - r, y0, color);
00352 
00353     while (x < y) {
00354         if (f >= 0) {
00355             y--;
00356             ddF_y += 2;
00357             f += ddF_y;
00358         }
00359         x++;
00360         ddF_x += 2;
00361         f += ddF_x;
00362 
00363         pixel(x0 + x, y0 + y, color);
00364         pixel(x0 - x, y0 + y, color);
00365         pixel(x0 + x, y0 - y, color);
00366         pixel(x0 - x, y0 - y, color);
00367         pixel(x0 + y, y0 + x, color);
00368         pixel(x0 - y, y0 + x, color);
00369         pixel(x0 + y, y0 - x, color);
00370         pixel(x0 - y, y0 - x, color);
00371     }
00372 }
00373 
00374 void TFT_22_ILI9225::fillcircle(uint8_t x0, uint8_t y0, uint8_t radius, uint16_t color)
00375 {
00376     int16_t f = 1 - radius;
00377     int16_t ddF_x = 1;
00378     int16_t ddF_y = -2 * radius;
00379     int16_t x = 0;
00380     int16_t y = radius;
00381 
00382     while (x < y) {
00383         if (f >= 0) {
00384             y--;
00385             ddF_y += 2;
00386             f += ddF_y;
00387         }
00388         x++;
00389         ddF_x += 2;
00390         f += ddF_x;
00391 
00392         hline(x0 + x, x0 - x, y0 + y, color); // bottom
00393         hline(x0 + x, x0 - x, y0 - y, color); // top
00394         vline(x0 + y, y0 - x, y0 + x, color); // right
00395         vline(x0 - y, y0 - x, y0 + x, color); // left
00396     }
00397     fillrect(x0 - x, y0 - y, x0 + x, y0 + y, color);
00398 }
00399 
00400 void TFT_22_ILI9225::triangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color)
00401 {
00402     line(x1, y1, x2, y2, color);
00403     line(x2, y2, x3, y3, color);
00404     line(x3, y3, x1, y1, color);
00405 }
00406 
00407 void TFT_22_ILI9225::filltriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color)
00408 {
00409     uint16_t a, b, y, last;
00410 
00411     // Sort coordinates by Y order (y3 >= y2 >= y1)
00412     if (y1 > y2) {
00413         _swap(y1, y2); _swap(x1, x2);
00414     }
00415     if (y2 > y3) {
00416         _swap(y3, y2); _swap(x3, x2);
00417     }
00418     if (y1 > y2) {
00419         _swap(y1, y2); _swap(x1, x2);
00420     }
00421 
00422     if (y1 == y3) { // Handle awkward all-on-same-line case as its own thing
00423         a = b = x1;
00424         if (x2 < a)      a = x2;
00425         else if (x2 > b) b = x2;
00426         if (x3 < a)      a = x3;
00427         else if (x3 > b) b = x3;
00428         hline(a, b, y1, color);
00429         return;
00430     }
00431 
00432     uint16_t    dx11 = x2 - x1,
00433         dy11 = y2 - y1,
00434         dx12 = x3 - x1,
00435         dy12 = y3 - y1,
00436         dx22 = x3 - x2,
00437         dy22 = y3 - y2,
00438         sa = 0,
00439         sb = 0;
00440 
00441     // For upper part of triangle, find scanline crossings for segments
00442     // 0-1 and 0-2.  If y2=y3 (flat-bottomed triangle), the scanline y2
00443     // is included here (and second loop will be skipped, avoiding a /0
00444     // error there), otherwise scanline y2 is skipped here and handled
00445     // in the second loop...which also avoids a /0 error here if y1=y2
00446     // (flat-topped triangle).
00447     if (y2 == y3) last = y2;   // Include y2 scanline
00448     else          last = y2 - 1; // Skip it
00449 
00450     for (y = y1; y <= last; y++) {
00451         a = x1 + sa / dy11;
00452         b = x1 + sb / dy12;
00453         sa += dx11;
00454         sb += dx12;
00455         /* longhand:
00456         a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
00457         b = x1 + (x3 - x1) * (y - y1) / (y3 - y1);
00458         */
00459         if (a > b) _swap(a, b);
00460         hline(a, b, y, color);
00461     }
00462 
00463     // For lower part of triangle, find scanline crossings for segments
00464     // 0-2 and 1-2.  This loop is skipped if y2=y3.
00465     sa = dx22 * (y - y2);
00466     sb = dx12 * (y - y1);
00467     for (; y <= y3; y++) {
00468         a = x2 + sa / dy22;
00469         b = x1 + sb / dy12;
00470         sa += dx22;
00471         sb += dx12;
00472         /* longhand:
00473         a = x2 + (x3 - x2) * (y - y2) / (y3 - y2);
00474         b = x1 + (x3 - x1) * (y - y1) / (y3 - y1);
00475         */
00476         if (a > b) _swap(a, b);
00477         hline(a, b, y, color);
00478     }
00479 }
00480 
00481 void TFT_22_ILI9225::roundrect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t rad, bool fill, uint16_t color)
00482 {
00483     signed int a, b, P;
00484 
00485     a = 0;                      // increment by 1
00486     b = rad;                // decrement by 1 using P
00487     P = 1 - rad;
00488 
00489     if (fill)
00490     {
00491         fillrect(x1, y1 + rad, x2, y2 - rad, color);
00492 
00493         do
00494         {
00495             fillrect(x1 - a + rad, y1 - b + rad, a + x2 - rad, y1 - b + rad, color);   // 8 --> 1
00496             fillrect(x1 - b + rad, y1 - a + rad, b + x2 - rad, y1 - a + rad, color);   // 7 --> 2
00497             fillrect(x1 - b + rad, a + y2 - rad, b + x2 - rad, a + y2 - rad, color);   // 6 --> 3
00498             fillrect(x1 - a + rad, b + y2 - rad, a + x2 - rad, b + y2 - rad, color);   // 5 --> 4
00499 
00500             if (P < 0)
00501                 P += 3 + 2 * a++;
00502             else
00503                 P += 5 + 2 * (a++ - b--);
00504 
00505         } while (a <= b);
00506     }
00507     else
00508     {
00509         hline(x1 + rad, x2 - rad, y1, color);   // top
00510         hline(x1 + rad, x2 - rad, y2, color);   // bottom
00511         vline(x1, y1 + rad, y2 - rad, color);   // left
00512         vline(x2, y1 + rad, y2 - rad, color);   // right
00513 
00514         do
00515         {
00516             pixel(a + x2 - rad, y1 - b + rad, color);   // `````` Segment 1
00517             pixel(b + x2 - rad, y1 - a + rad, color);   // `````` Segment 2
00518 
00519             pixel(b + x2 - rad, a + y2 - rad, color);   // `````` Segment 3
00520             pixel(a + x2 - rad, b + y2 - rad, color);   // `````` Segment 4
00521 
00522             pixel(x1 - a + rad, b + y2 - rad, color);   // `````` Segment 5
00523             pixel(x1 - b + rad, a + y2 - rad, color);   // `````` Segment 6
00524 
00525             pixel(x1 - b + rad, y1 - a + rad, color);   // `````` Segment 7
00526             pixel(x1 - a + rad, y1 - b + rad, color);   // `````` Segment 8
00527 
00528             if (P < 0)
00529                 P += 3 + 2 * a++;
00530             else
00531                 P += 5 + 2 * (a++ - b--);
00532         } while (a <= b);
00533     }
00534 }
00535 
00536 uint16_t TFT_22_ILI9225::maxX(void)
00537 {
00538     return _maxX - 1;
00539 }
00540 
00541 uint16_t TFT_22_ILI9225::maxY(void)
00542 {
00543     return _maxY - 1;
00544 }
00545 
00546 uint16_t TFT_22_ILI9225::width(void)
00547 {
00548     return _maxX;
00549 }
00550 
00551 uint16_t TFT_22_ILI9225::height(void)
00552 {
00553     return _maxY;
00554 }
00555 
00556 uint16_t TFT_22_ILI9225::setColor(uint8_t red8, uint8_t green8, uint8_t blue8)
00557 {
00558     // rgb16 = red5 green6 blue5
00559     return (red8 >> 3) << 11 | (green8 >> 2) << 5 | (blue8 >> 3);
00560 }
00561 
00562 void TFT_22_ILI9225::splitColor(uint16_t rgb, uint8_t &red, uint8_t &green, uint8_t &blue)
00563 {
00564     // rgb16 = red5 green6 blue5
00565     
00566     red = (rgb & 0xF800) >> 11 << 3;
00567     green = (rgb & 0x7E0) >> 5 << 2;
00568     blue = (rgb & 0x1F) << 3;
00569 }
00570 
00571 
00572 // Text functions
00573 
00574 void TFT_22_ILI9225::setFont(unsigned char* f)
00575 {
00576     font = f;
00577 }
00578 
00579 uint8_t TFT_22_ILI9225::fontX(void)
00580 {
00581     return font[FONT_HORZ];
00582 }
00583 
00584 uint8_t TFT_22_ILI9225::fontY(void)
00585 {
00586     return font[FONT_VERT];
00587 }
00588 
00589 int TFT_22_ILI9225::putc(int value)
00590 {
00591     if (value == '\n') {    // new line
00592         char_x = 0;
00593         char_y = char_y + (font[FONT_VERT] + char_line_spacing);
00594         if (char_y >= height() - (font[FONT_VERT] + char_line_spacing)) {
00595             char_y = 0;
00596         }
00597         return value;
00598     }
00599     if ((value < 32) || (value > 127)) {
00600         return value;
00601     }
00602     character(char_x, char_y, value);
00603     return value;
00604 }
00605 
00606 void TFT_22_ILI9225::character(int x, int y, int c)
00607 {
00608     unsigned int hor, vert, offset, bpl, i, j, b;
00609     unsigned char* char_ptr;
00610     unsigned char z,w;
00611 
00612     if ((c < 31) || (c > 127)) return;   // test char range
00613 
00614     // read font parameter from start of array
00615     offset = font[FONT_LENGTH];         // bytes / char
00616     hor    = font[FONT_HORZ];           // get hor size of font
00617     vert   = font[FONT_VERT];           // get vert size of font
00618     bpl    = font[FONT_BYTES_VERT];     // bytes per line
00619 
00620     if (char_x + hor > width()) {
00621         char_x = 0;
00622         char_y = char_y + vert + char_line_spacing;
00623         if (char_y >= height() - (vert + char_line_spacing)) {
00624             char_y = 0;
00625         }
00626     }
00627     _setWindow(char_x, char_y, (char_x+hor)-1, (char_y+vert)-1);
00628 
00629     char_ptr = &font[((c -32) * offset) + 4]; // start of char bitmap
00630     w = char_ptr[0];                          // width of actual char
00631     _startData();
00632 
00633     // Portrait
00634     for (j = 0; j < vert; j++) {  //  vert line
00635         for (i = 0; i < hor; i++) {   //  horz line
00636             z =  char_ptr[bpl * i + ((j & 0xF8) >> 3)+1];
00637             b = 1 << (j & 0x07);
00638             if (( z & b ) == 0x00) {
00639                 _spi.write(_background >> 8);
00640                 _spi.write(_background & 0xff);
00641             } else {
00642                 _spi.write(_foreground >> 8);
00643                 _spi.write(_foreground & 0xff);
00644             }
00645         }
00646     }
00647     
00648     _endData();
00649     _setWindowMax();
00650     if ((w + 2) < hor) {                   // x offset to next char
00651         char_x += w + 2;
00652     } else {
00653         char_x += hor;
00654     }
00655 }
00656 
00657 uint16_t TFT_22_ILI9225::getStringWidth(char * s)
00658 {
00659     unsigned char* char_ptr;
00660     uint16_t width  = 0;
00661     uint16_t offset = font[FONT_LENGTH];         // bytes / char
00662     uint16_t hor    = font[FONT_HORZ];           // get hor size of font
00663 
00664     uint16_t len = strlen(s);
00665     for (uint8_t i = 0; i < len; i++) {
00666         if ((s[i] < 31) || (s[i] > 127)) {
00667             continue;               // test char range
00668         }
00669         char_ptr = &font[((s[i] -32) * offset) + 4]; // start of char bitmap
00670         unsigned char w = char_ptr[0];
00671         if ((w + 2) < hor) {                   // x offset to next char
00672             width += w + 2;
00673         } else {
00674             width += hor;
00675         }
00676     }
00677     return width - 1;
00678 }
00679 
00680 void TFT_22_ILI9225::foreground(uint16_t color)
00681 {
00682     _foreground = color;
00683 }
00684 
00685 void TFT_22_ILI9225::background(uint16_t color)
00686 {
00687     _background = color;
00688 }
00689 
00690 void TFT_22_ILI9225::locate(int x, int y)
00691 {
00692     char_x = x;
00693     char_y = y;
00694 }
00695 
00696 void TFT_22_ILI9225::gotoxy(int x, int y)
00697 {
00698     char_x = x * font[FONT_HORZ];
00699     char_y = y * (font[FONT_VERT] + char_line_spacing);
00700 }
00701 
00702 void TFT_22_ILI9225::home(void)
00703 {
00704     gotoxy(0, 0);
00705 }
00706 
00707 void TFT_22_ILI9225::linespacing(int line_spacing)
00708 {
00709     char_line_spacing = line_spacing;
00710 }
00711 
00712 int TFT_22_ILI9225::columns()
00713 {
00714     return width() / font[FONT_HORZ];
00715 }
00716 
00717 int TFT_22_ILI9225::rows()
00718 {
00719     return height() / font[FONT_VERT];
00720 }
00721 
00722 void TFT_22_ILI9225::unicode2ascii(char *uni_str, char *ascii_str)
00723 {
00724     int counter = 0;
00725     int Uch = 0;
00726     char chl, chh;
00727 
00728 
00729     while (*uni_str)
00730     {
00731         chl = *uni_str++;
00732         chh = *uni_str++;
00733 
00734         Uch = 0;
00735         Uch = ((Uch | chh) << 8) | chl;
00736 
00737         if (Uch > 1574 && Uch < 1591)
00738             *(ascii_str + counter) = (char)(Uch - 1376);
00739         else if (Uch > 1590 && Uch < 1595)
00740             *(ascii_str + counter) = (char)(Uch - 1375);
00741         else if (Uch > 1600 && Uch < 1603)
00742             *(ascii_str + counter) = (char)(Uch - 1380);
00743         else if (Uch == 1705)
00744             *(ascii_str + counter) = (char)(Uch - 1482);
00745         else if (Uch == 1604)
00746             *(ascii_str + counter) = (char)(Uch - 1379);
00747         else if (Uch > 1604 && Uch < 1609)
00748             *(ascii_str + counter) = (char)(Uch - 1378);
00749         else if (Uch == 1740)
00750             *(ascii_str + counter) = (char)(Uch - 1503);
00751         else if (Uch == 1574)
00752             *(ascii_str + counter) = (char)(Uch - 1381);
00753         else if (Uch == 1662)
00754             *(ascii_str + counter) = (char)(Uch - 1533);
00755         else if (Uch == 1670)
00756             *(ascii_str + counter) = (char)(Uch - 1529);
00757         else if (Uch == 1688)
00758             *(ascii_str + counter) = (char)(Uch - 1546);
00759         else if (Uch == 1711)
00760             *(ascii_str + counter) = (char)(Uch - 1567);
00761         else if (Uch == 1570)
00762             *(ascii_str + counter) = (char)(Uch - 1376);
00763         else if (Uch > 1631 && Uch < 1642)
00764             *(ascii_str + counter) = (char)(Uch - 1584);
00765         else if (Uch == 65536)
00766             *(ascii_str + counter) = NULL;
00767         else
00768             *(ascii_str + counter) = (char)Uch;
00769 
00770 
00771         counter++;
00772 
00773     }
00774     *(ascii_str + counter) = NULL;
00775 }
00776 
00777 bool TFT_22_ILI9225::claim (FILE *stream)
00778 {
00779     if ( _path == NULL) {
00780         fprintf(stderr, "claim requires a name to be given in the instantioator of the TextDisplay instance!\r\n");
00781         return false;
00782     }
00783     if (freopen(_path, "w", stream) == NULL) {
00784         // Failed, should not happen
00785         return false;
00786     }
00787     // make sure we use line buffering
00788     setvbuf(stdout, NULL, _IOLBF, ILI9225_CHARS_PER_LINE);
00789     return true;
00790 } 
00791 
00792 // Private functions
00793 
00794 void TFT_22_ILI9225::_swap(uint16_t &a, uint16_t &b)
00795 {
00796     uint16_t w = a;
00797     a = b;
00798     b = w;
00799 }
00800 
00801 void TFT_22_ILI9225::_setWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
00802 {
00803     _orientCoordinates(x0, y0);
00804     _orientCoordinates(x1, y1);
00805 
00806     if (x1 < x0) _swap(x0, x1);
00807     if (y1 < y0) _swap(y0, y1);
00808 
00809     _writeRegister(ILI9225_HORIZONTAL_WINDOW_ADDR1, x1);
00810     _writeRegister(ILI9225_HORIZONTAL_WINDOW_ADDR2, x0);
00811 
00812     _writeRegister(ILI9225_VERTICAL_WINDOW_ADDR1, y1);
00813     _writeRegister(ILI9225_VERTICAL_WINDOW_ADDR2, y0);
00814 
00815     _writeRegister(ILI9225_RAM_ADDR_SET1, x0);
00816     _writeRegister(ILI9225_RAM_ADDR_SET2, y0);
00817 
00818     _writeCommand(0x00, 0x22);
00819 }
00820 
00821 void TFT_22_ILI9225::_setWindowMax(void)
00822 {
00823     _setWindow(0, 0, maxX(), maxY());
00824 }
00825 
00826 void TFT_22_ILI9225::_orientCoordinates(uint16_t &x, uint16_t &y)
00827 {
00828     switch (_orientation) {
00829         case 0:  // ok
00830             break;
00831         case 1: // ok
00832             y = _maxY - y - 1;
00833             _swap(x, y);
00834             break;
00835         case 2: // ok
00836             x = _maxX - x - 1;
00837             y = _maxY - y - 1;
00838             break;
00839         case 3: // ok
00840             x = _maxX - x - 1;
00841             _swap(x, y);
00842             break;
00843     }
00844 }
00845 
00846 void TFT_22_ILI9225::_writeRegister(uint16_t reg, uint16_t data)
00847 {
00848     _writeCommand(reg >> 8, reg & 0xff);
00849     _startData();
00850     _writeData(data);
00851     _endData();
00852 }
00853 
00854 void TFT_22_ILI9225::_writeCommand(uint8_t HI, uint8_t LO)
00855 {
00856     _rs = 0;
00857     _cs = 0;
00858     _spi.write(HI);
00859     _spi.write(LO);
00860     _cs = 1;
00861 }
00862 
00863 void TFT_22_ILI9225::_startData(void)
00864 {
00865     _rs = 1;
00866     _cs = 0;
00867 }
00868 
00869 void TFT_22_ILI9225::_writeData(uint16_t data)
00870 {
00871     _spi.write(data >> 8);
00872     _spi.write(data & 0xff);
00873 }
00874 
00875 void TFT_22_ILI9225::_endData(void)
00876 {
00877     _cs = 1;
00878 }