Software implemented real time clock driven by a Ticker. No external hardware (like DS1307 or DS3231 or etc.) is needed. Should work on any mbed platform where Ticker works.

Dependents:   Clock_Hello

See demo:

Import programClock_Hello

Demo for the Clock library (real time clock driven by a Ticker).

Clock.cpp

Committer:
hudakz
Date:
2016-04-01
Revision:
4:bbe7d7474acd
Parent:
3:58f5afbd24cd
Child:
5:d65fc7060635

File content as of revision 4:bbe7d7474acd:

/*
 Clock.cpp
 
 Created on: Mar 24, 2015
     Author: Zoltan Hudak
     
 This is a software implemented Real Time Clock driven by a Ticker.
 No external parts (like DS1307 or DS3231 or etc.) are needed.
 
 See demo <http://developer.mbed.org/users/hudakz/code/Clock_Hello/>
 
 Copyright (c) 2015 Zoltan Hudak <hudakz@inbox.com>
 All rights reserved.

 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/>.
 */
 
#include "mbed.h"
#include "Clock.h"

// static member initialization
time_t          Clock::_time = 0;
tm              Clock::_tm = {0, 0, 0, 0, 0, 0, -1};
ClockFnc_t      Clock::_onTick = NULL;

/**
 * @brief   Constructs a Clock.
 * @note    The clock is driven by a Ticker.
 *          Since the Clock is attached as an external RTC
 *          standard C time functions can be called as well.
 * @param   year:   long format (for instance 2015)
 *          mon:    month (1 stands for January etc.)
 *          mday:   day of month
 *          hour:   24hour format
 *          min:    minutes
 *          ser:    seconds
 * @retval
 */
Clock::Clock(int year, int mon, int mday, int hour, int min, int sec) {
    _ticker.attach(&tick, 1.0);             // a Ticker ticking at 1s rate
    set(year, mon, mday, hour, min, sec);   // set date and time as requested
    attach_rtc(time, NULL, NULL, NULL);     // attach for C time functions
}

/**
 * @brief   Constructs a Clock.
 * @note    The clock is driven by a Ticker.
 *          Since the Clock is attached as an external RTC
 *          standard C time functions can be called as well.
 *          Time is set to the begin of Epoch: 00:00:00 January 1, 1970
 * @param
 * @retval
 */
Clock::Clock() {
    _ticker.attach(&tick, 1.0);             // a Ticker ticking at 1s rate
    set(1970, 1, 1, 0, 0, 0);               // set date and time to the begin of Epoch
    attach_rtc(time, NULL, NULL, NULL);     // attach for C time functions
}

/**
 * @brief   Sets Clock time using human readable inputs
 * @note
 * @param   year:   long format (for instance 2015)
 *          mon:    month (1 stands for January etc.)
 *          mday:   day of month
 *          hour:   24hour format
 *          min:    minutes
 *          ser:    seconds
 * @retval
 */
void Clock::set(int year, int mon, int mday, int hour, int min, int sec) {
    _ticker.detach();           // suspend ticks

    _tm.tm_year = year - 1900;
    _tm.tm_mon =  mon - 1;      // convert to 0 based month
    _tm.tm_mday = mday;
    _tm.tm_hour = hour;
    _tm.tm_min = min;
    _tm.tm_sec = sec;
    _tm.tm_isdst = -1;          // Is DST on? 1 = yes, 0 = no, -1 = unknown

    _time = mktime(&_tm);       // convert to seconds elapsed since January 1, 1970
    set_time(_time);            // set time

    _ticker.attach(&tick, 1.0); // resume ticks
}

/**
 * @brief   Sets Clock to tm value
 * @note
 * @param   val:    tm structure
 * @retval
 */
void Clock::set(tm& val) {
    _ticker.detach();           // suspend ticks
    _tm = val;
    _ticker.attach(&tick, 1.0); // resume ticks
}

/**
 * @brief   Sets Clock to time_t value
 * @note
 * @param   val:    time_t structure (Number of seconds elapsed since January 1, 1970)
 * @retval
 */
void Clock::set(time_t val) {
    _ticker.detach();           // suspend ticks
    _time = val;
    _tm = *::localtime(&_time);
    _ticker.attach(&tick, 1.0); // resume ticks
}

/**
 * @brief   Current time
 * @note
 * @param
 * @retval  Number of seconds elapsed since January 1, 1970
 */
time_t Clock::time(void) {
    return _time;
}

/**
 * @brief   Year
 * @note
 * @param
 * @retval  Year
 */
int Clock::year(void) {
    return (_tm.tm_year + 1900);
}

/**
 * @brief   Month
 * @note
 * @param
 * @retval  Month
 */
int Clock::mon(void) {
    return (_tm.tm_mon + 1);
}

/**
 * @brief   Day of month
 * @note
 * @param
 * @retval  Day of the month
 */
int Clock::mday(void) {
    return _tm.tm_mday;
}

/**
 * @brief   Day of week
 * @note    
 * @param
 * @retval  Day of week (Sunday = 0, Monday = 1, etc.)
 */
int Clock::wday(void) {
    return _tm.tm_wday; // Sunday = 0, Monday = 1, etc.
}

/**
 * @brief   Hour
 * @note
 * @param
 * @retval  Hour
 */
int Clock::hour(void) {
    return _tm.tm_hour;
}

/**
 * @brief   Minutes
 * @note
 * @param
 * @retval  Minutes
 */
int Clock::min(void) {
    return _tm.tm_min;
}

/**
 * @brief   Seconds
 * @note
 * @param
 * @retval  Seconds
 */
int Clock::sec(void) {
    return _tm.tm_sec;
}

/**
 * @brief   Clock tick handler
 * @note    Called by the _ticker once per second
 *          Calls event handler if attached one by the user
 * @param
 * @retval
 */
void Clock::tick(void) {
    _tm = *::localtime(&(++_time));

    if(_onTick != NULL) // if a handler was attached by the user
        _onTick();      // call it
}


/**
 * @brief   Attaches a handler to the onTick event
 * @note    onTick event occurs each second
 * @param   fnc:    User defined handler function of type void fnc(void)
 * @retval
 */
void Clock::attach(ClockFnc_t fnc) {
    _onTick = fnc;
}

/**
 * @brief   Detaches handler function from the onTick event
 * @note
 * @param
 * @retval
 */
void Clock::detach() {
    _onTick = NULL;
}

/**
 * @brief   Converts human readable time to seconds elapsed since January 1, 1970
 * @note    It's a static helper function.
 * @param   year:   long format (for instance 2015)
 *          mon:    month (1 stands for January etc.)
 *          mday:   day of month
 *          hour:   24hour format
 *          min:    minutes
 *          ser:    seconds
 * @retval  Number of seconds elapsed since January 1, 1970
 */
time_t Clock::asTime(int year, int mon, int mday, int hour, int min, int sec) {
    struct tm   t;
    t.tm_year = year - 1900;
    t.tm_mon =  mon - 1;        // convert to 0 based month
    t.tm_mday = mday;
    t.tm_hour = hour;
    t.tm_min = min;
    t.tm_sec = sec;
    t.tm_isdst = -1;            // Is DST on? 1 = yes, 0 = no, -1 = unknown

    return mktime(&t);          // returns seconds elapsed since January 1, 1970
}