Here’s a video of it in action:
Parts used:
Libraries used:
My code:
#include "Bounce2.h"
#include "LedControl.h"
const byte lowA[8] = {B00000000, B00000000, B00000000, B01111100, B10000010, B10000010, B10000010, B01111101};
const byte capB[8] = {B11111110, B10000001, B10000001, B10000001, B11111110, B10000001, B10000001, B11111110};
const byte lowE[8] = {B00000000, B00000000, B00000000, B01111110, B10000001, B11111111, B10000000, B01111110};
const byte lowG[8] = {B00000000, B00000000, B01111110, B10000001, B10000001, B01111110, B00000001, B01111110};
const byte capH[8] = {B10000001, B10000001, B10000001, B11111111, B10000001, B10000001, B10000001, B10000001};
const byte lowR[8] = {B00000000, B00000000, B00000000, B01111111, B10000000, B10000000, B10000000, B10000000};
const byte lowS[8] = {B00000000, B00000000, B00000000, B01111111, B10000000, B01111110, B00000001, B01111110};
const byte lowU[8] = {B00000000, B00000000, B00000000, B10000001, B10000001, B10000001, B10000011, B01111101};
const byte capW[8] = {B10000001, B10000001, B10000001, B10010001, B10010001, B10010001, B10010001, B01111110};
const byte space[8] = {0, 0, 0, 0, 0, 0, 0, 0};
const byte digits[10][8] = {
{ B0111110, B1100011, B1100111, B1101011, B1110011, B1100011, B0111110, 0},
{ B0001110, B0011110, B0001110, B0001110, B0001110, B0001110, B0001110, 0},
{ B0111110, B1100011, B0000011, B0011110, B0110000, B1100000, B1111111, 0},
{ B0111110, B1100011, B0000011, B0011110, B0000011, B1100011, B0111110, 0},
{ B1100110, B1100110, B1100110, B1100110, B1111111, B0000110, B0000110, 0},
{ B1111111, B1100000, B1111110, B0000011, B0000011, B1100011, B0111110, 0},
{ B0111110, B1100011, B1100000, B1111110, B1100011, B1100011, B0111110, 0},
{ B1111111, B0000011, B0000110, B0001100, B0011100, B0011100, B0011100, 0},
{ B0111110, B1100011, B1100011, B0111110, B1100011, B1100011, B0111110, 0},
{ B0111110, B1100011, B1100011, B0111111, B0000011, B1100011, B0111110, 0}
};
const unsigned long maxTicks = 0xFFFFFFFF;
const unsigned twentyFourHour = false;
LedControl lc = LedControl(11, 12, 10, 4);
Bounce hourButton = Bounce();
Bounce minuteButton = Bounce();
Bounce tenMinuteButton = Bounce();
Bounce brightnessButton = Bounce();
Bounce *buttonArray[4] = {&hourButton, &minuteButton, &tenMinuteButton, &brightnessButton};
boolean firstLoop = true;
void clearAll(LedControl lc) {
for(int i = 0; i < lc.getDeviceCount(); ++i) {
lc.clearDisplay(i);
}
}
void setAll(LedControl lc, const int x, const int y)
{
for(int i = 0; i < lc.getDeviceCount(); ++i) {
lc.setRow(i, x, y);
}
}
void writeLetter(LedControl lc, const int digit, const byte letter[8], const boolean colon = false)
{
for(int i = 0; i < 8; ++i) {
int bits = letter[i];
if(colon && (i == 2 || i == 4)) {
bits |= B10000000;
}
lc.setRow(digit, i, bits);
}
}
void setIntensity(LedControl lc, const int brightness) {
for(int i = 0; i < lc.getDeviceCount(); ++i) {
lc.setIntensity(i, brightness);
}
}
void setup()
{
for(int i = 0; i < lc.getDeviceCount(); ++i) {
lc.shutdown(i, false);
lc.setIntensity(i, 0);
lc.clearDisplay(i);
}
pinMode(1, INPUT_PULLUP);
brightnessButton.attach(1);
pinMode(2, INPUT_PULLUP);
hourButton.attach(2);
pinMode(3, INPUT_PULLUP);
tenMinuteButton.attach(3);
pinMode(4, INPUT_PULLUP);
minuteButton.attach(4);
}
// returns array {hourTens, hourOnes, minuteTens, minuteOnes}
const byte *timeDigits(const unsigned long seconds) {
static byte ret[4] = {9,9,9,9};
byte hour = seconds / 3600;
if(twentyFourHour) {
hour %= 24;
} else {
hour %= 12;
if(hour == 0) {
hour = 12;
}
}
byte min = (seconds % 3600) / 60;
ret[0] = hour / 10;
ret[1] = hour % 10;
ret[2] = min / 10;
ret[3] = min % 10;
return ret;
}
unsigned long secondsFromTime(byte hourTens, byte hourOnes, byte minuteTens, byte minuteOnes)
{
return hourTens * 36000 +
hourOnes * 3600 +
minuteTens * 600 +
minuteOnes * 60;
}
void loop()
{
boolean reset = false;
static unsigned long ticks;
static unsigned long offsetSeconds;
static unsigned long lastSeconds;
static unsigned long offsetTicks;
static unsigned long lastTicks;
static unsigned short brightness;
ticks = millis();
if(hourButton.fell()) {
const byte *currentDigits = timeDigits(lastSeconds % 86400);
long hours = currentDigits[0] * 10 + currentDigits[1];
hours += 1;
if(twentyFourHour) {
hours %= 24;
} else {
hours %= 12;
if (hours == 0) {
hours = 12;
}
}
offsetSeconds = secondsFromTime(hours / 10,
hours % 10,
currentDigits[2],
currentDigits[3]) % 86400;
reset = true;
}
if(tenMinuteButton.fell()) {
const byte *currentDigits = timeDigits(lastSeconds % 86400);
offsetSeconds = secondsFromTime(currentDigits[0],
currentDigits[1],
(currentDigits[2] + 1) % 6,
currentDigits[3]) % 86400;
reset = true;
}
if(minuteButton.fell()) {
const byte *currentDigits = timeDigits(lastSeconds % 86400);
offsetSeconds = secondsFromTime(currentDigits[0],
currentDigits[1],
currentDigits[2],
(currentDigits[3] + 1) % 10) % 86400;
reset = true;
}
if(brightnessButton.fell()) {
brightness = (brightness + 1) % 0x10;
setIntensity(lc, brightness);
}
if(firstLoop) {
brightness = 0;
firstLoop = false;
offsetSeconds = 0;
reset = true;
}
if(reset) {
offsetTicks = 0;
lastTicks = ticks;
offsetTicks = -ticks;
lastSeconds = offsetSeconds;
} else {
if(lastTicks > ticks) {
offsetSeconds = lastSeconds;
offsetTicks = maxTicks - lastTicks;
}
}
for(byte i = 0; i < 4; ++i) {
buttonArray[i]->update();
}
lastSeconds = offsetSeconds + (ticks + offsetTicks) / 1000;
const byte *currentDigits = timeDigits(lastSeconds % 86400);
// Write the clock
if(currentDigits[0] == 0) {
writeLetter(lc, 3, space);
} else {
writeLetter(lc, 3, digits[currentDigits[0]]);
}
writeLetter(lc, 2, digits[currentDigits[1]]);
writeLetter(lc, 1, digits[currentDigits[2]], (lastSeconds % 2) == 1);
writeLetter(lc, 0, digits[currentDigits[3]]);
}