Rewrite the RTClock library.

This commit is contained in:
csnol 2017-08-29 10:07:42 -05:00 committed by GitHub
parent 47c94bc10c
commit fbe6264003
2 changed files with 158 additions and 21 deletions

View File

@ -81,21 +81,108 @@
*/
void RTClock::setTime (time_t time_stamp) {
rtc_set_count(time_stamp);
breakTime(time_stamp, tmm); // time will be broken to tm
setTime(tmm);
//rtc_set_count(time_stamp);
}
void RTClock::setTime (struct tm* tm_ptr) {
rtc_set_count(mktime (tm_ptr));
}
#define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) )
//-----------------------------------------------------------------------------
void RTClock::breakTime(time_t timeInput, tm_t & tmm)
{
// break the given time_t into time components
// this is a more compact version of the C library localtime function
// note that year is offset from 1970 !!!
uint8_t year;
uint8_t month, monthLength;
uint32_t time;
uint32_t days;
time = (uint32_t)timeInput;
tmm.second = time % 60;
time /= 60; // now it is minutes
tmm.minute = time % 60;
time /= 60; // now it is hours
tmm.hour = time % 24;
time /= 24; // now it is days
tmm.weekday = ((time + 4) % 7); // Monday is day 1 // + 1; // Sunday is day 1
year = 0;
days = 0;
while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) {
year++;
}
tmm.year = year; // year is offset from 1970
days -= LEAP_YEAR(year) ? 366 : 365;
time -= days; // now it is days in this year, starting at 0
days = 0;
month = 0;
monthLength = 0;
for (month=0; month<12; month++) {
if (month==1) { // february
if (LEAP_YEAR(year)) {
monthLength=29;
} else {
monthLength=28;
}
} else {
monthLength = monthDays[month];
}
if (time >= monthLength) {
time -= monthLength;
} else {
break;
}
}
tmm.month = month + 1; // jan is month 1
tmm.day = time + 1; // day of month
}
//-----------------------------------------------------------------------------
time_t RTClock::makeTime(tm_t & tmm)
{
// assemble time elements into time_t
// note year argument is offset from 1970 (see macros in time.h to convert to other formats)
// previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9
int i;
uint32_t seconds;
// seconds from 1970 till 1 jan 00:00:00 of the given year
seconds = tmm.year*(SECS_PER_DAY * 365);
for (i = 0; i < tmm.year; i++) {
if (LEAP_YEAR(i)) {
seconds += SECS_PER_DAY; // add extra days for leap years
}
}
// add days for this year, months start from 1
for (i = 1; i < tmm.month; i++) {
if ( (i == 2) && LEAP_YEAR(tmm.year)) {
seconds += SECS_PER_DAY * 29;
} else {
seconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0
}
}
seconds+= (tmm.day-1) * SECS_PER_DAY;
seconds+= tmm.hour * SECS_PER_HOUR;
seconds+= tmm.minute * SECS_PER_MIN;
seconds+= tmm.second;
return (time_t)seconds;
}
time_t RTClock::getTime() {
return rtc_get_count();
}
struct tm* RTClock::getTime(struct tm* tm_ptr) {
void RTClock::getTime(tm_t & tm_ptr) {
time_t res = rtc_get_count();
tm_ptr = gmtime(&res); //why not gmtime?
return tm_ptr;
breakTime(res, tm_ptr);
}
void RTClock::createAlarm(voidFuncPtr function, time_t alarm_time_t) {
@ -110,15 +197,16 @@
rtc_detach_interrupt(RTC_SECONDS_INTERRUPT);
}
void RTClock::createAlarm(voidFuncPtr function, tm* alarm_tm) {
time_t alarm = mktime(alarm_tm);//convert to time_t
void RTClock::createAlarm(voidFuncPtr function, tm_t & alarm_tm) {
time_t alarm = makeTime(alarm_tm);//convert to time_t
createAlarm(function, alarm);
}
//change alarm time
void RTClock::setAlarmTime (tm * tm_ptr) {
time_t time = mktime(tm_ptr);//convert to time_t
void RTClock::setAlarmTime (tm_t & tm_ptr) {
time_t time = makeTime(tm_ptr);//convert to time_t
rtc_set_alarm(time); //must be int... for standardization sake.
}

View File

@ -7,9 +7,35 @@
#ifndef _RTCLOCK_H_
#define _RTCLOCK_H_
#define SECS_PER_MIN (60UL)
#define SECS_PER_HOUR (3600UL)
#define SECS_PER_DAY (SECS_PER_HOUR * 24UL)
#define DAYS_PER_WEEK (7UL)
#define SECS_PER_WEEK (SECS_PER_DAY * DAYS_PER_WEEK)
#define SECS_PER_YEAR (SECS_PER_WEEK * 52UL)
#define SECS_YR_2000 (946684800UL) // the time at the start of y2k
#define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) )
#if !defined(__time_t_defined) // avoid conflict with newlib or other posix libc
#warning "Using private time_t definintion"
typedef uint32_t time_t;
#endif
static const unsigned char monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0
typedef struct tm_t {
uint8_t year; // years since 1970
uint8_t month; // month of a year - [ 1 to 12 ]
uint8_t day; // day of a month - [ 1 to 31 ]
uint8_t weekday; // day of a week (first day is Sunday) - [ 0 to 6 ]
uint8_t pm; // AM: 0, PM: 1
uint8_t hour; // hour of a day - [ 0 to 23 ]
uint8_t minute; // minute of an hour - [ 0 to 59 ]
uint8_t second; // second of a minute - [ 0 to 59 ]
} tm_t;
static inline uint8_t bcd2bin(uint8_t b) { return ( (10*(b>>4)) + (b&0x0F) ); }
static inline uint8_t bin2bcd(uint8_t b) { return ( ((b/10)<<4) + (b%10) ); }
class RTClock {
public:
@ -18,24 +44,47 @@ class RTClock {
RTClock(rtc_clk_src src, uint16 prescaler );
//~RTClock(); //to implement
void setTime (time_t time_stamp);
void setTime (struct tm * tm_ptr);
void breakTime(time_t epoch_time, tm_t & tmm);
time_t makeTime(tm_t & tmm);
void setTime (time_t time_stamp);
void setTime (tm_t & tmm);
struct tm* getTime(struct tm* tm_ptr);
time_t getTime();
void getTime(tm_t & tmm );
#define now getTime
uint8_t year(void) { getTime(tmm); return tmm.year; }
uint8_t month(void) { getTime(tmm); return tmm.month; }
uint8_t day(void) { getTime(tmm); return tmm.day; }
uint8_t weekday(void) { getTime(tmm); return tmm.weekday; }
uint8_t hour(void) { getTime(tmm); return tmm.hour; }
uint8_t minute(void) { getTime(tmm); return tmm.minute; }
uint8_t second(void) { getTime(tmm); return tmm.second; }
uint8_t isPM(void) { return ( hour()>=12 ); }
uint8_t year(time_t t) { breakTime(t, tmm); return tmm.year; }
uint8_t month(time_t t) { breakTime(t, tmm); return tmm.month; }
uint8_t day(time_t t) { breakTime(t, tmm); return tmm.day; }
uint8_t weekday(time_t t) { breakTime(t, tmm); return tmm.weekday; }
uint8_t hour(time_t t) { breakTime(t, tmm); return tmm.hour; }
uint8_t minute(time_t t) { breakTime(t, tmm); return tmm.minute; }
uint8_t second(time_t t) { breakTime(t, tmm); return tmm.second; }
uint8_t isPM(time_t t) { return (hour(t)>=12); }
void createAlarm(voidFuncPtr function, time_t alarm_time_t);
void createAlarm(voidFuncPtr function, struct tm* alarm_tm);
void createAlarm(voidFuncPtr function, struct tm_t & alarm_tm);
void attachSecondsInterrupt(voidFuncPtr function);
void detachSecondsInterrupt();
void setAlarmTime (tm * tm_ptr);
void setAlarmTime (tm_t & tm_ptr);
void setAlarmTime (time_t alarm_time);
//private:
tm_t tmm;
};
} ;