RTC: add notion of 'quality' for different time sources

Allow use of mesh based time until a GPS time arrives
1.2-legacy
Kevin Hester 2020-10-08 07:46:20 +08:00
rodzic f00d07baa3
commit 023f1c24fb
7 zmienionych plików z 40 dodań i 31 usunięć

Wyświetl plik

@ -6,8 +6,6 @@ bin/run.sh --set region 8
time only mode
./bin/run.sh --set gps_operation 3
set time provisionally from net even if we have gps
ublox parsing failure
record power measurements and update spreadsheet

Wyświetl plik

@ -1,10 +1,10 @@
#include "GPS.h"
#include "NodeDB.h"
#include "RTC.h"
#include "configuration.h"
#include "sleep.h"
#include <assert.h>
#include "RTC.h"
// If we have a serial GPS port it will not be null
#ifdef GPS_RX_PIN
@ -23,10 +23,8 @@ uint8_t GPS::i2cAddress = GPS_I2C_ADDRESS;
uint8_t GPS::i2cAddress = 0;
#endif
GPS *gps;
bool GPS::setup()
{
setAwake(true); // Wake GPS power before doing any init
@ -99,7 +97,8 @@ uint32_t GPS::getSleepTime() const
uint32_t t = radioConfig.preferences.gps_update_interval;
auto op = getGpsOp();
if ((timeSetFromGPS && op == GpsOperation_GpsOpTimeOnly) || (op == GpsOperation_GpsOpDisabled))
bool gotTime = (getRTCQuality() >= RTCQualityGPS);
if ((gotTime && op == GpsOperation_GpsOpTimeOnly) || (op == GpsOperation_GpsOpDisabled))
t = UINT32_MAX; // Sleep forever now
if (t == UINT32_MAX)
@ -148,7 +147,7 @@ void GPS::loop()
}
// If we've already set time from the GPS, no need to ask the GPS
bool gotTime = timeSetFromGPS || lookForTime();
bool gotTime = (getRTCQuality() >= RTCQualityGPS) || lookForTime();
bool gotLoc = lookForLocation();
// We've been awake too long - force sleep
@ -158,7 +157,7 @@ void GPS::loop()
// Once we get a location we no longer desperately want an update
// or if we got a time and we are in GpsOpTimeOnly mode
// DEBUG_MSG("gotLoc %d, tooLong %d, gotTime %d\n", gotLoc, tooLong, gotTime);
if ((gotLoc && timeSetFromGPS) || tooLong || (gotTime && getGpsOp() == GpsOperation_GpsOpTimeOnly)) {
if ((gotLoc && gotTime) || tooLong || (gotTime && getGpsOp() == GpsOperation_GpsOpTimeOnly)) {
if (gotLoc)
hasValidLocation = true;

Wyświetl plik

@ -45,7 +45,7 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
t.tm_mon = d.month() - 1;
t.tm_year = d.year() - 1900;
t.tm_isdst = false;
perhapsSetRTC(t);
perhapsSetRTC(RTCQualityGPS, t);
return true;
} else

Wyświetl plik

@ -1,9 +1,14 @@
#include "configuration.h"
#include "RTC.h"
#include "configuration.h"
#include <sys/time.h>
#include <time.h>
bool timeSetFromGPS; // We try to set our time from GPS each time we wake from sleep
static RTCQuality currentQuality = RTCQualityNone;
RTCQuality getRTCQuality()
{
return currentQuality;
}
// stuff that really should be in in the instance instead...
static uint32_t
@ -17,17 +22,17 @@ void readFromRTC()
if (!gettimeofday(&tv, NULL)) {
uint32_t now = millis();
DEBUG_MSG("Read RTC time as %ld (cur millis %u) valid=%d\n", tv.tv_sec, now, timeSetFromGPS);
DEBUG_MSG("Read RTC time as %ld (cur millis %u) quality=%d\n", tv.tv_sec, now, currentQuality);
timeStartMsec = now;
zeroOffsetSecs = tv.tv_sec;
}
}
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
bool perhapsSetRTC(const struct timeval *tv)
bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
{
if (!timeSetFromGPS) {
timeSetFromGPS = true;
if (q > currentQuality) {
currentQuality = q;
DEBUG_MSG("Setting RTC %ld secs\n", tv->tv_sec);
#ifndef NO_ESP32
settimeofday(tv, NULL);
@ -41,7 +46,7 @@ bool perhapsSetRTC(const struct timeval *tv)
}
}
bool perhapsSetRTC(struct tm &t)
bool perhapsSetRTC(RTCQuality q, struct tm &t)
{
/* Convert to unix time
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970
@ -57,7 +62,7 @@ bool perhapsSetRTC(struct tm &t)
// DEBUG_MSG("Ignoring invalid GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
return false;
} else {
return perhapsSetRTC(&tv);
return perhapsSetRTC(q, &tv);
}
}
@ -68,5 +73,5 @@ uint32_t getTime()
uint32_t getValidTime()
{
return timeSetFromGPS ? getTime() : 0;
return (currentQuality >= RTCQualityFromNet) ? getTime() : 0;
}

Wyświetl plik

@ -4,16 +4,27 @@
#include "sys/time.h"
#include <Arduino.h>
extern bool timeSetFromGPS; // We try to set our time from GPS each time we wake from sleep
enum RTCQuality {
/// We haven't had our RTC set yet
RTCQualityNone = 0,
/// Some other node gave us a time we can use
RTCQualityFromNet = 1,
/// Our time is based on our own GPS
RTCQualityGPS = 2
};
RTCQuality getRTCQuality();
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
bool perhapsSetRTC(const struct timeval *tv);
bool perhapsSetRTC(struct tm &t);
bool perhapsSetRTC(RTCQuality q, const struct timeval *tv);
bool perhapsSetRTC(RTCQuality q, struct tm &t);
/// Return time since 1970 in secs. Until we have a GPS lock we will be returning time based at zero
/// Return time since 1970 in secs. While quality is RTCQualityNone we will be returning time based at zero
uint32_t getTime();
/// Return time since 1970 in secs. If we don't have a GPS lock return zero
/// Return time since 1970 in secs. If quality is RTCQualityNone return zero
uint32_t getValidTime();
void readFromRTC();

Wyświetl plik

@ -152,7 +152,7 @@ bool UBloxGPS::lookForTime()
t.tm_mon = ublox.getMonth(0) - 1;
t.tm_year = ublox.getYear(0) - 1900;
t.tm_isdst = false;
perhapsSetRTC(t);
perhapsSetRTC(RTCQualityGPS, t);
return true;
}

Wyświetl plik

@ -140,7 +140,7 @@ void MeshService::handleIncomingPosition(const MeshPacket *mp)
tv.tv_sec = secs;
tv.tv_usec = 0;
perhapsSetRTC(&tv);
perhapsSetRTC(RTCQualityFromNet, &tv);
}
} else {
DEBUG_MSG("Ignoring incoming packet - not a position\n");
@ -151,12 +151,8 @@ int MeshService::handleFromRadio(const MeshPacket *mp)
{
powerFSM.trigger(EVENT_RECEIVED_PACKET); // Possibly keep the node from sleeping
// If it is a position packet, perhaps set our clock (if we don't have a GPS of our own, otherwise wait for that to work)
if (!gps->isConnected)
handleIncomingPosition(mp);
else {
DEBUG_MSG("Ignoring incoming time, because we have a GPS\n");
}
// If it is a position packet, perhaps set our clock
handleIncomingPosition(mp);
if (mp->which_payload == MeshPacket_decoded_tag && mp->decoded.which_payload == SubPacket_user_tag) {
mp = handleFromRadioUser(mp);