/*
 * Clock and counter with WS2811 LED strip (128 LEDs).
 */
#include <FastLED.h>
#include <Wire.h>

#define SWT_PIN  2
#define LED_PIN  5
#define NUM_LEDS 128
#define DS1307_ADDRESS 0x68

CRGB leds[NUM_LEDS];
CHSV colourOfNumbers(160, 255, 255);

int hue = 0;
int counter = 0;

uint8_t clear = 0x00;

const int digits[10][12] =
{
  {8, 9, 10, 14, 18, 22, 23, 24},
  {7, 10, 14, 15, 16, 17, 18, 21},
  {7, 8, 11, 14, 16, 18, 21, 24},
  {7, 11, 14, 16, 18, 22, 24},
  {9, 10, 11, 16, 21, 22, 23, 24, 25},
  {7, 9, 10, 11, 14, 16, 18, 22, 23, 25},
  {8, 9, 10, 14, 16, 18, 21, 22, 23, 25},
  {7, 8, 11, 16, 18, 24, 25},
  {7, 8, 10, 11, 14, 16, 18, 21, 22, 24, 25},
  {7, 9, 10, 11, 14, 16, 18, 22, 23, 24, 25},
};

void setup()
{
  pinMode(SWT_PIN, INPUT_PULLUP);
  Wire.begin();
  FastLED.addLeds<WS2811, LED_PIN, GRB>(leds, NUM_LEDS);
}

void displayNumber(int position, int number, CHSV colour)
{
  for (int i = 0 ; i < 12 ; i++) {
    if (digits[number / 10][i] != 0) {
      leds[(digits[number / 10][i] + position)] = colour;
    }
    if (digits[number % 10][i] != 0) {
      leds[(digits[number % 10][i] + 28 + position)] = colour;
    }
  }
}

void displayDots(int position, CHSV colour)
{
  leds[position] = colour;
  leds[position + 2] = colour;
}

void beginDS1307()
{
  // Read the values ​​(date and time) of the DS1307 module
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(clear);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_ADDRESS, 0x07);
}

uint8_t decToBcd(uint8_t value)
{
  return ((value / 10 * 16) + (value % 10));
}

uint8_t bcdToDec(uint8_t value)
{
  return ((value / 16 * 10) + (value % 16));
}

void loop()
{
  beginDS1307();

  uint8_t seconds = bcdToDec(Wire.read());
  uint8_t minutes = bcdToDec(Wire.read());
  uint8_t hours = bcdToDec(Wire.read() & 0xff);

  hue = (hue + 1) % 2550;
  colourOfNumbers.hue = hue / 10;

  if (digitalRead(SWT_PIN) == LOW) {
    counter = (counter + 1) % 10000;
    displayNumber(0, counter / 100, colourOfNumbers);

    if ((counter / 100) & 1)
      displayDots(64, colourOfNumbers);

    displayNumber(70, counter % 100, colourOfNumbers);     
  } else {
    counter = 0;
    displayNumber(0, hours, colourOfNumbers);

    if (seconds & 1)
      displayDots(64, colourOfNumbers);

    displayNumber(70, minutes, colourOfNumbers);          
  }

  FastLED.show();
  FastLED.clear();
}
GND5VSDASCLSQWRTCDS1307+