#include 
#include 
#include 

#define F_CPU 1600000UL;
#define SLA_W  0xD0;	//Slav address + write bit (0)
#define SLA_Rd  0xD1; //Slav address + read bit (1)


uint8_t buttonSave;
char minutes;
char hour;
char date;
char month;
char year;
int alarmOn = 0;
char tidSec = 'A';
char tidSec10 = 'A';
char tidMin = 'A';
char tidMin10 = 'A';
char tidHour = 'A';
char tidHour10 = 'A';
char tidDat = 'A';
char tidDat10 = 'A';
char tidMon = 'A';
char tidMon10 = 'A';
char tidYear = 'A';
char tidYear10 = 'A';
char totMon = 'A';
char readTime;
char currentPos = 0;

char alarmSec = '1';
char alarmSec10 = '0';
char alarmMin = '5';
char alarmMin10 = '1';
char alarmHour = '8';
char alarmHour10 = '0';

char dupMin = 'A';
char dupMin10 = 'A';
char dupHour = 'A';
char dupHour10 = 'A';
char dupDat = 'A';
char dupDat10 = 'A';
char dupMon = 'A';
char dupMon10 = 'A';
char dupYear = 'A';
char dupYear10 = 'A';


char currentButton;
char previousButton;

int alarmToggled = 0;
char buttonResult;

void TWI_transmitTime(char address, char data);
char TWI_readTime(char adress);
void writeDisplay(char command);

/**
		FLYTTADE MAIN LÄNGST NER, PALLAR INTE DEKLARERA FUNKTIONER
**/

void timeInit(char y10, char y, char mon10, char mon, char dat10, char dat, char h10, char h, char min10, char min, char sec10, char sec){
	
	char seconds = (sec10<<4)| sec;
	TWI_transmitTime(0x00, seconds);
	char minutes = (min10<<4)| min;
	TWI_transmitTime(0x01, minutes);
	char hour = (h10<<4)| h;
	TWI_transmitTime(0x02, hour);
	char date = (dat10<<4)| dat;
	TWI_transmitTime(0x04, date);
	char month = (mon10<<4)| mon;
	TWI_transmitTime(0x05, month);
	char year = (y10<<4)| y;
	TWI_transmitTime(0x06, year);
}

void timeOnDisplay(){	
	
	//gör cursorn osynlig efteråt här
	
	if(tidMin10 != ((TWI_readTime(0x01)&0x70)>>4)){
		tidMin10 = ((TWI_readTime(0x01)&0x70)>>4);
		minutes = (tidMin10<<4)|tidMin;
		moveCursor(0x07);
		writeDisplay(tidMin10+48);
	}
	
	if(tidMin != (TWI_readTime(0x01)&0x0F)){
		tidMin = (TWI_readTime(0x01)&0x0F);
		minutes = (tidMin10<<4)|tidMin;
		moveCursor(0x08);
		writeDisplay(tidMin+48);
	}
	
	if(tidHour10 != (TWI_readTime(0x02)&0x30)>>4){
		tidHour10 = ((TWI_readTime(0x02)&0x30)>>4);
		hour = (tidHour10<<4) | tidHour;
		moveCursor(0x04);
		writeDisplay(tidHour10+48);	
	}
	
	if(tidHour != (TWI_readTime(0x02)&0x0F)){
		tidHour = (TWI_readTime(0x02)&0x0F);
		hour = (tidHour10<<4) | tidHour;
		moveCursor(0x05);
		writeDisplay(tidHour+48);
	}
	
	if(tidDat10 != ((TWI_readTime(0x04)&0x30)>>4)){
		tidDat10 = ((TWI_readTime(0x04)&0x30)>>4);
		date = (tidDat10<<4) | tidDat;
		moveCursor(0x0A);
		writeDisplay(tidDat10+48);
	}
	
	if(tidDat != (TWI_readTime(0x04)&0x0F)){
		tidDat = (TWI_readTime(0x04)&0x0F);
		date = (tidDat10<<4) | tidDat;
		moveCursor(0x0B);
		writeDisplay(tidDat+48);
	}
	
	if(tidMon10 != ((TWI_readTime(0x05)&0x10)>>4)){
		tidMon10 = ((TWI_readTime(0x05)&0x10)>>4);
		month = (tidMon10<<4) | tidMon;
		writeMonth();
	}
	
	if(tidMon != (TWI_readTime(0x05)&0x0F)){
		tidMon = (TWI_readTime(0x05)&0x0F);
		month = (tidMon10<<4) | tidMon;
		writeMonth();
	}
	
	if(tidYear10 != ((TWI_readTime(0x06)&0xF0)>>4)){
		tidYear10 = ((TWI_readTime(0x06)&0xF0)>>4);
		year = (tidYear10<<4) | tidYear;
		moveCursor(0x4E);
		writeDisplay(tidYear10+48);
	}
	
	if(tidYear != (TWI_readTime(0x06)&0x0F)){
		tidYear = (TWI_readTime(0x06)&0x0F);
		year = (tidYear10<<4) | tidYear;
		moveCursor(0x4F);
		writeDisplay(tidYear+48);
	}
	
	moveCursor(currentPos);
}

void writeAlarmDisplay(){
	
	//detta är inte så effektivt, gör bara detta om alarmet har togglats av/på
	
	if(alarmOn==0){
		moveCursor(0x46);
		writeDisplay('A');
		writeDisplay('v');
		writeDisplay(' ');
		writeDisplay(' ');
		writeDisplay(' ');
		}else{
		moveCursor(0x46);
		writeDisplay(alarmHour10);
		writeDisplay(alarmHour);
		writeDisplay(':');
		writeDisplay(alarmMin10);
		writeDisplay(alarmMin);
	}
	moveCursor(currentPos);
}

void writeMonth(){
	totMon = tidMon + (tidMon10<<4);
	
	switch(totMon){
		case 0x01 :
			moveCursor(0x0D);
			writeDisplay('J');
			writeDisplay('a');
			writeDisplay('n');
			break;
		
		case 0x02 :
			moveCursor(0x0D);
			writeDisplay('F');
			writeDisplay('e');
			writeDisplay('b');
			break;
		
		case 0x03 :
			moveCursor(0x0D);
			writeDisplay('M');
			writeDisplay('a');
			writeDisplay('r');
			break;
		
		case 0x04 :
			moveCursor(0x0D);
			writeDisplay('A');
			writeDisplay('p');
			writeDisplay('r');
			break;
		
		case 0x05 :
			moveCursor(0x0D);
			writeDisplay('M');
			writeDisplay('a');
			writeDisplay('j');
			break;
		
		case 0x06 :
			moveCursor(0x0D);
			writeDisplay('J');
			writeDisplay('u');
			writeDisplay('n');
			break;
		
		case 0x07 :
			moveCursor(0x0D);
			writeDisplay('J');
			writeDisplay('u');
			writeDisplay('l');
			break;
		
		case 0x08 :
			moveCursor(0x0D);
			writeDisplay('A');
			writeDisplay('u');
			writeDisplay('g');
			break;
		
		case 0x09 :
			moveCursor(0x0D);
			writeDisplay('S');
			writeDisplay('e');
			writeDisplay('p');
			break;
		
		case 0x10 :
			moveCursor(0x0D);
			writeDisplay('O');
			writeDisplay('k');
			writeDisplay('t');
			break;
		
		case 0x11 :
			moveCursor(0x0D);
			writeDisplay('N');
			writeDisplay('o');
			writeDisplay('v');
			break;
		
		case 0x12 :
			moveCursor(0x0D);
			writeDisplay('D');
			writeDisplay('e');
			writeDisplay('c');
			break;
		
	}
}

void TWI_transmitTime(char address, char data){						//https://www.eit.lth.se/fileadmin/eit/courses/eita15/avr-libc-user-manual-2.0.0/util_2twi_8h.html
	TWCR |= (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); //startar kommunikation
	while (!(TWCR & (1< skriv 11:11
	
	
	if(currentPos==0x4F){
		currentPos = 0;
		commandDisplay(0x0C);
	}
	
	else if(currentPos==0){
		commandDisplay(0x0D);
		currentPos = 0x04;
	}
	
	else if(currentPos==0x04){
		currentPos += 1;
	}
	
	else if(currentPos==0x05){
		currentPos = 0x07;
	}
	
	else if(currentPos==0x07){
		currentPos += 1;
	}
	
	else if(currentPos==0x08){
		currentPos = 0x0A;
	}
	
	else if(currentPos==0x0A){
		currentPos += 1;
	}
	
	else if(currentPos==0x0B){
		currentPos = 0x0D;
	}
	
	else if(currentPos==0x0D){
		if(alarmOn==1)
		currentPos = 0x46;
		else
		currentPos = 0x4E;
	}
	//OM ALARM ÄR PÅ
	else if(currentPos == 0x46){
		currentPos = 0x47;
	}
	else if(currentPos == 0x47){
		currentPos = 0x49;
	}
	else if(currentPos == 0x49){
		currentPos = 0x4A;
	}
	else if(currentPos == 0x4A){
		currentPos = 0x4E;
	}
	
	else if(currentPos == 0x4E){
		currentPos = 0x4F;
	}
	
}

void reverseMovement(){
	
	//if alarmPå == 1, hoppa till 0x46 -> skriv 11:11
	
	if(currentPos==0){
		currentPos = 0x4F;
		commandDisplay(0x0D);
	}
	
	else if(currentPos==0x04){
		currentPos = 0;
		commandDisplay(0x0C);
	}
	
	else if(currentPos==0x05){
		currentPos = 0x04;
	}
	
	else if(currentPos==0x07){
		currentPos = 0x05;
	}
	
	else if(currentPos==0x08){
		currentPos = 0x07;
	}
	
	else if(currentPos==0x0A){
		currentPos = 0x08;
	}
	
	else if(currentPos==0x0B){
		currentPos = 0x0A;
	}
	
	else if(currentPos==0x0D){
		
		currentPos = 0x0B;
	}
	//OM ALARMET ÄR PÅ
	else if(currentPos == 0x4E){
		if(alarmOn==1)
		currentPos = 0x4A;
		else
		currentPos = 0x0D;
	}
	else if(currentPos==0x4A){
		
		currentPos = 0x49;
	}
	else if(currentPos==0x49){
		
		currentPos = 0x47;
	}
	else if(currentPos==0x47){
		
		currentPos = 0x46;
	}
	else if(currentPos==0x46){
		
		currentPos = 0x0D;
	}
	
	else if(currentPos==0x4F){
		currentPos = 0x4E;
	}
	
}

void alarmTrig(){
	if(alarmHour==tidHour+48 && alarmHour10 == tidHour10+48 && alarmMin10 == tidMin10+48 && alarmMin == tidMin+48){
		if(alarmOn==1){
		litetPip();
		}
	}
}

void testCommit(){
	TWI_transmitTime(0x01, minutes);
	TWI_transmitTime(0x02, hour);
	TWI_transmitTime(0x04, date);
	TWI_transmitTime(0x05, month);
	TWI_transmitTime(0x06, year);
}

void changeTime(){
	//deklarera nya variabler för tidMin osv.., i början av alla case satser p.g.a att vi använder den andra för att kolla uppdateringen.
	switch(currentPos){
		case 0x07 :
		dupMin10 = tidMin10;
		if(tidMin10 == 5){
			dupMin10 = 0;
			} else{
			dupMin10++;
		}
		minutes = (dupMin10<<4)| tidMin;
		break;
		case 0x08 :
		dupMin = tidMin;
		if(dupMin == 9){
			dupMin = 0;
		}
		else{
			dupMin++;
		}
		minutes = (tidMin10<<4)| dupMin;
		break;
		case 0x04 :
		dupHour10 = tidHour10;
		if(tidHour10 == 2){
			dupHour10 = 0;
		}
		else if(tidHour10==1 && tidHour>=4){
			dupHour10 = 0;
		}
		else{
			dupHour10++;
		}
		hour = (dupHour10<<4)| tidHour;
		break;
		case 0x05 :
		dupHour = tidHour;
		if(tidHour == 9 && tidHour10<2){
			dupHour = 0;
		}
		else if(tidHour10 == 2 && tidHour >= 4){	// i mån av tid lägger vi till + 10 h
			dupHour = 0;
		}
		else if(tidHour==9){
			dupHour++;
		}
		else{
			dupHour++;
		}
		hour = (tidHour10<<4)| dupHour;
		break;
		case 0x0A :
		dupDat10 = tidDat10;
		if(tidDat10 == 3){
			dupDat10 = 0;
		}
		else if(tidDat10==2 && tidMon==2 && tidMon10==0){
			dupDat10 = 0;
		}
		else if (tidDat10==2 && tidDat >= 2){
			dupDat10 = 0;
		}
		else{
			dupDat10++;
		}
		date = (dupDat10<<4)| tidDat;
		break;
		case 0x0B :
		dupDat = tidDat;
		if(tidDat == 8 && tidMon10 == 0 && tidMon == 2 && ((tidYear+(tidYear10))%4)!= 0){ //undantag feb ska fixas
			dupDat = 0;
		}
		else if(tidDat == 9 && tidDat10 >= 1){
			dupDat = 0;
		}
		else if(tidDat == 9){
			dupDat = 1;
		}
		else if (tidDat>=1&&tidDat10==3){
			dupDat = 0;
		}
		else{
			dupDat++;
		}
		date = (tidDat10<<4)| dupDat;
		break;
		case 0x0D :
		dupMon10 = tidMon10;
		dupMon = tidMon;
		if(tidMon == 9 && tidMon10==0){
			dupMon = 0;
			dupMon10 = 1;
		} else if(dupMon10 == 1 && dupMon == 2){
			dupMon = 1;
			dupMon10 = 0;
		}
		else {
			dupMon++;
		}
		month = (dupMon10<<4)| dupMon;
		break;
		case 0x4F :
		dupYear = tidYear;
		if(tidYear == 9){
			dupYear = 0;
		}
		else{
			dupYear++;
		}
		year = (tidYear10<<4)| dupYear;
		break;

		case 0x4E :
		dupYear10 = tidYear10;
		if(tidYear10 == 9){
			dupYear10 = 0;
		}
		else{
			dupYear10++;
		}
		year = (dupYear10<<4)| tidYear;
		break;

		case 0x49 :
		if(alarmMin10 == 53){
			alarmMin10 = 48;
			} else{
			alarmMin10++;
		}
		break;
		case 0x4A :
		if(alarmMin == 57){
			alarmMin = 48;
		}
		else{
			alarmMin++;
		}
		break;
		case 0x46 :
		if(alarmHour10 >= 50){
			alarmHour10 = 48;
		}
		else if(alarmHour10==49 && alarmHour>=52){
			alarmHour10 = 48;
		}
		else{
			alarmHour10++;
		}		
		break;
		case 0x47 :
		if(alarmHour == 57 && alarmHour10<50){
			alarmHour = 48;
		}
		else if(alarmHour10 >= 50 && alarmHour >= 52){	// i mån av tid lägger vi till + 10 h
			alarmHour = 48;
		}
		else{
			alarmHour++;
		}
		
		break;
	}
	
}

void litetPip(){
	for(int i=0;i<3;i++){
		_delay_ms(1);
		PORTB = (1<<3);
		_delay_ms(1);
		PORTB = (0<<3);
	}
}
	
void Alarm(){
	for(int i=0;i<20;i++){
		litetPip();
	}
}

void alarmOnOff(){
	if(currentPos == 0x46 ||  currentPos ==0x47 ||  currentPos ==0x49 ||  currentPos ==0x4A){
		currentPos = 0x04;
	}
	
	if(alarmOn==1){
		alarmOn=0;
	}
	else if(alarmOn==0){
		alarmOn=1;
	}
	
	writeAlarmDisplay();
}


char buttonDebounce(){
	previousButton = PIND;
	_delay_ms(20);
	currentButton = PIND;
	if(currentButton == previousButton){
		_delay_ms(100);
		return currentButton;
		}else{
		return 0;
	}
	return 0;
}

void resetPORTD(){
	DDRD = 0xFF;
	PORTD = 0xFF;
	_delay_ms(1);
	PORTD = 0x00;
	DDRD = 0x00;
}

void buttonAction(char Button){
	
	if(buttonResult != 0){
		switch(buttonResult) {
			case 0x04  :
			alarmOnOff();
			break;
		
			case 0x08  :
			reverseMovement();
			moveCursor(currentPos);
			break;
		
			case 0x10  :
			cursorMovement();
			moveCursor(currentPos);
		
			break;
		
			case 0x20  :
			changeTime();
			writeAlarmDisplay();
			break;
		}
	}
	
}

int main(void){
	DDRD = 0x00; //Knappar insignal
	//Alarm();
	//TWI_crystalInit();
	//timeInit(1, 9, 0, 5, 1, 6, 1, 4, 0, 2, 5, 0);
	Animation();
	displayInit();
	
	while (1){
		timeOnDisplay();
		alarmTrig();
		
		testCommit();
		
		resetPORTD();
		buttonResult = buttonDebounce(); 
		buttonAction(buttonResult);
	}
}