mbed port of the TinyGPSPlus library for Arduino, by Mikal Hart. The port is heavily inspired by Sergey Drobyshevskiy (dROb)'s port of the TinyGPS library.

Dependents:   ZZ_SSL_Main_L476 Sample_program_Font72

Fork of TinyGPSPlus by カレヴィ アンダース

Committer:
WaleedElmughrabi
Date:
Wed Nov 07 03:42:07 2018 +0000
Revision:
2:9fb16575b0f8
Parent:
1:a4d6efebcef8
UK time

Who changed what in which revision?

UserRevisionLine numberNew contents of line
OkiAviation 0:2576f9f1dc71 1 /*
OkiAviation 0:2576f9f1dc71 2 TinyGPS++ - a small GPS library for Arduino providing universal NMEA parsing
OkiAviation 0:2576f9f1dc71 3 Based on work by and "distanceBetween" and "courseTo" courtesy of Maarten Lamers.
OkiAviation 0:2576f9f1dc71 4 Suggestion to add satellites, courseTo(), and cardinal() by Matt Monson.
OkiAviation 0:2576f9f1dc71 5 Location precision improvements suggested by Wayne Holder.
OkiAviation 0:2576f9f1dc71 6 Copyright (C) 2008-2013 Mikal Hart
OkiAviation 0:2576f9f1dc71 7 All rights reserved.
OkiAviation 0:2576f9f1dc71 8
OkiAviation 0:2576f9f1dc71 9 This library is free software; you can redistribute it and/or
OkiAviation 0:2576f9f1dc71 10 modify it under the terms of the GNU Lesser General Public
OkiAviation 0:2576f9f1dc71 11 License as published by the Free Software Foundation; either
OkiAviation 0:2576f9f1dc71 12 version 2.1 of the License, or (at your option) any later version.
OkiAviation 0:2576f9f1dc71 13
OkiAviation 0:2576f9f1dc71 14 This library is distributed in the hope that it will be useful,
OkiAviation 0:2576f9f1dc71 15 but WITHOUT ANY WARRANTY; without even the implied warranty of
OkiAviation 0:2576f9f1dc71 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
OkiAviation 0:2576f9f1dc71 17 Lesser General Public License for more details.
OkiAviation 0:2576f9f1dc71 18
OkiAviation 0:2576f9f1dc71 19 You should have received a copy of the GNU Lesser General Public
OkiAviation 0:2576f9f1dc71 20 License along with this library; if not, write to the Free Software
OkiAviation 0:2576f9f1dc71 21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
OkiAviation 0:2576f9f1dc71 22
OkiAviation 0:2576f9f1dc71 23 MBED port by Kalevi Anders, but heavily inspired by Sergey Drobyshevskiy (dROb)
OkiAviation 0:2576f9f1dc71 24 */
OkiAviation 0:2576f9f1dc71 25
OkiAviation 0:2576f9f1dc71 26 #include "TinyGPSPlus.h"
OkiAviation 0:2576f9f1dc71 27
OkiAviation 0:2576f9f1dc71 28 #include <string.h>
OkiAviation 0:2576f9f1dc71 29 #include <ctype.h>
OkiAviation 0:2576f9f1dc71 30 #include <stdlib.h>
OkiAviation 0:2576f9f1dc71 31
OkiAviation 0:2576f9f1dc71 32 #define _GPRMCterm "GPRMC"
OkiAviation 0:2576f9f1dc71 33 #define _GPGGAterm "GPGGA"
OkiAviation 0:2576f9f1dc71 34
OkiAviation 0:2576f9f1dc71 35 TinyGPSPlus::TinyGPSPlus()
OkiAviation 0:2576f9f1dc71 36 : parity(0)
OkiAviation 0:2576f9f1dc71 37 , isChecksumTerm(false)
OkiAviation 0:2576f9f1dc71 38 , curSentenceType(GPS_SENTENCE_OTHER)
OkiAviation 0:2576f9f1dc71 39 , curTermNumber(0)
OkiAviation 0:2576f9f1dc71 40 , curTermOffset(0)
OkiAviation 0:2576f9f1dc71 41 , sentenceHasFix(false)
OkiAviation 0:2576f9f1dc71 42 , customElts(0)
OkiAviation 0:2576f9f1dc71 43 , customCandidates(0)
OkiAviation 0:2576f9f1dc71 44 , encodedCharCount(0)
OkiAviation 0:2576f9f1dc71 45 , sentencesWithFixCount(0)
OkiAviation 0:2576f9f1dc71 46 , failedChecksumCount(0)
OkiAviation 0:2576f9f1dc71 47 , passedChecksumCount(0)
OkiAviation 0:2576f9f1dc71 48 {
OkiAviation 0:2576f9f1dc71 49 term[0] = '\0';
OkiAviation 0:2576f9f1dc71 50 }
OkiAviation 0:2576f9f1dc71 51
OkiAviation 0:2576f9f1dc71 52 //
OkiAviation 0:2576f9f1dc71 53 // public methods
OkiAviation 0:2576f9f1dc71 54 //
OkiAviation 0:2576f9f1dc71 55
OkiAviation 0:2576f9f1dc71 56 bool TinyGPSPlus::encode(char c)
OkiAviation 0:2576f9f1dc71 57 {
OkiAviation 0:2576f9f1dc71 58 ++encodedCharCount;
OkiAviation 0:2576f9f1dc71 59
OkiAviation 0:2576f9f1dc71 60
OkiAviation 0:2576f9f1dc71 61 switch(c)
OkiAviation 0:2576f9f1dc71 62 {
OkiAviation 0:2576f9f1dc71 63 case ',': // term terminators
OkiAviation 0:2576f9f1dc71 64 parity ^= (uint8_t)c;
OkiAviation 0:2576f9f1dc71 65 case '\r':
OkiAviation 0:2576f9f1dc71 66 case '\n':
OkiAviation 0:2576f9f1dc71 67 case '*':
OkiAviation 0:2576f9f1dc71 68 {
OkiAviation 0:2576f9f1dc71 69 bool isValidSentence = false;
OkiAviation 0:2576f9f1dc71 70 if (curTermOffset < sizeof(term))
OkiAviation 0:2576f9f1dc71 71 {
OkiAviation 0:2576f9f1dc71 72 term[curTermOffset] = 0;
OkiAviation 0:2576f9f1dc71 73 isValidSentence = endOfTermHandler();
OkiAviation 0:2576f9f1dc71 74 }
OkiAviation 0:2576f9f1dc71 75 ++curTermNumber;
OkiAviation 0:2576f9f1dc71 76 curTermOffset = 0;
OkiAviation 0:2576f9f1dc71 77 isChecksumTerm = c == '*';
OkiAviation 0:2576f9f1dc71 78 return isValidSentence;
OkiAviation 0:2576f9f1dc71 79 }
OkiAviation 0:2576f9f1dc71 80 break;
OkiAviation 0:2576f9f1dc71 81
OkiAviation 0:2576f9f1dc71 82 case '$': // sentence begin
OkiAviation 0:2576f9f1dc71 83 curTermNumber = curTermOffset = 0;
OkiAviation 0:2576f9f1dc71 84 parity = 0;
OkiAviation 0:2576f9f1dc71 85 curSentenceType = GPS_SENTENCE_OTHER;
OkiAviation 0:2576f9f1dc71 86 isChecksumTerm = false;
OkiAviation 0:2576f9f1dc71 87 sentenceHasFix = false;
OkiAviation 0:2576f9f1dc71 88 return false;
OkiAviation 0:2576f9f1dc71 89
OkiAviation 0:2576f9f1dc71 90 default: // ordinary characters
OkiAviation 0:2576f9f1dc71 91 if (curTermOffset < sizeof(term) - 1)
OkiAviation 0:2576f9f1dc71 92 term[curTermOffset++] = c;
OkiAviation 0:2576f9f1dc71 93 if (!isChecksumTerm)
OkiAviation 0:2576f9f1dc71 94 parity ^= c;
OkiAviation 0:2576f9f1dc71 95 return false;
OkiAviation 0:2576f9f1dc71 96 }
OkiAviation 0:2576f9f1dc71 97
OkiAviation 0:2576f9f1dc71 98 return false;
OkiAviation 0:2576f9f1dc71 99 }
OkiAviation 0:2576f9f1dc71 100
OkiAviation 0:2576f9f1dc71 101 //
OkiAviation 0:2576f9f1dc71 102 // internal utilities
OkiAviation 0:2576f9f1dc71 103 //
OkiAviation 0:2576f9f1dc71 104 int TinyGPSPlus::fromHex(char a)
OkiAviation 0:2576f9f1dc71 105 {
OkiAviation 0:2576f9f1dc71 106 if (a >= 'A' && a <= 'F')
OkiAviation 0:2576f9f1dc71 107 return a - 'A' + 10;
OkiAviation 0:2576f9f1dc71 108 else if (a >= 'a' && a <= 'f')
OkiAviation 0:2576f9f1dc71 109 return a - 'a' + 10;
OkiAviation 0:2576f9f1dc71 110 else
OkiAviation 0:2576f9f1dc71 111 return a - '0';
OkiAviation 0:2576f9f1dc71 112 }
OkiAviation 0:2576f9f1dc71 113
OkiAviation 0:2576f9f1dc71 114 // static
OkiAviation 0:2576f9f1dc71 115 // Parse a (potentially negative) number with up to 2 decimal digits -xxxx.yy
OkiAviation 0:2576f9f1dc71 116 int32_t TinyGPSPlus::parseDecimal(const char *term)
OkiAviation 0:2576f9f1dc71 117 {
OkiAviation 0:2576f9f1dc71 118 bool negative = *term == '-';
OkiAviation 0:2576f9f1dc71 119 if (negative) ++term;
OkiAviation 0:2576f9f1dc71 120 int32_t ret = 100 * (int32_t)atol(term);
OkiAviation 0:2576f9f1dc71 121 while (isdigit(*term)) ++term;
OkiAviation 0:2576f9f1dc71 122 if (*term == '.' && isdigit(term[1]))
OkiAviation 0:2576f9f1dc71 123 {
OkiAviation 0:2576f9f1dc71 124 ret += 10 * (term[1] - '0');
OkiAviation 0:2576f9f1dc71 125 if (isdigit(term[2]))
OkiAviation 0:2576f9f1dc71 126 ret += term[2] - '0';
OkiAviation 0:2576f9f1dc71 127 }
OkiAviation 0:2576f9f1dc71 128 return negative ? -ret : ret;
OkiAviation 0:2576f9f1dc71 129 }
OkiAviation 0:2576f9f1dc71 130
OkiAviation 0:2576f9f1dc71 131 // static
OkiAviation 0:2576f9f1dc71 132 // Parse degrees in that funny NMEA format DDMM.MMMM
OkiAviation 0:2576f9f1dc71 133 void TinyGPSPlus::parseDegrees(const char *term, RawDegrees &deg)
OkiAviation 0:2576f9f1dc71 134 {
OkiAviation 0:2576f9f1dc71 135 uint32_t leftOfDecimal = (uint32_t)atol(term);
OkiAviation 0:2576f9f1dc71 136 uint16_t minutes = (uint16_t)(leftOfDecimal % 100);
OkiAviation 0:2576f9f1dc71 137 uint32_t multiplier = 10000000UL;
OkiAviation 0:2576f9f1dc71 138 uint32_t tenMillionthsOfMinutes = minutes * multiplier;
OkiAviation 0:2576f9f1dc71 139
OkiAviation 0:2576f9f1dc71 140 deg.deg = (int16_t)(leftOfDecimal / 100);
OkiAviation 0:2576f9f1dc71 141
OkiAviation 0:2576f9f1dc71 142 while (isdigit(*term))
OkiAviation 0:2576f9f1dc71 143 ++term;
OkiAviation 0:2576f9f1dc71 144
OkiAviation 0:2576f9f1dc71 145 if (*term == '.')
OkiAviation 0:2576f9f1dc71 146 while (isdigit(*++term))
OkiAviation 0:2576f9f1dc71 147 {
OkiAviation 0:2576f9f1dc71 148 multiplier /= 10;
OkiAviation 0:2576f9f1dc71 149 tenMillionthsOfMinutes += (*term - '0') * multiplier;
OkiAviation 0:2576f9f1dc71 150 }
OkiAviation 0:2576f9f1dc71 151
OkiAviation 0:2576f9f1dc71 152 deg.billionths = (5 * tenMillionthsOfMinutes + 1) / 3;
OkiAviation 0:2576f9f1dc71 153 deg.negative = false;
OkiAviation 0:2576f9f1dc71 154 }
OkiAviation 0:2576f9f1dc71 155
OkiAviation 0:2576f9f1dc71 156 #define COMBINE(sentence_type, term_number) (((unsigned)(sentence_type) << 5) | term_number)
OkiAviation 0:2576f9f1dc71 157
OkiAviation 0:2576f9f1dc71 158 // Processes a just-completed term
OkiAviation 0:2576f9f1dc71 159 // Returns true if new sentence has just passed checksum test and is validated
OkiAviation 0:2576f9f1dc71 160 bool TinyGPSPlus::endOfTermHandler()
OkiAviation 0:2576f9f1dc71 161 {
OkiAviation 0:2576f9f1dc71 162 // If it's the checksum term, and the checksum checks out, commit
OkiAviation 0:2576f9f1dc71 163 if (isChecksumTerm)
OkiAviation 0:2576f9f1dc71 164 {
OkiAviation 0:2576f9f1dc71 165 byte checksum = 16 * fromHex(term[0]) + fromHex(term[1]);
OkiAviation 0:2576f9f1dc71 166 if (checksum == parity)
OkiAviation 0:2576f9f1dc71 167 {
OkiAviation 0:2576f9f1dc71 168 passedChecksumCount++;
OkiAviation 0:2576f9f1dc71 169 if (sentenceHasFix)
OkiAviation 0:2576f9f1dc71 170 ++sentencesWithFixCount;
OkiAviation 0:2576f9f1dc71 171
OkiAviation 0:2576f9f1dc71 172 switch(curSentenceType)
OkiAviation 0:2576f9f1dc71 173 {
OkiAviation 0:2576f9f1dc71 174 case GPS_SENTENCE_GPRMC:
OkiAviation 0:2576f9f1dc71 175 date.commit();
OkiAviation 0:2576f9f1dc71 176 time.commit();
OkiAviation 0:2576f9f1dc71 177 if (sentenceHasFix)
OkiAviation 0:2576f9f1dc71 178 {
OkiAviation 0:2576f9f1dc71 179 location.commit();
OkiAviation 0:2576f9f1dc71 180 speed.commit();
OkiAviation 0:2576f9f1dc71 181 course.commit();
OkiAviation 0:2576f9f1dc71 182 }
OkiAviation 0:2576f9f1dc71 183 break;
OkiAviation 0:2576f9f1dc71 184 case GPS_SENTENCE_GPGGA:
OkiAviation 0:2576f9f1dc71 185 time.commit();
OkiAviation 0:2576f9f1dc71 186 if (sentenceHasFix)
OkiAviation 0:2576f9f1dc71 187 {
OkiAviation 0:2576f9f1dc71 188 location.commit();
OkiAviation 0:2576f9f1dc71 189 altitude.commit();
OkiAviation 0:2576f9f1dc71 190 }
OkiAviation 0:2576f9f1dc71 191 satellites.commit();
OkiAviation 0:2576f9f1dc71 192 hdop.commit();
OkiAviation 0:2576f9f1dc71 193 break;
OkiAviation 0:2576f9f1dc71 194 }
OkiAviation 0:2576f9f1dc71 195
OkiAviation 0:2576f9f1dc71 196 // Commit all custom listeners of this sentence type
OkiAviation 0:2576f9f1dc71 197 for (TinyGPSCustom *p = customCandidates; p != NULL && strcmp(p->sentenceName, customCandidates->sentenceName) == 0; p = p->next)
OkiAviation 0:2576f9f1dc71 198 p->commit();
OkiAviation 0:2576f9f1dc71 199 return true;
OkiAviation 0:2576f9f1dc71 200 }
OkiAviation 0:2576f9f1dc71 201
OkiAviation 0:2576f9f1dc71 202 else
OkiAviation 0:2576f9f1dc71 203 {
OkiAviation 0:2576f9f1dc71 204 ++failedChecksumCount;
OkiAviation 0:2576f9f1dc71 205 }
OkiAviation 0:2576f9f1dc71 206
OkiAviation 0:2576f9f1dc71 207 return false;
OkiAviation 0:2576f9f1dc71 208 }
OkiAviation 0:2576f9f1dc71 209
OkiAviation 0:2576f9f1dc71 210 // the first term determines the sentence type
OkiAviation 0:2576f9f1dc71 211 if (curTermNumber == 0)
OkiAviation 0:2576f9f1dc71 212 {
OkiAviation 0:2576f9f1dc71 213 if (!strcmp(term, _GPRMCterm))
OkiAviation 0:2576f9f1dc71 214 curSentenceType = GPS_SENTENCE_GPRMC;
OkiAviation 0:2576f9f1dc71 215 else if (!strcmp(term, _GPGGAterm))
OkiAviation 0:2576f9f1dc71 216 curSentenceType = GPS_SENTENCE_GPGGA;
OkiAviation 0:2576f9f1dc71 217 else
OkiAviation 0:2576f9f1dc71 218 curSentenceType = GPS_SENTENCE_OTHER;
OkiAviation 0:2576f9f1dc71 219
OkiAviation 0:2576f9f1dc71 220 // Any custom candidates of this sentence type?
OkiAviation 0:2576f9f1dc71 221 for (customCandidates = customElts; customCandidates != NULL && strcmp(customCandidates->sentenceName, term) < 0; customCandidates = customCandidates->next);
OkiAviation 0:2576f9f1dc71 222 if (customCandidates != NULL && strcmp(customCandidates->sentenceName, term) > 0)
OkiAviation 0:2576f9f1dc71 223 customCandidates = NULL;
OkiAviation 0:2576f9f1dc71 224
OkiAviation 0:2576f9f1dc71 225 return false;
OkiAviation 0:2576f9f1dc71 226 }
OkiAviation 0:2576f9f1dc71 227
OkiAviation 0:2576f9f1dc71 228 if (curSentenceType != GPS_SENTENCE_OTHER && term[0])
OkiAviation 0:2576f9f1dc71 229 switch(COMBINE(curSentenceType, curTermNumber))
OkiAviation 0:2576f9f1dc71 230 {
OkiAviation 0:2576f9f1dc71 231 case COMBINE(GPS_SENTENCE_GPRMC, 1): // Time in both sentences
OkiAviation 0:2576f9f1dc71 232 case COMBINE(GPS_SENTENCE_GPGGA, 1):
OkiAviation 0:2576f9f1dc71 233 time.setTime(term);
OkiAviation 0:2576f9f1dc71 234 break;
OkiAviation 0:2576f9f1dc71 235 case COMBINE(GPS_SENTENCE_GPRMC, 2): // GPRMC validity
OkiAviation 0:2576f9f1dc71 236 sentenceHasFix = term[0] == 'A';
OkiAviation 0:2576f9f1dc71 237 break;
OkiAviation 0:2576f9f1dc71 238 case COMBINE(GPS_SENTENCE_GPRMC, 3): // Latitude
OkiAviation 0:2576f9f1dc71 239 case COMBINE(GPS_SENTENCE_GPGGA, 2):
OkiAviation 0:2576f9f1dc71 240 location.setLatitude(term);
OkiAviation 0:2576f9f1dc71 241 break;
OkiAviation 0:2576f9f1dc71 242 case COMBINE(GPS_SENTENCE_GPRMC, 4): // N/S
OkiAviation 0:2576f9f1dc71 243 case COMBINE(GPS_SENTENCE_GPGGA, 3):
OkiAviation 0:2576f9f1dc71 244 location.rawNewLatData.negative = term[0] == 'S';
OkiAviation 0:2576f9f1dc71 245 break;
OkiAviation 0:2576f9f1dc71 246 case COMBINE(GPS_SENTENCE_GPRMC, 5): // Longitude
OkiAviation 0:2576f9f1dc71 247 case COMBINE(GPS_SENTENCE_GPGGA, 4):
OkiAviation 0:2576f9f1dc71 248 location.setLongitude(term);
OkiAviation 0:2576f9f1dc71 249 break;
OkiAviation 0:2576f9f1dc71 250 case COMBINE(GPS_SENTENCE_GPRMC, 6): // E/W
OkiAviation 0:2576f9f1dc71 251 case COMBINE(GPS_SENTENCE_GPGGA, 5):
OkiAviation 0:2576f9f1dc71 252 location.rawNewLngData.negative = term[0] == 'W';
OkiAviation 0:2576f9f1dc71 253 break;
OkiAviation 0:2576f9f1dc71 254 case COMBINE(GPS_SENTENCE_GPRMC, 7): // Speed (GPRMC)
OkiAviation 0:2576f9f1dc71 255 speed.set(term);
OkiAviation 0:2576f9f1dc71 256 break;
OkiAviation 0:2576f9f1dc71 257 case COMBINE(GPS_SENTENCE_GPRMC, 8): // Course (GPRMC)
OkiAviation 0:2576f9f1dc71 258 course.set(term);
OkiAviation 0:2576f9f1dc71 259 break;
OkiAviation 0:2576f9f1dc71 260 case COMBINE(GPS_SENTENCE_GPRMC, 9): // Date (GPRMC)
OkiAviation 0:2576f9f1dc71 261 date.setDate(term);
OkiAviation 0:2576f9f1dc71 262 break;
OkiAviation 0:2576f9f1dc71 263 case COMBINE(GPS_SENTENCE_GPGGA, 6): // Fix data (GPGGA)
OkiAviation 0:2576f9f1dc71 264 sentenceHasFix = term[0] > '0';
OkiAviation 0:2576f9f1dc71 265 break;
OkiAviation 0:2576f9f1dc71 266 case COMBINE(GPS_SENTENCE_GPGGA, 7): // Satellites used (GPGGA)
OkiAviation 0:2576f9f1dc71 267 satellites.set(term);
OkiAviation 0:2576f9f1dc71 268 break;
OkiAviation 0:2576f9f1dc71 269 case COMBINE(GPS_SENTENCE_GPGGA, 8): // HDOP
OkiAviation 0:2576f9f1dc71 270 hdop.set(term);
OkiAviation 0:2576f9f1dc71 271 break;
OkiAviation 0:2576f9f1dc71 272 case COMBINE(GPS_SENTENCE_GPGGA, 9): // Altitude (GPGGA)
OkiAviation 0:2576f9f1dc71 273 altitude.set(term);
OkiAviation 0:2576f9f1dc71 274 break;
OkiAviation 0:2576f9f1dc71 275 }
OkiAviation 0:2576f9f1dc71 276
OkiAviation 0:2576f9f1dc71 277 // Set custom values as needed
OkiAviation 0:2576f9f1dc71 278 for (TinyGPSCustom *p = customCandidates; p != NULL && strcmp(p->sentenceName, customCandidates->sentenceName) == 0 && p->termNumber <= curTermNumber; p = p->next)
OkiAviation 0:2576f9f1dc71 279 if (p->termNumber == curTermNumber)
OkiAviation 0:2576f9f1dc71 280 p->set(term);
OkiAviation 0:2576f9f1dc71 281
OkiAviation 0:2576f9f1dc71 282 return false;
OkiAviation 0:2576f9f1dc71 283 }
OkiAviation 0:2576f9f1dc71 284
OkiAviation 0:2576f9f1dc71 285 /* static */
OkiAviation 0:2576f9f1dc71 286 double TinyGPSPlus::distanceBetween(double lat1, double long1, double lat2, double long2)
OkiAviation 0:2576f9f1dc71 287 {
OkiAviation 0:2576f9f1dc71 288 // returns distance in meters between two positions, both specified
OkiAviation 0:2576f9f1dc71 289 // as signed decimal-degrees latitude and longitude. Uses great-circle
OkiAviation 0:2576f9f1dc71 290 // distance computation for hypothetical sphere of radius 6372795 meters.
OkiAviation 0:2576f9f1dc71 291 // Because Earth is no exact sphere, rounding errors may be up to 0.5%.
OkiAviation 0:2576f9f1dc71 292 // Courtesy of Maarten Lamers
OkiAviation 0:2576f9f1dc71 293 double delta = radians(long1-long2);
OkiAviation 0:2576f9f1dc71 294 double sdlong = sin(delta);
OkiAviation 0:2576f9f1dc71 295 double cdlong = cos(delta);
OkiAviation 0:2576f9f1dc71 296 lat1 = radians(lat1);
OkiAviation 0:2576f9f1dc71 297 lat2 = radians(lat2);
OkiAviation 0:2576f9f1dc71 298 double slat1 = sin(lat1);
OkiAviation 0:2576f9f1dc71 299 double clat1 = cos(lat1);
OkiAviation 0:2576f9f1dc71 300 double slat2 = sin(lat2);
OkiAviation 0:2576f9f1dc71 301 double clat2 = cos(lat2);
OkiAviation 0:2576f9f1dc71 302 delta = (clat1 * slat2) - (slat1 * clat2 * cdlong);
OkiAviation 0:2576f9f1dc71 303 delta = sq(delta);
OkiAviation 0:2576f9f1dc71 304 delta += sq(clat2 * sdlong);
OkiAviation 0:2576f9f1dc71 305 delta = sqrt(delta);
OkiAviation 0:2576f9f1dc71 306 double denom = (slat1 * slat2) + (clat1 * clat2 * cdlong);
OkiAviation 0:2576f9f1dc71 307 delta = atan2(delta, denom);
OkiAviation 0:2576f9f1dc71 308 return delta * 6372795;
OkiAviation 0:2576f9f1dc71 309 }
OkiAviation 0:2576f9f1dc71 310
OkiAviation 0:2576f9f1dc71 311 double TinyGPSPlus::courseTo(double lat1, double long1, double lat2, double long2)
OkiAviation 0:2576f9f1dc71 312 {
OkiAviation 0:2576f9f1dc71 313 // returns course in degrees (North=0, West=270) from position 1 to position 2,
OkiAviation 0:2576f9f1dc71 314 // both specified as signed decimal-degrees latitude and longitude.
OkiAviation 0:2576f9f1dc71 315 // Because Earth is no exact sphere, calculated course may be off by a tiny fraction.
OkiAviation 0:2576f9f1dc71 316 // Courtesy of Maarten Lamers
OkiAviation 0:2576f9f1dc71 317 double dlon = radians(long2-long1);
OkiAviation 0:2576f9f1dc71 318 lat1 = radians(lat1);
OkiAviation 0:2576f9f1dc71 319 lat2 = radians(lat2);
OkiAviation 0:2576f9f1dc71 320 double a1 = sin(dlon) * cos(lat2);
OkiAviation 0:2576f9f1dc71 321 double a2 = sin(lat1) * cos(lat2) * cos(dlon);
OkiAviation 0:2576f9f1dc71 322 a2 = cos(lat1) * sin(lat2) - a2;
OkiAviation 0:2576f9f1dc71 323 a2 = atan2(a1, a2);
OkiAviation 0:2576f9f1dc71 324 if (a2 < 0.0)
OkiAviation 0:2576f9f1dc71 325 {
OkiAviation 0:2576f9f1dc71 326 a2 += TWO_PI;
OkiAviation 0:2576f9f1dc71 327 }
OkiAviation 0:2576f9f1dc71 328 return degrees(a2);
OkiAviation 0:2576f9f1dc71 329 }
OkiAviation 0:2576f9f1dc71 330
OkiAviation 0:2576f9f1dc71 331 const char *TinyGPSPlus::cardinal(double course)
OkiAviation 0:2576f9f1dc71 332 {
OkiAviation 0:2576f9f1dc71 333 static const char* directions[] = {"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"};
OkiAviation 0:2576f9f1dc71 334 int direction = (int)((course + 11.25f) / 22.5f);
OkiAviation 0:2576f9f1dc71 335 return directions[direction % 16];
OkiAviation 0:2576f9f1dc71 336 }
OkiAviation 0:2576f9f1dc71 337
OkiAviation 0:2576f9f1dc71 338 void TinyGPSLocation::commit()
OkiAviation 0:2576f9f1dc71 339 {
OkiAviation 0:2576f9f1dc71 340 rawLatData = rawNewLatData;
OkiAviation 0:2576f9f1dc71 341 rawLngData = rawNewLngData;
OkiAviation 0:2576f9f1dc71 342 lastCommitTime = millis();
OkiAviation 0:2576f9f1dc71 343 valid = updated = true;
OkiAviation 0:2576f9f1dc71 344 }
OkiAviation 0:2576f9f1dc71 345
OkiAviation 0:2576f9f1dc71 346 void TinyGPSLocation::setLatitude(const char *term)
OkiAviation 0:2576f9f1dc71 347 {
OkiAviation 0:2576f9f1dc71 348 TinyGPSPlus::parseDegrees(term, rawNewLatData);
OkiAviation 0:2576f9f1dc71 349 }
OkiAviation 0:2576f9f1dc71 350
OkiAviation 0:2576f9f1dc71 351 void TinyGPSLocation::setLongitude(const char *term)
OkiAviation 0:2576f9f1dc71 352 {
OkiAviation 0:2576f9f1dc71 353 TinyGPSPlus::parseDegrees(term, rawNewLngData);
OkiAviation 0:2576f9f1dc71 354 }
OkiAviation 0:2576f9f1dc71 355
OkiAviation 0:2576f9f1dc71 356 double TinyGPSLocation::lat()
OkiAviation 0:2576f9f1dc71 357 {
OkiAviation 0:2576f9f1dc71 358 updated = false;
OkiAviation 0:2576f9f1dc71 359 double ret = rawLatData.deg + rawLatData.billionths / 1000000000.0;
OkiAviation 0:2576f9f1dc71 360 return rawLatData.negative ? -ret : ret;
OkiAviation 0:2576f9f1dc71 361 }
OkiAviation 0:2576f9f1dc71 362
OkiAviation 0:2576f9f1dc71 363 double TinyGPSLocation::lng()
OkiAviation 0:2576f9f1dc71 364 {
OkiAviation 0:2576f9f1dc71 365 updated = false;
OkiAviation 0:2576f9f1dc71 366 double ret = rawLngData.deg + rawLngData.billionths / 1000000000.0;
OkiAviation 0:2576f9f1dc71 367 return rawLngData.negative ? -ret : ret;
OkiAviation 0:2576f9f1dc71 368 }
OkiAviation 0:2576f9f1dc71 369
OkiAviation 0:2576f9f1dc71 370 void TinyGPSDate::commit()
OkiAviation 0:2576f9f1dc71 371 {
OkiAviation 0:2576f9f1dc71 372 date = newDate;
OkiAviation 0:2576f9f1dc71 373 lastCommitTime = millis();
OkiAviation 0:2576f9f1dc71 374 valid = updated = true;
OkiAviation 0:2576f9f1dc71 375 }
OkiAviation 0:2576f9f1dc71 376
OkiAviation 0:2576f9f1dc71 377 void TinyGPSTime::commit()
OkiAviation 0:2576f9f1dc71 378 {
OkiAviation 0:2576f9f1dc71 379 time = newTime;
OkiAviation 0:2576f9f1dc71 380 lastCommitTime = millis();
OkiAviation 0:2576f9f1dc71 381 valid = updated = true;
OkiAviation 0:2576f9f1dc71 382 }
OkiAviation 0:2576f9f1dc71 383
OkiAviation 0:2576f9f1dc71 384 void TinyGPSTime::setTime(const char *term)
OkiAviation 0:2576f9f1dc71 385 {
OkiAviation 0:2576f9f1dc71 386 newTime = (uint32_t)TinyGPSPlus::parseDecimal(term);
OkiAviation 0:2576f9f1dc71 387 }
OkiAviation 0:2576f9f1dc71 388
OkiAviation 0:2576f9f1dc71 389 void TinyGPSDate::setDate(const char *term)
OkiAviation 0:2576f9f1dc71 390 {
OkiAviation 0:2576f9f1dc71 391 newDate = atol(term);
OkiAviation 0:2576f9f1dc71 392 }
OkiAviation 0:2576f9f1dc71 393
OkiAviation 0:2576f9f1dc71 394 uint16_t TinyGPSDate::year()
OkiAviation 0:2576f9f1dc71 395 {
OkiAviation 0:2576f9f1dc71 396 updated = false;
OkiAviation 0:2576f9f1dc71 397 uint16_t year = date % 100;
OkiAviation 0:2576f9f1dc71 398 return year + 2000;
OkiAviation 0:2576f9f1dc71 399 }
OkiAviation 0:2576f9f1dc71 400
OkiAviation 0:2576f9f1dc71 401 uint8_t TinyGPSDate::month()
OkiAviation 0:2576f9f1dc71 402 {
OkiAviation 0:2576f9f1dc71 403 updated = false;
OkiAviation 0:2576f9f1dc71 404 return (date / 100) % 100;
OkiAviation 0:2576f9f1dc71 405 }
OkiAviation 0:2576f9f1dc71 406
OkiAviation 0:2576f9f1dc71 407 uint8_t TinyGPSDate::day()
OkiAviation 0:2576f9f1dc71 408 {
OkiAviation 0:2576f9f1dc71 409 updated = false;
OkiAviation 0:2576f9f1dc71 410 return date / 10000;
OkiAviation 0:2576f9f1dc71 411 }
OkiAviation 0:2576f9f1dc71 412
OkiAviation 0:2576f9f1dc71 413 uint8_t TinyGPSTime::hour()
OkiAviation 0:2576f9f1dc71 414 {
OkiAviation 0:2576f9f1dc71 415 updated = false;
WaleedElmughrabi 2:9fb16575b0f8 416 return ((time / 1000000));
OkiAviation 0:2576f9f1dc71 417 }
OkiAviation 0:2576f9f1dc71 418
OkiAviation 0:2576f9f1dc71 419 uint8_t TinyGPSTime::minute()
OkiAviation 0:2576f9f1dc71 420 {
OkiAviation 0:2576f9f1dc71 421 updated = false;
OkiAviation 0:2576f9f1dc71 422 return (time / 10000) % 100;
OkiAviation 0:2576f9f1dc71 423 }
OkiAviation 0:2576f9f1dc71 424
OkiAviation 0:2576f9f1dc71 425 uint8_t TinyGPSTime::second()
OkiAviation 0:2576f9f1dc71 426 {
OkiAviation 0:2576f9f1dc71 427 updated = false;
OkiAviation 0:2576f9f1dc71 428 return (time / 100) % 100;
OkiAviation 0:2576f9f1dc71 429 }
OkiAviation 0:2576f9f1dc71 430
OkiAviation 0:2576f9f1dc71 431 uint8_t TinyGPSTime::centisecond()
OkiAviation 0:2576f9f1dc71 432 {
OkiAviation 0:2576f9f1dc71 433 updated = false;
OkiAviation 0:2576f9f1dc71 434 return time % 100;
OkiAviation 0:2576f9f1dc71 435 }
OkiAviation 0:2576f9f1dc71 436
OkiAviation 0:2576f9f1dc71 437 void TinyGPSDecimal::commit()
OkiAviation 0:2576f9f1dc71 438 {
OkiAviation 0:2576f9f1dc71 439 val = newval;
OkiAviation 0:2576f9f1dc71 440 lastCommitTime = millis();
OkiAviation 0:2576f9f1dc71 441 valid = updated = true;
OkiAviation 0:2576f9f1dc71 442 }
OkiAviation 0:2576f9f1dc71 443
OkiAviation 0:2576f9f1dc71 444 void TinyGPSDecimal::set(const char *term)
OkiAviation 0:2576f9f1dc71 445 {
OkiAviation 0:2576f9f1dc71 446 newval = TinyGPSPlus::parseDecimal(term);
OkiAviation 0:2576f9f1dc71 447 }
OkiAviation 0:2576f9f1dc71 448
OkiAviation 0:2576f9f1dc71 449 void TinyGPSInteger::commit()
OkiAviation 0:2576f9f1dc71 450 {
OkiAviation 0:2576f9f1dc71 451 val = newval;
OkiAviation 0:2576f9f1dc71 452 lastCommitTime = millis();
OkiAviation 0:2576f9f1dc71 453 valid = updated = true;
OkiAviation 0:2576f9f1dc71 454 }
OkiAviation 0:2576f9f1dc71 455
OkiAviation 0:2576f9f1dc71 456 void TinyGPSInteger::set(const char *term)
OkiAviation 0:2576f9f1dc71 457 {
OkiAviation 0:2576f9f1dc71 458 newval = atol(term);
OkiAviation 0:2576f9f1dc71 459 }
OkiAviation 0:2576f9f1dc71 460
OkiAviation 0:2576f9f1dc71 461 TinyGPSCustom::TinyGPSCustom(TinyGPSPlus &gps, const char *_sentenceName, int _termNumber)
OkiAviation 0:2576f9f1dc71 462 {
OkiAviation 0:2576f9f1dc71 463 begin(gps, _sentenceName, _termNumber);
OkiAviation 0:2576f9f1dc71 464 }
OkiAviation 0:2576f9f1dc71 465
OkiAviation 0:2576f9f1dc71 466 void TinyGPSCustom::begin(TinyGPSPlus &gps, const char *_sentenceName, int _termNumber)
OkiAviation 0:2576f9f1dc71 467 {
OkiAviation 0:2576f9f1dc71 468 lastCommitTime = 0;
OkiAviation 0:2576f9f1dc71 469 updated = valid = false;
OkiAviation 0:2576f9f1dc71 470 sentenceName = _sentenceName;
OkiAviation 0:2576f9f1dc71 471 termNumber = _termNumber;
OkiAviation 0:2576f9f1dc71 472 memset(stagingBuffer, '\0', sizeof(stagingBuffer));
OkiAviation 0:2576f9f1dc71 473 memset(buffer, '\0', sizeof(buffer));
OkiAviation 0:2576f9f1dc71 474
OkiAviation 0:2576f9f1dc71 475 // Insert this item into the GPS tree
OkiAviation 0:2576f9f1dc71 476 gps.insertCustom(this, _sentenceName, _termNumber);
OkiAviation 0:2576f9f1dc71 477 }
OkiAviation 0:2576f9f1dc71 478
OkiAviation 0:2576f9f1dc71 479 void TinyGPSCustom::commit()
OkiAviation 0:2576f9f1dc71 480 {
OkiAviation 0:2576f9f1dc71 481 strcpy(this->buffer, this->stagingBuffer);
OkiAviation 0:2576f9f1dc71 482 lastCommitTime = millis();
OkiAviation 0:2576f9f1dc71 483 valid = updated = true;
OkiAviation 0:2576f9f1dc71 484 }
OkiAviation 0:2576f9f1dc71 485
OkiAviation 0:2576f9f1dc71 486 void TinyGPSCustom::set(const char *term)
OkiAviation 0:2576f9f1dc71 487 {
OkiAviation 0:2576f9f1dc71 488 strncpy(this->stagingBuffer, term, sizeof(this->stagingBuffer));
OkiAviation 0:2576f9f1dc71 489 }
OkiAviation 0:2576f9f1dc71 490
OkiAviation 0:2576f9f1dc71 491 void TinyGPSPlus::insertCustom(TinyGPSCustom *pElt, const char *sentenceName, int termNumber)
OkiAviation 0:2576f9f1dc71 492 {
OkiAviation 0:2576f9f1dc71 493 TinyGPSCustom **ppelt;
OkiAviation 0:2576f9f1dc71 494
OkiAviation 0:2576f9f1dc71 495 for (ppelt = &this->customElts; *ppelt != NULL; ppelt = &(*ppelt)->next)
OkiAviation 0:2576f9f1dc71 496 {
OkiAviation 0:2576f9f1dc71 497 int cmp = strcmp(sentenceName, (*ppelt)->sentenceName);
OkiAviation 0:2576f9f1dc71 498 if (cmp < 0 || (cmp == 0 && termNumber < (*ppelt)->termNumber))
OkiAviation 0:2576f9f1dc71 499 break;
OkiAviation 0:2576f9f1dc71 500 }
OkiAviation 0:2576f9f1dc71 501
OkiAviation 0:2576f9f1dc71 502 pElt->next = *ppelt;
OkiAviation 0:2576f9f1dc71 503 *ppelt = pElt;
OkiAviation 0:2576f9f1dc71 504 }