Skip to content

Commit

Permalink
Float/Double neg # fixes by John Archie
Browse files Browse the repository at this point in the history
  • Loading branch information
ladyada committed Aug 9, 2012
1 parent 2b23a5e commit df75720
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 104 deletions.
164 changes: 63 additions & 101 deletions Adafruit_LEDBackpack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,16 @@
#include "Adafruit_GFX.h"

static const uint8_t numbertable[] = {
0x3F /* 0 */,
0x06 /* 1 */,
0x5B /* 2 */,
0x4F /* 3 */,
0x66 /* 4 */,
0x6D /* 5 */,
0x3F, /* 0 */
0x06, /* 1 */
0x5B, /* 2 */
0x4F, /* 3 */
0x66, /* 4 */
0x6D, /* 5 */
0x7D, /* 6 */
0x07, /* 7 */
0x7F, /* 8 */
0x6F, /* 9 */
};

const uint8_t alphatable[] = {
0x77, /* a */
0x7C, /* b */
0x39, /* C */
Expand Down Expand Up @@ -275,108 +272,73 @@ void Adafruit_7segment::writeDigitNum(uint8_t d, uint8_t num, boolean dot) {
writeDigitRaw(d, numbertable[num] | (dot << 7));
}

void Adafruit_7segment::writeDigitAlpha(uint8_t d, uint8_t alph, boolean dot) {
if (d > 4) return;

writeDigitRaw(d, alphatable[alph] | (dot << 7));
}

void Adafruit_7segment::print(long n, int base)
{
if (base == 0) {
write(n);
} else if (base == 10) {
if (n < 0) {
print('-');
n = -n;
}
printNumber(n, 10);
} else {
printNumber(n, base);
}
printNumber(n, base);
}


void Adafruit_7segment::printNumber(unsigned long n, uint8_t base)
void Adafruit_7segment::printNumber(long n, uint8_t base)
{
position = 0;
printFloat(n, 0, base);
}

unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
unsigned long i = 0;

if (n == 0) {
writeDigitRaw(0, 0x0);
writeDigitRaw(1, 0x0);
writeDigitRaw(2, 0x0);
writeDigitRaw(3, 0x0);
writeDigitNum(4, 0);
return;
}

while (n > 0) {
buf[i++] = n % base;
n /= base;
void Adafruit_7segment::printFloat(double n, uint8_t fracDigits, uint8_t base)
{
uint8_t numericDigits = 4; // available digits on display
boolean isNegative = false; // true if the number is negative

// is the number negative?
if(n < 0) {
isNegative = true; // need to draw sign later
--numericDigits; // the sign will take up one digit
n *= -1; // pretend the number is positive
}

// we have i digits

if (i > 4) { // too big!
Serial.println("too long");
writeDigitRaw(0, 0x40);
writeDigitRaw(1, 0x40);
writeDigitRaw(2, 0x00);
writeDigitRaw(3, 0x40);
writeDigitRaw(4, 0x40);
return;

// calculate the factor required to shift all fractional digits
// into the integer part of the number
double toIntFactor = 1.0;
for(int i = 0; i < fracDigits; ++i) toIntFactor *= base;

// create integer containing digits to display by applying
// shifting factor and rounding adjustment
uint32_t displayNumber = n * toIntFactor + 0.5;

// calculate upper bound on displayNumber given
// available digits on display
uint32_t tooBig = 1;
for(int i = 0; i < numericDigits; ++i) tooBig *= base;

// if displayNumber is too large, try fewer fractional digits
while(displayNumber >= tooBig) {
--fracDigits;
toIntFactor /= base;
displayNumber = n * toIntFactor + 0.5;
}
//Serial.println(i);

clear();

position = 4;
for (uint8_t n=0; n<i; n++) {
if (buf[n] < 10)
writeDigitNum(position, buf[n]);
else
writeDigitAlpha(position, buf[n] - 10);

position--;
if (position == 2) position--;

// did toIntFactor shift the decimal off the display?
if (toIntFactor < 1) {
printError();
} else {
// otherwise, display the number
int8_t displayPos = 4;

for(uint8_t i = 0; displayNumber; ++i) {
boolean displayDecimal = (fracDigits != 0 && i == fracDigits);
writeDigitNum(displayPos--, displayNumber % base, displayDecimal);
if(displayPos == 2) writeDigitRaw(displayPos--, 0x00);
displayNumber /= base;
}

// display negative sign if negative
if(isNegative) writeDigitRaw(displayPos--, 0x40);

// clear remaining display positions
while(displayPos >= 0) writeDigitRaw(displayPos--, 0x00);
}
position = 0;
}

void Adafruit_7segment::printFloat(double number, uint8_t digits)
{
// Handle negative numbers
if (number < 0.0)
{
print('-');
number = -number;
void Adafruit_7segment::printError(void) {
for(uint8_t i = 0; i < SEVENSEG_DIGITS; ++i) {
writeDigitRaw(i, (i == 2 ? 0x00 : 0x40));
}

// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
for (uint8_t i=0; i<digits; ++i)
rounding /= 10.0;

number += rounding;

// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
print(int_part);

// Print the decimal point, but only if there are digits beyond
if (digits > 0)
print('.');

// Extract digits from the remainder one at a time
while (digits-- > 0)
{
remainder *= 10.0;
int toPrint = int(remainder);
print(toPrint);
remainder -= toPrint;
}
}
9 changes: 6 additions & 3 deletions Adafruit_LEDBackpack.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@

#define HT16K33_CMD_BRIGHTNESS 0x0E

#define SEVENSEG_DIGITS 5


// this is the raw HT16K33 controller
class Adafruit_LEDBackpack {
public:
Expand Down Expand Up @@ -110,10 +113,10 @@ class Adafruit_7segment : public Adafruit_LEDBackpack {

void writeDigitRaw(uint8_t x, uint8_t bitmask);
void writeDigitNum(uint8_t x, uint8_t num, boolean dot = false);
void writeDigitAlpha(uint8_t x, uint8_t num, boolean dot = false);
void drawColon(boolean state);
void printNumber(unsigned long n, uint8_t base);
void printFloat(double number, uint8_t digits);
void printNumber(long, uint8_t = 2);
void printFloat(double, uint8_t = 2, uint8_t = DEC);
void printError(void);

private:
uint8_t position;
Expand Down

0 comments on commit df75720

Please sign in to comment.