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