1358616Scy/* 2358616Scy * ntp_calgps.h - calendar for GPS/GNSS based clocks 3358616Scy * 4358616Scy * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project. 5358616Scy * The contents of 'html/copyright.html' apply. 6358616Scy * 7358616Scy * -------------------------------------------------------------------- 8358616Scy * 9358616Scy * This module implements stuff often used with GPS/GNSS receivers 10358616Scy */ 11358616Scy#ifndef NTP_CALGPS_H 12358616Scy#define NTP_CALGPS_H 13358616Scy 14358616Scy#include <time.h> 15358616Scy 16358616Scy#include "ntp_types.h" 17358616Scy#include "ntp_fp.h" 18358616Scy#include "ntp_calendar.h" 19358616Scy 20358616Scy/* GPS week calendar (extended weeks) 21358616Scy * We use weeks based on 1899-31-12, which was the last Sunday before 22358616Scy * the begin of the NTP epoch. (Which is equivalent to saying 1900-01-01 23358616Scy * was a Monday...) 24358616Scy * 25358616Scy * We simply pre-calculate the offsets and cycle shifts for the real GPS 26358616Scy * calendar, which starts at 1980-01-06, to simplyfy some expressions. 27358616Scy * 28358616Scy * This has a fringe benefit that should not be overlooked: Since week zero 29358616Scy * is around 1900, and we should never have to deal with dates before 30358616Scy * 1970 or 1980, a week number of zero can be easily used to indicate 31358616Scy * an invalid week time stamp. 32358616Scy */ 33358616Scy#define GPSNTP_WSHIFT 4175 /* weeks 1899-31-12 --> 1980-01-06 */ 34358616Scy#define GPSNTP_WCYCLE 79 /* above, modulo 1024 */ 35358616Scy#define GPSNTP_DSHIFT 1 /* day number of 1900-01-01 in week */ 36358616Scy 37358616Scystruct gpsdatum { 38358616Scy uint32_t weeks; /* weeks since GPS epoch */ 39358616Scy int32_t wsecs; /* seconds since week start */ 40358616Scy uint32_t frac; /* fractional seconds */ 41358616Scy}; 42358616Scytypedef struct gpsdatum TGpsDatum; 43358616Scytypedef struct gpsdatum const TcGpsDatum; 44358616Scy 45358616Scy/* NTP date/time in split representation */ 46358616Scystruct ntpdatum { 47358616Scy uint32_t days; /* since NTP epoch */ 48358616Scy int32_t secs; /* since midnight, denorm is ok */ 49358616Scy uint32_t frac; /* fractional seconds */ 50358616Scy}; 51358616Scytypedef struct ntpdatum TNtpDatum; 52358616Scytypedef struct ntpdatum const TcNtpDatum; 53358616Scy 54358616Scy/* 55358616Scy * GPS week/sec calendar functions 56358616Scy * 57358616Scy * see the implementation for details, especially the 58358616Scy * 'gpscal_from_weektime{1,2}()' 59358616Scy */ 60358616Scy 61358616Scyextern TGpsDatum 62358616Scygpscal_fix_gps_era(TcGpsDatum *); 63358616Scy 64358616Scyextern void 65358616Scygpscal_add_offset(TGpsDatum *datum, l_fp offset); 66358616Scy 67358616Scyextern TGpsDatum 68358616Scygpscal_from_calendar_ex(TcCivilDate*, l_fp fofs, int/*BOOL*/ warp); 69358616Scy 70358616Scystatic inline TGpsDatum 71358616Scygpscal_from_calendar(TcCivilDate *pCiv, l_fp fofs) { 72358616Scy return gpscal_from_calendar_ex(pCiv, fofs, TRUE); 73358616Scy} 74358616Scy 75358616Scyextern TGpsDatum /* see source for semantic of the 'fofs' value! */ 76358616Scygpscal_from_gpsweek(uint16_t w, int32_t s, l_fp fofs); 77358616Scy 78358616Scyextern TGpsDatum 79358616Scygpscal_from_weektime1(int32_t wsecs, l_fp fofs, l_fp pivot); 80358616Scy 81358616Scyextern TGpsDatum 82358616Scygpscal_from_weektime2(int32_t wsecs, l_fp fofs, TcGpsDatum *pivot); 83358616Scy 84358616Scyextern void 85358616Scygpscal_to_calendar(TCivilDate*, TcGpsDatum*); 86358616Scy 87358616Scyextern TGpsDatum 88358616Scygpscal_from_gpsntp(TcNtpDatum*); 89358616Scy 90358616Scyextern l_fp 91358616Scyntpfp_from_gpsdatum(TcGpsDatum *); 92358616Scy 93358616Scy/* 94358616Scy * NTP day/sec calendar functions 95358616Scy * 96358616Scy * see the implementation for details, especially the 97358616Scy * 'gpscal_from_daytime{1,2}()' 98358616Scy */ 99358616Scyextern TNtpDatum 100358616Scygpsntp_fix_gps_era(TcNtpDatum *); 101358616Scy 102358616Scyextern void 103358616Scygpsntp_add_offset(TNtpDatum *datum, l_fp offset); 104358616Scy 105358616Scyextern TNtpDatum 106358616Scygpsntp_from_calendar_ex(TcCivilDate*, l_fp fofs, int/*BOOL*/ warp); 107358616Scy 108358616Scystatic inline TNtpDatum 109358616Scygpsntp_from_calendar(TcCivilDate * pCiv, l_fp fofs) { 110358616Scy return gpsntp_from_calendar_ex(pCiv, fofs, TRUE); 111358616Scy} 112358616Scy 113358616Scyextern TNtpDatum 114358616Scygpsntp_from_daytime1_ex(TcCivilDate *dt, l_fp fofs, l_fp pivot, int/*BOOL*/ warp); 115358616Scy 116358616Scystatic inline TNtpDatum 117358616Scygpsntp_from_daytime1(TcCivilDate *dt, l_fp fofs, l_fp pivot) { 118358616Scy return gpsntp_from_daytime1_ex(dt, fofs, pivot, TRUE); 119358616Scy} 120358616Scy 121358616Scyextern TNtpDatum 122358616Scygpsntp_from_daytime2_ex(TcCivilDate *dt, l_fp fofs, TcNtpDatum *pivot, int/*BOOL*/ warp); 123358616Scy 124358616Scystatic inline TNtpDatum 125358616Scygpsntp_from_daytime2(TcCivilDate *dt, l_fp fofs, TcNtpDatum *pivot) { 126358616Scy return gpsntp_from_daytime2_ex(dt, fofs, pivot, TRUE); 127358616Scy} 128358616Scy 129358616Scyextern TNtpDatum 130358616Scygpsntp_from_gpscal_ex(TcGpsDatum*, int/*BOOL*/ warp); 131358616Scy 132358616Scystatic inline TNtpDatum 133358616Scygpsntp_from_gpscal(TcGpsDatum *wd) { 134358616Scy return gpsntp_from_gpscal_ex(wd, FALSE); 135358616Scy} 136358616Scy 137358616Scyextern void 138358616Scygpsntp_to_calendar(TCivilDate*, TcNtpDatum*); 139358616Scy 140358616Scyextern l_fp 141358616Scyntpfp_from_ntpdatum(TcNtpDatum*); 142358616Scy 143358616Scy/* 144358616Scy * Some helpers 145358616Scy */ 146358616Scy 147358616Scy/* apply fudge to time stamp: *SUBTRACT* the given offset from an l_fp*/ 148358616Scyextern l_fp 149358616Scyntpfp_with_fudge(l_fp lfp, double ofs); 150358616Scy 151358616Scy#endif /*!defined(NTP_CALGPS_H)*/ 152