Improve GPS stale probe recovery (#10714)
* Improve GPS stale probe recovery * Address GPS review feedback
This commit is contained in:
co-authored by
GitHub
parent
5d1c4f15b7
commit
882ca0a216
+71
-17
@@ -80,6 +80,12 @@ namespace
|
||||
constexpr uint32_t GPS_PROBE_CACHE_MAGIC = 0x47504348UL; // "GPCH"
|
||||
constexpr uint16_t GPS_PROBE_CACHE_VERSION = 1;
|
||||
constexpr const char *GPS_PROBE_CACHE_FILE = "/prefs/gps_probe_cache.dat";
|
||||
constexpr int MIN_PLAUSIBLE_GPS_YEAR = 2020;
|
||||
constexpr int MAX_PLAUSIBLE_GPS_YEAR = 2100;
|
||||
#ifdef TRACKER_T1000_E
|
||||
constexpr uint32_t T1000_E_AIROHA_WAKE_MS = 1000;
|
||||
constexpr uint32_t T1000_E_AIROHA_WAKE_INTERVAL_MS = 40;
|
||||
#endif
|
||||
|
||||
struct GPSProbeCacheRecord {
|
||||
uint32_t magic;
|
||||
@@ -101,6 +107,45 @@ bool isValidProbeBaud(uint32_t baud)
|
||||
return baud >= 1200 && baud <= 921600;
|
||||
}
|
||||
|
||||
template <typename T> void wakeAirohaForActiveProbe(T *serialGps)
|
||||
{
|
||||
#ifdef TRACKER_T1000_E
|
||||
digitalWrite(PIN_GPS_EN, GPS_EN_ACTIVE);
|
||||
digitalWrite(GPS_RTC_INT, HIGH);
|
||||
delay(3);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
delay(50);
|
||||
|
||||
const uint32_t start = millis();
|
||||
do {
|
||||
serialGps->write("$PAIR382,1*2E\r\n");
|
||||
delay(T1000_E_AIROHA_WAKE_INTERVAL_MS);
|
||||
} while (Throttle::isWithinTimespanMs(start, T1000_E_AIROHA_WAKE_MS));
|
||||
#elif defined(GNSS_AIROHA)
|
||||
serialGps->write("$PAIR382,1*2E\r\n");
|
||||
delay(20);
|
||||
#else
|
||||
(void)serialGps;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool isPlausibleNmeaTime(const struct tm &t)
|
||||
{
|
||||
const int year = t.tm_year + 1900;
|
||||
if (year < MIN_PLAUSIBLE_GPS_YEAR || year > MAX_PLAUSIBLE_GPS_YEAR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef BUILD_EPOCH
|
||||
const int64_t candidate = static_cast<int64_t>(gm_mktime(&t));
|
||||
const int64_t minEpoch = static_cast<int64_t>(BUILD_EPOCH);
|
||||
const int64_t maxEpoch = minEpoch + static_cast<int64_t>(FORTY_YEARS);
|
||||
return candidate >= minEpoch && candidate <= maxEpoch;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T> bool sawNmeaSentenceAtBaud(T *serialGps, uint32_t timeoutMs)
|
||||
{
|
||||
// Lightweight passive check: look for at least one complete
|
||||
@@ -689,6 +734,7 @@ bool GPS::verifyCachedProbePresence()
|
||||
case GNSS_MODEL_AG3352:
|
||||
if (cachedProbeModel == GNSS_MODEL_AG3352)
|
||||
cachedProbeModelName = "AG3352";
|
||||
wakeAirohaForActiveProbe(_serial_gps);
|
||||
_serial_gps->write("$PAIR021*39\r\n");
|
||||
present = (getACK("$PAIR021,", 900) == GNSS_RESPONSE_OK);
|
||||
break;
|
||||
@@ -741,7 +787,6 @@ bool GPS::verifyCachedProbePresence()
|
||||
if (!present) {
|
||||
LOG_WARN("Cached GPS probe is stale (%s @ %d), clearing cache", cachedProbeModelName, cachedProbeBaud);
|
||||
clearProbeCache();
|
||||
cachedProbeFailedThisBoot = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -762,13 +807,6 @@ bool GPS::setup()
|
||||
{
|
||||
if (!didSerialInit) {
|
||||
int msglen = 0;
|
||||
if (cachedProbeFailedThisBoot) {
|
||||
// If cached verification failed, suppress further probing until
|
||||
// reboot.
|
||||
didSerialInit = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tx_gpio && gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
if (!hasProbeCache && !triedProbeCache) {
|
||||
(void)loadProbeCache();
|
||||
@@ -777,12 +815,13 @@ bool GPS::setup()
|
||||
if (hasProbeCache && !triedProbeCache) {
|
||||
triedProbeCache = true;
|
||||
if (!verifyCachedProbePresence()) {
|
||||
// Cache was stale and got wiped; skip scanning this boot
|
||||
// and let next boot do a full probe.
|
||||
didSerialInit = true;
|
||||
return true;
|
||||
currentStep = 0;
|
||||
speedSelect = 0;
|
||||
probeTries = 0;
|
||||
}
|
||||
} else if (probeTries < GPS_PROBETRIES) {
|
||||
}
|
||||
|
||||
if (gnssModel == GNSS_MODEL_UNKNOWN && probeTries < GPS_PROBETRIES) {
|
||||
// No usable cache: walk common baud rates first.
|
||||
gnssModel = probe(serialSpeeds[speedSelect]);
|
||||
if (gnssModel != GNSS_MODEL_UNKNOWN) {
|
||||
@@ -794,7 +833,7 @@ bool GPS::setup()
|
||||
}
|
||||
// Rare Serial Speeds
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C6
|
||||
else if (probeTries == GPS_PROBETRIES) {
|
||||
else if (gnssModel == GNSS_MODEL_UNKNOWN && probeTries == GPS_PROBETRIES) {
|
||||
// Then try less common baud rates before giving up.
|
||||
gnssModel = probe(rareSerialSpeeds[speedSelect]);
|
||||
if (gnssModel != GNSS_MODEL_UNKNOWN) {
|
||||
@@ -1125,6 +1164,15 @@ void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
|
||||
break;
|
||||
if (oldState != GPS_ACTIVE && oldState != GPS_IDLE) // If hardware just waking now, clear buffer
|
||||
clearBuffer();
|
||||
#ifdef TRACKER_T1000_E
|
||||
pinMode(GPS_VRTC_EN, OUTPUT);
|
||||
digitalWrite(GPS_VRTC_EN, HIGH);
|
||||
pinMode(GPS_SLEEP_INT, OUTPUT);
|
||||
digitalWrite(GPS_SLEEP_INT, HIGH);
|
||||
pinMode(GPS_RTC_INT, OUTPUT);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
pinMode(GPS_RESETB_OUT, INPUT_PULLUP);
|
||||
#endif
|
||||
powerMon->setState(meshtastic_PowerMon_State_GPS_Active); // Report change for power monitoring (during testing)
|
||||
writePinEN(true); // Power (EN pin): on
|
||||
setPowerPMU(true); // Power (PMU): on
|
||||
@@ -1383,9 +1431,8 @@ int32_t GPS::runOnce()
|
||||
if (!setup())
|
||||
return currentDelay; // Setup failed, re-run in two seconds
|
||||
|
||||
if (cachedProbeFailedThisBoot || gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
LOG_WARN("GPS not detected at cached settings; marked not present "
|
||||
"for this boot");
|
||||
if (gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
LOG_WARN("GPS not detected; marked not present for this boot");
|
||||
return disable();
|
||||
}
|
||||
|
||||
@@ -1585,6 +1632,9 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
digitalWrite(PIN_GPS_RESET, GPS_RESET_MODE); // assert for 10ms
|
||||
delay(10);
|
||||
digitalWrite(PIN_GPS_RESET, !GPS_RESET_MODE);
|
||||
#ifdef TRACKER_T1000_E
|
||||
delay(100);
|
||||
#endif
|
||||
|
||||
// attempt to detect the chip based on boot messages
|
||||
std::vector<ChipInfo> passive_detect = {
|
||||
@@ -1637,6 +1687,7 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
}
|
||||
case 3: {
|
||||
/* Airoha (Mediatek) AG3335A/M/S, A3352Q, Quectel L89 2.0, SimCom SIM65M */
|
||||
wakeAirohaForActiveProbe(_serial_gps);
|
||||
_serial_gps->write("$PAIR062,2,0*3C\r\n"); // GSA OFF to reduce volume
|
||||
_serial_gps->write("$PAIR062,3,0*3D\r\n"); // GSV OFF to reduce volume
|
||||
_serial_gps->write("$PAIR513*3D\r\n"); // save configuration
|
||||
@@ -1968,6 +2019,9 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
|
||||
t.tm_year = d.year() - 1900;
|
||||
t.tm_isdst = false;
|
||||
if (t.tm_mon > -1) {
|
||||
if (!isPlausibleNmeaTime(t)) {
|
||||
return false;
|
||||
}
|
||||
if (perhapsSetRTC(RTCQualityGPS, t) == RTCSetResultSuccess) {
|
||||
LOG_DEBUG("NMEA GPS time set %02d-%02d-%02d %02d:%02d:%02d age %d", d.year(), d.month(), t.tm_mday, t.tm_hour,
|
||||
t.tm_min, t.tm_sec, ti.age());
|
||||
|
||||
@@ -193,8 +193,6 @@ class GPS : private concurrency::OSThread
|
||||
bool hasProbeCache = false;
|
||||
// Ensures cached probe is attempted once per boot.
|
||||
bool triedProbeCache = false;
|
||||
// Latched when cached presence check fails
|
||||
bool cachedProbeFailedThisBoot = false;
|
||||
|
||||
/**
|
||||
* hasValidLocation - indicates that the position variables contain a complete
|
||||
|
||||
@@ -45,13 +45,13 @@ void initVariant()
|
||||
digitalWrite(BUZZER_EN_PIN, HIGH);
|
||||
|
||||
pinMode(PIN_GPS_EN, OUTPUT);
|
||||
digitalWrite(PIN_GPS_EN, LOW);
|
||||
digitalWrite(PIN_GPS_EN, GPS_EN_ACTIVE);
|
||||
|
||||
pinMode(GPS_VRTC_EN, OUTPUT);
|
||||
digitalWrite(GPS_VRTC_EN, HIGH);
|
||||
|
||||
pinMode(PIN_GPS_RESET, OUTPUT);
|
||||
digitalWrite(PIN_GPS_RESET, LOW);
|
||||
digitalWrite(PIN_GPS_RESET, !GPS_RESET_MODE);
|
||||
|
||||
pinMode(GPS_SLEEP_INT, OUTPUT);
|
||||
digitalWrite(GPS_SLEEP_INT, HIGH);
|
||||
@@ -59,5 +59,5 @@ void initVariant()
|
||||
pinMode(GPS_RTC_INT, OUTPUT);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
|
||||
pinMode(GPS_RESETB_OUT, INPUT);
|
||||
}
|
||||
pinMode(GPS_RESETB_OUT, INPUT_PULLUP);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user