My first Arduino class (my first class ever!), suitable for common cathode or common anode display types.
Displays hex digits 0..F, plus eight segment test patterns.
Up to eight custom patterns available, subject to recompilation.
Comments welcome.
SevenSegment.h
#include <WProgram.h>
const byte N_PATTERNS = 32;
const byte N_SEGMENTS = 8;
const byte MAX_DIGITS = 8;
class SevenSeg {
public:
void begin (byte commonCathode, // true for common cathode, false for common anode
unsigned long onTime, // segment on time in microseconds
const byte segmentPins[N_SEGMENTS],
byte nDigits, // number of digits
const byte digitPins [],
byte* display); // user's display file.
void update (void); // must be called at least once per "loop"
void setDP (byte dpPos); // sets the digit for decimal place
void setOnTime (unsigned long onTime) {segmentOnTime =onTime;}
void blankDisplay (void);
private:
byte segmentOn;
byte digitOn;
byte digits; // total number of digits
byte digit; // current digit
byte segment; // current segment
byte displayPattern;
byte mask;
unsigned long segmentTime;
unsigned long segmentOnTime;
byte segmentPin [N_SEGMENTS]; // pin numbers for segments
byte digitPin [MAX_DIGITS]; // pin numbers for anode/cathode
byte* displayFile;
byte dpDigit;
};
SevenSegment.cpp
#include <SevenSeg.h>
#define digitOff ((LOW + HIGH) - digitOn)
#define segmentOff ((LOW + HIGH) - segmentOn)
static const byte DP = 0x80;
static const byte patterns [N_PATTERNS] = {
0x3F, 0x06, 0x5B, 0x4F, // +ve logic segment patterns
0x66, 0x6D, 0x7D, 0x07,
0x7F, 0x67, 0x77, 0x7C,
0x39, 0x5E, 0x79, 0x71,
0x01, 0x02, 0x04, 0x08, // single segment test patterns.
0x10, 0x20, 0x40, 0x80}; //remaining codes all zero.
void SevenSeg::begin (boolean commonCathode,
unsigned long onTime,
const byte segmentPins[N_SEGMENTS],
byte nDigits,
const byte digs [],
byte* disp)
{
if (commonCathode) {
digitOn = LOW;
segmentOn = HIGH;
} else {
digitOn = HIGH;
segmentOn = LOW;
}
segmentOnTime = onTime;
for (int i = 0; i < N_SEGMENTS; i++)
segmentPin [i] = segmentPins [i];
digits = (nDigits > MAX_DIGITS) ? MAX_DIGITS : nDigits;
for (int i = 0; i < digits; i++) {
digitPin [i] = digs[i];
}
displayFile = disp;
for (int i = 0; i < digits; i++) {
pinMode (digitPin[i], OUTPUT);
}
for (int i = 0; i < N_SEGMENTS; i++) {
pinMode (segmentPin[i], OUTPUT);
}
blankDisplay ();
dpDigit = MAX_DIGITS; // default to no decimal place displayed
digit = 0;
segment = 0;
displayPattern = 0;
mask = 1;
segmentTime = 0;
}
void SevenSeg::blankDisplay (void)
{
for (int i = 0; i < digits; i++) {
digitalWrite (digitPin[i], digitOff);
}
for (int i = 0; i < N_SEGMENTS; i++) {
digitalWrite (segmentPin[i], segmentOff);
}
}
void SevenSeg::update (void)
{
unsigned long now = micros ();
if (now - segmentTime > segmentOnTime) {
segmentTime = now;
digitalWrite (segmentPin [segment], segmentOff);
segment++;
mask <<= 1;
if (segment >= N_SEGMENTS) {
segment = 0;
mask = 1;
digitalWrite (digitPin [digit], digitOff);
digit++;
if (digit >= digits) {
digit = 0;
}
displayPattern = patterns [displayFile [digit] & (N_PATTERNS-1)];
displayPattern |= (dpDigit == digit)? DP : 0;
digitalWrite (digitPin [digit], digitOn);
}
if (displayPattern & mask) {
digitalWrite (segmentPin[segment], segmentOn);
}
}
}
void SevenSeg::setDP (byte dpPos)
{
dpDigit = dpPos;
}
Simple example sketch:
#include <SevenSeg.h>
const byte segments [N_SEGMENTS] = {2, 3, 4, 5, 6, 7, 8, 9}; // pin numbers for segments
const byte digits [] = {10, 11, 12, 13}; // pin numbers for anode/cathode
byte displayFile [4];
SevenSeg myDisplay;
void setup ()
{
myDisplay.begin (false, 400L, segments, 4, digits, displayFile);
}
void loop ()
{
updateClock ();
myDisplay.update ();
}
const unsigned long countTime = 1000L;
void updateClock (void)
{
static byte seconds = 0;
static byte minutes = 0;
static unsigned long updateTime = 0;
unsigned long now = millis ();
if (now - updateTime > countTime) {
updateTime = now;
seconds++;
if (seconds >= 60) {
seconds = 0;
minutes++;
if (minutes >= 60) {
minutes = 0;
}
}
displayFile [0] = seconds % 10;
displayFile [1] = seconds / 10;
displayFile [2] = minutes % 10;
displayFile [3] = minutes / 10;
}
}