Subversion Repositories idreammicro-arduino

Rev

Go to most recent revision | 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;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                day,
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
        
        case clock__MemberMonth:
        {
            byte month = clock__currentTime.month();
            month = (month + 1 <= CLOCK__MONTH_MAX) ? (month + 1) : CLOCK__MONTH_MIN;
            DateTime tempTime
            (
                clock__currentTime.year(),
                month,
                clock__currentTime.day(),
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
        
        case clock__MemberYear:
        {
            word year = clock__currentTime.year();
            year = (year + 1 <= CLOCK__YEAR_MAX) ? (year + 1) : CLOCK__YEAR_MIN;
            DateTime tempTime
            (
                year,
                clock__currentTime.month(),
                clock__currentTime.day(),
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
        
        case clock__MemberHour:
        {
            byte hour = clock__currentTime.hour();
            hour = (hour + 1 <= CLOCK__HOUR_MAX) ? (hour + 1) : CLOCK__HOUR_MIN;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                clock__currentTime.day(),
                hour,
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }   
        break;
        
        case clock__MemberMinute:
        {
            byte minute = clock__currentTime.minute();
            minute = (minute + 1 <= CLOCK__MINUTE_MAX) ? (minute + 1) : CLOCK__MINUTE_MIN;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                clock__currentTime.day(),
                clock__currentTime.hour(),
                minute,
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
        
        case clock__MemberSecond:
        {
            byte second = clock__currentTime.second();
            second = (second + 1 <= CLOCK__SECOND_MAX) ? (second + 1) : CLOCK__SECOND_MIN;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                clock__currentTime.day(),
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                second
            );
            clock__currentTime = tempTime;
        }
        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;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                day,
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
        
        case clock__MemberMonth:
        {
            byte month = clock__currentTime.month();
            month = (month - 1 >= CLOCK__MONTH_MIN) ? (month - 1) : CLOCK__MONTH_MAX; 
            DateTime tempTime
            (
                clock__currentTime.year(),
                month,
                clock__currentTime.day(),
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
        
        case clock__MemberYear:
        {
            word year = clock__currentTime.year();
            year = (year - 1 >= CLOCK__YEAR_MIN) ? (year - 1) : CLOCK__YEAR_MAX;
            DateTime tempTime
            (
                year,
                clock__currentTime.month(),
                clock__currentTime.day(),
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
        
        case clock__MemberHour:
        {
            byte hour = clock__currentTime.hour();
            hour = (hour - 1 >= CLOCK__HOUR_MIN) ? (hour - 1) : CLOCK__HOUR_MIN;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                clock__currentTime.day(),
                hour,
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }   
        break;
        
        case clock__MemberMinute:
        {
            byte minute = clock__currentTime.minute();
            minute = (minute - 1 >= CLOCK__MINUTE_MIN) ? (minute - 1) : CLOCK__MINUTE_MAX;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                clock__currentTime.day(),
                clock__currentTime.hour(),
                minute,
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
        
        case clock__MemberSecond:
        {
            byte second = clock__currentTime.second();
            second = (second - 1 >= CLOCK__SECOND_MIN) ? (second - 1) : CLOCK__SECOND_MAX;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                clock__currentTime.day(),
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                second
            );
            clock__currentTime = tempTime;
        }
        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);
}