2018 revision to classic DataBus AVC code.
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");