LED Matrix Clock

This clock is made of 60 LEDs and the AtMega328 chip with Arduino bootloader. Video of clock in operation. https://www.youtube.com/watch?v=L1F2BAmQfWg

Here is schematics. Board has two button to adjust hours and minutes and Real-time clock ic to keep time accurate.

Back side is not perfect because of cheap soldering iron.

Program code is below.

#include "Wire.h"

boolean LEDarr[60];
unsigned long newMillis = 0;
unsigned long blinkMillis = 0;
int second = 0;
int minute = 0;
int hour = 1;

unsigned long debounceTimer;
boolean A2state = 1;
boolean A3state = 1;

void setup() {
  pinMode(0, OUTPUT); // matrix
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);

  pinMode(8, OUTPUT); // matrix
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(A0, OUTPUT);
  pinMode(A1, OUTPUT);

  pinMode(A2, INPUT_PULLUP); // buttons
  pinMode(A3, INPUT_PULLUP);

  Wire.begin(); // A4,A5
  getRTC();
}

int ii = 0;

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - newMillis >= 500) {  
    newMillis = currentMillis;
    getRTC();
  }
  if(!digitalRead(A2)) {
    if(A2state) {
      A2state = 0;
      debounceTimer = millis();
    }
    if(millis() - debounceTimer > 150) {
      A2state = 1;
      if(++hour == 13) hour = 1;
      newMillis = currentMillis;
      setRTC();
    }
  }
  if(!digitalRead(A3)) {
    if(A3state) {
      A3state = 0;
      debounceTimer = millis();
    }
    if(millis() - debounceTimer > 150) {
      A3state = 1;
      if(++minute == 60) minute = 0;
      newMillis = currentMillis;
      setRTC();
    }
  }
  for(int i = 0; i <= 59; i++) LEDarr[i] = 0;
  
  if(second == 59) {
    if (ii < 59) for(int i = 0; i <= ii; i++) LEDarr[i] = 1;
    ii = ii + 2;
  } else {
    ii = 0;
    LEDarr[second] = 1;
  }
  
  LEDarr[minute] = 1;
  LEDarr[(hour*5)-1] = 1;
  
  if(second == (hour*5)-1 && currentMillis - blinkMillis > 200) {
    blinkMillis = currentMillis;
    LEDarr[second] = !LEDarr[second];
  }
  if(second == minute && currentMillis - blinkMillis > 200) {
    blinkMillis = currentMillis;
    LEDarr[second] = !LEDarr[second];
  }
  if(minute == (hour*5)-1 && currentMillis - blinkMillis > 200) {
    blinkMillis = currentMillis;
    LEDarr[minute] = !LEDarr[minute];
  }
  LEDloop();
}

byte decToBcd(byte val) {
  return ((val/10*16) + (val%10));
}

byte bcdToDec(byte val) {
  return ((val/16*10) + (val%16));
}

void setRTC() {
  Wire.beginTransmission(0x51);
  Wire.write(0x03);
  //Wire.write(decToBcd(second));  
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour-1));
  Wire.endTransmission();
}

void getRTC() {
  Wire.beginTransmission(0x51);
  Wire.write(0x02);
  Wire.endTransmission();
  Wire.requestFrom(0x51, 3);
  second = bcdToDec(Wire.read() & B01111111); // remove VL error bit
  minute = bcdToDec(Wire.read() & B01111111); // remove unwanted bits from MSB
  hour = bcdToDec(Wire.read() & B00111111);
  if(hour >= 12) hour = hour - 12;
  hour = hour + 1;
}

void LEDloop() {
  int led = 0;
  for(int a = 8; a <= 15; a++) {
    if (a <= 13) digitalWrite(a, 1);
    else if(a == 14) digitalWrite(A0, 1);
    else if(a == 15) digitalWrite(A1, 1);
    if(a != 8) {
      for(int i = 4; i <= 7; i++) {
        digitalWrite(i, !LEDarr[led++]);
        delayMicroseconds(340);
        digitalWrite(i, 1);
      }
    }
    for(int i = 0; i <= 3; i++) {
      digitalWrite(i, !LEDarr[led++]);
      delayMicroseconds(340);
      digitalWrite(i, 1);
    }
    if (a <= 13) digitalWrite(a, 0);
    else if(a == 14) digitalWrite(A0, 0);
    else if(a == 15) digitalWrite(A1, 0);
  }
}