Clock with Real-Time Clock (RTC-8564) and I2C LCD module(SB1062B).

Dependencies:   DebouncedEdgeIn I2cLCD_cursor Rtc8564 mbed beep

/media/uploads/togayan/imgp0004s.jpg /media/uploads/togayan/lcdclock_circuit_rev4.png

Model/Clock.cpp

Committer:
togayan
Date:
2014-03-01
Revision:
6:e7073adacdc8
Parent:
4:75ed86b78045

File content as of revision 6:e7073adacdc8:

#include "Clock.h"

using Model::Clock;

Clock::Clock(I_NotifyUpdate* notifyUpdate, I_SetPresentTime* setPresentTime)
    :m_notifyUpdate(notifyUpdate),
     m_setPresentTime(setPresentTime),
     m_mode(CLOCK)
{
}

void Clock::addSetMode(I_SetMode* setMode)
{
    m_setModes.push_back(setMode);
}

void Clock::initialize()
{
    m_dateTime.tm_year   = 100; // 2000-01-01
    m_dateTime.tm_mon    = 0;
    m_dateTime.tm_mday   = 1;
    m_dateTime.tm_wday   = 6; // Saturday
    m_dateTime.tm_hour   = 0; // 00:00:00
    m_dateTime.tm_min    = 0;
    m_dateTime.tm_sec    = 0;
    m_dateTime.tm_isdst  = -1;
}

void Clock::renew()
{
    if(m_mode != CLOCK) return;

    m_notifyUpdate->dateTimeUpdated();
}

struct tm* Clock::getDateTime() {
    return &m_dateTime;
}

void Clock::requestModeChange()
{
    switch(m_mode) {
        case CLOCK:
            m_mode = SET_YEAR;
            break;
        case SET_YEAR:
            m_mode = SET_MONTH;
            break;
        case SET_MONTH:
            m_mode = SET_DAY;
            break;
        case SET_DAY:
            m_mode = SET_HOUR;
            break;
        case SET_HOUR:
            m_mode = SET_MINUTE;
            break;
        case SET_MINUTE:
            m_mode = SET_SECOND;
            break;
        case SET_SECOND:
            m_mode = CLOCK;
            m_setPresentTime->setPresentTime();
            break;
        default:
            break;
    }
    notifyMode();
}

void Clock::requestIncrementValue()
{
    switch(m_mode) {
        case SET_YEAR:
            m_dateTime.tm_year++;
            if(m_dateTime.tm_year >= 200) {
                m_dateTime.tm_year = 100;
            }
            decideDayOfMonth();
            decideDayOfWeek();
            m_notifyUpdate->dateTimeUpdated();
            break;
        case SET_MONTH:
            m_dateTime.tm_mon++;
            if(m_dateTime.tm_mon >= 12) {
                m_dateTime.tm_mon = 0;
            }
            decideDayOfMonth();
            decideDayOfWeek();
            m_notifyUpdate->dateTimeUpdated();
            break;
        case SET_DAY:
            m_dateTime.tm_mday++;
            if(m_dateTime.tm_mday > getDays()) {
                m_dateTime.tm_mday = 1;
            }
            decideDayOfWeek();
            m_notifyUpdate->dateTimeUpdated();
            break;
        case SET_HOUR:
            m_dateTime.tm_hour++;
            if(m_dateTime.tm_hour >= 24) {
                m_dateTime.tm_hour = 0;
            }
            m_notifyUpdate->dateTimeUpdated();
            break;
        case SET_MINUTE:
            m_dateTime.tm_min++;
            if(m_dateTime.tm_min >= 60) {
                m_dateTime.tm_min = 0;
            }
            m_notifyUpdate->dateTimeUpdated();
            break;
        case SET_SECOND:
            m_dateTime.tm_sec++;
            if(m_dateTime.tm_sec >= 60) {
                m_dateTime.tm_sec = 0;
            }
            m_notifyUpdate->dateTimeUpdated();
            break;
        default:
            break;
    }
}

void Clock::requestDecrementValue()
{
    switch(m_mode) {
        case SET_YEAR:
            if(m_dateTime.tm_year <= 100) {
                m_dateTime.tm_year = 200;
            }
            m_dateTime.tm_year--;
            decideDayOfMonth();
            decideDayOfWeek();
            m_notifyUpdate->dateTimeUpdated();
            break;
        case SET_MONTH:
            if(m_dateTime.tm_mon < 0) {
                m_dateTime.tm_mon = 12;
            }
            m_dateTime.tm_mon--;
            decideDayOfMonth();
            decideDayOfWeek();
            m_notifyUpdate->dateTimeUpdated();
            break;
        case SET_DAY:
            if(m_dateTime.tm_mday <= 1) {
                m_dateTime.tm_mday = getDays() + 1;
            }
            m_dateTime.tm_mday--;
            decideDayOfWeek();
            m_notifyUpdate->dateTimeUpdated();
            break;
        case SET_HOUR:
            if(m_dateTime.tm_hour <= 0) {
                m_dateTime.tm_hour = 24;
            }
            m_dateTime.tm_hour--;
            m_notifyUpdate->dateTimeUpdated();
            break;
        case SET_MINUTE:
            if(m_dateTime.tm_min <= 0) {
                m_dateTime.tm_min = 60;
            }
            m_dateTime.tm_min--;
            m_notifyUpdate->dateTimeUpdated();
            break;
        case SET_SECOND:
            if(m_dateTime.tm_sec <= 0) {
                m_dateTime.tm_sec = 60;
            }
            m_dateTime.tm_sec--;
            m_notifyUpdate->dateTimeUpdated();
            break;
        default:
            break;
    }
}

void Clock::notifyMode()
{
    for(std::vector<I_SetMode*>::iterator it = m_setModes.begin(); it != m_setModes.end(); ++it) {
        (*it)->mode(m_mode);
    }
}

int Clock::getDays()
{
    const int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    int year = m_dateTime.tm_year + 1900;
    int month = m_dateTime.tm_mon + 1;

    int lastd = days[month - 1];
    if( month == 2 ) {
        if( year % 4 == 0 && year % 100 != 0 || year % 400 == 0 )
            lastd = 29;
    }
    return lastd;
}

void Clock::decideDayOfMonth()
{
    if(m_dateTime.tm_mday > getDays()) {
        m_dateTime.tm_mday = getDays();
    }
}

void Clock::decideDayOfWeek()
{
    if (mktime(&m_dateTime) == (time_t)(-1)) {
        m_dateTime.tm_wday = 7;
    }
    return;
}