<caption>mode byte bits and bit groups</caption>
<tbody><tr>
<th align="center">Bit</th>
- <th align="center">Dec.</th>
+ <th align="center">Decimal</th>
+ <th align="center">Hex</th>
<th align="left">Meaning</th>
</tr>
<tr>
<td align="center">0</td>
<td align="center">1</td>
+ <td align="center">1</td>
<td>process <tt>$GPMRC</tt></td>
</tr><tr>
<td align="center">1</td>
<td align="center">2</td>
+ <td align="center">2</td>
<td>process <tt>$GPGGA</tt></td>
</tr><tr>
<td align="center">2</td>
<td align="center">4</td>
+ <td align="center">4</td>
<td>process <tt>$GPGLL</tt></td>
</tr><tr>
<td align="center">3</td>
<td align="center">8</td>
+ <td align="center">8</td>
<td>process <tt>$GPZDA</tt> or <tt>$GPZDG</tt></td>
</tr><tr>
<td rowspan="6" align="center">4-6</td>
<td align="center">0</td>
+ <td align="center">0</td>
<td>linespeed 4800 bps</td>
</tr><tr>
<td align="center">16</td>
+ <td align="center">0x10</td>
<td>linespeed 9600 bps</td>
</tr><tr>
<td align="center">32</td>
+ <td align="center">0x20</td>
<td>linespeed 19200 bps</td>
</tr><tr>
<td align="center">48</td>
+ <td align="center">0x30</td>
<td>linespeed 38400 bps</td>
</tr><tr>
<td align="center">64</td>
+ <td align="center">0x40</td>
<td>linespeed 57600 bps</td>
</tr><tr>
<td align="center">80</td>
+ <td align="center">0x50</td>
<td>linespeed 115200 bps</td>
</tr><tr>
<td align="center">7</td>
<td align="center">128</td>
+ <td align="center">0x80</td>
<td>Write the sub-second fraction of the receive time stamp to the
clockstat file for all recognised NMEA sentences. This can be used to
get a useful value for fudge time2.<br><strong>Caveat:</strong> This
will fill your clockstat file rather fast. Use it only temporarily to
get the numbers for the NMEA sentence of your choice.</td>
</tr>
+ </tr><tr>
+ <td align="center">8</td>
+ <td align="center">256</td>
+ <td align="center">0x100</td>
+ <td>process <tt>$PGRMF</tt></td>
+ </tr><tr>
+ <td align="center">9-15</td>
+ <td align="center"></td>
+ <td align="center">0xFE00</td>
+ <td>reserved - leave 0</td>
+ </tr><tr>
+ <td align="center">16</td>
+ <td align="center">65536</td>
+ <td align="center">0x10000</td>
+ <td>Append extra statistics to the clockstats line.
+ Details below.</td>
+ </tr>
</tbody></table>
linespeed of 4800 bps or 9600 bps.
</p>
+ <h4>Monitor Data</h4>
+
+ <p>The last GPS sentence that is accepted or rejected is written to the
+ clockstats file and available with <code>ntpq -c clockvar</code>.
+ (Logging the rejected sentences lets you see/debug why they were rejected.)
+ Filtered sentences are not logged.</p>
+
+ <p>
+ If the 0x10000 mode bit is on and clockstats is enabled, several extra
+ counters will be appended to the NMEA sentence that gets logged.
+ For example:
+<pre>
+56299 76876.691 127.127.20.20 $GPGGA,212116.000,3726.0785,N,12212.2605,W,1,05,2.0,17.0,M,-25.7,M,,0000*5C 228 64 0 0 64 0
+</pre>
+ </p>
+
+ <table border="1">
+ <caption>Clockstats</caption>
+ <tbody><tr>
+ <th align="center">Column</th>
+ <th align="center">Sample</th>
+ <th align="left">Meaning</th>
+ </tr>
+
+ <tr>
+ <td align="center">1</td>
+ <td align="center">56299</td>
+ <td>MJD</td>
+ </tr><tr>
+ <td align="center">2</td>
+ <td align="center">76876.691</td>
+ <td>Time of day in seconds</td>
+ </tr><tr>
+ <td align="center">3</td>
+ <td align="center">127.127.20.20</td>
+ <td>IP Address from server config line</td>
+ </tr><tr>
+ <td align="center">4</td>
+ <td align="center">$GPGGA,...0*5C</td>
+ <td>NMEA Sentence</td>
+ </tr><tr>
+ <td align="center">5</td>
+ <td align="center">228</td>
+ <td>Number of sentences received</td>
+ </tr><tr>
+ <td align="center">6</td>
+ <td align="center">64</td>
+ <td>Number of sentences accepted and used for timekeeping</td>
+ </tr><tr>
+ <td align="center">7</td>
+ <td align="center">0</td>
+ <td>Number of sentences rejected because they were marked invalid (poor signal)</td>
+ </tr><tr>
+ <td align="center">8</td>
+ <td align="center">0</td>
+ <td>Number of sentences rejected because of bad checksum or invalid date/time</td>
+ </tr><tr>
+ <td align="center">9</td>
+ <td align="center">64</td>
+ <td>Number of sentences filtered by mode bits or same second</td>
+ </tr><tr>
+ <td align="center">10</td>
+ <td align="center">0</td>
+ <td>Number of PPS pulses used, overrides NMEA sentences</td>
+ </tr>
+ </tbody></table>
+
+ Sentences like $GPGSV that don't contain the time will get
+ counted in the total but otherwise ignored.
+
<p>
<a href="https://support.ntp.org/bin/view/Support/ConfiguringNMEARefclocks">Configuring
NMEA Refclocks</a> might give further useful hints for specific hardware
switched on by sending the following string.</p>
<pre>"$PGRMC,,,,,,,,,,,,2<cr><lf>"</pre>
- <h4>Monitor Data</h4>
-
- <p>The GPS sentence that is used is written to the clockstats file and
- available with ntpq -c clockvar.</p>
-
<h4>Fudge Factors</h4>
<dl>
#define NMEA_BAUDRATE_SHIFT 4
#define NMEA_DELAYMEAS_MASK 0x80
-#define NMEA_EXTLOG_MASK 0x01000000U
+#define NMEA_EXTLOG_MASK 0x010000U
#define NMEA_PROTO_IDLEN 5 /* tag name must be at least 5 chars */
#define NMEA_PROTO_MINLEN 6 /* min chars in sentence, excluding CS */
struct
{
u_int total;
- u_int good;
- u_int bad;
- u_int filtered;
+ u_int accepted;
+ u_int rejected; /* GPS said not enough signal */
+ u_int malformed; /* Bad checksum, invalid date or time */
+ u_int filtered; /* mode bits, not GPZDG, same second */
u_int pps_used;
}
tally;
DPRINTF(1, ("%s checksum missing: '%s'\n",
refnumtoa(&peer->srcadr), rd_lastcode));
refclock_report(peer, CEVNT_BADREPLY);
- up->tally.bad++;
+ up->tally.malformed++;
return;
}
}
/* Check sanity of time-of-day. */
- if (rc_time == 0) /* no time or conversion error? */
+ if (rc_time == 0) { /* no time or conversion error? */
checkres = CEVNT_BADTIME;
+ up->tally.malformed++;
+ }
/* Check sanity of date. */
- else if (rc_date == 0) /* no date or conversion error? */
+ else if (rc_date == 0) {/* no date or conversion error? */
checkres = CEVNT_BADDATE;
+ up->tally.malformed++;
+ }
/* check clock sanity; [bug 2143] */
- else if (pp->leap == LEAP_NOTINSYNC) /* no good status? */
+ else if (pp->leap == LEAP_NOTINSYNC) { /* no good status? */
checkres = CEVNT_BADREPLY;
+ up->tally.rejected++;
+ }
else
checkres = -1;
if (checkres != -1) {
save_ltc(pp, rd_lastcode, rd_lencode);
refclock_report(peer, checkres);
- up->tally.bad++;
return;
}
refnumtoa(&peer->srcadr), rd_lastcode));
/* Data will be accepted. Update stats & log data. */
- up->tally.good++;
+ up->tally.accepted++;
save_ltc(pp, rd_lastcode, rd_lencode);
pp->lastrec = rd_timestamp;
*/
if (peer->ttl & NMEA_EXTLOG_MASK) {
/* Log & reset counters with extended logging */
+ char *nmea = pp->a_lastcode;
+ if (*nmea == '\0') nmea = "(none)";
mprintf_clock_stats(
- &peer->srcadr, "%s %u %u %u %u %u",
- pp->a_lastcode,
- up->tally.total, up->tally.good, up->tally.bad,
+ &peer->srcadr, "%s %u %u %u %u %u %u",
+ nmea,
+ up->tally.total, up->tally.accepted,
+ up->tally.rejected, up->tally.malformed,
up->tally.filtered, up->tally.pps_used);
} else {
record_clock_stats(&peer->srcadr, pp->a_lastcode);