From: Harlan Stenn Date: Sat, 21 Apr 2001 02:10:20 +0000 (-0000) Subject: ChangeLog, refclock_nmea.c: X-Git-Tag: NTP_4_0_99_M~61 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c99b94b4e9e6351e63ebbc2b08cc7bdf25745b99;p=thirdparty%2Fntp.git ChangeLog, refclock_nmea.c: * ntpd/refclock_nmea.c: PPSAPI cleanup, default to RMC sentences, handle milliseconds, multiple sentences, other good stuff. From: John Woolner , Marc.Brett@westerngeco.com, John.Hay@icomtek.csir.co.za bk: 3ae0ec0cFhNWAHP9oLv9i1lrbYAwtg --- diff --git a/ChangeLog b/ChangeLog index 27fc62e908..8e33522708 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2001-04-20 Harlan Stenn + * ntpd/refclock_nmea.c: PPSAPI cleanup, default to RMC sentences, + handle milliseconds, multiple sentences, other good stuff. + From: John Woolner , Marc.Brett@westerngeco.com, + John.Hay@icomtek.csir.co.za + * ntpd/ntp_proto.c (receive): In the AM_NEWBCL case, return in all cases at the end. * ntpd/ntp_peer.c (newpeer): Check cast_flags against MDF_BCLNT, diff --git a/ntpd/refclock_nmea.c b/ntpd/refclock_nmea.c index 87a1513021..03ca8abc9d 100644 --- a/ntpd/refclock_nmea.c +++ b/ntpd/refclock_nmea.c @@ -177,6 +177,7 @@ nmea_start( * the assert edge and do not enable the kernel hardpps. */ if (time_pps_create(fd, &up->handle) < 0) { + up->handle = 0; msyslog(LOG_ERR, "refclock_nmea: time_pps_create failed: %m"); return (1); @@ -282,8 +283,8 @@ nmea_ppsapi( if (debug) { time_pps_getparams(up->handle, &up->pps_params); printf( - "refclock_ppsapi: fd %d capability 0x%x version %d mode 0x%x kern %d\n", - up->handle, capability, up->pps_params.api_version, + "refclock_ppsapi: capability 0x%x version %d mode 0x%x kern %d\n", + capability, up->pps_params.api_version, up->pps_params.mode, enb_hardpps); } #endif @@ -310,7 +311,7 @@ nmea_pps( /* * Convert the timespec nanoseconds field to ntp l_fp units. */ - if (up->handle == -1) + if (up->handle == 0) return (0); timeout.tv_sec = 0; timeout.tv_nsec = 0; @@ -354,11 +355,14 @@ nmea_receive( register struct nmeaunit *up; struct refclockproc *pp; struct peer *peer; - l_fp trtmp; int month, day; int i; char *cp, *dp; int cmdtype; + /* Use these variables to hold data until we decide its worth keeping */ + char rd_lastcode[BMAX]; + l_fp rd_tmp; + u_short rd_lencode; /* * Initialize pointers and read the timecode and timestamp @@ -366,30 +370,18 @@ nmea_receive( peer = (struct peer *)rbufp->recv_srcclock; pp = peer->procptr; up = (struct nmeaunit *)pp->unitptr; - pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp); + rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp); /* * There is a case that a gives back a "blank" line */ - if (pp->lencode == 0) + if (rd_lencode == 0) return; - /* - * We get a buffer and timestamp for each . - */ - pp->lastrec = up->tstamp = trtmp; - up->pollcnt = 2; - -#ifdef HAVE_PPSAPI - /* If the PPSAPI is working, rather use its timestamps. */ - if (nmea_pps(up, &trtmp) == 1) - pp->lastrec = up->tstamp = trtmp; -#endif /* HAVE_PPSAPI */ - #ifdef DEBUG if (debug) - printf("nmea: timecode %d %s\n", pp->lencode, - pp->a_lastcode); + printf("nmea: gpsread %d %s\n", rd_lencode, + rd_lastcode); #endif /* @@ -397,12 +389,22 @@ nmea_receive( * we only care about a few of them. The most important being * the $GPRMC format * $GPRMC,hhmmss,a,fddmm.xx,n,dddmmm.xx,w,zz.z,yyy.,ddmmyy,dd,v*CC - * $GPGGA,162617.0,4548.339,N,00837.719,E,1,07,0.97,00262,M,048,M,,*5D + * For Magellan (ColorTrak) GLL probably datum (order of sentences) + * also mode (0,1,2,3) select sentence ANY/ALL, RMC, GGA, GLL + * $GPGLL,3513.8385,S,14900.7851,E,232420.594,A*21 + * $GPGGA,232420.59,3513.8385,S,14900.7851,E,1,05,3.4,00519,M,,,,*3F + * $GPRMB,... + * $GPRMC,232418.19,A,3513.8386,S,14900.7853,E,00.0,000.0,121199,12.,E*77 + * $GPAPB,... + * $GPGSA,... + * $GPGSV,... + * $GPGSV,... */ -#define GPRMC 0 -#define GPXXX 1 +#define GPXXX 0 +#define GPRMC 1 #define GPGGA 2 - cp = pp->a_lastcode; +#define GPGLL 4 + cp = rd_lastcode; cmdtype=0; if(strncmp(cp,"$GPRMC",6)==0) { cmdtype=GPRMC; @@ -410,20 +412,99 @@ nmea_receive( else if(strncmp(cp,"$GPGGA",6)==0) { cmdtype=GPGGA; } + else if(strncmp(cp,"$GPGLL",6)==0) { + cmdtype=GPGLL; + } else if(strncmp(cp,"$GPXXX",6)==0) { cmdtype=GPXXX; } else return; + + /* See if I want to process this message type */ + if ( ((peer->ttlmax == 0) && (cmdtype != GPRMC)) + || ((peer->ttlmax != 0) && !(cmdtype & peer->ttlmax)) ) + return; + + pp->lencode = rd_lencode; + strcpy(pp->a_lastcode,rd_lastcode); + cp = pp->a_lastcode; + + pp->lastrec = up->tstamp = rd_tmp; + up->pollcnt = 2; + +#ifdef HAVE_PPSAPI + /* If the PPSAPI is working, rather use its timestamps. */ + if (nmea_pps(up, &rd_tmp) == 1) + pp->lastrec = up->tstamp = rd_tmp; +#endif /* HAVE_PPSAPI */ + +#ifdef DEBUG + if (debug) + printf("nmea: timecode %d %s\n", pp->lencode, + pp->a_lastcode); +#endif + + + /* Grab field depending on clock string type */ switch( cmdtype ) { case GPRMC: + /* + * Test for synchronization. Check for quality byte. + */ + dp = field_parse(cp,2); + if( dp[0] != 'A') + pp->leap = LEAP_NOTINSYNC; + else + pp->leap = LEAP_NOWARNING; + + /* Now point at the time field */ + dp = field_parse(cp,1); + break; + + case GPGGA: /* - * Check time code format of NMEA + * Test for synchronization. Check for quality byte. */ + dp = field_parse(cp,6); + if( dp[0] == '0') + pp->leap = LEAP_NOTINSYNC; + else + pp->leap = LEAP_NOWARNING; + /* Now point at the time field */ dp = field_parse(cp,1); + break; + + + case GPGLL: + /* + * Test for synchronization. Check for quality byte. + */ + dp = field_parse(cp,6); + if( dp[0] != 'A') + pp->leap = LEAP_NOTINSYNC; + else + pp->leap = LEAP_NOWARNING; + + /* Now point at the time field */ + dp = field_parse(cp,5); + break; + + + case GPXXX: + return; + default: + return; + + } + + /* + * Check time code format of NMEA + */ + if( !isdigit((int)dp[0]) || !isdigit((int)dp[1]) || !isdigit((int)dp[2]) || @@ -435,51 +516,55 @@ nmea_receive( return; } - /* - * Test for synchronization. Check for quality byte. - */ - switch( cmdtype ) { - case GPRMC: - dp = field_parse(cp,2); - if( dp[0] != 'A') { - refclock_report(peer, CEVNT_BADREPLY); - return; - } - break; - case GPGGA: - dp = field_parse(cp,6); - if( dp[0] == '0') { - refclock_report(peer, CEVNT_BADREPLY); - return; - } - break; + + /* + * Convert time and check values. + */ + pp->hour = ((dp[0] - '0') * 10) + dp[1] - '0'; + pp->minute = ((dp[2] - '0') * 10) + dp[3] - '0'; + pp->second = ((dp[4] - '0') * 10) + dp[5] - '0'; + /* Default to 0 milliseconds, if decimal convert milliseconds in + one, two or three digits + */ + pp->msec = 0; + if ( dp[6] == '.' ) + if ( isdigit(dp[7]) ) + { + pp->msec = (dp[7]-'0')*100; + if ( isdigit(dp[8]) ) + { + pp->msec = pp->msec + (dp[8]-'0')*10; + if ( isdigit(dp[9]) ) + pp->msec = pp->msec + (dp[9]-'0'); } - break; - case GPXXX: - return; - default: - return; + } + if (pp->hour > 23 || pp->minute > 59 || pp->second > 59) { + refclock_report(peer, CEVNT_BADTIME); + return; } - if (cmdtype ==GPGGA) { - /* only time */ - time_t tt = time(NULL); - struct tm * t = gmtime(&tt); - day = t->tm_mday; - month = t->tm_mon + 1; - pp->year= t->tm_year; - } else { - dp = field_parse(cp,9); + + if (cmdtype==GPRMC) + { /* * Convert date and check values. */ - day = dp[0] - '0'; - day = (day * 10) + dp[1] - '0'; - month = dp[2] - '0'; - month = (month * 10) + dp[3] - '0'; - pp->year = dp[4] - '0'; - pp->year = (pp->year * 10) + dp[5] - '0'; + dp = field_parse(cp,9); + day = dp[0] - '0'; + day = (day * 10) + dp[1] - '0'; + month = dp[2] - '0'; + month = (month * 10) + dp[3] - '0'; + pp->year = dp[4] - '0'; + pp->year = (pp->year * 10) + dp[5] - '0'; + } + else { + /* only time */ + time_t tt = time(NULL); + struct tm * t = gmtime(&tt); + day = t->tm_mday; + month = t->tm_mon + 1; + pp->year= t->tm_year; } if (month < 1 || month > 12 || day < 1) { @@ -487,6 +572,9 @@ nmea_receive( return; } + /* Hmmmm this will be a nono for 2100,2200,2300 but I don't think I'll be here */ + /* good thing that 2000 is a leap year */ + /* pp->year will be 00-99 if read from GPS, 00-> (years since 1900) from tm_year */ if (pp->year % 4) { if (day > day1tab[month - 1]) { refclock_report(peer, CEVNT_BADTIME); @@ -504,31 +592,6 @@ nmea_receive( } pp->day = day; - dp = field_parse(cp,1); - /* - * Convert time and check values. - */ - pp->hour = ((dp[0] - '0') * 10) + dp[1] - '0'; - pp->minute = ((dp[2] - '0') * 10) + dp[3] - '0'; - pp->second = ((dp[4] - '0') * 10) + dp[5] - '0'; - pp->msec = 0; - if (dp[6] == '.') { - if (isdigit((int)dp[7])) { - pp->msec += (dp[7] - '0') * 100; - if (isdigit((int)dp[8])) { - pp->msec += (dp[8] - '0') * 10; - if (isdigit((int)dp[9])) { - pp->msec += (dp[9] - '0'); - } - } - } - } - - if (pp->hour > 23 || pp->minute > 59 || pp->second > 59 - || pp->msec > 1000) { - refclock_report(peer, CEVNT_BADTIME); - return; - } /* * Process the new sample in the median filter and determine the @@ -538,11 +601,14 @@ nmea_receive( * time, which may cause a paranoid protocol module to chuck out * the data. */ + if (!refclock_process(pp)) { refclock_report(peer, CEVNT_BADTIME); return; } + + /* * Only go on if we had been polled. */ @@ -552,7 +618,11 @@ nmea_receive( refclock_receive(peer); + /* If we get here - what we got from the clock is OK, so say so */ + refclock_report(peer, CEVNT_NOMINAL); + record_clock_stats(&peer->srcadr, pp->a_lastcode); + } /*