123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- <sect1 id="driver_nmea.c"><title><filename>nmea_parse.c</filename></title>
- <informaltable frame='all' pgwide='1'>
- <tgroup cols='2'>
- <colspec colname='c1'></colspec>
- <colspec colname='c2'></colspec>
- <spanspec spanname='s1' namest='c1' nameend='c2'></spanspec>
- <!-- Not documented: processGPGBS(), processOHPR(), processPASHR() -->
- <thead>
- <row>
- <entry>Functions:-</entry><entry>Parser for NMEA strings, generic and proprietary.</entry>
- </row>
- </thead>
- <tfoot>
- <row>
- <entry spanname='s1' align='left'>Notes based on code as of Mon Apr 5 21:38:06 2010 -0400.</entry>
- </row>
- </tfoot>
- <tbody>
- <row>
- <entry><function>static void do_lat_lon(char *field[], struct gps_fix_t *out)</function></entry>
- <entry><para>Reads a four element array containing the value and
- hemisphere of the latitude and longitude of a location as text. It
- converts them into signed (-ve for S and W) values. The
- <structname>gps_data_t</structname> structure is updated with the
- new value(s).</para></entry>
- </row>
- <row>
- <entry><function>static void merge_ddmmyy(char *ddmmyy, struct gps_device_t *session)</function></entry>
- <entry><para>If the century has not yet been stored in the nmea
- driver private data, take the supplied ddmmyy date and generate and
- store a ddmmyyyy date, using the century value compiled in from
- <function>timebase.h</function>.</para></entry>
- </row>
- <row>
- <entry><function>static void merge_hhmmss(char *hhmmss, struct gps_device_t *session)</function></entry>
- <entry><para>Stash the present hour value before updating it from
- the incoming data. If the new hour is less than the stashed value,
- we have passed midnight, so update the day value. Finally update the
- minutes, seconds and fractions of a second from the incoming
- data.</para></entry>
- </row>
- <row>
- <entry><function>static gps_mask_t processGPRMC(int count, char *field[], struct gps_device_t *session)</function></entry>
- <entry><para>Handle a $GPRMC sentence stored in an array of strings,
- one member per field.</para><para>Check if the message is stamped
- valid or not.</para><para>If it is invalid, set the status and fix
- mode to NO_FIX and save the corresponding flags locally; also save
- the online flag to indicate we have handled a known
- sentence.</para><para>If the fix is autonomous and valid, start to
- decode the fields.</para><para>First, test if there are enough
- fields available; then handle the date and time via
- <function>merge_ddmmyy()</function> and
- <function>merge_hhmmss()</function>, storing the TIME_SET flag and
- storing the fix time as a UNIX-epoch relative value.</para><para>If
- the sentence time and this fix time are different, we have started a
- new cycle of observation, so update the sentence time and the store
- the CYCLE_START_SET flag.</para><para>Whatever the number of fields,
- store the fix co-ordinates via <function>do_lat_lon()</function>,
- store the speed and the track and save the corresponding
- flags.</para><para>Return the local aggregated flags to allow the
- main copy in the session data to be updated.</para></entry>
- </row>
- <row>
- <entry><function>static gps_mask_t processGPGLL(int count, char *field[], struct gps_device_t *session)</function></entry>
- <entry><para>Preload the local flag with the ERROR_SET
- flag.</para><para>Check that the sentence is usable, exiting with
- the preset error flag if it is not.</para><para>If it is usable,
- clear the local flags and start processing the fields, updating any
- local flag fields on the way.</para><para>If the year is already
- known, update the time and check for the start of cycle (see
- <function>processGPRMC()</function> above).</para><para>Handle the
- fix location and, if the number of received fixes is more than 8 and
- the status is differential, stash the new status as STATUS_DGPS_FIX;
- otherwise stash STATUS_FIX.</para><para>If the present mode is less
- than 2D_FIX, update it to 2D_FIX.</para><para>Write the stashed
- value of newstatus into the session status and return all the
- locally aggregated flags.</para></entry>
- </row>
- <row>
- <entry><function>static gps_mask_t processGPGGA(int c UNUSED, char *field[], struct gps_device_t *session)</function></entry>
- <entry><para>Stash the last fix time. Set the status to the value in
- the message and update the local flag variable.</para><para>If the
- status is STATUS_NO_FIX, exit immediately, returning the locally
- aggregated flags. If there is a fix, process it.</para><para>Handle
- the time as in <function>processGPGLL()</function> above. Handle the
- latitiude and longitude with a call to
- <function>do_lat_lon()</function> above and set the local
- flag.</para><para>Update the <function>satellites_used</function>
- field and stash the altitude.</para><para>If the altitude is empty,
- force the fix mode and status to 2D if it was 3D
- previously.</para><para>If it is not empty, stash the old value of
- altitude and replace it with the new value stashed earlier and set
- the local flag variable. If the mode is presently less than 3D,
- update it to 3D and set the local flag.</para><para>If the stashed
- old altitude is NaN or the stashed fix time and current fix time are
- equal, set the climb rate to 0 otherwise calculate it by dividing
- the altitude difference by the time difference and set the local
- flag.</para><para>If the geoid separation is available, store it,
- otherwise store the value from
- <function>wgs84_separation()</function> that depends on current
- location.</para><para>Finally, return all the locally aggregated
- flags.</para></entry>
- </row>
- <row>
- <entry><function>static gps_mask_t processGPGSA(int count, char *field[], struct gps_device_t *session)</function></entry>
- <entry><para>Start with a simple validity check on the number of
- fields (for i.Trek M3) and bail out with a simple indication of
- on-line status if it fails.</para><para>Set the fix mode from the
- sentence and either clear the local flag variable (if an Antaris
- chipset says we are in dead-reckoning mode) or set the MODE_SET
- flag.</para><para>Update all the DOP fields from the sentence, clear
- the count of used satellites, then scan all the satellite
- data.</para><para>If any satellite is good (prn != 0), store the prn
- and increment the count of used satellites.</para><para>Finally, set
- the local flags to indicate that DOPs are available and return all
- the locally aggregated flags.</para></entry>
- </row>
- <row>
- <entry><function>static gps_mask_t processGPGSV(int count, char *field[], struct gps_device_t *session)</function></entry>
- <entry><para>Check if the sentence has too few fields or the wrong
- number fo fields. In this case, clear the data for all satellites
- and return with an error indication.</para><para>Start to parse the
- sentence. First, note how many sentences are to be expected to
- complete the data transfer.</para><para>If the sentence number is
- invalid, clear the data for all satellites and return with an error
- indication.</para><para>If this is the first sentence of the
- sequence, clear the data for all satellites.</para><para>Loop
- through the sentence fields, updating the session's satellite
- data.</para><para>If any satellite number is higher than the number
- of channels, clear all satellite data and break out of the
- loop.</para><para>Assuming this is not a buggy chipset
- (e.g. Motorola Oncore GT+), update the satellite count and loop
- again.</para><para>If this was the last sentence of the block and
- the number of satellites seen is not the same as the number
- reported, generate an error log.</para><para>If this is not the last
- sentence of the block, exit early and return an error flag as a
- guard.</para><para>Finally, on the last sentence, carry out a sanity
- check and either return an error flag or a SATELLITE_SET
- flag.</para></entry>
- </row>
- <row>
- <entry><function>static gps_mask_t processPGRME(int c UNUSED, char *field[], struct gps_device_t *session)</function></entry>
- <entry><para>Check that the error estimate data is good. If not, set
- all error estimate fields to 100m and return an error
- flag.</para><para>If they are good, calculate the error value and
- store it. Return the appropriate flag values.</para></entry>
- </row>
- <row>
- <entry><function>static gps_mask_t processGPZDA(int c UNUSED, char *field[], struct gps_device_t *session)</function></entry>
- <entry><para>Set the local flag variable to indicate that the time
- is available.</para><para>Store the actual time by a call to
- <function>merge_hhmmss()</function> and fill in the other fields
- from the sentence data.</para><para>If the sentence is not
- timestamped the same as the fixtime, set the CYCLE_START_SET
- flag.</para><para>Update the fixtime to the sentence
- timestamp.</para><para>Finally, return all the locally aggregated
- flags.</para></entry>
- </row>
- <row>
- <entry><function>static gps_mask_t processTNTHTM(int c UNUSED, char *field[], struct gps_device_t *session)</function></entry>
- <entry><para>Set the local variable to indicate the unit is
- on-line.</para><para>Fill all appropriate fields from the sentence
- and set the associated flags in the local flag
- variable.</para><para>Set the fix status and return all the locally
- aggregated flags.</para></entry>
- </row>
- <row>
- <entry><function>static short nmea_checksum(char *sentence, unsigned char *correct_sum)</function></entry>
- <entry><para>Calculate and return the checksum of an NMEA sentence.</para></entry>
- </row>
- <row>
- <entry><function>gps_mask_t nmea_parse(char *sentence, struct gps_device_t *session)</function></entry>
- <entry><para>Test that the length of the NMEA sentence is
- acceptable, simply returning an on-line indication if it is too long
- to handle.</para><para>If it is within limits, make a local copy and
- split it on the commas into an array, one field per
- element.</para><para>Use the first element to match the command to
- the table of decodable commands.</para><para>Check if it is
- supported and the number of fields is reasonable, invoke the correct
- decoder and return the value from that call.</para><para>If it fails
- the check, simply return an on-line status.</para><para>This function is
- also responsible for performing adaptive end-of-cycle
- detection.</para></entry>
- </row>
- <row>
- <entry><function>void nmea_add_checksum(char *sentence)</function></entry>
- <entry><para>Calculate the checksum then append '*' + the checksum + CR/LF to the end of an NMEA sentence, skipping any existing '*'.</para></entry>
- </row>
- <row>
- <entry><function>int nmea_write(struct gps_device_t *session, const char *fmt, ... )</function></entry>
- <entry><para>Ship a string to an NMEA device, adding a checksum and
- CR/LF if needed. A checksum is added only if the sentence begins
- with '$'. Bytes written are returned.</para></entry>
- </row>
- <row>
- <entry><function>int nmea_send(struct gps_device_t *session, , const char *fmt, ... )</function></entry>
- <entry><para>A wrapper around <function>nmea_write()</function> to
- give it sprintf-like varargs behavior.</para></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </sect1>
|