Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2136 | - | 1 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
||
3 | |||
4 | //############################################################################ |
||
5 | //# HISTORY nmea.c |
||
6 | //# |
||
7 | //# 08.08.2015 CB |
||
8 | //# - add: Einführung eines neuen Interruptbasierten NMEA Parsers |
||
9 | //# cpp-Code auf c geändert und an PKT angepasst |
||
10 | //# |
||
11 | //############################################################################ |
||
12 | |||
13 | /* URSPRUNG: |
||
14 | File: nmea.cpp |
||
15 | Version: 0.1.0 |
||
16 | Date: Feb. 23, 2013 |
||
17 | License: GPL v2 |
||
18 | |||
19 | NMEA GPS content parser |
||
20 | |||
21 | **************************************************************************** |
||
22 | Copyright (C) 2013 Radu Motisan <radu.motisan@gmail.com> |
||
23 | |||
24 | http://www.pocketmagic.net |
||
25 | |||
26 | This program is free software; you can redistribute it and/or modify |
||
27 | it under the terms of the GNU General Public License as published by |
||
28 | the Free Software Foundation; either version 2 of the License, or |
||
29 | (at your option) any later version. |
||
30 | |||
31 | This program is distributed in the hope that it will be useful, |
||
32 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
33 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
34 | GNU General Public License for more details. |
||
35 | |||
36 | You should have received a copy of the GNU General Public License |
||
37 | along with this program; if not, write to the Free Software |
||
38 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
39 | **************************************************************************** |
||
40 | */ |
||
41 | |||
42 | #include "nmea.h" |
||
43 | #include "../timer/timer.h" |
||
44 | //#include <stdio.h> |
||
45 | //#include <stdlib.h> |
||
46 | //#include <util/delay.h> |
||
47 | #include <stdbool.h> |
||
48 | |||
49 | |||
50 | #define MAX_POWER 10 |
||
51 | #define getPower(x) (int32_t)pgm_read_dword(&powers[x]) |
||
52 | static const int32_t powers[MAX_POWER] PROGMEM = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; |
||
53 | |||
54 | uint8_t m_bFlagRead, // flag used by the parser, when a valid sentence has begun |
||
55 | m_bFlagDataReady = false; // valid GPS fix and data available, user can call reader functions |
||
56 | volatile uint32_t res_nNMEAcounter = 0; // NMEA Datensatzzähler |
||
57 | volatile uint32_t res_nCRCerror = 0; // zählt die CRC Errors beim dekodieren |
||
58 | uint8_t receiveNMEA = false; |
||
59 | char tmp_words[20][15], // hold parsed words for one given NMEA sentence |
||
60 | tmp_szChecksum[15]; // hold the received checksum for one given NMEA sentence |
||
61 | |||
62 | // will be set to true for characters between $ and * only |
||
63 | bool m_bFlagComputedCks ; // used to compute checksum and indicate valid checksum interval (between $ and * in a given sentence) |
||
64 | int m_nChecksum ; // numeric checksum, computed for a given sentence |
||
65 | bool m_bFlagReceivedCks ; // after getting * we start cuttings the received checksum |
||
66 | int index_received_checksum ; // used to parse received checksum |
||
67 | |||
68 | // word cutting variables |
||
69 | int m_nWordIdx , // the current word in a sentence |
||
70 | m_nPrevIdx, // last character index where we did a cut |
||
71 | m_nNowIdx ; // current character index |
||
72 | |||
73 | // globals to store parser results |
||
74 | int32_t res_fLongitude; // GPRMC and GPGGA |
||
75 | int32_t res_fLatitude; // GPRMC and GPGGA |
||
76 | unsigned char res_nUTCHour, res_nUTCMin, res_nUTCSec, // GPRMC and GPGGA |
||
77 | res_nUTCDay, res_nUTCMonth, res_nUTCYear; // GPRMC |
||
78 | char Time[9]; // GPRMC and GPGGA |
||
79 | uint8_t res_nSatellitesUsed; // GPGGA |
||
80 | uint8_t res_nGPSfix; // GPGGA |
||
81 | int16_t res_nHDOP; // GPGGA |
||
82 | int16_t res_fAltitude; // GPGGA |
||
83 | float res_fSpeed; // GPRMC |
||
84 | int16_t res_fBearing; // GPRMC |
||
85 | |||
86 | NMEA_GPGGA_t NMEA; // Variable mit der Struktur für die NMEA Daten für PKT |
||
87 | |||
88 | // the parser, currently handling GPRMC and GPGGA, but easy to add any new sentences |
||
89 | // void parsedata(); |
||
90 | // aux functions |
||
91 | int digit2dec(char hexdigit); |
||
92 | float string2float(char* s); |
||
93 | int mstrcmp(const char *s1, const char *s2); |
||
94 | |||
95 | |||
96 | |||
97 | |||
98 | /* |
||
99 | * The serial data is assembled on the fly, without using any redundant buffers. |
||
100 | * When a sentence is complete (one that starts with $, ending in EOL), all processing is done on |
||
101 | * this temporary buffer that we've built: checksum computation, extracting sentence "words" (the CSV values), |
||
102 | * and so on. |
||
103 | * When a new sentence is fully assembled using the fusedata function, the code calls parsedata. |
||
104 | * This function in turn, splits the sentences and interprets the data. Here is part of the parser function, |
||
105 | * handling both the $GPRMC NMEA sentence: |
||
106 | */ |
||
107 | uint8_t fusedata(char c) |
||
108 | |||
109 | { |
||
110 | |||
111 | if (c == '$') { |
||
112 | m_bFlagRead = true; |
||
113 | // init parser vars |
||
114 | m_bFlagComputedCks = false; |
||
115 | m_nChecksum = 0; |
||
116 | // after getting * we start cuttings the received m_nChecksum |
||
117 | m_bFlagReceivedCks = false; |
||
118 | index_received_checksum = 0; |
||
119 | // word cutting variables |
||
120 | m_nWordIdx = 0; m_nPrevIdx = 0; m_nNowIdx = 0; |
||
121 | timer_nmea_timeout = NMEA_TIMEOUT; // Timeout Timer setzen |
||
122 | } |
||
123 | |||
124 | if (m_bFlagRead) { |
||
125 | // check ending |
||
126 | if (c == '\r' || c== '\n') { |
||
127 | // catch last ending item too |
||
128 | tmp_words[m_nWordIdx][m_nNowIdx - m_nPrevIdx] = 0; |
||
129 | m_nWordIdx++; |
||
130 | // cut received m_nChecksum |
||
131 | tmp_szChecksum[index_received_checksum] = 0; |
||
132 | // sentence complete, read done |
||
133 | m_bFlagRead = false; |
||
134 | // parse |
||
135 | parsedata(); |
||
136 | } else { |
||
137 | // computed m_nChecksum logic: count all chars between $ and * exclusively |
||
138 | if (m_bFlagComputedCks && c == '*') m_bFlagComputedCks = false; |
||
139 | if (m_bFlagComputedCks) m_nChecksum ^= c; |
||
140 | if (c == '$') m_bFlagComputedCks = true; |
||
141 | // received m_nChecksum |
||
142 | if (m_bFlagReceivedCks) { |
||
143 | tmp_szChecksum[index_received_checksum] = c; |
||
144 | index_received_checksum++; |
||
145 | } |
||
146 | if (c == '*') m_bFlagReceivedCks = true; |
||
147 | // build a word |
||
148 | tmp_words[m_nWordIdx][m_nNowIdx - m_nPrevIdx] = c; |
||
149 | if (c == ',') { |
||
150 | tmp_words[m_nWordIdx][m_nNowIdx - m_nPrevIdx] = 0; |
||
151 | m_nWordIdx++; |
||
152 | m_nPrevIdx = m_nNowIdx; |
||
153 | } |
||
154 | else m_nNowIdx++; |
||
155 | } |
||
156 | } |
||
157 | return m_nWordIdx; |
||
158 | } |
||
159 | |||
160 | |||
161 | /* |
||
162 | * parse internal tmp_ structures, fused by pushdata, and set the data flag when done |
||
163 | */ |
||
164 | void parsedata(void) { |
||
165 | int received_cks = 16*digit2dec(tmp_szChecksum[0]) + digit2dec(tmp_szChecksum[1]); |
||
166 | //uart1.Send("seq: [cc:%X][words:%d][rc:%s:%d]\r\n", m_nChecksum,m_nWordIdx, tmp_szChecksum, received_cks); |
||
167 | // check checksum, and return if invalid! |
||
168 | if (m_nChecksum != received_cks) { |
||
169 | m_bFlagDataReady = false; |
||
170 | res_nCRCerror = res_nCRCerror+1; |
||
171 | return; |
||
172 | } |
||
173 | /* $GPGGA |
||
174 | * $GPGGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh |
||
175 | * ex: $GPGGA,230600.501,4543.8895,N,02112.7238,E,1,03,3.3,96.7,M,39.0,M,,0000*6A, |
||
176 | * |
||
177 | * WORDS: |
||
178 | * 1 = UTC of Position |
||
179 | * 2 = Latitude |
||
180 | * 3 = N or S |
||
181 | * 4 = Longitude |
||
182 | * 5 = E or W |
||
183 | * 6 = GPS quality indicator (0=invalid; 1=GPS fix; 2=Diff. GPS fix) |
||
184 | * 7 = Number of satellites in use [not those in view] |
||
185 | * 8 = Horizontal dilution of position |
||
186 | * 9 = Antenna altitude above/below mean sea level (geoid) |
||
187 | * 10 = Meters (Antenna height unit) |
||
188 | * 11 = Geoidal separation (Diff. between WGS-84 earth ellipsoid and mean sea level. |
||
189 | * -geoid is below WGS-84 ellipsoid) |
||
190 | * 12 = Meters (Units of geoidal separation) |
||
191 | * 13 = Age in seconds since last update from diff. reference station |
||
192 | * 14 = Diff. reference station ID# |
||
193 | * 15 = Checksum |
||
194 | */ |
||
195 | if (mstrcmp(tmp_words[0], "$GPGGA") == 0) { |
||
196 | // Check GPS Fix: 0=no fix, 1=GPS fix, 2=Dif. GPS fix |
||
197 | res_nGPSfix = atoi(&tmp_words[6][0]); |
||
198 | NMEA.SatFix = res_nGPSfix; |
||
199 | if (tmp_words[6][0] == '0') { |
||
200 | // clear data |
||
201 | res_fLatitude = 0; |
||
202 | res_fLongitude = 0; |
||
203 | // m_bFlagDataReady = false; |
||
204 | |||
205 | // return; |
||
206 | } |
||
207 | // parse time |
||
208 | res_nUTCHour = digit2dec(tmp_words[1][0]) * 10 + digit2dec(tmp_words[1][1]); |
||
209 | res_nUTCMin = digit2dec(tmp_words[1][2]) * 10 + digit2dec(tmp_words[1][3]); |
||
210 | res_nUTCSec = digit2dec(tmp_words[1][4]) * 10 + digit2dec(tmp_words[1][5]); |
||
211 | NMEA_getTime (tmp_words[1]); |
||
212 | |||
213 | // parse latitude and longitude in NMEA format |
||
214 | // res_fLatitude = string2float(tmp_words[2]); |
||
215 | // res_fLongitude = string2float(tmp_words[4]); |
||
216 | |||
217 | // get decimal format |
||
218 | // if (tmp_words[3][0] == 'S') res_fLatitude *= -1.0; |
||
219 | // if (tmp_words[5][0] == 'W') res_fLongitude *= -1.0; |
||
220 | // float degrees = trunc(res_fLatitude / 100.0f); |
||
221 | // float minutes = res_fLatitude - (degrees * 100.0f); |
||
222 | // res_fLatitude = degrees + minutes / 60.0f; |
||
223 | // degrees = trunc(res_fLongitude / 100.0f); |
||
224 | // minutes = res_fLongitude - (degrees * 100.0f); |
||
225 | // res_fLongitude = degrees + minutes / 60.0f; |
||
226 | |||
227 | res_fLatitude = NMEA_calcLatitude(tmp_words[2],tmp_words[3]); |
||
228 | res_fLongitude = NMEA_calcLongitude(tmp_words[4],tmp_words[5]); |
||
229 | NMEA.Latitude = res_fLatitude; |
||
230 | NMEA.Longitude = res_fLongitude; |
||
231 | // parse number of satellites |
||
232 | res_nSatellitesUsed = (int)string2float(tmp_words[7]); |
||
233 | NMEA.SatsInUse = atoi(tmp_words[7]); |
||
234 | // parse HDOP |
||
235 | res_nHDOP = NMEA_floatStrToInt(tmp_words[8],1); |
||
236 | NMEA.HDOP = res_nHDOP; |
||
237 | |||
238 | // parse altitude |
||
239 | // res_fAltitude = string2float(tmp_words[9]); |
||
240 | res_fAltitude = NMEA_floatStrToInt( tmp_words[9], 1); |
||
241 | NMEA.Altitude = res_fAltitude; |
||
242 | // data ready |
||
243 | m_bFlagDataReady = true; |
||
244 | res_nNMEAcounter = res_nNMEAcounter +1; |
||
245 | NMEA.Counter = res_nNMEAcounter; |
||
246 | |||
247 | } |
||
248 | |||
249 | // 8.8.2015 CB wird zur Zeit nicht benötigt |
||
250 | /* $GPRMC |
||
251 | * note: a siRF chipset will not support magnetic headers. |
||
252 | * $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh |
||
253 | * ex: $GPRMC,230558.501,A,4543.8901,N,02112.7219,E,1.50,181.47,230213,,,A*66, |
||
254 | * |
||
255 | * WORDS: |
||
256 | * 1 = UTC of position fix |
||
257 | * 2 = Data status (V=navigation receiver warning) |
||
258 | * 3 = Latitude of fix |
||
259 | * 4 = N or S |
||
260 | * 5 = Longitude of fix |
||
261 | * 6 = E or W |
||
262 | * 7 = Speed over ground in knots |
||
263 | * 8 = Track made good in degrees True, Bearing This indicates the direction that the device is currently moving in, |
||
264 | * from 0 to 360, measured in “azimuth”. |
||
265 | * 9 = UT date |
||
266 | * 10 = Magnetic variation degrees (Easterly var. subtracts from true course) |
||
267 | * 11 = E or W |
||
268 | * 12 = Checksum |
||
269 | */ |
||
270 | // if (mstrcmp(tmp_words[0], "$GPRMC") == 0) { |
||
271 | // // Check data status: A-ok, V-invalid |
||
272 | // if (tmp_words[2][0] == 'V') { |
||
273 | // // clear data |
||
274 | // res_fLatitude = 0; |
||
275 | // res_fLongitude = 0; |
||
276 | //// m_bFlagDataReady = false; |
||
277 | // return; |
||
278 | // } |
||
279 | //// // parse time |
||
280 | //// res_nUTCHour = digit2dec(tmp_words[1][0]) * 10 + digit2dec(tmp_words[1][1]); |
||
281 | //// res_nUTCMin = digit2dec(tmp_words[1][2]) * 10 + digit2dec(tmp_words[1][3]); |
||
282 | //// res_nUTCSec = digit2dec(tmp_words[1][4]) * 10 + digit2dec(tmp_words[1][5]); |
||
283 | //// // parse latitude and longitude in NMEA format |
||
284 | //// res_fLatitude = string2float(tmp_words[3]); |
||
285 | //// res_fLongitude = string2float(tmp_words[5]); |
||
286 | //// // get decimal format |
||
287 | //// if (tmp_words[4][0] == 'S') res_fLatitude *= -1.0; |
||
288 | //// if (tmp_words[6][0] == 'W') res_fLongitude *= -1.0; |
||
289 | //// float degrees = trunc(res_fLatitude / 100.0f); |
||
290 | //// float minutes = res_fLatitude - (degrees * 100.0f); |
||
291 | //// res_fLatitude = degrees + minutes / 60.0f; |
||
292 | //// degrees = trunc(res_fLongitude / 100.0f); |
||
293 | //// minutes = res_fLongitude - (degrees * 100.0f); |
||
294 | //// res_fLongitude = degrees + minutes / 60.0f; |
||
295 | // //parse speed |
||
296 | // // The knot (pronounced not) is a unit of speed equal to one nautical mile (1.852 km) per hour |
||
297 | // res_fSpeed = NMEA_floatStrToInt(tmp_words[7],1); |
||
298 | // res_fSpeed /= 1.852; // convert to km/h |
||
299 | // // parse bearing |
||
300 | // res_fBearing = NMEA_floatStrToInt(tmp_words[8],1); |
||
301 | //// // parse UTC date |
||
302 | //// res_nUTCDay = digit2dec(tmp_words[9][0]) * 10 + digit2dec(tmp_words[9][1]); |
||
303 | //// res_nUTCMonth = digit2dec(tmp_words[9][2]) * 10 + digit2dec(tmp_words[9][3]); |
||
304 | //// res_nUTCYear = digit2dec(tmp_words[9][4]) * 10 + digit2dec(tmp_words[9][5]); |
||
305 | // |
||
306 | // // data ready |
||
307 | // res_nNMEAcounter = res_nNMEAcounter +1; |
||
308 | // NMEA.Counter = res_nNMEAcounter; |
||
309 | // m_bFlagDataReady = true; |
||
310 | // } |
||
311 | } |
||
312 | |||
313 | |||
314 | |||
315 | //-------------------------------------------------------------- |
||
316 | // NMEA latitudes are in the form ddmm.mmmmm, we want an integer in 1E-7 degree steps |
||
317 | //-------------------------------------------------------------- |
||
318 | int32_t NMEA_calcLatitude( const char *s, const char *NS) |
||
319 | { |
||
320 | int32_t deg; |
||
321 | int32_t min; |
||
322 | |||
323 | //lcdx_puts_at(0,5,NS,0,0,0); |
||
324 | deg = (s[0] - '0') * 10 + s[1] - '0'; // First 2 chars are full degrees |
||
325 | min = NMEA_floatStrToInt( &s[2], 6) / 6; // Minutes * 1E5 * 100 / 60 = Minutes * 1E6 / 6 = 1E-7 degree steps |
||
326 | |||
327 | deg = deg * 10000000 + min; |
||
328 | |||
329 | if( *NS == 'S' ) |
||
330 | { |
||
331 | deg = -deg; |
||
332 | } |
||
333 | |||
334 | return deg; |
||
335 | } |
||
336 | |||
337 | |||
338 | |||
339 | //-------------------------------------------------------------- |
||
340 | // NMEA longitudes are in the form dddmm.mmmmm, we want an integer in 1E-7 degree steps |
||
341 | //-------------------------------------------------------------- |
||
342 | int32_t NMEA_calcLongitude( const char *s, const char *WE) |
||
343 | { |
||
344 | int32_t deg; |
||
345 | int32_t min; |
||
346 | |||
347 | //lcdx_puts_at(10,5,WE,0,0,0); |
||
348 | deg = ((s[0] - '0') * 10 + s[1] - '0') * 10 + s[2] - '0'; // First 3 chars are full degrees |
||
349 | min = NMEA_floatStrToInt( &s[3], 6) / 6; // Minutes * 1E5 * 100 / 60 = Minutes * 1E6 / 6 = 1E-7 degree steps |
||
350 | |||
351 | deg = deg * 10000000 + min; |
||
352 | |||
353 | if( *WE == 'W' ) |
||
354 | { |
||
355 | deg = -deg; |
||
356 | } |
||
357 | |||
358 | return deg; |
||
359 | } |
||
360 | |||
361 | //-------------------------------------------------------------- |
||
362 | void NMEA_getTime( const char *s) |
||
363 | { |
||
364 | uint8_t sem = 0; |
||
365 | uint8_t i; |
||
366 | |||
367 | for( i=0; i<6; i++ ) |
||
368 | { |
||
369 | NMEA.Time[sem++] = s[i]; |
||
370 | |||
371 | if( i==1 || i==3) |
||
372 | NMEA.Time[sem++] = ':'; |
||
373 | |||
374 | } |
||
375 | NMEA.Time[sem] = '\0'; |
||
376 | } |
||
377 | |||
378 | //-------------------------------------------------------------- |
||
379 | /* |
||
380 | * returns base-16 value of chars '0'-'9' and 'A'-'F'; |
||
381 | * does not trap invalid chars! |
||
382 | */ |
||
383 | int digit2dec(char digit) |
||
384 | { |
||
385 | if ((int)digit >= 65) |
||
386 | return ((int)digit - 55); |
||
387 | else |
||
388 | return ((int)digit - 48); |
||
389 | } |
||
390 | |||
391 | //-------------------------------------------------------------- |
||
392 | /* returns base-10 value of zero-terminated string |
||
393 | * that contains only chars '+','-','0'-'9','.'; |
||
394 | * does not trap invalid strings! |
||
395 | */ |
||
396 | float string2float(char* s) { |
||
397 | long integer_part = 0; |
||
398 | float decimal_part = 0.0; |
||
399 | float decimal_pivot = 0.1; |
||
400 | bool isdecimal = false, isnegative = false; |
||
401 | |||
402 | char c; |
||
403 | while ( ( c = *s++) ) { |
||
404 | // skip special/sign chars |
||
405 | if (c == '-') { isnegative = true; continue; } |
||
406 | if (c == '+') continue; |
||
407 | if (c == '.') { isdecimal = true; continue; } |
||
408 | |||
409 | if (!isdecimal) { |
||
410 | integer_part = (10 * integer_part) + (c - 48); |
||
411 | } |
||
412 | else { |
||
413 | decimal_part += decimal_pivot * (float)(c - 48); |
||
414 | decimal_pivot /= 10.0; |
||
415 | } |
||
416 | } |
||
417 | // add integer part |
||
418 | decimal_part += (float)integer_part; |
||
419 | |||
420 | // check negative |
||
421 | if (isnegative) decimal_part = - decimal_part; |
||
422 | |||
423 | return decimal_part; |
||
424 | } |
||
425 | |||
426 | |||
427 | //-------------------------------------------------------------- |
||
428 | // Trying to avoid floating point maths here. Converts a floating point string to an integer with a smaller unit |
||
429 | // i.e. floatStrToInt("4.5", 2) = 4.5 * 1E2 = 450 |
||
430 | //-------------------------------------------------------------- |
||
431 | int32_t NMEA_floatStrToInt( const char *s, int32_t power1 ) |
||
432 | { |
||
433 | char *endPtr; |
||
434 | int32_t v; |
||
435 | |||
436 | v = strtol(s, &endPtr, 10); |
||
437 | |||
438 | if( *endPtr == '.' ) |
||
439 | { |
||
440 | for (s = endPtr + 1; *s && power1; s++) |
||
441 | { |
||
442 | v = v * 10 + (*s - '0'); |
||
443 | --power1; |
||
444 | } |
||
445 | } |
||
446 | |||
447 | if( power1 ) |
||
448 | { |
||
449 | // Table to avoid multiple multiplications |
||
450 | v = v * getPower(power1); |
||
451 | } |
||
452 | |||
453 | return v; |
||
454 | } |
||
455 | |||
456 | |||
457 | //-------------------------------------------------------------- |
||
458 | int mstrcmp(const char *s1, const char *s2) |
||
459 | { |
||
460 | while((*s1 && *s2) && (*s1 == *s2)) |
||
461 | s1++,s2++; |
||
462 | return *s1 - *s2; |
||
463 | } |
||
464 | |||
465 | //-------------------------------------------------------------- |
||
466 | bool NMEA_isdataready() { |
||
467 | return m_bFlagDataReady; |
||
468 | } |
||
469 | |||
470 | int NMEA_getHour() { |
||
471 | return res_nUTCHour; |
||
472 | } |
||
473 | int NMEA_getMinute() { |
||
474 | return res_nUTCMin; |
||
475 | } |
||
476 | int NMEA_getSecond() { |
||
477 | return res_nUTCSec; |
||
478 | } |
||
479 | int NMEA_getDay() { |
||
480 | return res_nUTCDay; |
||
481 | } |
||
482 | int NMEA_getMonth() { |
||
483 | return res_nUTCMonth; |
||
484 | } |
||
485 | int NMEA_getYear() { |
||
486 | return res_nUTCYear; |
||
487 | } |
||
488 | |||
489 | int32_t NMEA_getLatitude() { |
||
490 | return res_fLatitude; |
||
491 | } |
||
492 | |||
493 | int32_t NMEA_getLongitude() { |
||
494 | return res_fLongitude; |
||
495 | } |
||
496 | |||
497 | uint8_t NMEA_getSatellites() { |
||
498 | return res_nSatellitesUsed; |
||
499 | } |
||
500 | |||
501 | uint8_t NMEA_getGPSfix() { |
||
502 | return res_nGPSfix; |
||
503 | } |
||
504 | int16_t NMEA_getHDOP() { |
||
505 | return res_nHDOP; |
||
506 | } |
||
507 | |||
508 | int16_t NMEA_getAltitude() { |
||
509 | return res_fAltitude; |
||
510 | } |
||
511 | |||
512 | float NMEA_getSpeed() { |
||
513 | return res_fSpeed; |
||
514 | } |
||
515 | |||
516 | int16_t NMEA_getBearing() { |
||
517 | return res_fBearing; |
||
518 | } |
||
519 | uint32_t NMEA_getNMEAcounter() { |
||
520 | return res_nNMEAcounter; |
||
521 | } |
||
522 | |||
523 | uint32_t NMEA_getCRCerror() { |
||
524 | return res_nCRCerror; |
||
525 | } |