#include <Arduino.h>

#define ASCII_OFFSET	32

/*  0b A B C D E F G DP */
const unsigned int SevenSegment[] = {
	0b11111100, /* 0 */
	0b01100000, /* 1 */
	0b11011010, /* 2 */
	0b11110010, /* 3 */
	0b01100110, /* 4 */
	0b10110110, /* 5 */
	0b10111110, /* 6 */
	0b11100000, /* 7 */
	0b11111110, /* 8 */
	0b11110110	/* 9 */
};

const unsigned int SevenSegmentTextAscii[] = {
	0b00000000, /* (space) */
	0b01100001, /* ! */
	0b01000100, /* " */
	0b01111110, /* # */
	0b10110110, /* $ */
	0b01001011, /* % */
	0b01100010, /* & */
	0b00000100, /* ' */
	0b10010100, /* ( */
	0b11010000, /* ) */
	0b10000100, /* * */
	0b00001110, /* + */
	0b00001000, /* , */
	0b00000010, /* - */
	0b00000001, /* . */
	0b01001010, /* / */
	0b11111100, /* 0 */
	0b01100000, /* 1 */
	0b11011010, /* 2 */
	0b11110010, /* 3 */
	0b01100110, /* 4 */
	0b10110110, /* 5 */
	0b10111110, /* 6 */
	0b11100000, /* 7 */
	0b11111110, /* 8 */
	0b11110110, /* 9 */
	0b10010000, /* : */
	0b10110000, /* ; */
	0b10000110, /* < */
	0b00010010, /* = */
	0b11000010, /* > */
	0b11001011, /* ? */
	0b11111010, /* @ */
	0b11101110, /* A */
	0b00111110, /* B */
	0b10011100, /* C */
	0b01111010, /* D */
	0b10011110, /* E */
	0b10001110, /* F */
	0b10111100, /* G */
	0b01101110, /* H */
	0b00001100, /* I */
	0b01111000, /* J */
	0b10101110, /* K */
	0b00011100, /* L */
	0b10101000, /* M */
	0b11101100, /* N */
	0b11111100, /* O */
	0b11001110, /* P */
	0b11010110, /* Q */
	0b11001100, /* R */
	0b10110110, /* S */
	0b00011110, /* T */
	0b01111100, /* U */
	0b01111100, /* V */
	0b01010100, /* W */
	0b01101110, /* X */
	0b01110110, /* Y */
	0b11011010, /* Z */
	0b10011100, /* [ */
	0b00100110, /* \ */
	0b11110000, /* ] */
	0b11000100, /* ^ */
	0b00010000, /* _ */
	0b01000000, /* ` */
	0b11111010, /* a */
	0b00111110, /* b */
	0b00011010, /* c */
	0b01111010, /* d */
	0b11011110, /* e */
	0b10001110, /* f */
	0b11110110, /* g */
	0b00101110, /* h */
	0b00001000, /* i */
	0b00110000, /* j */
	0b10101110, /* k */
	0b00001100, /* l */
	0b00101000, /* m */
	0b00101010, /* n */
	0b00111010, /* o */
	0b11001110, /* p */
	0b11100110, /* q */
	0b00001010, /* r */
	0b10110110, /* s */
	0b00011110, /* t */
	0b00111000, /* u */
	0b00111000, /* v */
	0b00101000, /* w */
	0b01101110, /* x */
	0b01110110, /* y */
	0b11011010, /* z */
};


const int dataPin = 5;   	/* DS   */
const int clockPin = 2; 	/* SHCP */
const int latchPin = 4;  	/* STCP */
const bool verbose = false;

const int displaySize = 8;

int hours = 23;
int minutes = 5;
int seconds = 15;
int frames = 16;

int timecode[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };


void incrementTimeCode()
{
	frames = frames + 1;

	if (frames >= 24)
	{
		frames = 0;
		seconds = seconds + 1;
	}
}

void timecodeToArray()
{
	timecode[7] = frames % 10;
	timecode[6] = frames / 10;
	timecode[5] = seconds % 10;
	timecode[4] = seconds / 10;
	timecode[3] = minutes % 10;
	timecode[2] = minutes / 10;
	timecode[1] = hours % 10;
	timecode[0] = hours / 10;
}

void displayTimecode()
{
	for (int i = 0; i < displaySize; i++)
	{
		int index = timecode[i];
		int lettersBits = ~SevenSegment[index];
		int mask = (1 << (displaySize - i - 1));

		if ((i % 2 == 1) && (i < displaySize - 1)) {
			lettersBits &= ~(1 << 0);
		}

		digitalWrite(latchPin, LOW);
		shiftOut(dataPin, clockPin, LSBFIRST, mask);
		shiftOut(dataPin, clockPin, LSBFIRST, lettersBits);
		digitalWrite(latchPin, HIGH);

		delay(100);
	}
}

void display(String text)
{
	int displaySize = 8;
	int position = 0;
	const char* textCharacters = text.c_str();

	for (int i = 0; i < text.length(); i++)
	{
		int	lettersBits = ~SevenSegmentTextAscii[textCharacters[i] - ASCII_OFFSET];
		int	mask = (1 << (displaySize - position - 1));

		if (textCharacters[i + 1] == '.')
		{
			lettersBits &= ~(1 << 0);
			i++;
		}

		digitalWrite(latchPin, LOW);
		shiftOut(dataPin, clockPin, LSBFIRST, mask);
		shiftOut(dataPin, clockPin, LSBFIRST, lettersBits);
		digitalWrite(latchPin, HIGH);

		delay(300);

		position++;

		if (position >= 8) {
			return;
		}
	}
}

void setup()
{
	Serial.begin(115200);
	pinMode(dataPin, OUTPUT);
	pinMode(clockPin, OUTPUT);
	pinMode(latchPin, OUTPUT);
}

void loop()
{
	incrementTimeCode();
	timecodeToArray();
	displayTimecode();

	display("HELLO.LUDOVIC");
}
74HC595
74HC595