// Pin Definitions
const int pinClockMode = A0;
const int pinMinus = A1;
const int pinPlus = A2;
const int pinSet = A3;
const int pinAM = A4;
const int pinPM = A5;
const int pinM1 = 0;
const int pinM2 = 1;
const int pinM4 = 2;
const int pinM8 = 3;
const int pinM10 = 4;
const int pinM20 = 5;
const int pinM40 = 6;
const int pinH1 = 7;
const int pinH2 = 8;
const int pinH4 = 9;
const int pinH8 = 10;
const int pinH10 = 11;
const int pinH20 = 12;
// States
const int STATE_RESET = 0;
const int STATE_SET_HOURS = 1;
const int STATE_SET_MINUTES = 2;
const int STATE_SET_MODE = 3;
const int STATE_RUN = 4;
// Clock Modes
const int MODE_12H = 0;
const int MODE_24H = 1;
// Buttons
const int MODE = 0;
const int PLUS = 1;
const int MINUS = 2;
const int SET = 3;
// Runtime Variables
int currentState = STATE_RESET;
int currentMode = MODE_12H;
int currentTime = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
unsigned long tickTime = 0;
unsigned long lastModeChange = 0;
unsigned long lastPlusChange = 0;
unsigned long lastMinusChange = 0;
unsigned long lastSetChange = 0;
int modeState = LOW;
int plusState = LOW;
int minusState = LOW;
int setState = LOW;
int lastModeState = LOW;
int lastPlusState = LOW;
int lastMinusState = LOW;
int lastSetState = LOW;
bool changedMode = false;
bool changedPlus = false;
bool changedMinus = false;
bool changedSet = false;
bool holdingPlus = false;
bool holdingMinus = false;
bool holdingSet = false;
int holdingPlusCount = 0;
int holdingMinusCount = 0;
int holdingSetCount = 0;
bool tick = false;
int blinkState = LOW;
bool refresh = false;
char logBuffer [64];
int test = 0;
// Function Overload Definitions
void writeTime(int hours, int minutes, int mode, int overrideHours = HIGH, int overrideMinutes = HIGH, int overrideMode = HIGH);
void incSeconds(bool rollOver = true);
void decSeconds(bool rollOver = true);
void incMinutes(bool rollOver = true);
void decMinutes(bool rollOver = true);
void setup() {
pinMode(pinClockMode, INPUT);
pinMode(pinMinus, INPUT);
pinMode(pinPlus, INPUT);
pinMode(pinSet, INPUT);
pinMode(pinAM, OUTPUT);
pinMode(pinPM, OUTPUT);
for (int i = pinM1; i <= pinH20; i++)
{
pinMode(i, OUTPUT);
}
}
void loop() {
currentTime = millis();
// SECOND TICK
tick = false;
if (currentTime - tickTime >= 1000) {
tick = true;
tickTime = currentTime;
blinkState = !blinkState;
refresh = true;
}
// Track Button Changes
int modeReading = digitalRead(pinClockMode);
if (modeReading != lastModeState) {
lastModeChange = currentTime;
}
if (modeReading != modeState && currentTime - lastModeChange > 20 ) {
modeState = modeReading;
changedMode = true;
}
lastModeState = modeReading;
int plusReading = digitalRead(pinPlus);
if (plusReading != lastPlusState) {
lastPlusChange = currentTime;
}
if (plusReading != plusState && currentTime - lastPlusChange > 20 ) {
plusState = plusReading;
changedPlus = true;
holdingPlus = false;
}
lastPlusState = plusReading;
int minusReading = digitalRead(pinMinus);
if (minusReading != lastMinusState) {
lastMinusChange = currentTime;
}
if (minusReading != minusState && currentTime - lastMinusChange > 20 ) {
minusState = minusReading;
changedMinus = true;
holdingMinus = false;
}
lastMinusState = minusReading;
int setReading = digitalRead(pinSet);
if (setReading != lastSetState) {
lastSetChange = currentTime;
}
if (setReading != setState && currentTime - lastSetChange > 20 ) {
setState = setReading;
changedSet = true;
holdingSet = false;
}
lastSetState = setReading;
// Check Mode Push
if (checkButtonPressed(MODE)) {
if (currentMode == MODE_12H) {
currentMode = MODE_24H;
} else {
currentMode = MODE_12H;
}
refresh = true;
}
//RESET STATE
if (currentState == STATE_RESET) {
// Check button pushes
if(checkButtonPressed(SET)) {
currentState = STATE_SET_HOURS;
holdingPlus = false;
holdingMinus = false;
refresh = true;
}
if (refresh) {
for (int i = pinM1; i <= pinH20; i++)
{
digitalWrite(i, blinkState);
}
digitalWrite(pinPM, blinkState);
digitalWrite(pinAM, blinkState);
if (currentState == STATE_RESET) {
refresh = false;
}
}
// SET HOURS STATE
} else if (currentState == STATE_SET_HOURS) {
// Blink the hours, display minutes normally. Time stopped.
// Check button pushes
if(checkButtonPressed(PLUS)) {
incHours();
holdingPlus = true;
holdingPlusCount = 0;
refresh = true;
}
if(checkButtonPressed(MINUS)) {
decHours();
holdingMinus = true;
holdingMinusCount = 0;
refresh = true;
}
if(checkButtonPressed(SET)) {
currentState = STATE_SET_MINUTES;
holdingPlus = false;
holdingMinus = false;
refresh = true;
}
// Check button holds
if (tick) {
if (holdingPlus && holdingPlusCount++ > 1 && blinkState == HIGH) {
hours = (hours + 4) % 24;
}
if (holdingMinus && holdingMinusCount++ > 1 && blinkState == HIGH) {
hours = (hours + 20) % 24;
}
}
// Refresh the visuals based on blink state
if (refresh) {
writeTime(hours, minutes, currentMode, blinkState, HIGH, blinkState);
if (currentMode == MODE_24H) {
digitalWrite(pinPM, blinkState);
digitalWrite(pinAM, blinkState);
}
if (currentState == STATE_SET_HOURS) {
refresh = false;
}
}
// SET MINUTES STATE
} else if (currentState == STATE_SET_MINUTES) {
// Blink the minutes, display hours normally. Time stopped.
// Check button pushes
if(checkButtonPressed(PLUS)) {
incMinutes(false);
holdingPlus = true;
holdingPlusCount = 0;
refresh = true;
}
if(checkButtonPressed(MINUS)) {
decMinutes(false);
holdingMinus = true;
holdingMinusCount = 0;
refresh = true;
}
if(checkButtonPressed(SET)) {
currentState = STATE_RUN;
holdingPlus = false;
holdingMinus = false;
refresh = true;
}
// Check button holds
if (tick) {
if (holdingPlus && holdingPlusCount++ > 1 && blinkState == HIGH) {
minutes = (minutes + 10) % 60;
}
if (holdingMinus && holdingMinusCount++ > 1 && blinkState == HIGH) {
minutes = (minutes + 50) % 60;
}
}
// Refresh the visuals based on blink state
if (refresh) {
writeTime(hours, minutes, currentMode, HIGH, blinkState, blinkState);
if (currentMode == MODE_24H) {
digitalWrite(pinPM, blinkState);
digitalWrite(pinAM, blinkState);
}
if (currentState == STATE_SET_MINUTES) {
refresh = false;
}
}
// RUN STATE
} else {
// Check button presses
if(checkButtonPressed(SET)) {
holdingSet = true;
holdingSetCount = 0;
}
// Check button holds
if (tick) {
if (holdingSet && holdingSetCount++ > 1) {
currentState = STATE_SET_HOURS;
refresh = true;
}
// Time Flows
incSeconds();
}
if (refresh) {
writeTime(hours, minutes, currentMode);
if (currentState == STATE_RUN) {
refresh = false;
}
}
}
// Reset Button Presses
changedMode = false;
changedPlus = false;
changedMinus = false;
changedSet = false;
}
void log(String str) {
Serial.begin(9600);
Serial.println(str);
Serial.end();
}
void writeTime(int hours, int minutes, int mode, int overrideHours, int overrideMinutes, int overrideMode) {
int modHours = hours;
if (mode == MODE_12H) {
modHours = hours % 12;
if (modHours == 0) {
modHours = 12;
}
}
digitalWrite(pinM1, ((minutes % 10) & 1) * overrideMinutes);
digitalWrite(pinM2, ((minutes % 10) & 2) * overrideMinutes);
digitalWrite(pinM4, ((minutes % 10) & 4) * overrideMinutes);
digitalWrite(pinM8, ((minutes % 10) & 8) * overrideMinutes);
digitalWrite(pinM10, ((minutes / 10) & 1) * overrideMinutes);
digitalWrite(pinM20, ((minutes / 10) & 2) * overrideMinutes);
digitalWrite(pinM40, ((minutes / 10) & 4) * overrideMinutes);
digitalWrite(pinH1, ((modHours % 10) & 1) * overrideHours);
digitalWrite(pinH2, ((modHours % 10) & 2) * overrideHours);
digitalWrite(pinH4, ((modHours % 10) & 4) * overrideHours);
digitalWrite(pinH8, ((modHours % 10) & 8) * overrideHours);
digitalWrite(pinH10, ((modHours / 10) & 1) * overrideHours);
digitalWrite(pinH20, ((modHours / 10) & 2) * overrideHours);
int stateAM = LOW;
int statePM = LOW;
if (mode == MODE_12H) {
if (hours < 12) {
stateAM = HIGH;
} else {
statePM = HIGH;
}
}
digitalWrite(pinAM, stateAM * overrideMode);
digitalWrite(pinPM, statePM * overrideMode);
// if (mode == MODE_12H) {
// sprintf(logBuffer, "12H Time: %d:%d", modHours, minutes);
// } else {
// sprintf(logBuffer, "24H Time: %d:%d", modHours, minutes);
// }
// log(logBuffer);
}
void incSeconds(bool rollOver) {
seconds++;
if (seconds >= 60) {
seconds = 0;
if (rollOver) {
incMinutes();
}
}
}
void decSeconds(bool rollOver) {
seconds--;
if (seconds < 0) {
seconds = 59;
if (rollOver) {
decMinutes();
}
}
}
void incMinutes(bool rollOver) {
minutes++;
if (minutes >= 60) {
minutes = 0;
if (rollOver) {
incHours();
}
}
}
void decMinutes(bool rollOver) {
minutes--;
if (minutes < 0) {
minutes = 59;
if (rollOver) {
decHours();
}
}
}
void incHours() {
hours++;
if (hours >= 24) {
hours = 0;
}
}
void decHours() {
hours--;
if (hours < 0) {
hours = 23;
}
}
bool checkButtonPressed(int button) {
if (button == MODE) {
return changedMode && modeState;
} else if (button == PLUS) {
return changedPlus && plusState;
} else if (button == MINUS) {
return changedMinus && minusState;
} else {
return changedSet && setState;
}
}
Set
+
-
Mode
Minutes
Hours
PM
AM