---
+* [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>
- 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);
TcNtpDatum * nd
)
{
+ memset(cd, 0, sizeof(*cd));
ntpcal_rd_to_date(
cd,
nd->days + DAY_NTP_STARTS + ntpcal_daysec_to_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;
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);
}
#include "ntp_unixtime.h"
#include "ntp_refclock.h"
#include "ntp_calendar.h"
+#include "ntp_calgps.h"
#include "ntp_stdlib.h"
#include <stdio.h>
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);
/* 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;
}
+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 (
void test_IsoCalWeeksToYearEnd(void);
void test_DaySecToDate(void);
void test_GpsRollOver(void);
+void test_GpsRemapFunny(void);
void test_GpsNtpFixpoints(void);
void test_NtpToNtp(void);
}
}
+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;
+}
/*
* ---------------------------------------------------------------------
*/
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)
{
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);
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());
}