ILI9340 Library based on the Arduino version from Adafruit. It has been tested with a custom STM32F103C8 board.

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Adafruit_GFX.cpp Source File

Adafruit_GFX.cpp

00001 /*
00002 This is the core graphics library for all our displays, providing a common
00003 set of graphics primitives (points, lines, circles, etc.).  It needs to be
00004 paired with a hardware-specific library for each display device we carry
00005 (to handle the lower-level functions).
00006 
00007 Adafruit invests time and resources providing this open source code, please
00008 support Adafruit & open-source hardware by purchasing products from Adafruit!
00009  
00010 Copyright (c) 2013 Adafruit Industries.  All rights reserved.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014 
00015 - Redistributions of source code must retain the above copyright notice,
00016   this list of conditions and the following disclaimer.
00017 - Redistributions in binary form must reproduce the above copyright notice,
00018   this list of conditions and the following disclaimer in the documentation
00019   and/or other materials provided with the distribution.
00020 
00021 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00022 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00025 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00026 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00027 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00028 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00029 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00030 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 POSSIBILITY OF SUCH DAMAGE.
00032 */
00033 
00034 // Modified for mbed
00035 // by Georgios Moralis 
00036 
00037 #include "Adafruit_GFX.h"
00038 #include "glcdfont.c"
00039 //#include "stm32f10x.h"
00040 //#include "stm32f10x_conf.h"
00041 //#include "stm32f10x_spi.h"
00042 
00043 //#include "core_cm3.h"
00044 #include "stdint.h"
00045 
00046 #define COMPILE_FOR_STM32
00047 #ifdef COMPILE_FOR_STM32
00048 #include "stm32f10x_flash.h"
00049 #endif
00050 
00051 uint8_t pgm_read_byte(const uint8_t *whatever)   
00052 { 
00053     uint8_t rd;
00054 #ifdef  COMPILE_FOR_STM32
00055     FLASH_Unlock();         
00056 #endif      
00057     rd = *((uint8_t *) whatever); 
00058 #ifdef  COMPILE_FOR_STM32   
00059     FLASH_Lock();
00060 #endif      
00061     return rd;
00062 }
00063 
00064 int16_t abs(int16_t num)
00065 {
00066     if(num>=0)
00067         return num;
00068     else
00069         return -num;
00070 }
00071 
00072 
00073 
00074 Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h):
00075   WIDTH(w), HEIGHT(h)
00076 {
00077   _width    = WIDTH;
00078   _height   = HEIGHT;
00079   rotation  = 0;
00080   cursor_y  = cursor_x    = 0;
00081   textsize  = 1;
00082   textcolor = textbgcolor = 0xFFFF;
00083   wrap      = true;
00084 }
00085 
00086 // Draw a circle outline
00087 void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r,
00088     uint16_t color) {
00089   int16_t f = 1 - r;
00090   int16_t ddF_x = 1;
00091   int16_t ddF_y = -2 * r;
00092   int16_t x = 0;
00093   int16_t y = r;
00094 
00095   drawPixel(x0  , y0+r, color);
00096   drawPixel(x0  , y0-r, color);
00097   drawPixel(x0+r, y0  , color);
00098   drawPixel(x0-r, y0  , color);
00099 
00100   while (x<y) {
00101     if (f >= 0) {
00102       y--;
00103       ddF_y += 2;
00104       f += ddF_y;
00105     }
00106     x++;
00107     ddF_x += 2;
00108     f += ddF_x;
00109   
00110     drawPixel(x0 + x, y0 + y, color);
00111     drawPixel(x0 - x, y0 + y, color);
00112     drawPixel(x0 + x, y0 - y, color);
00113     drawPixel(x0 - x, y0 - y, color);
00114     drawPixel(x0 + y, y0 + x, color);
00115     drawPixel(x0 - y, y0 + x, color);
00116     drawPixel(x0 + y, y0 - x, color);
00117     drawPixel(x0 - y, y0 - x, color);
00118   }
00119 }
00120 
00121 void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0,
00122                int16_t r, uint8_t cornername, uint16_t color) {
00123   int16_t f     = 1 - r;
00124   int16_t ddF_x = 1;
00125   int16_t ddF_y = -2 * r;
00126   int16_t x     = 0;
00127   int16_t y     = r;
00128 
00129   while (x<y) {
00130     if (f >= 0) {
00131       y--;
00132       ddF_y += 2;
00133       f     += ddF_y;
00134     }
00135     x++;
00136     ddF_x += 2;
00137     f     += ddF_x;
00138     if (cornername & 0x4) {
00139       drawPixel(x0 + x, y0 + y, color);
00140       drawPixel(x0 + y, y0 + x, color);
00141     } 
00142     if (cornername & 0x2) {
00143       drawPixel(x0 + x, y0 - y, color);
00144       drawPixel(x0 + y, y0 - x, color);
00145     }
00146     if (cornername & 0x8) {
00147       drawPixel(x0 - y, y0 + x, color);
00148       drawPixel(x0 - x, y0 + y, color);
00149     }
00150     if (cornername & 0x1) {
00151       drawPixel(x0 - y, y0 - x, color);
00152       drawPixel(x0 - x, y0 - y, color);
00153     }
00154   }
00155 }
00156 
00157 void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r,
00158                   uint16_t color) {
00159   drawFastVLine(x0, y0-r, 2*r+1, color);
00160   fillCircleHelper(x0, y0, r, 3, 0, color);
00161 }
00162 
00163 // Used to do circles and roundrects
00164 void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r,
00165     uint8_t cornername, int16_t delta, uint16_t color) {
00166 
00167   int16_t f     = 1 - r;
00168   int16_t ddF_x = 1;
00169   int16_t ddF_y = -2 * r;
00170   int16_t x     = 0;
00171   int16_t y     = r;
00172 
00173   while (x<y) {
00174     if (f >= 0) {
00175       y--;
00176       ddF_y += 2;
00177       f     += ddF_y;
00178     }
00179     x++;
00180     ddF_x += 2;
00181     f     += ddF_x;
00182 
00183     if (cornername & 0x1) {
00184       drawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
00185       drawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
00186     }
00187     if (cornername & 0x2) {
00188       drawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
00189       drawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
00190     }
00191   }
00192 }
00193 
00194 // Bresenham's algorithm - thx wikpedia
00195 void Adafruit_GFX::drawLine(int16_t x0, int16_t y0,
00196                 int16_t x1, int16_t y1,
00197                 uint16_t color) {
00198   int16_t steep = abs(y1 - y0) > abs(x1 - x0);
00199   if (steep) {
00200     swap(x0, y0);
00201     swap(x1, y1);
00202   }
00203 
00204   if (x0 > x1) {
00205     swap(x0, x1);
00206     swap(y0, y1);
00207   }
00208 
00209   int16_t dx, dy;
00210   dx = x1 - x0;
00211   dy = abs(y1 - y0);
00212 
00213   int16_t err = dx / 2;
00214   int16_t ystep;
00215 
00216   if (y0 < y1) {
00217     ystep = 1;
00218   } else {
00219     ystep = -1;
00220   }
00221 
00222   for (; x0<=x1; x0++) {
00223     if (steep) {
00224       drawPixel(y0, x0, color);
00225     } else {
00226       drawPixel(x0, y0, color);
00227     }
00228     err -= dy;
00229     if (err < 0) {
00230       y0 += ystep;
00231       err += dx;
00232     }
00233   }
00234 }
00235 
00236 // Draw a rectangle
00237 void Adafruit_GFX::drawRect(int16_t x, int16_t y,
00238                 int16_t w, int16_t h,
00239                 uint16_t color) {
00240   drawFastHLine(x, y, w, color);
00241   drawFastHLine(x, y+h-1, w, color);
00242   drawFastVLine(x, y, h, color);
00243   drawFastVLine(x+w-1, y, h, color);
00244 }
00245 
00246 void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y,
00247                  int16_t h, uint16_t color) {
00248   // Update in subclasses if desired!
00249   drawLine(x, y, x, y+h-1, color);
00250 }
00251 
00252 void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y,
00253                  int16_t w, uint16_t color) {
00254   // Update in subclasses if desired!
00255   drawLine(x, y, x+w-1, y, color);
00256 }
00257 
00258 void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
00259                 uint16_t color) {
00260   // Update in subclasses if desired!
00261   for (int16_t i=x; i<x+w; i++) {
00262     drawFastVLine(i, y, h, color);
00263   }
00264 }
00265 
00266 void Adafruit_GFX::fillScreen(uint16_t color) {
00267   fillRect(0, 0, _width, _height, color);
00268 }
00269 
00270 // Draw a rounded rectangle
00271 void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w,
00272   int16_t h, int16_t r, uint16_t color) {
00273   // smarter version
00274   drawFastHLine(x+r  , y    , w-2*r, color); // Top
00275   drawFastHLine(x+r  , y+h-1, w-2*r, color); // Bottom
00276   drawFastVLine(x    , y+r  , h-2*r, color); // Left
00277   drawFastVLine(x+w-1, y+r  , h-2*r, color); // Right
00278   // draw four corners
00279   drawCircleHelper(x+r    , y+r    , r, 1, color);
00280   drawCircleHelper(x+w-r-1, y+r    , r, 2, color);
00281   drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
00282   drawCircleHelper(x+r    , y+h-r-1, r, 8, color);
00283 }
00284 
00285 // Fill a rounded rectangle
00286 void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w,
00287                  int16_t h, int16_t r, uint16_t color) {
00288   // smarter version
00289   fillRect(x+r, y, w-2*r, h, color);
00290 
00291   // draw four corners
00292   fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
00293   fillCircleHelper(x+r    , y+r, r, 2, h-2*r-1, color);
00294 }
00295 
00296 // Draw a triangle
00297 void Adafruit_GFX::drawTriangle(int16_t x0, int16_t y0,
00298                 int16_t x1, int16_t y1,
00299                 int16_t x2, int16_t y2, uint16_t color) {
00300   drawLine(x0, y0, x1, y1, color);
00301   drawLine(x1, y1, x2, y2, color);
00302   drawLine(x2, y2, x0, y0, color);
00303 }
00304 
00305 // Fill a triangle
00306 void Adafruit_GFX::fillTriangle ( int16_t x0, int16_t y0,
00307                   int16_t x1, int16_t y1,
00308                   int16_t x2, int16_t y2, uint16_t color) {
00309 
00310   int16_t a, b, y, last;
00311 
00312   // Sort coordinates by Y order (y2 >= y1 >= y0)
00313   if (y0 > y1) {
00314     swap(y0, y1); swap(x0, x1);
00315   }
00316   if (y1 > y2) {
00317     swap(y2, y1); swap(x2, x1);
00318   }
00319   if (y0 > y1) {
00320     swap(y0, y1); swap(x0, x1);
00321   }
00322 
00323   if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
00324     a = b = x0;
00325     if(x1 < a)      a = x1;
00326     else if(x1 > b) b = x1;
00327     if(x2 < a)      a = x2;
00328     else if(x2 > b) b = x2;
00329     drawFastHLine(a, y0, b-a+1, color);
00330     return;
00331   }
00332 
00333   int16_t
00334     dx01 = x1 - x0,
00335     dy01 = y1 - y0,
00336     dx02 = x2 - x0,
00337     dy02 = y2 - y0,
00338     dx12 = x2 - x1,
00339     dy12 = y2 - y1;
00340   int32_t
00341     sa   = 0,
00342     sb   = 0;
00343 
00344   // For upper part of triangle, find scanline crossings for segments
00345   // 0-1 and 0-2.  If y1=y2 (flat-bottomed triangle), the scanline y1
00346   // is included here (and second loop will be skipped, avoiding a /0
00347   // error there), otherwise scanline y1 is skipped here and handled
00348   // in the second loop...which also avoids a /0 error here if y0=y1
00349   // (flat-topped triangle).
00350   if(y1 == y2) last = y1;   // Include y1 scanline
00351   else         last = y1-1; // Skip it
00352 
00353   for(y=y0; y<=last; y++) {
00354     a   = x0 + sa / dy01;
00355     b   = x0 + sb / dy02;
00356     sa += dx01;
00357     sb += dx02;
00358     /* longhand:
00359     a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
00360     b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
00361     */
00362     if(a > b) swap(a,b);
00363     drawFastHLine(a, y, b-a+1, color);
00364   }
00365 
00366   // For lower part of triangle, find scanline crossings for segments
00367   // 0-2 and 1-2.  This loop is skipped if y1=y2.
00368   sa = dx12 * (y - y1);
00369   sb = dx02 * (y - y0);
00370   for(; y<=y2; y++) {
00371     a   = x1 + sa / dy12;
00372     b   = x0 + sb / dy02;
00373     sa += dx12;
00374     sb += dx02;
00375     /* longhand:
00376     a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
00377     b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
00378     */
00379     if(a > b) swap(a,b);
00380     drawFastHLine(a, y, b-a+1, color);
00381   }
00382 }
00383 
00384 void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
00385                   const uint8_t *bitmap, int16_t w, int16_t h,
00386                   uint16_t color) {
00387 
00388   int16_t i, j, byteWidth = (w + 7) / 8;
00389 
00390   for(j=0; j<h; j++) {
00391     for(i=0; i<w; i++ ) {
00392       if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
00393         drawPixel(x+i, y+j, color);
00394       }
00395     }
00396   }
00397 }
00398 
00399 // Draw a 1-bit color bitmap at the specified x, y position from the
00400 // provided bitmap buffer (must be PROGMEM memory) using color as the
00401 // foreground color and bg as the background color.
00402 void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
00403             const uint8_t *bitmap, int16_t w, int16_t h,
00404             uint16_t color, uint16_t bg) {
00405 
00406   int16_t i, j, byteWidth = (w + 7) / 8;
00407   
00408   for(j=0; j<h; j++) {
00409     for(i=0; i<w; i++ ) {
00410       if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
00411         drawPixel(x+i, y+j, color);
00412       }
00413       else {
00414         drawPixel(x+i, y+j, bg);
00415       }
00416     }
00417   }
00418 }
00419 
00420 //Draw XBitMap Files (*.xbm), exported from GIMP,
00421 //Usage: Export from GIMP to *.xbm, rename *.xbm to *.c and open in editor.
00422 //C Array can be directly used with this function
00423 void Adafruit_GFX::drawXBitmap(int16_t x, int16_t y,
00424                               const uint8_t *bitmap, int16_t w, int16_t h,
00425                               uint16_t color) {
00426   
00427   int16_t i, j, byteWidth = (w + 7) / 8;
00428   
00429   for(j=0; j<h; j++) {
00430     for(i=0; i<w; i++ ) {
00431       if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (1 << (i % 8))) {
00432         drawPixel(x+i, y+j, color);
00433       }
00434     }
00435   }
00436 }
00437 
00438 #if ARDUINO >= 100
00439 size_t Adafruit_GFX::write(uint8_t c) {
00440 #else
00441 void Adafruit_GFX::write(uint8_t c) {
00442 #endif
00443   if (c == '\n') {
00444     cursor_y += textsize*8;
00445     cursor_x  = 0;
00446   } else if (c == '\r') {
00447     // skip em
00448   } else {
00449     drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
00450     cursor_x += textsize*6;
00451     if (wrap && (cursor_x > (_width - textsize*6))) {
00452       cursor_y += textsize*8;
00453       cursor_x = 0;
00454     }
00455   }
00456 #if ARDUINO >= 100
00457   return 1;
00458 #endif
00459 }
00460 
00461 // Draw a character
00462 void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
00463                 uint16_t color, uint16_t bg, uint8_t size) {
00464 
00465   if((x >= _width)            || // Clip right
00466      (y >= _height)           || // Clip bottom
00467      ((x + 6 * size - 1) < 0) || // Clip left
00468      ((y + 8 * size - 1) < 0))   // Clip top
00469     return;
00470 
00471   for (int8_t i=0; i<6; i++ ) {
00472     uint8_t line;
00473     if (i == 5) 
00474       line = 0x0;
00475     else 
00476       line = pgm_read_byte(font+(c*5)+i);
00477     for (int8_t j = 0; j<8; j++) {
00478       if (line & 0x1) {
00479         if (size == 1) // default size
00480           drawPixel(x+i, y+j, color);
00481         else {  // big size
00482           fillRect(x+(i*size), y+(j*size), size, size, color);
00483         } 
00484       } else if (bg != color) {
00485         if (size == 1) // default size
00486           drawPixel(x+i, y+j, bg);
00487         else {  // big size
00488           fillRect(x+i*size, y+j*size, size, size, bg);
00489         }
00490       }
00491       line >>= 1;
00492     }
00493   }
00494 }
00495 
00496 void Adafruit_GFX::setCursor(int16_t x, int16_t y) {
00497   cursor_x = x;
00498   cursor_y = y;
00499 }
00500 
00501 void Adafruit_GFX::setTextSize(uint8_t s) {
00502   textsize = (s > 0) ? s : 1;
00503 }
00504 
00505 void Adafruit_GFX::setTextColor(uint16_t c) {
00506   // For 'transparent' background, we'll set the bg 
00507   // to the same as fg instead of using a flag
00508   textcolor = textbgcolor = c;
00509 }
00510 
00511 void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) {
00512   textcolor   = c;
00513   textbgcolor = b; 
00514 }
00515 
00516 void Adafruit_GFX::setTextWrap(char w) {
00517   wrap = w;
00518 }
00519 
00520 uint8_t Adafruit_GFX::getRotation(void) const {
00521   return rotation;
00522 }
00523 
00524 void Adafruit_GFX::setRotation(uint8_t x) {
00525   rotation = (x & 3);
00526   switch(rotation) {
00527    case 0:
00528    case 2:
00529     _width  = WIDTH;
00530     _height = HEIGHT;
00531     break;
00532    case 1:
00533    case 3:
00534     _width  = HEIGHT;
00535     _height = WIDTH;
00536     break;
00537   }
00538 }
00539 
00540 // Return the size of the display (per current rotation)
00541 int16_t Adafruit_GFX::width(void) const {
00542   return _width;
00543 }
00544  
00545 int16_t Adafruit_GFX::height(void) const {
00546   return _height;
00547 }
00548 
00549 void Adafruit_GFX::invertDisplay(char i) {
00550   // Do nothing, must be subclassed if supported
00551 }
00552 
00553