Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: LSM303DLM Servo SerialGraphicLCD L3G4200D IncrementalEncoder SimpleShell
Revision 44:0d72a8a1288a, committed 2019-01-07
- Comitter:
- shimniok
- Date:
- Mon Jan 07 16:47:33 2019 +0000
- Parent:
- 43:9a285515f33a
- Commit message:
- Rewrote TinyGPS -> NMEA, GPS::read() now returns struct
Changed in this revision
--- a/GPS/GPS.h Thu Jan 03 19:07:20 2019 +0000
+++ b/GPS/GPS.h Mon Jan 07 16:47:33 2019 +0000
@@ -1,48 +1,19 @@
#ifndef __GPS_H
#define __GPS_H
-/** uBlox GPS UBX Protocol Reader
- * Parses uBlox GPS binary protocol
- *
- * @author Wayne Holder; Ported to mbed by Michael Shimniok
+/** GPS interface class for character-at-a-time parsing of GPS protocols
+ * @author Michael Shimniok
*/
-#include "mbed.h"
-
class GPS {
public:
- GPS(): _callback(0) {}
-
- /**
- * Parse one character of protocol
- * @param c is the character to parse
- * @return 1 when entire packet of data obtained, 0 otherwise
- */
- virtual int parse(char c) = 0;
-
- void subscribe(Callback<void()> cb) {
- _callback = cb;
- }
-
- /** Read the latest data from GPS
- * @param lat latitude in degrees
- * @param lon longitude in degrees
- * @param course heading/course in degrees
- * @param speed speed m/s
- * @param hdop horizontal dilution of precision
- * @param svcount is the number of sattelites being tracked
- * @return all parameters
- */
- void read(double& lat, double& lon, float& course, float& speed, float& hdop, int& svcount) {
- lat = latest.lat;
- lon = latest.lon;
- course = latest.course;
- speed = latest.speed;
- hdop = latest.hdop;
- svcount = latest.svcount;
- }
-
-protected:
+ /// struct containing year, month, date, hour, minute, second, lat, lon, course, speed, hdop, svcount
typedef struct {
+ int year;
+ int month;
+ int date;
+ int hour;
+ int minute;
+ int second;
double lat;
double lon;
float course;
@@ -51,10 +22,38 @@
int svcount;
} gps_data_t;
+#ifdef __MBED__
+ GPS(): _callback(0) {}
+#else
+ GPS() {}
+#endif
+
+ /** Parse one character of protocol
+ * @param c is the character to parse
+ * @return 1 when entire packet of data obtained, 0 otherwise
+ */
+ virtual int parse(char c) = 0;
+
+#ifdef __MBED__
+ void subscribe(Callback<void()> cb) {
+ _callback = cb;
+ }
+#endif
+
+ /** Read the latest data from GPS
+ * @returns gps_data_t struct with date, time, position, course, speed, hdop, and svcount
+ */
+ gps_data_t read() {
+ return latest;
+ }
+
+protected:
gps_data_t latest;
gps_data_t tmp;
+#ifdef __MBED__
Callback<void()> _callback;
+#endif
};
#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/GPS/NMEA.cpp Mon Jan 07 16:47:33 2019 +0000
@@ -0,0 +1,285 @@
+/** NMEA - a small NMEA-parsing library based on TinyGPS
+ * @Author Michael Shimniok
+ * www.bot-thoughts.com
+
+ * TinyGPS - a small GPS library for Arduino providing basic NMEA parsing
+ * Copyright (C) 2008-9 Mikal Hart
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "NMEA.h"
+#include <cstdlib>
+#include <stdio.h>
+#include <string.h>
+
+#define _GPRMC_TERM "GPRMC"
+#define _GPGGA_TERM "GPGGA"
+
+NMEA::NMEA()
+: _new_time(GPS_INVALID_TIME)
+, _new_date(GPS_INVALID_DATE)
+, _new_latitude(GPS_INVALID_ANGLE)
+, _new_longitude(GPS_INVALID_ANGLE)
+, _new_altitude(GPS_INVALID_ALTITUDE)
+, _new_speed(GPS_INVALID_SPEED)
+, _new_course(GPS_INVALID_ANGLE)
+, _new_hdop(0)
+, _new_sat_count(0)
+, _last_time_fix(GPS_INVALID_FIX_TIME)
+, _new_time_fix(GPS_INVALID_FIX_TIME)
+, _last_position_fix(GPS_INVALID_FIX_TIME)
+, _new_position_fix(GPS_INVALID_FIX_TIME)
+, _parity(0)
+, _is_checksum_term(false)
+, _sentence_type(_GPS_SENTENCE_OTHER)
+, _term_number(0)
+, _term_offset(0)
+, _gps_data_good(false)
+, _rmc_ready(false)
+, _gga_ready(false)
+{
+ _term[0] = '\0';
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+// Public member functions
+//
+
+// Parse NMEA once character at a time
+// @return 1 if GGA and RMC sentences are valid and ready
+int NMEA::parse(char c)
+{
+ int valid_sentence = 0;
+
+ switch(c) {
+ case ',': // term terminators
+ _parity ^= c;
+ // no break
+ case '\r':
+ case '\n':
+ case '*':
+ if (_term_offset < sizeof(_term)) {
+ _term[_term_offset] = 0;
+ valid_sentence = term_complete();
+ }
+ ++_term_number;
+ _term_offset = 0;
+ _is_checksum_term = c == '*';
+#ifdef __MBED__
+ if (_callback) _callback();
+#endif
+ break;
+
+ case '$': // sentence begin
+ _term_number = _term_offset = 0;
+ _parity = 0;
+ _sentence_type = _GPS_SENTENCE_OTHER;
+ _is_checksum_term = false;
+ _gps_data_good = false;
+ break;
+
+ default:
+ // ordinary characters
+ if (_term_offset < sizeof(_term) - 1)
+ _term[_term_offset++] = c;
+ if (!_is_checksum_term)
+ _parity ^= c;
+ }
+
+ return valid_sentence & ready();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+// Private member functions
+
+// Convert hex char representation to int
+int NMEA::from_hex(char a)
+{
+ if (a >= 'A' && a <= 'F')
+ return a - 'A' + 10;
+ else if (a >= 'a' && a <= 'f')
+ return a - 'a' + 10;
+ else
+ return a - '0';
+}
+
+
+// Convert string to integer
+int NMEA::parse_int()
+{
+ char *p = _term;
+ bool isneg = *p == '-';
+ if (isneg) ++p;
+ int ret = atoi(p);
+ return isneg ? -ret : ret;
+}
+
+
+// Convert string to double
+double NMEA::parse_decimal()
+{
+ char *p = _term;
+ double ret = atof(p);
+ return ret;
+}
+
+
+// Convert NMEA lat/lon degrees/minutes to double degrees
+double NMEA::parse_degrees()
+{
+ double result;
+ int16_t degrees = atoi(_term) / 100;
+ char *minutes = strchr(_term, '.') - 2;
+ //printf("term=<%s> %d %f\n", _term, degrees, atof(minutes));
+ result = degrees + atof(minutes) / 60.0;
+ return result;
+}
+
+
+// Processes a just-completed term
+// @return true if new sentence has just passed checksum test and is validated
+bool NMEA::term_complete()
+{
+ if (_is_checksum_term) {
+ byte checksum = 16 * from_hex(_term[0]) + from_hex(_term[1]);
+ if (checksum == _parity) {
+ if (_gps_data_good) {
+ _last_time_fix = _new_time_fix;
+ _last_position_fix = _new_position_fix;
+ switch(_sentence_type) {
+ case _GPS_SENTENCE_GPRMC:
+ latest.date = _new_date;
+ latest.month = _new_month;
+ latest.year = _new_year;
+ latest.hour = _new_hour;
+ latest.minute = _new_minute;
+ latest.second = _new_second;
+ latest.lat = _new_latitude;
+ latest.lon = _new_longitude;
+ latest.speed = _new_speed;
+ latest.course = _new_course;
+ printf("--- RMC_READY\n");
+ _rmc_ready = true;
+ break;
+ case _GPS_SENTENCE_GPGGA:
+ _altitude = _new_altitude;
+ latest.lat = _new_latitude;
+ latest.lon = _new_longitude;
+ latest.hdop = _new_hdop;
+ latest.svcount = _new_sat_count;
+ printf("--- GGA_READY\n");
+ _gga_ready = true;
+ break;
+ }//switch _sentence_type
+ return true;
+// } else {
+// printf("bad data\n");
+ }//if _gps_data_good
+ } else {
+ printf("bad checksum 0x%x expected 0x%x\n", checksum, _parity);
+ }//if checksum
+
+ return false;
+ }//if _is_checksum_term
+
+ // the first term determines the sentence type
+ if (_term_number == 0) {
+ if (!strcmp(_term, _GPRMC_TERM))
+ _sentence_type = _GPS_SENTENCE_GPRMC;
+ else if (!strcmp(_term, _GPGGA_TERM))
+ _sentence_type = _GPS_SENTENCE_GPGGA;
+ else
+ _sentence_type = _GPS_SENTENCE_OTHER;
+ return false;
+ }
+
+ if (_sentence_type != _GPS_SENTENCE_OTHER && _term[0]) {
+ printf("\tterm:<%s>\n", _term);
+ switch (_sentence_type | _term_number) {
+ case _GPS_SENTENCE_GPRMC|1: // Time in both sentences
+ //case _GPS_SENTENCE_GPGGA|1:
+ {
+ char *s = _term+4;
+ _new_second = atoi(s);
+ *s = 0;
+ s -= 2;
+ _new_minute = atoi(s);
+ *s = 0;
+ s -= 2;
+ _new_hour = atoi(s);
+ }
+ break;
+ case _GPS_SENTENCE_GPRMC|2: // GPRMC validity
+ _gps_data_good = _term[0] == 'A';
+ break;
+ case _GPS_SENTENCE_GPRMC|3: // Latitude
+ case _GPS_SENTENCE_GPGGA|2:
+ _new_latitude = parse_degrees();
+ break;
+ case _GPS_SENTENCE_GPRMC|4: // N/S
+ case _GPS_SENTENCE_GPGGA|3:
+ if (_term[0] == 'S')
+ _new_latitude = -_new_latitude;
+ break;
+ case _GPS_SENTENCE_GPRMC|5: // Longitude
+ case _GPS_SENTENCE_GPGGA|4:
+ _new_longitude = parse_degrees();
+ break;
+ case _GPS_SENTENCE_GPRMC|6: // E/W
+ case _GPS_SENTENCE_GPGGA|5:
+ if (_term[0] == 'W')
+ _new_longitude = -_new_longitude;
+ break;
+ case _GPS_SENTENCE_GPRMC|7: // Speed (GPRMC)
+ _new_speed = parse_decimal();
+ break;
+ case _GPS_SENTENCE_GPRMC|8: // Course (GPRMC)
+ _new_course = parse_decimal();
+ break;
+ case _GPS_SENTENCE_GPRMC|9: // Date (GPRMC)
+ {
+ char *s = _term+4;
+ _new_year = atoi(s);
+ *s = 0;
+ s -= 2;
+ _new_month = atoi(s);
+ *s = 0;
+ s -= 2;
+ _new_date = atoi(s);
+ //printf("%02d:%02d:%02d %02d/%02d/%02d\n", _new_hour, _new_minute, _new_second, _new_month, _new_date, _new_year);
+ }
+ break;
+ case _GPS_SENTENCE_GPGGA|6: // Fix data (GPGGA)
+ _gps_data_good = _term[0] > '0';
+ break;
+ case _GPS_SENTENCE_GPGGA|7: // Number of satelites tracked (GPGGA)
+ _new_sat_count = parse_int();
+ break;
+ case _GPS_SENTENCE_GPGGA|8: // Horizontal Dilution of Position (GPGGA)
+ _new_hdop = parse_decimal();
+ break;
+ case _GPS_SENTENCE_GPGGA|9: // Altitude (GPGGA)
+ _new_altitude = parse_decimal();
+ break;
+ default :
+ break;
+ } /* switch */
+ }//if
+
+ return false;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/GPS/NMEA.h Mon Jan 07 16:47:33 2019 +0000
@@ -0,0 +1,125 @@
+/* NMEA - a small NMEA-parsing library based on TinyGPS
+
+ TinyGPS - a small GPS library for Arduino providing basic NMEA parsing
+ Copyright (C) 2008-9 Mikal Hart
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Ported to mbed by Michael Shimniok
+*/
+
+#ifdef __MBED__
+#include "mbed.h"
+#endif
+
+#include <stdint.h>
+#include <ctype.h>
+#include "GPS.h"
+
+#ifndef __NMEA_h
+#define __NMEA_h
+
+#define _GPS_VERSION 9 // software version of this library
+#define _GPS_MPH_PER_KNOT 1.15077945
+#define _GPS_MPS_PER_KNOT 0.51444444
+#define _GPS_KMPH_PER_KNOT 1.852
+#define _GPS_MILES_PER_METER 0.00062137112
+#define _GPS_KM_PER_METER 0.001
+
+/** An library parsing for parsing select NMEA-0183 sentences
+ * @author Michael Shimniok
+ */
+class NMEA: public GPS {
+public:
+ typedef uint8_t byte;
+
+ /** Create a new GPS parsing object for parsing NMEA sentences
+ */
+ NMEA();
+
+ /** Parse a single character received from GPS
+ *
+ * @param c is the character received from the GPS
+ * @returns 1 when all sentences received
+ */
+ virtual int parse(char c);
+
+#ifndef _GPS_NO_STATS
+ void stats(unsigned long *chars, unsigned short *good_sentences, unsigned short *failed_cs);
+#endif
+
+ /** determine if all sentences parsed
+ *
+ */
+ inline bool ready() {
+ if (_rmc_ready && _gga_ready) {
+ _rmc_ready = _gga_ready = false;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /** Reset the ready flags for all the parsed sentences
+ */
+ inline void reset_ready() { _rmc_ready = _gga_ready = false; }
+
+ enum {GPS_INVALID_AGE = 0xFFFFFFFF, GPS_INVALID_ANGLE = 999999999, GPS_INVALID_ALTITUDE = 999999999, GPS_INVALID_DATE = 0,
+ GPS_INVALID_TIME = 0xFFFFFFFF, GPS_INVALID_SPEED = 999999999, GPS_INVALID_FIX_TIME = 0xFFFFFFFF};
+
+private:
+ enum {_GPS_SENTENCE_GPGGA=0x10, _GPS_SENTENCE_GPRMC=0x20, _GPS_SENTENCE_GPGSV=0x40, _GPS_SENTENCE_OTHER=0};
+
+ // properties
+ int _new_time;
+ int _new_hour;
+ int _new_minute;
+ int _new_second;
+ int _new_date;
+ int _new_month;
+ int _new_year;
+ double _new_latitude;
+ double _new_longitude;
+ long _altitude;
+ float _new_altitude;
+ float _new_speed;
+ float _new_course;
+ float _new_hdop;
+ unsigned int _new_sat_count;
+ unsigned long _last_time_fix, _new_time_fix;
+ unsigned long _last_position_fix, _new_position_fix;
+
+ // parsing state variables
+ byte _parity;
+ bool _is_checksum_term;
+ char _term[15];
+ byte _sentence_type;
+ byte _term_number;
+ uint8_t _term_offset;
+ bool _gps_data_good;
+ bool _rmc_ready;
+ bool _gga_ready;
+
+ double parse_degrees();
+ int from_hex(char a);
+ int parse_int();
+ double parse_decimal();
+ bool term_complete();
+ bool gpsisdigit(char c) { return c >= '0' && c <= '9'; }
+ int gpsstrcmp(const char *str1, const char *str2);
+};
+
+#endif
--- a/GPS/TinyGPS.cpp Thu Jan 03 19:07:20 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,354 +0,0 @@
-/*
- TinyGPS - a small GPS library for Arduino providing basic NMEA parsing
- Copyright (C) 2008-9 Mikal Hart
- All rights reserved.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- Ported to mbed by Michael Shimniok http://www.bot-thoughts.com/
-*/
-
-#include "TinyGPS.h"
-
-#define _GPRMC_TERM "GPRMC"
-#define _GPGGA_TERM "GPGGA"
-#define _GPGSV_TERM "GPGSV"
-
-TinyGPS::TinyGPS()
-: _time(GPS_INVALID_TIME)
-, _new_time(GPS_INVALID_TIME)
-, _date(GPS_INVALID_DATE)
-, _new_date(GPS_INVALID_DATE)
-, _latitude(GPS_INVALID_ANGLE)
-, _new_latitude(GPS_INVALID_ANGLE)
-, _longitude(GPS_INVALID_ANGLE)
-, _new_longitude(GPS_INVALID_ANGLE)
-, _altitude(GPS_INVALID_ALTITUDE)
-, _new_altitude(GPS_INVALID_ALTITUDE)
-, _speed(GPS_INVALID_SPEED)
-, _new_speed(0)
-, _course(GPS_INVALID_ANGLE)
-, _new_course(GPS_INVALID_ANGLE)
-, _hdop(0)
-, _new_hdop(0)
-, _sat_count(0)
-, _new_sat_count(0)
-, _last_time_fix(GPS_INVALID_FIX_TIME)
-, _new_time_fix(GPS_INVALID_FIX_TIME)
-, _last_position_fix(GPS_INVALID_FIX_TIME)
-, _new_position_fix(GPS_INVALID_FIX_TIME)
-, _parity(0)
-, _is_checksum_term(false)
-, _sentence_type(_GPS_SENTENCE_OTHER)
-, _term_number(0)
-, _term_offset(0)
-, _gps_data_good(false)
-, _rmc_ready(false)
-, _gga_ready(false)
-, _gsv_ready(false)
-#ifndef _GPS_NO_STATS
-, _encoded_characters(0)
-, _good_sentences(0)
-, _failed_checksum(0)
-, _passed_checksum(0)
-#endif
-{
- _term[0] = '\0';
-}
-
-//
-// public methods
-//
-
-int TinyGPS::parse(char c)
-{
- int valid_sentence = 0;
-
- ++_encoded_characters;
- switch(c) {
- case ',': // term terminators
- _parity ^= c;
- // no break
- case '\r':
- case '\n':
- case '*':
- if (_term_offset < sizeof(_term)) {
- _term[_term_offset] = 0;
- valid_sentence = term_complete();
- }
- ++_term_number;
- _term_offset = 0;
- _is_checksum_term = c == '*';
- if (_callback) _callback();
- return valid_sentence;
-
- case '$': // sentence begin
- _term_number = _term_offset = 0;
- _parity = 0;
- _sentence_type = _GPS_SENTENCE_OTHER;
- _is_checksum_term = false;
- _gps_data_good = false;
- return valid_sentence;
- }
-
- // ordinary characters
- if (_term_offset < sizeof(_term) - 1)
- _term[_term_offset++] = c;
- if (!_is_checksum_term)
- _parity ^= c;
-
- return valid_sentence;
-}
-
-#ifndef _GPS_NO_STATS
-void TinyGPS::stats(unsigned long *chars, unsigned short *sentences, unsigned short *failed_cs)
-{
- if (chars) *chars = _encoded_characters;
- if (sentences) *sentences = _good_sentences;
- if (failed_cs) *failed_cs = _failed_checksum;
-}
-#endif
-
-//
-// internal utilities
-//
-int TinyGPS::from_hex(char a)
-{
- if (a >= 'A' && a <= 'F')
- return a - 'A' + 10;
- else if (a >= 'a' && a <= 'f')
- return a - 'a' + 10;
- else
- return a - '0';
-}
-
-int TinyGPS::parse_int()
-{
- char *p = _term;
- bool isneg = *p == '-';
- if (isneg) ++p;
- while (*p == '0') ++p;
- int ret = gpsatol(p);
- return isneg ? -ret : ret;
-}
-
-long TinyGPS::parse_decimal()
-{
- char *p = _term;
- bool isneg = *p == '-';
- if (isneg) ++p;
- unsigned long ret = 100UL * gpsatol(p);
- while (gpsisdigit(*p)) ++p;
- if (*p == '.')
- {
- if (gpsisdigit(p[1]))
- {
- ret += 10 * (p[1] - '0');
- if (gpsisdigit(p[2]))
- ret += p[2] - '0';
- }
- }
- return isneg ? -ret : ret;
-}
-
-// mes 04/27/12 increased fractional precision to 7 digits, was 5
-unsigned long TinyGPS::parse_degrees()
-{
- char *p;
- unsigned long left = gpsatol(_term);
- unsigned long tenk_minutes = (left % 100UL) * 1000000UL;
- for (p=_term; gpsisdigit(*p); ++p);
- if (*p == '.')
- {
- unsigned long mult = 100000;
- while (gpsisdigit(*++p))
- {
- tenk_minutes += mult * (*p - '0');
- mult /= 10;
- }
- }
- return (left / 100) * 10000000 + tenk_minutes / 6;
-}
-
-// Processes a just-completed term
-// Returns true if new sentence has just passed checksum test and is validated
-bool TinyGPS::term_complete()
-{
- if (_is_checksum_term) {
-
- byte checksum = 16 * from_hex(_term[0]) + from_hex(_term[1]);
- if (checksum == _parity) {
-
- if (_gps_data_good) {
-
-#ifndef _GPS_NO_STATS
- ++_good_sentences;
-#endif
- _last_time_fix = _new_time_fix;
- _last_position_fix = _new_position_fix;
-
- switch(_sentence_type) {
- case _GPS_SENTENCE_GPRMC:
- _time = _new_time;
- _date = _new_date;
- latest.lat = _new_latitude;
- latest.lon = _new_longitude;
- latest.speed = _new_speed;
- latest.course = _new_course;
- _rmc_ready = true;
- break;
- case _GPS_SENTENCE_GPGGA:
- _altitude = _new_altitude;
- _time = _new_time;
- latest.lat = _new_latitude;
- latest.lon = _new_longitude;
- latest.hdop = _new_hdop;
- latest.svcount = _new_sat_count;
- _gga_ready = true;
- break;
- case _GPS_SENTENCE_GPGSV:
- _gsv_ready = true;
- break;
- }
-
- return true;
- }
- }
-
-#ifndef _GPS_NO_STATS
- else
- ++_failed_checksum;
-#endif
- return false;
- }
-
- // the first term determines the sentence type
- if (_term_number == 0) {
- if (!gpsstrcmp(_term, _GPRMC_TERM))
- _sentence_type = _GPS_SENTENCE_GPRMC;
- else if (!gpsstrcmp(_term, _GPGGA_TERM))
- _sentence_type = _GPS_SENTENCE_GPGGA;
- else if (!gpsstrcmp(_term, _GPGSV_TERM))
- _sentence_type = _GPS_SENTENCE_GPGSV;
- else
- _sentence_type = _GPS_SENTENCE_OTHER;
- return false;
- }
-
- if (_sentence_type != _GPS_SENTENCE_OTHER && _term[0])
- /*
- if (_sentence_type == _GPS_SENTENCE_GPGSV) {
- // $GPGSV,3,1,12,05,54,069,45,12,44,061,44,21,07,184,46,22,78,289,47*72<CR><LF>
- // TODO 4 need to maintain a list of 12 structs with sat info and update it each time
- switch (_term_number) {
- case 0 : // number of messages
- break;
- case 1 : // sequence number
- break;
- case 2 : // satellites in view
- break;
- case 3 : // sat ID
- case 8 :
- case 12 :
- case 16 :
- break;
- case 4 : // elevation
- case 9 :
- case 13 :
- case 17 :
- break;
- case 5 : // azimuth
- case 10 :
- case 14 :
- case 18 :
- break;
- case 6 : // SNR
- case 11 :
- case 15 :
- case 19 :
- break;
- }
- } else {*/
- switch (((_sentence_type == _GPS_SENTENCE_GPGGA) ? 200 : 100) + _term_number) {
- case 101: // Time in both sentences
- case 201:
- _new_time = parse_decimal();
- //_new_time_fix = millis();
- break;
- case 102: // GPRMC validity
- _gps_data_good = _term[0] == 'A';
- break;
- case 103: // Latitude
- case 202:
- _new_latitude = parse_degrees();
- //_new_position_fix = millis();
- break;
- case 104: // N/S
- case 203:
- if (_term[0] == 'S')
- _new_latitude = -_new_latitude;
- break;
- case 105: // Longitude
- case 204:
- _new_longitude = parse_degrees();
- break;
- case 106: // E/W
- case 205:
- if (_term[0] == 'W')
- _new_longitude = -_new_longitude;
- break;
- case 107: // Speed (GPRMC)
- _new_speed = parse_decimal();
- break;
- case 108: // Course (GPRMC)
- _new_course = parse_decimal();
- break;
- case 109: // Date (GPRMC)
- _new_date = gpsatol(_term);
- break;
- case 206: // Fix data (GPGGA)
- _gps_data_good = _term[0] > '0';
- break;
- case 207: // Number of satelites tracked (GPGGA)
- _new_sat_count = parse_int();
- break;
- case 208: // Horizontal Dilution of Position (GPGGA)
- _new_hdop = parse_decimal();
- break;
- case 209: // Altitude (GPGGA)
- _new_altitude = parse_decimal();
- break;
- default :
- break;
- } /* switch */
- //}
-
- return false;
-}
-
-long TinyGPS::gpsatol(const char *str)
-{
- long ret = 0;
- while (gpsisdigit(*str))
- ret = 10 * ret + *str++ - '0';
- return ret;
-}
-
-int TinyGPS::gpsstrcmp(const char *str1, const char *str2)
-{
- while (*str1 && *str1 == *str2)
- ++str1, ++str2;
- return *str1;
-}
--- a/GPS/TinyGPS.h Thu Jan 03 19:07:20 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +0,0 @@
-/*
- TinyGPS - a small GPS library for Arduino providing basic NMEA parsing
- Copyright (C) 2008-9 Mikal Hart
- All rights reserved.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- Ported to mbed by Michael Shimniok
-*/
-
-#include "mbed.h"
-#include "GPS.h"
-
-#ifndef TinyGPS_h
-#define TinyGPS_h
-
-#define _GPS_VERSION 9 // software version of this library
-#define _GPS_MPH_PER_KNOT 1.15077945
-#define _GPS_MPS_PER_KNOT 0.51444444
-#define _GPS_KMPH_PER_KNOT 1.852
-#define _GPS_MILES_PER_METER 0.00062137112
-#define _GPS_KM_PER_METER 0.001
-//#define _GPS_NO_STATS
-
-/** TinyGPS - a small GPS library for Arduino providing basic NMEA parsing Copyright (C) 2008-9 Mikal Hart
- * All rights reserved. Modified by Michael Shimniok
- */
-
-class TinyGPS: public GPS {
-public:
- typedef uint8_t byte;
-
- /** Create a new GPS parsing object for parsing NMEA sentences
- */
- TinyGPS();
-
- /** Parse a single character received from GPS
- *
- * @param c is the character received from the GPS
- * @returns 1 when all sentences received
- */
- virtual int parse(char c);
-
- /** Return the date and time from the parsed NMEA sentences
- *
- * @returns date as an integer value
- * @returns time as an integer value
- * @returns fix_age in milliseconds if available
- */
- inline void get_datetime(unsigned long *date, unsigned long *time)
- {
- if (date) *date = _date;
- if (time) *time = _time;
- }
-
- /** signed altitude in centimeters (from GPGGA sentence)
- * @returns altitude in centimeters, integer
- */
- inline long altitude() { return _altitude; }
-
- /** course in last full GPRMC sentence in 100th of a degree
- * @returns course as an integer, 100ths of a degree
- */
- inline unsigned long course() { return _course; }
-
- /** speed in last full GPRMC sentence in 100ths of a knot
- * @returns speed in 100ths of a knot
- */
- unsigned long speed() { return _speed; }
-
- /* horizontal dilution of position in last full GPGGA sentence in 100ths
- * @returns hdop in 100ths
- */
- unsigned long hdop() { return _hdop; }
-
- /** number of satellites tracked in last full GPGGA sentence
- * @returns number of satellites tracked
- */
- unsigned long sat_count() { return _sat_count; }
-
-#ifndef _GPS_NO_STATS
- void stats(unsigned long *chars, unsigned short *good_sentences, unsigned short *failed_cs);
-#endif
-
- /** Convert date and time of last parsed sentence to integers
- *
- * @returns year
- * @returns month
- * @returns day of month
- * @returns hour
- * @returns minute
- * @returns second
- * @returns hundreths
- * @returns fix_age in milliseconds if available
- */
- inline void crack_datetime(int *year, byte *month, byte *day,
- byte *hour, byte *minute, byte *second, byte *hundredths = 0, unsigned long *fix_age = 0)
- {
- unsigned long date, time;
- get_datetime(&date, &time);
- if (year)
- {
- *year = date % 100;
- *year += *year > 80 ? 1900 : 2000;
- }
- if (month) *month = (date / 100) % 100;
- if (day) *day = date / 10000;
- if (hour) *hour = time / 1000000;
- if (minute) *minute = (time / 10000) % 100;
- if (second) *second = (time / 100) % 100;
- if (hundredths) *hundredths = time % 100;
- }
-
- /** returns altitude as a float
- */
- inline double f_altitude() { return altitude() / 100.0; }
-
- /** returns course as a float
- */
- inline double f_course() { return course() / 100.0; }
-
- /** returns speed in knots as a float
- */
- inline double f_speed_knots() { return speed() / 100.0; }
-
- /** returns speed in mph as a float
- */
- inline double f_speed_mph() { return _GPS_MPH_PER_KNOT * f_speed_knots(); }
-
- /** returns speed in meters per second as a float
- */
- inline double f_speed_mps() { return _GPS_MPS_PER_KNOT * f_speed_knots(); }
-
- /** returns speed in km per hour as a float
- */
- inline double f_speed_kmph() { return _GPS_KMPH_PER_KNOT * f_speed_knots(); }
-
- /** returns hdop as a float
- */
- inline double f_hdop() { return hdop() / 100.0; }
-
- /** @returns library version
- */
- static int library_version() { return _GPS_VERSION; }
-
- /** determine if all sentences parsed
- *
- */
- inline bool ready() { return (_rmc_ready && _gga_ready); }
-
- /** determine if GSV sentence parsed since last reset_ready()
- */
- inline bool gsv_ready() { return _gsv_ready; }
-
- inline bool gga_ready() { return _gga_ready; }
-
- inline bool rmc_ready() { return _rmc_ready; }
-
- /** Reset the ready flags for all the parsed sentences
- */
- inline void reset_ready() { _gsv_ready = _rmc_ready = _gga_ready = false; }
-
- enum {GPS_INVALID_AGE = 0xFFFFFFFF, GPS_INVALID_ANGLE = 999999999, GPS_INVALID_ALTITUDE = 999999999, GPS_INVALID_DATE = 0,
- GPS_INVALID_TIME = 0xFFFFFFFF, GPS_INVALID_SPEED = 999999999, GPS_INVALID_FIX_TIME = 0xFFFFFFFF};
-
-private:
- enum {_GPS_SENTENCE_GPGGA, _GPS_SENTENCE_GPRMC, _GPS_SENTENCE_GPGSV, _GPS_SENTENCE_OTHER};
-
- // properties
- unsigned long _time, _new_time;
- unsigned long _date, _new_date;
- long _latitude, _new_latitude;
- long _longitude, _new_longitude;
- long _altitude, _new_altitude;
- unsigned long _speed, _new_speed;
- unsigned long _course, _new_course;
- unsigned long _hdop, _new_hdop;
- unsigned int _sat_count, _new_sat_count;
- unsigned long _last_time_fix, _new_time_fix;
- unsigned long _last_position_fix, _new_position_fix;
-
- // parsing state variables
- byte _parity;
- bool _is_checksum_term;
- char _term[15];
- byte _sentence_type;
- byte _term_number;
- uint8_t _term_offset;
- bool _gps_data_good;
- bool _rmc_ready;
- bool _gga_ready;
- bool _gsv_ready;
-
-#ifndef _GPS_NO_STATS
- // statistics
- unsigned long _encoded_characters;
- unsigned short _good_sentences;
- unsigned short _failed_checksum;
- unsigned short _passed_checksum;
-#endif
-
- // internal utilities
- int from_hex(char a);
- int parse_int();
- long parse_decimal();
- unsigned long parse_degrees();
- bool term_complete();
- bool gpsisdigit(char c) { return c >= '0' && c <= '9'; }
- long gpsatol(const char *str);
- int gpsstrcmp(const char *str1, const char *str2);
-};
-
-// Arduino 0012 workaround
-#undef int
-#undef char
-#undef long
-#undef byte
-#undef double
-#undef abs
-#undef round
-
-#endif
--- a/main.cpp Thu Jan 03 19:07:20 2019 +0000
+++ b/main.cpp Mon Jan 07 16:47:33 2019 +0000
@@ -15,7 +15,7 @@
#include "Config.h"
#include "Updater.h"
//#include "Ublox6.h"
-#include "TinyGPS.h"
+#include "NMEA.h"
#include "Logger.h"
#include "SystemState.h"
#include "Display.h"
@@ -129,16 +129,23 @@
///////////////////////////////////////////////////////////////////////////////
// GPS
//Ublox6 ublox;
-TinyGPS gps;
+NMEA nmea;
EventQueue gpsQueue(8 * EVENTS_EVENT_SIZE);
// Callback for gps parse data ready
void gps_callback() {
+ GPS::gps_data_t data;
GpsData d;
led2 = !led2;
//ublox.read(d.latitude, d.longitude, d.course, d.speed, d.hdop, d.svcount);
- gps.read(d.latitude, d.longitude, d.course, d.speed, d.hdop, d.svcount);
+ data = nmea.read();
+ d.latitude = data.lat;
+ d.longitude = data.lon;
+ d.course = data.course;
+ d.speed = data.speed;
+ d.hdop = data.hdop;
+ d.svcount = data.svcount;
d.timestamp = Kernel::get_ms_count();
logQueue.call(&logger, &Logger::log_gps, d);
lcdQueue.call(&display, &Display::gps, d);
@@ -149,7 +156,7 @@
while (s.readable()) {
char c = s.getc();
//gpsQueue.call(&ublox, &Ublox6::parse, c);
- gpsQueue.call(&gps, &TinyGPS::parse, c);
+ gpsQueue.call(&nmea, &NMEA::parse, c);
}
}
@@ -178,17 +185,12 @@
void read_gps(int argc, char **argv)
{
- double lat=0;
- double lon=0;
- float course=0;
- float speed=0;
- float hdop=0.0;
- int svcount=0;
+ GPS::gps_data_t d;
- gps.read(lat, lon, course, speed, hdop, svcount);
- printf("%3.7f %3.7f\n", lat, lon);
- printf("hdg=%03.1f deg spd=%3.1f m/s\n", course, speed);
- printf("%d %f\n", svcount, hdop);
+ d = nmea.read();
+ printf("%3.7f %3.7f\n", d.lat, d.lon);
+ printf("hdg=%03.1f deg spd=%3.1f m/s\n", d.course, d.speed);
+ printf("%d %f\n", d.svcount, d.hdop);
}
void read_imu(int argc, char **argv)
@@ -334,7 +336,7 @@
display.status("Starting gps");
Thread gpsThread(osPriorityHigh, 2048, 0, "gps");
gpsThread.start(callback(&gpsQueue, &EventQueue::dispatch_forever));
- gps.subscribe(gps_callback);
+ nmea.subscribe(gps_callback);
s.attach(gps_handler);
printf("Starting logging...\n");