]>
Commit | Line | Data |
---|---|---|
e63b2f75 L |
1 | /* |
2 | * (C)2012 Michael Duane Rice All rights reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions are | |
6 | * met: | |
7 | * | |
8 | * Redistributions of source code must retain the above copyright notice, this | |
9 | * list of conditions and the following disclaimer. Redistributions in binary | |
10 | * form must reproduce the above copyright notice, this list of conditions | |
11 | * and the following disclaimer in the documentation and/or other materials | |
12 | * provided with the distribution. Neither the name of the copyright holders | |
13 | * nor the names of contributors may be used to endorse or promote products | |
14 | * derived from this software without specific prior written permission. | |
15 | * | |
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
26 | * POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | |
28 | ||
29 | /* $Id: time.h 2427 2014-05-01 14:06:03Z amylaar $ */ | |
30 | ||
31 | /** \file */ | |
32 | ||
33 | /** \defgroup avr_time <time.h>: Time | |
34 | \code #include <time.h> \endcode | |
35 | <h3>Introduction to the Time functions</h3> | |
36 | This file declares the time functions implemented in \c avr-libc. | |
37 | ||
38 | The implementation aspires to conform with ISO/IEC 9899 (C90). However, due to limitations of the | |
39 | target processor and the nature of its development environment, a practical implementation must | |
40 | of necessity deviate from the standard. | |
41 | ||
42 | ||
43 | ||
44 | Section 7.23.2.1 clock() | |
45 | The type clock_t, the macro CLOCKS_PER_SEC, and the function clock() are not implemented. We | |
46 | consider these items belong to operating system code, or to application code when no operating | |
47 | system is present. | |
48 | ||
49 | Section 7.23.2.3 mktime() | |
50 | The standard specifies that mktime() should return (time_t) -1, if the time cannot be represented. | |
51 | This implementation always returns a 'best effort' representation. | |
52 | ||
53 | Section 7.23.2.4 time() | |
54 | The standard specifies that time() should return (time_t) -1, if the time is not available. | |
55 | Since the application must initialize the time system, this functionality is not implemented. | |
56 | ||
57 | Section 7.23.2.2, difftime() | |
58 | Due to the lack of a 64 bit double, the function difftime() returns a long integer. In most cases | |
59 | this change will be invisible to the user, handled automatically by the compiler. | |
60 | ||
61 | Section 7.23.1.4 struct tm | |
62 | Per the standard, struct tm->tm_isdst is greater than zero when Daylight Saving time is in effect. | |
63 | This implementation further specifies that, when positive, the value of tm_isdst represents | |
64 | the amount time is advanced during Daylight Saving time. | |
65 | ||
66 | Section 7.23.3.5 strftime() | |
67 | Only the 'C' locale is supported, therefore the modifiers 'E' and 'O' are ignored. | |
68 | The 'Z' conversion is also ignored, due to the lack of time zone name. | |
69 | ||
70 | In addition to the above departures from the standard, there are some behaviors which are different | |
71 | from what is often expected, though allowed under the standard. | |
72 | ||
73 | There is no 'platform standard' method to obtain the current time, time zone, or | |
74 | daylight savings 'rules' in the AVR environment. Therefore the application must initialize | |
75 | the time system with this information. The functions set_zone(), set_dst(), and | |
76 | set_system_time() are provided for initialization. Once initialized, system time is maintained by | |
77 | calling the function system_tick() at one second intervals. | |
78 | ||
79 | Though not specified in the standard, it is often expected that time_t is a signed integer | |
80 | representing an offset in seconds from Midnight Jan 1 1970... i.e. 'Unix time'. This implementation | |
81 | uses an unsigned 32 bit integer offset from Midnight Jan 1 2000. The use of this 'epoch' helps to | |
82 | simplify the conversion functions, while the 32 bit value allows time to be properly represented | |
83 | until Tue Feb 7 06:28:15 2136 UTC. The macros UNIX_OFFSET and NTP_OFFSET are defined to assist in | |
84 | converting to and from Unix and NTP time stamps. | |
85 | ||
86 | Unlike desktop counterparts, it is impractical to implement or maintain the 'zoneinfo' database. | |
87 | Therefore no attempt is made to account for time zone, daylight saving, or leap seconds in past dates. | |
88 | All calculations are made according to the currently configured time zone and daylight saving 'rule'. | |
89 | ||
90 | In addition to C standard functions, re-entrant versions of ctime(), asctime(), gmtime() and | |
91 | localtime() are provided which, in addition to being re-entrant, have the property of claiming | |
92 | less permanent storage in RAM. An additional time conversion, isotime() and its re-entrant version, | |
93 | uses far less storage than either ctime() or asctime(). | |
94 | ||
95 | Along with the usual smattering of utility functions, such as is_leap_year(), this library includes | |
96 | a set of functions related the sun and moon, as well as sidereal time functions. | |
97 | */ | |
98 | ||
99 | #ifndef TIME_H | |
100 | #define TIME_H | |
101 | ||
102 | #ifdef __cplusplus | |
103 | extern "C" { | |
104 | #endif | |
105 | ||
106 | #include <inttypes.h> | |
107 | #include <stdlib.h> | |
108 | ||
109 | /** \ingroup avr_time */ | |
110 | /* @{ */ | |
111 | ||
112 | /** | |
113 | time_t represents seconds elapsed from Midnight, Jan 1 2000 UTC (the Y2K 'epoch'). | |
114 | Its range allows this implementation to represent time up to Tue Feb 7 06:28:15 2136 UTC. | |
115 | */ | |
116 | typedef uint32_t time_t; | |
117 | ||
118 | /** | |
119 | The time function returns the systems current time stamp. | |
120 | If timer is not a null pointer, the return value is also assigned to the object it points to. | |
121 | */ | |
122 | time_t time(time_t *timer); | |
123 | ||
124 | /** | |
125 | The difftime function returns the difference between two binary time stamps, | |
126 | time1 - time0. | |
127 | */ | |
128 | int32_t difftime(time_t time1, time_t time0); | |
129 | ||
130 | ||
131 | /** | |
132 | The tm structure contains a representation of time 'broken down' into components of the | |
133 | Gregorian calendar. | |
134 | ||
135 | The normal ranges of the elements are.. | |
136 | ||
137 | \code | |
138 | tm_sec seconds after the minute - [ 0 to 59 ] | |
139 | tm_min minutes after the hour - [ 0 to 59 ] | |
140 | tm_hour hours since midnight - [ 0 to 23 ] | |
141 | tm_mday day of the month - [ 1 to 31 ] | |
142 | tm_wday days since Sunday - [ 0 to 6 ] | |
143 | tm_mon months since January - [ 0 to 11 ] | |
144 | tm_year years since 1900 | |
145 | tm_yday days since January 1 - [ 0 to 365 ] | |
146 | tm_isdst Daylight Saving Time flag * | |
147 | ||
148 | \endcode | |
149 | ||
150 | *The value of tm_isdst is zero if Daylight Saving Time is not in effect, and is negative if | |
151 | the information is not available. | |
152 | ||
153 | When Daylight Saving Time is in effect, the value represents the number of | |
154 | seconds the clock is advanced. | |
155 | ||
156 | See the set_dst() function for more information about Daylight Saving. | |
157 | ||
158 | */ | |
159 | struct tm { | |
160 | int8_t tm_sec; | |
161 | int8_t tm_min; | |
162 | int8_t tm_hour; | |
163 | int8_t tm_mday; | |
164 | int8_t tm_wday; | |
165 | int8_t tm_mon; | |
166 | int16_t tm_year; | |
167 | int16_t tm_yday; | |
168 | int16_t tm_isdst; | |
169 | }; | |
170 | ||
171 | ||
172 | /* We have to provide clock_t / CLOCKS_PER_SEC so that libstdc++-v3 can | |
173 | be built. We define CLOCKS_PER_SEC via a symbol _CLOCKS_PER_SEC_ | |
174 | so that the user can provide the value on the link line, which should | |
175 | result in little or no run-time overhead compared with a constant. */ | |
176 | typedef unsigned long clock_t; | |
177 | extern char *_CLOCKS_PER_SEC_; | |
178 | #define CLOCKS_PER_SEC ((clock_t) _CLOCKS_PER_SEC_) | |
179 | extern clock_t clock(void); | |
180 | ||
181 | /** | |
182 | This function 'compiles' the elements of a broken-down time structure, returning a binary time stamp. | |
183 | The elements of timeptr are interpreted as representing Local Time. | |
184 | ||
185 | The original values of the tm_wday and tm_yday elements of the structure are ignored, | |
186 | and the original values of the other elements are not restricted to the ranges stated for struct tm. | |
187 | ||
188 | On successful completion, the values of all elements of timeptr are set to the appropriate range. | |
189 | */ | |
190 | time_t mktime(struct tm * timeptr); | |
191 | ||
192 | /** | |
193 | This function 'compiles' the elements of a broken-down time structure, returning a binary time stamp. | |
194 | The elements of timeptr are interpreted as representing UTC. | |
195 | ||
196 | The original values of the tm_wday and tm_yday elements of the structure are ignored, | |
197 | and the original values of the other elements are not restricted to the ranges stated for struct tm. | |
198 | ||
199 | Unlike mktime(), this function DOES NOT modify the elements of timeptr. | |
200 | */ | |
201 | time_t mk_gmtime(const struct tm * timeptr); | |
202 | ||
203 | /** | |
204 | The gmtime function converts the time stamp pointed to by timer into broken-down time, | |
205 | expressed as UTC. | |
206 | */ | |
207 | struct tm *gmtime(const time_t * timer); | |
208 | ||
209 | /** | |
210 | Re entrant version of gmtime(). | |
211 | */ | |
212 | void gmtime_r(const time_t * timer, struct tm * timeptr); | |
213 | ||
214 | /** | |
215 | The localtime function converts the time stamp pointed to by timer into broken-down time, | |
216 | expressed as Local time. | |
217 | */ | |
218 | struct tm *localtime(const time_t * timer); | |
219 | ||
220 | /** | |
221 | Re entrant version of localtime(). | |
222 | */ | |
223 | void localtime_r(const time_t * timer, struct tm * timeptr); | |
224 | ||
225 | /** | |
226 | The asctime function converts the broken-down time of timeptr, into an ascii string in the form | |
227 | ||
228 | Sun Mar 23 01:03:52 2013 | |
229 | */ | |
230 | char *asctime(const struct tm * timeptr); | |
231 | ||
232 | /** | |
233 | Re entrant version of asctime(). | |
234 | */ | |
235 | void asctime_r(const struct tm * timeptr, char *buf); | |
236 | ||
237 | /** | |
238 | The ctime function is equivalent to asctime(localtime(timer)) | |
239 | */ | |
240 | char *ctime(const time_t * timer); | |
241 | ||
242 | /** | |
243 | Re entrant version of ctime(). | |
244 | */ | |
245 | void ctime_r(const time_t * timer, char *buf); | |
246 | ||
247 | /** | |
248 | The isotime function constructs an ascii string in the form | |
249 | \code2013-03-23 01:03:52\endcode | |
250 | */ | |
251 | char *isotime(const struct tm * tmptr); | |
252 | ||
253 | /** | |
254 | Re entrant version of isotime() | |
255 | */ | |
256 | void isotime_r(const struct tm *, char *); | |
257 | ||
258 | /** | |
259 | A complete description of strftime() is beyond the pale of this document. | |
260 | Refer to ISO/IEC document 9899 for details. | |
261 | ||
262 | All conversions are made using the 'C Locale', ignoring the E or O modifiers. Due to the lack of | |
263 | a time zone 'name', the 'Z' conversion is also ignored. | |
264 | */ | |
265 | size_t strftime(char *s, size_t maxsize, const char *format, const struct tm * timeptr); | |
266 | ||
267 | /** | |
268 | Specify the Daylight Saving function. | |
269 | ||
270 | The Daylight Saving function should examine its parameters to determine whether | |
271 | Daylight Saving is in effect, and return a value appropriate for tm_isdst. | |
272 | ||
273 | Working examples for the USA and the EU are available.. | |
274 | ||
275 | \code #include <util/eu_dst.h>\endcode | |
276 | for the European Union, and | |
277 | \code #include <util/usa_dst.h>\endcode | |
278 | for the United States | |
279 | ||
280 | If a Daylight Saving function is not specified, the system will ignore Daylight Saving. | |
281 | */ | |
282 | void set_dst(int (*) (const time_t *, int32_t *)); | |
283 | ||
284 | /** | |
285 | Set the 'time zone'. The parameter is given in seconds East of the Prime Meridian. | |
286 | Example for New York City: | |
287 | \code set_zone(-5 * ONE_HOUR);\endcode | |
288 | ||
289 | If the time zone is not set, the time system will operate in UTC only. | |
290 | */ | |
291 | void set_zone(int32_t); | |
292 | ||
293 | /** | |
294 | Initialize the system time. Examples are... | |
295 | ||
296 | From a Clock / Calendar type RTC: | |
297 | \code | |
298 | struct tm rtc_time; | |
299 | ||
300 | read_rtc(&rtc_time); | |
301 | rtc_time.tm_isdst = 0; | |
302 | set_system_time( mktime(&rtc_time) ); | |
303 | \endcode | |
304 | ||
305 | From a Network Time Protocol time stamp: | |
306 | \code | |
307 | set_system_time(ntp_timestamp - NTP_OFFSET); | |
308 | \endcode | |
309 | ||
310 | From a UNIX time stamp: | |
311 | \code | |
312 | set_system_time(unix_timestamp - UNIX_OFFSET); | |
313 | \endcode | |
314 | ||
315 | */ | |
316 | void set_system_time(time_t timestamp); | |
317 | ||
318 | /** | |
319 | Maintain the system time by calling this function at a rate of 1 Hertz. | |
320 | ||
321 | It is anticipated that this function will typically be called from within an | |
322 | Interrupt Service Routine, (though that is not required). It therefore includes code which | |
323 | makes it simple to use from within a 'Naked' ISR, avoiding the cost of saving and restoring | |
324 | all the cpu registers. | |
325 | ||
326 | Such an ISR may resemble the following example... | |
327 | \code | |
328 | ISR(RTC_OVF_vect, ISR_NAKED) | |
329 | { | |
330 | system_tick(); | |
331 | reti(); | |
332 | } | |
333 | \endcode | |
334 | */ | |
335 | void system_tick(void); | |
336 | ||
337 | /** | |
338 | Enumerated labels for the days of the week. | |
339 | */ | |
340 | enum _WEEK_DAYS_ { | |
341 | SUNDAY, | |
342 | MONDAY, | |
343 | TUESDAY, | |
344 | WEDNESDAY, | |
345 | THURSDAY, | |
346 | FRIDAY, | |
347 | SATURDAY | |
348 | }; | |
349 | ||
350 | /** | |
351 | Enumerated labels for the months. | |
352 | */ | |
353 | enum _MONTHS_ { | |
354 | JANUARY, | |
355 | FEBRUARY, | |
356 | MARCH, | |
357 | APRIL, | |
358 | MAY, | |
359 | JUNE, | |
360 | JULY, | |
361 | AUGUST, | |
362 | SEPTEMBER, | |
363 | OCTOBER, | |
364 | NOVEMBER, | |
365 | DECEMBER | |
366 | }; | |
367 | ||
368 | /** | |
369 | Return 1 if year is a leap year, zero if it is not. | |
370 | */ | |
371 | uint8_t is_leap_year(int16_t year); | |
372 | ||
373 | /** | |
374 | Return the length of month, given the year and month, where month is in the range 1 to 12. | |
375 | */ | |
376 | uint8_t month_length(int16_t year, uint8_t month); | |
377 | ||
378 | /** | |
379 | Return the calendar week of year, where week 1 is considered to begin on the | |
380 | day of week specified by 'start'. The returned value may range from zero to 52. | |
381 | */ | |
382 | uint8_t week_of_year(const struct tm * timeptr, uint8_t start); | |
383 | ||
384 | /** | |
385 | Return the calendar week of month, where the first week is considered to begin on the | |
386 | day of week specified by 'start'. The returned value may range from zero to 5. | |
387 | */ | |
388 | uint8_t week_of_month(const struct tm * timeptr, uint8_t start); | |
389 | ||
390 | /** | |
391 | Structure which represents a date as a year, week number of that year, and day of week. | |
392 | See http://en.wikipedia.org/wiki/ISO_week_date for more information. | |
393 | */ | |
394 | struct week_date{ | |
395 | int year; | |
396 | int week; | |
397 | int day; | |
398 | }; | |
399 | ||
400 | /** | |
401 | Return a week_date structure with the ISO_8601 week based date corresponding to the given | |
402 | year and day of year. See http://en.wikipedia.org/wiki/ISO_week_date for more | |
403 | information. | |
404 | */ | |
405 | struct week_date * iso_week_date( int year, int yday); | |
406 | ||
407 | /** | |
408 | Re-entrant version of iso-week_date. | |
409 | */ | |
410 | void iso_week_date_r( int year, int yday, struct week_date *); | |
411 | ||
412 | /** | |
413 | Convert a Y2K time stamp into a FAT file system time stamp. | |
414 | */ | |
415 | uint32_t fatfs_time(const struct tm * timeptr); | |
416 | ||
417 | /** One hour, expressed in seconds */ | |
418 | #define ONE_HOUR 3600 | |
419 | ||
420 | /** Angular degree, expressed in arc seconds */ | |
421 | #define ONE_DEGREE 3600 | |
422 | ||
423 | /** One day, expressed in seconds */ | |
424 | #define ONE_DAY 86400 | |
425 | ||
426 | /** Difference between the Y2K and the UNIX epochs, in seconds. To convert a Y2K | |
427 | timestamp to UNIX... | |
428 | \code | |
429 | long unix; | |
430 | time_t y2k; | |
431 | ||
432 | y2k = time(NULL); | |
433 | unix = y2k + UNIX_OFFSET; | |
434 | \endcode | |
435 | */ | |
436 | #define UNIX_OFFSET 946684800 | |
437 | ||
438 | /** Difference between the Y2K and the NTP epochs, in seconds. To convert a Y2K | |
439 | timestamp to NTP... | |
440 | \code | |
441 | unsigned long ntp; | |
442 | time_t y2k; | |
443 | ||
444 | y2k = time(NULL); | |
445 | ntp = y2k + NTP_OFFSET; | |
446 | \endcode | |
447 | */ | |
448 | #define NTP_OFFSET 3155673600 | |
449 | ||
450 | /* | |
451 | * =================================================================== | |
452 | * Ephemera | |
453 | */ | |
454 | ||
455 | /** | |
456 | Set the geographic coordinates of the 'observer', for use with several of the | |
457 | following functions. Parameters are passed as seconds of North Latitude, and seconds | |
458 | of East Longitude. | |
459 | ||
460 | For New York City... | |
461 | \code set_position( 40.7142 * ONE_DEGREE, -74.0064 * ONE_DEGREE); \endcode | |
462 | */ | |
463 | void set_position(int32_t latitude, int32_t longitude); | |
464 | ||
465 | /** | |
466 | Computes the difference between apparent solar time and mean solar time. | |
467 | The returned value is in seconds. | |
468 | */ | |
469 | int16_t equation_of_time(const time_t * timer); | |
470 | ||
471 | /** | |
472 | Computes the amount of time the sun is above the horizon, at the location of the observer. | |
473 | ||
474 | NOTE: At observer locations inside a polar circle, this value can be zero during the winter, | |
475 | and can exceed ONE_DAY during the summer. | |
476 | ||
477 | The returned value is in seconds. | |
478 | */ | |
479 | int32_t daylight_seconds(const time_t * timer); | |
480 | ||
481 | /** | |
482 | Computes the time of solar noon, at the location of the observer. | |
483 | */ | |
484 | time_t solar_noon(const time_t * timer); | |
485 | ||
486 | /** | |
487 | Return the time of sunrise, at the location of the observer. See the note about daylight_seconds(). | |
488 | */ | |
489 | time_t sun_rise(const time_t * timer); | |
490 | ||
491 | /** | |
492 | Return the time of sunset, at the location of the observer. See the note about daylight_seconds(). | |
493 | */ | |
494 | time_t sun_set(const time_t * timer); | |
495 | ||
496 | /** Returns the declination of the sun in radians. */ | |
497 | double solar_declination(const time_t * timer); | |
498 | ||
499 | /** | |
500 | Returns an approximation to the phase of the moon. | |
501 | The sign of the returned value indicates a waning or waxing phase. | |
502 | The magnitude of the returned value indicates the percentage illumination. | |
503 | */ | |
504 | int8_t moon_phase(const time_t * timer); | |
505 | ||
506 | /** | |
507 | Returns Greenwich Mean Sidereal Time, as seconds into the sidereal day. | |
508 | The returned value will range from 0 through 86399 seconds. | |
509 | */ | |
510 | unsigned long gm_sidereal(const time_t * timer); | |
511 | ||
512 | /** | |
513 | Returns Local Mean Sidereal Time, as seconds into the sidereal day. | |
514 | The returned value will range from 0 through 86399 seconds. | |
515 | */ | |
516 | unsigned long lm_sidereal(const time_t * timer); | |
517 | ||
518 | /* @} */ | |
519 | #ifdef __cplusplus | |
520 | } | |
521 | #endif | |
522 | ||
523 | #endif /* TIME_H */ |