/* 
	countdown.pde
	Eric Ayars
	8/18/11

	Countdown timer 
	This program displays days, hours, minutes, and seconds until some
	specified time. At that time (and aftwards) it displays a message.
*/

#include <Wire.h>
#include "DS3231.h"
#include <LiquidCrystal.h>
#include <avr/sleep.h>

#define SECONDSINDAY 86400
#define SECONDSINHOUR 3600
#define SECONDSINMINUTE 60

unsigned long remSeconds, remMinutes, remHours, remDays;
byte year, month, day, hour, minute, second, DoW;

// Put your target date here. 
byte targetYear = 11; 
byte targetMonth = 12;
byte targetDay = 25;
byte targetHour = 0;
byte targetMinute = 0;
byte targetSecond = 0;

unsigned int monthdays[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};

bool century, h24, ampm;
unsigned long targetDate;
unsigned long Now, dT;

DS3231 RTC;
LiquidCrystal lcd(8,9,7,6,5,4);

unsigned long secondsSince2000(unsigned int year, byte month, byte day, byte hour, byte minute, byte second)
{
	// This code stolen from someene else's DS1337 library. It was called 
	// "date_to_epoch_seconds()" there, but it didn't do epoch seconds,
	// just seconds since 2000. That's fine in this case, since seconds
	// since 2000 is sufficient for this purpose.
  unsigned long sse = (((unsigned long)year)*365*24*60*60)   +   ((((unsigned long)year+3)>>2) + ((unsigned long)year%4==0 && (unsigned long)month>2))*24*60*60   +   \
         ((unsigned long)monthdays[month-1] + (unsigned long)day-1) *24*60*60   +   ((unsigned long)hour*60*60)   +   ((unsigned long)minute*60)   + (unsigned long)second;

  return sse;
}

void celebrate() {
	// Put whatever you want here. You could of course do more than just
	// a static message.
	lcd.setCursor(0, 0);
	lcd.print("     Merry      ");
	lcd.setCursor(0, 1);
	lcd.print("   Christmas!   ");
	
	// Stay stuck here, leaving the message.
	set_sleep_mode(SLEEP_MODE_POWER_DOWN);
	sleep_enable();
	sleep_mode();

	/*	It wouldn't be difficult to change this so that it displayed the
		Merry Christmas message for a day and then started counting down
		to next year. I decided not to make it Christmas-specific, though,
		so it can also be used for other nice countdowns such as the end
		of the school term and so on.  */
}

void setup() {
	Wire.begin();
	lcd.begin(2,16);
	targetDate =secondsSince2000(targetYear, targetMonth, targetDay, targetHour, targetMinute, targetSecond);
}

void loop() {
	
	year = RTC.getYear();
	month = RTC.getMonth(century);
	if (century) year += 100;
	day = RTC.getDate();
	hour = RTC.getHour(h24, ampm);
	if ((h24) && (ampm)) hour += 12;
	minute = RTC.getMinute();
	second = RTC.getSecond();
	Now = secondsSince2000(year, month, day, hour, minute, second);

	// Are we past the countdown?
	if (Now >= targetDate) {
		celebrate();
	}

	// Here's the time remaining.
	dT = targetDate - Now;

	// Figure out whole days remaining
	remDays = dT/SECONDSINDAY;

	// Here's the leftover HMS
	remSeconds = dT%SECONDSINDAY;
	
	// Figure out the whole hours remaining
	remHours = remSeconds/SECONDSINHOUR;

	// Here's the leftover MS
	remSeconds = remSeconds%SECONDSINHOUR;

	// Figure out the whole minutes remaining
	remMinutes = remSeconds/SECONDSINMINUTE;

	// Here's the leftover S
	remSeconds = remSeconds%SECONDSINMINUTE;

	// Make sure we're dealing with a blank display
	lcd.clear();

	// Print the top line to the display
	lcd.setCursor(0,0);
	lcd.print(remDays, DEC);
	lcd.setCursor(4,0);
	lcd.print("Days ");
	lcd.setCursor(9,0);
	lcd.print(remHours, DEC);
	lcd.setCursor(12,0);
	lcd.print("Hrs ");

	// Print the bottom line to the display
	lcd.setCursor(0,1);
	lcd.print(remMinutes, DEC);
	lcd.setCursor(4,1);
	lcd.print("Min ");
	lcd.setCursor(9,1);
	lcd.print(remSeconds, DEC);
	lcd.setCursor(12,1);
	lcd.print("Sec ");

	// No need running this more than 4x per second, really... 
	delay(250);
}