?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{FILE START}

library

?curdirlinks? - Rev 6

?prevdifflink? - Blame - ?getfile?

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>Procyon AVRlib: nmea.c Source File</title>
<link href="dox.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.4.2 -->
<div class="qindex"><a class="qindex" href="main.html">Main&nbsp;Page</a> | <a class="qindex" href="modules.html">Modules</a> | <a class="qindex" href="annotated.html">Data&nbsp;Structures</a> | <a class="qindex" href="dirs.html">Directories</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Data&nbsp;Fields</a> | <a class="qindex" href="globals.html">Globals</a> | <a class="qindex" href="pages.html">Related&nbsp;Pages</a></div>
<h1>nmea.c</h1><a href="nmea_8c.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment">00001 <span class="comment">/*! \file nmea.c \brief NMEA protocol function library. */</span>
00002 <span class="comment">//*****************************************************************************</span>
00003 <span class="comment">//</span>
00004 <span class="comment">// File Name    : 'nmea.c'</span>
00005 <span class="comment">// Title        : NMEA protocol function library</span>
00006 <span class="comment">// Author       : Pascal Stang - Copyright (C) 2002</span>
00007 <span class="comment">// Created      : 2002.08.27</span>
00008 <span class="comment">// Revised      : 2002.08.27</span>
00009 <span class="comment">// Version      : 0.1</span>
00010 <span class="comment">// Target MCU   : Atmel AVR Series</span>
00011 <span class="comment">// Editor Tabs  : 4</span>
00012 <span class="comment">//</span>
00013 <span class="comment">// NOTE: This code is currently below version 1.0, and therefore is considered</span>
00014 <span class="comment">// to be lacking in some functionality or documentation, or may not be fully</span>
00015 <span class="comment">// tested.  Nonetheless, you can expect most functions to work.</span>
00016 <span class="comment">//</span>
00017 <span class="comment">// This code is distributed under the GNU Public License</span>
00018 <span class="comment">//      which can be found at http://www.gnu.org/licenses/gpl.txt</span>
00019 <span class="comment">//</span>
00020 <span class="comment">//*****************************************************************************</span>
00021 
00022 <span class="preprocessor">#ifndef WIN32</span>
00023 <span class="preprocessor"></span><span class="preprocessor">    #include &lt;avr/io.h&gt;</span>
00024 <span class="preprocessor">    #include &lt;avr/interrupt.h&gt;</span>
00025 <span class="preprocessor">    #include &lt;avr/pgmspace.h&gt;</span>
00026 <span class="preprocessor">#endif</span>
00027 <span class="preprocessor"></span><span class="preprocessor">#include &lt;string.h&gt;</span>
00028 <span class="preprocessor">#include &lt;stdlib.h&gt;</span>
00029 <span class="preprocessor">#include &lt;math.h&gt;</span>
00030 
00031 <span class="preprocessor">#include "<a class="code" href="global_8h.html">global.h</a>"</span>
00032 <span class="preprocessor">#include "<a class="code" href="buffer_8h.html">buffer.h</a>"</span>
00033 <span class="preprocessor">#include "<a class="code" href="rprintf_8h.html">rprintf.h</a>"</span>
00034 <span class="preprocessor">#include "<a class="code" href="gps_8h.html">gps.h</a>"</span>
00035 
00036 <span class="preprocessor">#include "<a class="code" href="nmea_8h.html">nmea.h</a>"</span>
00037 
00038 <span class="comment">// Program ROM constants</span>
00039 
00040 <span class="comment">// Global variables</span>
00041 <span class="keyword">extern</span> GpsInfoType GpsInfo;
00042 u08 NmeaPacket[NMEA_BUFFERSIZE];
00043 
00044 <span class="keywordtype">void</span> nmeaInit(<span class="keywordtype">void</span>)
00045 {
00046 }
00047 
00048 u08* nmeaGetPacketBuffer(<span class="keywordtype">void</span>)
00049 {
00050     <span class="keywordflow">return</span> NmeaPacket;
00051 }
00052 
00053 u08 nmeaProcess(<a class="code" href="structstruct__cBuffer.html">cBuffer</a>* rxBuffer)
00054 {
00055     u08 foundpacket = NMEA_NODATA;
00056     u08 startFlag = FALSE;
00057     <span class="comment">//u08 data;</span>
00058     u16 i,j;
00059 
00060     <span class="comment">// process the receive buffer</span>
00061     <span class="comment">// go through buffer looking for packets</span>
00062     <span class="keywordflow">while</span>(rxBuffer-&gt;<a class="code" href="structstruct__cBuffer.html#o2">datalength</a>)
00063     {
00064         <span class="comment">// look for a start of NMEA packet</span>
00065         <span class="keywordflow">if</span>(<a class="code" href="group__buffer.html#ga4">bufferGetAtIndex</a>(rxBuffer,0) == <span class="charliteral">'$'</span>)
00066         {
00067             <span class="comment">// found start</span>
00068             startFlag = TRUE;
00069             <span class="comment">// when start is found, we leave it intact in the receive buffer</span>
00070             <span class="comment">// in case the full NMEA string is not completely received.  The</span>
00071             <span class="comment">// start will be detected in the next nmeaProcess iteration.</span>
00072 
00073             <span class="comment">// done looking for start</span>
00074             <span class="keywordflow">break</span>;
00075         }
00076         <span class="keywordflow">else</span>
00077             <a class="code" href="group__buffer.html#ga2">bufferGetFromFront</a>(rxBuffer);
00078     }
00079     
00080     <span class="comment">// if we detected a start, look for end of packet</span>
00081     <span class="keywordflow">if</span>(startFlag)
00082     {
00083         <span class="keywordflow">for</span>(i=1; i&lt;(rxBuffer-&gt;<a class="code" href="structstruct__cBuffer.html#o2">datalength</a>)-1; i++)
00084         {
00085             <span class="comment">// check for end of NMEA packet &lt;CR&gt;&lt;LF&gt;</span>
00086             <span class="keywordflow">if</span>((<a class="code" href="group__buffer.html#ga4">bufferGetAtIndex</a>(rxBuffer,i) == <span class="charliteral">'\r'</span>) &amp;&amp; (<a class="code" href="group__buffer.html#ga4">bufferGetAtIndex</a>(rxBuffer,i+1) == <span class="charliteral">'\n'</span>))
00087             {
00088                 <span class="comment">// have a packet end</span>
00089                 <span class="comment">// dump initial '$'</span>
00090                 <a class="code" href="group__buffer.html#ga2">bufferGetFromFront</a>(rxBuffer);
00091                 <span class="comment">// copy packet to NmeaPacket</span>
00092                 <span class="keywordflow">for</span>(j=0; j&lt;(i-1); j++)
00093                 {
00094                     <span class="comment">// although NMEA strings should be 80 characters or less,</span>
00095                     <span class="comment">// receive buffer errors can generate erroneous packets.</span>
00096                     <span class="comment">// Protect against packet buffer overflow</span>
00097                     <span class="keywordflow">if</span>(j&lt;(NMEA_BUFFERSIZE-1))
00098                         NmeaPacket[j] = <a class="code" href="group__buffer.html#ga2">bufferGetFromFront</a>(rxBuffer);
00099                     <span class="keywordflow">else</span>
00100                         <a class="code" href="group__buffer.html#ga2">bufferGetFromFront</a>(rxBuffer);
00101                 }
00102                 <span class="comment">// null terminate it</span>
00103                 NmeaPacket[j] = 0;
00104                 <span class="comment">// dump &lt;CR&gt;&lt;LF&gt; from rxBuffer</span>
00105                 <a class="code" href="group__buffer.html#ga2">bufferGetFromFront</a>(rxBuffer);
00106                 <a class="code" href="group__buffer.html#ga2">bufferGetFromFront</a>(rxBuffer);
00107 
00108 <span class="preprocessor">                #ifdef NMEA_DEBUG_PKT</span>
00109 <span class="preprocessor"></span>                rprintf(<span class="stringliteral">"Rx NMEA packet type: "</span>);
00110                 <a class="code" href="group__rprintf.html#ga3">rprintfStrLen</a>(NmeaPacket, 0, 5);
00111                 <a class="code" href="group__rprintf.html#ga3">rprintfStrLen</a>(NmeaPacket, 5, (i-1)-5);
00112                 <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00113 <span class="preprocessor">                #endif</span>
00114 <span class="preprocessor"></span>                <span class="comment">// found a packet</span>
00115                 <span class="comment">// done with this processing session</span>
00116                 foundpacket = NMEA_UNKNOWN;
00117                 <span class="keywordflow">break</span>;
00118             }
00119         }
00120     }
00121 
00122     <span class="keywordflow">if</span>(foundpacket)
00123     {
00124         <span class="comment">// check message type and process appropriately</span>
00125         <span class="keywordflow">if</span>(!strncmp(NmeaPacket, <span class="stringliteral">"GPGGA"</span>, 5))
00126         {
00127             <span class="comment">// process packet of this type</span>
00128             nmeaProcessGPGGA(NmeaPacket);
00129             <span class="comment">// report packet type</span>
00130             foundpacket = NMEA_GPGGA;
00131         }
00132         <span class="keywordflow">else</span> <span class="keywordflow">if</span>(!strncmp(NmeaPacket, <span class="stringliteral">"GPVTG"</span>, 5))
00133         {
00134             <span class="comment">// process packet of this type</span>
00135             nmeaProcessGPVTG(NmeaPacket);
00136             <span class="comment">// report packet type</span>
00137             foundpacket = NMEA_GPVTG;
00138         }
00139     }
00140     <span class="keywordflow">else</span> <span class="keywordflow">if</span>(rxBuffer-&gt;<a class="code" href="structstruct__cBuffer.html#o2">datalength</a> &gt;= rxBuffer-&gt;<a class="code" href="structstruct__cBuffer.html#o1">size</a>)
00141     {
00142         <span class="comment">// if we found no packet, and the buffer is full</span>
00143         <span class="comment">// we're logjammed, flush entire buffer</span>
00144         <a class="code" href="group__buffer.html#ga7">bufferFlush</a>(rxBuffer);
00145     }
00146     <span class="keywordflow">return</span> foundpacket;
00147 }
00148 
00149 <span class="keywordtype">void</span> nmeaProcessGPGGA(u08* packet)
00150 {
00151     u08 i;
00152     <span class="keywordtype">char</span>* endptr;
00153     <span class="keywordtype">double</span> degrees, minutesfrac;
00154 
00155 <span class="preprocessor">    #ifdef NMEA_DEBUG_GGA</span>
00156 <span class="preprocessor"></span>    rprintf(<span class="stringliteral">"NMEA: "</span>);
00157     <a class="code" href="group__rprintf.html#ga2">rprintfStr</a>(packet);
00158     <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00159 <span class="preprocessor">    #endif</span>
00160 <span class="preprocessor"></span>
00161     <span class="comment">// start parsing just after "GPGGA,"</span>
00162     i = 6;
00163     <span class="comment">// attempt to reject empty packets right away</span>
00164     <span class="keywordflow">if</span>(packet[i]==<span class="charliteral">','</span> &amp;&amp; packet[i+1]==<span class="charliteral">','</span>)
00165         <span class="keywordflow">return</span>;
00166 
00167     <span class="comment">// get UTC time [hhmmss.sss]</span>
00168     GpsInfo.PosLLA.TimeOfFix.f = strtod(&amp;packet[i], &amp;endptr);
00169     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: latitude</span>
00170     
00171     <span class="comment">// get latitude [ddmm.mmmmm]</span>
00172     GpsInfo.PosLLA.lat.f = strtod(&amp;packet[i], &amp;endptr);
00173     <span class="comment">// convert to pure degrees [dd.dddd] format</span>
00174     minutesfrac = modf(GpsInfo.PosLLA.lat.f/100, &amp;degrees);
00175     GpsInfo.PosLLA.lat.f = degrees + (minutesfrac*100)/60;
00176     <span class="comment">// convert to radians</span>
00177     GpsInfo.PosLLA.lat.f *= (M_PI/180);
00178     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: N/S indicator</span>
00179     
00180     <span class="comment">// correct latitute for N/S</span>
00181     <span class="keywordflow">if</span>(packet[i] == <span class="charliteral">'S'</span>) GpsInfo.PosLLA.lat.f = -GpsInfo.PosLLA.lat.f;
00182     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: longitude</span>
00183     
00184     <span class="comment">// get longitude [ddmm.mmmmm]</span>
00185     GpsInfo.PosLLA.lon.f = strtod(&amp;packet[i], &amp;endptr);
00186     <span class="comment">// convert to pure degrees [dd.dddd] format</span>
00187     minutesfrac = modf(GpsInfo.PosLLA.lon.f/100, &amp;degrees);
00188     GpsInfo.PosLLA.lon.f = degrees + (minutesfrac*100)/60;
00189     <span class="comment">// convert to radians</span>
00190     GpsInfo.PosLLA.lon.f *= (M_PI/180);
00191     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: E/W indicator</span>
00192 
00193     <span class="comment">// correct latitute for E/W</span>
00194     <span class="keywordflow">if</span>(packet[i] == <span class="charliteral">'W'</span>) GpsInfo.PosLLA.lon.f = -GpsInfo.PosLLA.lon.f;
00195     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: position fix status</span>
00196 
00197     <span class="comment">// position fix status</span>
00198     <span class="comment">// 0 = Invalid, 1 = Valid SPS, 2 = Valid DGPS, 3 = Valid PPS</span>
00199     <span class="comment">// check for good position fix</span>
00200     <span class="keywordflow">if</span>( (packet[i] != <span class="charliteral">'0'</span>) &amp;&amp; (packet[i] != <span class="charliteral">','</span>) )
00201         GpsInfo.PosLLA.updates++;
00202     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: satellites used</span>
00203     
00204     <span class="comment">// get number of satellites used in GPS solution</span>
00205     GpsInfo.numSVs = atoi(&amp;packet[i]);
00206     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: HDOP (horizontal dilution of precision)</span>
00207     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: altitude</span>
00208     
00209     <span class="comment">// get altitude (in meters)</span>
00210     GpsInfo.PosLLA.alt.f = strtod(&amp;packet[i], &amp;endptr);
00211 
00212     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: altitude units, always 'M'</span>
00213     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: geoid seperation</span>
00214     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: seperation units</span>
00215     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: DGPS age</span>
00216     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: DGPS station ID</span>
00217     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">'*'</span>);              <span class="comment">// next field: checksum</span>
00218 }
00219 
00220 <span class="keywordtype">void</span> nmeaProcessGPVTG(u08* packet)
00221 {
00222     u08 i;
00223     <span class="keywordtype">char</span>* endptr;
00224 
00225 <span class="preprocessor">    #ifdef NMEA_DEBUG_VTG</span>
00226 <span class="preprocessor"></span>    rprintf(<span class="stringliteral">"NMEA: "</span>);
00227     <a class="code" href="group__rprintf.html#ga2">rprintfStr</a>(packet);
00228     <a class="code" href="group__rprintf.html#ga5">rprintfCRLF</a>();
00229 <span class="preprocessor">    #endif</span>
00230 <span class="preprocessor"></span>
00231     <span class="comment">// start parsing just after "GPVTG,"</span>
00232     i = 6;
00233     <span class="comment">// attempt to reject empty packets right away</span>
00234     <span class="keywordflow">if</span>(packet[i]==<span class="charliteral">','</span> &amp;&amp; packet[i+1]==<span class="charliteral">','</span>)
00235         <span class="keywordflow">return</span>;
00236 
00237     <span class="comment">// get course (true north ref) in degrees [ddd.dd]</span>
00238     GpsInfo.VelHS.heading.f = strtod(&amp;packet[i], &amp;endptr);
00239     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: 'T'</span>
00240     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: course (magnetic north)</span>
00241 
00242     <span class="comment">// get course (magnetic north ref) in degrees [ddd.dd]</span>
00243     <span class="comment">//GpsInfo.VelHS.heading.f = strtod(&amp;packet[i], &amp;endptr);</span>
00244     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: 'M'</span>
00245     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: speed (knots)</span>
00246 
00247     <span class="comment">// get speed in knots</span>
00248     <span class="comment">//GpsInfo.VelHS.speed.f = strtod(&amp;packet[i], &amp;endptr);</span>
00249     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: 'N'</span>
00250     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: speed (km/h)</span>
00251 
00252     <span class="comment">// get speed in km/h</span>
00253     GpsInfo.VelHS.speed.f = strtod(&amp;packet[i], &amp;endptr);
00254     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">','</span>);              <span class="comment">// next field: 'K'</span>
00255     <span class="keywordflow">while</span>(packet[i++] != <span class="charliteral">'*'</span>);              <span class="comment">// next field: checksum</span>
00256 
00257     GpsInfo.VelHS.updates++;
00258 }
00259 
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Sun Oct 29 03:41:07 2006 for Procyon AVRlib by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.4.2 </small></address>
</body>
</html>
{FILE END}
{FOOTER START}

Powered by WebSVN v2.8.3