NerfStatTrak/SegmentDisplay.cpp
2016-12-09 21:06:18 +01:00

193 lines
4.2 KiB
C++

#include "SegmentDisplayConfig.h"
#include "SegmentDisplay.h"
void SegmentDisplay::begin()
{
pinMode(latchPin, OUTPUT);
#if !defined(SDUseSPI)
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
digitalWrite(clockPin, LOW);
digitalWrite(dataPin, LOW);
#endif
writeDisplay(0, 0);
digitalWrite(latchPin, HIGH);
digitalWrite(latchPin, LOW);
digitalWrite(latchPin, HIGH);
#if defined(SDUseSPI)
SPI.begin();
#endif
#if defined(SDSerialDebug)
Serial.begin(9600);
Serial.print("SegmentDisplay::begin\n");
#endif
}
void SegmentDisplay::end()
{
#if defined(SDUseSPI)
SPI.end();
#endif
}
void SegmentDisplay::clear()
{
writeDisplay(0, 0);
}
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--)
{
writeDigit((byte)(value % 10), digitMask);
value /= 10;
digitMask <<= 1;
}
}
void SegmentDisplay::writeTextLeft(char const* value)
{
#if defined(SDSerialDebug)
Serial.print("SegmentDisplay::writeTextLeft: " + value + "\n");
#endif
byte digitMask = 1 << (digits - 1);
byte charIndex = 0;
while (charIndex < digits && value[charIndex] != '\0')
{
writeChar(value[charIndex], digitMask);
digitMask >>= 1;
charIndex++;
}
while (charIndex < digits)
{
writeDisplay(0, digitMask);
digitMask >>= 1;
charIndex++;
}
}
void SegmentDisplay::writeRaw(char const* value)
{
#if defined(SDSerialDebug)
Serial.print("SegmentDisplay::writeRaw: " + value + "\n");
#endif
byte digitMask = 1 << (digits - 1);
byte charIndex = 0;
while (charIndex < digits)
{
writeDisplay(value[charIndex], digitMask);
digitMask >>= 1;
charIndex++;
}
while (charIndex < digits)
{
writeDisplay(0, digitMask);
digitMask >>= 1;
charIndex++;
}
}
inline void SegmentDisplay::writeDigit(byte value, byte digitMask)
{
writeDisplay(pgm_read_byte_near(SDNumberSegments + value), digitMask);
}
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);
}
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);
}