1 /* 2 * refclock_nmea.c - clock driver for an NMEA GPS CLOCK 3 * Michael Petry Jun 20, 1994 4 * based on refclock_heathn.c 5 */ 6 #ifdef HAVE_CONFIG_H 7 #include <config.h> 8 #endif 9 10 #if defined(REFCLOCK) && defined(CLOCK_NMEA) 11 12 #include "ntpd.h" 13 #include "ntp_io.h" 14 #include "ntp_unixtime.h" 15 #include "ntp_refclock.h" 16 #include "ntp_stdlib.h" 17 18 #include <stdio.h> 19 #include <ctype.h> 20 21 #ifdef HAVE_PPSAPI 22 # ifdef HAVE_TIMEPPS_H 23 # include <timepps.h> 24 # else 25 # ifdef HAVE_SYS_TIMEPPS_H 26 # include <sys/timepps.h> 27 # endif 28 # endif 29 #endif /* HAVE_PPSAPI */ 30 31 /* 32 * This driver supports the NMEA GPS Receiver with 33 * 34 * Protype was refclock_trak.c, Thanks a lot. 35 * 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. 39 * 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. 43 * 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. 47 * 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 51 * 52 * bit 0 - enables RMC (1) 53 * bit 1 - enables GGA (2) 54 * bit 2 - enables GLL (4) 55 * multiple sentences may be selected 56 */ 57 58 /* 59 * Definitions 60 */ 61 #ifdef SYS_WINNT 62 # define DEVICE "COM%d:" /* COM 1 - 3 supported */ 63 #else 64 # define DEVICE "/dev/gps%d" /* name of radio device */ 65 #endif 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) */ 73 74 #define LENNMEA 75 /* min timecode length */ 75 76 /* 77 * Tables to compute the ddd of year form icky dd/mm timecode. Viva la 78 * leap. 79 */ 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}; 82 83 /* 84 * Unit control structure 85 */ 86 struct nmeaunit { 87 int pollcnt; /* poll message counter */ 88 int polled; /* Hand in a sample? */ 89 l_fp tstamp; /* timestamp of last poll */ 90 #ifdef HAVE_PPSAPI 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 */ 96 }; 97 98 /* 99 * Function prototypes 100 */ 101 static int nmea_start P((int, struct peer *)); 102 static void nmea_shutdown P((int, struct peer *)); 103 #ifdef HAVE_PPSAPI 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)); 113 114 /* 115 * Transfer vector 116 */ 117 struct refclock refclock_nmea = { 118 nmea_start, /* start up driver */ 119 nmea_shutdown, /* shut down driver */ 120 nmea_poll, /* transmit poll message */ 121 #ifdef HAVE_PPSAPI 122 nmea_control, /* fudge control */ 123 #else 124 noentry, /* fudge control */ 125 #endif /* HAVE_PPSAPI */ 126 noentry, /* initialize driver */ 127 noentry, /* buginfo */ 128 NOFLAGS /* not used */ 129 }; 130 131 /* 132 * nmea_start - open the GPS devices and initialize data for processing 133 */ 134 static int 135 nmea_start( 136 int unit, 137 struct peer *peer 138 ) 139 { 140 register struct nmeaunit *up; 141 struct refclockproc *pp; 142 int fd; 143 char device[20]; 144 145 /* 146 * Open serial port. Use CLK line discipline, if available. 147 */ 148 (void)sprintf(device, DEVICE, unit); 149 150 if (!(fd = refclock_open(device, SPEED232, LDISC_CLK))) 151 return (0); 152 153 /* 154 * Allocate and initialize unit structure 155 */ 156 if (!(up = (struct nmeaunit *) 157 emalloc(sizeof(struct nmeaunit)))) { 158 (void) close(fd); 159 return (0); 160 } 161 memset((char *)up, 0, sizeof(struct nmeaunit)); 162 pp = peer->procptr; 163 pp->io.clock_recv = nmea_receive; 164 pp->io.srcclock = (caddr_t)peer; 165 pp->io.datalen = 0; 166 pp->io.fd = fd; 167 if (!io_addclock(&pp->io)) { 168 (void) close(fd); 169 free(up); 170 return (0); 171 } 172 pp->unitptr = (caddr_t)up; 173 174 /* 175 * Initialize miscellaneous variables 176 */ 177 peer->precision = PRECISION; 178 pp->clockdesc = DESCRIPTION; 179 memcpy((char *)&pp->refid, REFID, 4); 180 up->pollcnt = 2; 181 gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer); 182 183 #ifdef HAVE_PPSAPI 184 /* 185 * Start the PPSAPI interface if it is there. Default to use 186 * the assert edge and do not enable the kernel hardpps. 187 */ 188 if (time_pps_create(fd, &up->handle) < 0) { 189 up->handle = 0; 190 msyslog(LOG_ERR, 191 "refclock_nmea: time_pps_create failed: %m"); 192 return (1); 193 } 194 return(nmea_ppsapi(peer, 0, 0)); 195 #else 196 return (1); 197 #endif /* HAVE_PPSAPI */ 198 } 199 200 /* 201 * nmea_shutdown - shut down a GPS clock 202 */ 203 static void 204 nmea_shutdown( 205 int unit, 206 struct peer *peer 207 ) 208 { 209 register struct nmeaunit *up; 210 struct refclockproc *pp; 211 212 pp = peer->procptr; 213 up = (struct nmeaunit *)pp->unitptr; 214 #ifdef HAVE_PPSAPI 215 if (up->handle != 0) 216 time_pps_destroy(up->handle); 217 #endif /* HAVE_PPSAPI */ 218 io_closeclock(&pp->io); 219 free(up); 220 } 221 222 #ifdef HAVE_PPSAPI 223 /* 224 * nmea_control - fudge control 225 */ 226 static void 227 nmea_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 */ 232 ) 233 { 234 struct refclockproc *pp; 235 236 pp = peer->procptr; 237 nmea_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2, 238 pp->sloppyclockflag & CLK_FLAG3); 239 } 240 241 242 /* 243 * Initialize PPSAPI 244 */ 245 int 246 nmea_ppsapi( 247 struct peer *peer, /* peer structure pointer */ 248 int enb_clear, /* clear enable */ 249 int enb_hardpps /* hardpps enable */ 250 ) 251 { 252 struct refclockproc *pp; 253 struct nmeaunit *up; 254 int capability; 255 256 pp = peer->procptr; 257 up = (struct nmeaunit *)pp->unitptr; 258 if (time_pps_getcap(up->handle, &capability) < 0) { 259 msyslog(LOG_ERR, 260 "refclock_nmea: time_pps_getcap failed: %m"); 261 return (0); 262 } 263 memset(&up->pps_params, 0, sizeof(pps_params_t)); 264 if (enb_clear) 265 up->pps_params.mode = capability & PPS_CAPTURECLEAR; 266 else 267 up->pps_params.mode = capability & PPS_CAPTUREASSERT; 268 if (!up->pps_params.mode) { 269 msyslog(LOG_ERR, 270 "refclock_nmea: invalid capture edge %d", 271 !enb_clear); 272 return (0); 273 } 274 up->pps_params.mode |= PPS_TSFMT_TSPEC; 275 if (time_pps_setparams(up->handle, &up->pps_params) < 0) { 276 msyslog(LOG_ERR, 277 "refclock_nmea: time_pps_setparams failed: %m"); 278 return (0); 279 } 280 if (enb_hardpps) { 281 if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS, 282 up->pps_params.mode & ~PPS_TSFMT_TSPEC, 283 PPS_TSFMT_TSPEC) < 0) { 284 msyslog(LOG_ERR, 285 "refclock_nmea: time_pps_kcbind failed: %m"); 286 return (0); 287 } 288 pps_enable = 1; 289 } 290 peer->precision = PPS_PRECISION; 291 292 #if DEBUG 293 if (debug) { 294 time_pps_getparams(up->handle, &up->pps_params); 295 printf( 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); 299 } 300 #endif 301 302 return (1); 303 } 304 305 /* 306 * Get PPSAPI timestamps. 307 * 308 * Return 0 on failure and 1 on success. 309 */ 310 static int 311 nmea_pps( 312 struct nmeaunit *up, 313 l_fp *tsptr 314 ) 315 { 316 pps_info_t pps_info; 317 struct timespec timeout, ts; 318 double dtemp; 319 l_fp tstmp; 320 321 /* 322 * Convert the timespec nanoseconds field to ntp l_fp units. 323 */ 324 if (up->handle == 0) 325 return (0); 326 timeout.tv_sec = 0; 327 timeout.tv_nsec = 0; 328 memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t)); 329 if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info, 330 &timeout) < 0) 331 return (0); 332 if (up->pps_params.mode & PPS_CAPTUREASSERT) { 333 if (pps_info.assert_sequence == 334 up->pps_info.assert_sequence) 335 return (0); 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) 340 return (0); 341 ts = up->pps_info.clear_timestamp; 342 } else { 343 return (0); 344 } 345 if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec)) 346 return (0); 347 up->ts = ts; 348 349 tstmp.l_ui = ts.tv_sec + JAN_1970; 350 dtemp = ts.tv_nsec * FRAC / 1e9; 351 tstmp.l_uf = (u_int32)dtemp; 352 *tsptr = tstmp; 353 return (1); 354 } 355 #endif /* HAVE_PPSAPI */ 356 357 /* 358 * nmea_receive - receive data from the serial interface 359 */ 360 static void 361 nmea_receive( 362 struct recvbuf *rbufp 363 ) 364 { 365 register struct nmeaunit *up; 366 struct refclockproc *pp; 367 struct peer *peer; 368 int month, day; 369 int i; 370 char *cp, *dp; 371 int cmdtype; 372 /* Use these variables to hold data until we decide its worth keeping */ 373 char rd_lastcode[BMAX]; 374 l_fp rd_tmp; 375 u_short rd_lencode; 376 377 /* 378 * Initialize pointers and read the timecode and timestamp 379 */ 380 peer = (struct peer *)rbufp->recv_srcclock; 381 pp = peer->procptr; 382 up = (struct nmeaunit *)pp->unitptr; 383 rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp); 384 385 /* 386 * There is a case that a <CR><LF> gives back a "blank" line 387 */ 388 if (rd_lencode == 0) 389 return; 390 391 #ifdef DEBUG 392 if (debug) 393 printf("nmea: gpsread %d %s\n", rd_lencode, 394 rd_lastcode); 395 #endif 396 397 /* 398 * We check the timecode format and decode its contents. The 399 * we only care about a few of them. The most important being 400 * the $GPRMC format 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 406 * $GPRMB,... 407 * $GPRMC,232418.19,A,3513.8386,S,14900.7853,E,00.0,000.0,121199,12.,E*77 408 * $GPAPB,... 409 * $GPGSA,... 410 * $GPGSV,... 411 * $GPGSV,... 412 */ 413 #define GPXXX 0 414 #define GPRMC 1 415 #define GPGGA 2 416 #define GPGLL 4 417 cp = rd_lastcode; 418 cmdtype=0; 419 if(strncmp(cp,"$GPRMC",6)==0) { 420 cmdtype=GPRMC; 421 } 422 else if(strncmp(cp,"$GPGGA",6)==0) { 423 cmdtype=GPGGA; 424 } 425 else if(strncmp(cp,"$GPGLL",6)==0) { 426 cmdtype=GPGLL; 427 } 428 else if(strncmp(cp,"$GPXXX",6)==0) { 429 cmdtype=GPXXX; 430 } 431 else 432 return; 433 434 435 /* See if I want to process this message type */ 436 if ( ((peer->ttlmax == 0) && (cmdtype != GPRMC)) 437 || ((peer->ttlmax != 0) && !(cmdtype & peer->ttlmax)) ) 438 return; 439 440 pp->lencode = rd_lencode; 441 strcpy(pp->a_lastcode,rd_lastcode); 442 cp = pp->a_lastcode; 443 444 pp->lastrec = up->tstamp = rd_tmp; 445 up->pollcnt = 2; 446 447 #ifdef DEBUG 448 if (debug) 449 printf("nmea: timecode %d %s\n", pp->lencode, 450 pp->a_lastcode); 451 #endif 452 453 454 /* Grab field depending on clock string type */ 455 switch( cmdtype ) { 456 case GPRMC: 457 /* 458 * Test for synchronization. Check for quality byte. 459 */ 460 dp = field_parse(cp,2); 461 if( dp[0] != 'A') 462 pp->leap = LEAP_NOTINSYNC; 463 else 464 pp->leap = LEAP_NOWARNING; 465 466 /* Now point at the time field */ 467 dp = field_parse(cp,1); 468 break; 469 470 471 case GPGGA: 472 /* 473 * Test for synchronization. Check for quality byte. 474 */ 475 dp = field_parse(cp,6); 476 if( dp[0] == '0') 477 pp->leap = LEAP_NOTINSYNC; 478 else 479 pp->leap = LEAP_NOWARNING; 480 481 /* Now point at the time field */ 482 dp = field_parse(cp,1); 483 break; 484 485 486 case GPGLL: 487 /* 488 * Test for synchronization. Check for quality byte. 489 */ 490 dp = field_parse(cp,6); 491 if( dp[0] != 'A') 492 pp->leap = LEAP_NOTINSYNC; 493 else 494 pp->leap = LEAP_NOWARNING; 495 496 /* Now point at the time field */ 497 dp = field_parse(cp,5); 498 break; 499 500 501 case GPXXX: 502 return; 503 default: 504 return; 505 506 } 507 508 /* 509 * Check time code format of NMEA 510 */ 511 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]) || 517 !isdigit((int)dp[5]) 518 ) { 519 refclock_report(peer, CEVNT_BADREPLY); 520 return; 521 } 522 523 524 /* 525 * Convert time and check values. 526 */ 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 532 */ 533 pp->msec = 0; 534 if (dp[6] == '.') { 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'); 541 } 542 } 543 } 544 } 545 546 if (pp->hour > 23 || pp->minute > 59 || pp->second > 59 547 || pp->msec > 1000) { 548 refclock_report(peer, CEVNT_BADTIME); 549 return; 550 } 551 552 553 /* 554 * Convert date and check values. 555 */ 556 if (cmdtype==GPRMC) { 557 dp = field_parse(cp,9); 558 day = dp[0] - '0'; 559 day = (day * 10) + dp[1] - '0'; 560 month = dp[2] - '0'; 561 month = (month * 10) + dp[3] - '0'; 562 pp->year = dp[4] - '0'; 563 pp->year = (pp->year * 10) + dp[5] - '0'; 564 } 565 else { 566 /* only time */ 567 time_t tt = time(NULL); 568 struct tm * t = gmtime(&tt); 569 day = t->tm_mday; 570 month = t->tm_mon + 1; 571 pp->year= t->tm_year; 572 } 573 574 if (month < 1 || month > 12 || day < 1) { 575 refclock_report(peer, CEVNT_BADTIME); 576 return; 577 } 578 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 */ 582 if (pp->year % 4) { 583 if (day > day1tab[month - 1]) { 584 refclock_report(peer, CEVNT_BADTIME); 585 return; 586 } 587 for (i = 0; i < month - 1; i++) 588 day += day1tab[i]; 589 } else { 590 if (day > day2tab[month - 1]) { 591 refclock_report(peer, CEVNT_BADTIME); 592 return; 593 } 594 for (i = 0; i < month - 1; i++) 595 day += day2tab[i]; 596 } 597 pp->day = day; 598 599 600 #ifdef HAVE_PPSAPI 601 /* 602 * If the PPSAPI is working, rather use its timestamps. 603 * assume that the PPS occurs on the second so blow any msec 604 */ 605 if (nmea_pps(up, &rd_tmp) == 1) { 606 pp->lastrec = up->tstamp = rd_tmp; 607 pp->msec = 0; 608 } 609 #endif /* HAVE_PPSAPI */ 610 611 /* 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 617 * the data. 618 */ 619 620 if (!refclock_process(pp)) { 621 refclock_report(peer, CEVNT_BADTIME); 622 return; 623 } 624 625 626 627 /* 628 * Only go on if we had been polled. 629 */ 630 if (!up->polled) 631 return; 632 up->polled = 0; 633 634 refclock_receive(peer); 635 636 /* If we get here - what we got from the clock is OK, so say so */ 637 refclock_report(peer, CEVNT_NOMINAL); 638 639 record_clock_stats(&peer->srcadr, pp->a_lastcode); 640 641 } 642 643 /* 644 * nmea_poll - called by the transmit procedure 645 * 646 * We go to great pains to avoid changing state here, since there may be 647 * more than one eavesdropper receiving the same timecode. 648 */ 649 static void 650 nmea_poll( 651 int unit, 652 struct peer *peer 653 ) 654 { 655 register struct nmeaunit *up; 656 struct refclockproc *pp; 657 658 pp = peer->procptr; 659 up = (struct nmeaunit *)pp->unitptr; 660 if (up->pollcnt == 0) 661 refclock_report(peer, CEVNT_TIMEOUT); 662 else 663 up->pollcnt--; 664 pp->polls++; 665 up->polled = 1; 666 667 /* 668 * usually nmea_receive can get a timestamp every second 669 */ 670 671 gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer); 672 } 673 674 /* 675 * 676 * gps_send(fd,cmd, peer) Sends a command to the GPS receiver. 677 * as gps_send(fd,"rqts,u\r", peer); 678 * 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 683 * 684 */ 685 static void 686 gps_send( 687 int fd, 688 const char *cmd, 689 struct peer *peer 690 ) 691 { 692 693 if (write(fd, cmd, strlen(cmd)) == -1) { 694 refclock_report(peer, CEVNT_FAULT); 695 } 696 } 697 698 static char * 699 field_parse( 700 char *cp, 701 int fn 702 ) 703 { 704 char *tp; 705 int i = fn; 706 707 for (tp = cp; *tp != '\0'; tp++) { 708 if (*tp == ',') 709 i--; 710 if (i == 0) 711 break; 712 } 713 return (++tp); 714 } 715 #else 716 int refclock_nmea_bs; 717 #endif /* REFCLOCK */ 718