@@ -36,11 +36,11 @@ TinyGPSPlus::TinyGPSPlus()
3636 , curSentenceType(GPS_SENTENCE_OTHER)
3737 , curTermNumber(0 )
3838 , curTermOffset(0 )
39- , gpsDataGood (false )
39+ , sentenceHasFix (false )
4040 , customElts(0 )
4141 , customCandidates(0 )
4242 , encodedCharCount(0 )
43- , goodSentenceCount (0 )
43+ , sentencesWithFixCount (0 )
4444 , failedChecksumCount(0 )
4545 , passedChecksumCount(0 )
4646{
@@ -81,7 +81,7 @@ bool TinyGPSPlus::encode(char c)
8181 parity = 0 ;
8282 curSentenceType = GPS_SENTENCE_OTHER;
8383 isChecksumTerm = false ;
84- gpsDataGood = false ;
84+ sentenceHasFix = false ;
8585 return false ;
8686
8787 default : // ordinary characters
@@ -127,21 +127,26 @@ int32_t TinyGPSPlus::parseDecimal(const char *term)
127127
128128// static
129129// Parse degrees in that funny NMEA format DDMM.MMMM
130- uint32_t TinyGPSPlus::parseDegrees (const char *term)
130+ void TinyGPSPlus::parseDegrees (const char *term, int16_t °rees, uint32_t &billionths )
131131{
132- unsigned long leftOfDecimal = atol (term);
133- unsigned long _100000thsOfMinute = (leftOfDecimal % 100UL ) * 100000UL ;
134- while (isdigit (*term)) ++term;
132+ uint32_t leftOfDecimal = (uint32_t )atol (term);
133+ uint16_t minutes = (uint16_t )(leftOfDecimal % 100 );
134+ uint32_t multiplier = 10000000UL ;
135+ uint32_t tenMillionthsOfMinutes = minutes * multiplier;
136+
137+ degrees = (int16_t )(leftOfDecimal / 100 );
138+
139+ while (isdigit (*term))
140+ ++term;
141+
135142 if (*term == ' .' )
136- {
137- unsigned long mult = 10000 ;
138143 while (isdigit (*++term))
139144 {
140- _100000thsOfMinute += mult * (*term - ' 0 ' ) ;
141- mult /= 10 ;
145+ multiplier /= 10 ;
146+ tenMillionthsOfMinutes += (*term - ' 0 ' ) * multiplier ;
142147 }
143- }
144- return (leftOfDecimal / 100 ) * 1000000 + (_100000thsOfMinute + 3 ) / 6 ;
148+
149+ billionths = ( 5 * tenMillionthsOfMinutes + 1 ) / 3 ;
145150}
146151
147152#define COMBINE (sentence_type, term_number ) (((unsigned )(sentence_type) << 5 ) | term_number)
@@ -150,34 +155,38 @@ uint32_t TinyGPSPlus::parseDegrees(const char *term)
150155// Returns true if new sentence has just passed checksum test and is validated
151156bool TinyGPSPlus::endOfTermHandler ()
152157{
153- // If it's the checksum term, and the checksum checks out and it's got "good" data, then commit it
158+ // If it's the checksum term, and the checksum checks out, commit
154159 if (isChecksumTerm)
155160 {
156161 byte checksum = 16 * fromHex (term[0 ]) + fromHex (term[1 ]);
157162 if (checksum == parity)
158163 {
159164 passedChecksumCount++;
160- if (gpsDataGood)
161- {
162- ++goodSentenceCount;
165+ if (sentenceHasFix)
166+ ++sentencesWithFixCount;
163167
164- switch (curSentenceType)
168+ switch (curSentenceType)
169+ {
170+ case GPS_SENTENCE_GPRMC:
171+ date.commit ();
172+ time.commit ();
173+ if (sentenceHasFix)
165174 {
166- case GPS_SENTENCE_GPRMC:
167- date.commit ();
168- time.commit ();
169175 location.commit ();
170176 speed.commit ();
171177 course.commit ();
172- break ;
173- case GPS_SENTENCE_GPGGA:
174- time.commit ();
175- location.commit ();
176- altitude.commit ();
177- satellites.commit ();
178- hdop.commit ();
179- break ;
180178 }
179+ break ;
180+ case GPS_SENTENCE_GPGGA:
181+ time.commit ();
182+ if (sentenceHasFix)
183+ {
184+ location.commit ();
185+ altitude.commit ();
186+ }
187+ satellites.commit ();
188+ hdop.commit ();
189+ break ;
181190 }
182191
183192 // Commit all custom listeners of this sentence type
@@ -220,7 +229,7 @@ bool TinyGPSPlus::endOfTermHandler()
220229 time.setTime (term);
221230 break ;
222231 case COMBINE (GPS_SENTENCE_GPRMC, 2 ): // GPRMC validity
223- gpsDataGood = term[0 ] == ' A' ;
232+ sentenceHasFix = term[0 ] == ' A' ;
224233 break ;
225234 case COMBINE (GPS_SENTENCE_GPRMC, 3 ): // Latitude
226235 case COMBINE (GPS_SENTENCE_GPGGA, 2 ):
@@ -229,7 +238,7 @@ bool TinyGPSPlus::endOfTermHandler()
229238 case COMBINE (GPS_SENTENCE_GPRMC, 4 ): // N/S
230239 case COMBINE (GPS_SENTENCE_GPGGA, 3 ):
231240 if (term[0 ] == ' S' )
232- location.newlat = -location.newlat ;
241+ location.iNewLatDegrees = -location.iNewLatDegrees ;
233242 break ;
234243 case COMBINE (GPS_SENTENCE_GPRMC, 5 ): // Longitude
235244 case COMBINE (GPS_SENTENCE_GPGGA, 4 ):
@@ -238,7 +247,7 @@ bool TinyGPSPlus::endOfTermHandler()
238247 case COMBINE (GPS_SENTENCE_GPRMC, 6 ): // E/W
239248 case COMBINE (GPS_SENTENCE_GPGGA, 5 ):
240249 if (term[0 ] == ' W' )
241- location.newlng = -location.newlng ;
250+ location.iNewLngDegrees = -location.iNewLngDegrees ;
242251 break ;
243252 case COMBINE (GPS_SENTENCE_GPRMC, 7 ): // Speed (GPRMC)
244253 speed.set (term);
@@ -250,7 +259,7 @@ bool TinyGPSPlus::endOfTermHandler()
250259 date.setDate (term);
251260 break ;
252261 case COMBINE (GPS_SENTENCE_GPGGA, 6 ): // Fix data (GPGGA)
253- gpsDataGood = term[0 ] > ' 0' ;
262+ sentenceHasFix = term[0 ] > ' 0' ;
254263 break ;
255264 case COMBINE (GPS_SENTENCE_GPGGA, 7 ): // Satellites used (GPGGA)
256265 satellites.set (term);
@@ -320,39 +329,44 @@ double TinyGPSPlus::courseTo(double lat1, double long1, double lat2, double long
320329const char *TinyGPSPlus::cardinal (double course)
321330{
322331 static const char * directions[] = {" N" , " NNE" , " NE" , " ENE" , " E" , " ESE" , " SE" , " SSE" , " S" , " SSW" , " SW" , " WSW" , " W" , " WNW" , " NW" , " NNW" };
323-
324332 int direction = (int )((course + 11 .25f ) / 22 .5f );
325333 return directions[direction % 16 ];
326334}
327335
328336void TinyGPSLocation::commit ()
329337{
330- ilat = newlat;
331- ilng = newlng;
338+ iLatDegrees = iNewLatDegrees;
339+ uLatBillionths = uNewLatBillionths;
340+ iLngDegrees = iNewLngDegrees;
341+ uLngBillionths = uNewLngBillionths;
332342 lastCommitTime = millis ();
333343 valid = updated = true ;
334344}
335345
336346void TinyGPSLocation::setLatitude (const char *term)
337347{
338- newlat = TinyGPSPlus::parseDegrees (term);
348+ TinyGPSPlus::parseDegrees (term, iNewLatDegrees, uNewLatBillionths );
339349}
340350
341351void TinyGPSLocation::setLongitude (const char *term)
342352{
343- newlng = TinyGPSPlus::parseDegrees (term);
353+ TinyGPSPlus::parseDegrees (term, iNewLngDegrees, uNewLngBillionths );
344354}
345355
346356double TinyGPSLocation::lat ()
347357{
348358 updated = false ;
349- return ilat / 1000000.0 ;
359+ return iLatDegrees > 0 ?
360+ (iLatDegrees + uLatBillionths / 1000000000.0 ) :
361+ (iLatDegrees - uLatBillionths / 1000000000.0 );
350362}
351363
352364double TinyGPSLocation::lng ()
353365{
354366 updated = false ;
355- return ilng / 1000000.0 ;
367+ return iLngDegrees > 0 ?
368+ (iLngDegrees + uLngBillionths / 1000000000.0 ) :
369+ (iLngDegrees - uLngBillionths / 1000000000.0 );
356370}
357371
358372void TinyGPSDate::commit ()
0 commit comments