Skip to content

Commit

Permalink
Data type overhaul. Added setNumberF()
Browse files Browse the repository at this point in the history
Now using stdint.h types. Other data types can be interpreted differently on different systems, leading to unexpected behaviour. E.g. 'char' being signed or unsigned.
I also removed floating point support for SevSeg.setNumber. Use SevSeg.setNumberF instead.
  • Loading branch information
DeanIsMe committed Feb 13, 2021
1 parent 00b8dc0 commit 5d8260a
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 115 deletions.
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,24 +103,23 @@ If you wish to use more than 8 digits, increase MAXNUMDIGITS in SevSeg.h.


### Setting a number

#### Integer
```c++
sevseg.setNumber(3141,3); // Displays '3.141'
```

The first argument is the number to display. The second argument indicates where the decimal place should be, counted from the least significant digit. E.g. to display an integer, the second argument is 0.
Floats are supported. In this case, the second argument indicates how many decimal places of precision you want to display. E.g:

#### Floating point
```c++
sevseg.setNumber(3.14159f,3); //Displays '3.141'
sevseg.setNumberF(3.14159f,3); //Displays '3.141'
```
Floats are supported. In this case, the second argument indicates how many decimal places of precision you want to display.

Out of range numbers are shown as '----'.

If the second argument is -1 or omitted, there will be no decimal place.

Enter 'true' as the third agument to display the number in hexadecimal representation.
Note that:

- Out of range numbers are shown as '----'.
- If the second argument is -1 or omitted, there will be no decimal place.
- Enter 'true' as the third argument to display the number in hexadecimal representation (instead of decimal)

### Setting a character string

Expand Down
131 changes: 55 additions & 76 deletions SevSeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#define ASTERISK_IDX 39
#define UNDERSCORE_IDX 40

static const long powersOf10[] = {
static const int32_t powersOf10[] = {
1, // 10^0
10,
100,
Expand All @@ -30,7 +30,7 @@ static const long powersOf10[] = {
1000000000
}; // 10^9

static const long powersOf16[] = {
static const int32_t powersOf16[] = {
0x1, // 16^0
0x10,
0x100,
Expand All @@ -43,7 +43,7 @@ static const long powersOf16[] = {

// digitCodeMap indicate which segments must be illuminated to display
// each number.
static const byte digitCodeMap[] = {
static const uint8_t digitCodeMap[] = {
// GFEDCBA Segments 7-segment map:
B00111111, // 0 "0" AAA
B00000110, // 1 "1" F B
Expand Down Expand Up @@ -89,8 +89,8 @@ static const byte digitCodeMap[] = {
};

// Constant pointers to constant data
const byte * const numeralCodes = digitCodeMap;
const byte * const alphaCodes = digitCodeMap + 10;
const uint8_t * const numeralCodes = digitCodeMap;
const uint8_t * const alphaCodes = digitCodeMap + 10;

// SevSeg Constructor
/******************************************************************************/
Expand All @@ -117,8 +117,8 @@ SevSeg::SevSeg() {
// leadingZerosIn indicates whether leading zeros should be displayed
// disableDecPoint is true when the decimal point segment is not connected, in
// which case there are only 7 segments.
void SevSeg::begin(byte hardwareConfig, byte numDigitsIn, const byte digitPinsIn[],
const byte segmentPinsIn[], bool resOnSegmentsIn,
void SevSeg::begin(uint8_t hardwareConfig, uint8_t numDigitsIn, const uint8_t digitPinsIn[],
const uint8_t segmentPinsIn[], bool resOnSegmentsIn,
bool updateWithDelaysIn, bool leadingZerosIn, bool disableDecPoint) {

resOnSegments = resOnSegmentsIn;
Expand Down Expand Up @@ -167,21 +167,21 @@ void SevSeg::begin(byte hardwareConfig, byte numDigitsIn, const byte digitPinsIn
}

// Save the input pin numbers to library variables
for (byte segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {
for (uint8_t segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {
segmentPins[segmentNum] = segmentPinsIn[segmentNum];
}

for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) {
for (uint8_t digitNum = 0 ; digitNum < numDigits ; digitNum++) {
digitPins[digitNum] = digitPinsIn[digitNum];
}

// Set the pins as outputs, and turn them off
for (byte digit = 0 ; digit < numDigits ; digit++) {
for (uint8_t digit = 0 ; digit < numDigits ; digit++) {
pinMode(digitPins[digit], OUTPUT);
digitalWrite(digitPins[digit], digitOffVal);
}

for (byte segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {
for (uint8_t segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {
pinMode(segmentPins[segmentNum], OUTPUT);
digitalWrite(segmentPins[segmentNum], segmentOffVal);
}
Expand Down Expand Up @@ -211,14 +211,14 @@ void SevSeg::begin(byte hardwareConfig, byte numDigitsIn, const byte digitPinsIn
void SevSeg::refreshDisplay() {

if (!updateWithDelays) {
unsigned long us = micros();
uint32_t us = micros();

// Exit if it's not time for the next display change
if (waitOffActive) {
if (us - prevUpdateTime < waitOffTime) return;
if ((int32_t)(us - prevUpdateTime) < waitOffTime) return;
}
else {
if (us - prevUpdateTime < ledOnTime) return;
if ((int32_t)(us - prevUpdateTime) < ledOnTime) return;
}
prevUpdateTime = us;

Expand Down Expand Up @@ -276,7 +276,7 @@ void SevSeg::refreshDisplay() {
if (!resOnSegments) {
/**********************************************/
// RESISTORS ON DIGITS, UPDATE WITH DELAYS
for (byte segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {
for (uint8_t segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {

// Illuminate the required digits for this segment
segmentOn(segmentNum);
Expand All @@ -294,7 +294,7 @@ void SevSeg::refreshDisplay() {
else {
/**********************************************/
// RESISTORS ON SEGMENTS, UPDATE WITH DELAYS
for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) {
for (uint8_t digitNum = 0 ; digitNum < numDigits ; digitNum++) {

// Illuminate the required segments for this digit
digitOn(digitNum);
Expand All @@ -316,9 +316,9 @@ void SevSeg::refreshDisplay() {
/******************************************************************************/
// Turns a segment on, as well as all corresponding digit pins
// (according to digitCodes[])
void SevSeg::segmentOn(byte segmentNum) {
void SevSeg::segmentOn(uint8_t segmentNum) {
digitalWrite(segmentPins[segmentNum], segmentOnVal);
for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) {
for (uint8_t digitNum = 0 ; digitNum < numDigits ; digitNum++) {
if (digitCodes[digitNum] & (1 << segmentNum)) { // Check a single bit
digitalWrite(digitPins[digitNum], digitOnVal);
}
Expand All @@ -328,8 +328,8 @@ void SevSeg::segmentOn(byte segmentNum) {
// segmentOff
/******************************************************************************/
// Turns a segment off, as well as all digit pins
void SevSeg::segmentOff(byte segmentNum) {
for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) {
void SevSeg::segmentOff(uint8_t segmentNum) {
for (uint8_t digitNum = 0 ; digitNum < numDigits ; digitNum++) {
digitalWrite(digitPins[digitNum], digitOffVal);
}
digitalWrite(segmentPins[segmentNum], segmentOffVal);
Expand All @@ -339,9 +339,9 @@ void SevSeg::segmentOff(byte segmentNum) {
/******************************************************************************/
// Turns a digit on, as well as all corresponding segment pins
// (according to digitCodes[])
void SevSeg::digitOn(byte digitNum) {
void SevSeg::digitOn(uint8_t digitNum) {
digitalWrite(digitPins[digitNum], digitOnVal);
for (byte segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {
for (uint8_t segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {
if (digitCodes[digitNum] & (1 << segmentNum)) { // Check a single bit
digitalWrite(segmentPins[segmentNum], segmentOnVal);
}
Expand All @@ -351,8 +351,8 @@ void SevSeg::digitOn(byte digitNum) {
// digitOff
/******************************************************************************/
// Turns a digit off, as well as all segment pins
void SevSeg::digitOff(byte digitNum) {
for (byte segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {
void SevSeg::digitOff(uint8_t digitNum) {
for (uint8_t segmentNum = 0 ; segmentNum < numSegments ; segmentNum++) {
digitalWrite(segmentPins[segmentNum], segmentOffVal);
}
digitalWrite(digitPins[digitNum], digitOffVal);
Expand All @@ -364,7 +364,7 @@ void SevSeg::digitOff(byte digitNum) {
// is 0 to 100. Flickering is more likely at brightness > 100, and < -100.
// A positive brightness introduces a delay while the LEDs are on, and a
// negative brightness introduces a delay while the LEDs are off.
void SevSeg::setBrightness(int brightness) {
void SevSeg::setBrightness(int16_t brightness) {
brightness = constrain(brightness, -200, 200);
if (brightness > 0) {
ledOnTime = map(brightness, 0, 100, 1, 2000);
Expand All @@ -380,52 +380,32 @@ void SevSeg::setBrightness(int brightness) {

// setNumber
/******************************************************************************/
// This function only receives the input and passes it to 'setNewNum'.
// It is overloaded for all number data types, so that floats can be handled
// correctly.
void SevSeg::setNumber(long numToShow, char decPlaces, bool hex) { //long
// Receives an integer and passes it to 'setNewNum'.
void SevSeg::setNumber(int32_t numToShow, int8_t decPlaces, bool hex) { //int32_t
setNewNum(numToShow, decPlaces, hex);
}

void SevSeg::setNumber(unsigned long numToShow, char decPlaces, bool hex) { //unsigned long
setNewNum(numToShow, decPlaces, hex);
}

void SevSeg::setNumber(int numToShow, char decPlaces, bool hex) { //int
setNewNum(numToShow, decPlaces, hex);
}

void SevSeg::setNumber(unsigned int numToShow, char decPlaces, bool hex) { //unsigned int
setNewNum(numToShow, decPlaces, hex);
}

void SevSeg::setNumber(char numToShow, char decPlaces, bool hex) { //char
setNewNum(numToShow, decPlaces, hex);
}

void SevSeg::setNumber(byte numToShow, char decPlaces, bool hex) { //byte
setNewNum(numToShow, decPlaces, hex);
}

void SevSeg::setNumber(float numToShow, char decPlaces, bool hex) { //float
char decPlacesPos = constrain(decPlaces, 0, MAXNUMDIGITS);
// setNumberF
/******************************************************************************/
// Receives a float, prepares it, and passes it to 'setNewNum'.
void SevSeg::setNumberF(float numToShow, int8_t decPlaces, bool hex) { //float
int8_t decPlacesPos = constrain(decPlaces, 0, MAXNUMDIGITS);
if (hex) {
numToShow = numToShow * powersOf16[decPlacesPos];
}
else {
numToShow = numToShow * powersOf10[decPlacesPos];
}
// Modify the number so that it is rounded to an integer correctly
numToShow += (numToShow >= 0) ? 0.5f : -0.5f;
setNewNum(numToShow, decPlaces, hex);
numToShow += (numToShow >= 0.f) ? 0.5f : -0.5f;
setNewNum((int32_t)numToShow, (int8_t)decPlaces, hex);
}


// setNewNum
/******************************************************************************/
// Changes the number that will be displayed.
void SevSeg::setNewNum(long numToShow, char decPlaces, bool hex) {
byte digits[MAXNUMDIGITS];
void SevSeg::setNewNum(int32_t numToShow, int8_t decPlaces, bool hex) {
uint8_t digits[MAXNUMDIGITS];
findDigits(numToShow, decPlaces, hex, digits);
setDigitCodes(digits, decPlaces);
}
Expand All @@ -447,8 +427,8 @@ void SevSeg::setNewNum(long numToShow, char decPlaces, bool hex) {
// E C 4 2
// E C 4 2 (Segment H is often called
// DDDD H 3333 7 DP, for Decimal Point)
void SevSeg::setSegments(const byte segs[]) {
for (byte digit = 0; digit < numDigits; digit++) {
void SevSeg::setSegments(const uint8_t segs[]) {
for (uint8_t digit = 0; digit < numDigits; digit++) {
digitCodes[digit] = segs[digit];
}
}
Expand All @@ -461,8 +441,8 @@ void SevSeg::setSegments(const byte segs[]) {
// only some digits.
// See setSegments() for bit-segment mapping
//
void SevSeg::getSegments(byte segs[]) {
for (byte digit = 0; digit < numDigits; digit++) {
void SevSeg::getSegments(uint8_t segs[]) {
for (uint8_t digit = 0; digit < numDigits; digit++) {
segs[digit] = digitCodes[digit];
}
}
Expand All @@ -471,14 +451,14 @@ void SevSeg::getSegments(byte segs[]) {
/******************************************************************************/
// Displays the string on the display, as best as possible.
// Only alphanumeric characters plus '-' and ' ' are supported
void SevSeg::setChars(const char str[]) {
for (byte digit = 0; digit < numDigits; digit++) {
void SevSeg::setChars(const int8_t str[]) {
for (uint8_t digit = 0; digit < numDigits; digit++) {
digitCodes[digit] = 0;
}

byte strIdx = 0; // Current position within str[]
for (byte digitNum = 0; digitNum < numDigits; digitNum++) {
char ch = str[strIdx];
uint8_t strIdx = 0; // Current position within str[]
for (uint8_t digitNum = 0; digitNum < numDigits; digitNum++) {
int8_t ch = str[strIdx];
if (ch == '\0') break; // NULL string terminator
if (ch >= '0' && ch <= '9') { // Numerical
digitCodes[digitNum] = numeralCodes[ch - '0'];
Expand Down Expand Up @@ -518,7 +498,7 @@ void SevSeg::setChars(const char str[]) {
// blank
/******************************************************************************/
void SevSeg::blank(void) {
for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) {
for (uint8_t digitNum = 0 ; digitNum < numDigits ; digitNum++) {
digitCodes[digitNum] = digitCodeMap[BLANK_IDX];
}
segmentOff(0);
Expand All @@ -530,19 +510,19 @@ void SevSeg::blank(void) {
// Decides what each digit will display.
// Enforces the upper and lower limits on the number to be displayed.
// digits[] is an output
void SevSeg::findDigits(long numToShow, char decPlaces, bool hex, byte digits[]) {
const long * powersOfBase = hex ? powersOf16 : powersOf10;
const long maxNum = powersOfBase[numDigits] - 1;
const long minNum = -(powersOfBase[numDigits - 1] - 1);
void SevSeg::findDigits(int32_t numToShow, int8_t decPlaces, bool hex, uint8_t digits[]) {
const int32_t * powersOfBase = hex ? powersOf16 : powersOf10;
const int32_t maxNum = powersOfBase[numDigits] - 1;
const int32_t minNum = -(powersOfBase[numDigits - 1] - 1);

// If the number is out of range, just display dashes
if (numToShow > maxNum || numToShow < minNum) {
for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) {
for (uint8_t digitNum = 0 ; digitNum < numDigits ; digitNum++) {
digits[digitNum] = DASH_IDX;
}
}
else {
byte digitNum = 0;
uint8_t digitNum = 0;

// Convert all number to positive values
if (numToShow < 0) {
Expand All @@ -554,7 +534,7 @@ void SevSeg::findDigits(long numToShow, char decPlaces, bool hex, byte digits[])
// Find all digits for base's representation, starting with the most
// significant digit
for ( ; digitNum < numDigits ; digitNum++) {
long factor = powersOfBase[numDigits - 1 - digitNum];
int32_t factor = powersOfBase[numDigits - 1 - digitNum];
digits[digitNum] = numToShow / factor;
numToShow -= digits[digitNum] * factor;
}
Expand All @@ -580,11 +560,10 @@ void SevSeg::findDigits(long numToShow, char decPlaces, bool hex, byte digits[])
// setDigitCodes
/******************************************************************************/
// Sets the 'digitCodes' that are required to display the input numbers

void SevSeg::setDigitCodes(const byte digits[], char decPlaces) {
void SevSeg::setDigitCodes(const uint8_t digits[], int8_t decPlaces) {

// Set the digitCode for each digit in the display
for (byte digitNum = 0 ; digitNum < numDigits ; digitNum++) {
for (uint8_t digitNum = 0 ; digitNum < numDigits ; digitNum++) {
digitCodes[digitNum] = digitCodeMap[digits[digitNum]];
// Set the decimal point segment
if (decPlaces >= 0) {
Expand Down
Loading

0 comments on commit 5d8260a

Please sign in to comment.