From bf34454a82d611c1c9c2829fc6b84b058d9dbe35 Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Mon, 26 Sep 2016 23:14:03 +0200 Subject: [PATCH] Added SegmentDisplay class based on circuits.io test code (untested) --- NerfStatTrek.ino | 10 +- lib/SegmentDisplay.cpp | 125 +++++++++++++++ lib/SegmentDisplay.h | 71 +++++++++ lib/SegmentDisplayChars.h | 312 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 514 insertions(+), 4 deletions(-) create mode 100644 lib/SegmentDisplay.cpp create mode 100644 lib/SegmentDisplay.h create mode 100644 lib/SegmentDisplayChars.h diff --git a/NerfStatTrek.ino b/NerfStatTrek.ino index 62a6aef..4b5c165 100644 --- a/NerfStatTrek.ino +++ b/NerfStatTrek.ino @@ -1,3 +1,5 @@ +#include "lib/SegmentDisplay.h" + const int PinBottom = 2; const int PinTop = 5; @@ -5,7 +7,7 @@ const int PinDigit3 = 3; const int PinDigit2 = 4; -void setup() +void setup() { pinMode(PinTop, OUTPUT); pinMode(PinBottom, OUTPUT); @@ -19,7 +21,7 @@ void setup() int lastTime = 0; bool top = true; -void loop() +void loop() { int currentTime = millis(); if (currentTime - lastTime > 1000) @@ -41,7 +43,7 @@ void loop() { digitalWrite(PinBottom, HIGH); delay(1); - digitalWrite(PinBottom, LOW); + digitalWrite(PinBottom, LOW); } digitalWrite(PinDigit3, LOW); @@ -50,6 +52,6 @@ void loop() digitalWrite(PinDigit2, HIGH); digitalWrite(PinBottom, HIGH); delay(1); - digitalWrite(PinBottom, LOW); + digitalWrite(PinBottom, LOW); digitalWrite(PinDigit2, LOW); } diff --git a/lib/SegmentDisplay.cpp b/lib/SegmentDisplay.cpp new file mode 100644 index 0000000..81b90bf --- /dev/null +++ b/lib/SegmentDisplay.cpp @@ -0,0 +1,125 @@ +#include "SegmentDisplay.h" + + +void SegmentDisplay::begin() +{ + #if !defined(SDSupportSPI) + pinMode(latchPin, OUTPUT); + pinMode(clockPin, OUTPUT); + pinMode(dataPin, OUTPUT); + + digitalWrite(clockPin, LOW); + digitalWrite(dataPin, LOW); + #endif + + digitalWrite(latchPin, HIGH); + digitalWrite(latchPin, LOW); + digitalWrite(latchPin, HIGH); + + #if defined(SDSupportSPI) + SPI.begin(); + //SPI.setClockDivider(SPI_CLOCK_DIV128); + #endif +} + + +void SegmentDisplay::end() +{ + #if defined(SDSupportSPI) + SPI.end(); + #endif +} + + +void SegmentDisplay::writeNumber(int value) +{ + unsigned char digitMask = 1; + + for (unsigned char digit = digits; digit > 0; digit--) + { + writeDigit((unsigned char)(value % 10), digitMask); + + value /= 10; + digitMask <<= 1; + } +} + + +#define ASCIIZero 48 +#define ASCIINine 57 +#define ASCIIUppercaseA 65 +#define ASCIIUppercaseZ 90 +#define ASCIILowercaseA 97 +#define ASCIILowercaseZ 122 + + +void SegmentDisplay::writeText(char* value) +{ + unsigned char digitMask = 1; + unsigned char digit = digits; + unsigned char charValue; + + while (digit > 0 && value != '\0') + { + charValue = *value; + + // Lowercase + if (charValue >= ASCIILowercaseA && charValue <= ASCIILowercaseZ) + writeDisplay(SDCharacterSegments[charValue - ASCIILowercaseA], digitMask); + + // Uppercase + else if (charValue >= ASCIIUppercaseA && charValue <= ASCIIUppercaseZ) + writeDisplay(SDCharacterSegments[charValue - ASCIIUppercaseA], digitMask); + + // Numbers + else if (charValue >= ASCIIZero && charValue <= ASCIINine) + writeDisplay(SDNumberSegments[charValue - ASCIIZero], digitMask); + + // Space / unknown + else + writeDisplay(0, digitMask); + + digit--; + digitMask <<= 1; + value++; + } + + while (digit > 0) + { + writeDisplay(0, digitMask); + + digit--; + digitMask <<= 1; + } +} + + +inline void SegmentDisplay::writeDigit(unsigned char value, unsigned char digitMask) +{ + writeDisplay(SDNumberSegments[value], digitMask); +} + + +#if defined(SDSupportSPI) + +inline void SegmentDisplay::writeDisplay(unsigned char characterMask, unsigned char digitMask) +{ + SPI.beginTransaction(SPISettings(clockSpeed, MSBFIRST, SPI_MODE0)); + SPI.transfer(characterMask); + SPI.transfer(digitMask); + SPI.endTransaction(); +} + +#else + +inline void SegmentDisplay::writeDisplay(unsigned char characterMask, unsigned char digitMask) +{ + digitalWrite(latchPin, LOW); + + shiftOut(dataPin, clockPin, MSBFIRST, characterMask); + shiftOut(dataPin, clockPin, MSBFIRST, digitMask); + + digitalWrite(latchPin, HIGH); +} + +#endif diff --git a/lib/SegmentDisplay.h b/lib/SegmentDisplay.h new file mode 100644 index 0000000..a4b96a0 --- /dev/null +++ b/lib/SegmentDisplay.h @@ -0,0 +1,71 @@ +#ifndef SegmentDisplay_h +#define SegmentDisplay_h + +#include "Arduino.h" +#include "SPI.h" + +#include "SegmentDisplayChars.h" + +/** + * Drives up to 8 digits using two 8-bit shift registers. + * + * Pushes out the segment bits first and the display selection + * second: connect the display select register first and chain the + * segment register to it's output. + * + * Least significant bit as defined in SegmentDisplayChars.h: + * - Last digit + * - Segment A +**/ + +// Comment to use shiftOut. Set clockPin and dataPin instead. +#define SDSupportSPI + + +class SegmentDisplay +{ + public: + void begin(); + void end(); + + void writeNumber(int value); + void writeText(char* value); + + int getDigits() { return digits; } + void setDigits(int value) { digits = value; } + + int getLatchPin() { return latchPin; } + void setLatchPin(int value) { latchPin = value; } + + #if defined(SDSupportSPI) + long getClockSpeed() { return clockSpeed; } + void setClockSpeed(long value) { clockSpeed = value; } + #endif + + #if !defined(SDSupportSPI) + int getClockPin() { return clockPin; } + void setClockPin(int value) { clockPin = value; } + + int getDataPin() { return dataPin; } + void setDataPin(int value) { dataPin = value; } + #endif + + protected: + void writeDigit(byte value, byte digitMask); + void writeDisplay(byte characterMask, byte digitMask); + + private: + int digits = 6; + int latchPin = SS; + + #if defined(SDSupportSPI) + long clockSpeed = 20000000; + #endif + + #if !defined(SDSupportSPI) + int clockPin = SCK; + int dataPin = MOSI; + #endif +}; + +#endif \ No newline at end of file diff --git a/lib/SegmentDisplayChars.h b/lib/SegmentDisplayChars.h new file mode 100644 index 0000000..fbc80cd --- /dev/null +++ b/lib/SegmentDisplayChars.h @@ -0,0 +1,312 @@ +#ifndef SegmentDisplayChars_h +#define SegmentDisplayChars_h + +#include "avr/pgmspace.h" + + +#define SegmentA 1 // Top +#define SegmentB 2 // Top right +#define SegmentC 4 // Bottom right +#define SegmentD 8 // Bottom +#define SegmentE 16 // Bottom left +#define SegmentF 32 // Top left +#define SegmentG 64 // Middle + + +const byte SDNumberSegments[10] PROGMEM = +{ + /** + * _ + * | | + * |_| + * + **/ + SegmentA | SegmentB | SegmentC | SegmentD | SegmentE | SegmentF, + + /** + * + * | + * | + * + **/ + SegmentB | SegmentC, + + /** + * _ + * _| + * |_ + * + **/ + SegmentA | SegmentB | SegmentD | SegmentE | SegmentG, + + /** + * _ + * _| + * _| + * + **/ + SegmentA | SegmentB | SegmentC | SegmentD | SegmentG, + + /** + * + * |_| + * | + * + **/ + SegmentB | SegmentC | SegmentF | SegmentG, + + /** + * _ + * |_ + * _| + * + **/ + SegmentA | SegmentC | SegmentD | SegmentF | SegmentG, + + /** + * _ + * |_ + * |_| + * + **/ + SegmentA | SegmentC | SegmentD | SegmentE | SegmentF | SegmentG, + + /** + * _ + * | + * | + * + **/ + SegmentA | SegmentB | SegmentC, + + /** + * _ + * |_| + * |_| + * + **/ + SegmentA | SegmentB | SegmentC | SegmentD | SegmentE | SegmentF | SegmentG, + + /** + * _ + * |_| + * _| + * + **/ + SegmentA | SegmentB | SegmentC | SegmentD | SegmentF | SegmentG +}; + + + +const byte SDCharacterSegments[26] PROGMEM = +{ + /** + * _ + * |_| + * | | + * + **/ + SegmentA | SegmentB | SegmentC | SegmentE | SegmentF | SegmentG, + + /** + * + * |_ + * |_| + * + **/ + SegmentC | SegmentD | SegmentE | SegmentF | SegmentG, + + /** + * _ + * | + * |_ + * + **/ + SegmentA | SegmentD | SegmentE | SegmentF, + + /** + * + * _| + * |_| + * + **/ + SegmentB | SegmentC | SegmentD | SegmentE | SegmentG, + + /** + * _ + * |_ + * |_ + * + **/ + SegmentA | SegmentD | SegmentE | SegmentF | SegmentG, + + /** + * _ + * |_ + * | + * + **/ + SegmentA | SegmentE | SegmentF | SegmentG, + + /** + * _ + * |_| + * _| + * + **/ + SegmentA | SegmentB | SegmentC | SegmentD | SegmentF | SegmentG, + + /** + * + * |_| + * | | + * + **/ + SegmentB | SegmentC | SegmentD | SegmentF | SegmentG, + + /** + * + * | + * | + * + **/ + SegmentE | SegmentF, + + /** + * + * | + * |_| + * + **/ + SegmentB | SegmentC | SegmentD | SegmentE, + + /** + * + * |_ + * | + * + **/ + SegmentE | SegmentF | SegmentG, + + /** + * + * | + * |_ + * + **/ + SegmentD | SegmentE | SegmentF, + + /** + * _ + * + * | | + * + **/ + SegmentA | SegmentC | SegmentE, + + /** + * + * _ + * | | + * + **/ + SegmentC | SegmentE | SegmentG, + + /** + * _ + * | | + * |_| + * + **/ + SegmentA | SegmentB | SegmentC | SegmentD | SegmentE | SegmentF, + + /** + * _ + * |_| + * | + * + **/ + SegmentA | SegmentB | SegmentE | SegmentF | SegmentG, + + /** + * _ + * |_| + * | + * + **/ + SegmentA | SegmentB | SegmentC | SegmentF | SegmentG, + + /** + * + * _ + * | + * + **/ + SegmentE | SegmentG, + + /** + * _ + * |_ + * _| + * + **/ + SegmentA | SegmentC | SegmentD | SegmentF | SegmentG, + + /** + * + * |_ + * |_ + * + **/ + SegmentD | SegmentE | SegmentF | SegmentG, + + /** + * + * | | + * |_| + * + **/ + SegmentB | SegmentC | SegmentD | SegmentE | SegmentF, + + /** + * + * + * |_| + * + **/ + SegmentC | SegmentD | SegmentE, + + /** + * + * | | + * _ + * + **/ + SegmentB | SegmentD | SegmentF, + + /** + * + * _| + * | + * + **/ + SegmentB | SegmentC | SegmentG, + + /** + * + * |_| + * _| + * + **/ + SegmentB | SegmentC | SegmentD | SegmentF | SegmentG, + + /** + * _ + * _| + * |_ + * + **/ + SegmentA | SegmentB | SegmentD | SegmentE | SegmentG +}; + +#endif