Port of the Adafruit_GFX library for use in MBED. This is the core graphics library for all Adafruit's displays, providing a common set of graphics primitives (points, lines, circles, strings,bitmaps. etc). Complete details found @ https://github.com/adafruit/Adafruit-GFX-Library Required by Adafruit_PCD8544 Driver. BSD license.
Dependents: ili9341_test ece495_firmware Adafruit-64x32-PWM-Demo Pong_ILI9163C
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 /*Modified for MBED usage and tested with STM32F411RE on a Nucleo board. 00034 Embedded Print methods from Arduino Print.Cpp/Print.h 00035 00036 by James Kidd 2014 00037 * */ 00038 00039 #include <stdint.h> 00040 #include "Adafruit_GFX.h" 00041 #include "glcdfont.c" 00042 #include <math.h> 00043 #include <stdlib.h> 00044 #include <stddef.h> 00045 #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) 00046 00047 00048 Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h): 00049 WIDTH(w), HEIGHT(h) 00050 { 00051 _width = WIDTH; 00052 _height = HEIGHT; 00053 rotation = 0; 00054 cursor_y = cursor_x = 0; 00055 textsize = 1; 00056 textcolor = textbgcolor = 0xFFFF; 00057 wrap = true; 00058 } 00059 00060 // Draw a circle outline 00061 void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r, 00062 uint16_t color) { 00063 int16_t f = 1 - r; 00064 int16_t ddF_x = 1; 00065 int16_t ddF_y = -2 * r; 00066 int16_t x = 0; 00067 int16_t y = r; 00068 00069 drawPixel(x0 , y0+r, color); 00070 drawPixel(x0 , y0-r, color); 00071 drawPixel(x0+r, y0 , color); 00072 drawPixel(x0-r, y0 , color); 00073 00074 while (x<y) { 00075 if (f >= 0) { 00076 y--; 00077 ddF_y += 2; 00078 f += ddF_y; 00079 } 00080 x++; 00081 ddF_x += 2; 00082 f += ddF_x; 00083 00084 drawPixel(x0 + x, y0 + y, color); 00085 drawPixel(x0 - x, y0 + y, color); 00086 drawPixel(x0 + x, y0 - y, color); 00087 drawPixel(x0 - x, y0 - y, color); 00088 drawPixel(x0 + y, y0 + x, color); 00089 drawPixel(x0 - y, y0 + x, color); 00090 drawPixel(x0 + y, y0 - x, color); 00091 drawPixel(x0 - y, y0 - x, color); 00092 } 00093 } 00094 00095 void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0, 00096 int16_t r, uint8_t cornername, uint16_t color) { 00097 int16_t f = 1 - r; 00098 int16_t ddF_x = 1; 00099 int16_t ddF_y = -2 * r; 00100 int16_t x = 0; 00101 int16_t y = r; 00102 00103 while (x<y) { 00104 if (f >= 0) { 00105 y--; 00106 ddF_y += 2; 00107 f += ddF_y; 00108 } 00109 x++; 00110 ddF_x += 2; 00111 f += ddF_x; 00112 if (cornername & 0x4) { 00113 drawPixel(x0 + x, y0 + y, color); 00114 drawPixel(x0 + y, y0 + x, color); 00115 } 00116 if (cornername & 0x2) { 00117 drawPixel(x0 + x, y0 - y, color); 00118 drawPixel(x0 + y, y0 - x, color); 00119 } 00120 if (cornername & 0x8) { 00121 drawPixel(x0 - y, y0 + x, color); 00122 drawPixel(x0 - x, y0 + y, color); 00123 } 00124 if (cornername & 0x1) { 00125 drawPixel(x0 - y, y0 - x, color); 00126 drawPixel(x0 - x, y0 - y, color); 00127 } 00128 } 00129 } 00130 00131 void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r, 00132 uint16_t color) { 00133 drawFastVLine(x0, y0-r, 2*r+1, color); 00134 fillCircleHelper(x0, y0, r, 3, 0, color); 00135 } 00136 00137 // Used to do circles and roundrects 00138 void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, 00139 uint8_t cornername, int16_t delta, uint16_t color) { 00140 00141 int16_t f = 1 - r; 00142 int16_t ddF_x = 1; 00143 int16_t ddF_y = -2 * r; 00144 int16_t x = 0; 00145 int16_t y = r; 00146 00147 while (x<y) { 00148 if (f >= 0) { 00149 y--; 00150 ddF_y += 2; 00151 f += ddF_y; 00152 } 00153 x++; 00154 ddF_x += 2; 00155 f += ddF_x; 00156 00157 if (cornername & 0x1) { 00158 drawFastVLine(x0+x, y0-y, 2*y+1+delta, color); 00159 drawFastVLine(x0+y, y0-x, 2*x+1+delta, color); 00160 } 00161 if (cornername & 0x2) { 00162 drawFastVLine(x0-x, y0-y, 2*y+1+delta, color); 00163 drawFastVLine(x0-y, y0-x, 2*x+1+delta, color); 00164 } 00165 } 00166 } 00167 00168 // Bresenham's algorithm - thx wikpedia 00169 void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, 00170 int16_t x1, int16_t y1, 00171 uint16_t color) { 00172 int16_t steep = abs(y1 - y0) > abs(x1 - x0); 00173 if (steep) { 00174 swap(x0, y0); 00175 swap(x1, y1); 00176 } 00177 00178 if (x0 > x1) { 00179 swap(x0, x1); 00180 swap(y0, y1); 00181 } 00182 00183 int16_t dx, dy; 00184 dx = x1 - x0; 00185 dy = abs(y1 - y0); 00186 00187 int16_t err = dx / 2; 00188 int16_t ystep; 00189 00190 if (y0 < y1) { 00191 ystep = 1; 00192 } else { 00193 ystep = -1; 00194 } 00195 00196 for (; x0<=x1; x0++) { 00197 if (steep) { 00198 drawPixel(y0, x0, color); 00199 } else { 00200 drawPixel(x0, y0, color); 00201 } 00202 err -= dy; 00203 if (err < 0) { 00204 y0 += ystep; 00205 err += dx; 00206 } 00207 } 00208 } 00209 00210 // Draw a rectangle 00211 void Adafruit_GFX::drawRect(int16_t x, int16_t y, 00212 int16_t w, int16_t h, 00213 uint16_t color) { 00214 drawFastHLine(x, y, w, color); 00215 drawFastHLine(x, y+h-1, w, color); 00216 drawFastVLine(x, y, h, color); 00217 drawFastVLine(x+w-1, y, h, color); 00218 } 00219 00220 void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y, 00221 int16_t h, uint16_t color) { 00222 // Update in subclasses if desired! 00223 drawLine(x, y, x, y+h-1, color); 00224 } 00225 00226 void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y, 00227 int16_t w, uint16_t color) { 00228 // Update in subclasses if desired! 00229 drawLine(x, y, x+w-1, y, color); 00230 } 00231 00232 void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, 00233 uint16_t color) { 00234 // Update in subclasses if desired! 00235 for (int16_t i=x; i<x+w; i++) { 00236 drawFastVLine(i, y, h, color); 00237 } 00238 } 00239 00240 void Adafruit_GFX::fillScreen(uint16_t color) { 00241 fillRect(0, 0, _width, _height, color); 00242 } 00243 00244 // Draw a rounded rectangle 00245 void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w, 00246 int16_t h, int16_t r, uint16_t color) { 00247 // smarter version 00248 drawFastHLine(x+r , y , w-2*r, color); // Top 00249 drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom 00250 drawFastVLine(x , y+r , h-2*r, color); // Left 00251 drawFastVLine(x+w-1, y+r , h-2*r, color); // Right 00252 // draw four corners 00253 drawCircleHelper(x+r , y+r , r, 1, color); 00254 drawCircleHelper(x+w-r-1, y+r , r, 2, color); 00255 drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color); 00256 drawCircleHelper(x+r , y+h-r-1, r, 8, color); 00257 } 00258 00259 // Fill a rounded rectangle 00260 void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w, 00261 int16_t h, int16_t r, uint16_t color) { 00262 // smarter version 00263 fillRect(x+r, y, w-2*r, h, color); 00264 00265 // draw four corners 00266 fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color); 00267 fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color); 00268 } 00269 00270 // Draw a triangle 00271 void Adafruit_GFX::drawTriangle(int16_t x0, int16_t y0, 00272 int16_t x1, int16_t y1, 00273 int16_t x2, int16_t y2, uint16_t color) { 00274 drawLine(x0, y0, x1, y1, color); 00275 drawLine(x1, y1, x2, y2, color); 00276 drawLine(x2, y2, x0, y0, color); 00277 } 00278 00279 // Fill a triangle 00280 void Adafruit_GFX::fillTriangle ( int16_t x0, int16_t y0, 00281 int16_t x1, int16_t y1, 00282 int16_t x2, int16_t y2, uint16_t color) { 00283 00284 int16_t a, b, y, last; 00285 00286 // Sort coordinates by Y order (y2 >= y1 >= y0) 00287 if (y0 > y1) { 00288 swap(y0, y1); swap(x0, x1); 00289 } 00290 if (y1 > y2) { 00291 swap(y2, y1); swap(x2, x1); 00292 } 00293 if (y0 > y1) { 00294 swap(y0, y1); swap(x0, x1); 00295 } 00296 00297 if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing 00298 a = b = x0; 00299 if(x1 < a) a = x1; 00300 else if(x1 > b) b = x1; 00301 if(x2 < a) a = x2; 00302 else if(x2 > b) b = x2; 00303 drawFastHLine(a, y0, b-a+1, color); 00304 return; 00305 } 00306 00307 int16_t 00308 dx01 = x1 - x0, 00309 dy01 = y1 - y0, 00310 dx02 = x2 - x0, 00311 dy02 = y2 - y0, 00312 dx12 = x2 - x1, 00313 dy12 = y2 - y1; 00314 int32_t 00315 sa = 0, 00316 sb = 0; 00317 00318 // For upper part of triangle, find scanline crossings for segments 00319 // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 00320 // is included here (and second loop will be skipped, avoiding a /0 00321 // error there), otherwise scanline y1 is skipped here and handled 00322 // in the second loop...which also avoids a /0 error here if y0=y1 00323 // (flat-topped triangle). 00324 if(y1 == y2) last = y1; // Include y1 scanline 00325 else last = y1-1; // Skip it 00326 00327 for(y=y0; y<=last; y++) { 00328 a = x0 + sa / dy01; 00329 b = x0 + sb / dy02; 00330 sa += dx01; 00331 sb += dx02; 00332 /* longhand: 00333 a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); 00334 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); 00335 */ 00336 if(a > b) swap(a,b); 00337 drawFastHLine(a, y, b-a+1, color); 00338 } 00339 00340 // For lower part of triangle, find scanline crossings for segments 00341 // 0-2 and 1-2. This loop is skipped if y1=y2. 00342 sa = dx12 * (y - y1); 00343 sb = dx02 * (y - y0); 00344 for(; y<=y2; y++) { 00345 a = x1 + sa / dy12; 00346 b = x0 + sb / dy02; 00347 sa += dx12; 00348 sb += dx02; 00349 /* longhand: 00350 a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); 00351 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); 00352 */ 00353 if(a > b) swap(a,b); 00354 drawFastHLine(a, y, b-a+1, color); 00355 } 00356 } 00357 00358 void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, 00359 const uint8_t *bitmap, int16_t w, int16_t h, 00360 uint16_t color) { 00361 00362 int16_t i, j, byteWidth = (w + 7) / 8; 00363 00364 for(j=0; j<h; j++) { 00365 for(i=0; i<w; i++ ) { 00366 if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) { 00367 drawPixel(x+i, y+j, color); 00368 } 00369 } 00370 } 00371 } 00372 00373 // Draw a 1-bit color bitmap at the specified x, y position from the 00374 // provided bitmap buffer (must be PROGMEM memory) using color as the 00375 // foreground color and bg as the background color. 00376 void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, 00377 const uint8_t *bitmap, int16_t w, int16_t h, 00378 uint16_t color, uint16_t bg) { 00379 00380 int16_t i, j, byteWidth = (w + 7) / 8; 00381 00382 for(j=0; j<h; j++) { 00383 for(i=0; i<w; i++ ) { 00384 if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) { 00385 drawPixel(x+i, y+j, color); 00386 } 00387 else { 00388 drawPixel(x+i, y+j, bg); 00389 } 00390 } 00391 } 00392 } 00393 00394 //Draw XBitMap Files (*.xbm), exported from GIMP, 00395 //Usage: Export from GIMP to *.xbm, rename *.xbm to *.c and open in editor. 00396 //C Array can be directly used with this function 00397 void Adafruit_GFX::drawXBitmap(int16_t x, int16_t y, 00398 const uint8_t *bitmap, int16_t w, int16_t h, 00399 uint16_t color) { 00400 00401 int16_t i, j, byteWidth = (w + 7) / 8; 00402 00403 for(j=0; j<h; j++) { 00404 for(i=0; i<w; i++ ) { 00405 if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (1 << (i % 8))) { 00406 drawPixel(x+i, y+j, color); 00407 } 00408 } 00409 } 00410 } 00411 00412 00413 uint8_t Adafruit_GFX::write(uint8_t c) { 00414 00415 if (c == '\n') { 00416 cursor_y += textsize*8; 00417 cursor_x = 0; 00418 } else if (c == '\r') { 00419 // skip em 00420 } else { 00421 drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); 00422 cursor_x += textsize*6; 00423 if (wrap && (cursor_x > (_width - textsize*6))) { 00424 cursor_y += textsize*8; 00425 cursor_x = 0; 00426 } 00427 } 00428 00429 return 1; 00430 00431 } 00432 00433 // Draw a character 00434 void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c, 00435 uint16_t color, uint16_t bg, uint8_t size) { 00436 00437 if((x >= _width) || // Clip right 00438 (y >= _height) || // Clip bottom 00439 ((x + 6 * size - 1) < 0) || // Clip left 00440 ((y + 8 * size - 1) < 0)) // Clip top 00441 return; 00442 00443 for (int8_t i=0; i<6; i++ ) { 00444 uint8_t line; 00445 if (i == 5) 00446 line = 0x0; 00447 else 00448 line = pgm_read_byte(font+(c*5)+i); 00449 for (int8_t j = 0; j<8; j++) { 00450 if (line & 0x1) { 00451 if (size == 1) // default size 00452 drawPixel(x+i, y+j, color); 00453 else { // big size 00454 fillRect(x+(i*size), y+(j*size), size, size, color); 00455 } 00456 } else if (bg != color) { 00457 if (size == 1) // default size 00458 drawPixel(x+i, y+j, bg); 00459 else { // big size 00460 fillRect(x+i*size, y+j*size, size, size, bg); 00461 } 00462 } 00463 line >>= 1; 00464 } 00465 } 00466 } 00467 00468 void Adafruit_GFX::setCursor(int16_t x, int16_t y) { 00469 cursor_x = x; 00470 cursor_y = y; 00471 } 00472 00473 void Adafruit_GFX::setTextSize(uint8_t s) { 00474 textsize = (s > 0) ? s : 1; 00475 } 00476 00477 void Adafruit_GFX::setTextColor(uint16_t c) { 00478 // For 'transparent' background, we'll set the bg 00479 // to the same as fg instead of using a flag 00480 textcolor = textbgcolor = c; 00481 } 00482 00483 void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) { 00484 textcolor = c; 00485 textbgcolor = b; 00486 } 00487 00488 void Adafruit_GFX::setTextWrap(bool w) { 00489 wrap = w; 00490 } 00491 00492 uint8_t Adafruit_GFX::getRotation(void) const { 00493 return rotation; 00494 } 00495 00496 void Adafruit_GFX::setRotation(uint8_t x) { 00497 rotation = (x & 3); 00498 switch(rotation) { 00499 case 0: 00500 case 2: 00501 _width = WIDTH; 00502 _height = HEIGHT; 00503 break; 00504 case 1: 00505 case 3: 00506 _width = HEIGHT; 00507 _height = WIDTH; 00508 break; 00509 } 00510 } 00511 00512 // Return the size of the display (per current rotation) 00513 int16_t Adafruit_GFX::width(void) const { 00514 return _width; 00515 } 00516 00517 int16_t Adafruit_GFX::height(void) const { 00518 return _height; 00519 } 00520 00521 void Adafruit_GFX::invertDisplay(bool i) { 00522 // Do nothing, must be subclassed if supported 00523 } 00524 00525 00526 //Methods from Print.cpp Arduino 00527 00528 uint8_t Adafruit_GFX::write(const uint8_t *buffer, uint8_t size) 00529 { 00530 uint8_t n = 0; 00531 while (size--) { 00532 n += write(*buffer++); 00533 } 00534 return n; 00535 } 00536 00537 uint8_t Adafruit_GFX::print(const char str[]) 00538 { 00539 return write(str); 00540 } 00541 00542 uint8_t Adafruit_GFX::print(char c) 00543 { 00544 return write(c); 00545 } 00546 00547 uint8_t Adafruit_GFX::print(unsigned char b, int base) 00548 { 00549 return print((unsigned long) b, base); 00550 } 00551 00552 uint8_t Adafruit_GFX::print(int n, int base) 00553 { 00554 return print((long) n, base); 00555 } 00556 00557 uint8_t Adafruit_GFX::print(unsigned int n, int base) 00558 { 00559 return print((unsigned long) n, base); 00560 } 00561 00562 uint8_t Adafruit_GFX::print(long n, int base) 00563 { 00564 if (base == 0) { 00565 return write(n); 00566 } else if (base == 10) { 00567 if (n < 0) { 00568 int t = print('-'); 00569 n = -n; 00570 return printNumber(n, 10) + t; 00571 } 00572 return printNumber(n, 10); 00573 } else { 00574 return printNumber(n, base); 00575 } 00576 } 00577 00578 uint8_t Adafruit_GFX::print(unsigned long n, int base) 00579 { 00580 if (base == 0) return write(n); 00581 else return printNumber(n, base); 00582 } 00583 00584 uint8_t Adafruit_GFX::print(double n, int digits) 00585 { 00586 return printFloat(n, digits); 00587 } 00588 00589 00590 00591 00592 00593 uint8_t Adafruit_GFX::println(void) 00594 { 00595 size_t n = print('\r'); 00596 n += print('\n'); 00597 return n; 00598 } 00599 00600 00601 00602 uint8_t Adafruit_GFX::println(const char c[]) 00603 { 00604 size_t n = print(c); 00605 n += println(); 00606 return n; 00607 } 00608 00609 uint8_t Adafruit_GFX::println(char c) 00610 { 00611 size_t n = print(c); 00612 n += println(); 00613 return n; 00614 } 00615 00616 uint8_t Adafruit_GFX::println(unsigned char b, int numBase) 00617 { 00618 size_t n = print(b, numBase); 00619 n += println(); 00620 return n; 00621 } 00622 00623 uint8_t Adafruit_GFX::println(int num, int base) 00624 { 00625 size_t n = print(num, base); 00626 n += println(); 00627 return n; 00628 } 00629 00630 uint8_t Adafruit_GFX::println(unsigned int num, int base) 00631 { 00632 size_t n = print(num, base); 00633 n += println(); 00634 return n; 00635 } 00636 00637 uint8_t Adafruit_GFX::println(long num, int base) 00638 { 00639 size_t n = print(num, base); 00640 n += println(); 00641 return n; 00642 } 00643 00644 uint8_t Adafruit_GFX::println(unsigned long num, int base) 00645 { 00646 size_t n = print(num, base); 00647 n += println(); 00648 return n; 00649 } 00650 00651 uint8_t Adafruit_GFX::println(double num, int digits) 00652 { 00653 size_t n = print(num, digits); 00654 n += println(); 00655 return n; 00656 } 00657 00658 00659 00660 // Private Methods ///////////////////////////////////////////////////////////// 00661 00662 uint8_t Adafruit_GFX::printNumber(unsigned long n, uint8_t base) { 00663 char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. 00664 char *str = &buf[sizeof(buf) - 1]; 00665 00666 *str = '\0'; 00667 00668 // prevent crash if called with base == 1 00669 if (base < 2) base = 10; 00670 00671 do { 00672 unsigned long m = n; 00673 n /= base; 00674 char c = m - base * n; 00675 *--str = c < 10 ? c + '0' : c + 'A' - 10; 00676 } while(n); 00677 00678 return write(str); 00679 } 00680 00681 uint8_t Adafruit_GFX::printFloat(double number, uint8_t digits) 00682 { 00683 uint8_t n = 0; 00684 00685 if (isnan(number)) return print("nan"); 00686 if (isinf(number)) return print("inf"); 00687 if (number > 4294967040.0) return print ("ovf"); // constant determined empirically 00688 if (number <-4294967040.0) return print ("ovf"); // constant determined empirically 00689 00690 // Handle negative numbers 00691 if (number < 0.0) 00692 { 00693 n += print('-'); 00694 number = -number; 00695 } 00696 00697 // Round correctly so that print(1.999, 2) prints as "2.00" 00698 double rounding = 0.5; 00699 for (uint8_t i=0; i<digits; ++i) 00700 rounding /= 10.0; 00701 00702 number += rounding; 00703 00704 // Extract the integer part of the number and print it 00705 unsigned long int_part = (unsigned long)number; 00706 double remainder = number - (double)int_part; 00707 n += print(int_part); 00708 00709 // Print the decimal point, but only if there are digits beyond 00710 if (digits > 0) { 00711 n += print("."); 00712 } 00713 00714 // Extract digits from the remainder one at a time 00715 while (digits-- > 0) 00716 { 00717 remainder *= 10.0; 00718 int toPrint = int(remainder); 00719 n += print(toPrint); 00720 remainder -= toPrint; 00721 } 00722 00723 return n; 00724 } 00725 00726
Generated on Wed Jul 13 2022 01:48:11 by
