]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 3590] Update refclock_oncore.c to the new GPS date API
authorJuergen Perlinger <perlinger@ntp.org>
Mon, 13 May 2019 05:44:52 +0000 (07:44 +0200)
committerJuergen Perlinger <perlinger@ntp.org>
Mon, 13 May 2019 05:44:52 +0000 (07:44 +0200)
bk: 5cd90454wWo2XaX9L6hjBeqtbkILKg

ChangeLog
libntp/ntp_calgps.c
ntpd/refclock_oncore.c
tests/libntp/calendar.c
tests/libntp/run-calendar.c

index 434054efebe4ce507605c8c7a0d10ded2f6371fa..fe0899336caf0647b0930f7994a874b184c2f916 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,5 @@
 ---
+* [Bug 3590] Update refclock_oncore.c to the new GPS date API <perlinger@ntp.org>
 * [Bug 3577] Update refclock_zyfer.c to the new GPS date API <perlinger@ntp.org>
   - also updates for refclock_nmea.c and refclock_jupiter.c
 * [Bug 3576] New GPS date function API <perlinger@ntp.org>
index 20e1f103afed4fc2f4a1ea23f6c2a65f19faddb8..773cfe909a834b662391a1c49a31bc8d7e7f76df 100644 (file)
@@ -164,7 +164,7 @@ _gpsntp_fix_gps_era(
             - GPSNTP_DSHIFT;
        days = out.days;
 
-       sign = (uint32_t) -(days < base);
+       sign = (uint32_t)-(days < base);
        days = sign ^ (days - base);
        days %= clen;
        days = base + (sign & clen) + (sign ^ days);
@@ -282,6 +282,7 @@ gpsntp_to_calendar(
        TcNtpDatum * nd
        )
 {
+       memset(cd, 0, sizeof(*cd));
        ntpcal_rd_to_date(
                cd,
                nd->days + DAY_NTP_STARTS + ntpcal_daysec_to_date(
@@ -407,13 +408,33 @@ again:    if (cal.month && cal.monthday) {        /* use y/m/d civil date */
                     + (int32_t)cal.yearday
                     - 1; /* both RDN and yearday start with '1'. */
        }
-       if (days < DAY_GPS_STARTS) {
+
+       /* Rebase to days after the GPS epoch. 'days' is positive here,
+        * but it might be less than the GPS epoch start. Depending on
+        * the input, we have to do different things to get the desired
+        * result. (Since we want to remap the era anyway, we only have
+        * to retain congruential identities....)
+        */
+
+       if (days >= DAY_GPS_STARTS) {
+               /* simply shift to days since GPS epoch */
+               days -= DAY_GPS_STARTS;
+       } else if (jd->year < 100) {
+               /* Two-digit year on input: add another century and
+                * retry.  This can happen only if the century expansion
+                * yielded a date between 1980-01-01 and 1980-01-05,
+                * both inclusive. We have at most one retry here.
+                */
                cal.year += 100;
                goto again;
+       } else {
+               /* add the complement of DAY_GPS_STARTS (this is, use a
+                * congruential identity here)
+                */
+               days += (7 * 1024) - DAY_GPS_STARTS % (7 * 1024);
        }
 
-       /* get GPS time since start of GPS */
-       days -= DAY_GPS_STARTS;
+       /* Splitting to weeks is simple now: */
        week  = days / 7;
        days -= week * 7;
 
@@ -436,7 +457,10 @@ gpscal_to_calendar(
        TcGpsDatum * wd
        )
 {
-       TNtpDatum nd = gpsntp_from_gpscal(wd);
+       TNtpDatum nd;
+
+       memset(cd, 0, sizeof(*cd));
+       nd = gpsntp_from_gpscal(wd);
        gpsntp_to_calendar(cd, &nd);
 }
 
index 2c82caeb68c6aff4952417924872060480f1f490..17c8cbf294abcfda21243579c58986a1331e72a3 100644 (file)
 #include "ntp_unixtime.h"
 #include "ntp_refclock.h"
 #include "ntp_calendar.h"
+#include "ntp_calgps.h"
 #include "ntp_stdlib.h"
 
 #include <stdio.h>
@@ -388,6 +389,7 @@ static      void    oncore_set_traim      (struct instance *);
 static void    oncore_shmem_get_3D   (struct instance *);
 static void    oncore_ss             (struct instance *);
 static int     oncore_wait_almanac   (struct instance *);
+static void    oncore_feed_clockproc (struct instance *);
 
 static void    oncore_msg_any     (struct instance *, u_char *, size_t, int);
 static void    oncore_msg_Adef    (struct instance *, u_char *, size_t);
@@ -1872,12 +1874,16 @@ oncore_get_timestamp(
 
        /* and some things I dont understand (magic ntp things) */
 
+#if 1
+       oncore_feed_clockproc(instance);
+#else
        if (!refclock_process(instance->pp)) {
-               refclock_report(instance->peer, CEVNT_BADTIME);
+               refclock_report(peer, CEVNT_BADTIME);
                peer->flags &= ~FLAG_PPS;       /* problem - clear PPS FLAG */
                return;
        }
-
+#endif
+       
        oncore_log(instance, LOG_INFO, Msg);     /* this is long message above */
        instance->pollcnt = 2;
 
@@ -4036,6 +4042,52 @@ oncore_wait_almanac(
 }
 
 
+static void
+oncore_feed_clockproc(
+       struct instance * instance
+       )
+{
+       struct peer         * const peer = instance->peer;
+       struct refclockproc * const pp   = instance->pp;
+       
+       TCivilDate cd;  /* calendar date + time */
+       TGpsDatum  gd;  /* GPS datum, remapped into NTP epoch */
+       l_fp       fp;  /* the reference time in NTP format */
+
+       if (pp->year >= 1980) {
+               /* There are oncore receivers that run in a fixed
+                * (possibly shifted) GPS era and fold back into that
+                * era on every GPS week rollover.
+                *
+                * We do not trust the date we get and remap to a GPS
+                * era defined by the GPS base date (derived from the
+                * build time stamp or a 'tos basedate' config option.
+                */
+               ZERO(fp);       /* has a zero to begin with */
+               ZERO(cd);       /* month == monthday == 0 -> use year+yearday */
+               cd.year    = pp->year;
+               cd.yearday = pp->day;
+               cd.hour    = pp->hour;
+               cd.minute  = pp->minute;
+               cd.second  = pp->second;
+               
+               /* the magic happens in the next line: */
+               gd = gpscal_from_calendar(&cd, fp); /* fp should be zero here */
+               
+               /* To avoid the trouble the day-of-year calculations in
+                * 'refclock_process()' can cause we feed the time
+                * stamps we have now directly. This also saves us two
+                * full calendar calendar conversion cycles.
+                */
+               fp = ntpfp_from_gpsdatum(&gd);
+               refclock_process_offset(pp, fp, pp->lastrec, pp->fudgetime1);
+       } else {
+               /* This is obviously a bad date/time... */
+               refclock_report(peer, CEVNT_BADDATE);
+               peer->flags &= ~FLAG_PPS;       /* problem - clear PPS FLAG */
+               return;
+       }
+}
 
 static void
 oncore_log (
index 5953b62c55f9dbc693f91a7d0ed03936a536b34b..97778959fce81783fcf6d7ea80891e37a73da4dd 100644 (file)
@@ -43,6 +43,7 @@ void  test_IsoCalWeeksToYearStart(void);
 void   test_IsoCalWeeksToYearEnd(void);
 void   test_DaySecToDate(void);
 void   test_GpsRollOver(void);
+void   test_GpsRemapFunny(void);
 
 void   test_GpsNtpFixpoints(void);
 void   test_NtpToNtp(void);
@@ -215,6 +216,28 @@ IsEqualDateIso(
        }
 }
 
+static int/*BOOL*/
+strToCal(
+       struct calendar * jd,
+       const char * str
+       )
+{
+       unsigned short y,m,d, H,M,S;
+       
+       if (6 == sscanf(str, "%hu-%2hu-%2huT%2hu:%2hu:%2hu",
+                       &y, &m, &d, &H, &M, &S)) {
+               memset(jd, 0, sizeof(*jd));
+               jd->year     = y;
+               jd->month    = (uint8_t)m;
+               jd->monthday = (uint8_t)d;
+               jd->hour     = (uint8_t)H;
+               jd->minute   = (uint8_t)M;
+               jd->second   = (uint8_t)S;
+               
+               return TRUE;
+       }
+       return FALSE;
+}
 
 /*
  * ---------------------------------------------------------------------
@@ -821,51 +844,67 @@ test_GpsRollOver(void)
         */
        basedate_set_day(2047 * 7 + NTP_TO_GPS_DAYS);
 
-       jd.year     = 19;
-       jd.month    = 4;
-       jd.monthday = 3;
-       jd.hour     = 12;
-       jd.minute   = 0;
-       jd.second   = 0;
-
+       strToCal(&jd, "19-04-03T12:00:00");
        gps = gpscal_from_calendar(&jd, fpz);
        TEST_ASSERT_EQUAL_MESSAGE(week0, gps.weeks, "(week test 1))");
        TEST_ASSERT_EQUAL_MESSAGE(wsec1, gps.wsecs, "(secs test 1)");
 
-       jd.year     = 19;
-       jd.month    = 4;
-       jd.monthday = 6;
-       jd.hour     = 23;
-       jd.minute   = 59;
-       jd.second   = 59;
-
+       strToCal(&jd, "19-04-06T23:59:59");
        gps = gpscal_from_calendar(&jd, fpz);
        TEST_ASSERT_EQUAL_MESSAGE(week0, gps.weeks, "(week test 2)");
        TEST_ASSERT_EQUAL_MESSAGE(wsec2, gps.wsecs, "(secs test 2)");
 
-       jd.year     = 19;
-       jd.month    = 4;
-       jd.monthday = 7;
-       jd.hour     = 0;
-       jd.minute   = 0;
-       jd.second   = 0;
-
+       strToCal(&jd, "19-04-07T00:00:00");
        gps = gpscal_from_calendar(&jd, fpz);
        TEST_ASSERT_EQUAL_MESSAGE(week1, gps.weeks, "(week test 3)");
        TEST_ASSERT_EQUAL_MESSAGE(  0 , gps.wsecs, "(secs test 3)");
        
-       jd.year     = 19;
-       jd.month    = 4;
-       jd.monthday = 10;
-       jd.hour     = 12;
-       jd.minute   = 0;
-       jd.second   = 0;
-
+       strToCal(&jd, "19-04-10T12:00:00");
        gps = gpscal_from_calendar(&jd, fpz);
        TEST_ASSERT_EQUAL_MESSAGE(week1, gps.weeks, "(week test 4)");
        TEST_ASSERT_EQUAL_MESSAGE(wsec1, gps.wsecs, "(secs test 4)");
 }
 
+void
+test_GpsRemapFunny(void)
+{
+       TCivilDate di, dc, de;
+       TGpsDatum  gd;
+
+       l_fp       fpz;
+
+       ZERO(fpz);
+       basedate_set_day(2048 * 7 + NTP_TO_GPS_DAYS);
+
+       /* expand 2digit year to 2080, then fold back into 3rd GPS era: */
+       strToCal(&di, "80-01-01T00:00:00");
+       strToCal(&de, "2021-02-15T00:00:00");
+       gd = gpscal_from_calendar(&di, fpz);
+       gpscal_to_calendar(&dc, &gd);
+       TEST_ASSERT_TRUE(IsEqualCal(&de, &dc));
+
+       /* expand 2digit year to 2080, then fold back into 3rd GPS era: */
+       strToCal(&di, "80-01-05T00:00:00");
+       strToCal(&de, "2021-02-19T00:00:00");
+       gd = gpscal_from_calendar(&di, fpz);
+       gpscal_to_calendar(&dc, &gd);
+       TEST_ASSERT_TRUE(IsEqualCal(&de, &dc));
+
+       /* remap days before epoch into 3rd era: */
+       strToCal(&di, "1980-01-05T00:00:00");
+       strToCal(&de, "2038-11-20T00:00:00");
+       gd = gpscal_from_calendar(&di, fpz);
+       gpscal_to_calendar(&dc, &gd);
+       TEST_ASSERT_TRUE(IsEqualCal(&de, &dc));
+
+       /* remap GPS epoch: */
+       strToCal(&di, "1980-01-06T00:00:00");
+       strToCal(&de, "2019-04-07T00:00:00");
+       gd = gpscal_from_calendar(&di, fpz);
+       gpscal_to_calendar(&dc, &gd);
+       TEST_ASSERT_TRUE(IsEqualCal(&de, &dc));
+}
+
 void
 test_GpsNtpFixpoints(void)
 {
index 6988d1c0d94d089d971a2f0c5421fc6f7cbaf9c1..26089200e7c0634567c156d8a237d664a3205136 100644 (file)
@@ -51,6 +51,7 @@ extern void test_IsoCalWeeksToYearStart(void);
 extern void test_IsoCalWeeksToYearEnd(void);
 extern void test_DaySecToDate(void);
 extern void test_GpsRollOver(void);
+extern void test_GpsRemapFunny(void);
 extern void test_GpsNtpFixpoints(void);
 extern void test_NtpToNtp(void);
 extern void test_NtpToTime(void);
@@ -98,9 +99,10 @@ int main(int argc, char *argv[])
   RUN_TEST(test_IsoCalWeeksToYearEnd, 43);
   RUN_TEST(test_DaySecToDate, 44);
   RUN_TEST(test_GpsRollOver, 45);
-  RUN_TEST(test_GpsNtpFixpoints, 47);
-  RUN_TEST(test_NtpToNtp, 48);
-  RUN_TEST(test_NtpToTime, 49);
+  RUN_TEST(test_GpsRemapFunny, 46);
+  RUN_TEST(test_GpsNtpFixpoints, 48);
+  RUN_TEST(test_NtpToNtp, 49);
+  RUN_TEST(test_NtpToTime, 50);
 
   return (UnityEnd());
 }