Mark van Renswoude
ba58eb93c0
- Button library - State handling and transitions - Default state: dual counter display - User unknown state: static for now - Lost the game state: static for now
173 lines
3.8 KiB
C++
173 lines
3.8 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::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* 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::writeTextCenter(char* value)
|
|
{
|
|
// TODO
|
|
}
|
|
|
|
|
|
void SegmentDisplay::writeTextRight(char* value)
|
|
{
|
|
// TODO
|
|
}
|
|
|
|
|
|
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);
|
|
}
|