//==============================================================================
//
//	DS1307.h
//
//		fabian.traczuk@gmail.com
//==============================================================================
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <avr/pgmspace.h>
#include "twi.h"

// DS1307 defines
#define DS1307_SLA 0x68  // Slave Address

#define RTC_REGISTER_SECOND		0x00
#define RTC_REGISTER_MINUTES	0x01
#define RTC_REGISTER_HOURS		0x02
#define RTC_REGISTER_DAY		0x03
#define RTC_REGISTER_DATE		0x04
#define RTC_REGISTER_MONTH		0x05
#define RTC_REGISTER_YEAR		0x06
#define RTC_REGISTER_CONTROL	0x07
#define RTC_SQWAVE_1HZ			0x00
#define RTC_SQWAVE_4096HZ		0x01
#define RTC_SQWAVE_8192HZ		0x02
#define RTC_SQWAVE_32768HZ		0x03
#define RTC_SQWAVE_ON			0x10
#define RTC_SQWAVE_OFF			0x00

char RTC_SetTime(char Hh, char Mm, char Ss);
char RTC_SetDate(char Yy, char Mm, char Dd);
char RTC_SetDay(char day);
char RTC_SquareWaveControl(char Freq, unsigned char OnOff);
char RTC_ReadDateTime(void);

typedef struct {
  unsigned char seconds;
  unsigned char minutes;
  unsigned char hours;
  unsigned char day;
  unsigned char date;
  unsigned char month;
  unsigned char year;
  unsigned char rs;			// rate select
} ds1307Reg_t;

ds1307Reg_t TimeAndDate;

//---------------------------------------------------------------------------------
//	RTC_SetTime
//---------------------------------------------------------------------------------
char RTC_SetTime(char Hh, char Mm, char Ss)
{
	unsigned char ioBuffer[4];

	// write time
	ioBuffer[0] = RTC_REGISTER_SECOND;
	ioBuffer[1] = Ss;
	ioBuffer[2] = Mm;
	ioBuffer[3] = Hh;

	if(TWI_Write(DS1307_SLA, ioBuffer, 4) > 0 )
		return 1;

	return 0;
}

//---------------------------------------------------------------------------------
//	setDate
//---------------------------------------------------------------------------------
char RTC_SetDate(char Yy, char Mm, char Dd)
{
	unsigned char ioBuffer[4];

	// write date7
	ioBuffer[0] = RTC_REGISTER_DATE;
	ioBuffer[1] = Dd;
	ioBuffer[2] = Mm;
	ioBuffer[3] = Yy;

	if(TWI_Write(DS1307_SLA, ioBuffer, 4) > 0 )
		return 1;

	return 0;
}

//---------------------------------------------------------------------------------
//	RTC_SetDay
//---------------------------------------------------------------------------------
char RTC_SetDay(char day)
{
	unsigned char ioBuffer[2];

	// write day
	ioBuffer[0] = RTC_REGISTER_DAY;
	ioBuffer[1] = day;

	if(TWI_Write(DS1307_SLA, ioBuffer, 2) > 0 )
		return 1;

	return 0;
}

//---------------------------------------------------------------------------------
//	squareWaveControl
//
//					RS1-RS0 = Freq
//		1HZ:		0-0
//		4096HZ:		0-1
//		7192HZ:		1-0
//		32768HZ:	1-1
//---------------------------------------------------------------------------------
char RTC_SquareWaveControl(char Freq, unsigned char OnOff)
{
	unsigned char ioBuffer[2];

	// write output control
	ioBuffer[0] = RTC_REGISTER_CONTROL;
	if(OnOff != RTC_SQWAVE_ON)
		ioBuffer[1] = Freq;
	else
		ioBuffer[1] = RTC_SQWAVE_ON | Freq;

	if(TWI_Write( DS1307_SLA, ioBuffer, 2 ) > 0 )
		return 1;

	return 0;
}
          
//---------------------------------------------------------------------------------
//	showDateTime
//---------------------------------------------------------------------------------
char RTC_ReadDateTime(void)
{
	unsigned char RegAddress;
	char decenas = 0x00;
	char gTime = 0x00;

	// write DS1307 register address
	RegAddress = RTC_REGISTER_SECOND;
	TWI_Write( DS1307_SLA, &RegAddress, 1 );

	// read DS1307 registers
	if(TWI_Read(DS1307_SLA, (unsigned char *)&TimeAndDate, 8) > 0 )
		return 1;

	decenas = ((TimeAndDate.seconds & 0x70)>>4) * 10;
	gTime = decenas + (TimeAndDate.seconds & 0x0F);
	TimeAndDate.seconds = gTime;

	decenas = ((TimeAndDate.minutes & 0x70)>>4) * 10;
	gTime = decenas + (TimeAndDate.minutes & 0x0F);
	TimeAndDate.minutes = gTime;

	decenas = ((TimeAndDate.hours & 0x30)>>4) * 10;
	gTime = decenas + (TimeAndDate.hours & 0x0F);
	TimeAndDate.hours = gTime;

	decenas = ((TimeAndDate.date & 0x30)>>4) * 10;
	gTime = decenas + (TimeAndDate.date & 0x0F);
	TimeAndDate.date = gTime;

	decenas = ((TimeAndDate.month & 0x10)>>4) * 10;
	gTime = decenas + (TimeAndDate.month & 0x0F);
	TimeAndDate.month = gTime;

	decenas = ((TimeAndDate.year & 0xF0)>>4) * 10;
	gTime = decenas + (TimeAndDate.year & 0x0F);
	TimeAndDate.year = gTime;

	return 0;
}
