So I built a clock

On October 6, 2015, in General, by Neil Stevens

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

Comments are closed.