<head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
- <meta name="GENERATOR" content="Mozilla/4.76 [en] (X11; U; Linux 2.2.16-22 i586) [Netscape]">
<title>Generic NMEA GPS Receiver</title>
<link href="scripts/style.css" type="text/css" rel="stylesheet">
</head>
<p>Address: 127.127.20.<i>u</i><br>
Reference ID: <tt>GPS</tt><br>
Driver ID: <tt>GPS_NMEA</tt><br>
- Serial Port: <tt>/dev/gps<i>u</i></tt>; 4800/9600 baud, 8-bits, no parity<br>
+ Serial Port: <tt>/dev/gps<i>u</i></tt>; 4800 - 115200 bps, 8-bits, no parity<br>
Serial Port: <tt>/dev/gpspps<i>u</i></tt>; for just the PPS signal (this is tried first for PPS, before <tt>/dev/gps<i>u</i></tt>)<br>
Serial Port: <tt>/dev/gps<i>u</i></tt>; symlink to server:port (for nmead) Features: <tt>tty_clk</tt></p>
<h4>Description</h4>
- <p>This driver supports GPS receivers with the <tt>$GPRMC</tt> NMEA output string by default. Alternately the <tt>$GPGGA</tt> or <tt>$GPGLL </tt>may be selected. The driver also supports Accord's custom NMEA sentence <tt>$GPZDG</tt>, which gives GPS time unlike rest of the sentences which give UTC.</p>
- <p>The driver expects the receiver to be set up to transmit a <tt>$GPRMC</tt> message every second.</p>
- <p>The accuracy depend on the receiver used. Inexpesive GPS models are available with a claimed PPS signal accuracy of 1 <font face="Symbol">m</font>s or better relative to the broadcast signal. However, in most cases the actual accuracy is limited by the precision of the timecode and the latencies of the serial interface and operating system.</p>
+ <p>This driver supports GPS receivers with the <tt>$GPRMC, $GPGLL, $GPGGA, $GPZDA, and $GPZDG</tt> NMEA sentences by default. Note that Accord's custom NMEA sentence <tt>$GPZDG</tt> reports using the GPS timescale, while the rest of the sentences report UTC. The difference between the two is a whole number of seconds which increases with each leap second insertion in UTC. To avoid problems mixing UTC and GPS timescales, the driver disables processing of UTC sentences once <tt>$GPZDG</tt> is received.</p>
+ <p>The driver expects the receiver to be set up to transmit at least one supported sentence every second.</p>
+ <p>The accuracy depends on the receiver used. Inexpensive GPS models are available with a claimed PPS signal accuracy of 1 <font face="Symbol">m</font>s or better relative to the broadcast signal. However, in most cases the actual accuracy is limited by the precision of the timecode and the latencies of the serial interface and operating system.</p>
<p>If the Operating System supports the PPSAPI, RFC-2783, it will be used.<br> </p>
<p>The various GPS sentences that this driver recognises look like this:<br>
(others quietly ignored)</p>
- <pre><tt>$GPRMC,POS_UTC,POS_STAT,LAT,LAT_REF,LON,LON_REF,SPD,HDG,DATE,MAG_VAR,MAG_REF*CC<cr><lf>
-$GPGLL,LAT,LAT_REF,LONG,LONG_REF,POS_UTC,POS_STAT*CC<cr><lf>
-$GPGGA,POS_UTC,LAT,LAT_REF,LONG,LONG_REF,FIX_MODE,SAT_USED,HDOP,ALT,ALT_UNIT,GEO,G_UNIT,D_AGE,D_REF*CC<cr><lf>
+ <pre><tt>$GPRMC,UTC,POS_STAT,LAT,LAT_REF,LON,LON_REF,SPD,HDG,DATE,MAG_VAR,MAG_REF*CS<cr><lf>
+$GPGLL,LAT,LAT_REF,LONG,LONG_REF,UTC,POS_STAT*CS<cr><lf>
+$GPGGA,UTC,LAT,LAT_REF,LONG,LONG_REF,FIX_MODE,SAT_USED,HDOP,ALT,ALT_UNIT,GEO,G_UNIT,D_AGE,D_REF*CS<cr><lf>
+$GPZDA,UTC,DD,MM,YYYY,TH,TM,*CS<cr><lf>
+$GPZDG,GPSTIME,DD,MM,YYYY,AA.BB,V*CS<cr><lf>
- POS_UTC - UTC of position. Hours, minutes and seconds [fraction (opt.)]. (hhmmss[.fff])
+ UTC - Time of day on UTC timescale. Hours, minutes and seconds [fraction (opt.)]. (hhmmss[.fff])
POS_STAT - Position status. (A = Data valid, V = Data invalid)
LAT - Latitude (llll.ll)
LAT_REF - Latitude direction. (N = North, S = South)
G_UNIT - Geoid units (M/F)
D_AGE - Age of last DGPS Fix
D_REF - Reference ID of DGPS station
- CC - Checksum (optional)
- <cr><lf> - Sentence terminator.</tt></pre>
-Accord's <tt>$GPZDG</tt> has the folowing format:
-<pre><tt>$GPZDG,POS_GPS,DD,MM,YYYY,AA.BB,V*CS<cr><lf>
-
- POS_GPS - GPS of position. Hours, minutes and seconds [fraction (opt.)]. (hhmmss[.f])
+ GPSTIME - Time of day on GPS timescale. Hours, minutes and seconds [fraction (opt.)]. (hhmmss[.f])
DD - Day of the month (1-31)
MM - Month of the year (1-12)
YYYY - Year
CS - Checksum
<cr><lf> - Sentence terminator.</tt></pre>
-<p>Alternate GPS sentences (other than <tt>$GPRMC</tt> - the default) and baudrates may be enabled by setting the relevent bits of 'mode' in the server configuration line<br> * server 127.127.20.x mode X<br> bit 0 - enables RMC (value = 1)<br> bit 1 - enables GGA (value = 2)<br> bit 2 - enables GLL (value = 4)<br> bit 3 - enables ZDG (value = 8)<br>
-<p> Multiple sentences may be selected except when ZDG is enabled. The driver falls back to standard NMEA sentences when incorrent selection is configured.The driver uses 4800 baudrate by default. Altenatively, 9600 baudrate can be selected by using the fourth bit of 'mode' field;<br><br>
- bit 4 - selects baudrate ( 0 for 4800 - the default, 1 for 9600 )<br></p>
- <p>The driver will send a <tt>$PMOTG,RMC,0000*1D<cr><lf></tt> message each time a <tt>$GPRMC</tt> string is needed. This is not needed on most GPS receivers because they automatically send the <tt>$GPRMC</tt> string every second and will only work on GPS receivers that understand the <tt>$PMOTG</tt> string. Others will just ignore it.</p>
+<p>Specific GPS sentences and bitrates may be selected by setting bits of the 'mode' in the server configuration line:<br>
+ <tt>server 127.127.20.x mode X</tt><br> bit 0 - process <tt>$GPMRC</tt> (value = 1)<br> bit 1 - process <tt>$GPGGA</tt> (value = 2)<br> bit 2 - process <tt>$GPGLL</tt> (value = 4)<br> bit 4 - process <tt>$GPZDA</tt> or <tt>$GPZDG</tt> (value = 8)<br>
+<p>The default (mode 0) is to process all supported sentences, which results in the last received each cycle being used. Multiple sentences may be selected by adding their mode bit values. The driver uses 4800 bits per second by default. Faster bitrates can be selected using bits 4, 5, and 6 of the mode field:<br><br>
+ bits 4/5/6 - select serial bitrate ( 0 for 4800 - the default, 1 for 9600, 2 for 19200, 3 for 38400, 4 for 57600, 5 for 115200 )<br></p>
+ <p>The driver will send a <tt>$PMOTG,RMC,0000*1D<cr><lf></tt> command each poll interval. This is not needed on most GPS receivers because they automatically send <tt>$GPRMC</tt> every second, but helps a Motorola GPS receiver that is otherwise silent. NMEA devices ignore commands they do not understand.</p>
<h4>Setting up the Garmin GPS-25XL</h4>
Switch off all output with by sending it the following string.
<pre>"$PGRMO,,2<cr><lf>"</pre>
<p>On some systems the PPS signal isn't switched on by default. It can be switched on by sending the following string.</p>
<pre>"$PGRMC,,,,,,,,,,,,2<cr><lf>"</pre>
<h4>Monitor Data</h4>
- <p>The GPS sentence(s) that is used is written to the clockstats file.</p>
+ <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>
<dt><tt>time1 <i>time</i></tt>
<dt><tt>flag3 0 | 1</tt>
<dd>Controls the kernel PPS discipline: 0 for disable (default), 1 for enable.
<dt><tt>flag4 0 | 1</tt>
- <dd>Not used by this driver.
+ <dd>Obscures location in timecode: 0 for disable (default), 1 for enable.
</dl>
<p>Additional Information</p>
<p><a href="../refclock.html">Reference Clock Drivers</a></p>
* neo.venu@gmail.com, venugopal_d@pgad.gov.in
*
* Updated to process 'time1' fudge factor
- * Venu Gopal May 05, 2008
+ * Venu Gopal May 05, 2008
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#ifdef SYS_WINNT
extern int async_write(int, const void *, unsigned int);
-#undef write
#define write(fd, data, octets) async_write(fd, data, octets)
#endif
* Multiple sentences may be selected except when ZDG/ZDA is selected.
*
* bit 4/5/6 - selects the baudrate for serial port :
- * 0 for 4800 (default)
- * 1 for 9600
- * 2 for 19200
- * 3 for 38400
- * 4 for 57600
- * 5 for 115200
+ * 0 for 4800 (default)
+ * 1 for 9600
+ * 2 for 19200
+ * 3 for 38400
+ * 4 for 57600
+ * 5 for 115200
*/
#define NMEA_MESSAGE_MASK_OLD 0x07
#define NMEA_MESSAGE_MASK_SINGLE 0x08
/* Grab field depending on clock string type */
switch (cmdtype) {
- case GPRMC:
+ case GPRMC:
/*
* Test for synchronization. Check for quality byte.
*/
dp = field_parse(cp, 1);
break;
- case GPGGA:
+ case GPGGA:
/*
* Test for synchronization. Check for quality byte.
*/
dp = field_parse(cp, 1);
break;
- case GPGLL:
+ case GPGLL:
/*
* Test for synchronization. Check for quality byte.
*/
dp = field_parse(cp, 5);
break;
- case GPZDG_ZDA:
+ case GPZDG_ZDA:
/*
* Test for synchronization. For $GPZDG check for validity of GPS time.
*/
dp = field_parse(cp, 1);
break;
- default:
+ default:
return;
}
}
pp->day = day;
+ /*
+ * If "fudge 127.127.20.__ flag4 1" is configured in ntp.conf,
+ * remove the location and checksum from the NMEA sentence
+ * recorded as the last timecode and visible to remote users
+ * with:
+ *
+ * ntpq -c clockvar <server>
+ *
+ * Note that this also removes the location from the clockstats
+ * log (if it is enabled). Some NTP operators monitor their
+ * NMEA GPS using the change in location in clockstats over
+ * time as as a proxy for the quality of GPS reception and
+ * thereby time reported.
+ */
+ if (CLK_FLAG4 & pp->sloppyclockflag) {
+ /*
+ * Start by pointing cp and dp at the fields with
+ * longitude and latitude in the last timecode.
+ */
+ switch (cmdtype) {
+
+ case GPGLL:
+ cp = field_parse(pp->a_lastcode, 1);
+ dp = field_parse(cp, 2);
+ break;
+
+ case GPGGA:
+ cp = field_parse(pp->a_lastcode, 2);
+ dp = field_parse(cp, 2);
+ break;
+
+ case GPRMC:
+ cp = field_parse(pp->a_lastcode, 3);
+ dp = field_parse(cp, 2);
+ break;
+
+ case GPZDG_ZDA:
+ default:
+ cp = dp = NULL;
+ }
+
+ /*
+ * Blanking everything after the decimal point '.' is easy and
+ * gives enough error for at least a few neighbors to be as
+ * likely as you to be the one with the reflock. We're keeping
+ * degrees and minutes but tossing the seconds (expressed as
+ * decimal fractions of a minute). Degrees minutes seconds,
+ * not hours minutes seconds. :)
+ */
+ while (cp) {
+ while (',' != *cp) {
+ if ('.' != *cp)
+ *cp = '_';
+ cp++;
+ }
+
+ /*
+ * blank the longitude at cp then the latitude at dp
+ * then we're done.
+ */
+ if (cp < dp)
+ cp = dp;
+ else
+ cp = NULL;
+ }
+
+ /*
+ * blank the checksum, last two characters on the line
+ */
+ if (dp) {
+ cp = pp->a_lastcode + pp->lencode - 2;
+ if (0 == cp[2])
+ cp[0] = cp[1] = '_';
+ }
+
+ }
+
#ifdef HAVE_PPSAPI
/*
* If the PPSAPI is working, rather use its timestamps.