xref: /freebsd/contrib/ntp/html/drivers/oncore-shmem.html (revision 416ba5c74546f32a993436a99516d35008e9f384)
19c2daa00SOllivier Robert<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
29c2daa00SOllivier Robert
39c2daa00SOllivier Robert<html>
49c2daa00SOllivier Robert
59c2daa00SOllivier Robert	<head>
6ea906c41SOllivier Robert		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
79c2daa00SOllivier Robert		<title>ONCORE - SHMEM</title>
8ea906c41SOllivier Robert		<link href="scripts/style.css" type="text/css" rel="stylesheet">
99c2daa00SOllivier Robert	</head>
109c2daa00SOllivier Robert
119c2daa00SOllivier Robert	<body>
129c2daa00SOllivier Robert		<h3>Motorola ONCORE - The Shared Memory Interface</h3>
13*2b15cb3dSCy Schubert<p>Last update:
14*2b15cb3dSCy Schubert  <!-- #BeginDate format:En2m -->21-Oct-2010  23:44<!-- #EndDate -->
15*2b15cb3dSCy Schubert  UTC</p>
169c2daa00SOllivier Robert		<hr>
179c2daa00SOllivier Robert		<h4>Introduction</h4>
189c2daa00SOllivier Robert		<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.</p>
199c2daa00SOllivier Robert		<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>
209c2daa00SOllivier Robert		<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>
219c2daa00SOllivier Robert		<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+/GT+/M12 manuals are available as a pdf documents at <a href="http://www.synergy-gps.com/Mot_Manuals.html">Synergy</a> .</p>
229c2daa00SOllivier Robert		<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.</p>
239c2daa00SOllivier Robert		<h4>Activating the Interface</h4>
249c2daa00SOllivier Robert		<p>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> or <b>SHMEM</b> line in the <tt>/etc/ntp.oncore</tt> data file that looks like</p>
259c2daa00SOllivier Robert		<pre>
269c2daa00SOllivier Robert        STATUS &lt; file_name &gt;<br>
27ea906c41SOllivier Robert
289c2daa00SOllivier Robert        or<br>
29ea906c41SOllivier Robert
309c2daa00SOllivier Robert        SHMEM &lt; file_name &gt;
319c2daa00SOllivier Robert</pre>
329c2daa00SOllivier Robert		Thus a line like
339c2daa00SOllivier Robert		<pre>
349c2daa00SOllivier Robert        SHMEM /var/adm/ntpstats/ONCORE
359c2daa00SOllivier Robert</pre>
369c2daa00SOllivier Robert		<p>would be acceptable. This file name will be used to access the Shared Memory.</p>
379c2daa00SOllivier Robert		<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</p>
389c2daa00SOllivier Robert		<pre>
399c2daa00SOllivier Robert        SHMEM /var/adm/ntpstats/ONCORE
409c2daa00SOllivier Robert        Posn3D
419c2daa00SOllivier Robert</pre>
429c2daa00SOllivier Robert		<p>would be required.</p>
439c2daa00SOllivier Robert		<h4>Storage of Messages in Shared Memory</h4>
449c2daa00SOllivier Robert		<p>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>
459c2daa00SOllivier Robert		<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 &lt;checksum&gt;&lt;CR&gt;&lt;LF&gt;.</p>
469c2daa00SOllivier Robert		<p>The data starts at location ONE of SHMEM (NOT location ZERO).</p>
479c2daa00SOllivier Robert		<p>The messages are stacked in a series of variable length structures, that look like</p>
489c2daa00SOllivier Robert		<pre>
499c2daa00SOllivier Robert        struct message {
509c2daa00SOllivier Robert                u_int   length;
519c2daa00SOllivier Robert                u_char  sequence;
529c2daa00SOllivier Robert                u_char  message[length];
539c2daa00SOllivier Robert        }
549c2daa00SOllivier Robert</pre>
559c2daa00SOllivier Robert		<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 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>
569c2daa00SOllivier Robert		<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>
579c2daa00SOllivier Robert		<p>Following the last structure, is a u_int containing a zero length to indicate the end of the data.</p>
589c2daa00SOllivier Robert		<p>The messages are recognized by reading the headers in the data itself, viz @@Ea or whatever.</p>
599c2daa00SOllivier Robert		<p>There are two special cases.</p>
609c2daa00SOllivier Robert		<p>(1) The almanac takes a total of 34 submessages all starting with @@Cb.<br>
619c2daa00SOllivier Robert			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 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>
629c2daa00SOllivier Robert		<p>(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. In 0D mode no position is calculated.</p>
639c2daa00SOllivier Robert		<p>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) 2D/3D tick in its timekeeping functions.</p>
649c2daa00SOllivier Robert		<p>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, 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.</p>
659c2daa00SOllivier Robert		<h4>Opening the Shared Memory File</h4>
669c2daa00SOllivier Robert		<p>The shared memory segment is accessed through a file name given on a <b>SHMEM</b> card in the <tt>/etc/ntp.oncore</tt> input file. The following code could be used to open the Shared Memory Segment:</p>
679c2daa00SOllivier Robert		<pre>
689c2daa00SOllivier Robert        char *Buf, *file;
699c2daa00SOllivier Robert        int size, fd;
709c2daa00SOllivier Robert        struct stat statbuf;
719c2daa00SOllivier Robert
729c2daa00SOllivier Robert        file = &quot;/var/adm/ntpstats/ONCORE&quot;;  /* the file name on my ACCESS card */
739c2daa00SOllivier Robert        if ((fd=open(file, O_RDONLY)) &lt; 0) {
749c2daa00SOllivier Robert                fprintf(stderr, &quot;Cant open %s\n&quot;, file);
759c2daa00SOllivier Robert                exit(1);
769c2daa00SOllivier Robert        }
779c2daa00SOllivier Robert
789c2daa00SOllivier Robert        if (stat(file, &amp;statbuf) &lt; 0) {
799c2daa00SOllivier Robert                fprintf(stderr, &quot;Cant stat %s\n&quot;, file);
809c2daa00SOllivier Robert                exit(1);
819c2daa00SOllivier Robert        }
829c2daa00SOllivier Robert
839c2daa00SOllivier Robert        size = statbuf.st_size;
849c2daa00SOllivier Robert        if ((Buf=mmap(0, size, PROT_READ, MAP_SHARED, fd, (off_t) 0)) &lt; 0) {
859c2daa00SOllivier Robert                fprintf(stderr, &quot;MMAP failed\n&quot;);
869c2daa00SOllivier Robert                exit(1);
879c2daa00SOllivier Robert        }
889c2daa00SOllivier Robert</pre>
899c2daa00SOllivier Robert		<h4>Accessing the data</h4>
909c2daa00SOllivier Robert		<p>The following code shows how to get to the individual records.</p>
919c2daa00SOllivier Robert		<pre>
929c2daa00SOllivier Robert        void    oncore_msg_Ea(), oncore_msg_As(), oncore_msg_Bb();
939c2daa00SOllivier Robert
949c2daa00SOllivier Robert        struct Msg {
959c2daa00SOllivier Robert            char         c[5];
969c2daa00SOllivier Robert            unsigned int seq;
979c2daa00SOllivier Robert            void         (*go_to)(uchar *);
989c2daa00SOllivier Robert        };
999c2daa00SOllivier Robert
1009c2daa00SOllivier Robert        struct Msg Hdr[] = { {&quot;@@Bb&quot;, 0, &amp;oncore_msg_Bb},
1019c2daa00SOllivier Robert                             {&quot;@@Ea&quot;, 0, &amp;oncore_msg_Ea},
1029c2daa00SOllivier Robert                             {&quot;@@As&quot;, 0, &amp;oncore_msg_As}};
1039c2daa00SOllivier Robert
1049c2daa00SOllivier Robert        void
1059c2daa00SOllivier Robert        read_data()
1069c2daa00SOllivier Robert        {
1079c2daa00SOllivier Robert            int     i, j, k, n, iseq, jseq;
1089c2daa00SOllivier Robert            uchar   *cp, *cp1;
1099c2daa00SOllivier Robert
1109c2daa00SOllivier Robert
1119c2daa00SOllivier Robert            for(cp=Buf+1; (n = 256*(*cp) + *(cp+1)) != 0;  cp+=(n+3)) {
1129c2daa00SOllivier Robert                for (k=0; k &lt; sizeof(Hdr)/sizeof(Hdr[0]);  k++) {
1139c2daa00SOllivier Robert                    if (!strncmp(cp+3, Hdr[k].c, 4)) {      /* am I interested? */
1149c2daa00SOllivier Robert                        iseq = *(cp+2);
1159c2daa00SOllivier Robert                        jseq = Hdr[k].seq;
1169c2daa00SOllivier Robert                        Hdr[k].seq = iseq;
1179c2daa00SOllivier Robert                        if (iseq &gt; jseq) {              /* has it changed? */
1189c2daa00SOllivier Robert                            /* verify checksum */
1199c2daa00SOllivier Robert                            j = 0;
1209c2daa00SOllivier Robert                            cp1 = cp+3;             /* points to start of oncore response */
1219c2daa00SOllivier Robert                            for (i=2; i &lt; n-3; i++)
1229c2daa00SOllivier Robert                                j ^= cp1[i];
1239c2daa00SOllivier Robert                            if (j == cp1[n-3]) {    /* good checksum */
1249c2daa00SOllivier Robert                                    Hdr[k].go_to(cp1);
1259c2daa00SOllivier Robert                            } else {
1269c2daa00SOllivier Robert                                fprintf(stderr, &quot;Bad Checksum for %s\n&quot;, Hdr[k].c);
1279c2daa00SOllivier Robert                                break;
1289c2daa00SOllivier Robert                            }
1299c2daa00SOllivier Robert                        }
1309c2daa00SOllivier Robert                    }
1319c2daa00SOllivier Robert                }
1329c2daa00SOllivier Robert                if (!strncmp(cp+3, &quot;@@Ea&quot;, 4))
1339c2daa00SOllivier Robert                    cp += 3*(n+3);
1349c2daa00SOllivier Robert                if (!strncmp(cp+3, &quot;@@Cb&quot;, 4))
1359c2daa00SOllivier Robert                    cp += 34*(n+3);
1369c2daa00SOllivier Robert            }
1379c2daa00SOllivier Robert        }
1389c2daa00SOllivier Robert
1399c2daa00SOllivier Robert        oncore_msg_Bb(uchar *buf)
1409c2daa00SOllivier Robert        {
1419c2daa00SOllivier Robert                /* process Bb messages */
1429c2daa00SOllivier Robert        }
1439c2daa00SOllivier Robert
1449c2daa00SOllivier Robert        oncore_msg_Ea(uchar *buf)
1459c2daa00SOllivier Robert        {
1469c2daa00SOllivier Robert                /* process Ea messages */
1479c2daa00SOllivier Robert        }
1489c2daa00SOllivier Robert
1499c2daa00SOllivier Robert        oncore_msg_As(uchar *buf)
1509c2daa00SOllivier Robert        {
1519c2daa00SOllivier Robert                /* process As messages */
1529c2daa00SOllivier Robert        }
1539c2daa00SOllivier Robert</pre>
1549c2daa00SOllivier Robert		<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. The loop can be run every few seconds to check for new data.</p>
1559c2daa00SOllivier Robert		<h4>Examples</h4>
1569c2daa00SOllivier Robert		<p>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>
1579c2daa00SOllivier Robert		<p>Try the new interface, enjoy.</p>
1589c2daa00SOllivier Robert		<hr>
1599c2daa00SOllivier Robert		<address>Reg.Clemens (reg@dwf.com), Poul-Henning Kamp (phk@FreeBSD.org)</address>
1609c2daa00SOllivier Robert		<hr>
161ea906c41SOllivier Robert		<script type="text/javascript" language="javascript" src="scripts/footer.txt"></script>
1629c2daa00SOllivier Robert	</body>
1639c2daa00SOllivier Robert
1649c2daa00SOllivier Robert</html>
165