--- /dev/null
+<HTML>
+<HEAD>
+ <TITLE> ONCORE - SHMEM </TITLE>
+</HEAD>
+<BODY>
+<H3>
+Motorola ONCORE - The Shared Memory Interface
+</H3>
+<HR>
+
+<H4>
+Introduction
+</H4>
+
+<P>
+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.
+In the case of the VP,
+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>
+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>
+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>
+Storage of Messages in Shared Memory
+</H4>
+With the shared memory interface, the oncore driver (refclock_oncore) allocates space
+for all of the messages that it is configured to receive, and then puts each message
+in the appropriate slot in shared memory as it arrives from the receiver.
+Since there is no easy way for a client program to know when the shared memory has
+been updated,
+a sequence number is associated with each message, and is incremented when a new message
+arrives.
+With the sequence number it is easy to check through the shared memory segment for messages that
+have changed.
+<P>
+The Oncore binary messages are kept in their full length, as described in the Reference
+manual, that is everything from the @@ prefix thru the <checksum><CR><LF>.
+<P>
+The data starts at location ONE of SHMEM (NOT location ZERO).
+<P>
+The messages are stacked in a series of variable length structures, that look like
+<PRE>
+ struct message {
+ u_int length;
+ u_char sequence;
+ u_char message[length];
+ }
+</PRE>
+<P>
+if something like that were legal.
+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 type is received.
+This is followed by 'length' characters of the actual message.
+<P>
+The next structure starts immediately following the last char of the previous message (no alignment).
+Thus, each structure starts a distance of 'length+3' from the previous structure.
+<P>
+Following the last structure, is a u_int containing a zero length to indicate the end
+of the data.
+<P>
+The messages are recognized by reading the headers in the data itself, viz @@Ea or whatever.
+<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.
+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.
+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.
+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.
+<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
+tracking SA).
+The timekeeping code is careful NOT to use the time associated with this (less accurate) 3D tick
+in its timekeeping functions.
+<P>
+Following the initial @@Ea record are 3 subrecords 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.
+<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 following code could be used to open the Shared Memory Segment:
+
+<PRE>
+ char *Buf, *file;
+ int size, fd;
+ struct stat statbuf;
+
+ file = "/var/adm/ntpstats/ONCORE"; /* the file name on my ACCESS card */
+ if ((fd=open(file, O_RDONLY)) < 0) {
+ fprintf(stderr, "Cant open %s\n", file);
+ exit(1);
+ }
+
+ if (stat(file, &statbuf) < 0) {
+ fprintf(stderr, "Cant stat %s\n", file);
+ exit(1);
+ }
+
+ size = statbuf.st_size;
+ if ((Buf=mmap(0, size, PROT_READ, MAP_SHARED, fd, (off_t) 0)) < 0) {
+ fprintf(stderr, "MMAP failed\n");
+ exit(1);
+ }
+</PRE>
+
+<H4>
+Accessing the data
+</H4>
+The following code shows how to get to the individual records.
+
+<PRE>
+ void oncore_msg_Ea(), oncore_msg_As(), oncore_msg_Bb();
+
+ struct Msg {
+ char c[5];
+ unsigned int seq;
+ void (*go_to)(uchar *);
+ };
+
+ struct Msg Hdr[] = { {"@@Bb", 0, &oncore_msg_Bb},
+ {"@@Ea", 0, &oncore_msg_Ea},
+ {"@@As", 0, &oncore_msg_As}};
+
+ void
+ read_data()
+ {
+ int i, j, k, n, iseq, jseq;
+ uchar *cp, *cp1;
+
+
+ for(cp=Buf+1; (n = 256*(*cp) + *(cp+1)) != 0; cp+=(n+3)) {
+ for (k=0; k < sizeof(Hdr)/sizeof(Hdr[0]); k++) {
+ if (!strncmp(cp+3, Hdr[k].c, 4)) { /* am I interested? */
+ iseq = *(cp+2);
+ jseq = Hdr[k].seq;
+ Hdr[k].seq = iseq;
+ if (iseq > jseq) { /* has it changed? */
+ /* verify checksum */
+ j = 0;
+ cp1 = cp+3; /* points to start of oncore response */
+ for (i=2; i < n-3; i++)
+ j ^= cp1[i];
+ if (j == cp1[n-3]) { /* good checksum */
+ Hdr[k].go_to(cp1);
+ } else {
+ fprintf(stderr, "Bad Checksum for %s\n", Hdr[k].c);
+ break;
+ }
+ }
+ }
+ }
+ if (!strncmp(cp+3, "@@Ea", 4))
+ cp += 3*(n+3);
+ if (!strncmp(cp+3, "@@Cb", 4))
+ cp += 34*(n+3);
+ }
+ }
+
+ oncore_msg_Bb(uchar *buf)
+ {
+ /* process Bb messages */
+ }
+
+ oncore_msg_Ea(uchar *buf)
+ {
+ /* process Ea messages */
+ }
+
+ oncore_msg_As(uchar *buf)
+ {
+ /* process As messages */
+ }
+</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
+<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.
+<HR>
+<ADDRESS>
+<Reg.Clemens> reg@dwf.com
+</ADDRESS>
+</BODY>
+</HTML>
the "UT+",
and the "Remote" which is a prepackaged "UT+".
The "VP" is no longer available.
-
-<P>The evaluation kit
+The evaluation kit
can also be recommended, it interfaces to a PC straightaway, using the
serial (DCD) or parallel port for PPS input and packs the
receiver in a nice and sturdy box.
<P>The driver will use the "position hold" mode with
user provided coordinates,
the receivers built-in site-survey,
-or a similar algorithm implemented in this driver.
+or a similar algorithm implemented in this driver to determine the antenna position.
<H4>
Monitor Data</H4>
-The driver is quite chatty on stdout if ntpd is run with
-debugging.
-A manual will be required though.
-Additional information is written to the clockstats file, if configured.
+The driver is quite chatty on stdout if ntpd is run with debugging.
+<P>
+In addition, on platforms supporting Shared Memory, all of the messages
+received from the Oncore receiver are made available in shared memory for
+use by other programs.
+See the <A HREF=Oncore-SHMEM.htm> Oncore-SHMEM </A> manual page for
+information on how to use this option.
+For either debugging or using the SHMEM option, an Oncore Reference Manual
+for the specific receiver in use will be required.
<H4>
Fudge Factors</H4>
Not used by this driver.</DD>
</DL>
<B>Additional Information</B>
-<P>The driver has been tested on FreeBSD, Linux and SunOS.
+<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