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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Clock.cpp Source File

Clock.cpp

00001 /*
00002  Clock.cpp
00003  
00004  Created on: Mar 24, 2015
00005      Author: Zoltan Hudak
00006      
00007  This is a software implemented Real Time Clock driven by a Ticker.
00008  No external parts (like DS1307 or DS3231 or etc.) are needed.
00009  
00010  See demo <http://developer.mbed.org/users/hudakz/code/Clock_Hello/>
00011  
00012  Copyright (c) 2015 Zoltan Hudak <hudakz@outlook.com>
00013  All rights reserved.
00014 
00015  This program is free software: you can redistribute it and/or modify
00016  it under the terms of the GNU General Public License as published by
00017  the Free Software Foundation, either version 3 of the License, or
00018  (at your option) any later version.
00019 
00020  This program is distributed in the hope that it will be useful,
00021  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  GNU General Public License for more details.
00024 
00025  You should have received a copy of the GNU General Public License
00026  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00027  */
00028 #include "mbed.h"
00029 #include "Clock.h"
00030 
00031 // Static member initialization
00032 time_t              Clock::_time = 0;
00033 tm                  Clock::_tm = { 0, 0, 0, 0, 0, 0, 0, 0, -1 };
00034 Callback<void ()>   Clock::_onTick = NULL;
00035 
00036 /**
00037  * @brief   Constructs a Clock.
00038  * @note    The clock is driven by a Ticker.
00039  *          Since the Clock is attached as an external RTC
00040  *          standard C time functions can be called as well.
00041  * @param   year:   long format (for instance 2015)
00042  * @param   mon:    month (1 stands for January etc.)
00043  * @param   mday:   day of month
00044  * @param   hour:   24hour format
00045  * @param   min:    minutes
00046  * @param   ser:    seconds
00047  * @retval
00048  */
00049 Clock::Clock(int year, int mon, int mday, int hour, int min, int sec) :
00050     _ticker(new Ticker)
00051 {
00052     _ticker->attach_us(&tick, 1000000); // a Ticker ticking at 1s rate
00053     attach_rtc(time, NULL, NULL, NULL); // attach for C time functions
00054 }
00055 
00056 /**
00057  * @brief   Constructs a Clock.
00058  * @note    The clock is driven by a Ticker.
00059  *          Since the Clock is attached as an external RTC
00060  *          standard C time functions can be called as well.
00061  *          Time is set to the begin of Epoch: 00:00:00 January 1, 1970
00062  * @param
00063  * @retval
00064  */
00065 Clock::Clock() :
00066     _ticker(new Ticker)
00067 {
00068     _ticker->attach_us(&tick, 1000000); // a Ticker ticking at 1s rate
00069     attach_rtc(time, NULL, NULL, NULL); // attach for C time functions
00070 }
00071 
00072 /**
00073  * @brief   Destroys a Clock.
00074  * @note    Destructor
00075  * @param
00076  * @retval
00077  */
00078 Clock::~Clock()
00079 {
00080     _ticker->detach();  // suspend ticks
00081     delete _ticker;     // distroys _ticker
00082 }
00083 
00084 /**
00085  * @brief   Sets Clock time using human readable inputs
00086  * @note
00087  * @param   year:   long format (for instance 2015)
00088  * @param   mon:    month (1 stands for January etc.)
00089  * @param   mday:   day of month
00090  * @param   hour:   24hour format
00091  * @param   min:    minutes
00092  * @param   ser:    seconds
00093  * @retval
00094  */
00095 void Clock::set(int year, int mon, int mday, int hour, int min, int sec)
00096 {
00097     _ticker->detach();                  // suspend ticks
00098     _tm.tm_year = year - 1900;
00099     _tm.tm_mon = mon - 1;               // convert to 0 based month
00100     _tm.tm_mday = mday;
00101     _tm.tm_hour = hour;
00102     _tm.tm_min = min;
00103     _tm.tm_sec = sec;
00104     _tm.tm_isdst = -1;
00105 
00106     // Is DST on? 1 = yes, 0 = no, -1 = unknown
00107     _time = mktime(&_tm);               // convert to seconds elapsed since January 1, 1970
00108     set_time(_time);                    // set time
00109     _ticker->attach_us(&tick, 1000000); // resume ticks
00110 }
00111 
00112 /**
00113  * @brief   Sets Clock to tm value
00114  * @note
00115  * @param   val:    tm structure
00116  * @retval
00117  */
00118 void Clock::set(tm& val)
00119 {
00120     _ticker->detach();                  // suspend ticks
00121     _tm = val;
00122     _ticker->attach_us(&tick, 1000000); // resume ticks
00123 }
00124 
00125 /**
00126  * @brief   Sets Clock to time_t value
00127  * @note
00128  * @param   val:    time_t structure (Number of seconds elapsed since January 1, 1970)
00129  * @retval
00130  */
00131 void Clock::set(time_t val)
00132 {
00133     _ticker->detach();                  // suspend ticks
00134     _time = val;
00135     _tm = *::localtime(&_time);
00136     _ticker->attach_us(&tick, 1000000); // resume ticks
00137 }
00138 
00139 /**
00140  * @brief   Current time
00141  * @note
00142  * @param
00143  * @retval  Number of seconds elapsed since January 1, 1970
00144  */
00145 time_t Clock::time(void)
00146 {
00147     return _time;
00148 }
00149 
00150 /**
00151  * @brief   Year
00152  * @note
00153  * @param
00154  * @retval  Year
00155  */
00156 int Clock::year(void)
00157 {
00158     return(_tm.tm_year + 1900);
00159 }
00160 
00161 /**
00162  * @brief   Month
00163  * @note
00164  * @param
00165  * @retval  Month
00166  */
00167 int Clock::mon(void)
00168 {
00169     return(_tm.tm_mon + 1);
00170 }
00171 
00172 /**
00173  * @brief   Day of month
00174  * @note
00175  * @param
00176  * @retval  Day of the month
00177  */
00178 int Clock::mday(void)
00179 {
00180     return _tm.tm_mday;
00181 }
00182 
00183 /**
00184  * @brief   Day of week
00185  * @note    
00186  * @param
00187  * @retval  Day of week (Sunday = 0, Monday = 1, etc.)
00188  */
00189 int Clock::wday(void)
00190 {
00191     return _tm.tm_wday; // Sunday = 0, Monday = 1, etc.
00192 }
00193 
00194 /**
00195  * @brief   Hour
00196  * @note
00197  * @param
00198  * @retval  Hour
00199  */
00200 int Clock::hour(void)
00201 {
00202     return _tm.tm_hour;
00203 }
00204 
00205 /**
00206  * @brief   Minutes
00207  * @note
00208  * @param
00209  * @retval  Minutes
00210  */
00211 int Clock::min(void)
00212 {
00213     return _tm.tm_min;
00214 }
00215 
00216 /**
00217  * @brief   Seconds
00218  * @note
00219  * @param
00220  * @retval  Seconds
00221  */
00222 int Clock::sec(void)
00223 {
00224     return _tm.tm_sec;
00225 }
00226 
00227 /**
00228  * @brief   Clock tick handler
00229  * @note    Called by the _ticker once per second
00230  *          Calls event handler if attached one by the user
00231  * @param
00232  * @retval
00233  */
00234 void Clock::tick(void)
00235 {
00236     _tm = *::localtime(&(++_time));
00237     _onTick.call();
00238 }
00239 
00240 /**
00241  * @brief   Attaches a handler to the onTick event
00242  * @note    onTick event occurs each second
00243  * @param   fnc  User defined handler function of type 'void fnc(void)'
00244  * @retval
00245  */
00246 void Clock::attach(void (*fptr) (void))
00247 {
00248     if (fptr)
00249         _onTick = fptr;
00250 }
00251 
00252 /**
00253  * @brief   Attaches a class method as handler to the onTick event
00254  * @note    onTick event occurs each second
00255  * @param   tptr  Pointer a class
00256  * @param   mptr  Poiter to a 'void fnc(void)' method
00257  * @retval
00258  */
00259 template<typename T>
00260 void Clock::attach(T* tptr, void (T::*mptr) (void))
00261 {
00262     if ((tptr != NULL) && (mptr != NULL))
00263         _onTick.attach(tptr, mptr);
00264 }
00265 
00266 /**
00267  * @brief   Detaches handler function from the onTick event
00268  * @note
00269  * @param
00270  * @retval
00271  */
00272 void Clock::detach()
00273 {
00274     _onTick = NULL;
00275 }
00276 
00277 /**
00278  * @brief   Converts human readable time to seconds elapsed since January 1, 1970
00279  * @note    A static helper function.
00280  * @param   year:   long format (for instance 2015)
00281  * @param   mon:    month (1 stands for January etc.)
00282  * @param   mday:   day of month
00283  * @param   hour:   24hour format
00284  * @param   min:    minutes
00285  * @param   ser:    seconds
00286  * @retval  Number of seconds elapsed since January 1, 1970
00287  */
00288 time_t Clock::asTime(int year, int mon, int mday, int hour, int min, int sec)
00289 {
00290     struct tm   t;
00291     t.tm_year = year - 1900;
00292     t.tm_mon = mon - 1; // convert to 0 based month
00293     t.tm_mday = mday;
00294     t.tm_hour = hour;
00295     t.tm_min = min;
00296     t.tm_sec = sec;
00297     t.tm_isdst = -1;    // Is DST on? 1 = yes, 0 = no, -1 = unknown
00298     return mktime(&t);  // returns seconds elapsed since January 1, 1970
00299 }
00300