diff --git a/DateStrings.cpp b/DateStrings.cpp index 3eccff3..2424678 100644 --- a/DateStrings.cpp +++ b/DateStrings.cpp @@ -9,18 +9,18 @@ * */ -#if defined(__AVR__) -#include -#else -// for compatiblity with Arduino Due and Teensy 3.0 and maybe others? +#include + +// Arduino.h should properly define PROGMEM, PGM_P, strcpy_P, pgm_read_byte, pgm_read_ptr +// But not all platforms define these as they should. If you find a platform needing these +// defined, or if any this becomes unnecessary as platforms improve, please send a pull req. +#if defined(ESP8266) +#undef PROGMEM #define PROGMEM -#define PGM_P const char * -#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) -#define pgm_read_word(addr) (*(const unsigned char **)(addr)) -#define strcpy_P(dest, src) strcpy((dest), (src)) #endif -#include // for strcpy_P or strcpy + #include "TimeLib.h" + // the short strings for each day or month must be exactly dt_SHORT_STR_LEN #define dt_SHORT_STR_LEN 3 // the length of short strings @@ -69,7 +69,7 @@ const char dayShortNames_P[] PROGMEM = "ErrSunMonTueWedThuFriSat"; char* monthStr(uint8_t month) { - strcpy_P(buffer, (PGM_P)pgm_read_word(&(monthNames_P[month]))); + strcpy_P(buffer, (PGM_P)pgm_read_ptr(&(monthNames_P[month]))); return buffer; } @@ -83,7 +83,7 @@ char* monthShortStr(uint8_t month) char* dayStr(uint8_t day) { - strcpy_P(buffer, (PGM_P)pgm_read_word(&(dayNames_P[day]))); + strcpy_P(buffer, (PGM_P)pgm_read_ptr(&(dayNames_P[day]))); return buffer; } diff --git a/Readme.md b/Readme.md index 795d26e..ba47aeb 100644 --- a/Readme.md +++ b/Readme.md @@ -2,6 +2,8 @@ Time is a library that provides timekeeping functionality for Arduino. +Using the Arduino Library Manager, install "*Time* by *Michael Margolis*". + The code is derived from the Playground DateTime library but is updated to provide an API that is more flexible and easier to use. @@ -14,6 +16,12 @@ for time synchronization. ## Functionality +To use the Time library in an Arduino sketch, include TimeLib.h. + +```c +#include +``` + The functions available in the library include ```c @@ -66,8 +74,8 @@ timeNeedsSync // the time had been set but a sync attempt did timeSet // the time is set and is synced ``` -Time and Date values are not valid if the status is timeNotSet. Otherwise, values can be used but -the returned time may have drifted if the status is timeNeedsSync. +Time and Date values are not valid if the status is `timeNotSet`. Otherwise, values can be used but +the returned time may have drifted if the status is `timeNeedsSync`. ```c setSyncProvider(getTimeFunction); // set the external time provider @@ -89,15 +97,15 @@ illustrating how the library can be used with various time sources: A companion Processing sketch will automatically provide these messages if it is running and connected to the Arduino serial port. -- `TimeSerialDateStrings.pde` adds day and month name strings to the sketch above - Short (3 character) and long strings are available to print the days of +- `TimeSerialDateStrings.pde` adds day and month name strings to the sketch above. + Short (3 characters) and long strings are available to print the days of the week and names of the months. -- `TimeRTC` uses a DS1307 real time clock to provide time synchronization. - A basic RTC library named DS1307RTC is included in the download. - To run this sketch the DS1307RTC library must be installed. +- `TimeRTC` uses a DS1307 real-time clock to provide time synchronization. + The basic [DS1307RTC library][1] must be downloaded and installed, + in order to run this sketch. -- `TimeRTCSet` is similar to the above and adds the ability to set the Real Time Clock +- `TimeRTCSet` is similar to the above and adds the ability to set the Real Time Clock. - `TimeRTCLog` demonstrates how to calculate the difference between times. It is a very simple logger application that monitors events on digital pins @@ -106,11 +114,11 @@ illustrating how the library can be used with various time sources: - `TimeNTP` uses the Arduino Ethernet shield to access time using the internet NTP time service. The NTP protocol uses UDP and the UdpBytewise library is required, see: - http://bitbucket.org/bjoern/arduino_osc/src/14667490521f/libraries/Ethernet/ + -- `TimeGPS` gets time from a GPS +- `TimeGPS` gets time from a GPS. This requires the TinyGPS library from Mikal Hart: - http://arduiniana.org/libraries/TinyGPS + ## Differences @@ -126,7 +134,7 @@ Changes in the Time library API: - function added to automatically sync time with external source - `localTime` and `maketime` parameters changed, `localTime` renamed to `breakTime` -## Technical notes: +## Technical Notes Internal system time is based on the standard Unix `time_t`. The value is the number of seconds since Jan 1, 1970. @@ -140,16 +148,18 @@ See the sketches in the examples directory for usage. The default interval for re-syncing the time is 5 minutes but can be changed by calling the `setSyncInterval(interval)` method to set the number of seconds between re-sync attempts. -The Time library defines a structure for holding time elements that is a compact version of the C tm structure. -All the members of the Arduino tm structure are bytes and the year is offset from 1970. +The Time library defines a structure for holding time elements that is a compact version of the C `tm` structure. +All the members of the Arduino `tm` structure are bytes and the year is offset from 1970. Convenience macros provide conversion to and from the Arduino format. -Low level functions to convert between system time and individual time elements are provided: +Low-level functions to convert between system time and individual time elements are provided: ```c breakTime(time, &tm); // break time_t into elements stored in tm struct -makeTime(&tm); // return time_t from elements stored in tm struct +makeTime(&tm); // return time_t from elements stored in tm struct ``` -The DS1307RTC library included in the download provides an example of how a time provider +This [DS1307RTC library][1] provides an example of how a time provider can use the low-level functions to interface with the Time library. + +[1]: diff --git a/TimeLib.h b/TimeLib.h index 20e2445..39b092f 100644 --- a/TimeLib.h +++ b/TimeLib.h @@ -21,6 +21,8 @@ typedef unsigned long time_t; #endif +#define usePPS +#define TIMELIB_ENABLE_MILLIS // This ugly hack allows us to define C++ overloaded functions, when included // from within an extern "C", as newlib's sys/stat.h does. Actually it is @@ -80,7 +82,7 @@ typedef time_t(*getExternalTime)(); #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 +// Always set the correct time before setting 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 @@ -118,6 +120,14 @@ 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 +#endif +#ifdef usePPS +void IRAM_ATTR 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); diff --git a/docs/issue_template.md b/docs/issue_template.md new file mode 100644 index 0000000..0610992 --- /dev/null +++ b/docs/issue_template.md @@ -0,0 +1,64 @@ +Please use this form only to report code defects or bugs. + +For any question, even questions directly pertaining to this code, post your question on the forums related to the board you are using. + +Arduino: forum.arduino.cc +Teensy: forum.pjrc.com +ESP8266: www.esp8266.com +ESP32: www.esp32.com +Adafruit Feather/Metro/Trinket: forums.adafruit.com +Particle Photon: community.particle.io + +If you are experiencing trouble but not certain of the cause, or need help using this code, ask on the appropriate forum. This is not the place to ask for support or help, even directly related to this code. Only use this form you are certain you have discovered a defect in this code! + +Please verify the problem occurs when using the very latest version, using the newest version of Arduino and any other related software. + + +----------------------------- Remove above ----------------------------- + + + +### Description + +Describe your problem. + + + +### Steps To Reproduce Problem + +Please give detailed instructions needed for anyone to attempt to reproduce the problem. + + + +### Hardware & Software + +Board +Shields / modules used +Arduino IDE version +Teensyduino version (if using Teensy) +Version info & package name (from Tools > Boards > Board Manager) +Operating system & version +Any other software or hardware? + + +### Arduino Sketch + +```cpp +// Change the code below by your sketch (please try to give the smallest code which demonstrates the problem) +#include + +// libraries: give links/details so anyone can compile your code for the same result + +void setup() { +} + +void loop() { +} +``` + + +### Errors or Incorrect Output + +If you see any errors or incorrect output, please show it here. Please use copy & paste to give an exact copy of the message. Details matter, so please show (not merely describe) the actual message or error exactly as it appears. + + diff --git a/examples/Processing/SyncArduinoClock/SyncArduinoClock.pde b/examples/Processing/SyncArduinoClock/SyncArduinoClock.pde index 4313be3..62ee57b 100644 --- a/examples/Processing/SyncArduinoClock/SyncArduinoClock.pde +++ b/examples/Processing/SyncArduinoClock/SyncArduinoClock.pde @@ -1,8 +1,17 @@ /** * SyncArduinoClock. * + * SyncArduinoClock is a Processing sketch that responds to Arduino + * requests for time synchronization messages. Run this in the + * Processing environment (not in Arduino) on your PC or Mac. + * + * Download TimeSerial onto Arduino and you should see the time + * message displayed when you run SyncArduinoClock in Processing. + * The Arduino time is set from the time on your computer through the + * Processing sketch. + * * portIndex must be set to the port connected to the Arduino - * + * * The current time is sent in response to request message from Arduino * or by clicking the display window * diff --git a/library.json b/library.json index 6603650..014ec33 100644 --- a/library.json +++ b/library.json @@ -1,5 +1,5 @@ { - "name": "Time", + "name": "microTime", "description": "Time keeping library", "keywords": "Time, date, hour, minute, second, day, week, month, year, RTC", "authors": [ @@ -7,17 +7,15 @@ "name": "Michael Margolis" }, { - "name": "Paul Stoffregen", - "email": "paul@pjrc.com", - "url": "http://www.pjrc.com", + "name": "cyberman54", "maintainer": true } ], "repository": { "type": "git", - "url": "https://github.com/PaulStoffregen/Time" + "url": "https://github.com/cyberman54/microTime" }, - "version": "1.5", + "version": "1.6", "homepage": "http://playground.arduino.cc/Code/Time", "frameworks": "Arduino", "examples": [ diff --git a/library.properties b/library.properties index 49b1e2a..5807c98 100644 --- a/library.properties +++ b/library.properties @@ -1,10 +1,11 @@ -name=Time -version=1.5 +name=microTime +version=1.6 author=Michael Margolis -maintainer=Paul Stoffregen +maintainer=cyberman54 sentence=Timekeeping functionality for Arduino paragraph=Date and Time functions, with provisions to synchronize to external time sources like GPS and NTP (Internet). This library is often used together with TimeAlarms and DS1307RTC. category=Timing -url=http://playground.arduino.cc/code/time +url=http://playground.arduino.cc/Code/Time/ +includes=TimeLib.h architectures=* diff --git a/Time.cpp b/microTime.cpp similarity index 89% rename from Time.cpp rename to microTime.cpp index 8e53e56..c240d5f 100644 --- a/Time.cpp +++ b/microTime.cpp @@ -33,6 +33,9 @@ #include #endif +#define TIMELIB_ENABLE_MILLIS +#define usePPS + #include "TimeLib.h" static tmElements_t tm; // a cache of time elements @@ -141,9 +144,9 @@ int year(time_t t) { // the year for the given time /*============================================================================*/ /* 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 services and are not normally needed in a sketch */ -// leap year calulator expects year argument as years offset from 1970 +// leap year calculator expects year argument as years offset from 1970 #define LEAP_YEAR(Y) ( ((1970+(Y))>0) && !((1970+(Y))%4) && ( ((1970+(Y))%100) || !((1970+(Y))%400) ) ) 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 @@ -213,7 +216,7 @@ time_t makeTime(const tmElements_t &tm){ seconds= tm.Year*(SECS_PER_DAY * 365); 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 } } @@ -235,7 +238,7 @@ time_t makeTime(const tmElements_t &tm){ /* Low level system time functions */ static uint32_t sysTime = 0; -static uint32_t prevMillis = 0; +static uint32_t prevMicros = 0; static uint32_t nextSyncTime = 0; static timeStatus_t Status = timeNotSet; @@ -246,18 +249,30 @@ getExternalTime getTimePtr; // pointer to external sync function time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync #endif +#ifdef usePPS +void IRAM_ATTR SyncToPPS() { + sysTime++; + prevMicros = micros(); +} +#endif time_t now() { - // calculate number of seconds passed since last call to now() - while (millis() - prevMillis >= 1000) { - // millis() and prevMillis are both unsigned ints thus the subtraction will always be the absolute value of the difference - sysTime++; - prevMillis += 1000; + uint32_t sysTimeMicros; + return now(sysTimeMicros); +} + +time_t now(uint32_t& sysTimeMicros) { + // calculate number of seconds passed since last call to now() + uint32_t n_secs = (micros() - prevMicros) / 1000000U; + sysTime += n_secs; + prevMicros += n_secs * 1000000U; + #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 (sysTime - nextSyncTime < 2147483648U) { if (getTimePtr != 0) { time_t t = getTimePtr(); if (t != 0) { @@ -280,7 +295,9 @@ void setTime(time_t t) { sysTime = (uint32_t)t; nextSyncTime = (uint32_t)t + syncInterval; Status = timeSet; - prevMillis = millis(); // restart counting from now (thanks to Korman for this fix) + #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){ diff --git a/Time.h b/microTime.h similarity index 100% rename from Time.h rename to microTime.h