Reset GPS receive state without changing buffer roles

Clear the embedded framer during common_init() and initialize lastline only once so repeated initialization preserves the actual completed buffer. Cover initial, odd, and even buffer swaps, discarded partial input, cleared timestamps, and resumed reception.

Co-authored-by: Limor Fried <ladyada@users.noreply.github.com>
This commit is contained in:
ladyadaandLimor Fried committed 2026-09-15 19:00:09 -04:00
1 parent ee7522e7b5
commit e1996d8b49
3 files changed
+52 -2

No files matched your search

+47
View File
@@ -1,4 +1,10 @@
#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
// common_init() detaches the transport; reconnect the test stream afterwards.
#define private public
#include <Adafruit_GPS.h>
#undef private
class TestStream : public Stream {
public:
@@ -18,6 +24,7 @@ const char navigation[] =
"$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A\r\n";
bool receive(TestStream &stream, Adafruit_GPS &gps, const char *text);
bool checkReinitialization();
void setup() {
Serial.begin(115200);
@@ -134,6 +141,11 @@ void setup() {
return;
}
Serial.println(F("PASS: two receivers keep independent sentence timestamps"));
if (!checkReinitialization()) {
Serial.println(F("FAIL: reinitialization retained input or mixed buffer roles"));
return;
}
Serial.println(F("PASS: reinitialization clears input and preserves buffer roles"));
testsPassed = true;
}
@@ -159,3 +171,38 @@ bool receive(TestStream &stream, Adafruit_GPS &gps, const char *text) {
}
return completed;
}
bool checkReinitialization() {
// Cover the initial buffer orientation and both roles after completed lines.
for (uint8_t completed = 0; completed < 3; completed++) {
TestStream stream;
Adafruit_GPS gps((Stream *)&stream);
for (uint8_t i = 0; i < completed; i++) {
if (!receive(stream, gps, navigation)) {
return false;
}
}
// Leave any completed line unacknowledged while starting another line.
receive(stream, gps, "$stale,");
gps.common_init();
if (gps.newNMEAreceived() || gps.lastNMEA()[0] ||
gps.receiver.lastText().data || gps.receiver.sentenceStartedAt() ||
gps.receiver.sentenceReceivedAt()) {
return false;
}
gps.gpsStream = &stream;
if (receive(stream, gps, "tail\n") || gps.lastNMEA()[0] ||
receive(stream, gps, "$fresh,") || gps.lastNMEA()[0] ||
!receive(stream, gps, navigation) || strcmp(gps.lastNMEA(), navigation)) {
return false;
}
if (receive(stream, gps, "$next,") || strcmp(gps.lastNMEA(), navigation)) {
return false;
}
gps.common_init();
if (gps.newNMEAreceived() || gps.lastNMEA()[0]) {
return false;
}
}
return true;
}
+3 -1
View File
@@ -159,7 +159,9 @@ void Adafruit_GPS::common_init(void) {
gpsSPI = NULL;
recvdflag = false;
paused = false;
lastline = (const char *)line2;
// Reset clears both buffers without swapping them. Keep lastline pointing
// at the completed buffer, which may be either line1 or line2 by now.
receiver.reset();
hour = minute = seconds = year = month = day = fixquality = fixquality_3d =
satellites = antenna = 0; // uint8_t
+2 -1
View File
@@ -292,7 +292,8 @@ private:
///< and leave one for the main program
volatile char line2[MAXLINELENGTH]; ///< Second buffer
Adafruit_NMEA receiver{line1, line2, MAXLINELENGTH}; ///< Bounded byte framing
const char *volatile lastline; ///< Completed line published by read()
const char *volatile lastline =
(const char *)line2; ///< Completed line published by read()
volatile bool recvdflag; ///< Received flag
volatile bool inStandbyMode; ///< In standby flag
};