#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); }