timekeeper fixes
This commit is contained in:
		
							parent
							
								
									f944725cff
								
							
						
					
					
						commit
						182f850d23
					
				| @ -1,359 +0,0 @@ | ||||
| /*
 | ||||
|   time.c - low level time and date functions | ||||
|   Copyright (c) Michael Margolis 2009-2014 | ||||
| 
 | ||||
|   This library is free software; you can redistribute it and/or | ||||
|   modify it under the terms of the GNU Lesser General Public | ||||
|   License as published by the Free Software Foundation; either | ||||
|   version 2.1 of the License, or (at your option) any later version. | ||||
| 
 | ||||
|   This library 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 | ||||
|   Lesser General Public License for more details. | ||||
| 
 | ||||
|   You should have received a copy of the GNU Lesser General Public | ||||
|   License along with this library; if not, write to the Free Software | ||||
|   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|    | ||||
|   1.0  6  Jan 2010 - initial release | ||||
|   1.1  12 Feb 2010 - fixed leap year calculation error | ||||
|   1.2  1  Nov 2010 - fixed setTime bug (thanks to Korman for this) | ||||
|   1.3  24 Mar 2012 - many edits by Paul Stoffregen: fixed timeStatus() to update | ||||
|                      status, updated examples for Arduino 1.0, fixed ARM | ||||
|                      compatibility issues, added TimeArduinoDue and TimeTeensy3 | ||||
|                      examples, add error checking and messages to RTC examples, | ||||
|                      add examples to DS1307RTC library. | ||||
|   1.4  5  Sep 2014 - compatibility with Arduino 1.5.7 | ||||
| */ | ||||
| 
 | ||||
| #if ARDUINO >= 100 | ||||
| #include <Arduino.h>  | ||||
| #else | ||||
| #include <WProgram.h>  | ||||
| #endif | ||||
| 
 | ||||
| #define TIMELIB_ENABLE_MILLIS | ||||
| #define usePPS | ||||
| 
 | ||||
| #include "microTimeLib.h" | ||||
| 
 | ||||
| // Convert days since epoch to week day. Sunday is day 1.
 | ||||
| #define DAYS_TO_WDAY(x) (((x) + 4) % 7) + 1 | ||||
| 
 | ||||
| static tmElements_t cacheElements;   // a cache of time elements
 | ||||
| static time_t cacheTime;   // the time the cache was updated
 | ||||
| static uint32_t syncInterval = 300;  // time sync will be attempted after this many seconds
 | ||||
| 
 | ||||
| void refreshCache(time_t t) { | ||||
|   if (t != cacheTime) { | ||||
|     breakTime(t, cacheElements); | ||||
|     cacheTime = t; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| int hour() { // the hour now 
 | ||||
|   return hour(now());  | ||||
| } | ||||
| 
 | ||||
| int hour(time_t t) { // the hour for the given time
 | ||||
|   refreshCache(t); | ||||
|   return cacheElements.Hour; | ||||
| } | ||||
| 
 | ||||
| int hourFormat12() { // the hour now in 12 hour format
 | ||||
|   return hourFormat12(now());  | ||||
| } | ||||
| 
 | ||||
| int hourFormat12(time_t t) { // the hour for the given time in 12 hour format
 | ||||
|   refreshCache(t); | ||||
|   if( cacheElements.Hour == 0 ) | ||||
|     return 12; // 12 midnight
 | ||||
|   else if( cacheElements.Hour  > 12) | ||||
|     return cacheElements.Hour - 12 ; | ||||
|   else | ||||
|     return cacheElements.Hour ; | ||||
| } | ||||
| 
 | ||||
| uint8_t isAM() { // returns true if time now is AM
 | ||||
|   return !isPM(now());  | ||||
| } | ||||
| 
 | ||||
| uint8_t isAM(time_t t) { // returns true if given time is AM
 | ||||
|   return !isPM(t);   | ||||
| } | ||||
| 
 | ||||
| uint8_t isPM() { // returns true if PM
 | ||||
|   return isPM(now());  | ||||
| } | ||||
| 
 | ||||
| uint8_t isPM(time_t t) { // returns true if PM
 | ||||
|   return (hour(t) >= 12);  | ||||
| } | ||||
| 
 | ||||
| int minute() { | ||||
|   return minute(now());  | ||||
| } | ||||
| 
 | ||||
| int minute(time_t t) { // the minute for the given time
 | ||||
|   refreshCache(t); | ||||
|   return cacheElements.Minute; | ||||
| } | ||||
| 
 | ||||
| int second() { | ||||
|   return second(now());  | ||||
| } | ||||
| 
 | ||||
| int second(time_t t) {  // the second for the given time
 | ||||
|   refreshCache(t); | ||||
|   return cacheElements.Second; | ||||
| } | ||||
| 
 | ||||
| int millisecond() { | ||||
|   uint32_t ms; | ||||
|   now(ms); | ||||
|   ms = ms / 1000; | ||||
|   return (int)ms; | ||||
| } | ||||
| 
 | ||||
| int microsecond() { | ||||
|   uint32_t us; | ||||
|   now(us); | ||||
|   return (int)us; | ||||
| } | ||||
| 
 | ||||
| int day(){ | ||||
|   return(day(now()));  | ||||
| } | ||||
| 
 | ||||
| int day(time_t t) { // the day for the given time (0-6)
 | ||||
|   refreshCache(t); | ||||
|   return cacheElements.Day; | ||||
| } | ||||
| 
 | ||||
| int weekday() {   // Sunday is day 1
 | ||||
|   return weekday(now());  | ||||
| } | ||||
| 
 | ||||
| int weekday(time_t t) { | ||||
|   refreshCache(t); | ||||
|   return cacheElements.Wday; | ||||
| } | ||||
|     | ||||
| int month(){ | ||||
|   return month(now());  | ||||
| } | ||||
| 
 | ||||
| int month(time_t t) {  // the month for the given time
 | ||||
|   refreshCache(t); | ||||
|   return cacheElements.Month; | ||||
| } | ||||
| 
 | ||||
| int year() {  // as in Processing, the full four digit year: (2009, 2010 etc) 
 | ||||
|   return year(now());  | ||||
| } | ||||
| 
 | ||||
| int year(time_t t) { // the year for the given time
 | ||||
|   refreshCache(t); | ||||
|   return tmYearToCalendar(cacheElements.Year); | ||||
| } | ||||
| 
 | ||||
| /*============================================================================*/	 | ||||
| /* functions to convert to and from system time */ | ||||
| /* These are for interfacing with time serivces and are not normally needed in a sketch */ | ||||
| 
 | ||||
| // leap year calulator expects year argument as years offset from 1970
 | ||||
| #define LEAP_YEAR(Y)     ( ((1970+(Y))>0) && !((1970+(Y))%4) && ( ((1970+(Y))%100) || !((1970+(Y))%400) ) ) | ||||
| #define daysInYear(year) ((time_t) (LEAP_YEAR(year) ? 366 : 365)) | ||||
| 
 | ||||
| static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0
 | ||||
| 
 | ||||
| void breakTime(time_t time, tmElements_t &tm){ | ||||
| // 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 period; | ||||
|   time_t length; | ||||
| 
 | ||||
|   tm.Second = time % 60; | ||||
|   time /= 60; // now it is minutes
 | ||||
|   tm.Minute = time % 60; | ||||
|   time /= 60; // now it is hours
 | ||||
|   tm.Hour = time % 24; | ||||
|   time /= 24; // now it is days since 1 Jan 1970
 | ||||
| 
 | ||||
|   // if the number of days since epoch matches cacheTime, then can take date
 | ||||
|   // elements from cacheElements and avoid expensive calculation.
 | ||||
|   if (time == (cacheTime / SECS_PER_DAY)) { | ||||
|     if (&tm != &cacheElements) {  // check whether tm is actually cacheElements
 | ||||
|       tm.Wday = cacheElements.Wday; | ||||
|       tm.Day = cacheElements.Day; | ||||
|       tm.Month = cacheElements.Month; | ||||
|       tm.Year = cacheElements.Year; | ||||
|     } | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   tm.Wday = DAYS_TO_WDAY(time); | ||||
|    | ||||
|   period = 0; | ||||
|   while (time >= (length = daysInYear(period))) | ||||
|   { | ||||
|     time -= length; | ||||
|     period++; | ||||
|   } | ||||
|   tm.Year = period; // year is offset from 1970 
 | ||||
|   // time is now days since 1 Jan of the year
 | ||||
| 
 | ||||
|   bool leap_year = LEAP_YEAR(period); | ||||
|   period = 0; | ||||
|   while (period < 12 && time >= (length = monthDays[period] + (leap_year && period==1))) | ||||
|   { | ||||
|     time -= length; | ||||
|     period++; | ||||
|   } | ||||
|   tm.Month = period + 1;  // jan is month 1  
 | ||||
|   // time is now days since the 1st day of the month
 | ||||
| 
 | ||||
|   tm.Day = time + 1;  // day of month
 | ||||
| } | ||||
| 
 | ||||
| time_t makeTime(const tmElements_t &tm){    | ||||
| // 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 = SECS_PER_DAY * (365 * tm.Year); | ||||
|   for (i = 0; i < tm.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 < tm.Month; i++) { | ||||
|     if ( (i == 2) && LEAP_YEAR(tm.Year)) {  | ||||
|       seconds += SECS_PER_DAY * 29; | ||||
|     } else { | ||||
|       seconds += SECS_PER_DAY * monthDays[i-1];  //monthDay array starts from 0
 | ||||
|     } | ||||
|   } | ||||
|   seconds+= (tm.Day-1) * SECS_PER_DAY; | ||||
|   seconds+= tm.Hour * SECS_PER_HOUR; | ||||
|   seconds+= tm.Minute * SECS_PER_MIN; | ||||
|   seconds+= tm.Second; | ||||
|   return (time_t)seconds;  | ||||
| } | ||||
| /*=====================================================*/	 | ||||
| /* Low level system time functions  */ | ||||
| 
 | ||||
| static time_t sysTime = 0; | ||||
| static uint32_t prevMicros = 0; | ||||
| static time_t nextSyncTime = 0; | ||||
| static timeStatus_t Status = timeNotSet; | ||||
| 
 | ||||
| getExternalTime getTimePtr;  // pointer to external sync function
 | ||||
| //setExternalTime setTimePtr; // not used in this version
 | ||||
| 
 | ||||
| #ifdef TIME_DRIFT_INFO   // define this to get drift data
 | ||||
| time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync  
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef usePPS | ||||
| void SyncToPPS() | ||||
| { | ||||
|   sysTime++; | ||||
|   prevMicros = micros(); | ||||
|   //Serial.println(prevMicros);  
 | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| time_t now() { | ||||
|   uint32_t sysTimeMicros; | ||||
|   return now(sysTimeMicros); | ||||
| } | ||||
| 
 | ||||
| time_t now(uint32_t& sysTimeMicros) { | ||||
|   // calculate number of seconds passed since last call to now()
 | ||||
|   while ((sysTimeMicros = micros() - prevMicros) >= 1000000) {  | ||||
|     // micros() and prevMicros are both unsigned ints thus the subtraction will
 | ||||
|     // always result in a positive difference. This is OK since it corrects for
 | ||||
|     // wrap-around and micros() is monotonic.
 | ||||
|     sysTime++; | ||||
|     prevMicros += 1000000;	 | ||||
| #ifdef TIME_DRIFT_INFO | ||||
|     sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift     
 | ||||
| #endif | ||||
|   } | ||||
|   if (nextSyncTime <= sysTime) { | ||||
|     if (getTimePtr != 0) { | ||||
|       time_t t = getTimePtr(); | ||||
|        | ||||
|       if (t != 0) { | ||||
|         setTime(t); | ||||
|       } else { | ||||
|         nextSyncTime = sysTime + syncInterval; | ||||
|         Status = (Status == timeNotSet) ?  timeNotSet : timeNeedsSync; | ||||
|       } | ||||
|     } | ||||
|   }   | ||||
|   return sysTime; | ||||
| } | ||||
| 
 | ||||
| void setTime(time_t t) {  | ||||
| #ifdef TIME_DRIFT_INFO | ||||
|  if(sysUnsyncedTime == 0)  | ||||
|    sysUnsyncedTime = t;   // store the time of the first call to set a valid Time   
 | ||||
| #endif | ||||
| 
 | ||||
|   sysTime = t;   | ||||
|   nextSyncTime = t + (time_t) syncInterval; | ||||
|   Status = timeSet; | ||||
|   #ifndef usePPS | ||||
|     prevMicros = micros();  // restart counting from now (thanks to Korman for this fix)
 | ||||
|   #endif | ||||
| }  | ||||
| 
 | ||||
| void setTime(int hr, int min, int sec, int dy, int mnth, int yr) { | ||||
|   // year can be given as full four digit year or two digts (2010 or 10 for 2010);
 | ||||
|   // it is converted to years since 1970
 | ||||
|   if (yr > 99) | ||||
|       yr = CalendarYrToTm(yr); | ||||
|   else | ||||
|       yr = tmYearToY2k(yr); | ||||
|   cacheElements.Year = yr; | ||||
|   cacheElements.Month = mnth; | ||||
|   cacheElements.Day = dy; | ||||
|   cacheElements.Hour = hr; | ||||
|   cacheElements.Minute = min; | ||||
|   cacheElements.Second = sec; | ||||
|   cacheTime = makeTime(cacheElements); | ||||
|   cacheElements.Wday = DAYS_TO_WDAY(cacheTime / SECS_PER_DAY); | ||||
|   setTime(cacheTime); | ||||
| } | ||||
| 
 | ||||
| void adjustTime(long adjustment) { | ||||
|   sysTime += adjustment; | ||||
| } | ||||
| 
 | ||||
| // indicates if time has been set and recently synchronized
 | ||||
| timeStatus_t timeStatus() { | ||||
|   now(); // required to actually update the status
 | ||||
|   return Status; | ||||
| } | ||||
| 
 | ||||
| void setSyncProvider(getExternalTime getTimeFunction){ | ||||
|   getTimePtr = getTimeFunction;   | ||||
|   nextSyncTime = sysTime; | ||||
|   now(); // this will sync the clock
 | ||||
| } | ||||
| 
 | ||||
| void setSyncInterval(time_t interval){ // set the number of seconds between re-sync
 | ||||
|   syncInterval = (uint32_t)interval; | ||||
|   nextSyncTime = sysTime + syncInterval; | ||||
| } | ||||
| @ -27,11 +27,7 @@ | ||||
|   1.4  5  Sep 2014 - compatibility with Arduino 1.5.7 | ||||
| */ | ||||
| 
 | ||||
| #if ARDUINO >= 100 | ||||
| #include <Arduino.h>  | ||||
| #else | ||||
| #include <WProgram.h>  | ||||
| #endif | ||||
| #include <Arduino.h> | ||||
| 
 | ||||
| #define TIMELIB_ENABLE_MILLIS | ||||
| #define usePPS | ||||
| @ -41,9 +37,10 @@ | ||||
| // Convert days since epoch to week day. Sunday is day 1.
 | ||||
| #define DAYS_TO_WDAY(x) (((x) + 4) % 7) + 1 | ||||
| 
 | ||||
| static tmElements_t cacheElements;   // a cache of time elements
 | ||||
| static time_t cacheTime;   // the time the cache was updated
 | ||||
| static uint32_t syncInterval = 300;  // time sync will be attempted after this many seconds
 | ||||
| static tmElements_t cacheElements; // a cache of time elements
 | ||||
| static time_t cacheTime;           // the time the cache was updated
 | ||||
| static uint32_t syncInterval = | ||||
|     300; // time sync will be attempted after this many seconds
 | ||||
| 
 | ||||
| void refreshCache(time_t t) { | ||||
|   if (t != cacheTime) { | ||||
| @ -52,8 +49,8 @@ void refreshCache(time_t t) { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| int hour() { // the hour now 
 | ||||
|   return hour(now());  | ||||
| int hour() { // the hour now
 | ||||
|   return hour(now()); | ||||
| } | ||||
| 
 | ||||
| int hour(time_t t) { // the hour for the given time
 | ||||
| @ -62,49 +59,45 @@ int hour(time_t t) { // the hour for the given time | ||||
| } | ||||
| 
 | ||||
| int hourFormat12() { // the hour now in 12 hour format
 | ||||
|   return hourFormat12(now());  | ||||
|   return hourFormat12(now()); | ||||
| } | ||||
| 
 | ||||
| int hourFormat12(time_t t) { // the hour for the given time in 12 hour format
 | ||||
|   refreshCache(t); | ||||
|   if( cacheElements.Hour == 0 ) | ||||
|   if (cacheElements.Hour == 0) | ||||
|     return 12; // 12 midnight
 | ||||
|   else if( cacheElements.Hour  > 12) | ||||
|     return cacheElements.Hour - 12 ; | ||||
|   else if (cacheElements.Hour > 12) | ||||
|     return cacheElements.Hour - 12; | ||||
|   else | ||||
|     return cacheElements.Hour ; | ||||
|     return cacheElements.Hour; | ||||
| } | ||||
| 
 | ||||
| uint8_t isAM() { // returns true if time now is AM
 | ||||
|   return !isPM(now());  | ||||
|   return !isPM(now()); | ||||
| } | ||||
| 
 | ||||
| uint8_t isAM(time_t t) { // returns true if given time is AM
 | ||||
|   return !isPM(t);   | ||||
|   return !isPM(t); | ||||
| } | ||||
| 
 | ||||
| uint8_t isPM() { // returns true if PM
 | ||||
|   return isPM(now());  | ||||
|   return isPM(now()); | ||||
| } | ||||
| 
 | ||||
| uint8_t isPM(time_t t) { // returns true if PM
 | ||||
|   return (hour(t) >= 12);  | ||||
|   return (hour(t) >= 12); | ||||
| } | ||||
| 
 | ||||
| int minute() { | ||||
|   return minute(now());  | ||||
| } | ||||
| int minute() { return minute(now()); } | ||||
| 
 | ||||
| int minute(time_t t) { // the minute for the given time
 | ||||
|   refreshCache(t); | ||||
|   return cacheElements.Minute; | ||||
| } | ||||
| 
 | ||||
| int second() { | ||||
|   return second(now());  | ||||
| } | ||||
| int second() { return second(now()); } | ||||
| 
 | ||||
| int second(time_t t) {  // the second for the given time
 | ||||
| int second(time_t t) { // the second for the given time
 | ||||
|   refreshCache(t); | ||||
|   return cacheElements.Second; | ||||
| } | ||||
| @ -122,35 +115,31 @@ int microsecond() { | ||||
|   return (int)us; | ||||
| } | ||||
| 
 | ||||
| int day(){ | ||||
|   return(day(now()));  | ||||
| } | ||||
| int day() { return (day(now())); } | ||||
| 
 | ||||
| int day(time_t t) { // the day for the given time (0-6)
 | ||||
|   refreshCache(t); | ||||
|   return cacheElements.Day; | ||||
| } | ||||
| 
 | ||||
| int weekday() {   // Sunday is day 1
 | ||||
|   return weekday(now());  | ||||
| int weekday() { // Sunday is day 1
 | ||||
|   return weekday(now()); | ||||
| } | ||||
| 
 | ||||
| int weekday(time_t t) { | ||||
|   refreshCache(t); | ||||
|   return cacheElements.Wday; | ||||
| } | ||||
|     | ||||
| int month(){ | ||||
|   return month(now());  | ||||
| } | ||||
| 
 | ||||
| int month(time_t t) {  // the month for the given time
 | ||||
| int month() { return month(now()); } | ||||
| 
 | ||||
| int month(time_t t) { // the month for the given time
 | ||||
|   refreshCache(t); | ||||
|   return cacheElements.Month; | ||||
| } | ||||
| 
 | ||||
| int year() {  // as in Processing, the full four digit year: (2009, 2010 etc) 
 | ||||
|   return year(now());  | ||||
| int year() { // as in Processing, the full four digit year: (2009, 2010 etc)
 | ||||
|   return year(now()); | ||||
| } | ||||
| 
 | ||||
| int year(time_t t) { // the year for the given time
 | ||||
| @ -158,20 +147,25 @@ int year(time_t t) { // the year for the given time | ||||
|   return tmYearToCalendar(cacheElements.Year); | ||||
| } | ||||
| 
 | ||||
| /*============================================================================*/	 | ||||
| /*============================================================================*/ | ||||
| /* functions to convert to and from system time */ | ||||
| /* These are for interfacing with time serivces and are not normally needed in a sketch */ | ||||
| /* These are for interfacing with time serivces and are not normally needed in a
 | ||||
|  * sketch */ | ||||
| 
 | ||||
| // leap year calulator expects year argument as years offset from 1970
 | ||||
| #define LEAP_YEAR(Y)     ( ((1970+(Y))>0) && !((1970+(Y))%4) && ( ((1970+(Y))%100) || !((1970+(Y))%400) ) ) | ||||
| #define daysInYear(year) ((time_t) (LEAP_YEAR(year) ? 366 : 365)) | ||||
| #define LEAP_YEAR(Y)                                                           \ | ||||
|   (((1970 + (Y)) > 0) && !((1970 + (Y)) % 4) &&                                \ | ||||
|    (((1970 + (Y)) % 100) || !((1970 + (Y)) % 400))) | ||||
| #define daysInYear(year) ((time_t)(LEAP_YEAR(year) ? 366 : 365)) | ||||
| 
 | ||||
| static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0
 | ||||
| static const uint8_t monthDays[] = { | ||||
|     31, 28, 31, 30, 31, 30, 31, | ||||
|     31, 30, 31, 30, 31}; // API starts months from 1, this array starts from 0
 | ||||
| 
 | ||||
| void breakTime(time_t time, tmElements_t &tm){ | ||||
| // 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 !!!
 | ||||
| void breakTime(time_t time, tmElements_t &tm) { | ||||
|   // 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 period; | ||||
|   time_t length; | ||||
| @ -186,7 +180,7 @@ void breakTime(time_t time, tmElements_t &tm){ | ||||
|   // if the number of days since epoch matches cacheTime, then can take date
 | ||||
|   // elements from cacheElements and avoid expensive calculation.
 | ||||
|   if (time == (cacheTime / SECS_PER_DAY)) { | ||||
|     if (&tm != &cacheElements) {  // check whether tm is actually cacheElements
 | ||||
|     if (&tm != &cacheElements) { // check whether tm is actually cacheElements
 | ||||
|       tm.Wday = cacheElements.Wday; | ||||
|       tm.Day = cacheElements.Day; | ||||
|       tm.Month = cacheElements.Month; | ||||
| @ -196,34 +190,34 @@ void breakTime(time_t time, tmElements_t &tm){ | ||||
|   } | ||||
| 
 | ||||
|   tm.Wday = DAYS_TO_WDAY(time); | ||||
|    | ||||
| 
 | ||||
|   period = 0; | ||||
|   while (time >= (length = daysInYear(period))) | ||||
|   { | ||||
|   while (time >= (length = daysInYear(period))) { | ||||
|     time -= length; | ||||
|     period++; | ||||
|   } | ||||
|   tm.Year = period; // year is offset from 1970 
 | ||||
|   tm.Year = period; // year is offset from 1970
 | ||||
|   // time is now days since 1 Jan of the year
 | ||||
| 
 | ||||
|   bool leap_year = LEAP_YEAR(period); | ||||
|   period = 0; | ||||
|   while (period < 12 && time >= (length = monthDays[period] + (leap_year && period==1))) | ||||
|   { | ||||
|   while (period < 12 && | ||||
|          time >= (length = monthDays[period] + (leap_year && period == 1))) { | ||||
|     time -= length; | ||||
|     period++; | ||||
|   } | ||||
|   tm.Month = period + 1;  // jan is month 1  
 | ||||
|   tm.Month = period + 1; // jan is month 1
 | ||||
|   // time is now days since the 1st day of the month
 | ||||
| 
 | ||||
|   tm.Day = time + 1;  // day of month
 | ||||
|   tm.Day = time + 1; // day of month
 | ||||
| } | ||||
| 
 | ||||
| time_t makeTime(const tmElements_t &tm){    | ||||
| // 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
 | ||||
|    | ||||
| time_t makeTime(const tmElements_t &tm) { | ||||
|   // 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; | ||||
| 
 | ||||
| @ -231,25 +225,26 @@ time_t makeTime(const tmElements_t &tm){ | ||||
|   seconds = SECS_PER_DAY * (365 * tm.Year); | ||||
|   for (i = 0; i < tm.Year; i++) { | ||||
|     if (LEAP_YEAR(i)) { | ||||
|       seconds +=  SECS_PER_DAY;   // add extra days for leap years
 | ||||
|       seconds += SECS_PER_DAY; // add extra days for leap years
 | ||||
|     } | ||||
|   } | ||||
|    | ||||
| 
 | ||||
|   // add days for this year, months start from 1
 | ||||
|   for (i = 1; i < tm.Month; i++) { | ||||
|     if ( (i == 2) && LEAP_YEAR(tm.Year)) {  | ||||
|     if ((i == 2) && LEAP_YEAR(tm.Year)) { | ||||
|       seconds += SECS_PER_DAY * 29; | ||||
|     } else { | ||||
|       seconds += SECS_PER_DAY * monthDays[i-1];  //monthDay array starts from 0
 | ||||
|       seconds += SECS_PER_DAY * monthDays[i - 1]; // monthDay array starts from
 | ||||
|                                                   // 0
 | ||||
|     } | ||||
|   } | ||||
|   seconds+= (tm.Day-1) * SECS_PER_DAY; | ||||
|   seconds+= tm.Hour * SECS_PER_HOUR; | ||||
|   seconds+= tm.Minute * SECS_PER_MIN; | ||||
|   seconds+= tm.Second; | ||||
|   return (time_t)seconds;  | ||||
|   seconds += (tm.Day - 1) * SECS_PER_DAY; | ||||
|   seconds += tm.Hour * SECS_PER_HOUR; | ||||
|   seconds += tm.Minute * SECS_PER_MIN; | ||||
|   seconds += tm.Second; | ||||
|   return (time_t)seconds; | ||||
| } | ||||
| /*=====================================================*/	 | ||||
| /*=====================================================*/ | ||||
| /* Low level system time functions  */ | ||||
| 
 | ||||
| static time_t sysTime = 0; | ||||
| @ -257,19 +252,18 @@ static uint32_t prevMicros = 0; | ||||
| static time_t nextSyncTime = 0; | ||||
| static timeStatus_t Status = timeNotSet; | ||||
| 
 | ||||
| getExternalTime getTimePtr;  // pointer to external sync function
 | ||||
| //setExternalTime setTimePtr; // not used in this version
 | ||||
| getExternalTime getTimePtr; // pointer to external sync function
 | ||||
| // setExternalTime setTimePtr; // not used in this version
 | ||||
| 
 | ||||
| #ifdef TIME_DRIFT_INFO   // define this to get drift data
 | ||||
| time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync  
 | ||||
| #ifdef TIME_DRIFT_INFO      // define this to get drift data
 | ||||
| time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef usePPS | ||||
| void SyncToPPS() | ||||
| { | ||||
| time_t SyncToPPS() { | ||||
|   sysTime++; | ||||
|   prevMicros = micros(); | ||||
|   //Serial.println(prevMicros);  
 | ||||
|   return sysTime; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| @ -278,54 +272,56 @@ time_t now() { | ||||
|   return now(sysTimeMicros); | ||||
| } | ||||
| 
 | ||||
| time_t now(uint32_t& sysTimeMicros) { | ||||
| time_t now(uint32_t &sysTimeMicros) { | ||||
|   // calculate number of seconds passed since last call to now()
 | ||||
|   while ((sysTimeMicros = micros() - prevMicros) >= 1000000) {  | ||||
|   while ((sysTimeMicros = micros() - prevMicros) >= 1000000) { | ||||
|     // micros() and prevMicros are both unsigned ints thus the subtraction will
 | ||||
|     // always result in a positive difference. This is OK since it corrects for
 | ||||
|     // wrap-around and micros() is monotonic.
 | ||||
|     sysTime++; | ||||
|     prevMicros += 1000000;	 | ||||
|     prevMicros += 1000000; | ||||
| #ifdef TIME_DRIFT_INFO | ||||
|     sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift     
 | ||||
|     sysUnsyncedTime++; // this can be compared to the synced time to measure
 | ||||
|                        // long term drift
 | ||||
| #endif | ||||
|   } | ||||
|   if (nextSyncTime <= sysTime) { | ||||
|     if (getTimePtr != 0) { | ||||
|       time_t t = getTimePtr(); | ||||
|        | ||||
| 
 | ||||
|       if (t != 0) { | ||||
|         setTime(t); | ||||
|       } else { | ||||
|         nextSyncTime = sysTime + syncInterval; | ||||
|         Status = (Status == timeNotSet) ?  timeNotSet : timeNeedsSync; | ||||
|         Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync; | ||||
|       } | ||||
|     } | ||||
|   }   | ||||
|   } | ||||
|   return sysTime; | ||||
| } | ||||
| 
 | ||||
| void setTime(time_t t) {  | ||||
| void setTime(time_t t) { | ||||
| #ifdef TIME_DRIFT_INFO | ||||
|  if(sysUnsyncedTime == 0)  | ||||
|    sysUnsyncedTime = t;   // store the time of the first call to set a valid Time   
 | ||||
|   if (sysUnsyncedTime == 0) | ||||
|     sysUnsyncedTime = t; // store the time of the first call to set a valid Time
 | ||||
| #endif | ||||
| 
 | ||||
|   sysTime = t;   | ||||
|   nextSyncTime = t + (time_t) syncInterval; | ||||
|   sysTime = t; | ||||
|   nextSyncTime = t + (time_t)syncInterval; | ||||
|   Status = timeSet; | ||||
|   #ifndef usePPS | ||||
|     prevMicros = micros();  // restart counting from now (thanks to Korman for this fix)
 | ||||
|   #endif | ||||
| }  | ||||
| #ifndef usePPS | ||||
|   prevMicros = | ||||
|       micros(); // restart counting from now (thanks to Korman for this fix)
 | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void setTime(int hr, int min, int sec, int dy, int mnth, int yr) { | ||||
|   // year can be given as full four digit year or two digts (2010 or 10 for 2010);
 | ||||
|   // it is converted to years since 1970
 | ||||
|   // year can be given as full four digit year or two digts (2010 or 10 for
 | ||||
|   // 2010); it is converted to years since 1970
 | ||||
|   if (yr > 99) | ||||
|       yr = CalendarYrToTm(yr); | ||||
|     yr = CalendarYrToTm(yr); | ||||
|   else | ||||
|       yr = tmYearToY2k(yr); | ||||
|     yr = tmYearToY2k(yr); | ||||
|   cacheElements.Year = yr; | ||||
|   cacheElements.Month = mnth; | ||||
|   cacheElements.Day = dy; | ||||
| @ -337,9 +333,7 @@ void setTime(int hr, int min, int sec, int dy, int mnth, int yr) { | ||||
|   setTime(cacheTime); | ||||
| } | ||||
| 
 | ||||
| void adjustTime(long adjustment) { | ||||
|   sysTime += adjustment; | ||||
| } | ||||
| void adjustTime(long adjustment) { sysTime += adjustment; } | ||||
| 
 | ||||
| // indicates if time has been set and recently synchronized
 | ||||
| timeStatus_t timeStatus() { | ||||
| @ -347,13 +341,14 @@ timeStatus_t timeStatus() { | ||||
|   return Status; | ||||
| } | ||||
| 
 | ||||
| void setSyncProvider(getExternalTime getTimeFunction){ | ||||
|   getTimePtr = getTimeFunction;   | ||||
| void setSyncProvider(getExternalTime getTimeFunction) { | ||||
|   getTimePtr = getTimeFunction; | ||||
|   nextSyncTime = sysTime; | ||||
|   now(); // this will sync the clock
 | ||||
| } | ||||
| 
 | ||||
| void setSyncInterval(time_t interval){ // set the number of seconds between re-sync
 | ||||
| void setSyncInterval( | ||||
|     time_t interval) { // set the number of seconds between re-sync
 | ||||
|   syncInterval = (uint32_t)interval; | ||||
|   nextSyncTime = sysTime + syncInterval; | ||||
| } | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
| /*
 | ||||
|   July 3 2011 - fixed elapsedSecsThisWeek macro (thanks Vincent Valdy for this) | ||||
|               - fixed  daysToTime_t macro (thanks maniacbug) | ||||
| */      | ||||
| */ | ||||
| 
 | ||||
| #ifndef _Time_h | ||||
| #ifdef __cplusplus | ||||
| @ -16,7 +16,6 @@ | ||||
| #include <sys/types.h> // for __time_t_defined, but avr libc lacks sys/types.h | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #if !defined(__time_t_defined) // avoid conflict with newlib or other posix libc
 | ||||
| typedef unsigned long time_t; | ||||
| #endif | ||||
| @ -33,126 +32,154 @@ typedef unsigned long time_t; | ||||
| // but at least this hack lets us define C++ functions as intended.  Hopefully
 | ||||
| // nothing too terrible will result from overriding the C library header?!
 | ||||
| extern "C++" { | ||||
| typedef enum {timeNotSet, timeNeedsSync, timeSet | ||||
| }  timeStatus_t ; | ||||
| typedef enum { timeNotSet, timeNeedsSync, timeSet } timeStatus_t; | ||||
| 
 | ||||
| typedef enum { | ||||
|     dowInvalid, dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday | ||||
|   dowInvalid, | ||||
|   dowSunday, | ||||
|   dowMonday, | ||||
|   dowTuesday, | ||||
|   dowWednesday, | ||||
|   dowThursday, | ||||
|   dowFriday, | ||||
|   dowSaturday | ||||
| } timeDayOfWeek_t; | ||||
| 
 | ||||
| typedef enum { | ||||
|     tmSecond, tmMinute, tmHour, tmWday, tmDay,tmMonth, tmYear, tmNbrFields | ||||
| } tmByteFields;	    | ||||
|   tmSecond, | ||||
|   tmMinute, | ||||
|   tmHour, | ||||
|   tmWday, | ||||
|   tmDay, | ||||
|   tmMonth, | ||||
|   tmYear, | ||||
|   tmNbrFields | ||||
| } tmByteFields; | ||||
| 
 | ||||
| typedef struct  {  | ||||
|   uint8_t Second;  | ||||
|   uint8_t Minute;  | ||||
|   uint8_t Hour;  | ||||
|   uint8_t Wday;   // day of week, sunday is day 1
 | ||||
| typedef struct { | ||||
|   uint8_t Second; | ||||
|   uint8_t Minute; | ||||
|   uint8_t Hour; | ||||
|   uint8_t Wday; // day of week, sunday is day 1
 | ||||
|   uint8_t Day; | ||||
|   uint8_t Month;  | ||||
|   uint8_t Year;   // offset from 1970; 
 | ||||
| } 	tmElements_t, TimeElements, *tmElementsPtr_t; | ||||
|   uint8_t Month; | ||||
|   uint8_t Year; // offset from 1970;
 | ||||
| } tmElements_t, TimeElements, *tmElementsPtr_t; | ||||
| 
 | ||||
| //convenience macros to convert to and from tm years 
 | ||||
| #define  tmYearToCalendar(Y) ((Y) + 1970)  // full four digit year 
 | ||||
| #define  CalendarYrToTm(Y)   ((Y) - 1970) | ||||
| #define  tmYearToY2k(Y)      ((Y) - 30)    // offset is from 2000
 | ||||
| #define  y2kYearToTm(Y)      ((Y) + 30)    | ||||
| 
 | ||||
| typedef time_t(*getExternalTime)(); | ||||
| //typedef void  (*setExternalTime)(const time_t); // not used in this version
 | ||||
| // convenience macros to convert to and from tm years
 | ||||
| #define tmYearToCalendar(Y) ((Y) + 1970) // full four digit year
 | ||||
| #define CalendarYrToTm(Y) ((Y)-1970) | ||||
| #define tmYearToY2k(Y) ((Y)-30) // offset is from 2000
 | ||||
| #define y2kYearToTm(Y) ((Y) + 30) | ||||
| 
 | ||||
| typedef time_t (*getExternalTime)(); | ||||
| // typedef void  (*setExternalTime)(const time_t); // not used in this version
 | ||||
| 
 | ||||
| /*==============================================================================*/ | ||||
| /* Useful Constants */ | ||||
| #define SECS_PER_MIN  ((time_t)(60UL)) | ||||
| #define SECS_PER_MIN ((time_t)(60UL)) | ||||
| #define SECS_PER_HOUR ((time_t)(3600UL)) | ||||
| #define SECS_PER_DAY  ((time_t)(SECS_PER_HOUR * 24UL)) | ||||
| #define SECS_PER_DAY ((time_t)(SECS_PER_HOUR * 24UL)) | ||||
| #define DAYS_PER_WEEK ((time_t)(7UL)) | ||||
| #define SECS_PER_WEEK ((time_t)(SECS_PER_DAY * DAYS_PER_WEEK)) | ||||
| #define SECS_PER_YEAR ((time_t)(SECS_PER_DAY * 365UL)) // TODO: ought to handle leap years
 | ||||
| #define SECS_YR_2000  ((time_t)(946684800UL)) // the time at the start of y2k
 | ||||
|   | ||||
| /* Useful Macros for getting elapsed time */ | ||||
| #define numberOfSeconds(_time_) ((_time_) % SECS_PER_MIN)   | ||||
| #define numberOfMinutes(_time_) (((_time_) / SECS_PER_MIN) % SECS_PER_MIN)  | ||||
| #define numberOfHours(_time_) (((_time_) % SECS_PER_DAY) / SECS_PER_HOUR) | ||||
| #define dayOfWeek(_time_) ((((_time_) / SECS_PER_DAY + 4)  % DAYS_PER_WEEK)+1) // 1 = Sunday
 | ||||
| #define elapsedDays(_time_) ((_time_) / SECS_PER_DAY)  // this is number of days since Jan 1 1970
 | ||||
| #define elapsedSecsToday(_time_) ((_time_) % SECS_PER_DAY)   // the number of seconds since last midnight 
 | ||||
| // The following macros are used in calculating alarms and assume the clock is set to a date later than Jan 1 1971
 | ||||
| // Always set the correct time before settting alarms
 | ||||
| #define previousMidnight(_time_) (((_time_) / SECS_PER_DAY) * SECS_PER_DAY)  // time at the start of the given day
 | ||||
| #define nextMidnight(_time_) (previousMidnight(_time_)  + SECS_PER_DAY)   // time at the end of the given day 
 | ||||
| #define elapsedSecsThisWeek(_time_) (elapsedSecsToday(_time_) +  ((dayOfWeek(_time_)-1) * SECS_PER_DAY))   // note that week starts on day 1
 | ||||
| #define previousSunday(_time_) ((_time_) - elapsedSecsThisWeek(_time_))      // time at the start of the week for the given time
 | ||||
| #define nextSunday(_time_) (previousSunday(_time_)+SECS_PER_WEEK)          // time at the end of the week for the given time
 | ||||
| #define SECS_PER_YEAR                                                          \ | ||||
|   ((time_t)(SECS_PER_DAY * 365UL))           // TODO: ought to handle leap years
 | ||||
| #define SECS_YR_2000 ((time_t)(946684800UL)) // the time at the start of y2k
 | ||||
| 
 | ||||
| /* Useful Macros for getting elapsed time */ | ||||
| #define numberOfSeconds(_time_) ((_time_) % SECS_PER_MIN) | ||||
| #define numberOfMinutes(_time_) (((_time_) / SECS_PER_MIN) % SECS_PER_MIN) | ||||
| #define numberOfHours(_time_) (((_time_) % SECS_PER_DAY) / SECS_PER_HOUR) | ||||
| #define dayOfWeek(_time_)                                                      \ | ||||
|   ((((_time_) / SECS_PER_DAY + 4) % DAYS_PER_WEEK) + 1) // 1 = Sunday
 | ||||
| #define elapsedDays(_time_)                                                    \ | ||||
|   ((_time_) / SECS_PER_DAY) // this is number of days since Jan 1 1970
 | ||||
| #define elapsedSecsToday(_time_)                                               \ | ||||
|   ((_time_) % SECS_PER_DAY) // the number of seconds since last midnight
 | ||||
| // The following macros are used in calculating alarms and assume the clock is
 | ||||
| // set to a date later than Jan 1 1971 Always set the correct time before
 | ||||
| // settting alarms
 | ||||
| #define previousMidnight(_time_)                                               \ | ||||
|   (((_time_) / SECS_PER_DAY) *                                                 \ | ||||
|    SECS_PER_DAY) // time at the start of the given day
 | ||||
| #define nextMidnight(_time_)                                                   \ | ||||
|   (previousMidnight(_time_) + SECS_PER_DAY) // time at the end of the given day
 | ||||
| #define elapsedSecsThisWeek(_time_)                                            \ | ||||
|   (elapsedSecsToday(_time_) +                                                  \ | ||||
|    ((dayOfWeek(_time_) - 1) * SECS_PER_DAY)) // note that week starts on day 1
 | ||||
| #define previousSunday(_time_)                                                 \ | ||||
|   ((_time_)-elapsedSecsThisWeek(                                               \ | ||||
|       _time_)) // time at the start of the week for the given time
 | ||||
| #define nextSunday(_time_)                                                     \ | ||||
|   (previousSunday(_time_) +                                                    \ | ||||
|    SECS_PER_WEEK) // time at the end of the week for the given time
 | ||||
| 
 | ||||
| /* Useful Macros for converting elapsed time to a time_t */ | ||||
| #define minutesToTime_t ((M)) ( (M) * SECS_PER_MIN)   | ||||
| #define hoursToTime_t   ((H)) ( (H) * SECS_PER_HOUR)   | ||||
| #define daysToTime_t    ((D)) ( (D) * SECS_PER_DAY) // fixed on Jul 22 2011
 | ||||
| #define weeksToTime_t   ((W)) ( (W) * SECS_PER_WEEK)    | ||||
| #define minutesToTime_t ((M))((M)*SECS_PER_MIN) | ||||
| #define hoursToTime_t ((H))((H)*SECS_PER_HOUR) | ||||
| #define daysToTime_t ((D))((D)*SECS_PER_DAY) // fixed on Jul 22 2011
 | ||||
| #define weeksToTime_t ((W))((W)*SECS_PER_WEEK) | ||||
| 
 | ||||
| /*============================================================================*/ | ||||
| /*  time and date functions   */ | ||||
| int     hour();            // the hour now 
 | ||||
| int     hour(time_t t);    // the hour for the given time
 | ||||
| int     hourFormat12();    // the hour now in 12 hour format
 | ||||
| int     hourFormat12(time_t t); // the hour for the given time in 12 hour format
 | ||||
| uint8_t isAM();            // returns true if time now is AM
 | ||||
| uint8_t isAM(time_t t);    // returns true the given time is AM
 | ||||
| uint8_t isPM();            // returns true if time now is PM
 | ||||
| uint8_t isPM(time_t t);    // returns true the given time is PM
 | ||||
| int     minute();          // the minute now 
 | ||||
| int     minute(time_t t);  // the minute for the given time
 | ||||
| int     second();          // the second now 
 | ||||
| int     second(time_t t);  // the second for the given time
 | ||||
| int hour();                 // the hour now
 | ||||
| int hour(time_t t);         // the hour for the given time
 | ||||
| int hourFormat12();         // the hour now in 12 hour format
 | ||||
| int hourFormat12(time_t t); // the hour for the given time in 12 hour format
 | ||||
| uint8_t isAM();             // returns true if time now is AM
 | ||||
| uint8_t isAM(time_t t);     // returns true the given time is AM
 | ||||
| uint8_t isPM();             // returns true if time now is PM
 | ||||
| uint8_t isPM(time_t t);     // returns true the given time is PM
 | ||||
| int minute();               // the minute now
 | ||||
| int minute(time_t t);       // the minute for the given time
 | ||||
| int second();               // the second now
 | ||||
| int second(time_t t);       // the second for the given time
 | ||||
| #ifdef TIMELIB_ENABLE_MILLIS | ||||
| int     millisecond();     // the millisecond now
 | ||||
| int     microsecond(); | ||||
| int millisecond(); // the millisecond now
 | ||||
| int microsecond(); | ||||
| #endif | ||||
| int     day();             // the day now 
 | ||||
| int     day(time_t t);     // the day for the given time
 | ||||
| int     weekday();         // the weekday now (Sunday is day 1) 
 | ||||
| int     weekday(time_t t); // the weekday for the given time 
 | ||||
| int     month();           // the month now  (Jan is month 1)
 | ||||
| int     month(time_t t);   // the month for the given time
 | ||||
| int     year();            // the full four digit year: (2009, 2010 etc) 
 | ||||
| int     year(time_t t);    // the year for the given time
 | ||||
| int day();             // the day now
 | ||||
| int day(time_t t);     // the day for the given time
 | ||||
| int weekday();         // the weekday now (Sunday is day 1)
 | ||||
| int weekday(time_t t); // the weekday for the given time
 | ||||
| int month();           // the month now  (Jan is month 1)
 | ||||
| int month(time_t t);   // the month for the given time
 | ||||
| int year();            // the full four digit year: (2009, 2010 etc)
 | ||||
| int year(time_t t);    // the year for the given time
 | ||||
| 
 | ||||
| time_t  now();              // return the current time as seconds since Jan 1 1970 
 | ||||
| #ifdef  TIMELIB_ENABLE_MILLIS | ||||
| time_t  now(uint32_t& sysTimeMicros); // return the current time as seconds and microseconds since Jan 1 1970
 | ||||
| time_t now(); // return the current time as seconds since Jan 1 1970
 | ||||
| #ifdef TIMELIB_ENABLE_MILLIS | ||||
| time_t now(uint32_t &sysTimeMicros); // return the current time as seconds and
 | ||||
|                                      // microseconds since Jan 1 1970
 | ||||
| 
 | ||||
| #endif | ||||
| #ifdef usePPS | ||||
| void    SyncToPPS(); | ||||
| time_t SyncToPPS(); | ||||
| #endif | ||||
| void    setTime(time_t t); | ||||
| void    setTime(int hr,int min,int sec,int day, int month, int yr); | ||||
| void    adjustTime(long adjustment); | ||||
| void setTime(time_t t); | ||||
| void setTime(int hr, int min, int sec, int day, int month, int yr); | ||||
| void adjustTime(long adjustment); | ||||
| 
 | ||||
| /* date strings */ | ||||
| #define dt_MAX_STRING_LEN                                                      \ | ||||
|   9 // length of longest date string (excluding terminating null)
 | ||||
| char *monthStr(uint8_t month); | ||||
| char *dayStr(uint8_t day); | ||||
| char *monthShortStr(uint8_t month); | ||||
| char *dayShortStr(uint8_t day); | ||||
| 
 | ||||
| /* date strings */  | ||||
| #define dt_MAX_STRING_LEN 9 // length of longest date string (excluding terminating null)
 | ||||
| char* monthStr(uint8_t month); | ||||
| char* dayStr(uint8_t day); | ||||
| char* monthShortStr(uint8_t month); | ||||
| char* dayShortStr(uint8_t day); | ||||
| 	 | ||||
| /* time sync functions	*/ | ||||
| timeStatus_t timeStatus(); // indicates if time has been set and recently synchronized
 | ||||
| void    setSyncProvider( getExternalTime getTimeFunction); // identify the external time provider
 | ||||
| void    setSyncInterval(time_t interval); // set the number of seconds between re-sync
 | ||||
| timeStatus_t | ||||
| timeStatus(); // indicates if time has been set and recently synchronized
 | ||||
| void setSyncProvider( | ||||
|     getExternalTime getTimeFunction); // identify the external time provider
 | ||||
| void setSyncInterval( | ||||
|     time_t interval); // set the number of seconds between re-sync
 | ||||
| 
 | ||||
| /* low level functions to convert to and from system time                     */ | ||||
| void breakTime(time_t time, tmElements_t &tm);  // break time_t into elements
 | ||||
| time_t makeTime(const tmElements_t &tm);  // convert time elements into time_t
 | ||||
| void breakTime(time_t time, tmElements_t &tm); // break time_t into elements
 | ||||
| time_t makeTime(const tmElements_t &tm); // convert time elements into time_t
 | ||||
| 
 | ||||
| } // extern "C++"
 | ||||
| #endif // __cplusplus
 | ||||
| #endif /* _Time_h */ | ||||
| 
 | ||||
|  | ||||
| @ -131,7 +131,7 @@ void refreshtheDisplay() { | ||||
| 
 | ||||
|   uint8_t msgWaiting; | ||||
|   char timeState, buff[16]; | ||||
|   time_t t = myTZ.toLocal(now()); // note: call now() here *before* locking mutex!
 | ||||
|   const time_t t = myTZ.toLocal(now()); // note: call now() here *before* locking mutex!
 | ||||
| 
 | ||||
|   // block i2c bus access
 | ||||
|   if (I2C_MUTEX_LOCK()) { | ||||
|  | ||||
| @ -358,10 +358,13 @@ void setup() { | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
|   // start pps timepulse and timekeepr
 | ||||
|   // start pps timepulse
 | ||||
|   ESP_LOGI(TAG, "Starting Timekeeper..."); | ||||
|   assert(timepulse_init()); // setup timepulse
 | ||||
|   timepulse_start(); | ||||
|   // set time source and sync time
 | ||||
|   setSyncInterval(TIME_SYNC_INTERVAL * 60); | ||||
|   setSyncProvider(&timeProvider); | ||||
| 
 | ||||
|   // start wifi in monitor mode and start channel rotation timer
 | ||||
|   ESP_LOGI(TAG, "Starting Wifi..."); | ||||
| @ -414,10 +417,6 @@ void setup() { | ||||
| #endif | ||||
| #endif // HAS_BUTTON
 | ||||
| 
 | ||||
|   // set time source
 | ||||
|   setSyncInterval(TIME_SYNC_INTERVAL * 60); | ||||
|   setSyncProvider(&timeProvider); | ||||
| 
 | ||||
| #if defined HAS_IF482 || defined HAS_DCF77 | ||||
|   ESP_LOGI(TAG, "Starting Clock Controller..."); | ||||
|   clock_init(); | ||||
|  | ||||
| @ -15,10 +15,8 @@ time_t timeProvider(void) { | ||||
|   time_t t = 0; | ||||
| 
 | ||||
| #ifdef HAS_GPS | ||||
|   // xSemaphoreTake(TimePulse, pdMS_TO_TICKS(1100)); // wait for pps
 | ||||
|   t = get_gpstime(); // fetch recent time from last NEMA record
 | ||||
|   if (t) { | ||||
|     // t++; // last NMEA record concerns past second, so we add one
 | ||||
| #ifdef HAS_RTC | ||||
|     set_rtctime(t); // calibrate RTC
 | ||||
| #endif | ||||
| @ -102,10 +100,10 @@ void timepulse_start(void) { | ||||
| // interrupt service routine triggered by either pps or esp32 hardware timer
 | ||||
| void IRAM_ATTR CLOCKIRQ(void) { | ||||
| 
 | ||||
|   SyncToPPS(); // calibrate systime from Time.h
 | ||||
|   time_t t = SyncToPPS(); // calibrates UTC systime, see Time.h
 | ||||
| 
 | ||||
|   if (ClockTask != NULL) | ||||
|     xTaskNotifyFromISR(ClockTask, uint32_t(now()), eSetBits, NULL); | ||||
|     xTaskNotifyFromISR(ClockTask, uint32_t(t), eSetBits, NULL); | ||||
| 
 | ||||
| #if defined GPS_INT || defined RTC_INT | ||||
|   xSemaphoreGiveFromISR(TimePulse, NULL); | ||||
| @ -167,61 +165,61 @@ void clock_init(void) { | ||||
|   pinMode(HAS_DCF77, OUTPUT); | ||||
| #endif | ||||
| 
 | ||||
|   xTaskCreatePinnedToCore(clock_loop,  // task function
 | ||||
|                           "clockloop", // name of task
 | ||||
|                           2048,        // stack size of task
 | ||||
|                           (void *)1,   // task parameter
 | ||||
|                           4,           // priority of the task
 | ||||
|                           &ClockTask,  // task handle
 | ||||
|                           1);          // CPU core
 | ||||
|   userUTCTime = now(); | ||||
| 
 | ||||
|   xTaskCreatePinnedToCore(clock_loop,           // task function
 | ||||
|                           "clockloop",          // name of task
 | ||||
|                           2048,                 // stack size of task
 | ||||
|                           (void *)&userUTCTime, // start time as task parameter
 | ||||
|                           4,                    // priority of the task
 | ||||
|                           &ClockTask,           // task handle
 | ||||
|                           1);                   // CPU core
 | ||||
| 
 | ||||
|   assert(ClockTask); // has clock task started?
 | ||||
| } // clock_init
 | ||||
| 
 | ||||
| void clock_loop(void *pvParameters) { // ClockTask
 | ||||
| void clock_loop(void *taskparameter) { // ClockTask
 | ||||
| 
 | ||||
|   configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
 | ||||
|   // caveat: don't use now() in this task, it will cause a race condition
 | ||||
|   // due to concurrent access to i2c bus for setting rtc via SyncProvider!
 | ||||
| 
 | ||||
| #define nextsec(t) (t + 1)                // next second
 | ||||
| #define nextmin(t) (t + SECS_PER_MIN + 1) // next minute
 | ||||
| 
 | ||||
|   TickType_t wakeTime; | ||||
|   uint32_t printtime; | ||||
|   time_t t; | ||||
| 
 | ||||
| #define t1(t) (t + DCF77_FRAME_SIZE + 1) // future minute for next DCF77 frame
 | ||||
| #define t2(t) (t + 1) // future second after sync with 1pps trigger
 | ||||
|   time_t t = *((time_t *)taskparameter); // UTC time seconds
 | ||||
| 
 | ||||
|   // preload first DCF frame before start
 | ||||
| #ifdef HAS_DCF77 | ||||
|   uint8_t *DCFpulse; // pointer on array with DCF pulse bits
 | ||||
|   DCFpulse = DCF77_Frame(t1(now())); | ||||
|   DCFpulse = DCF77_Frame(nextmin(t)); | ||||
| #endif | ||||
| 
 | ||||
|   // output time telegram for second following sec beginning with timepulse
 | ||||
|   // output the next second's pulse after timepulse arrived
 | ||||
|   for (;;) { | ||||
|     xTaskNotifyWait(0x00, ULONG_MAX, &printtime, | ||||
|                     portMAX_DELAY); // wait for timepulse
 | ||||
| 
 | ||||
|     // no confident time -> suppress clock output
 | ||||
|     // no confident time -> we suppress clock output
 | ||||
|     if (timeStatus() == timeNotSet) | ||||
|       continue; | ||||
| 
 | ||||
|     t = time_t(printtime); | ||||
|     t = time_t(printtime); // UTC time seconds
 | ||||
| 
 | ||||
| #if defined HAS_IF482 | ||||
| 
 | ||||
|     // IF482_Pulse(t2(t)); // next second
 | ||||
|     IF482_Pulse(t); // next second
 | ||||
|     IF482_Pulse(nextsec(t)); | ||||
| 
 | ||||
| #elif defined HAS_DCF77 | ||||
| 
 | ||||
|     if (second(t) == DCF77_FRAME_SIZE - 1) // is it time to load new frame?
 | ||||
|       DCFpulse = DCF77_Frame(t1(t));       // generate next frame
 | ||||
|       DCFpulse = DCF77_Frame(nextmin(t));  // generate frame for next minute
 | ||||
| 
 | ||||
|     if (DCFpulse[DCF77_FRAME_SIZE] != | ||||
|         minute(t1(t))) // have recent frame? (timepulses could be missed!)
 | ||||
|       continue; | ||||
|     if (minute(nextmin(t)) ==            // do we still have a recent frame?
 | ||||
|         DCFpulse[DCF77_FRAME_SIZE])      // (timepulses could be missed!)
 | ||||
|       DCF77_Pulse(t, DCFpulse); // then output current second's pulse
 | ||||
|     else | ||||
|       // DCF77_Pulse(t2(t), DCFpulse); // then output next second of this frame
 | ||||
|       DCF77_Pulse(t, DCFpulse); // then output next second of this frame
 | ||||
|       continue; // no recent frame -> we suppress clock output
 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user