2 * refclock_nmea.c - clock driver for an NMEA GPS CLOCK
3 * Michael Petry Jun 20, 1994
4 * based on refclock_heathn.c
10 #if defined(REFCLOCK) && defined(CLOCK_NMEA)
14 #include "ntp_unixtime.h"
15 #include "ntp_refclock.h"
16 #include "ntp_stdlib.h"
22 # ifdef HAVE_TIMEPPS_H
25 # ifdef HAVE_SYS_TIMEPPS_H
26 # include <sys/timepps.h>
29 #endif /* HAVE_PPSAPI */
32 * This driver supports the NMEA GPS Receiver with
34 * Protype was refclock_trak.c, Thanks a lot.
36 * The receiver used spits out the NMEA sentences for boat navigation.
37 * And you thought it was an information superhighway. Try a raging river
38 * filled with rapids and whirlpools that rip away your data and warp time.
40 * If HAVE_PPSAPI is defined code to use the PPSAPI will be compiled in.
41 * On startup if initialization of the PPSAPI fails, it will fall back
42 * to the "normal" timestamps.
44 * The PPSAPI part of the driver understands fudge flag2 and flag3. If
45 * flag2 is set, it will use the clear edge of the pulse. If flag3 is
46 * set, kernel hardpps is enabled.
48 * GPS sentences other than RMC (the default) may be enabled by setting
49 * the relevent bits of 'mode' in the server configuration line
50 * server 127.127.20.x mode X
52 * bit 0 - enables RMC (1)
53 * bit 1 - enables GGA (2)
54 * bit 2 - enables GLL (4)
55 * multiple sentences may be selected
62 # define DEVICE "COM%d:" /* COM 1 - 3 supported */
64 # define DEVICE "/dev/gps%d" /* name of radio device */
66 #define SPEED232 B4800 /* uart speed (4800 bps) */
67 #define PRECISION (-9) /* precision assumed (about 2 ms) */
68 #define PPS_PRECISION (-20) /* precision assumed (about 1 us) */
69 #define REFID "GPS\0" /* reference id */
70 #define DESCRIPTION "NMEA GPS Clock" /* who we are */
71 #define NANOSECOND 1000000000 /* one second (ns) */
72 #define RANGEGATE 500000 /* range gate (ns) */
74 #define LENNMEA 75 /* min timecode length */
77 * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
80 static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
81 static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
84 * Unit control structure
87 int pollcnt; /* poll message counter */
88 int polled; /* Hand in a sample? */
89 l_fp tstamp; /* timestamp of last poll */
91 struct timespec ts; /* last timestamp */
92 pps_params_t pps_params; /* pps parameters */
93 pps_info_t pps_info; /* last pps data */
94 pps_handle_t handle; /* pps handlebars */
95 #endif /* HAVE_PPSAPI */
101 static int nmea_start P((int, struct peer *));
102 static void nmea_shutdown P((int, struct peer *));
104 static void nmea_control P((int, struct refclockstat *, struct
105 refclockstat *, struct peer *));
106 static int nmea_ppsapi P((struct peer *, int, int));
107 static int nmea_pps P((struct nmeaunit *, l_fp *));
108 #endif /* HAVE_PPSAPI */
109 static void nmea_receive P((struct recvbuf *));
110 static void nmea_poll P((int, struct peer *));
111 static void gps_send P((int, const char *, struct peer *));
112 static char *field_parse P((char *, int));
117 struct refclock refclock_nmea = {
118 nmea_start, /* start up driver */
119 nmea_shutdown, /* shut down driver */
120 nmea_poll, /* transmit poll message */
122 nmea_control, /* fudge control */
124 noentry, /* fudge control */
125 #endif /* HAVE_PPSAPI */
126 noentry, /* initialize driver */
127 noentry, /* buginfo */
128 NOFLAGS /* not used */
132 * nmea_start - open the GPS devices and initialize data for processing
140 register struct nmeaunit *up;
141 struct refclockproc *pp;
146 * Open serial port. Use CLK line discipline, if available.
148 (void)sprintf(device, DEVICE, unit);
150 if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
154 * Allocate and initialize unit structure
156 if (!(up = (struct nmeaunit *)
157 emalloc(sizeof(struct nmeaunit)))) {
161 memset((char *)up, 0, sizeof(struct nmeaunit));
163 pp->io.clock_recv = nmea_receive;
164 pp->io.srcclock = (caddr_t)peer;
167 if (!io_addclock(&pp->io)) {
172 pp->unitptr = (caddr_t)up;
175 * Initialize miscellaneous variables
177 peer->precision = PRECISION;
178 pp->clockdesc = DESCRIPTION;
179 memcpy((char *)&pp->refid, REFID, 4);
181 gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer);
185 * Start the PPSAPI interface if it is there. Default to use
186 * the assert edge and do not enable the kernel hardpps.
188 if (time_pps_create(fd, &up->handle) < 0) {
191 "refclock_nmea: time_pps_create failed: %m");
194 return(nmea_ppsapi(peer, 0, 0));
197 #endif /* HAVE_PPSAPI */
201 * nmea_shutdown - shut down a GPS clock
209 register struct nmeaunit *up;
210 struct refclockproc *pp;
213 up = (struct nmeaunit *)pp->unitptr;
216 time_pps_destroy(up->handle);
217 #endif /* HAVE_PPSAPI */
218 io_closeclock(&pp->io);
224 * nmea_control - fudge control
228 int unit, /* unit (not used */
229 struct refclockstat *in, /* input parameters (not uded) */
230 struct refclockstat *out, /* output parameters (not used) */
231 struct peer *peer /* peer structure pointer */
234 struct refclockproc *pp;
237 nmea_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
238 pp->sloppyclockflag & CLK_FLAG3);
247 struct peer *peer, /* peer structure pointer */
248 int enb_clear, /* clear enable */
249 int enb_hardpps /* hardpps enable */
252 struct refclockproc *pp;
257 up = (struct nmeaunit *)pp->unitptr;
258 if (time_pps_getcap(up->handle, &capability) < 0) {
260 "refclock_nmea: time_pps_getcap failed: %m");
263 memset(&up->pps_params, 0, sizeof(pps_params_t));
265 up->pps_params.mode = capability & PPS_CAPTURECLEAR;
267 up->pps_params.mode = capability & PPS_CAPTUREASSERT;
268 if (!up->pps_params.mode) {
270 "refclock_nmea: invalid capture edge %d",
274 up->pps_params.mode |= PPS_TSFMT_TSPEC;
275 if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
277 "refclock_nmea: time_pps_setparams failed: %m");
281 if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
282 up->pps_params.mode & ~PPS_TSFMT_TSPEC,
283 PPS_TSFMT_TSPEC) < 0) {
285 "refclock_nmea: time_pps_kcbind failed: %m");
290 peer->precision = PPS_PRECISION;
294 time_pps_getparams(up->handle, &up->pps_params);
296 "refclock_ppsapi: capability 0x%x version %d mode 0x%x kern %d\n",
297 capability, up->pps_params.api_version,
298 up->pps_params.mode, enb_hardpps);
306 * Get PPSAPI timestamps.
308 * Return 0 on failure and 1 on success.
317 struct timespec timeout, ts;
322 * Convert the timespec nanoseconds field to ntp l_fp units.
328 memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
329 if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
332 if (up->pps_params.mode & PPS_CAPTUREASSERT) {
333 if (pps_info.assert_sequence ==
334 up->pps_info.assert_sequence)
336 ts = up->pps_info.assert_timestamp;
337 } else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
338 if (pps_info.clear_sequence ==
339 up->pps_info.clear_sequence)
341 ts = up->pps_info.clear_timestamp;
345 if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec))
349 tstmp.l_ui = ts.tv_sec + JAN_1970;
350 dtemp = ts.tv_nsec * FRAC / 1e9;
351 tstmp.l_uf = (u_int32)dtemp;
355 #endif /* HAVE_PPSAPI */
358 * nmea_receive - receive data from the serial interface
362 struct recvbuf *rbufp
365 register struct nmeaunit *up;
366 struct refclockproc *pp;
372 /* Use these variables to hold data until we decide its worth keeping */
373 char rd_lastcode[BMAX];
378 * Initialize pointers and read the timecode and timestamp
380 peer = (struct peer *)rbufp->recv_srcclock;
382 up = (struct nmeaunit *)pp->unitptr;
383 rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
386 * There is a case that a <CR><LF> gives back a "blank" line
393 printf("nmea: gpsread %d %s\n", rd_lencode,
398 * We check the timecode format and decode its contents. The
399 * we only care about a few of them. The most important being
401 * $GPRMC,hhmmss,a,fddmm.xx,n,dddmmm.xx,w,zz.z,yyy.,ddmmyy,dd,v*CC
402 * For Magellan (ColorTrak) GLL probably datum (order of sentences)
403 * also mode (0,1,2,3) select sentence ANY/ALL, RMC, GGA, GLL
404 * $GPGLL,3513.8385,S,14900.7851,E,232420.594,A*21
405 * $GPGGA,232420.59,3513.8385,S,14900.7851,E,1,05,3.4,00519,M,,,,*3F
407 * $GPRMC,232418.19,A,3513.8386,S,14900.7853,E,00.0,000.0,121199,12.,E*77
419 if(strncmp(cp,"$GPRMC",6)==0) {
422 else if(strncmp(cp,"$GPGGA",6)==0) {
425 else if(strncmp(cp,"$GPGLL",6)==0) {
428 else if(strncmp(cp,"$GPXXX",6)==0) {
435 /* See if I want to process this message type */
436 if ( ((peer->ttlmax == 0) && (cmdtype != GPRMC))
437 || ((peer->ttlmax != 0) && !(cmdtype & peer->ttlmax)) )
440 pp->lencode = rd_lencode;
441 strcpy(pp->a_lastcode,rd_lastcode);
444 pp->lastrec = up->tstamp = rd_tmp;
449 printf("nmea: timecode %d %s\n", pp->lencode,
454 /* Grab field depending on clock string type */
458 * Test for synchronization. Check for quality byte.
460 dp = field_parse(cp,2);
462 pp->leap = LEAP_NOTINSYNC;
464 pp->leap = LEAP_NOWARNING;
466 /* Now point at the time field */
467 dp = field_parse(cp,1);
473 * Test for synchronization. Check for quality byte.
475 dp = field_parse(cp,6);
477 pp->leap = LEAP_NOTINSYNC;
479 pp->leap = LEAP_NOWARNING;
481 /* Now point at the time field */
482 dp = field_parse(cp,1);
488 * Test for synchronization. Check for quality byte.
490 dp = field_parse(cp,6);
492 pp->leap = LEAP_NOTINSYNC;
494 pp->leap = LEAP_NOWARNING;
496 /* Now point at the time field */
497 dp = field_parse(cp,5);
509 * Check time code format of NMEA
512 if( !isdigit((int)dp[0]) ||
513 !isdigit((int)dp[1]) ||
514 !isdigit((int)dp[2]) ||
515 !isdigit((int)dp[3]) ||
516 !isdigit((int)dp[4]) ||
519 refclock_report(peer, CEVNT_BADREPLY);
525 * Convert time and check values.
527 pp->hour = ((dp[0] - '0') * 10) + dp[1] - '0';
528 pp->minute = ((dp[2] - '0') * 10) + dp[3] - '0';
529 pp->second = ((dp[4] - '0') * 10) + dp[5] - '0';
530 /* Default to 0 milliseconds, if decimal convert milliseconds in
531 one, two or three digits
535 if (isdigit((int)dp[7])) {
536 pp->msec = (dp[7] - '0') * 100;
537 if (isdigit((int)dp[8])) {
538 pp->msec += (dp[8] - '0') * 10;
539 if (isdigit((int)dp[9])) {
540 pp->msec += (dp[9] - '0');
546 if (pp->hour > 23 || pp->minute > 59 || pp->second > 59
547 || pp->msec > 1000) {
548 refclock_report(peer, CEVNT_BADTIME);
554 * Convert date and check values.
556 if (cmdtype==GPRMC) {
557 dp = field_parse(cp,9);
559 day = (day * 10) + dp[1] - '0';
561 month = (month * 10) + dp[3] - '0';
562 pp->year = dp[4] - '0';
563 pp->year = (pp->year * 10) + dp[5] - '0';
567 time_t tt = time(NULL);
568 struct tm * t = gmtime(&tt);
570 month = t->tm_mon + 1;
571 pp->year= t->tm_year;
574 if (month < 1 || month > 12 || day < 1) {
575 refclock_report(peer, CEVNT_BADTIME);
579 /* Hmmmm this will be a nono for 2100,2200,2300 but I don't think I'll be here */
580 /* good thing that 2000 is a leap year */
581 /* pp->year will be 00-99 if read from GPS, 00-> (years since 1900) from tm_year */
583 if (day > day1tab[month - 1]) {
584 refclock_report(peer, CEVNT_BADTIME);
587 for (i = 0; i < month - 1; i++)
590 if (day > day2tab[month - 1]) {
591 refclock_report(peer, CEVNT_BADTIME);
594 for (i = 0; i < month - 1; i++)
602 * If the PPSAPI is working, rather use its timestamps.
603 * assume that the PPS occurs on the second so blow any msec
605 if (nmea_pps(up, &rd_tmp) == 1) {
606 pp->lastrec = up->tstamp = rd_tmp;
609 #endif /* HAVE_PPSAPI */
612 * Process the new sample in the median filter and determine the
613 * reference clock offset and dispersion. We use lastrec as both
614 * the reference time and receive time, in order to avoid being
615 * cute, like setting the reference time later than the receive
616 * time, which may cause a paranoid protocol module to chuck out
620 if (!refclock_process(pp)) {
621 refclock_report(peer, CEVNT_BADTIME);
628 * Only go on if we had been polled.
634 refclock_receive(peer);
636 /* If we get here - what we got from the clock is OK, so say so */
637 refclock_report(peer, CEVNT_NOMINAL);
639 record_clock_stats(&peer->srcadr, pp->a_lastcode);
644 * nmea_poll - called by the transmit procedure
646 * We go to great pains to avoid changing state here, since there may be
647 * more than one eavesdropper receiving the same timecode.
655 register struct nmeaunit *up;
656 struct refclockproc *pp;
659 up = (struct nmeaunit *)pp->unitptr;
660 if (up->pollcnt == 0)
661 refclock_report(peer, CEVNT_TIMEOUT);
668 * usually nmea_receive can get a timestamp every second
671 gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer);
676 * gps_send(fd,cmd, peer) Sends a command to the GPS receiver.
677 * as gps_send(fd,"rqts,u\r", peer);
679 * We don't currently send any data, but would like to send
680 * RTCM SC104 messages for differential positioning. It should
681 * also give us better time. Without a PPS output, we're
682 * Just fooling ourselves because of the serial code paths
693 if (write(fd, cmd, strlen(cmd)) == -1) {
694 refclock_report(peer, CEVNT_FAULT);
707 for (tp = cp; *tp != '\0'; tp++) {
716 int refclock_nmea_bs;
717 #endif /* REFCLOCK */