/*
// Typhon firmware
// v0.2 alpha 2010-23-11
// N. Enders, R. Ensminger
// Changes made by BoostLED have notations as below.
// This sketch provides firmware for the Typhon LED controller.
// It provides a structure to fade 4 independent channels of LED lighting
// on and off each day, to simulate sunrise and sunset.
//
// Current work in progress:
// - store all LED variables in EEPROM so they are not reset by a loss of power
//
// Future developments may include:
// - moon phase simulation
// - storm simulation
// 
// Sketch developed in Arduino-18
// Requires LiquidCrystal, Wire, EEPROM, EEPROMVar, and Button libraries.
// Button is available here: http://www.arduino.cc/playground/Code/Button
// EEPROMVar is available here: http://www.arduino.cc/playground/uploads/Profiles/EEPROMVar_01.zip
*/
// include the libraries:
#include <Button.h>
#include <EEPROMVar.h>
#include <EEPROM.h>
#include <LiquidCrystal.h>
#include <Wire.h>
/**** Define Variables & Constants ****/
/**************************************/
// set the RTC's I2C address
#define DS1307_I2C_ADDRESS 0x68
// create the LCD
LiquidCrystal lcd(8, 7, 5, 4, 16, 2);
// set up backlight
int bkl         = 6;        // backlight pin
byte bklIdle    = 10;       // PWM value for backlight at idle
byte bklOn      = 70;       // PWM value for backlight when on
int bklDelay    = 10000;    // ms for the backlight to idle before turning off
unsigned long bklTime = 0;  // counter since backlight turned on
// create the menu counter
int menuCount   = 1;
int menuSelect = 0;
//create manual override variables
boolean override = false;
byte overmenu = 0;
int overpercent = 0;
// create the buttons
Button menu = Button(12,PULLDOWN);
Button select = Button(13,PULLDOWN);
Button plus = Button(14,PULLDOWN);
Button minus = Button(15,PULLDOWN);
// Button state constants.
byte buttonNotPressed  = 0;
byte buttonUniquePress = 1;
byte buttonIsPressed   = 2;
byte slowCount = 3;         // number of intervals to do a "slowDelay" when holding a button
int slowDelay = 1000;       // milliseconds to delay when initially holding a button
int fastDelay = 100;        // milliseconds to delay after holding the button for "slowCount" intervals
// LED variables. These control the behavior of lighting. Change these to customize behavoir
int minCounter = 0;         // counter that resets at midnight.
int oldMinCounter = 0;      // counter that resets at midnight.
EEPROMVar<boolean> inverted = false; //Modified by NetSurge
// Used for button hold down
int intervalCounter = 0;
int oldIntervalCounter;
unsigned long currMil = 0;         // current millisecond
int oneVal = 0;             // current value for channel 1
int twoVal = 0;             // current value for channel 2
int threeVal = 0;           // current value for channel 3
int fourVal = 0;            // current value for channel 4
// Variables making use of EEPROM memory:
EEPROMVar<int> oneStartMins = 750;     // minute to start this channel.
EEPROMVar<int> onePhotoPeriod = 720;   // photoperiod in minutes for this channel.
EEPROMVar<int> oneMax = 100;           // max intensity for this channel, as a percentage
EEPROMVar<int> oneFadeDuration = 60;   // duration of the fade on and off for sunrise and sunset for
                                      //    this channel.
EEPROMVar<int> twoStartMins = 810;
EEPROMVar<int> twoPhotoPeriod = 600;
EEPROMVar<int> twoMax = 100;
EEPROMVar<int> twoFadeDuration = 60;
EEPROMVar<int> threeStartMins = 810;
EEPROMVar<int> threePhotoPeriod = 600;
EEPROMVar<int> threeMax = 100;
EEPROMVar<int> threeFadeDuration = 60;
EEPROMVar<int> fourStartMins = 480;
EEPROMVar<int> fourPhotoPeriod = 510;  
EEPROMVar<int> fourMax = 100;          
EEPROMVar<int> fourFadeDuration = 60;  
typedef struct {
 int Led;            // channel pin
 int StartMins;      // minute to start this channel.
 int PhotoPeriod;    // photoperiod in minutes for this channel.
 int Max;            // max intensity for this channel, as a percentage
 int FadeDuration;   // duration of the fade on and off for sunrise and sunset for
                     //    this channel.
} 
channelVals_t;
channelVals_t channel[4];
/*
int oneStartMins = 1380;    // minute to start this channel.
int onePhotoPeriod = 120;   // photoperiod in minutes for this channel.
int oneMax = 100;           // max intensity for this channel, as a percentage
int oneFadeDuration = 60;   // duration of the fade on and off for sunrise and sunset for
                            //    this channel.                                    
int twoStartMins = 800;
int twoPhotoPeriod = 60;
int twoMax = 100;
int twoFadeDuration = 15;
int threeStartMins = 800;
int threePhotoPeriod = 60;
int threeMax = 100;
int threeFadeDuration = 30;
int fourStartMins = 800;
int fourPhotoPeriod = 120;  
int fourMax = 100;          
int fourFadeDuration = 60;  
*/
/****** RTC Functions ******/
/***************************/
// Convert decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
 return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to decimal numbers
byte bcdToDec(byte val)
{
 return ( (val/16*10) + (val%16) );
}
// Sets date and time, starts the clock
void setDate(byte second,        // 0-59
byte minute,        // 0-59
byte hour,          // 1-23
byte dayOfWeek,     // 1-7
byte dayOfMonth,    // 1-31
byte month,         // 1-12
byte year)          // 0-99
{
 Wire.beginTransmission(DS1307_I2C_ADDRESS);
 Wire.write(0);
 Wire.write(decToBcd(second));
 Wire.write(decToBcd(minute));
 Wire.write(decToBcd(hour));
 Wire.write(decToBcd(dayOfWeek));
 Wire.write(decToBcd(dayOfMonth));
 Wire.write(decToBcd(month));
 Wire.write(decToBcd(year));
 Wire.endTransmission();
}
// Gets the date and time
void getDate(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
 Wire.beginTransmission(DS1307_I2C_ADDRESS);
 Wire.write(0);
 Wire.endTransmission();
 Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
 *second     = bcdToDec(Wire.read() & 0x7f);
 *minute     = bcdToDec(Wire.read());
 *hour       = bcdToDec(Wire.read() & 0x3f);
 *dayOfWeek  = bcdToDec(Wire.read());
 *dayOfMonth = bcdToDec(Wire.read());
 *month      = bcdToDec(Wire.read());
 *year       = bcdToDec(Wire.read());
}
/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
//function has three equal phases - ramp up, hold, and ramp down
int   setLed(int mins,    // current time in minutes
int ledPin,  // pin for this channel of LEDs
int start,   // start time for this channel of LEDs
int period,  // photoperiod for this channel of LEDs
int fade,    // fade duration for this channel of LEDs
int ledMax   // max value for this channel
)  {
 int val = 0;
 //fade up
 if (mins > start || mins <= start + fade)  {
   val = map(mins - start, 0, fade, 0, ledMax);
 }
 //fade down
 if (mins > start + period - fade && mins <= start + period)  {
   val = map(mins - (start + period - fade), 0, fade, ledMax, 0);
 }
 //off or post-midnight run.
 if (mins <= start || mins > start + period)  {
   if((start+period)%1440 < start && (start + period)%1440 > mins )
   {
     val=map((start+period-mins)%1440,0,fade,0,ledMax);
   }
   else  
     val = 0; 
 }
//invert for BuckPuck Functions
//Added by NetSurge
if(inverted){
//  val=~val;
//  val=val&255;
//  ledMax=~ledMax;
//  ledMax=100-ledMax;
}
 if (val > ledMax)  {
   val = ledMax;
 } 
 if (val < 0) {
   val = 0; 
 } 
if(inverted){
 analogWrite(ledPin, map(val, 0, 100, 255, 0));
}
else{
 analogWrite(ledPin, map(val, 0, 100, 0, 255));
}
//Debugging info 0-255 PWM Output
//Modified by NetSurge
/*
if(inverted){
if(ledPin == 9){
lcd.setCursor(0,0);
 lcd.print(map(val, 0, 100, 255, 0));
}
if(ledPin == 10){
 lcd.setCursor(4,0);
 lcd.print(map(val, 0, 100, 255, 0));
}
if(ledPin == 11){
 lcd.setCursor(8,0);
 lcd.print(map(val, 0, 100, 255, 0));
}
if(ledPin == 3){
 lcd.setCursor(12,0);
 lcd.print(map(val, 0, 100, 255, 0));
}
}
else{
if(ledPin == 9){
lcd.setCursor(0,0);
 lcd.print(map(val, 0, 100, 0, 255));
}
if(ledPin == 10){
 lcd.setCursor(4,0);
 lcd.print(map(val, 0, 100, 0, 255));
}
if(ledPin == 11){
 lcd.setCursor(8,0);
 lcd.print(map(val, 0, 100, 0, 255));
}
if(ledPin == 3){
 lcd.setCursor(12,0);
 lcd.print(map(val, 0, 100, 0, 255));
 }
}
*/
 if(override){
   val=overpercent;
 }
 return val;
}
/**** Display Functions ****/
/***************************/
// format a number of minutes into a readable time (24 hr format)
void printMins(int mins,       //time in minutes to print
boolean ampm    //print am/pm?
)  {
 int hr = (mins%1440)/60;
 int mn = mins%60;
 if(hr<10){
   lcd.print(" ");
 }
 lcd.print(hr);
 lcd.print(":");
 if(mn<10){
   lcd.print("0");
 }
 lcd.print(mn); 
}
// format hours, mins, secs into a readable time (24 hr format)
void printHMS (byte hr,
byte mn,
byte sec      //time to print
)  
{
 if(hr<10){
   lcd.print(" ");
 }
 lcd.print(hr, DEC);
 lcd.print(":");
 if(mn<10){
   lcd.print("0");
 }
 lcd.print(mn, DEC);
 lcd.print(":");
 if(sec<10){
   lcd.print("0");
 }
 lcd.print(sec, DEC);
}
void ovrSetAll(int pct){
 analogWrite(channel[0].Led, map(pct,0,100,0,255));
 analogWrite(channel[1].Led, map(pct,0,100,0,255));
 analogWrite(channel[2].Led, map(pct,0,100,0,255));
 analogWrite(channel[3].Led, map(pct,0,100,0,255));
}
byte buttonCheck(Button *button) {
 if (button->uniquePress()) {
   return buttonUniquePress;
 } 
 else if (button->isPressed()) {
   return buttonIsPressed;
 } 
 else {
   return buttonNotPressed;
 }
}
boolean checkButtonAction(Button *button) {
 byte buttonState = buttonCheck(button);
 unsigned long mil = millis();
 if (buttonState == buttonUniquePress) {
   intervalCounter = slowCount;
   currMil = mil;
   return true;
 } 
 else if (buttonState == buttonIsPressed) {
   if (intervalCounter > 0) {
     if (currMil < (mil - slowDelay)) {
       intervalCounter--;
       currMil = mil;
       return true;
     }
   } 
   else {
     if (currMil < (mil - fastDelay)) {
       currMil = mil;
       return true;
     }
   }
 }
 return false;
}
/**** Setup ****/
/***************/
void setup() {
 // Initialize channel variables. Set LED channel pin and retrieve values from EEPROM
 channel[0].Led = 9;
 channel[0].StartMins = oneStartMins;
 channel[0].PhotoPeriod = onePhotoPeriod;
 channel[0].Max = oneMax;
 channel[0].FadeDuration = oneFadeDuration;
 channel[1].Led = 10;
 channel[1].StartMins = twoStartMins;
 channel[1].PhotoPeriod = twoPhotoPeriod;
 channel[1].Max = twoMax;
 channel[1].FadeDuration = twoFadeDuration;
 channel[2].Led = 11;
 channel[2].StartMins = threeStartMins;
 channel[2].PhotoPeriod = threePhotoPeriod;
 channel[2].Max = threeMax;
 channel[2].FadeDuration = threeFadeDuration;
 channel[3].Led = 3;
 channel[3].StartMins = fourStartMins;
 channel[3].PhotoPeriod = fourPhotoPeriod;
 channel[3].Max = fourMax;
 channel[3].FadeDuration = fourFadeDuration;
// Title & Credits added
 Wire.begin();
 pinMode(bkl, OUTPUT);
 lcd.begin(16, 2);
 digitalWrite(bkl, HIGH);
 lcd.setCursor(0,0); //Modified by NetSurge
 lcd.print("Typhon Reef LED");
 lcd.setCursor(0,1);
 lcd.print("Controller"); 
 delay(1000);
 lcd.clear();
 lcd.setCursor(0,0);
 lcd.print("by N. Enders &");
 lcd.setCursor(0,1);
 lcd.print("R. Ensminger    ");
 delay(1000);
 lcd.clear();
 lcd.setCursor(0,0);
 lcd.print("Brought to you  ");
 lcd.setCursor(0,1);
 lcd.print("by BoostLED     ");
 delay(2000);
 lcd.clear();
 analogWrite(bkl,bklIdle);
}
/***** Loop *****/
/****************/
void loop() {
 byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
 getDate(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
 oldMinCounter = minCounter;
 minCounter = hour * 60 + minute;
 int i;
 for (i=0; i<4; i++) {
   //check & set fade durations
   if(channel[i].FadeDuration > channel[i].PhotoPeriod/2 && channel[i].PhotoPeriod >0) {
     channel[i].FadeDuration = channel[i].PhotoPeriod/2;
   }
   if(channel[i].FadeDuration<1){
     channel[i].FadeDuration=1;
   }
 }
 //check & set any time functions
 //set outputs
 if(!override){
   oneVal = setLed(minCounter, channel[0].Led, channel[0].StartMins, channel[0].PhotoPeriod, channel[0].FadeDuration, channel[0].Max);
   twoVal = setLed(minCounter, channel[1].Led, channel[1].StartMins, channel[1].PhotoPeriod, channel[1].FadeDuration, channel[1].Max);
   threeVal = setLed(minCounter, channel[2].Led, channel[2].StartMins, channel[2].PhotoPeriod, channel[2].FadeDuration, channel[2].Max);
   fourVal = setLed(minCounter, channel[3].Led, channel[3].StartMins, channel[3].PhotoPeriod, channel[3].FadeDuration, channel[3].Max);
 }
 else{
   oneVal = overpercent;
   twoVal = overpercent;
   threeVal = overpercent;
   fourVal = overpercent;
   ovrSetAll(overpercent);
 }
 // Update EEProms with any values that may have changed
 if (channel[0].StartMins != oneStartMins) {
   oneStartMins = channel[0].StartMins;
 }
 if (channel[0].PhotoPeriod != onePhotoPeriod) {
   onePhotoPeriod = channel[0].PhotoPeriod;
 }
 if (channel[0].Max != oneMax) {
   oneMax = channel[0].Max;
 }
 if (channel[0].FadeDuration != oneFadeDuration) {
   oneFadeDuration = channel[0].FadeDuration;
 }
 if (channel[1].StartMins != twoStartMins) {
   twoStartMins = channel[1].StartMins;
 }
 if (channel[1].PhotoPeriod != twoPhotoPeriod) {
   twoPhotoPeriod = channel[1].PhotoPeriod;
 }
 if (channel[1].Max != twoMax) {
   twoMax = channel[1].Max;
 }
 if (channel[1].FadeDuration != twoFadeDuration) {
   twoFadeDuration = channel[1].FadeDuration;
 }
 if (channel[2].StartMins != threeStartMins) {
   threeStartMins = channel[2].StartMins;
 }
 if (channel[2].PhotoPeriod != threePhotoPeriod) {
   threePhotoPeriod = channel[2].PhotoPeriod;
 }
 if (channel[2].Max != threeMax) {
   threeMax = channel[2].Max;
 }
 if (channel[2].FadeDuration != threeFadeDuration) {
   threeFadeDuration = channel[2].FadeDuration;
 }
 if (channel[3].StartMins != fourStartMins) {
   fourStartMins = channel[3].StartMins;
 }
 if (channel[3].PhotoPeriod != fourPhotoPeriod) {
   fourPhotoPeriod = channel[3].PhotoPeriod;
 }
 if (channel[3].Max != fourMax) {
   fourMax = channel[3].Max;
 }
 if (channel[3].FadeDuration != fourFadeDuration) {
   fourFadeDuration = channel[3].FadeDuration;
 }
 //  if (intervalCounter > 0) {
 //    unsigned long milsec = millis();
 //    if ((currMil < (milsec - 1000)) || (currMil > milsec)) {
 //      currMil = milsec;
 //      intervalCounter--;
 //    }
 //  }
 //turn the backlight off and reset the menu if the idle time has elapsed
 if(bklTime + bklDelay < millis() && bklTime > 0 ){
   analogWrite(bkl,bklIdle);
   menuCount = 1;
   lcd.clear();
   bklTime = 0;
 }
 //iterate through the menus
 if(menu.uniquePress()){
   analogWrite(bkl,bklOn);
   bklTime = millis();
   if(menuCount < 21){  //Modified by NetSurge
     menuCount++;
   }
  else {
     menuCount = 1;
   }
   lcd.clear();
 }
 switch (menuCount) {
 case 1:
   doMainMenu(minCounter, oldMinCounter, hour, minute, second,
   oneVal, twoVal, threeVal, fourVal);
   break;
 case 2:
   doOverride(second);
   break;
 case 3:
   doStartTime(0);
   break;
 case 4:
   doEndTime(0);
   break;
 case 5:
   doFadeDuration(0);
   break;
 case 6:
   doMaxIntensity(0);
   break;
 case 7:
  doStartTime(1);
   break;
 case 8:
   doEndTime(1);
   break;
 case 9:
   doFadeDuration(1);
   break;
 case 10:
   doMaxIntensity(1);
   break;
 case 11:
   doStartTime(2);
   break;
 case 12:
   doEndTime(2);
   break;
 case 13:
   doFadeDuration(2);
   break;
 case 14:
   doMaxIntensity(2);
   break;
 case 15:
   doStartTime(3);
   break;
 case 16:
   doEndTime(3);
   break;
 case 17:
   doFadeDuration(3);
   break;
 case 18:
   doMaxIntensity(3);
   break;
 case 19:
   setHour(&hour, minute, second, dayOfWeek, dayOfMonth, month, year);
   break;
 case 20:
   setMinute(hour, &minute, second, dayOfWeek, dayOfMonth, month, year);
   break;
 case 21:
doinvertPWM();
 break;
 }
}
void doMainMenu(int minCounter,
int oldMinCounter,
byte hour,
byte minute,
byte second,
int oneVal,
int twoVal,
int threeVal,
int fourVal) {
//main screen turn on!!!
 if (minCounter > oldMinCounter){
   lcd.clear();
 }
 lcd.setCursor(0,0);
//Take out display time and uncomment in the led funtion for PWM value debugging
//NetSurge
 lcd.print("Time: "); // Displays Time.
 printHMS(hour, minute, second);
 lcd.setCursor(0,1);
 lcd.print(oneVal);
 lcd.setCursor(4,1);
 lcd.print(twoVal);
 lcd.setCursor(8,1);
 lcd.print(threeVal);
 lcd.setCursor(12,1);
 lcd.print(fourVal);
if(inverted){
  lcd.setCursor(15,0);
  lcd.print("V");
 }
 //debugging function to use the select button to advance the timer by 1 minute
 //if(select.uniquePress()){setDate(second, minute+1, hour, dayOfWeek, dayOfMonth, month, year);}
}
void doOverride(byte second) {
 //Manual Override Menu
 lcd.setCursor(0,0);
 lcd.print("SETTING MODE:        "); // Changed by BoostLED
 lcd.setCursor(0,1);
//if(menuSelect ==4){
//menuSelect = 0;            //modified by NetSurge
//}
 if(select.uniquePress()){
   if(menuSelect < 4){
     menuSelect++;
   }
   else{
     menuSelect = 0;
   }
   bklTime = millis();
 }
 if(menuSelect == 0){
   lcd.print("Timer           "); // Changed by BoostLED
   override = false;
 }
 if(menuSelect == 1){
   lcd.print("All Channels ON "); // Changed by BoostLED
   overpercent = 100;
   override = true;
 }
 if(menuSelect == 2){
   lcd.print("All Channels OFF"); // Changed by BoostLED
   overpercent = 0;
   override = true;
 }    
 if(menuSelect == 3){
   override = true;
   lcd.print("Custom ");   // Added by BoostLED
   lcd.print(overpercent,DEC);
   lcd.print("%        "); 
   if (overpercent < 100) {
     if (checkButtonAction(&plus)) {
       overpercent++;
       bklTime = millis();
     }
    }
   if (overpercent > 0) {
     if (checkButtonAction(&minus)) {
       overpercent--;
       bklTime = millis();
     }
   }
 }
 
//invert PWM 
//Modified by NetSurge
/* Moved to Main Menu and not in Overide Menu
if(menuSelect == 4){
  if(inverted == true)
 lcd.print("PWM Inverted:YES ");
  if(inverted == false)
 lcd.print("PWM Inverted:NO ");
 if (checkButtonAction(&minus) || checkButtonAction(&plus)) {
  inverted = !inverted;
}
override = false;
}
*/
}
void doStartTime(int val) {
 //set start time
 lcd.setCursor(0,0);
 lcd.print("Channel ");
 lcd.print(val+1);
 lcd.print(" Start");
 lcd.setCursor(0,1);
 printMins(channel[val].StartMins, true);
 if (channel[val].StartMins < 1440) {
   if (checkButtonAction(&plus)) {
     channel[val].StartMins++;
     if (channel[val].PhotoPeriod > 0) {
       channel[val].PhotoPeriod--;
     } 
    else {
        channel[val].PhotoPeriod = 1439;
     }
     bklTime = millis();
   }
 } 
 if (channel[val].StartMins > 0) {
   if (checkButtonAction(&minus)) {
     channel[val].StartMins--;
     if (channel[val].PhotoPeriod < 1439) {
       channel[val].PhotoPeriod++;
     } 
    else {
       channel[val].PhotoPeriod=0;
     }
     bklTime = millis();
   }
 } 
}
void doEndTime(int val) {
 //set end time
 lcd.setCursor(0,0);
 lcd.print("Channel ");
 lcd.print(val+1);
 lcd.print(" End");
 lcd.setCursor(0,1);
 printMins(channel[val].StartMins+channel[val].PhotoPeriod, true);
 if (checkButtonAction(&plus)) {
   if(channel[val].PhotoPeriod < 1439){
     channel[val].PhotoPeriod++;
   } 
   else {
     channel[val].PhotoPeriod=0;
   }
   bklTime = millis();
 }
 if (checkButtonAction(&minus)) {
   if(channel[val].PhotoPeriod > 0){
     channel[val].PhotoPeriod--;
   } 
   else {
     channel[val].PhotoPeriod = 1439;
   }
   bklTime = millis();
 }
}
void doFadeDuration(int val) {
 //set fade duration
 lcd.setCursor(0,0);
 lcd.print("Channel ");
 lcd.print(val+1);
 lcd.print(" Fade");
 lcd.setCursor(0,1);
 lcd.print("Duration ");
 printMins(channel[val].FadeDuration, false);
 if (channel[val].FadeDuration < channel[val].PhotoPeriod/2 || channel[val].FadeDuration == 0) {
   if (checkButtonAction(&plus)) {
     channel[val].FadeDuration++;
     bklTime = millis();
   }
 }
 if (channel[val].FadeDuration > 1) {
   if (checkButtonAction(&minus)) {
     channel[val].FadeDuration--;
     bklTime = millis();
   }
 }
}
void doMaxIntensity(int val) {
 //set intensity
 lcd.setCursor(0,0);
 lcd.print("Channel ");
 lcd.print(val+1);
 lcd.print(" Max");
 lcd.setCursor(0,1);
 lcd.print("Level: "); // Added by BoostLED
 lcd.print(channel[val].Max);
 lcd.print("%        "); // Added by BoostLED
 if (channel[val].Max < 100) {
   if (checkButtonAction(&plus)) {
     lcd.clear();
     channel[val].Max++;
     bklTime = millis();
   }
 }
 if (channel[val].Max > 0) {
   if (checkButtonAction(&minus)) {
     lcd.clear();
     channel[val].Max--;
     bklTime = millis();
   }
 }
}
//Select Inverted PWM or not
//Added  By NetSurge
void doinvertPWM() {
lcd.setCursor(0,0);
 lcd.print("PWM Inverted... ");
lcd.setCursor(0,1);
  if(inverted == true)
 lcd.print("YES ");
  if(inverted == false)
 lcd.print("NO ");
 if (checkButtonAction(&minus) || checkButtonAction(&plus)) {
  inverted = !inverted;
}
}
void setHour(byte *hour, byte minute, byte second,
byte dayOfWeek, byte dayOfMonth, byte month, byte year) {
 //set hours
 lcd.setCursor(0,0);
 lcd.print("Set Time: Hrs");
 lcd.setCursor(0,1);
 printHMS(*hour, minute, second);
 if (checkButtonAction(&plus)) {
   if (*hour < 23) {
     (*hour)++;
   } 
  else {
     *hour = 0;
   }
   bklTime = millis();
 }
 if (checkButtonAction(&minus)) {
   if (*hour > 0) {
     (*hour)--;
   } 
   else {
     *hour = 23;
   }
   bklTime = millis();
 }
 setDate(second, minute, *hour, dayOfWeek, dayOfMonth, month, year);
}
void setMinute(byte hour, byte *minute, byte second,
byte dayOfWeek, byte dayOfMonth, byte month, byte year) {
 //set minutes
 lcd.setCursor(0,0);
 lcd.print("Set Time: Mins");
 lcd.setCursor(0,1);
 printHMS(hour, *minute, second);
 if (checkButtonAction(&plus)) {
   if (*minute < 59) {
     (*minute)++;
   } 
  else {
     *minute = 0;
   }
   bklTime = millis();
 }
 if (checkButtonAction(&minus)) {
   if (*minute > 0) {
     (*minute)--;
   } 
  else {
     *minute = 59;
   }
   bklTime = millis();
 }
 setDate(second, *minute, hour, dayOfWeek, dayOfMonth, month, year);
}