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)
19 #include "ntp_refclock.h"
20 #include "ntp_stdlib.h"
23 * This driver supports the NMEA GPS Receiver with
25 * Protype was refclock_trak.c, Thanks a lot.
27 * The receiver used spits out the NMEA sentences for boat navigation.
28 * And you thought it was an information superhighway. Try a raging river
29 * filled with rapids and whirlpools that rip away your data and warp time.
36 # define DEVICE "COM%d:" /* COM 1 - 3 supported */
38 # define DEVICE "/dev/gps%d" /* name of radio device */
40 #define SPEED232 B4800 /* uart speed (4800 bps) */
41 #define PRECISION (-9) /* precision assumed (about 2 ms) */
42 #define DCD_PRECISION (-20) /* precision assumed (about 1 us) */
43 #define REFID "GPS\0" /* reference id */
44 #define DESCRIPTION "NMEA GPS Clock" /* who we are */
46 #define LENNMEA 75 /* min timecode length */
49 * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
52 static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
53 static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
56 * Unit control structure
59 int pollcnt; /* poll message counter */
60 int polled; /* Hand in a sample? */
61 l_fp tstamp; /* timestamp of last poll */
67 static int nmea_start P((int, struct peer *));
68 static void nmea_shutdown P((int, struct peer *));
69 static void nmea_receive P((struct recvbuf *));
70 static void nmea_poll P((int, struct peer *));
71 static void gps_send P((int, const char *, struct peer *));
72 static char *field_parse P((char *, int));
77 struct refclock refclock_nmea = {
78 nmea_start, /* start up driver */
79 nmea_shutdown, /* shut down driver */
80 nmea_poll, /* transmit poll message */
81 noentry, /* handle control */
82 noentry, /* initialize driver */
83 noentry, /* buginfo */
84 NOFLAGS /* not used */
88 * nmea_start - open the GPS devices and initialize data for processing
96 register struct nmeaunit *up;
97 struct refclockproc *pp;
102 * Open serial port. Use CLK line discipline, if available.
104 (void)sprintf(device, DEVICE, unit);
106 if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
110 * Allocate and initialize unit structure
112 if (!(up = (struct nmeaunit *)
113 emalloc(sizeof(struct nmeaunit)))) {
117 memset((char *)up, 0, sizeof(struct nmeaunit));
119 pp->io.clock_recv = nmea_receive;
120 pp->io.srcclock = (caddr_t)peer;
123 if (!io_addclock(&pp->io)) {
128 pp->unitptr = (caddr_t)up;
131 * Initialize miscellaneous variables
133 peer->precision = DCD_PRECISION;
134 pp->clockdesc = DESCRIPTION;
135 memcpy((char *)&pp->refid, REFID, 4);
137 gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer);
143 * nmea_shutdown - shut down a GPS clock
151 register struct nmeaunit *up;
152 struct refclockproc *pp;
155 up = (struct nmeaunit *)pp->unitptr;
156 io_closeclock(&pp->io);
161 * nmea_receive - receive data from the serial interface
165 struct recvbuf *rbufp
168 register struct nmeaunit *up;
169 struct refclockproc *pp;
178 * Initialize pointers and read the timecode and timestamp
180 peer = (struct peer *)rbufp->recv_srcclock;
182 up = (struct nmeaunit *)pp->unitptr;
183 pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
186 * There is a case that a <CR><LF> gives back a "blank" line
188 if (pp->lencode == 0)
192 * We get a buffer and timestamp for each <cr>.
194 pp->lastrec = up->tstamp = trtmp;
198 printf("nmea: timecode %d %s\n", pp->lencode,
203 * We check the timecode format and decode its contents. The
204 * we only care about a few of them. The most important being
206 * $GPRMC,hhmmss,a,fddmm.xx,n,dddmmm.xx,w,zz.z,yyy.,ddmmyy,dd,v*CC
207 * $GPGGA,162617.0,4548.339,N,00837.719,E,1,07,0.97,00262,M,048,M,,*5D
214 if(strncmp(cp,"$GPRMC",6)==0) {
217 else if(strncmp(cp,"$GPGGA",6)==0) {
220 else if(strncmp(cp,"$GPXXX",6)==0) {
230 * Check time code format of NMEA
233 dp = field_parse(cp,1);
234 if( !isdigit((int)dp[0]) ||
235 !isdigit((int)dp[1]) ||
236 !isdigit((int)dp[2]) ||
237 !isdigit((int)dp[3]) ||
238 !isdigit((int)dp[4]) ||
241 refclock_report(peer, CEVNT_BADREPLY);
246 * Test for synchronization. Check for quality byte.
248 dp = field_parse(cp,2);
250 refclock_report(peer, CEVNT_BADREPLY);
261 if (cmdtype ==GPGCA) {
263 time_t tt = time(NULL);
264 struct tm * t = gmtime(&tt);
266 month = t->tm_mon + 1;
267 pp->year= t->tm_year;
269 dp = field_parse(cp,9);
271 * Convert date and check values.
274 day = (day * 10) + dp[1] - '0';
276 month = (month * 10) + dp[3] - '0';
277 pp->year = dp[4] - '0';
278 pp->year = (pp->year * 10) + dp[5] - '0';
281 if (month < 1 || month > 12 || day < 1) {
282 refclock_report(peer, CEVNT_BADTIME);
287 if (day > day1tab[month - 1]) {
288 refclock_report(peer, CEVNT_BADTIME);
291 for (i = 0; i < month - 1; i++)
294 if (day > day2tab[month - 1]) {
295 refclock_report(peer, CEVNT_BADTIME);
298 for (i = 0; i < month - 1; i++)
303 dp = field_parse(cp,1);
305 * Convert time and check values.
307 pp->hour = ((dp[0] - '0') * 10) + dp[1] - '0';
308 pp->minute = ((dp[2] - '0') * 10) + dp[3] - '0';
309 pp->second = ((dp[4] - '0') * 10) + dp[5] - '0';
312 if (pp->hour > 23 || pp->minute > 59 || pp->second > 59) {
313 refclock_report(peer, CEVNT_BADTIME);
318 * Process the new sample in the median filter and determine the
319 * reference clock offset and dispersion. We use lastrec as both
320 * the reference time and receive time, in order to avoid being
321 * cute, like setting the reference time later than the receive
322 * time, which may cause a paranoid protocol module to chuck out
325 if (!refclock_process(pp)) {
326 refclock_report(peer, CEVNT_BADTIME);
331 * Only go on if we had been polled.
337 refclock_receive(peer);
339 record_clock_stats(&peer->srcadr, pp->a_lastcode);
343 * nmea_poll - called by the transmit procedure
345 * We go to great pains to avoid changing state here, since there may be
346 * more than one eavesdropper receiving the same timecode.
354 register struct nmeaunit *up;
355 struct refclockproc *pp;
358 up = (struct nmeaunit *)pp->unitptr;
359 if (up->pollcnt == 0)
360 refclock_report(peer, CEVNT_TIMEOUT);
367 * usually nmea_receive can get a timestamp every second
370 gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer);
375 * gps_send(fd,cmd, peer) Sends a command to the GPS receiver.
376 * as gps_send(fd,"rqts,u\r", peer);
378 * We don't currently send any data, but would like to send
379 * RTCM SC104 messages for differential positioning. It should
380 * also give us better time. Without a PPS output, we're
381 * Just fooling ourselves because of the serial code paths
392 if (write(fd, cmd, strlen(cmd)) == -1) {
393 refclock_report(peer, CEVNT_FAULT);
406 for (tp = cp; *tp != '\0'; tp++) {
415 int refclock_nmea_bs;
416 #endif /* REFCLOCK */