Lines Matching +full:min +full:- +full:sample +full:- +full:time +full:- +full:ns

2  * refclock_nmea.c - clock driver for an NMEA GPS CLOCK
51 * This driver supports NMEA-compatible GPS receivers
57 * filled with rapids and whirlpools that rip away your data and warp time.
71 * bit 0 - enables RMC (1)
72 * bit 1 - enables GGA (2)
73 * bit 2 - enables GLL (4)
74 * bit 3 - enables ZDA (8) - Standard Time & Date
75 * bit 3 - enables ZDG (8) - Accord GPS Clock's custom sentence with GPS time
80 * bit 4/5/6 - selects the baudrate for serial port :
99 #define NMEA_PROTO_MINLEN 6 /* min chars in sentence, excluding CS */
114 * Defining GPZDA to support Standard Time & Date
117 * $--ZDA,HHMMSS.SS,DD,MM,YYYY,TH,TM,*CS<CR><LF>
120 * 'TH' Time zone Hours
121 * 'TM' Time zone Minutes
132 * '0' indicates INVALID time,
133 * '1' indicates accuracy of +/-20 ms
134 * '2' indicates accuracy of +/-100 ns
137 * $PGRMF,WN,WS,DATE,TIME,LS,LAT,LAT_DIR,LON,LON_DIR,MODE,FIX,SPD,DIR,PDOP,TDOP
138 * WN -- GPS week number (weeks since 1980-01-06, mod 1024)
139 * WS -- GPS seconds in week
140 * LS -- GPS leap seconds, accumulated ( UTC + LS == GPS )
141 * FIX -- Fix type: 0=nofix, 1=2D, 2=3D
142 * DATE/TIME are standard date/time strings in UTC time scale
144 * The GPS time can be used to get the full century for the truncated
154 #define PRECISION (-9) /* precision assumed (about 2 ms) */
155 #define PPS_PRECISION (-20) /* precision assumed (about 1 us) */
173 #define NMEA_GPRMC 0 /* recommended min. nav. */
176 #define NMEA_GPZDA 3 /* date/time */
181 * isolated from other NTP networks, as it operates in GPS time, not
182 * UTC as is much more common. GPS time is >15 seconds different from
215 DATE_1_DDMMYY, /* use 1 field with 2-digit year */
216 DATE_3_DDMMYYYY /* use 3 fields with 4-digit year */
222 DTYP_Y2D, /* 2-digit year */
223 DTYP_W10B, /* 10-bit week in GPS epoch */
224 DTYP_Y4D, /* 4-digit (full) year */
233 #define CHECK_EMPTY -1 /* no data */
250 uint16_t rcvtout; /* one-shot for sample expiration */
252 u_char gps_time; /* use GPS time, not UTC */
254 TNtpDatum last_gpsdate; /* last processed split date/time */
263 u_int malformed; /* Bad checksum, invalid date or time */
320 * If we want the driver to output sentences, too: re-enable the send
321 * support functions by defining NMEA_WRITE_SUPPORT to non-zero...
328 * -------------------------------------------------------------------
330 * -------------------------------------------------------------------
344 * -------------------------------------------------------------------
345 * nmea_start - open the GPS devices and initialize data for processing
350 * -------------------------------------------------------------------
358 struct refclockproc * const pp = peer->procptr; in nmea_start()
366 rate = (peer->ttl & NMEA_BAUDRATE_MASK) >> NMEA_BAUDRATE_SHIFT; in nmea_start()
395 pp->unitptr = (caddr_t)up; in nmea_start()
396 pp->io.fd = -1; in nmea_start()
397 pp->io.clock_recv = nmea_receive; in nmea_start()
398 pp->io.srcclock = peer; in nmea_start()
399 pp->io.datalen = 0; in nmea_start()
401 memset(&up->last_reftime, 0xFF, sizeof(up->last_reftime)); in nmea_start()
402 memset(&up->last_gpsdate, 0x00, sizeof(up->last_gpsdate)); in nmea_start()
404 up->cksum_type[NMEA_GPRMC] = CHECK_CSVALID; in nmea_start()
406 up->ppsapi_fd = -1; in nmea_start()
408 ZERO(up->tally); in nmea_start()
411 peer->precision = PRECISION; in nmea_start()
412 pp->clockdesc = DESCRIPTION; in nmea_start()
413 memcpy(&pp->refid, REFID, 4); in nmea_start()
419 refnumtoa(&peer->srcadr)); in nmea_start()
422 pp->io.fd = refclock_open(&peer->srcadr, device, baudrate, LDISC_CLK); in nmea_start()
423 if (0 >= pp->io.fd) { in nmea_start()
424 pp->io.fd = nmead_open(device); in nmea_start()
425 if (-1 == pp->io.fd) in nmea_start()
430 return io_addclock(&pp->io) != 0; in nmea_start()
434 * -------------------------------------------------------------------
435 * nmea_shutdown - shut down a GPS clock
439 * -------------------------------------------------------------------
447 struct refclockproc * const pp = peer->procptr; in nmea_shutdown()
448 nmea_unit * const up = (nmea_unit *)pp->unitptr; in nmea_shutdown()
454 if (up->ppsapi_lit) in nmea_shutdown()
455 time_pps_destroy(up->atom.handle); in nmea_shutdown()
456 ppsdev_close(pp->io.fd, up->ppsapi_fd); in nmea_shutdown()
460 pp->unitptr = (caddr_t)NULL; in nmea_shutdown()
461 if (-1 != pp->io.fd) in nmea_shutdown()
462 io_closeclock(&pp->io); in nmea_shutdown()
463 pp->io.fd = -1; in nmea_shutdown()
467 * -------------------------------------------------------------------
468 * nmea_control - configure fudge params
469 * -------------------------------------------------------------------
480 struct refclockproc * const pp = peer->procptr; in nmea_control()
481 nmea_unit * const up = (nmea_unit *)pp->unitptr; in nmea_control()
501 if ((CLK_FLAG1 & pp->sloppyclockflag) && !up->ppsapi_tried) { in nmea_control()
503 up->ppsapi_tried = TRUE; in nmea_control()
508 refnumtoa(&peer->srcadr)); in nmea_control()
511 up->ppsapi_fd = ppsdev_reopen( in nmea_control()
512 &peer->srcadr, in nmea_control()
513 pp->io.fd, up->ppsapi_fd, in nmea_control()
517 * - the clock is shut down in nmea_control()
518 * - flag1 is set again after being cleared in nmea_control()
520 if (refclock_ppsapi(up->ppsapi_fd, &up->atom)) { in nmea_control()
522 up->ppsapi_lit = refclock_params( in nmea_control()
523 pp->sloppyclockflag, &up->atom); in nmea_control()
524 if (!up->ppsapi_lit) { in nmea_control()
526 time_pps_destroy(up->atom.handle); in nmea_control()
529 refnumtoa(&peer->srcadr)); in nmea_control()
534 refnumtoa(&peer->srcadr)); in nmea_control()
539 if ( !(CLK_FLAG1 & pp->sloppyclockflag) && up->ppsapi_tried) { in nmea_control()
541 if (up->ppsapi_lit) in nmea_control()
542 time_pps_destroy(up->atom.handle); in nmea_control()
543 up->atom.handle = 0; in nmea_control()
547 up->ppsapi_gate = FALSE; in nmea_control()
548 up->ppsapi_lit = FALSE; in nmea_control()
549 up->ppsapi_tried = FALSE; in nmea_control()
551 peer->flags &= ~FLAG_PPS; in nmea_control()
552 peer->precision = PRECISION; in nmea_control()
558 * -------------------------------------------------------------------
559 * nmea_timer - called once per second
562 * least one Motorola unit needs prompting each time. Doing so in
563 * 'nmea_poll()' gives only one sample per poll cycle, which actually
567 * Also takes care of sample expiration if the receiver fails to
569 * -------------------------------------------------------------------
577 struct refclockproc * const pp = peer->procptr; in nmea_timer()
578 nmea_unit * const up = (nmea_unit *)pp->unitptr; in nmea_timer()
584 if (-1 != pp->io.fd) /* any mode bits to evaluate here? */ in nmea_timer()
585 gps_send(pp->io.fd, "$PMOTG,RMC,0000*1D\r\n", peer); in nmea_timer()
590 if (up->rcvtout) { in nmea_timer()
591 --up->rcvtout; in nmea_timer()
592 } else if (pp->codeproc != pp->coderecv) { in nmea_timer()
593 /* expire one (the oldest) sample, if any */ in nmea_timer()
596 up->lb_buf[0] = '\0'; in nmea_timer()
597 up->lb_len = 0; in nmea_timer()
600 if (up->hold_gpsdate && (--up->hold_gpsdate < DATE_HLIM)) in nmea_timer()
601 up->type_gpsdate = DTYP_NONE; in nmea_timer()
605 * -------------------------------------------------------------------
606 * nmea_procrec - receive data from the serial interface
613 * + it parses the time and date data from the NMEA data string and
617 * + it eventually replaces the receive time with the PPS edge time.
620 * This function assumes a non-empty line in the unit line buffer.
621 * -------------------------------------------------------------------
630 struct refclockproc * const pp = peer->procptr; in nmea_procrec()
631 nmea_unit * const up = (nmea_unit*)pp->unitptr; in nmea_procrec()
638 TCivilDate date; /* to keep & convert the time stamp */ in nmea_procrec()
639 TGpsDatum wgps; /* week time storage */ in nmea_procrec()
641 l_fp tofs; /* offset to full-second reftime */ in nmea_procrec()
642 /* results of sentence/date/time parsing */ in nmea_procrec()
666 checkres = field_init(&rdata, up->lb_buf, up->lb_len); in nmea_procrec()
671 refnumtoa(&peer->srcadr), up->lb_buf)); in nmea_procrec()
680 refnumtoa(&peer->srcadr), up->lb_len, in nmea_procrec()
681 up->lb_buf)); in nmea_procrec()
684 up->tally.total++; in nmea_procrec()
687 * --> below this point we have a valid NMEA sentence <-- in nmea_procrec()
713 if (peer->ttl & NMEA_DELAYMEAS_MASK) { in nmea_procrec()
714 mprintf_clock_stats(&peer->srcadr, "delay %0.6f %.*s", in nmea_procrec()
715 ldexp(rd_timestamp.l_uf, -32), in nmea_procrec()
716 (int)(strchr(up->lb_buf, ',') - up->lb_buf), in nmea_procrec()
717 up->lb_buf); in nmea_procrec()
721 if ((peer->ttl & NMEA_MESSAGE_MASK) && in nmea_procrec()
722 !(peer->ttl & sentence_mode[sentence])) { in nmea_procrec()
723 up->tally.filtered++; in nmea_procrec()
736 * preserve its error-detection capabilities with modern GPSes in nmea_procrec()
740 * checksum. ('up->cksum_type[NMEA_GPRMC]' is set in in nmea_procrec()
744 if (up->cksum_type[sentence] <= (u_char)checkres) { in nmea_procrec()
745 up->cksum_type[sentence] = (u_char)checkres; in nmea_procrec()
748 refnumtoa(&peer->srcadr), up->lb_buf)); in nmea_procrec()
750 up->tally.malformed++; in nmea_procrec()
755 * $GPZDG provides GPS time not UTC, and the two mix poorly. in nmea_procrec()
760 if (!up->gps_time) { in nmea_procrec()
762 "%s using GPS time as if it were UTC", in nmea_procrec()
763 refnumtoa(&peer->srcadr)); in nmea_procrec()
764 up->gps_time = 1; in nmea_procrec()
767 if (up->gps_time) { in nmea_procrec()
768 up->tally.filtered++; in nmea_procrec()
774 refnumtoa(&peer->srcadr), up->lb_len, up->lb_buf)); in nmea_procrec()
780 rc_date = -1; /* assume we have to do day-time mapping */ in nmea_procrec()
785 /* Check quality byte, fetch data & time */ in nmea_procrec()
787 pp->leap = parse_qual(&rdata, 2, 'A', 0); in nmea_procrec()
788 if (up->type_gpsdate <= DTYP_Y2D) { in nmea_procrec()
792 if (CLK_FLAG4 & pp->sloppyclockflag) in nmea_procrec()
793 field_wipe(&rdata, 3, 4, 5, 6, -1); in nmea_procrec()
797 /* Check quality byte, fetch time only */ in nmea_procrec()
799 pp->leap = parse_qual(&rdata, 6, '0', 1); in nmea_procrec()
800 if (CLK_FLAG4 & pp->sloppyclockflag) in nmea_procrec()
801 field_wipe(&rdata, 2, 4, -1); in nmea_procrec()
805 /* Check quality byte, fetch time only */ in nmea_procrec()
807 pp->leap = parse_qual(&rdata, 6, 'A', 0); in nmea_procrec()
808 if (CLK_FLAG4 & pp->sloppyclockflag) in nmea_procrec()
809 field_wipe(&rdata, 1, 3, -1); in nmea_procrec()
813 /* No quality. Assume best, fetch time & full date */ in nmea_procrec()
815 if (up->type_gpsdate <= DTYP_Y4D) { in nmea_procrec()
822 /* Check quality byte, fetch time & full date */ in nmea_procrec()
824 pp->leap = parse_qual(&rdata, 4, '0', 1); in nmea_procrec()
825 --tofs.l_ui; /* GPZDG gives *following* second */ in nmea_procrec()
826 if (up->type_gpsdate <= DTYP_Y4D) { in nmea_procrec()
833 /* get time, qualifier and GPS weektime. */ in nmea_procrec()
835 if (up->type_gpsdate <= DTYP_W10B) { in nmea_procrec()
839 pp->leap = parse_qual(&rdata, 11, '0', 1); in nmea_procrec()
840 if (CLK_FLAG4 & pp->sloppyclockflag) in nmea_procrec()
841 field_wipe(&rdata, 6, 8, -1); in nmea_procrec()
845 /* PUBX,04 is peculiar. The UTC time-of-week is the *internal* in nmea_procrec()
846 * time base, which is not exactly on par with the fix time. in nmea_procrec()
849 if (up->type_gpsdate <= DTYP_WEXT) { in nmea_procrec()
850 rc_date = parse_gpsw(&wgps, &rdata, 5, 4, -1); in nmea_procrec()
861 if (peer->ttl & NMEA_IGNSTATUS_MASK) { /* assume always good? */ in nmea_procrec()
862 pp->leap = LEAP_NOWARNING; in nmea_procrec()
866 if (pp->leap == LEAP_NOTINSYNC) { /* no good status? */ in nmea_procrec()
868 up->tally.rejected++; in nmea_procrec()
870 /* Check sanity of time-of-day. */ in nmea_procrec()
871 else if (rc_time == 0) { /* no time or conversion error? */ in nmea_procrec()
873 up->tally.malformed++; in nmea_procrec()
878 up->tally.malformed++; in nmea_procrec()
881 checkres = -1; in nmea_procrec()
884 if (checkres != -1) { in nmea_procrec()
885 refclock_save_lcode(pp, up->lb_buf, up->lb_len); in nmea_procrec()
890 /* See if we can augment the receive time stamp. If not, apply in nmea_procrec()
891 * fudge time 2 to the receive time stamp directly. in nmea_procrec()
894 if (up->ppsapi_lit && pp->leap != LEAP_NOTINSYNC) in nmea_procrec()
896 &up->atom, &rd_timestamp, in nmea_procrec()
897 pp->fudgetime2, pp->fudgetime1); in nmea_procrec()
901 rd_timestamp, pp->fudgetime2); in nmea_procrec()
904 warp = !(peer->ttl & NMEA_DATETRUST_MASK); in nmea_procrec()
907 refnumtoa(&peer->srcadr), rc_dtyp)); in nmea_procrec()
910 up->last_gpsdate = gpsntp_from_gpscal_ex( in nmea_procrec()
914 up->last_gpsdate = gpsntp_from_gpscal_ex( in nmea_procrec()
918 up->last_gpsdate = gpsntp_from_calendar_ex( in nmea_procrec()
922 up->type_gpsdate = rc_dtyp; in nmea_procrec()
923 up->hold_gpsdate = DATE_HOLD; in nmea_procrec()
925 /* now convert and possibly extend/expand the time stamp. */ in nmea_procrec()
926 if (up->hold_gpsdate) { /* time of day, based */ in nmea_procrec()
928 &date, tofs, &up->last_gpsdate, warp); in nmea_procrec()
929 } else { /* time of day, floating */ in nmea_procrec()
935 /* debug print time stamp */ in nmea_procrec()
939 refnumtoa(&peer->srcadr), in nmea_procrec()
944 refnumtoa(&peer->srcadr), in nmea_procrec()
949 /* Get the reference time stamp from the calendar buffer. in nmea_procrec()
950 * Process the new sample in the median filter and determine the in nmea_procrec()
952 * Discard sentence if reference time did not change. in nmea_procrec()
955 if (L_ISEQU(&up->last_reftime, &rd_reftime)) { in nmea_procrec()
956 /* Do not touch pp->a_lastcode on purpose! */ in nmea_procrec()
957 up->tally.filtered++; in nmea_procrec()
960 up->last_reftime = rd_reftime; in nmea_procrec()
963 refnumtoa(&peer->srcadr), up->lb_buf)); in nmea_procrec()
966 up->tally.accepted++; in nmea_procrec()
967 refclock_save_lcode(pp, up->lb_buf, up->lb_len); in nmea_procrec()
968 pp->lastrec = rd_timestamp; in nmea_procrec()
970 /* If we have PPS augmented receive time, we *must* have a in nmea_procrec()
975 up->ppsapi_gate = TRUE; in nmea_procrec()
976 peer->precision = PPS_PRECISION; in nmea_procrec()
978 if ( ! (peer->ttl & NMEA_QUIETPPS_MASK)) in nmea_procrec()
979 peer->flags |= FLAG_PPS; in nmea_procrec()
981 refnumtoa(&peer->srcadr))); in nmea_procrec()
982 up->tally.pps_used++; in nmea_procrec()
985 refnumtoa(&peer->srcadr))); in nmea_procrec()
990 /* Whether the receive time stamp is PPS-augmented or not, in nmea_procrec()
995 up->rcvtout = 2; in nmea_procrec()
999 * -------------------------------------------------------------------
1000 * nmea_receive - receive data from the serial interface
1005 * not line oriented, and there's no one to do the line-splitting work
1016 * record processor every time we hit a CR/LF, provided the resulting
1020 * previous line-oriented input: One line is copied to the buffer and
1024 * -------------------------------------------------------------------
1032 struct peer * const peer = rbufp->recv_peer; in nmea_receive()
1033 struct refclockproc * const pp = peer->procptr; in nmea_receive()
1034 nmea_unit * const up = (nmea_unit*)pp->unitptr; in nmea_receive()
1040 if (up->lb_len >= sizeof(up->lb_buf)) in nmea_receive()
1041 up->lb_len = 0; in nmea_receive()
1044 dp = up->lb_buf + up->lb_len; in nmea_receive()
1045 de = up->lb_buf + sizeof(up->lb_buf) - 1; in nmea_receive()
1047 sp = (const char *)rbufp->recv_buffer; in nmea_receive()
1048 se = sp + rbufp->recv_length; in nmea_receive()
1052 * complete non-empty line. in nmea_receive()
1056 if (dp == up->lb_buf) { in nmea_receive()
1060 dp = up->lb_buf; in nmea_receive()
1063 up->lb_len = (int)(dp - up->lb_buf); in nmea_receive()
1064 dp = up->lb_buf; in nmea_receive()
1065 nmea_procrec(peer, rbufp->recv_time); in nmea_receive()
1072 up->lb_len = (int)(dp - up->lb_buf); in nmea_receive()
1076 * -------------------------------------------------------------------
1077 * nmea_poll - called by the transmit procedure
1084 * -------------------------------------------------------------------
1092 struct refclockproc * const pp = peer->procptr; in nmea_poll()
1093 nmea_unit * const up = (nmea_unit *)pp->unitptr; in nmea_poll()
1101 * If we don't have PPS pulses and time stamps, turn PPS down in nmea_poll()
1104 if (!up->ppsapi_gate) { in nmea_poll()
1105 peer->flags &= ~FLAG_PPS; in nmea_poll()
1106 peer->precision = PRECISION; in nmea_poll()
1108 up->ppsapi_gate = FALSE; in nmea_poll()
1116 if (pp->coderecv == pp->codeproc) { in nmea_poll()
1117 peer->flags &= ~FLAG_PPS; in nmea_poll()
1118 if (pp->currentstatus < CEVNT_TIMEOUT) in nmea_poll()
1120 memset(&up->last_gpsdate, 0, sizeof(up->last_gpsdate)); in nmea_poll()
1122 pp->polls++; in nmea_poll()
1123 pp->lastref = pp->lastrec; in nmea_poll()
1125 if (pp->currentstatus > CEVNT_NOMINAL) in nmea_poll()
1134 if (peer->ttl & NMEA_EXTLOG_MASK) { in nmea_poll()
1136 const char *nmea = pp->a_lastcode; in nmea_poll()
1139 &peer->srcadr, "%s %u %u %u %u %u %u", in nmea_poll()
1141 up->tally.total, up->tally.accepted, in nmea_poll()
1142 up->tally.rejected, up->tally.malformed, in nmea_poll()
1143 up->tally.filtered, up->tally.pps_used); in nmea_poll()
1145 record_clock_stats(&peer->srcadr, pp->a_lastcode); in nmea_poll()
1147 ZERO(up->tally); in nmea_poll()
1152 * -------------------------------------------------------------------
1164 * time. Without a PPS output, we're Just fooling ourselves because of
1166 * -------------------------------------------------------------------
1187 len = end - beg; in gps_send()
1193 refnumtoa(&peer->srcadr), cmd)); in gps_send()
1201 DPRINTF(1, ("%s gps_send: '%.*s'\n", refnumtoa(&peer->srcadr), in gps_send()
1202 len - 2, cmd)); in gps_send()
1211 * -------------------------------------------------------------------
1213 * -------------------------------------------------------------------
1219 * 8-bit XOR of characters between $ and * noninclusive is transmitted
1241 * -------------------------------------------------------------------
1264 data->base = cptr; in field_init()
1265 data->cptr = cptr; in field_init()
1266 data->cidx = 0; in field_init()
1267 data->blen = dlen; in field_init()
1272 * regex equiv: '^\$[A-Z][A-Z0-9]{4,}[^*]*(\*[0-9A-F]{2})?$' in field_init()
1275 /* -*- start character: '^\$' */ in field_init()
1281 /* -*- advance context beyond start character */ in field_init()
1282 data->base++; in field_init()
1283 data->cptr++; in field_init()
1284 data->blen--; in field_init()
1286 /* -*- field name: '[A-Z][A-Z0-9]{4,},' */ in field_init()
1293 if (*cptr != ',' || (cptr - data->base) < NMEA_PROTO_IDLEN) in field_init()
1297 /* -*- data: '[^*]*' */ in field_init()
1301 /* -*- checksum field: (\*[0-9A-F]{2})?$ */ in field_init()
1304 if (*cptr != '*' || cptr != eptr - 3 || in field_init()
1305 (cptr - data->base) >= NMEA_PROTO_MAXLEN) in field_init()
1310 cs_r = (cs_r << 4) + (tmp - '0'); in field_init()
1312 cs_r = (cs_r << 4) + (tmp - 'A' + 10); in field_init()
1317 /* -*- make sure we are at end of string and csum matches */ in field_init()
1325 * -------------------------------------------------------------------
1331 * -------------------------------------------------------------------
1341 if (fn < data->cidx) { in field_parse()
1342 data->cidx = 0; in field_parse()
1343 data->cptr = data->base; in field_parse()
1345 while ((fn > data->cidx) && (tmp = *data->cptr) != '\0') { in field_parse()
1346 data->cidx += (tmp == ','); in field_parse()
1347 data->cptr++; in field_parse()
1349 return data->cptr; in field_parse()
1353 * -------------------------------------------------------------------
1364 * ntpq -c clockvar <server>
1368 * location in clockstats over time as as a proxy for the quality of
1369 * GPS reception and thereby time reported.
1370 * -------------------------------------------------------------------
1380 int fidx; /* field to nuke, or -1 for checksum */ in field_wipe()
1391 cp = data->base + data->blen; in field_wipe()
1392 if (data->blen >= 3 && cp[-3] == '*') in field_wipe()
1393 cp -= 2; in field_wipe()
1398 } while (fcnt-- && fidx >= 0); in field_wipe()
1403 * -------------------------------------------------------------------
1405 * -------------------------------------------------------------------
1417 while (--nfields && ep && *ep == ',') in field_length()
1420 ? (int)((UCC*)ep - cp) in field_length()
1425 /* /[,*\r\n]/ --> skip */
1433 /* /,/ --> skip */
1441 /* /[[:digit:]]{2}/ --> uint16_t */
1447 *into = (cp[0] - '0') * 10 + (cp[1] - '0'); in _parse_num2d()
1455 /* /[[:digit:]]+/ --> uint16_t */
1463 num = (num * 10) + (*cp - '0'); in _parse_u16()
1464 while (isdigit(*++cp) && --ndig); in _parse_u16()
1471 /* /[[:digit:]]+/ --> uint32_t */
1479 num = (num * 10) + (*cp - '0'); in _parse_u32()
1480 while (isdigit(*++cp) && --ndig); in _parse_u32()
1487 /* /(\.[[:digit:]]*)?/ --> l_fp{0, f}
1491 * away but silently ignored. (--> truncation to 1 nanosecond)
1508 ts.tv_nsec = fval * powtab[(size_t)(cp - sp)]; in _parse_frac()
1518 /* /[[:digit:]]{6}/ --> time-of-day
1532 into->hour = (uint8_t)h; in _parse_time()
1533 into->minute = (uint8_t)m; in _parse_time()
1534 into->second = (uint8_t)s; in _parse_time()
1538 DPRINTF(1, ("nmea: invalid time code: '%.*s'\n", in _parse_time()
1544 /* /[[:digit:]]{6}/ --> civil date
1553 rc = _parse_num2d(cp, &cp, &d) && (d - 1 < 31) in _parse_date1()
1554 && _parse_num2d(cp, &cp, &m) && (m - 1 < 12) in _parse_date1()
1558 into->monthday = (uint8_t )d; in _parse_date1()
1559 into->month = (uint8_t )m; in _parse_date1()
1560 into->year = (uint16_t)y; in _parse_date1()
1570 /* /[[:digit:]]+,[[:digit:]]+,[[:digit:]]+/ --> civil date
1579 rc = _parse_u16(cp, &cp, &d, 2) && (d - 1 < 31) in _parse_date3()
1581 && _parse_u16(cp, &cp, &m, 2) && (m - 1 < 12) in _parse_date3()
1586 into->monthday = (uint8_t )d; in _parse_date3()
1587 into->month = (uint8_t )m; in _parse_date3()
1588 into->year = (uint16_t)y; in _parse_date3()
1599 * -------------------------------------------------------------------
1606 * -------------------------------------------------------------------
1625 * -------------------------------------------------------------------
1626 * Parse a time stamp in HHMMSS[.sss] format with error checking.
1629 * -------------------------------------------------------------------
1647 * -------------------------------------------------------------------
1654 * -------------------------------------------------------------------
1679 * -------------------------------------------------------------------
1680 * Parse GPS week time info from an NMEA sentence. This info contains
1681 * the GPS week number, the GPS time-of-week and the leap seconds GPS
1685 * -------------------------------------------------------------------
1716 fofs.l_ui -= leap; in parse_gpsw()
1746 * See http://home.hiwaay.net/~taylorc/gps/nmea-server/
1752 * ln -s server:port /dev/gps1
1755 * (perlinger-at-ntp-dot-org)
1764 int fd = -1; /* result file descriptor */ in nmead_open()
1775 fd = -1; in nmead_open()
1803 for (ai = ai_list; ai && (fd == -1); ai = ai->ai_next) { in nmead_open()
1804 sh = socket(ai->ai_family, ai->ai_socktype, in nmead_open()
1805 ai->ai_protocol); in nmead_open()
1808 rc = connect(sh, ai->ai_addr, ai->ai_addrlen); in nmead_open()
1809 if (-1 != rc) in nmead_open()
1815 if (fd != -1) in nmead_open()
1818 fd = -1; in nmead_open()