+2000-02-17 Harlan Stenn <stenn@whimsy.udel.edu>
+ * ntpd/refclock_oncore.c: Cleanup/fixes
+ * html/driver30.htm: Cleanup
+ * html/Oncore-SHMEM.htm: Cleanup
+ From: Reg Clemens <reg@dwf.com>
2000-02-16 Sven Dietrich <sven_dietrich@trimble.com>
In NMEA mode, the Oncore GPS receiver provides the user with the same information as
other GPS receivers.
In BINARY mode, it can provide a lot of additional information.
-When using the Oncore GPS receiver with NTP, this additional information is usually
-not available since the receiver is only talking to the oncore driver in NTPD.
<P>
In particular, you can ask for satellite positions, satellite health, signal levels,
the ephemeris and the almanac, and you can set many operational parameters.
you can get the pseudorange corrections necessary to act as a DGPS base station, and you can see
the raw satellite data messages themselves.
<P>
-To make use of this information you will need an Oncore Reference Manual for the
-Oncore GPS receiver that you have. The Manual for the VP only exists as a paper
-document, the UT manuals are available as a pdf document online.
-<P>
+When using the Oncore GPS receiver with NTP, this additional information is usually
+not available since the receiver is only talking to the oncore driver in NTPD.
To make this information available for use in other programs,
(say graphic displays of satellites positions, plots of SA, etc.), a shared memory interface
(SHMEM) has been added to the refclock_oncore driver on those operating systems that support
shared memory.
<P>
+To make use of this information you will need an Oncore Reference Manual for the
+Oncore GPS receiver that you have. The Manual for the VP only exists as a paper
+document, the UT manuals are available as a pdf document online.
+<P>
This interface was written by Poul-Henning Kamp (phk@FreeBSD.org), and modified by
Reg Clemens (reg@dwf.com).
The interface is known to work in FreeBSD, Linux, and Solaris.
<H4>
+Activating the Interface
+</H4>
+Although the Shared Memory Interface will be compiled into the Oncore driver
+on those systems where Shared Memory is supported, to activate this interface you must
+include a <B>STATUS</B> line in the <tt>/etc/ntp.oncore</tt> data file that looks like
+<PRE>
+ STATUS < file_name >
+</PRE>
+Thus a line like
+<PRE>
+ STATUS /var/adm/ntpstats/ONCORE
+</PRE>
+would be acceptable.
+This file name will be used to access the Shared Memory.
+<P>
+In addition, one the two keywords <B>Posn2D</B> and <B>Posn3D</B> can be added to
+see @@Ea records containing the 2D or 3D position of the station (see below).
+Thus to activate the interface, and see 3D positions, something like
+<PRE>
+ STATUS /var/adm/ntpstats/ONCORE
+ Posn3D
+</PRE>
+would be required.
+<H4>
Storage of Messages in Shared Memory
</H4>
With the shared memory interface, the oncore driver (refclock_oncore) allocates space
That is, there are two bytes (caution, these may NOT be aligned with word boundaries, so
the field needs to be treated as a pair of u_char), that contains the length of the next
message.
-This is followed by a u_char, a sequence number, that is incremented whenever a new message of
+This is followed by a u_char sequence number, that is incremented whenever a new message of
this type is received.
This is followed by 'length' characters of the actual message.
<P>
<P>
There are two special cases.
<P>
-(1) The almanac takes a total of 34 subrecords all starting with @@Cb. <br>
-35 records are allocated.
+(1) The almanac takes a total of 34 submessages all starting with @@Cb. <br>
+35 slots are allocated in shared memory.
Each @@Cb message is initially placed in the first of these locations,
-and then later it is moved to the appropriate location for that sub-message.
+and then later it is moved to the appropriate location for that submessage.
The submessages can be distinguished by the first two characters following the @@Cb header,
and new data is received only when the almanac changes.
<P>
-(2) The @@Ea record contains the satellite position, and are received 1/second.
+(2) The @@Ea message contains the calculated location of the antenna, and is received
+once per second.
However, when in timekeeping mode, the receiver is normally put in 0D mode, with the
-position fixed to get better accuracy, so the current position is not available.
+position fixed, to get better accuracy.
+In 0D mode no position is calculated.
<P>
-When the SHMEM option is active, one @@Ea record is hijacked each 15s, and the receiver
-is put back in 3D mode so the the current location can be determined (for position determination, or for
+When the SHMEM option is active,
+and if one of <B>Posn2D</B> or <B>Posn3D</B> is specified,
+one @@Ea record is hijacked each 15s, and the receiver
+is put back in 2D/3D mode so the the current location can be determined (for position determination, or for
tracking SA).
-The timekeeping code is careful NOT to use the time associated with this (less accurate) 3D tick
+The timekeeping code is careful NOT to use the time associated with this (less accurate) 2D/3D tick
in its timekeeping functions.
<P>
-Following the initial @@Ea record are 3 subrecords for a total of four.
+Following the initial @@Ea message are 3 additional slots for a total of four.
As with the almanac, the first gets filled each time a new record becomes available,
-Later in the code, it is distributed to the appropriate subrecord.
-These records can be distinguished by different bit patterns in the last byte of the record.
-Currently there
-are subrecords for 0D, 2D, 3D, but the code only fills in the 0D and 3D positions at
-present.
+later in the code, the message is distributed to the appropriate slot.
+The additional slots are for messages containing 0D, 2D and 3D positions.
+These messages can be distinguished by different bit patterns in the last data byte of the record.
<H4>
Opening the Shared Memory File
</H4>
-The shared memory segment is accessed through a file name given on a ACCESS card in the
-/etc/ntp.oncore input file.
+The shared memory segment is accessed through a file name given on a <B>ACCESS</B> card in the
+<tt>/etc/ntp.oncore</tt> input file.
The following code could be used to open the Shared Memory Segment:
<PRE>
}
</PRE>
-<P>
The structure Hdr contains the Identifying string for each of the messages that
we want to examine, and the name of a program to call when a new message of that
type is arrives.
-<P>
The loop can be run every few seconds to check for new data.
-<P>
-There are two more complete examples
-(one that that show satellite positions and the station position as affected by SA, and
-another that computes the effective horizon by watching satellite tracks) that
-will be found in the GNU-zipped tar file
+<H4>
+Examples
+</H4>
+There are two complete examples available.
+The first plots satellite positions and the station position as affected by SA, and
+keeps track of the mean station position, so you can run it for periods of days
+to get a better station position.
+The second shows the effective horizon by watching satellite tracks.
+The examples will be found in the GNU-zipped tar file
<A HREF=ftp://ftp.udel.edu/pub/ntp/software/OncorePlot.tar.gz>
ftp://ftp.udel.edu/pub/ntp/software/OncorePlot.tar.gz</A>.
<P>
-Try it, have fun.
+Try the new interface, enjoy.
<HR>
<ADDRESS>
-<Reg.Clemens> reg@dwf.com
-</ADDRESS>
+Reg.Clemens (reg@dwf.com),
+Poul-Henning Kamp (phk@FreeBSD.org)
+<ADDRESS>
</BODY>
</HTML>
Not used by this driver.</DD>
</DL>
<B>Additional Information</B>
-<P>The driver was initially developed on FreeBSD, and has since been tested on Linux SunOS and Solaris.
+<P>The driver was initially developed on FreeBSD, and has since been tested
+on Linux, SunOS and Solaris.
<P>There is a driver specific configuration file <TT>/etc/ntp.oncore</TT>
that contains information on the startup mode, the location of the GPS
*
* (UT) (VP)
* COPYRIGHT 1991-1997 MOTOROLA INC. COPYRIGHT 1991-1996 MOTOROLA INC.
- * SFTW P/N # 98-P36848P SFTW P/N # 98-P36830P
+ * SFTW P/N # 98-P36848P SFTW P/N # 98-P36830P
* SOFTWARE VER # 2 SOFTWARE VER # 8
* SOFTWARE REV # 2 SOFTWARE REV # 8
* SOFTWARE DATE APR 24 1998 SOFTWARE DATE 06 Aug 1996
* copy of all types of messages we recognize. This file can be mmap(2)'ed
* by monitoring and statistics programs.
*
- * See separate documentation for this option.
+ * See separate HTML documentation for this option.
*/
#ifdef HAVE_CONFIG_H
u_char En[70];
u_char Cj[300];
u_char shmem_first;
+ u_char shmem_reset;
+ u_char shmem_Posn;
u_char As;
u_char Ay;
u_char Az;
{ "Af", 15, 0, "" },
{ "As", 20, oncore_msg_As, "" },
{ "At", 8, oncore_msg_At, "" },
+ { "Au", 12, 0, "" },
+ { "Av", 8, 0, "" },
{ "Aw", 8, 0, "" },
{ "Ay", 11, oncore_msg_Ay, "" },
{ "Az", 11, oncore_msg_Az, "" },
static u_char oncore_cmd_At[] = { 'A', 't', 2 };
/*
- * Position-Hold Position
+ * 0D/2D Position and Set.
*/
u_char oncore_cmd_As[] = { 'A', 's', 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 };
u_char oncore_cmd_Asx[]= { 'A', 's', 0x7f, 0xff, 0xff, 0xff,
0x7f, 0xff, 0xff, 0xff,
0x7f, 0xff, 0xff, 0xff, 0xff };
+u_char oncore_cmd_Au[] = { 'A', 'u', 0,0,0,0,0 };
+u_char oncore_cmd_Av[] = { 'A', 'v', 0 };
+
/*
* Set to UTC time (not GPS).
instance->assert = 1;
} else if (!strncmp(cc, "CLEAR", 5)) {
instance->assert = 0;
+ } else if (!strncmp(cc, "POSN2D", 6)) {
+ instance->shmem_Posn = 2;
+ } else if (!strncmp(cc, "POSN3D", 6)) {
+ instance->shmem_Posn = 3;
}
}
fclose(fd);
if (mode == 1 || mode == 3)
instance->init_type++;
}
+
+ /* simplify SHMEM tests later */
+
+ if (!instance->shmem)
+ instance->shmem_Posn = 0;
}
oncore_cmd_As[14] = instance->ss_ht_type;
oncore_sendmsg(instance->ttyfd, oncore_cmd_As, sizeof oncore_cmd_As);
+ w32_buf(&oncore_cmd_Au[2], (int) instance->ss_ht);
+ oncore_cmd_Au[6] = instance->ss_ht_type;
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Au, sizeof oncore_cmd_Au);
+
instance->site_survey = ONCORE_SS_DONE;
oncore_cmd_At[2] = 1;
oncore_sendmsg(instance->ttyfd, oncore_cmd_At, sizeof oncore_cmd_At);
int i;
i = 0;
- if (instance->Ea[72]&010) /* 0D, Position Hold */
+ if (instance->Ea[72]&0x8) /* 0D, Position Hold */
i = 1;
- else if (instance->Ea[72]&020) /* 2D, Altitude Hold */
+ else if (instance->Ea[72]&0x10) /* 2D, Altitude Hold */
i = 2;
- else if (instance->Ea[72]&040) /* 3D fix */
+ else if (instance->Ea[72]&0x20) /* 3D fix */
i = 3;
if (i) {
i *= 79;
/* When we have an almanac, start the En messages */
if (instance->o_state == ONCORE_ALMANAC) {
- if ((instance->Ea[72] & 1)) {
+ if ((instance->Ea[72] & 0x1)) {
if (debug)
printf("ONCORE: waiting for almanac\n");
return;
instance->pp->minute = buf[9];
instance->pp->second = buf[10];
-#if 1
- /* every 15s, steal one 'tick' to get 3D posn */
-
- if (instance->site_survey != ONCORE_SS_SW) { /* dont screw up the HWSS by changing mode */
- static int reset;
+ /* every 15s, steal one 'tick' to get 2D or 3D posn if asked for */
+ if (instance->shmem_Posn && instance->site_survey != ONCORE_SS_SW) { /* dont screw up the HWSS by changing mode */
if (instance->pp->second%15 == 3) { /* start the sequence */
- reset = 1;
- oncore_cmd_At[2] = 0;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At, sizeof oncore_cmd_At);
- } else if (reset) {
- reset = 0;
- oncore_cmd_At[2] = 1;
+ instance->shmem_reset = 1;
+ oncore_cmd_At[2] = 0; /* out of 0D mode, to 3D mode */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_At, sizeof oncore_cmd_At);
+ if (instance->shmem_Posn == 2) {
+ oncore_cmd_Av[2] = 1; /* into 2D mode */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Av, sizeof oncore_cmd_Av);
+ }
+ } else if (instance->shmem_reset || !(instance->Ea[72] & 0x8)) {
+ instance->shmem_reset = 0;
+ if (instance->Ea[72] & 0x10) {
+ oncore_cmd_Av[2] = 0; /* out of 2D mode */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Av, sizeof oncore_cmd_Av);
+ }
+ oncore_cmd_At[2] = 1; /* into 0D mode */
oncore_sendmsg(instance->ttyfd, oncore_cmd_At, sizeof oncore_cmd_At);
}
-
- if ((instance->site_survey == ONCORE_SS_DONE) && !(instance->Ea[72]&010))
- return;
}
-#endif
+
if (instance->site_survey != ONCORE_SS_SW)
return;
* We have to average our own position for the Position Hold Mode
*/
- /* We only take PDOP/3D fixes */
-
- if (instance->Ea[37] & 1)
- return;
-
/* Not if poor geometry or less than 3 sats */
if (instance->Ea[72] & 0x52)
oncore_cmd_As[14] = 0;
oncore_sendmsg(instance->ttyfd, oncore_cmd_As, sizeof oncore_cmd_As);
+ w32_buf(&oncore_cmd_Au[2], (int) instance->ss_ht);
+ oncore_cmd_Au[6] = 0;
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Au, sizeof oncore_cmd_Au);
+
oncore_cmd_At[2] = 1;
oncore_sendmsg(instance->ttyfd, oncore_cmd_At, sizeof oncore_cmd_At);
record_clock_stats(&(instance->peer->srcadr), "Now in 0D mode");
#endif
#endif /* ! HAVE_PPS_API */
- if ((instance->site_survey == ONCORE_SS_DONE) && !(instance->Ea[72]&010))
+ if ((instance->site_survey == ONCORE_SS_DONE) && !(instance->Ea[72]&0x8))
return;
if (instance->o_state != ONCORE_RUN)
return;
/* Don't do anything without an almanac to define the GPS->UTC delta */
- if (instance->Ea[72] & 1)
+ if (instance->Ea[72] & 0x1)
return;
/* If Time RAIM doesn't like it, don't trust it */
tsp = &pps_i.assert_timestamp;
if (debug > 2)
- printf("ONCORE: serial/j (%d, %d) %ld.%09ld\n",
+ printf("ONCORE: serial/j (%lu, %d) %ld.%09ld\n",
pps_i.assert_sequence, j, tsp->tv_sec, tsp->tv_nsec);
if (pps_i.assert_sequence == j) {
tsp = &pps_i.clear_timestamp;
if (debug > 2)
- printf("ONCORE: serial/j (%d, %d) %ld.%09ld\n",
+ printf("ONCORE: serial/j (%lu, %d) %ld.%09ld\n",
pps_i.clear_sequence, j, tsp->tv_sec, tsp->tv_nsec);
if (pps_i.clear_sequence == j) {