1/*
2 * ntp_calgps.h - calendar for GPS/GNSS based clocks
3 *
4 * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
5 * The contents of 'html/copyright.html' apply.
6 *
7 * --------------------------------------------------------------------
8 *
9 * This module implements stuff often used with GPS/GNSS receivers
10 */
11#ifndef NTP_CALGPS_H
12#define NTP_CALGPS_H
13
14#include <time.h>
15
16#include "ntp_types.h"
17#include "ntp_fp.h"
18#include "ntp_calendar.h"
19
20/* GPS week calendar (extended weeks)
21 * We use weeks based on 1899-31-12, which was the last Sunday before
22 * the begin of the NTP epoch. (Which is equivalent to saying 1900-01-01
23 * was a Monday...)
24 *
25 * We simply pre-calculate the offsets and cycle shifts for the real GPS
26 * calendar, which starts at 1980-01-06, to simplyfy some expressions.
27 *
28 * This has a fringe benefit that should not be overlooked: Since week zero
29 * is around 1900, and we should never have to deal with dates before
30 * 1970 or 1980, a week number of zero can be easily used to indicate
31 * an invalid week time stamp.
32 */
33#define GPSNTP_WSHIFT	4175	/* weeks 1899-31-12 --> 1980-01-06 */
34#define GPSNTP_WCYCLE	  79	/* above, modulo 1024 */
35#define GPSNTP_DSHIFT	   1	/* day number of 1900-01-01 in week */
36
37struct gpsdatum {
38	uint32_t weeks;		/* weeks since GPS epoch	*/
39	int32_t  wsecs;		/* seconds since week start	*/
40	uint32_t frac;		/* fractional seconds		*/
41};
42typedef struct gpsdatum TGpsDatum;
43typedef struct gpsdatum const TcGpsDatum;
44
45/* NTP date/time in split representation */
46struct ntpdatum {
47	uint32_t days;		/* since NTP epoch		*/
48	int32_t  secs;		/* since midnight, denorm is ok */
49	uint32_t frac;		/* fractional seconds		*/
50};
51typedef struct ntpdatum TNtpDatum;
52typedef struct ntpdatum const TcNtpDatum;
53
54/*
55 * GPS week/sec calendar functions
56 *
57 * see the implementation for details, especially the
58 * 'gpscal_from_weektime{1,2}()'
59 */
60
61extern TGpsDatum
62gpscal_fix_gps_era(TcGpsDatum *);
63
64extern void
65gpscal_add_offset(TGpsDatum *datum, l_fp offset);
66
67extern TGpsDatum
68gpscal_from_calendar_ex(TcCivilDate*, l_fp fofs, int/*BOOL*/ warp);
69
70static inline TGpsDatum
71gpscal_from_calendar(TcCivilDate *pCiv, l_fp fofs) {
72    return gpscal_from_calendar_ex(pCiv, fofs, TRUE);
73}
74
75extern TGpsDatum 	/* see source for semantic of the 'fofs' value! */
76gpscal_from_gpsweek(uint16_t w, int32_t s, l_fp fofs);
77
78extern TGpsDatum
79gpscal_from_weektime1(int32_t wsecs, l_fp fofs, l_fp pivot);
80
81extern TGpsDatum
82gpscal_from_weektime2(int32_t wsecs, l_fp fofs,	TcGpsDatum *pivot);
83
84extern void
85gpscal_to_calendar(TCivilDate*, TcGpsDatum*);
86
87extern TGpsDatum
88gpscal_from_gpsntp(TcNtpDatum*);
89
90extern l_fp
91ntpfp_from_gpsdatum(TcGpsDatum *);
92
93/*
94 * NTP day/sec calendar functions
95 *
96 * see the implementation for details, especially the
97 * 'gpscal_from_daytime{1,2}()'
98 */
99extern TNtpDatum
100gpsntp_fix_gps_era(TcNtpDatum *);
101
102extern void
103gpsntp_add_offset(TNtpDatum *datum, l_fp offset);
104
105extern TNtpDatum
106gpsntp_from_calendar_ex(TcCivilDate*, l_fp fofs, int/*BOOL*/ warp);
107
108static inline TNtpDatum
109gpsntp_from_calendar(TcCivilDate * pCiv, l_fp fofs) {
110	return gpsntp_from_calendar_ex(pCiv, fofs, TRUE);
111}
112
113extern TNtpDatum
114gpsntp_from_daytime1_ex(TcCivilDate *dt, l_fp fofs, l_fp pivot, int/*BOOL*/ warp);
115
116static inline TNtpDatum
117gpsntp_from_daytime1(TcCivilDate *dt, l_fp fofs, l_fp pivot) {
118	return gpsntp_from_daytime1_ex(dt, fofs, pivot, TRUE);
119}
120
121extern TNtpDatum
122gpsntp_from_daytime2_ex(TcCivilDate *dt, l_fp fofs, TcNtpDatum *pivot, int/*BOOL*/ warp);
123
124static inline TNtpDatum
125gpsntp_from_daytime2(TcCivilDate *dt, l_fp fofs, TcNtpDatum *pivot) {
126	return gpsntp_from_daytime2_ex(dt, fofs, pivot, TRUE);
127}
128
129extern TNtpDatum
130gpsntp_from_gpscal_ex(TcGpsDatum*, int/*BOOL*/ warp);
131
132static inline TNtpDatum
133gpsntp_from_gpscal(TcGpsDatum *wd) {
134	return gpsntp_from_gpscal_ex(wd, FALSE);
135}
136
137extern void
138gpsntp_to_calendar(TCivilDate*, TcNtpDatum*);
139
140extern l_fp
141ntpfp_from_ntpdatum(TcNtpDatum*);
142
143/*
144 * Some helpers
145 */
146
147/* apply fudge to time stamp: *SUBTRACT* the given offset from an l_fp*/
148extern l_fp
149ntpfp_with_fudge(l_fp lfp, double ofs);
150
151#endif /*!defined(NTP_CALGPS_H)*/
152