test st7735 on lpc1768 with mbed v5. bug with spi frequency...

Committer:
skydarc
Date:
Wed Apr 08 15:00:13 2020 +0000
Revision:
2:2946f9eefcae
v2

Who changed what in which revision?

UserRevisionLine numberNew contents of line
skydarc 2:2946f9eefcae 1 /*
skydarc 2:2946f9eefcae 2 This is the core graphics library for all our displays, providing a common
skydarc 2:2946f9eefcae 3 set of graphics primitives (points, lines, circles, etc.). It needs to be
skydarc 2:2946f9eefcae 4 paired with a hardware-specific library for each display device we carry
skydarc 2:2946f9eefcae 5 (to handle the lower-level functions).
skydarc 2:2946f9eefcae 6
skydarc 2:2946f9eefcae 7 Adafruit invests time and resources providing this open source code, please
skydarc 2:2946f9eefcae 8 support Adafruit & open-source hardware by purchasing products from Adafruit!
skydarc 2:2946f9eefcae 9
skydarc 2:2946f9eefcae 10 Copyright (c) 2013 Adafruit Industries. All rights reserved.
skydarc 2:2946f9eefcae 11
skydarc 2:2946f9eefcae 12 Redistribution and use in source and binary forms, with or without
skydarc 2:2946f9eefcae 13 modification, are permitted provided that the following conditions are met:
skydarc 2:2946f9eefcae 14
skydarc 2:2946f9eefcae 15 - Redistributions of source code must retain the above copyright notice,
skydarc 2:2946f9eefcae 16 this list of conditions and the following disclaimer.
skydarc 2:2946f9eefcae 17 - Redistributions in binary form must reproduce the above copyright notice,
skydarc 2:2946f9eefcae 18 this list of conditions and the following disclaimer in the documentation
skydarc 2:2946f9eefcae 19 and/or other materials provided with the distribution.
skydarc 2:2946f9eefcae 20
skydarc 2:2946f9eefcae 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
skydarc 2:2946f9eefcae 22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
skydarc 2:2946f9eefcae 23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
skydarc 2:2946f9eefcae 24 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
skydarc 2:2946f9eefcae 25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
skydarc 2:2946f9eefcae 26 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
skydarc 2:2946f9eefcae 27 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
skydarc 2:2946f9eefcae 28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
skydarc 2:2946f9eefcae 29 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
skydarc 2:2946f9eefcae 30 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
skydarc 2:2946f9eefcae 31 POSSIBILITY OF SUCH DAMAGE.*/
skydarc 2:2946f9eefcae 32
skydarc 2:2946f9eefcae 33 /*Modified for MBED usage and tested with STM32F411RE on a Nucleo board.
skydarc 2:2946f9eefcae 34 Embedded Print methods from Arduino Print.Cpp/Print.h
skydarc 2:2946f9eefcae 35
skydarc 2:2946f9eefcae 36 by James Kidd 2014
skydarc 2:2946f9eefcae 37 * */
skydarc 2:2946f9eefcae 38
skydarc 2:2946f9eefcae 39 #include <stdint.h>
skydarc 2:2946f9eefcae 40 #include "GFX.h"
skydarc 2:2946f9eefcae 41 #include "font.c"
skydarc 2:2946f9eefcae 42 #include <math.h>
skydarc 2:2946f9eefcae 43 #include <stdlib.h>
skydarc 2:2946f9eefcae 44 #include <stddef.h>
skydarc 2:2946f9eefcae 45 #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
skydarc 2:2946f9eefcae 46
skydarc 2:2946f9eefcae 47
skydarc 2:2946f9eefcae 48 GFX::GFX(int16_t w, int16_t h):
skydarc 2:2946f9eefcae 49 WIDTH(w), HEIGHT(h)
skydarc 2:2946f9eefcae 50 {
skydarc 2:2946f9eefcae 51 _width = WIDTH;
skydarc 2:2946f9eefcae 52 _height = HEIGHT;
skydarc 2:2946f9eefcae 53 rotation = 0;
skydarc 2:2946f9eefcae 54 cursor_y = cursor_x = 0;
skydarc 2:2946f9eefcae 55 textsize = 1;
skydarc 2:2946f9eefcae 56 textcolor = textbgcolor = 0xFFFF;
skydarc 2:2946f9eefcae 57 wrap = true;
skydarc 2:2946f9eefcae 58 }
skydarc 2:2946f9eefcae 59
skydarc 2:2946f9eefcae 60 // Draw a circle outline
skydarc 2:2946f9eefcae 61 void GFX::drawCircle(int16_t x0, int16_t y0, int16_t r,
skydarc 2:2946f9eefcae 62 uint16_t color) {
skydarc 2:2946f9eefcae 63 int16_t f = 1 - r;
skydarc 2:2946f9eefcae 64 int16_t ddF_x = 1;
skydarc 2:2946f9eefcae 65 int16_t ddF_y = -2 * r;
skydarc 2:2946f9eefcae 66 int16_t x = 0;
skydarc 2:2946f9eefcae 67 int16_t y = r;
skydarc 2:2946f9eefcae 68
skydarc 2:2946f9eefcae 69 drawPixel(x0 , y0+r, color);
skydarc 2:2946f9eefcae 70 drawPixel(x0 , y0-r, color);
skydarc 2:2946f9eefcae 71 drawPixel(x0+r, y0 , color);
skydarc 2:2946f9eefcae 72 drawPixel(x0-r, y0 , color);
skydarc 2:2946f9eefcae 73
skydarc 2:2946f9eefcae 74 while (x<y) {
skydarc 2:2946f9eefcae 75 if (f >= 0) {
skydarc 2:2946f9eefcae 76 y--;
skydarc 2:2946f9eefcae 77 ddF_y += 2;
skydarc 2:2946f9eefcae 78 f += ddF_y;
skydarc 2:2946f9eefcae 79 }
skydarc 2:2946f9eefcae 80 x++;
skydarc 2:2946f9eefcae 81 ddF_x += 2;
skydarc 2:2946f9eefcae 82 f += ddF_x;
skydarc 2:2946f9eefcae 83
skydarc 2:2946f9eefcae 84 drawPixel(x0 + x, y0 + y, color);
skydarc 2:2946f9eefcae 85 drawPixel(x0 - x, y0 + y, color);
skydarc 2:2946f9eefcae 86 drawPixel(x0 + x, y0 - y, color);
skydarc 2:2946f9eefcae 87 drawPixel(x0 - x, y0 - y, color);
skydarc 2:2946f9eefcae 88 drawPixel(x0 + y, y0 + x, color);
skydarc 2:2946f9eefcae 89 drawPixel(x0 - y, y0 + x, color);
skydarc 2:2946f9eefcae 90 drawPixel(x0 + y, y0 - x, color);
skydarc 2:2946f9eefcae 91 drawPixel(x0 - y, y0 - x, color);
skydarc 2:2946f9eefcae 92 }
skydarc 2:2946f9eefcae 93 }
skydarc 2:2946f9eefcae 94
skydarc 2:2946f9eefcae 95 void GFX::drawCircleHelper( int16_t x0, int16_t y0,
skydarc 2:2946f9eefcae 96 int16_t r, uint8_t cornername, uint16_t color) {
skydarc 2:2946f9eefcae 97 int16_t f = 1 - r;
skydarc 2:2946f9eefcae 98 int16_t ddF_x = 1;
skydarc 2:2946f9eefcae 99 int16_t ddF_y = -2 * r;
skydarc 2:2946f9eefcae 100 int16_t x = 0;
skydarc 2:2946f9eefcae 101 int16_t y = r;
skydarc 2:2946f9eefcae 102
skydarc 2:2946f9eefcae 103 while (x<y) {
skydarc 2:2946f9eefcae 104 if (f >= 0) {
skydarc 2:2946f9eefcae 105 y--;
skydarc 2:2946f9eefcae 106 ddF_y += 2;
skydarc 2:2946f9eefcae 107 f += ddF_y;
skydarc 2:2946f9eefcae 108 }
skydarc 2:2946f9eefcae 109 x++;
skydarc 2:2946f9eefcae 110 ddF_x += 2;
skydarc 2:2946f9eefcae 111 f += ddF_x;
skydarc 2:2946f9eefcae 112 if (cornername & 0x4) {
skydarc 2:2946f9eefcae 113 drawPixel(x0 + x, y0 + y, color);
skydarc 2:2946f9eefcae 114 drawPixel(x0 + y, y0 + x, color);
skydarc 2:2946f9eefcae 115 }
skydarc 2:2946f9eefcae 116 if (cornername & 0x2) {
skydarc 2:2946f9eefcae 117 drawPixel(x0 + x, y0 - y, color);
skydarc 2:2946f9eefcae 118 drawPixel(x0 + y, y0 - x, color);
skydarc 2:2946f9eefcae 119 }
skydarc 2:2946f9eefcae 120 if (cornername & 0x8) {
skydarc 2:2946f9eefcae 121 drawPixel(x0 - y, y0 + x, color);
skydarc 2:2946f9eefcae 122 drawPixel(x0 - x, y0 + y, color);
skydarc 2:2946f9eefcae 123 }
skydarc 2:2946f9eefcae 124 if (cornername & 0x1) {
skydarc 2:2946f9eefcae 125 drawPixel(x0 - y, y0 - x, color);
skydarc 2:2946f9eefcae 126 drawPixel(x0 - x, y0 - y, color);
skydarc 2:2946f9eefcae 127 }
skydarc 2:2946f9eefcae 128 }
skydarc 2:2946f9eefcae 129 }
skydarc 2:2946f9eefcae 130
skydarc 2:2946f9eefcae 131 void GFX::fillCircle(int16_t x0, int16_t y0, int16_t r,
skydarc 2:2946f9eefcae 132 uint16_t color) {
skydarc 2:2946f9eefcae 133 drawFastVLine(x0, y0-r, 2*r+1, color);
skydarc 2:2946f9eefcae 134 fillCircleHelper(x0, y0, r, 3, 0, color);
skydarc 2:2946f9eefcae 135 }
skydarc 2:2946f9eefcae 136
skydarc 2:2946f9eefcae 137 // Used to do circles and roundrects
skydarc 2:2946f9eefcae 138 void GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r,
skydarc 2:2946f9eefcae 139 uint8_t cornername, int16_t delta, uint16_t color) {
skydarc 2:2946f9eefcae 140
skydarc 2:2946f9eefcae 141 int16_t f = 1 - r;
skydarc 2:2946f9eefcae 142 int16_t ddF_x = 1;
skydarc 2:2946f9eefcae 143 int16_t ddF_y = -2 * r;
skydarc 2:2946f9eefcae 144 int16_t x = 0;
skydarc 2:2946f9eefcae 145 int16_t y = r;
skydarc 2:2946f9eefcae 146
skydarc 2:2946f9eefcae 147 while (x<y) {
skydarc 2:2946f9eefcae 148
skydarc 2:2946f9eefcae 149 if (f >= 0) {
skydarc 2:2946f9eefcae 150 y--;
skydarc 2:2946f9eefcae 151 ddF_y += 2;
skydarc 2:2946f9eefcae 152 f += ddF_y;
skydarc 2:2946f9eefcae 153 }
skydarc 2:2946f9eefcae 154 x++;
skydarc 2:2946f9eefcae 155 ddF_x += 2;
skydarc 2:2946f9eefcae 156 f += ddF_x;
skydarc 2:2946f9eefcae 157
skydarc 2:2946f9eefcae 158 if (cornername & 0x1) {
skydarc 2:2946f9eefcae 159 drawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
skydarc 2:2946f9eefcae 160 drawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
skydarc 2:2946f9eefcae 161 }
skydarc 2:2946f9eefcae 162 if (cornername & 0x2) {
skydarc 2:2946f9eefcae 163 drawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
skydarc 2:2946f9eefcae 164 drawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
skydarc 2:2946f9eefcae 165 }
skydarc 2:2946f9eefcae 166 }
skydarc 2:2946f9eefcae 167 }
skydarc 2:2946f9eefcae 168
skydarc 2:2946f9eefcae 169 // Bresenham's algorithm - thx wikpedia
skydarc 2:2946f9eefcae 170 void GFX::drawLine(int16_t x0, int16_t y0,
skydarc 2:2946f9eefcae 171 int16_t x1, int16_t y1,
skydarc 2:2946f9eefcae 172 uint16_t color) {
skydarc 2:2946f9eefcae 173 int16_t steep = abs(y1 - y0) > abs(x1 - x0);
skydarc 2:2946f9eefcae 174 if (steep) {
skydarc 2:2946f9eefcae 175 swap(x0, y0);
skydarc 2:2946f9eefcae 176 swap(x1, y1);
skydarc 2:2946f9eefcae 177 }
skydarc 2:2946f9eefcae 178
skydarc 2:2946f9eefcae 179 if (x0 > x1) {
skydarc 2:2946f9eefcae 180 swap(x0, x1);
skydarc 2:2946f9eefcae 181 swap(y0, y1);
skydarc 2:2946f9eefcae 182 }
skydarc 2:2946f9eefcae 183
skydarc 2:2946f9eefcae 184 int16_t dx, dy;
skydarc 2:2946f9eefcae 185 dx = x1 - x0;
skydarc 2:2946f9eefcae 186 dy = abs(y1 - y0);
skydarc 2:2946f9eefcae 187
skydarc 2:2946f9eefcae 188 int16_t err = dx / 2;
skydarc 2:2946f9eefcae 189 int16_t ystep;
skydarc 2:2946f9eefcae 190
skydarc 2:2946f9eefcae 191 if (y0 < y1) {
skydarc 2:2946f9eefcae 192 ystep = 1;
skydarc 2:2946f9eefcae 193 } else {
skydarc 2:2946f9eefcae 194 ystep = -1;
skydarc 2:2946f9eefcae 195 }
skydarc 2:2946f9eefcae 196
skydarc 2:2946f9eefcae 197 for (; x0<=x1; x0++) {
skydarc 2:2946f9eefcae 198 if (steep) {
skydarc 2:2946f9eefcae 199 drawPixel(y0, x0, color);
skydarc 2:2946f9eefcae 200 } else {
skydarc 2:2946f9eefcae 201 drawPixel(x0, y0, color);
skydarc 2:2946f9eefcae 202 }
skydarc 2:2946f9eefcae 203 err -= dy;
skydarc 2:2946f9eefcae 204 if (err < 0) {
skydarc 2:2946f9eefcae 205 y0 += ystep;
skydarc 2:2946f9eefcae 206 err += dx;
skydarc 2:2946f9eefcae 207 }
skydarc 2:2946f9eefcae 208 }
skydarc 2:2946f9eefcae 209 }
skydarc 2:2946f9eefcae 210
skydarc 2:2946f9eefcae 211 // Draw a rectangle
skydarc 2:2946f9eefcae 212 void GFX::drawRect(int16_t x, int16_t y,
skydarc 2:2946f9eefcae 213 int16_t w, int16_t h,
skydarc 2:2946f9eefcae 214 uint16_t color) {
skydarc 2:2946f9eefcae 215 drawFastHLine(x, y, w, color);
skydarc 2:2946f9eefcae 216 drawFastHLine(x, y+h-1, w, color);
skydarc 2:2946f9eefcae 217 drawFastVLine(x, y, h, color);
skydarc 2:2946f9eefcae 218 drawFastVLine(x+w-1, y, h, color);
skydarc 2:2946f9eefcae 219 }
skydarc 2:2946f9eefcae 220
skydarc 2:2946f9eefcae 221 void GFX::drawFastVLine(int16_t x, int16_t y,
skydarc 2:2946f9eefcae 222 int16_t h, uint16_t color) {
skydarc 2:2946f9eefcae 223 // Update in subclasses if desired!
skydarc 2:2946f9eefcae 224 drawLine(x, y, x, y+h-1, color);
skydarc 2:2946f9eefcae 225 }
skydarc 2:2946f9eefcae 226
skydarc 2:2946f9eefcae 227 void GFX::drawFastHLine(int16_t x, int16_t y,
skydarc 2:2946f9eefcae 228 int16_t w, uint16_t color) {
skydarc 2:2946f9eefcae 229 // Update in subclasses if desired!
skydarc 2:2946f9eefcae 230 drawLine(x, y, x+w-1, y, color);
skydarc 2:2946f9eefcae 231 }
skydarc 2:2946f9eefcae 232
skydarc 2:2946f9eefcae 233 void GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
skydarc 2:2946f9eefcae 234 uint16_t color) {
skydarc 2:2946f9eefcae 235 // Update in subclasses if desired!
skydarc 2:2946f9eefcae 236 for (int16_t i=x; i<x+w; i++) {
skydarc 2:2946f9eefcae 237 drawFastVLine(i, y, h, color);
skydarc 2:2946f9eefcae 238 }
skydarc 2:2946f9eefcae 239 }
skydarc 2:2946f9eefcae 240
skydarc 2:2946f9eefcae 241 void GFX::fillScreen(uint16_t color) {
skydarc 2:2946f9eefcae 242 fillRect(-10, -10, _width+20, _height+20, color);
skydarc 2:2946f9eefcae 243 }
skydarc 2:2946f9eefcae 244
skydarc 2:2946f9eefcae 245 // Draw a rounded rectangle
skydarc 2:2946f9eefcae 246 void GFX::drawRoundRect(int16_t x, int16_t y, int16_t w,
skydarc 2:2946f9eefcae 247 int16_t h, int16_t r, uint16_t color) {
skydarc 2:2946f9eefcae 248 // smarter version
skydarc 2:2946f9eefcae 249 drawFastHLine(x+r , y , w-2*r, color); // Top
skydarc 2:2946f9eefcae 250 drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom
skydarc 2:2946f9eefcae 251 drawFastVLine(x , y+r , h-2*r, color); // Left
skydarc 2:2946f9eefcae 252 drawFastVLine(x+w-1, y+r , h-2*r, color); // Right
skydarc 2:2946f9eefcae 253 // draw four corners
skydarc 2:2946f9eefcae 254 drawCircleHelper(x+r , y+r , r, 1, color);
skydarc 2:2946f9eefcae 255 drawCircleHelper(x+w-r-1, y+r , r, 2, color);
skydarc 2:2946f9eefcae 256 drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
skydarc 2:2946f9eefcae 257 drawCircleHelper(x+r , y+h-r-1, r, 8, color);
skydarc 2:2946f9eefcae 258 }
skydarc 2:2946f9eefcae 259
skydarc 2:2946f9eefcae 260 // Fill a rounded rectangle
skydarc 2:2946f9eefcae 261 void GFX::fillRoundRect(int16_t x, int16_t y, int16_t w,
skydarc 2:2946f9eefcae 262 int16_t h, int16_t r, uint16_t color) {
skydarc 2:2946f9eefcae 263 // smarter version
skydarc 2:2946f9eefcae 264 fillRect(x+r, y, w-2*r, h, color);
skydarc 2:2946f9eefcae 265
skydarc 2:2946f9eefcae 266 // draw four corners
skydarc 2:2946f9eefcae 267 fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
skydarc 2:2946f9eefcae 268 fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color);
skydarc 2:2946f9eefcae 269 }
skydarc 2:2946f9eefcae 270
skydarc 2:2946f9eefcae 271 // Draw a triangle
skydarc 2:2946f9eefcae 272 void GFX::drawTriangle(int16_t x0, int16_t y0,
skydarc 2:2946f9eefcae 273 int16_t x1, int16_t y1,
skydarc 2:2946f9eefcae 274 int16_t x2, int16_t y2, uint16_t color) {
skydarc 2:2946f9eefcae 275 drawLine(x0, y0, x1, y1, color);
skydarc 2:2946f9eefcae 276 drawLine(x1, y1, x2, y2, color);
skydarc 2:2946f9eefcae 277 drawLine(x2, y2, x0, y0, color);
skydarc 2:2946f9eefcae 278 }
skydarc 2:2946f9eefcae 279
skydarc 2:2946f9eefcae 280 // Fill a triangle
skydarc 2:2946f9eefcae 281 void GFX::fillTriangle ( int16_t x0, int16_t y0,
skydarc 2:2946f9eefcae 282 int16_t x1, int16_t y1,
skydarc 2:2946f9eefcae 283 int16_t x2, int16_t y2, uint16_t color) {
skydarc 2:2946f9eefcae 284
skydarc 2:2946f9eefcae 285 int16_t a, b, y, last;
skydarc 2:2946f9eefcae 286
skydarc 2:2946f9eefcae 287 // Sort coordinates by Y order (y2 >= y1 >= y0)
skydarc 2:2946f9eefcae 288 if (y0 > y1) {
skydarc 2:2946f9eefcae 289 swap(y0, y1); swap(x0, x1);
skydarc 2:2946f9eefcae 290 }
skydarc 2:2946f9eefcae 291 if (y1 > y2) {
skydarc 2:2946f9eefcae 292 swap(y2, y1); swap(x2, x1);
skydarc 2:2946f9eefcae 293 }
skydarc 2:2946f9eefcae 294 if (y0 > y1) {
skydarc 2:2946f9eefcae 295 swap(y0, y1); swap(x0, x1);
skydarc 2:2946f9eefcae 296 }
skydarc 2:2946f9eefcae 297
skydarc 2:2946f9eefcae 298 if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
skydarc 2:2946f9eefcae 299 a = b = x0;
skydarc 2:2946f9eefcae 300 if(x1 < a) a = x1;
skydarc 2:2946f9eefcae 301 else if(x1 > b) b = x1;
skydarc 2:2946f9eefcae 302 if(x2 < a) a = x2;
skydarc 2:2946f9eefcae 303 else if(x2 > b) b = x2;
skydarc 2:2946f9eefcae 304 drawFastHLine(a, y0, b-a+1, color);
skydarc 2:2946f9eefcae 305 return;
skydarc 2:2946f9eefcae 306 }
skydarc 2:2946f9eefcae 307
skydarc 2:2946f9eefcae 308 int16_t
skydarc 2:2946f9eefcae 309 dx01 = x1 - x0,
skydarc 2:2946f9eefcae 310 dy01 = y1 - y0,
skydarc 2:2946f9eefcae 311 dx02 = x2 - x0,
skydarc 2:2946f9eefcae 312 dy02 = y2 - y0,
skydarc 2:2946f9eefcae 313 dx12 = x2 - x1,
skydarc 2:2946f9eefcae 314 dy12 = y2 - y1;
skydarc 2:2946f9eefcae 315 int32_t
skydarc 2:2946f9eefcae 316 sa = 0,
skydarc 2:2946f9eefcae 317 sb = 0;
skydarc 2:2946f9eefcae 318
skydarc 2:2946f9eefcae 319 // For upper part of triangle, find scanline crossings for segments
skydarc 2:2946f9eefcae 320 // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
skydarc 2:2946f9eefcae 321 // is included here (and second loop will be skipped, avoiding a /0
skydarc 2:2946f9eefcae 322 // error there), otherwise scanline y1 is skipped here and handled
skydarc 2:2946f9eefcae 323 // in the second loop...which also avoids a /0 error here if y0=y1
skydarc 2:2946f9eefcae 324 // (flat-topped triangle).
skydarc 2:2946f9eefcae 325 if(y1 == y2) last = y1; // Include y1 scanline
skydarc 2:2946f9eefcae 326 else last = y1-1; // Skip it
skydarc 2:2946f9eefcae 327
skydarc 2:2946f9eefcae 328 for(y=y0; y<=last; y++) {
skydarc 2:2946f9eefcae 329 a = x0 + sa / dy01;
skydarc 2:2946f9eefcae 330 b = x0 + sb / dy02;
skydarc 2:2946f9eefcae 331 sa += dx01;
skydarc 2:2946f9eefcae 332 sb += dx02;
skydarc 2:2946f9eefcae 333 /* longhand:
skydarc 2:2946f9eefcae 334 a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
skydarc 2:2946f9eefcae 335 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
skydarc 2:2946f9eefcae 336 */
skydarc 2:2946f9eefcae 337 if(a > b) swap(a,b);
skydarc 2:2946f9eefcae 338 drawFastHLine(a, y, b-a+1, color);
skydarc 2:2946f9eefcae 339 }
skydarc 2:2946f9eefcae 340
skydarc 2:2946f9eefcae 341 // For lower part of triangle, find scanline crossings for segments
skydarc 2:2946f9eefcae 342 // 0-2 and 1-2. This loop is skipped if y1=y2.
skydarc 2:2946f9eefcae 343 sa = dx12 * (y - y1);
skydarc 2:2946f9eefcae 344 sb = dx02 * (y - y0);
skydarc 2:2946f9eefcae 345 for(; y<=y2; y++) {
skydarc 2:2946f9eefcae 346 a = x1 + sa / dy12;
skydarc 2:2946f9eefcae 347 b = x0 + sb / dy02;
skydarc 2:2946f9eefcae 348 sa += dx12;
skydarc 2:2946f9eefcae 349 sb += dx02;
skydarc 2:2946f9eefcae 350 /* longhand:
skydarc 2:2946f9eefcae 351 a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
skydarc 2:2946f9eefcae 352 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
skydarc 2:2946f9eefcae 353 */
skydarc 2:2946f9eefcae 354 if(a > b) swap(a,b);
skydarc 2:2946f9eefcae 355 drawFastHLine(a, y, b-a+1, color);
skydarc 2:2946f9eefcae 356 }
skydarc 2:2946f9eefcae 357 }
skydarc 2:2946f9eefcae 358
skydarc 2:2946f9eefcae 359 void GFX::drawBitmap(int16_t x, int16_t y,
skydarc 2:2946f9eefcae 360 const uint8_t *bitmap, int16_t w, int16_t h,
skydarc 2:2946f9eefcae 361 uint16_t color) {
skydarc 2:2946f9eefcae 362
skydarc 2:2946f9eefcae 363 int16_t i, j, byteWidth = (w + 7) / 8;
skydarc 2:2946f9eefcae 364
skydarc 2:2946f9eefcae 365 for(j=0; j<h; j++) {
skydarc 2:2946f9eefcae 366 for(i=0; i<w; i++ ) {
skydarc 2:2946f9eefcae 367 if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
skydarc 2:2946f9eefcae 368 drawPixel(x+i, y+j, color);
skydarc 2:2946f9eefcae 369 }
skydarc 2:2946f9eefcae 370 }
skydarc 2:2946f9eefcae 371 }
skydarc 2:2946f9eefcae 372 }
skydarc 2:2946f9eefcae 373
skydarc 2:2946f9eefcae 374 // Draw a 1-bit color bitmap at the specified x, y position from the
skydarc 2:2946f9eefcae 375 // provided bitmap buffer (must be PROGMEM memory) using color as the
skydarc 2:2946f9eefcae 376 // foreground color and bg as the background color.
skydarc 2:2946f9eefcae 377 void GFX::drawBitmap(int16_t x, int16_t y,
skydarc 2:2946f9eefcae 378 const uint8_t *bitmap, int16_t w, int16_t h,
skydarc 2:2946f9eefcae 379 uint16_t color, uint16_t bg) {
skydarc 2:2946f9eefcae 380
skydarc 2:2946f9eefcae 381 int16_t i, j, byteWidth = (w + 7) / 8;
skydarc 2:2946f9eefcae 382
skydarc 2:2946f9eefcae 383 for(j=0; j<h; j++) {
skydarc 2:2946f9eefcae 384 for(i=0; i<w; i++ ) {
skydarc 2:2946f9eefcae 385 if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
skydarc 2:2946f9eefcae 386 drawPixel(x+i, y+j, color);
skydarc 2:2946f9eefcae 387 }
skydarc 2:2946f9eefcae 388 else {
skydarc 2:2946f9eefcae 389 drawPixel(x+i, y+j, bg);
skydarc 2:2946f9eefcae 390 }
skydarc 2:2946f9eefcae 391 }
skydarc 2:2946f9eefcae 392 }
skydarc 2:2946f9eefcae 393 }
skydarc 2:2946f9eefcae 394
skydarc 2:2946f9eefcae 395 //Draw XBitMap Files (*.xbm), exported from GIMP,
skydarc 2:2946f9eefcae 396 //Usage: Export from GIMP to *.xbm, rename *.xbm to *.c and open in editor.
skydarc 2:2946f9eefcae 397 //C Array can be directly used with this function
skydarc 2:2946f9eefcae 398 void GFX::drawXBitmap(int16_t x, int16_t y,
skydarc 2:2946f9eefcae 399 const uint8_t *bitmap, int16_t w, int16_t h,
skydarc 2:2946f9eefcae 400 uint16_t color) {
skydarc 2:2946f9eefcae 401
skydarc 2:2946f9eefcae 402 int16_t i, j, byteWidth = (w + 7) / 8;
skydarc 2:2946f9eefcae 403
skydarc 2:2946f9eefcae 404 for(j=0; j<h; j++) {
skydarc 2:2946f9eefcae 405 for(i=0; i<w; i++ ) {
skydarc 2:2946f9eefcae 406 if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (1 << (i % 8))) {
skydarc 2:2946f9eefcae 407 drawPixel(x+i, y+j, color);
skydarc 2:2946f9eefcae 408 }
skydarc 2:2946f9eefcae 409 }
skydarc 2:2946f9eefcae 410 }
skydarc 2:2946f9eefcae 411 }
skydarc 2:2946f9eefcae 412
skydarc 2:2946f9eefcae 413
skydarc 2:2946f9eefcae 414 uint8_t GFX::write(uint8_t c) {
skydarc 2:2946f9eefcae 415
skydarc 2:2946f9eefcae 416 if (c == '\n') {
skydarc 2:2946f9eefcae 417 cursor_y += textsize*8;
skydarc 2:2946f9eefcae 418 cursor_x = 0;
skydarc 2:2946f9eefcae 419 } else if (c == '\r') {
skydarc 2:2946f9eefcae 420 // skip em
skydarc 2:2946f9eefcae 421 } else {
skydarc 2:2946f9eefcae 422 drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
skydarc 2:2946f9eefcae 423 cursor_x += textsize*6;
skydarc 2:2946f9eefcae 424 if (wrap && (cursor_x > (_width - textsize*6))) {
skydarc 2:2946f9eefcae 425 cursor_y += textsize*8;
skydarc 2:2946f9eefcae 426 cursor_x = 0;
skydarc 2:2946f9eefcae 427 }
skydarc 2:2946f9eefcae 428 }
skydarc 2:2946f9eefcae 429
skydarc 2:2946f9eefcae 430 return 1;
skydarc 2:2946f9eefcae 431
skydarc 2:2946f9eefcae 432 }
skydarc 2:2946f9eefcae 433
skydarc 2:2946f9eefcae 434 // Draw a character
skydarc 2:2946f9eefcae 435 void GFX::drawChar(int16_t x, int16_t y, unsigned char c,
skydarc 2:2946f9eefcae 436 uint16_t color, uint16_t bg, uint8_t size) {
skydarc 2:2946f9eefcae 437
skydarc 2:2946f9eefcae 438 if((x >= _width) || // Clip right
skydarc 2:2946f9eefcae 439 (y >= _height) || // Clip bottom
skydarc 2:2946f9eefcae 440 ((x + 6 * size - 1) < 0) || // Clip left
skydarc 2:2946f9eefcae 441 ((y + 8 * size - 1) < 0)) // Clip top
skydarc 2:2946f9eefcae 442 return;
skydarc 2:2946f9eefcae 443
skydarc 2:2946f9eefcae 444 for (int8_t i=0; i<6; i++ ) {
skydarc 2:2946f9eefcae 445 uint8_t line;
skydarc 2:2946f9eefcae 446 if (i == 5)
skydarc 2:2946f9eefcae 447 line = 0x0;
skydarc 2:2946f9eefcae 448 else
skydarc 2:2946f9eefcae 449 line = pgm_read_byte(font+(c*5)+i);
skydarc 2:2946f9eefcae 450 for (int8_t j = 0; j<8; j++) {
skydarc 2:2946f9eefcae 451 if (line & 0x1) {
skydarc 2:2946f9eefcae 452 if (size == 1) // default size
skydarc 2:2946f9eefcae 453 drawPixel(x+i, y+j, color);
skydarc 2:2946f9eefcae 454 else { // big size
skydarc 2:2946f9eefcae 455 fillRect(x+(i*size), y+(j*size), size, size, color);
skydarc 2:2946f9eefcae 456 }
skydarc 2:2946f9eefcae 457 } else if (bg != color) {
skydarc 2:2946f9eefcae 458 if (size == 1) // default size
skydarc 2:2946f9eefcae 459 drawPixel(x+i, y+j, bg);
skydarc 2:2946f9eefcae 460 else { // big size
skydarc 2:2946f9eefcae 461 fillRect(x+i*size, y+j*size, size, size, bg);
skydarc 2:2946f9eefcae 462 }
skydarc 2:2946f9eefcae 463 }
skydarc 2:2946f9eefcae 464 line >>= 1;
skydarc 2:2946f9eefcae 465 }
skydarc 2:2946f9eefcae 466 }
skydarc 2:2946f9eefcae 467 }
skydarc 2:2946f9eefcae 468
skydarc 2:2946f9eefcae 469 void GFX::setCursor(int16_t x, int16_t y) {
skydarc 2:2946f9eefcae 470 cursor_x = x;
skydarc 2:2946f9eefcae 471 cursor_y = y;
skydarc 2:2946f9eefcae 472 }
skydarc 2:2946f9eefcae 473
skydarc 2:2946f9eefcae 474 void GFX::setTextSize(uint8_t s) {
skydarc 2:2946f9eefcae 475 textsize = (s > 0) ? s : 1;
skydarc 2:2946f9eefcae 476 }
skydarc 2:2946f9eefcae 477
skydarc 2:2946f9eefcae 478 void GFX::setTextColor(uint16_t c) {
skydarc 2:2946f9eefcae 479 // For 'transparent' background, we'll set the bg
skydarc 2:2946f9eefcae 480 // to the same as fg instead of using a flag
skydarc 2:2946f9eefcae 481 textcolor = textbgcolor = c;
skydarc 2:2946f9eefcae 482 }
skydarc 2:2946f9eefcae 483
skydarc 2:2946f9eefcae 484 void GFX::setTextColor(uint16_t c, uint16_t b) {
skydarc 2:2946f9eefcae 485 textcolor = c;
skydarc 2:2946f9eefcae 486 textbgcolor = b;
skydarc 2:2946f9eefcae 487 }
skydarc 2:2946f9eefcae 488
skydarc 2:2946f9eefcae 489 void GFX::setTextWrap(bool w) {
skydarc 2:2946f9eefcae 490 wrap = w;
skydarc 2:2946f9eefcae 491 }
skydarc 2:2946f9eefcae 492
skydarc 2:2946f9eefcae 493 uint8_t GFX::getRotation(void) const {
skydarc 2:2946f9eefcae 494 return rotation;
skydarc 2:2946f9eefcae 495 }
skydarc 2:2946f9eefcae 496
skydarc 2:2946f9eefcae 497 void GFX::setRotation(uint8_t x) {
skydarc 2:2946f9eefcae 498 rotation = (x & 3);
skydarc 2:2946f9eefcae 499 switch(rotation) {
skydarc 2:2946f9eefcae 500 case 0:
skydarc 2:2946f9eefcae 501 case 2:
skydarc 2:2946f9eefcae 502 _width = WIDTH;
skydarc 2:2946f9eefcae 503 _height = HEIGHT;
skydarc 2:2946f9eefcae 504 break;
skydarc 2:2946f9eefcae 505 case 1:
skydarc 2:2946f9eefcae 506 case 3:
skydarc 2:2946f9eefcae 507 _width = HEIGHT;
skydarc 2:2946f9eefcae 508 _height = WIDTH;
skydarc 2:2946f9eefcae 509 break;
skydarc 2:2946f9eefcae 510 }
skydarc 2:2946f9eefcae 511 }
skydarc 2:2946f9eefcae 512
skydarc 2:2946f9eefcae 513 // Return the size of the display (per current rotation)
skydarc 2:2946f9eefcae 514 int16_t GFX::width(void) const {
skydarc 2:2946f9eefcae 515 return _width;
skydarc 2:2946f9eefcae 516 }
skydarc 2:2946f9eefcae 517
skydarc 2:2946f9eefcae 518 int16_t GFX::height(void) const {
skydarc 2:2946f9eefcae 519 return _height;
skydarc 2:2946f9eefcae 520 }
skydarc 2:2946f9eefcae 521
skydarc 2:2946f9eefcae 522 void GFX::invertDisplay(bool i) {
skydarc 2:2946f9eefcae 523 // Do nothing, must be subclassed if supported
skydarc 2:2946f9eefcae 524 }
skydarc 2:2946f9eefcae 525
skydarc 2:2946f9eefcae 526
skydarc 2:2946f9eefcae 527 //Methods from Print.cpp Arduino
skydarc 2:2946f9eefcae 528
skydarc 2:2946f9eefcae 529 uint8_t GFX::write(const uint8_t *buffer, uint8_t size)
skydarc 2:2946f9eefcae 530 {
skydarc 2:2946f9eefcae 531 uint8_t n = 0;
skydarc 2:2946f9eefcae 532 while (size--) {
skydarc 2:2946f9eefcae 533 n += write(*buffer++);
skydarc 2:2946f9eefcae 534 }
skydarc 2:2946f9eefcae 535 return n;
skydarc 2:2946f9eefcae 536 }
skydarc 2:2946f9eefcae 537
skydarc 2:2946f9eefcae 538 uint8_t GFX::print(const char str[])
skydarc 2:2946f9eefcae 539 {
skydarc 2:2946f9eefcae 540 return write(str);
skydarc 2:2946f9eefcae 541 }
skydarc 2:2946f9eefcae 542
skydarc 2:2946f9eefcae 543 uint8_t GFX::print(char c)
skydarc 2:2946f9eefcae 544 {
skydarc 2:2946f9eefcae 545 return write(c);
skydarc 2:2946f9eefcae 546 }
skydarc 2:2946f9eefcae 547
skydarc 2:2946f9eefcae 548 uint8_t GFX::print(unsigned char b, int base)
skydarc 2:2946f9eefcae 549 {
skydarc 2:2946f9eefcae 550 return print((unsigned long) b, base);
skydarc 2:2946f9eefcae 551 }
skydarc 2:2946f9eefcae 552
skydarc 2:2946f9eefcae 553 uint8_t GFX::print(int n, int base)
skydarc 2:2946f9eefcae 554 {
skydarc 2:2946f9eefcae 555 return print((long) n, base);
skydarc 2:2946f9eefcae 556 }
skydarc 2:2946f9eefcae 557
skydarc 2:2946f9eefcae 558 uint8_t GFX::print(unsigned int n, int base)
skydarc 2:2946f9eefcae 559 {
skydarc 2:2946f9eefcae 560 return print((unsigned long) n, base);
skydarc 2:2946f9eefcae 561 }
skydarc 2:2946f9eefcae 562
skydarc 2:2946f9eefcae 563 uint8_t GFX::print(long n, int base)
skydarc 2:2946f9eefcae 564 {
skydarc 2:2946f9eefcae 565 if (base == 0) {
skydarc 2:2946f9eefcae 566 return write(n);
skydarc 2:2946f9eefcae 567 } else if (base == 10) {
skydarc 2:2946f9eefcae 568 if (n < 0) {
skydarc 2:2946f9eefcae 569 int t = print('-');
skydarc 2:2946f9eefcae 570 n = -n;
skydarc 2:2946f9eefcae 571 return printNumber(n, 10) + t;
skydarc 2:2946f9eefcae 572 }
skydarc 2:2946f9eefcae 573 return printNumber(n, 10);
skydarc 2:2946f9eefcae 574 } else {
skydarc 2:2946f9eefcae 575 return printNumber(n, base);
skydarc 2:2946f9eefcae 576 }
skydarc 2:2946f9eefcae 577 }
skydarc 2:2946f9eefcae 578
skydarc 2:2946f9eefcae 579 uint8_t GFX::print(unsigned long n, int base)
skydarc 2:2946f9eefcae 580 {
skydarc 2:2946f9eefcae 581 if (base == 0) return write(n);
skydarc 2:2946f9eefcae 582 else return printNumber(n, base);
skydarc 2:2946f9eefcae 583 }
skydarc 2:2946f9eefcae 584
skydarc 2:2946f9eefcae 585 uint8_t GFX::print(double n, int digits)
skydarc 2:2946f9eefcae 586 {
skydarc 2:2946f9eefcae 587 return printFloat(n, digits);
skydarc 2:2946f9eefcae 588 }
skydarc 2:2946f9eefcae 589
skydarc 2:2946f9eefcae 590
skydarc 2:2946f9eefcae 591
skydarc 2:2946f9eefcae 592
skydarc 2:2946f9eefcae 593
skydarc 2:2946f9eefcae 594 uint8_t GFX::println(void)
skydarc 2:2946f9eefcae 595 {
skydarc 2:2946f9eefcae 596 size_t n = print('\r');
skydarc 2:2946f9eefcae 597 n += print('\n');
skydarc 2:2946f9eefcae 598 return n;
skydarc 2:2946f9eefcae 599 }
skydarc 2:2946f9eefcae 600
skydarc 2:2946f9eefcae 601
skydarc 2:2946f9eefcae 602
skydarc 2:2946f9eefcae 603 uint8_t GFX::println(const char c[])
skydarc 2:2946f9eefcae 604 {
skydarc 2:2946f9eefcae 605 size_t n = print(c);
skydarc 2:2946f9eefcae 606 n += println();
skydarc 2:2946f9eefcae 607 return n;
skydarc 2:2946f9eefcae 608 }
skydarc 2:2946f9eefcae 609
skydarc 2:2946f9eefcae 610 uint8_t GFX::println(char c)
skydarc 2:2946f9eefcae 611 {
skydarc 2:2946f9eefcae 612 size_t n = print(c);
skydarc 2:2946f9eefcae 613 n += println();
skydarc 2:2946f9eefcae 614 return n;
skydarc 2:2946f9eefcae 615 }
skydarc 2:2946f9eefcae 616
skydarc 2:2946f9eefcae 617 uint8_t GFX::println(unsigned char b, int numBase)
skydarc 2:2946f9eefcae 618 {
skydarc 2:2946f9eefcae 619 size_t n = print(b, numBase);
skydarc 2:2946f9eefcae 620 n += println();
skydarc 2:2946f9eefcae 621 return n;
skydarc 2:2946f9eefcae 622 }
skydarc 2:2946f9eefcae 623
skydarc 2:2946f9eefcae 624 uint8_t GFX::println(int num, int base)
skydarc 2:2946f9eefcae 625 {
skydarc 2:2946f9eefcae 626 size_t n = print(num, base);
skydarc 2:2946f9eefcae 627 n += println();
skydarc 2:2946f9eefcae 628 return n;
skydarc 2:2946f9eefcae 629 }
skydarc 2:2946f9eefcae 630
skydarc 2:2946f9eefcae 631 uint8_t GFX::println(unsigned int num, int base)
skydarc 2:2946f9eefcae 632 {
skydarc 2:2946f9eefcae 633 size_t n = print(num, base);
skydarc 2:2946f9eefcae 634 n += println();
skydarc 2:2946f9eefcae 635 return n;
skydarc 2:2946f9eefcae 636 }
skydarc 2:2946f9eefcae 637
skydarc 2:2946f9eefcae 638 uint8_t GFX::println(long num, int base)
skydarc 2:2946f9eefcae 639 {
skydarc 2:2946f9eefcae 640 size_t n = print(num, base);
skydarc 2:2946f9eefcae 641 n += println();
skydarc 2:2946f9eefcae 642 return n;
skydarc 2:2946f9eefcae 643 }
skydarc 2:2946f9eefcae 644
skydarc 2:2946f9eefcae 645 uint8_t GFX::println(unsigned long num, int base)
skydarc 2:2946f9eefcae 646 {
skydarc 2:2946f9eefcae 647 size_t n = print(num, base);
skydarc 2:2946f9eefcae 648 n += println();
skydarc 2:2946f9eefcae 649 return n;
skydarc 2:2946f9eefcae 650 }
skydarc 2:2946f9eefcae 651
skydarc 2:2946f9eefcae 652 uint8_t GFX::println(double num, int digits)
skydarc 2:2946f9eefcae 653 {
skydarc 2:2946f9eefcae 654 size_t n = print(num, digits);
skydarc 2:2946f9eefcae 655 n += println();
skydarc 2:2946f9eefcae 656 return n;
skydarc 2:2946f9eefcae 657 }
skydarc 2:2946f9eefcae 658
skydarc 2:2946f9eefcae 659
skydarc 2:2946f9eefcae 660
skydarc 2:2946f9eefcae 661 // Private Methods /////////////////////////////////////////////////////////////
skydarc 2:2946f9eefcae 662
skydarc 2:2946f9eefcae 663 uint8_t GFX::printNumber(unsigned long n, uint8_t base) {
skydarc 2:2946f9eefcae 664 char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
skydarc 2:2946f9eefcae 665 char *str = &buf[sizeof(buf) - 1];
skydarc 2:2946f9eefcae 666
skydarc 2:2946f9eefcae 667 *str = '\0';
skydarc 2:2946f9eefcae 668
skydarc 2:2946f9eefcae 669 // prevent crash if called with base == 1
skydarc 2:2946f9eefcae 670 if (base < 2) base = 10;
skydarc 2:2946f9eefcae 671
skydarc 2:2946f9eefcae 672 do {
skydarc 2:2946f9eefcae 673 unsigned long m = n;
skydarc 2:2946f9eefcae 674 n /= base;
skydarc 2:2946f9eefcae 675 char c = m - base * n;
skydarc 2:2946f9eefcae 676 *--str = c < 10 ? c + '0' : c + 'A' - 10;
skydarc 2:2946f9eefcae 677 } while(n);
skydarc 2:2946f9eefcae 678
skydarc 2:2946f9eefcae 679 return write(str);
skydarc 2:2946f9eefcae 680 }
skydarc 2:2946f9eefcae 681
skydarc 2:2946f9eefcae 682 uint8_t GFX::printFloat(double number, uint8_t digits)
skydarc 2:2946f9eefcae 683 {
skydarc 2:2946f9eefcae 684 uint8_t n = 0;
skydarc 2:2946f9eefcae 685
skydarc 2:2946f9eefcae 686 if (isnan(number)) return print("nan");
skydarc 2:2946f9eefcae 687 if (isinf(number)) return print("inf");
skydarc 2:2946f9eefcae 688 if (number > 4294967040.0) return print ("ovf"); // constant determined empirically
skydarc 2:2946f9eefcae 689 if (number <-4294967040.0) return print ("ovf"); // constant determined empirically
skydarc 2:2946f9eefcae 690
skydarc 2:2946f9eefcae 691 // Handle negative numbers
skydarc 2:2946f9eefcae 692 if (number < 0.0)
skydarc 2:2946f9eefcae 693 {
skydarc 2:2946f9eefcae 694 n += print('-');
skydarc 2:2946f9eefcae 695 number = -number;
skydarc 2:2946f9eefcae 696 }
skydarc 2:2946f9eefcae 697
skydarc 2:2946f9eefcae 698 // Round correctly so that print(1.999, 2) prints as "2.00"
skydarc 2:2946f9eefcae 699 double rounding = 0.5;
skydarc 2:2946f9eefcae 700 for (uint8_t i=0; i<digits; ++i)
skydarc 2:2946f9eefcae 701 rounding /= 10.0;
skydarc 2:2946f9eefcae 702
skydarc 2:2946f9eefcae 703 number += rounding;
skydarc 2:2946f9eefcae 704
skydarc 2:2946f9eefcae 705 // Extract the integer part of the number and print it
skydarc 2:2946f9eefcae 706 unsigned long int_part = (unsigned long)number;
skydarc 2:2946f9eefcae 707 double remainder = number - (double)int_part;
skydarc 2:2946f9eefcae 708 n += print(int_part);
skydarc 2:2946f9eefcae 709
skydarc 2:2946f9eefcae 710 // Print the decimal point, but only if there are digits beyond
skydarc 2:2946f9eefcae 711 if (digits > 0) {
skydarc 2:2946f9eefcae 712 n += print(".");
skydarc 2:2946f9eefcae 713 }
skydarc 2:2946f9eefcae 714
skydarc 2:2946f9eefcae 715 // Extract digits from the remainder one at a time
skydarc 2:2946f9eefcae 716 while (digits-- > 0)
skydarc 2:2946f9eefcae 717 {
skydarc 2:2946f9eefcae 718 remainder *= 10.0;
skydarc 2:2946f9eefcae 719 int toPrint = int(remainder);
skydarc 2:2946f9eefcae 720 n += print(toPrint);
skydarc 2:2946f9eefcae 721 remainder -= toPrint;
skydarc 2:2946f9eefcae 722 }
skydarc 2:2946f9eefcae 723
skydarc 2:2946f9eefcae 724 return n;
skydarc 2:2946f9eefcae 725 }
skydarc 2:2946f9eefcae 726
skydarc 2:2946f9eefcae 727