Fixed character output

Added placeholders for centered/right-aligned text
Added text mode toggle for testing purposes
Added serial debug option
This commit is contained in:
Mark van Renswoude 2016-11-29 20:00:47 +01:00
parent 8cc217b168
commit b4e971cc4a
6 changed files with 219 additions and 86 deletions

View File

@ -1,11 +1,18 @@
#include "SegmentDisplay.h"
#define ASCIIUppercaseA 65
#define ASCIIUppercaseZ 90
SegmentDisplay* display;
char* text = new char[7];
void setup()
{
pinMode(2, INPUT_PULLUP);
pinMode(A3, INPUT);
display = new SegmentDisplay();
//display->setClockSpeed(4000000UL);
display->setClockPin(12);
@ -13,6 +20,14 @@ void setup()
display->setLatchPin(10);
display->setDigits(6);
display->begin();
text[0] = '\0';
text[1] = '\0';
text[2] = '\0';
text[3] = '\0';
text[4] = '\0';
text[5] = '\0';
text[6] = '\0';
}
unsigned long currentTime;
@ -20,21 +35,76 @@ unsigned long lastCounterTime = 0;
uint32_t counter = 0;
uint32_t delayValue;
bool showChars = true;
byte character = ASCIIUppercaseA - 1;
int buttonValue;
bool buttonDown = false;
unsigned long lastButtonChange = 0;
void loop()
{
currentTime = millis();
if (currentTime - lastCounterTime > 100UL)
buttonValue = digitalRead(2);
if (buttonValue == LOW)
{
counter++;
if (counter > 999999)
counter = 0;
lastCounterTime = currentTime;
delayValue = ((uint32_t)analogRead(A3) * 100);
display->setDigitDelayMicroseconds(delayValue);
if (!buttonDown && (currentTime - lastButtonChange) > 50)
{
buttonDown = true;
showChars = !showChars;
lastButtonChange = currentTime;
}
}
else
{
if (buttonDown && (currentTime - lastButtonChange) > 50)
{
buttonDown = false;
lastButtonChange = currentTime;
}
}
display->writeNumber(counter);
if (showChars)
{
if (lastCounterTime == 0 || currentTime - lastCounterTime > 250UL)
{
character++;
if (character > ASCIIUppercaseZ)
character = ASCIIUppercaseA;
lastCounterTime = currentTime;
delayValue = ((uint32_t)analogRead(A3) * 100);
display->setDigitDelayMicroseconds(delayValue);
}
for (byte c = 0; c < 6; c++)
{
if (character + c > ASCIIUppercaseZ)
text[c] = ' ';
else
text[c] = character + c;
}
display->writeTextLeft(text);
}
else
{
if (currentTime - lastCounterTime > 100UL)
{
counter++;
if (counter > 999999)
counter = 0;
lastCounterTime = currentTime;
delayValue = ((uint32_t)analogRead(A3) * 100);
display->setDigitDelayMicroseconds(delayValue);
}
display->writeNumber(counter);
}
}

View File

@ -23,6 +23,11 @@ void SegmentDisplay::begin()
#if defined(SDUseSPI)
SPI.begin();
#endif
#if defined(SDSerialDebug)
Serial.begin(9600);
Serial.print("SegmentDisplay::begin\n");
#endif
}
@ -36,6 +41,11 @@ void SegmentDisplay::end()
void SegmentDisplay::writeNumber(uint32_t value)
{
#if defined(SDSerialDebug)
String textValue = String(value);
Serial.print("SegmentDisplay::writeNumber: " + textValue + "\n");
#endif
byte digitMask = 1;
for (byte digit = digits; digit > 0; digit--)
@ -48,96 +58,113 @@ void SegmentDisplay::writeNumber(uint32_t value)
}
#define ASCIIZero 48
#define ASCIINine 57
#define ASCIIUppercaseA 65
#define ASCIIUppercaseZ 90
#define ASCIILowercaseA 97
#define ASCIILowercaseZ 122
void SegmentDisplay::writeText(char* value)
void SegmentDisplay::writeTextLeft(char* value)
{
byte digitMask = 1;
byte digit = digits;
byte charValue;
#if defined(SDSerialDebug)
Serial.print("SegmentDisplay::writeTextLeft: " + value + "\n");
#endif
while (digit > 0 && value != '\0')
byte digitMask = 1 << (digits - 1);
byte charIndex = 0;
while (charIndex < digits && value[charIndex] != '\0')
{
charValue = *value;
writeChar(value[charIndex], digitMask);
// Lowercase
if (charValue >= ASCIILowercaseA && charValue <= ASCIILowercaseZ)
writeDisplay(pgm_read_byte_near(SDCharacterSegments + (charValue - ASCIILowercaseA)), digitMask);
// Uppercase
else if (charValue >= ASCIIUppercaseA && charValue <= ASCIIUppercaseZ)
writeDisplay(pgm_read_byte_near(SDCharacterSegments + (charValue - ASCIIUppercaseA)), digitMask);
// Numbers
else if (charValue >= ASCIIZero && charValue <= ASCIINine)
writeDisplay(pgm_read_byte_near(SDNumberSegments + (charValue - ASCIIZero)), digitMask);
// Space / unknown
else
writeDisplay(0, digitMask);
digit--;
digitMask <<= 1;
value++;
digitMask >>= 1;
charIndex++;
}
while (digit > 0)
while (charIndex < digits)
{
writeDisplay(0, digitMask);
digit--;
digitMask <<= 1;
digitMask >>= 1;
charIndex++;
}
}
void SegmentDisplay::writeTextCenter(char* value)
{
}
void SegmentDisplay::writeTextRight(char* value)
{
}
inline void SegmentDisplay::writeDigit(byte value, byte digitMask)
{
writeDisplay(pgm_read_byte_near(SDNumberSegments + value), digitMask);
}
if (digitDelayMicroseconds > 1000)
inline void SegmentDisplay::writeChar(char value, byte digitMask)
{
// Lowercase
if (value >= ASCIILowercaseA && value <= ASCIILowercaseZ)
writeDisplay(pgm_read_byte_near(SDCharacterSegments + (value - ASCIILowercaseA)), digitMask);
// Uppercase
else if (value >= ASCIIUppercaseA && value <= ASCIIUppercaseZ)
writeDisplay(pgm_read_byte_near(SDCharacterSegments + (value - ASCIIUppercaseA)), digitMask);
// Numbers
else if (value >= ASCIIZero && value <= ASCIINine)
writeDisplay(pgm_read_byte_near(SDNumberSegments + (value - ASCIIZero)), digitMask);
// Space / unknown
else
writeDisplay(0, digitMask);
}
inline void SegmentDisplay::writeDisplay(byte segmentMask, byte digitMask)
{
// If no segments should be lit, clear the digit mask as well to prevent
// power leaking through (it's probably an issue in my circuit or with the
// specific displays I used, but it still makes sense to close both sides).
//
// Still push out the zeros though, if we don't the display will vary
// in brightness depending on what's on it.
if (segmentMask == 0)
digitMask = 0;
#if defined(SDSerialDebug)
String segmentValue = String(segmentMask);
String digitValue = String(digitMask);
Serial.print("SegmentDisplay::writeDisplay: " + segmentValue + " " + digitValue + "\n");
#endif
#if defined(SDUseSPI)
SPI.beginTransaction(SPISettings(clockSpeed, MSBFIRST, SPI_MODE0));
#if defined(SDPushSegmentsFirst)
SPI.transfer(segmentMask);
SPI.transfer(digitMask);
#else
SPI.transfer(digitMask);
SPI.transfer(segmentMask);
#endif
SPI.endTransaction();
#else
#if defined(SDPushSegmentsFirst)
shiftOut(dataPin, clockPin, MSBFIRST, segmentMask);
shiftOut(dataPin, clockPin, MSBFIRST, digitMask);
#else
shiftOut(dataPin, clockPin, MSBFIRST, digitMask);
shiftOut(dataPin, clockPin, MSBFIRST, segmentMask);
#endif
digitalWrite(latchPin, HIGH);
digitalWrite(latchPin, LOW);
#endif
#if defined(SPHandleLargeDelays)
if (digitDelayMicroseconds > 15000)
delay(digitDelayMicroseconds / 1000);
else
#endif
delayMicroseconds(digitDelayMicroseconds);
}
#if defined(SDUseSPI)
inline void SegmentDisplay::writeDisplay(byte segmentMask, byte digitMask)
{
SPI.beginTransaction(SPISettings(clockSpeed, MSBFIRST, SPI_MODE0));
#if defined(SDPushSegmentsFirst)
SPI.transfer(segmentMask);
SPI.transfer(digitMask);
#else
SPI.transfer(digitMask);
SPI.transfer(segmentMask);
#endif
SPI.endTransaction();
}
#else
inline void SegmentDisplay::writeDisplay(byte segmentMask, byte digitMask)
{
digitalWrite(latchPin, LOW);
#if defined(SDPushSegmentsFirst)
shiftOut(dataPin, clockPin, MSBFIRST, segmentMask);
shiftOut(dataPin, clockPin, MSBFIRST, digitMask);
#else
shiftOut(dataPin, clockPin, MSBFIRST, digitMask);
shiftOut(dataPin, clockPin, MSBFIRST, segmentMask);
#endif
digitalWrite(latchPin, HIGH);
}
#endif

View File

@ -29,7 +29,9 @@ class SegmentDisplay
void end();
void writeNumber(uint32_t value);
void writeText(char* value);
void writeTextLeft(char* value);
void writeTextCenter(char* value);
void writeTextRight(char* value);
byte getDigits() { return digits; }
void setDigits(byte value) { digits = value; }
@ -55,6 +57,8 @@ class SegmentDisplay
protected:
void writeDigit(byte value, byte digitMask);
void writeChar(char value, byte digitMask);
public:
void writeDisplay(byte characterMask, byte digitMask);
private:

View File

@ -13,6 +13,14 @@
#define SegmentG 64 // Middle
#define ASCIIZero 48
#define ASCIINine 57
#define ASCIIUppercaseA 65
#define ASCIIUppercaseZ 90
#define ASCIILowercaseA 97
#define ASCIILowercaseZ 122
const byte SDNumberSegments[10] PROGMEM =
{
/**
@ -162,7 +170,7 @@ const byte SDCharacterSegments[26] PROGMEM =
* | |
*
**/
SegmentB | SegmentC | SegmentD | SegmentF | SegmentG,
SegmentB | SegmentC | SegmentE | SegmentF | SegmentG,
/**
*

View File

@ -23,4 +23,28 @@
**/
//#define SDPushSegmentsFirst
/**
* Support large digit delays (> 15000 microseconds)
*
* If not defined, delayMicroseconds() will always be used,
* which is currently only accurate up to 16383, but it saves
* the cost of checking the value.
*
* If you want to delay the digits further, most likely
* for multiplexing demonstration purposes only, enable this
* to automatically fall back to delay().
**/
#define SPHandleLargeDelays
/**
* Debug output
*
* If defined, outputs a trace of every call using Serial.print.
* The performance cost is of course massive, you probably
* only want to enable this while debugging the library.
**/
//#define SDSerialDebug
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 KiB