Rev 21 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/**************************************************************************//**
* \brief Arduino clock.
* \author Copyright (C) 2012 Julien Le Sech - www.idreammicro.com
* \version 1.0
* \date 20120428
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
******************************************************************************/
/**************************************************************************//**
* \file clock.ino
******************************************************************************/
/******************************************************************************
* Header file inclusions.
******************************************************************************/
#include "Keyboard.h"
#include <Deuligne.h>
#include <RTClib.h>
#include <Arduino.h>
#include <Wire.h>
#include <stdio.h>
/******************************************************************************
* Private macro definitions.
******************************************************************************/
#define CLOCK__DAY_MIN 1
#define CLOCK__DAY_MAX 31
#define CLOCK__MONTH_MIN 1
#define CLOCK__MONTH_MAX 12
#define CLOCK__YEAR_MIN 2000
#define CLOCK__YEAR_MAX 2099
#define CLOCK__HOUR_MIN 0
#define CLOCK__HOUR_MAX 23
#define CLOCK__MINUTE_MIN 0
#define CLOCK__MINUTE_MAX 59
#define CLOCK__SECOND_MIN 0
#define CLOCK__SECOND_MAX 59
/******************************************************************************
* Private type definitions.
******************************************************************************/
/**************************************************************************//**
* \enum clock__members
* \brief
*
* \type clock__member_t
* \brief
******************************************************************************/
typedef enum clock__members
{
clock__MemberDay,
clock__MemberMonth,
clock__MemberYear,
clock__MemberHour,
clock__MemberMinute,
clock__MemberSecond
} clock__member_t;
/******************************************************************************
* Private function prototypes.
******************************************************************************/
/**************************************************************************//**
* \fn static void clock__handleKey(Keyboard::Key_t key)
*
* \brief Handle pressed key.
*
* \param key Pressed key.
******************************************************************************/
static
void
clock__handleKey
(
Keyboard::Key_t key
);
/**************************************************************************//**
* \fn static void clock__setCursor()
*
* \brief Set cursor position.
******************************************************************************/
static
void
clock__setCursor();
/**************************************************************************//**
* \fn static clock__incrementMember()
*
* \brief Increment current member: day, month, year, hour, minute or second.
******************************************************************************/
static
void
clock__incrementMember();
/**************************************************************************//**
* \fn static void clock__decrementMember()
*
* \brief Decrement current member: day, month, year, hour, minute or second.
******************************************************************************/
static
void
clock__decrementMember();
/**************************************************************************//**
* \fn static void clock__printDatetime()
*
* \brief Print current datetime.
******************************************************************************/
static
void
clock__printDatetime();
/******************************************************************************
* Private variable declarations.
******************************************************************************/
static Deuligne clock__lcd;
static RTC_DS1307 clock__rtc;
static DateTime clock__currentTime;
static bool clock__adjustMode = false;
static clock__member_t clock__currentMember = clock__MemberDay;
/******************************************************************************
* Public function definitions.
******************************************************************************/
/**************************************************************************//**
* \fn void setup()
*
* \brief System initialization.
******************************************************************************/
void setup()
{
// Initialize TWI bus.
Wire.begin();
// Initialize RTC.
clock__rtc.begin();
// Initialize LCD.
clock__lcd.init();
clock__lcd.clear();
clock__lcd.backLight(true);
// Get current time and print it.
clock__currentTime = clock__rtc.now();
clock__printDatetime();
}
/**************************************************************************//**
* \fn void loop()
*
* \brief Infinite loop.
******************************************************************************/
void loop()
{
// Get pressed key and process it.
Keyboard::Key_t key = (Keyboard::Key_t)(clock__lcd.get_key());
if (key > Keyboard::KeyNone)
{
clock__handleKey(key);
}
// If we aren't in adjust mode, get current time and print it.
if (!clock__adjustMode)
{
clock__currentTime = clock__rtc.now();
clock__printDatetime();
}
delay(200);
}
/******************************************************************************
* Private function definitions.
******************************************************************************/
/**************************************************************************//**
* \fn static void clock__handleKey(Keyboard::Key_t key)
*
* \brief Handle pressed key.
*
* \param key Pressed key.
******************************************************************************/
static
void
clock__handleKey
(
Keyboard::Key_t key
){
switch (key)
{
case Keyboard::KeyRight:
{
if (clock__adjustMode)
{
if (clock__currentMember < clock__MemberSecond)
{
byte tmpMember = (byte)clock__currentMember;
tmpMember++;
clock__currentMember = (clock__member_t)tmpMember;
}
else
{
clock__currentMember = clock__MemberDay;
}
clock__setCursor();
}
}
break;
case Keyboard::KeyUp:
{
if (clock__adjustMode)
{
clock__incrementMember();
clock__setCursor();
}
}
break;
case Keyboard::KeyDown:
{
if (clock__adjustMode)
{
clock__decrementMember();
clock__setCursor();
}
}
break;
case Keyboard::KeyLeft:
{
if (clock__adjustMode)
{
if (clock__currentMember > clock__MemberDay)
{
byte tmpMember = (byte)clock__currentMember;
tmpMember--;
clock__currentMember = (clock__member_t)tmpMember;
}
else
{
clock__currentMember = clock__MemberSecond;
}
clock__setCursor();
}
}
break;
case Keyboard::KeySelect:
{
if (clock__adjustMode)
{
// If we are in adjust mode, update RTC time.
clock__rtc.adjust(clock__currentTime);
clock__lcd.noBlink();
clock__lcd.noCursor();
clock__currentMember = clock__MemberDay;
clock__adjustMode = false;
}
else
{
// Enter adjust mode.
clock__adjustMode = true;
clock__lcd.setCursor(1, 0);
clock__lcd.blink();
clock__lcd.cursor();
}
}
break;
case Keyboard::KeyNone:
case Keyboard::KeyInvalid:
default:
break;
}
}
/**************************************************************************//**
* \fn static void clock__setCursor()
*
* \brief Set cursor position.
******************************************************************************/
static
void
clock__setCursor()
{
switch (clock__currentMember)
{
case clock__MemberDay:
clock__lcd.setCursor(1, 0);
break;
case clock__MemberMonth:
clock__lcd.setCursor(4, 0);
break;
case clock__MemberYear:
clock__lcd.setCursor(9, 0);
break;
case clock__MemberHour:
clock__lcd.setCursor(1, 1);
break;
case clock__MemberMinute:
clock__lcd.setCursor(4, 1);
break;
case clock__MemberSecond:
clock__lcd.setCursor(7, 1);
break;
default:
break;
}
}
/**************************************************************************//**
* \fn static void clock__incrementMember()
*
* \brief Increment current member: day, month, year, hour, minute or second.
******************************************************************************/
static
void
clock__incrementMember()
{
switch (clock__currentMember)
{
case clock__MemberDay:
{
byte day = clock__currentTime.day();
day = (day + 1 <= CLOCK__DAY_MAX) ? (day + 1) : CLOCK__DAY_MIN;
clock__currentTime.setDay(day);
}
break;
case clock__MemberMonth:
{
byte month = clock__currentTime.month();
month = (month + 1 <= CLOCK__MONTH_MAX) ? (month + 1) : CLOCK__MONTH_MIN;
clock__currentTime.setMonth(month);
}
break;
case clock__MemberYear:
{
word year = clock__currentTime.year();
year = (year + 1 <= CLOCK__YEAR_MAX) ? (year + 1) : CLOCK__YEAR_MIN;
clock__currentTime.setYear(year);
}
break;
case clock__MemberHour:
{
byte hour = clock__currentTime.hour();
hour = (hour + 1 <= CLOCK__HOUR_MAX) ? (hour + 1) : CLOCK__HOUR_MIN;
clock__currentTime.setHour(hour);
}
break;
case clock__MemberMinute:
{
byte minute = clock__currentTime.minute();
minute = (minute + 1 <= CLOCK__MINUTE_MAX) ? (minute + 1) : CLOCK__MINUTE_MIN;
clock__currentTime.setMinute(minute);
}
break;
case clock__MemberSecond:
{
byte second = clock__currentTime.second();
second = (second + 1 <= CLOCK__SECOND_MAX) ? (second + 1) : CLOCK__SECOND_MIN;
clock__currentTime.setSecond(second);
}
break;
default:
break;
}
clock__printDatetime();
}
/**************************************************************************//**
* \fn static void clock__decrementMember()
*
* \brief Decrement current member: day, month, year, hour, minute or second.
******************************************************************************/
static
void
clock__decrementMember()
{
switch (clock__currentMember)
{
case clock__MemberDay:
{
byte day = clock__currentTime.day();
day = (day - 1 >= CLOCK__DAY_MIN) ? (day - 1) : CLOCK__DAY_MAX;
clock__currentTime.setDay(day);
}
break;
case clock__MemberMonth:
{
byte month = clock__currentTime.month();
month = (month - 1 >= CLOCK__MONTH_MIN) ? (month - 1) : CLOCK__MONTH_MAX;
clock__currentTime.setMonth(month);
}
break;
case clock__MemberYear:
{
word year = clock__currentTime.year();
year = (year - 1 >= CLOCK__YEAR_MIN) ? (year - 1) : CLOCK__YEAR_MAX;
clock__currentTime.setYear(year);
}
break;
case clock__MemberHour:
{
byte hour = clock__currentTime.hour();
hour = (hour - 1 >= CLOCK__HOUR_MIN) ? (hour - 1) : CLOCK__HOUR_MIN;
clock__currentTime.setHour(hour);
}
break;
case clock__MemberMinute:
{
byte minute = clock__currentTime.minute();
minute = (minute - 1 >= CLOCK__MINUTE_MIN) ? (minute - 1) : CLOCK__MINUTE_MAX;
clock__currentTime.setMinute(minute);
}
break;
case clock__MemberSecond:
{
byte second = clock__currentTime.second();
second = (second - 1 >= CLOCK__SECOND_MIN) ? (second - 1) : CLOCK__SECOND_MAX;
clock__currentTime.setSecond(second);
}
break;
default:
break;
}
clock__printDatetime();
}
/**************************************************************************//**
* \fn static void clock__printDatetime()
*
* \brief Print current datetime.
******************************************************************************/
static
void
clock__printDatetime()
{
// Build date string.
char date[] = "01/01/2000";
snprintf
(
date,
strlen(date) + 1,
"%02d/%02d/%04d",
clock__currentTime.day(),
clock__currentTime.month(),
clock__currentTime.year()
);
// Build time string.
char time[] = "00:00:00";
snprintf
(
time,
strlen(time) + 1,
"%02d:%02d:%02d",
clock__currentTime.hour(),
clock__currentTime.minute(),
clock__currentTime.second()
);
// Print date.
clock__lcd.setCursor(0, 0);
clock__lcd.print(date);
// Print time.
clock__lcd.setCursor(0, 1);
clock__lcd.print(time);
}