Devuan fork of gpsd
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

209 lines
11 KiB

  1. <sect1 id="driver_nmea.c"><title><filename>nmea_parse.c</filename></title>
  2. <informaltable frame='all' pgwide='1'>
  3. <tgroup cols='2'>
  4. <colspec colname='c1'></colspec>
  5. <colspec colname='c2'></colspec>
  6. <spanspec spanname='s1' namest='c1' nameend='c2'></spanspec>
  7. <!-- Not documented: processGPGBS(), processOHPR(), processPASHR() -->
  8. <thead>
  9. <row>
  10. <entry>Functions:-</entry><entry>Parser for NMEA strings, generic and proprietary.</entry>
  11. </row>
  12. </thead>
  13. <tfoot>
  14. <row>
  15. <entry spanname='s1' align='left'>Notes based on code as of Mon Apr 5 21:38:06 2010 -0400.</entry>
  16. </row>
  17. </tfoot>
  18. <tbody>
  19. <row>
  20. <entry><function>static void do_lat_lon(char *field[], struct gps_fix_t *out)</function></entry>
  21. <entry><para>Reads a four element array containing the value and
  22. hemisphere of the latitude and longitude of a location as text. It
  23. converts them into signed (-ve for S and W) values. The
  24. <structname>gps_data_t</structname> structure is updated with the
  25. new value(s).</para></entry>
  26. </row>
  27. <row>
  28. <entry><function>static void merge_ddmmyy(char *ddmmyy, struct gps_device_t *session)</function></entry>
  29. <entry><para>If the century has not yet been stored in the nmea
  30. driver private data, take the supplied ddmmyy date and generate and
  31. store a ddmmyyyy date, using the century value compiled in from
  32. <function>gpsd.h</function>.</para></entry>
  33. </row>
  34. <row>
  35. <entry><function>static void merge_hhmmss(char *hhmmss, struct gps_device_t *session)</function></entry>
  36. <entry><para>Stash the present hour value before updating it from
  37. the incoming data. If the new hour is less than the stashed value,
  38. we have passed midnight, so update the day value. Finally update the
  39. minutes, seconds and fractions of a second from the incoming
  40. data.</para></entry>
  41. </row>
  42. <row>
  43. <entry><function>static gps_mask_t processGPRMC(int count, char *field[], struct gps_device_t *session)</function></entry>
  44. <entry><para>Handle a $GPRMC sentence stored in an array of strings,
  45. one member per field.</para><para>Check if the message is stamped
  46. valid or not.</para><para>If it is invalid, set the status and fix
  47. mode to NO_FIX and save the corresponding flags locally; also save
  48. the online flag to indicate we have handled a known
  49. sentence.</para><para>If the fix is autonomous and valid, start to
  50. decode the fields.</para><para>First, test if there are enough
  51. fields available; then handle the date and time via
  52. <function>merge_ddmmyy()</function> and
  53. <function>merge_hhmmss()</function>, storing the TIME_SET flag and
  54. storing the fix time as a UNIX-epoch relative value.</para><para>If
  55. the sentence time and this fix time are different, we have started a
  56. new cycle of observation, so update the sentence time and the store
  57. the CYCLE_START_SET flag.</para><para>Whatever the number of fields,
  58. store the fix co-ordinates via <function>do_lat_lon()</function>,
  59. store the speed and the track and save the corresponding
  60. flags.</para><para>Return the local aggregated flags to allow the
  61. main copy in the session data to be updated.</para></entry>
  62. </row>
  63. <row>
  64. <entry><function>static gps_mask_t processGPGLL(int count, char *field[], struct gps_device_t *session)</function></entry>
  65. <entry><para>Preload the local flag with the ERROR_SET
  66. flag.</para><para>Check that the sentence is usable, exiting with
  67. the preset error flag if it is not.</para><para>If it is usable,
  68. clear the local flags and start processing the fields, updating any
  69. local flag fields on the way.</para><para>If the year is already
  70. known, update the time and check for the start of cycle (see
  71. <function>processGPRMC()</function> above).</para><para>Handle the
  72. fix location and, if the number of received fixes is more than 8 and
  73. the status is differential, stash the new status as STATUS_DGPS_FIX;
  74. otherwise stash STATUS_FIX.</para><para>If the present mode is less
  75. than 2D_FIX, update it to 2D_FIX.</para><para>Write the stashed
  76. value of newstatus into the session status and return all the
  77. locally aggregated flags.</para></entry>
  78. </row>
  79. <row>
  80. <entry><function>static gps_mask_t processGPGGA(int c UNUSED, char *field[], struct gps_device_t *session)</function></entry>
  81. <entry><para>Stash the last fix time. Set the status to the value in
  82. the message and update the local flag variable.</para><para>If the
  83. status is STATUS_NO_FIX, exit immediately, returning the locally
  84. aggregated flags. If there is a fix, process it.</para><para>Handle
  85. the time as in <function>processGPGLL()</function> above. Handle the
  86. latitiude and longitude with a call to
  87. <function>do_lat_lon()</function> above and set the local
  88. flag.</para><para>Update the <function>satellites_used</function>
  89. field and stash the altitude.</para><para>If the altitude is empty,
  90. force the fix mode and status to 2D if it was 3D
  91. previously.</para><para>If it is not empty, stash the old value of
  92. altitude and replace it with the new value stashed earlier and set
  93. the local flag variable. If the mode is presently less than 3D,
  94. update it to 3D and set the local flag.</para><para>If the stashed
  95. old altitude is NaN or the stashed fix time and current fix time are
  96. equal, set the climb rate to 0 otherwise calculate it by dividing
  97. the altitude difference by the time difference and set the local
  98. flag.</para><para>If the geoid separation is available, store it,
  99. otherwise store the value from
  100. <function>wgs84_separation()</function> that depends on current
  101. location.</para><para>Finally, return all the locally aggregated
  102. flags.</para></entry>
  103. </row>
  104. <row>
  105. <entry><function>static gps_mask_t processGPGSA(int count, char *field[], struct gps_device_t *session)</function></entry>
  106. <entry><para>Start with a simple validity check on the number of
  107. fields (for i.Trek M3) and bail out with a simple indication of
  108. on-line status if it fails.</para><para>Set the fix mode from the
  109. sentence and either clear the local flag variable (if an Antaris
  110. chipset says we are in dead-reckoning mode) or set the MODE_SET
  111. flag.</para><para>Update all the DOP fields from the sentence, clear
  112. the count of used satellites, then scan all the satellite
  113. data.</para><para>If any satellite is good (prn != 0), store the prn
  114. and increment the count of used satellites.</para><para>Finally, set
  115. the local flags to indicate that DOPs are available and return all
  116. the locally aggregated flags.</para></entry>
  117. </row>
  118. <row>
  119. <entry><function>static gps_mask_t processGPGSV(int count, char *field[], struct gps_device_t *session)</function></entry>
  120. <entry><para>Check if the sentence has too few fields or the wrong
  121. number fo fields. In this case, clear the data for all satellites
  122. and return with an error indication.</para><para>Start to parse the
  123. sentence. First, note how many sentences are to be expected to
  124. complete the data transfer.</para><para>If the sentence number is
  125. invalid, clear the data for all satellites and return with an error
  126. indication.</para><para>If this is the first sentence of the
  127. sequence, clear the data for all satellites.</para><para>Loop
  128. through the sentence fields, updating the session's satellite
  129. data.</para><para>If any satellite number is higher than the number
  130. of channels, clear all satellite data and break out of the
  131. loop.</para><para>Assuming this is not a buggy chipset
  132. (e.g. Motorola Oncore GT+), update the satellite count and loop
  133. again.</para><para>If this was the last sentence of the block and
  134. the number of satellites seen is not the same as the number
  135. reported, generate an error log.</para><para>If this is not the last
  136. sentence of the block, exit early and return an error flag as a
  137. guard.</para><para>Finally, on the last sentence, carry out a sanity
  138. check and either return an error flag or a SATELLITE_SET
  139. flag.</para></entry>
  140. </row>
  141. <row>
  142. <entry><function>static gps_mask_t processPGRME(int c UNUSED, char *field[], struct gps_device_t *session)</function></entry>
  143. <entry><para>Check that the error estimate data is good. If not, set
  144. all error estimate fields to 100m and return an error
  145. flag.</para><para>If they are good, calculate the error value and
  146. store it. Return the appropriate flag values.</para></entry>
  147. </row>
  148. <row>
  149. <entry><function>static gps_mask_t processGPZDA(int c UNUSED, char *field[], struct gps_device_t *session)</function></entry>
  150. <entry><para>Set the local flag variable to indicate that the time
  151. is available.</para><para>Store the actual time by a call to
  152. <function>merge_hhmmss()</function> and fill in the other fields
  153. from the sentence data.</para><para>If the sentence is not
  154. timestamped the same as the fixtime, set the CYCLE_START_SET
  155. flag.</para><para>Update the fixtime to the sentence
  156. timestamp.</para><para>Finally, return all the locally aggregated
  157. flags.</para></entry>
  158. </row>
  159. <row>
  160. <entry><function>static gps_mask_t processTNTHTM(int c UNUSED, char *field[], struct gps_device_t *session)</function></entry>
  161. <entry><para>Set the local variable to indicate the unit is
  162. on-line.</para><para>Fill all appropriate fields from the sentence
  163. and set the associated flags in the local flag
  164. variable.</para><para>Set the fix status and return all the locally
  165. aggregated flags.</para></entry>
  166. </row>
  167. <row>
  168. <entry><function>static short nmea_checksum(char *sentence, unsigned char *correct_sum)</function></entry>
  169. <entry><para>Calculate and return the checksum of an NMEA sentence.</para></entry>
  170. </row>
  171. <row>
  172. <entry><function>gps_mask_t nmea_parse(char *sentence, struct gps_device_t *session)</function></entry>
  173. <entry><para>Test that the length of the NMEA sentence is
  174. acceptable, simply returning an on-line indication if it is too long
  175. to handle.</para><para>If it is within limits, make a local copy and
  176. split it on the commas into an array, one field per
  177. element.</para><para>Use the first element to match the command to
  178. the table of decodable commands.</para><para>Check if it is
  179. supported and the number of fields is reasonable, invoke the correct
  180. decoder and return the value from that call.</para><para>If it fails
  181. the check, simply return an on-line status.</para><para>This function is
  182. also responsible for performing adaptive end-of-cycle
  183. detection.</para></entry>
  184. </row>
  185. <row>
  186. <entry><function>void nmea_add_checksum(char *sentence)</function></entry>
  187. <entry><para>Calculate the checksum then append '*' + the checksum + CR/LF to the end of an NMEA sentence, skipping any existing '*'.</para></entry>
  188. </row>
  189. <row>
  190. <entry><function>int nmea_write(struct gps_device_t *session, const char *fmt, ... )</function></entry>
  191. <entry><para>Ship a string to an NMEA device, adding a checksum and
  192. CR/LF if needed. A checksum is added only if the sentence begins
  193. with '$'. Bytes written are returned.</para></entry>
  194. </row>
  195. <row>
  196. <entry><function>int nmea_send(struct gps_device_t *session, , const char *fmt, ... )</function></entry>
  197. <entry><para>A wrapper around <function>nmea_write()</function> to
  198. give it sprintf-like varargs behavior.</para></entry>
  199. </row>
  200. </tbody>
  201. </tgroup>
  202. </informaltable>
  203. </sect1>