The existing 7 segment or 8x8 matrix libraries have a lot of extra stuff and are difficult to do what I was suggesting. I have written a class Aclock (analog clock) to turn on the leds one at a time as they go abound the clock face. Here is the code with a simple sample of use.
/******************************************
*
* Aclock - A class to implement a class for analog clock parts
*
* This class considers the MAX7219 as a 64 les driver rather than as a display
* driver.
* The leds as considered as 8 groups of 8 leds which are individually addressable.
* The digit driver lines define the groups and the segment lines define the leds
* within the group.
*
************************************************/
// define Max7219 registers (note not all are used)
const uint8_t REG_GRP_BASE = 0x01;
const uint8_t REG_DECODE_MODE = 0x09;
const uint8_t REG_INTENSITY = 0x0A;
const uint8_t REG_SCAN_LIMIT = 0x0B;
const uint8_t REG_SHUTDOWN = 0x0C;
const uint8_t REG_TEST = 0x0F;
class Aclock {
public:
Aclock(){}; // constructor
// initializer
void begin(uint8_t clkPin,uint8_t dataPin,uint8_t loadPin,uint8_t maxCount);
void setLed(uint8_t ledNumber);
void clearDisplay();
void setIntensity(uint8_t intensity);
void setShutDown(bool mode);
private:
// minimize chances for user to screw up
Aclock (const Aclock& a); // disallow copy constructor
Aclock & operator=(const Aclock& a); // disallow assignment operator
void setReg(uint8_t reg_number);
void setData(uint8_t data);
void setZeros(); // data is all zeros
void setOnes(); //data is all setOnes
void setDecodeOff();
void setScanAll();
// object data
uint8_t clk_Pin;
uint8_t data_Pin;
uint8_t load_Pin;
uint8_t lastGroup; // last group used
}; // end Aclock class definition
// implementation
void Aclock::begin(uint8_t clkPin,uint8_t dataPin,uint8_t loadPin,uint8_t maxCount){
clk_Pin = clkPin;
data_Pin = dataPin;
load_Pin = loadPin;
pinMode(clk_Pin,OUTPUT);
pinMode(data_Pin,OUTPUT);
pinMode(load_Pin,OUTPUT);
lastGroup = maxCount >> 3; // divide by 8 to get the last group
setDecodeOff(); // no digit decode
setScanAll(); // use all groups
setIntensity(7); // set to half intensity
clearDisplay();
setShutDown(false); // start display
}
void Aclock::setLed(uint8_t ledNumber){
// set the led in the display and turn off previous ledNumber
// Since the group and segmant are both powers of 2 we can optimize
// calculating the group and segment
uint8_t previousGroup; // previous group used
uint8_t group = ledNumber >> 3; // same as divide by 8
uint8_t segment = ledNumber & 0x07; // same as remainder after divide by 8
if (segment == 0){
// we are starting a new group we need to turn off previous group
if (group == 0) {
// first group
previousGroup = lastGroup;
}else{
previousGroup = group-1;
}
setReg(previousGroup+REG_GRP_BASE );
setZeros(); // turnoff all segmants in previous group
}
setReg(group+REG_GRP_BASE); // select current group
setData(1<<segment); // select segment for led
}
void Aclock::clearDisplay(){
// set all groups/segment off
uint8_t i;
for(i = REG_GRP_BASE; i<REG_GRP_BASE+8;i++) {
// for all groups
setReg(i); // select group
setZeros(); // turn off all segments
}
}
void Aclock::setIntensity(uint8_t intensity) {
setReg(REG_INTENSITY);
setData(intensity);
}
void Aclock::setShutDown(bool mode){
setReg(REG_SHUTDOWN);
setData(mode?0:1);
}
void Aclock::setReg(uint8_t reg){
// the register is only the low 4 bits so we can simplify the shift operation
uint8_t i;
// we dont'need to change the data because the upper bits are ignored
digitalWrite(data_Pin,LOW);
for (i=0;i<4;i++){
digitalWrite(clk_Pin,LOW);
digitalWrite(clk_Pin,HIGH); // toggle clock lines
}
// send the low 4 bits of reg ledNumber
uint8_t mask = 0x08; // first bit of actual reg number
for (i = 0;i<4;i++) {
// the ? operator is shorthand for if .. then ..else
digitalWrite(data_Pin, ((reg&mask) ? HIGH:LOW));
digitalWrite(clk_Pin,LOW);
digitalWrite(clk_Pin,HIGH); // toggle clock lines
mask >>= 1; // move down to next bit
}
}
void Aclock::setData(uint8_t data){
// send the 8 bits of data
uint8_t i;
uint8_t mask = 0x80; // first bit of data
for (i = 0;i<8;i++) {
// the ? operator is shorthand for if .. then ..else
digitalWrite(data_Pin,((data&mask) ? HIGH:LOW)); // set data bit
digitalWrite(clk_Pin,LOW);
digitalWrite(clk_Pin,HIGH); // toggle clock lines
mask >>= 1; // move down to next bit
}
digitalWrite(load_Pin,LOW);
digitalWrite(load_Pin,HIGH); // toggle load line to store data
}
void Aclock::setZeros(){
// special case to send all zeros
uint8_t i;
digitalWrite(data_Pin, LOW); // set data bits to low
for (i = 0;i<8;i++) {
digitalWrite(clk_Pin,LOW);
digitalWrite(clk_Pin,HIGH); // toggle clock lines
}
digitalWrite(load_Pin,LOW);
digitalWrite(load_Pin,HIGH); // toggle load line to store data
}
void Aclock::setOnes(){
// special case to send all ones
uint8_t i;
digitalWrite(data_Pin, HIGH); // set data bits to low
for (i = 0;i<8;i++) {
digitalWrite(clk_Pin,LOW);
digitalWrite(clk_Pin,HIGH); // toggle clock lines
}
digitalWrite(load_Pin,LOW);
digitalWrite(load_Pin,HIGH); // toggle load line to store data
}
void Aclock::setDecodeOff(){
setReg(REG_DECODE_MODE);
setZeros(); // no decode - send segments directly
}
void Aclock:: setScanAll(){
setReg(REG_SCAN_LIMIT);
setOnes(); // use all digits
}
// end implementation
/**************
*
* test Aclock class
*
*/
const uint8_t clk_line = 3;
const uint8_t data_line = 4;
const uint8_t sec_load = 5;
const uint8_t min_load = 6;
const uint8_t hr_load = 7;
Aclock seconds,minutes,hours; // declare parts of clock
// starting time
uint8_t timeSec = 0;
uint8_t timeMin = 0;
uint8_t timeHr = 0;
unsigned long waitTime = 1000; // wait a second
unsigned long lastTime,curTime;
bool updateMin = false;
bool updateHr = false;
void setup()
{
Serial.begin(115200);
seconds.begin(clk_line,data_line,sec_load,59);
minutes.begin(clk_line,data_line,min_load,59);
hours.begin(clk_line,data_line,hr_load,11);
seconds.setLed(timeSec);
minutes.setLed(timeMin);
hours.setLed(timeHr);
lastTime = millis(); // get current ms
}
void loop() // run over and over again
{
curTime = millis();
if ((curTime-lastTime) >= waitTime) {
lastTime = curTime;
// update clock
timeSec++; //increment seconds
if (timeSec >= 60){ // use >= "just in case"
timeSec = 0; // start new minute
updateMin = true;
}
seconds.setLed(timeSec);
if (updateMin) {
// rolled over to new minute
timeMin++; //increment minutes
if (timeMin >= 60){ // use >= "just in case"
timeMin = 0; // start new minute
updateHr = true;
}
minutes.setLed(timeMin);
updateMin = false;
}
if (updateHr) {
// rolled over to new hour
timeHr++; //increment hours
if (timeHr >= 12){ // use >= "just in case"
timeHr = 0; // start new hour
}
hours.setLed(timeHr);
updateHr = false;
}
}
}