Matrix Orbital Clock with Set Buttons

Here's my first real project, once I got the matrix orbital to talk over I2C.

This clock uses the Big Digit function of the Matrix Orbital display and shows 24-hour format (could easily be adjusted for 12-hour plus AM/PM, but 24 is what I use). It displays hours, minutes, and seconds. Two buttons are used for setting the time up or down. When setting the time the display shows Forward and Reverse arrows as long as you're holding down the button.

This code doesn't currently do anything about millis rollover.

#include <Wire.h>
#include <stdlib.h>
#define LCD (0x2E)

int incrementPin = 8;
int decrementPin = 11;
int ledPin = 10;
int led2Pin = 12;
int buttonVal = 0;

int incomingByte = 0;
int analogVal = 0;
int contrastVal = 0;
char stringVal[80];
int initialContrast = 110;

long previousMillis = 0;
long interval = 1000;

int theHour = 12;
int theMinutes = 0;
int theSeconds = 0;

void setup() {
  
  pinMode(incrementPin, INPUT); 
  digitalWrite(incrementPin, HIGH); // turn on pullup resistor
  pinMode(decrementPin, INPUT);
  digitalWrite(decrementPin, HIGH); // turn on pullup resistor
  pinMode(ledPin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  
  Wire.begin();
  Wire.beginTransmission(LCD);
  
  setContrast(initialContrast);
  underlineCursor(false);
  blockCursor(false);
  clearScreen();
  wrap(true);
  scroll(true);
  
  enableBigDigits();
  displayHour(theHour);
  displayMinutes(theMinutes);
  
  Wire.endTransmission();
}

void loop() {

  if( digitalRead(incrementPin) == LOW || digitalRead(decrementPin) == LOW){
    delay(100);
    if( digitalRead(incrementPin) == LOW ){
      setTimeUp();
    } else if( digitalRead(decrementPin) == LOW) {
      setTimeDown();
    }
  } else {
    doClock();
  }
  
  /*
  // Set contrast from pot
  analogVal = analogRead(1);
  contrastVal = ( 255.0 / 1024.0 ) * analogVal;
  Wire.beginTransmission(LCD);
  setContrast(contrastVal);
  Wire.endTransmission(); */
}

void clearScreen(){
  Wire.send(254);
  Wire.send(88);
}

void setContrast(int val){
  Wire.send(254);
  Wire.send(80);
  Wire.send(val);
}

void blockCursor(boolean c){
  Wire.send(254);
  if(c){
    Wire.send(83);
  } else {
    Wire.send(84);
  }
}

void underlineCursor(boolean c){
  Wire.send(254);
  if(c){
    Wire.send(74);
  } else {
    Wire.send(75);
  }
}

void wrap(boolean c){
  Wire.send(254);
  if(c){
    Wire.send(67);
  } else {
    Wire.send(68);
  }
}

void scroll(boolean c){
  Wire.send(254);
  if(c){
    Wire.send(81);
  } else {
    Wire.send(82);
  }
}

void cursorHome(){
  Wire.send(254);
  Wire.send(72); 
}

void enableBigDigits(){
 // initialize large digits
 Wire.send(254);
 Wire.send(110);
}

void bigDigit(int col, int digit){
 Wire.send(254);
 Wire.send(35);
 Wire.send(col);
 Wire.send(digit);
}

void doClock(){
  if( millis() - previousMillis > interval ) {
    previousMillis = millis();
    //time to increment digits
    if( theSeconds == 59 ) {
      theSeconds = 0;
      if( theMinutes == 59 ) {
        theMinutes = 0;
        if( theHour == 23 ) {
          theHour = 0;
        } else {
          theHour++;
        }
       } else {
        theMinutes++;
       }
    } else {
      theSeconds++;
    }
    Wire.beginTransmission(LCD);
    displayTime(true);
    Wire.endTransmission();
  }
}

void setTimeUp(){
  digitalWrite(ledPin, HIGH);
  theSeconds = 0;
  if( theMinutes == 59 ) {
    theMinutes = 0;
    if( theHour == 23 ) {
      theHour = 0;
    } else {
      theHour++;
    }
  } else {
    theMinutes++; 
  }
  Wire.beginTransmission(LCD);
  displayTime(false);
  // Display forward arrows
  moveCursorTo(19, 1);
  Wire.send(126);
  Wire.send(126);
  Wire.endTransmission();
  digitalWrite(ledPin, LOW);
}

void setTimeDown(){
  digitalWrite(led2Pin, HIGH);
  theSeconds = 0;
  if( theMinutes == 0 ) {
    theMinutes = 59;
    if( theHour == 0 ) {
      theHour = 23;
    } else {
      theHour--;
    }
  } else {
    theMinutes--; 
  }
  Wire.beginTransmission(LCD);
  displayTime(false);
  // Display forward arrows
  moveCursorTo(19, 1);
  Wire.send(127);
  Wire.send(127);
  Wire.endTransmission();
  digitalWrite(led2Pin, LOW);
}

void displayTime(boolean seconds){
  displayHour(theHour);
  displayMinutes(theMinutes);
  if(seconds){
    displaySeconds(theSeconds);
  }
  displayDots();
}

void displayHour(int hour){
 if( hour <= 23 && hour >= 0 ){
   if( hour < 10 ){
     bigDigit(1, 0);
     bigDigit(5, hour);
   } else {
     bigDigit(1, (hour / 10));
     bigDigit(5, (hour % 10));
   }
 } 
}

void displayMinutes(int minutes){
  if( minutes <= 59 && minutes >= 0 ){
    if( minutes < 10 ){
      bigDigit(11, 0);
      bigDigit(15, minutes);
    } else {
      bigDigit(11, (minutes / 10));
      bigDigit(15, (minutes % 10));
    }
  }
}

void displaySeconds(int seconds){
  if( seconds <= 59 && seconds >= 0 ){
    itoa(seconds, stringVal, 10);
    if(seconds < 10){
      moveCursorTo(19, 1);
      Wire.send('0');
    } else {
      moveCursorTo(19, 1);
    }
    Wire.send(stringVal); 
  }
}

void displayDots(){
  if(theSeconds % 2){
    moveCursorTo(9, 2);
    Wire.send('.');
    moveCursorTo(9, 3);
    Wire.send(161);
  } else {
    moveCursorTo(9, 2);
    Wire.send(161);
    moveCursorTo(9, 3);
    Wire.send('.');
  }
}

void moveCursorTo(int col, int row){
  Wire.send(254);
  Wire.send(71);
  Wire.send(col);
  Wire.send(row);
}





Video of operation: