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