mirror of
https://github.com/meshtastic/firmware.git
synced 2025-09-20 16:56:17 +00:00
abstract out the UBlox GPS driver
This commit is contained in:
parent
ecf528f9b6
commit
933d5424da
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -50,7 +50,9 @@
|
||||
"cassert": "cpp"
|
||||
},
|
||||
"cSpell.words": [
|
||||
"Blox",
|
||||
"Meshtastic",
|
||||
"Ublox",
|
||||
"descs",
|
||||
"protobufs"
|
||||
]
|
||||
|
@ -31,7 +31,7 @@ board_build.partitions = partition-table.csv
|
||||
|
||||
; note: we add src to our include search path so that lmic_project_config can override
|
||||
; FIXME: fix lib/BluetoothOTA dependency back on src/ so we can remove -Isrc
|
||||
build_flags = -Wno-missing-field-initializers -Isrc -Isrc/mesh -Ilib/nanopb/include -Os -Wl,-Map,.pio/build/output.map
|
||||
build_flags = -Wno-missing-field-initializers -Isrc -Isrc/mesh -Isrc/gps -Ilib/nanopb/include -Os -Wl,-Map,.pio/build/output.map
|
||||
-DAXP_DEBUG_PORT=Serial
|
||||
-DHW_VERSION_${sysenv.COUNTRY}
|
||||
-DAPP_VERSION=${sysenv.APP_VERSION}
|
||||
|
@ -87,7 +87,7 @@ static void lsIdle()
|
||||
static void lsExit()
|
||||
{
|
||||
// setGPSPower(true); // restore GPS power
|
||||
gps.startLock();
|
||||
gps->startLock();
|
||||
}
|
||||
|
||||
static void nbEnter()
|
||||
|
@ -178,7 +178,7 @@ class MyNodeInfoCharacteristic : public ProtobufCharacteristic
|
||||
void onRead(BLECharacteristic *c)
|
||||
{
|
||||
// update gps connection state
|
||||
myNodeInfo.has_gps = gps.isConnected;
|
||||
myNodeInfo.has_gps = gps->isConnected;
|
||||
|
||||
ProtobufCharacteristic::onRead(c);
|
||||
|
||||
|
171
src/gps/GPS.cpp
171
src/gps/GPS.cpp
@ -6,89 +6,23 @@
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef GPS_RX_PIN
|
||||
HardwareSerial _serial_gps(GPS_SERIAL_NUM);
|
||||
HardwareSerial _serial_gps_real(GPS_SERIAL_NUM);
|
||||
HardwareSerial &GPS::_serial_gps = _serial_gps_real;
|
||||
#else
|
||||
// Assume NRF52
|
||||
HardwareSerial &_serial_gps = Serial1;
|
||||
HardwareSerial &GPS::_serial_gps = Serial1;
|
||||
#endif
|
||||
|
||||
bool timeSetFromGPS; // We try to set our time from GPS each time we wake from sleep
|
||||
|
||||
GPS gps;
|
||||
GPS *gps;
|
||||
|
||||
// stuff that really should be in in the instance instead...
|
||||
static uint32_t
|
||||
timeStartMsec; // Once we have a GPS lock, this is where we hold the initial msec clock that corresponds to that time
|
||||
static uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only updated once on initial lock
|
||||
|
||||
static bool wantNewLocation = true;
|
||||
|
||||
GPS::GPS() : PeriodicTask() {}
|
||||
|
||||
void GPS::setup()
|
||||
{
|
||||
PeriodicTask::setup();
|
||||
|
||||
readFromRTC(); // read the main CPU RTC at first
|
||||
|
||||
#ifdef GPS_RX_PIN
|
||||
_serial_gps.begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
|
||||
#else
|
||||
_serial_gps.begin(GPS_BAUDRATE);
|
||||
#endif
|
||||
// _serial_gps.setRxBufferSize(1024); // the default is 256
|
||||
// ublox.enableDebugging(Serial);
|
||||
|
||||
// note: the lib's implementation has the wrong docs for what the return val is
|
||||
// it is not a bool, it returns zero for success
|
||||
isConnected = ublox.begin(_serial_gps);
|
||||
|
||||
// try a second time, the ublox lib serial parsing is buggy?
|
||||
if (!isConnected)
|
||||
isConnected = ublox.begin(_serial_gps);
|
||||
|
||||
if (isConnected) {
|
||||
DEBUG_MSG("Connected to UBLOX GPS successfully\n");
|
||||
|
||||
bool factoryReset = false;
|
||||
bool ok;
|
||||
if (factoryReset) {
|
||||
// It is useful to force back into factory defaults (9600baud, NEMA to test the behavior of boards that don't have
|
||||
// GPS_TX connected)
|
||||
ublox.factoryReset();
|
||||
delay(2000);
|
||||
isConnected = ublox.begin(_serial_gps);
|
||||
DEBUG_MSG("Factory reset success=%d\n", isConnected);
|
||||
if (isConnected) {
|
||||
ublox.assumeAutoPVT(true, true); // Just parse NEMA for now
|
||||
}
|
||||
} else {
|
||||
ok = ublox.setUART1Output(COM_TYPE_UBX, 500); // Use native API
|
||||
assert(ok);
|
||||
ok = ublox.setNavigationFrequency(1, 500); // Produce 4x/sec to keep the amount of time we stall in getPVT low
|
||||
assert(ok);
|
||||
// ok = ublox.setAutoPVT(false); // Not implemented on NEO-6M
|
||||
// assert(ok);
|
||||
// ok = ublox.setDynamicModel(DYN_MODEL_BIKE); // probably PEDESTRIAN but just in case assume bike speeds
|
||||
// assert(ok);
|
||||
ok = ublox.powerSaveMode(); // use power save mode
|
||||
assert(ok);
|
||||
}
|
||||
ok = ublox.saveConfiguration(3000);
|
||||
assert(ok);
|
||||
} else {
|
||||
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
|
||||
// assume NEMA at 9600 baud.
|
||||
DEBUG_MSG("ERROR: No bidirectional GPS found, hoping that it still might work\n");
|
||||
|
||||
// tell lib, we are expecting the module to send PVT messages by itself to our Rx pin
|
||||
// you can set second parameter to "false" if you want to control the parsing and eviction of the data (need to call
|
||||
// checkUblox cyclically)
|
||||
ublox.assumeAutoPVT(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
void GPS::readFromRTC()
|
||||
void readFromRTC()
|
||||
{
|
||||
struct timeval tv; /* btw settimeofday() is helpfull here too*/
|
||||
|
||||
@ -102,7 +36,7 @@ void GPS::readFromRTC()
|
||||
}
|
||||
|
||||
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
|
||||
void GPS::perhapsSetRTC(const struct timeval *tv)
|
||||
void perhapsSetRTC(const struct timeval *tv)
|
||||
{
|
||||
if (!timeSetFromGPS) {
|
||||
timeSetFromGPS = true;
|
||||
@ -118,101 +52,12 @@ void GPS::perhapsSetRTC(const struct timeval *tv)
|
||||
|
||||
#include <time.h>
|
||||
|
||||
uint32_t GPS::getTime()
|
||||
uint32_t getTime()
|
||||
{
|
||||
return ((millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
|
||||
}
|
||||
|
||||
uint32_t GPS::getValidTime()
|
||||
uint32_t getValidTime()
|
||||
{
|
||||
return timeSetFromGPS ? getTime() : 0;
|
||||
}
|
||||
|
||||
/// Returns true if we think the board can enter deep or light sleep now (we might be trying to get a GPS lock)
|
||||
bool GPS::canSleep()
|
||||
{
|
||||
return true; // we leave GPS on during sleep now, so sleep is okay !wantNewLocation;
|
||||
}
|
||||
|
||||
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
|
||||
void GPS::prepareSleep()
|
||||
{
|
||||
if (isConnected)
|
||||
ublox.powerOff();
|
||||
}
|
||||
|
||||
void GPS::doTask()
|
||||
{
|
||||
uint8_t fixtype = 3; // If we are only using the RX pin, assume we have a 3d fix
|
||||
|
||||
if (isConnected) {
|
||||
// Consume all characters that have arrived
|
||||
|
||||
// getPVT automatically calls checkUblox
|
||||
ublox.checkUblox(); // See if new data is available. Process bytes as they come in.
|
||||
|
||||
// If we don't have a fix (a quick check), don't try waiting for a solution)
|
||||
// Hmmm my fix type reading returns zeros for fix, which doesn't seem correct, because it is still sptting out positions
|
||||
// turn off for now
|
||||
// fixtype = ublox.getFixType();
|
||||
DEBUG_MSG("fix type %d\n", fixtype);
|
||||
}
|
||||
|
||||
// DEBUG_MSG("sec %d\n", ublox.getSecond());
|
||||
// DEBUG_MSG("lat %d\n", ublox.getLatitude());
|
||||
|
||||
// any fix that has time
|
||||
if (!timeSetFromGPS && ublox.getT()) {
|
||||
struct timeval tv;
|
||||
|
||||
/* 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
|
||||
(midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
|
||||
*/
|
||||
struct tm t;
|
||||
t.tm_sec = ublox.getSecond();
|
||||
t.tm_min = ublox.getMinute();
|
||||
t.tm_hour = ublox.getHour();
|
||||
t.tm_mday = ublox.getDay();
|
||||
t.tm_mon = ublox.getMonth() - 1;
|
||||
t.tm_year = ublox.getYear() - 1900;
|
||||
t.tm_isdst = false;
|
||||
time_t res = mktime(&t);
|
||||
tv.tv_sec = res;
|
||||
tv.tv_usec = 0; // time.centisecond() * (10 / 1000);
|
||||
|
||||
DEBUG_MSG("Got time from GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
|
||||
if (t.tm_year < 0 || t.tm_year >= 300)
|
||||
DEBUG_MSG("Ignoring invalid GPS time\n");
|
||||
else
|
||||
perhapsSetRTC(&tv);
|
||||
}
|
||||
|
||||
if ((fixtype >= 3 && fixtype <= 4) && ublox.getP()) // rd fixes only
|
||||
{
|
||||
// we only notify if position has changed
|
||||
latitude = ublox.getLatitude();
|
||||
longitude = ublox.getLongitude();
|
||||
altitude = ublox.getAltitude() / 1000; // in mm convert to meters
|
||||
DEBUG_MSG("new gps pos lat=%f, lon=%f, alt=%d\n", latitude * 1e-7, longitude * 1e-7, altitude);
|
||||
|
||||
hasValidLocation = (latitude != 0) || (longitude != 0); // bogus lat lon is reported as 0,0
|
||||
if (hasValidLocation) {
|
||||
wantNewLocation = false;
|
||||
notifyObservers(NULL);
|
||||
// ublox.powerOff();
|
||||
}
|
||||
} else // we didn't get a location update, go back to sleep and hope the characters show up
|
||||
wantNewLocation = true;
|
||||
|
||||
// Once we have sent a location once we only poll the GPS rarely, otherwise check back every 1s until we have something over
|
||||
// the serial
|
||||
setPeriod(hasValidLocation && !wantNewLocation ? 30 * 1000 : 10 * 1000);
|
||||
}
|
||||
|
||||
void GPS::startLock()
|
||||
{
|
||||
DEBUG_MSG("Looking for GPS lock\n");
|
||||
wantNewLocation = true;
|
||||
setPeriod(1);
|
||||
}
|
||||
|
@ -2,54 +2,50 @@
|
||||
|
||||
#include "Observer.h"
|
||||
#include "PeriodicTask.h"
|
||||
#include "SparkFun_Ublox_Arduino_Library.h"
|
||||
#include "sys/time.h"
|
||||
|
||||
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
|
||||
void perhapsSetRTC(const struct timeval *tv);
|
||||
|
||||
/// Return time since 1970 in secs. Until we have a GPS lock 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
|
||||
uint32_t getValidTime();
|
||||
|
||||
void readFromRTC();
|
||||
|
||||
/**
|
||||
* A gps class that only reads from the GPS periodically (and FIXME - eventually keeps the gps powered down except when reading)
|
||||
*
|
||||
* When new data is available it will notify observers.
|
||||
*/
|
||||
class GPS : public PeriodicTask, public Observable<void *>
|
||||
class GPS : public Observable<void *>
|
||||
{
|
||||
SFE_UBLOX_GPS ublox;
|
||||
protected:
|
||||
bool hasValidLocation = false; // default to false, until we complete our first read
|
||||
|
||||
static HardwareSerial &_serial_gps;
|
||||
|
||||
public:
|
||||
uint32_t latitude, longitude; // as an int mult by 1e-7 to get value as double
|
||||
uint32_t altitude;
|
||||
bool isConnected; // Do we have a GPS we are talking to
|
||||
uint32_t latitude = 0, longitude = 0; // as an int mult by 1e-7 to get value as double
|
||||
uint32_t altitude = 0;
|
||||
bool isConnected = false; // Do we have a GPS we are talking to
|
||||
|
||||
GPS();
|
||||
virtual ~GPS() {}
|
||||
|
||||
/// Return time since 1970 in secs. Until we have a GPS lock 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
|
||||
uint32_t getValidTime();
|
||||
|
||||
void setup();
|
||||
|
||||
virtual void doTask();
|
||||
|
||||
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
|
||||
void perhapsSetRTC(const struct timeval *tv);
|
||||
|
||||
/// Returns true if we think the board can enter deep or light sleep now (we might be trying to get a GPS lock)
|
||||
bool canSleep();
|
||||
|
||||
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
|
||||
void prepareSleep();
|
||||
|
||||
/// Restart our lock attempt - try to get and broadcast a GPS reading ASAP
|
||||
void startLock();
|
||||
/**
|
||||
* Returns true if we succeeded
|
||||
*/
|
||||
virtual bool setup() = 0;
|
||||
|
||||
/// Returns ture if we have acquired GPS lock.
|
||||
bool hasLock() const { return hasValidLocation; }
|
||||
|
||||
private:
|
||||
void readFromRTC();
|
||||
|
||||
bool hasValidLocation = false; // default to false, until we complete our first read
|
||||
/**
|
||||
* Restart our lock attempt - try to get and broadcast a GPS reading ASAP
|
||||
* called after the CPU wakes from light-sleep state */
|
||||
virtual void startLock() {}
|
||||
};
|
||||
|
||||
extern GPS gps;
|
||||
extern GPS *gps;
|
||||
|
153
src/gps/UBloxGPS.cpp
Normal file
153
src/gps/UBloxGPS.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
#include "UBloxGPS.h"
|
||||
#include "sleep.h"
|
||||
#include <assert.h>
|
||||
|
||||
UBloxGPS::UBloxGPS() : PeriodicTask()
|
||||
{
|
||||
notifySleepObserver.observe(¬ifySleep);
|
||||
}
|
||||
|
||||
bool UBloxGPS::setup()
|
||||
{
|
||||
PeriodicTask::setup();
|
||||
|
||||
#ifdef GPS_RX_PIN
|
||||
_serial_gps.begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
|
||||
#else
|
||||
_serial_gps.begin(GPS_BAUDRATE);
|
||||
#endif
|
||||
// _serial_gps.setRxBufferSize(1024); // the default is 256
|
||||
// ublox.enableDebugging(Serial);
|
||||
|
||||
// note: the lib's implementation has the wrong docs for what the return val is
|
||||
// it is not a bool, it returns zero for success
|
||||
isConnected = ublox.begin(_serial_gps);
|
||||
|
||||
// try a second time, the ublox lib serial parsing is buggy?
|
||||
if (!isConnected)
|
||||
isConnected = ublox.begin(_serial_gps);
|
||||
|
||||
if (isConnected) {
|
||||
DEBUG_MSG("Connected to UBLOX GPS successfully\n");
|
||||
|
||||
bool factoryReset = false;
|
||||
bool ok;
|
||||
if (factoryReset) {
|
||||
// It is useful to force back into factory defaults (9600baud, NEMA to test the behavior of boards that don't have
|
||||
// GPS_TX connected)
|
||||
ublox.factoryReset();
|
||||
delay(2000);
|
||||
isConnected = ublox.begin(_serial_gps);
|
||||
DEBUG_MSG("Factory reset success=%d\n", isConnected);
|
||||
if (isConnected) {
|
||||
ublox.assumeAutoPVT(true, true); // Just parse NEMA for now
|
||||
}
|
||||
} else {
|
||||
ok = ublox.setUART1Output(COM_TYPE_UBX, 500); // Use native API
|
||||
assert(ok);
|
||||
ok = ublox.setNavigationFrequency(1, 500); // Produce 4x/sec to keep the amount of time we stall in getPVT low
|
||||
assert(ok);
|
||||
// ok = ublox.setAutoPVT(false); // Not implemented on NEO-6M
|
||||
// assert(ok);
|
||||
// ok = ublox.setDynamicModel(DYN_MODEL_BIKE); // probably PEDESTRIAN but just in case assume bike speeds
|
||||
// assert(ok);
|
||||
ok = ublox.powerSaveMode(); // use power save mode
|
||||
assert(ok);
|
||||
}
|
||||
ok = ublox.saveConfiguration(3000);
|
||||
assert(ok);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
|
||||
// assume NEMA at 9600 baud.
|
||||
DEBUG_MSG("ERROR: No bidirectional GPS found, hoping that it still might work\n");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
|
||||
int UBloxGPS::prepareSleep(void *unused)
|
||||
{
|
||||
if (isConnected)
|
||||
ublox.powerOff();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UBloxGPS::doTask()
|
||||
{
|
||||
uint8_t fixtype = 3; // If we are only using the RX pin, assume we have a 3d fix
|
||||
|
||||
if (isConnected) {
|
||||
// Consume all characters that have arrived
|
||||
|
||||
// getPVT automatically calls checkUblox
|
||||
ublox.checkUblox(); // See if new data is available. Process bytes as they come in.
|
||||
|
||||
// If we don't have a fix (a quick check), don't try waiting for a solution)
|
||||
// Hmmm my fix type reading returns zeros for fix, which doesn't seem correct, because it is still sptting out positions
|
||||
// turn off for now
|
||||
// fixtype = ublox.getFixType();
|
||||
DEBUG_MSG("fix type %d\n", fixtype);
|
||||
}
|
||||
|
||||
// DEBUG_MSG("sec %d\n", ublox.getSecond());
|
||||
// DEBUG_MSG("lat %d\n", ublox.getLatitude());
|
||||
|
||||
// any fix that has time
|
||||
if (ublox.getT()) {
|
||||
struct timeval tv;
|
||||
|
||||
/* 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
|
||||
(midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
|
||||
*/
|
||||
struct tm t;
|
||||
t.tm_sec = ublox.getSecond();
|
||||
t.tm_min = ublox.getMinute();
|
||||
t.tm_hour = ublox.getHour();
|
||||
t.tm_mday = ublox.getDay();
|
||||
t.tm_mon = ublox.getMonth() - 1;
|
||||
t.tm_year = ublox.getYear() - 1900;
|
||||
t.tm_isdst = false;
|
||||
time_t res = mktime(&t);
|
||||
tv.tv_sec = res;
|
||||
tv.tv_usec = 0; // time.centisecond() * (10 / 1000);
|
||||
|
||||
DEBUG_MSG("Got time from GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
|
||||
if (t.tm_year < 0 || t.tm_year >= 300)
|
||||
DEBUG_MSG("Ignoring invalid GPS time\n");
|
||||
else
|
||||
perhapsSetRTC(&tv);
|
||||
}
|
||||
|
||||
if ((fixtype >= 3 && fixtype <= 4) && ublox.getP()) // rd fixes only
|
||||
{
|
||||
// we only notify if position has changed
|
||||
latitude = ublox.getLatitude();
|
||||
longitude = ublox.getLongitude();
|
||||
altitude = ublox.getAltitude() / 1000; // in mm convert to meters
|
||||
DEBUG_MSG("new gps pos lat=%f, lon=%f, alt=%d\n", latitude * 1e-7, longitude * 1e-7, altitude);
|
||||
|
||||
hasValidLocation = (latitude != 0) || (longitude != 0); // bogus lat lon is reported as 0,0
|
||||
if (hasValidLocation) {
|
||||
wantNewLocation = false;
|
||||
notifyObservers(NULL);
|
||||
// ublox.powerOff();
|
||||
}
|
||||
} else // we didn't get a location update, go back to sleep and hope the characters show up
|
||||
wantNewLocation = true;
|
||||
|
||||
// Once we have sent a location once we only poll the GPS rarely, otherwise check back every 1s until we have something over
|
||||
// the serial
|
||||
setPeriod(hasValidLocation && !wantNewLocation ? 30 * 1000 : 10 * 1000);
|
||||
}
|
||||
|
||||
void UBloxGPS::startLock()
|
||||
{
|
||||
DEBUG_MSG("Looking for GPS lock\n");
|
||||
wantNewLocation = true;
|
||||
setPeriod(1);
|
||||
}
|
41
src/gps/UBloxGPS.h
Normal file
41
src/gps/UBloxGPS.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "GPS.h"
|
||||
#include "Observer.h"
|
||||
#include "PeriodicTask.h"
|
||||
#include "SparkFun_Ublox_Arduino_Library.h"
|
||||
|
||||
/**
|
||||
* A gps class that only reads from the GPS periodically (and FIXME - eventually keeps the gps powered down except when reading)
|
||||
*
|
||||
* When new data is available it will notify observers.
|
||||
*/
|
||||
class UBloxGPS : public GPS, public PeriodicTask
|
||||
{
|
||||
SFE_UBLOX_GPS ublox;
|
||||
|
||||
bool wantNewLocation = true;
|
||||
|
||||
CallbackObserver<UBloxGPS, void *> notifySleepObserver = CallbackObserver<UBloxGPS, void *>(this, &UBloxGPS::prepareSleep);
|
||||
|
||||
public:
|
||||
UBloxGPS();
|
||||
|
||||
/**
|
||||
* Returns true if we succeeded
|
||||
*/
|
||||
virtual bool setup();
|
||||
|
||||
virtual void doTask();
|
||||
|
||||
/**
|
||||
* Restart our lock attempt - try to get and broadcast a GPS reading ASAP
|
||||
* called after the CPU wakes from light-sleep state */
|
||||
virtual void startLock();
|
||||
|
||||
private:
|
||||
|
||||
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
|
||||
/// always returns 0 to indicate okay to sleep
|
||||
int prepareSleep(void *unused);
|
||||
};
|
13
src/main.cpp
13
src/main.cpp
@ -21,13 +21,13 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "GPS.h"
|
||||
#include "MeshRadio.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "Periodic.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "Router.h"
|
||||
#include "UBloxGPS.h"
|
||||
#include "configuration.h"
|
||||
#include "error.h"
|
||||
#include "power.h"
|
||||
@ -188,8 +188,13 @@ void setup()
|
||||
|
||||
screen.print("Started...\n");
|
||||
|
||||
// Init GPS
|
||||
gps.setup();
|
||||
readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time)
|
||||
|
||||
// Init GPS - first try ublox
|
||||
gps = new UBloxGPS();
|
||||
if (!gps->setup()) {
|
||||
// FIXME - fallback to NEMA
|
||||
}
|
||||
|
||||
service.init();
|
||||
|
||||
@ -306,7 +311,7 @@ void loop()
|
||||
screen.debug()->setChannelNameStatus(channelSettings.name);
|
||||
screen.debug()->setPowerStatus(powerStatus);
|
||||
// TODO(#4): use something based on hdop to show GPS "signal" strength.
|
||||
screen.debug()->setGPSStatus(gps.hasLock() ? "ok" : ":(");
|
||||
screen.debug()->setGPSStatus(gps->hasLock() ? "good" : "bad");
|
||||
|
||||
// No GPS lock yet, let the OS put the main CPU in low power mode for 100ms (or until another interrupt comes in)
|
||||
// i.e. don't just keep spinning in loop as fast as we can.
|
||||
|
@ -84,7 +84,7 @@ void MeshService::init()
|
||||
sendOwnerPeriod.setup();
|
||||
nodeDB.init();
|
||||
|
||||
gpsObserver.observe(&gps);
|
||||
gpsObserver.observe(gps);
|
||||
packetReceivedObserver.observe(&router.notifyPacketReceived);
|
||||
}
|
||||
|
||||
@ -153,7 +153,7 @@ void MeshService::handleIncomingPosition(const MeshPacket *mp)
|
||||
tv.tv_sec = secs;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
gps.perhapsSetRTC(&tv);
|
||||
perhapsSetRTC(&tv);
|
||||
}
|
||||
} else {
|
||||
DEBUG_MSG("Ignoring incoming packet - not a position\n");
|
||||
@ -165,7 +165,7 @@ 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)
|
||||
if (!gps->isConnected)
|
||||
handleIncomingPosition(mp);
|
||||
else {
|
||||
DEBUG_MSG("Ignoring incoming time, because we have a GPS\n");
|
||||
@ -234,8 +234,8 @@ void MeshService::handleToRadio(MeshPacket &p)
|
||||
if (p.id == 0)
|
||||
p.id = generatePacketId(); // If the phone didn't supply one, then pick one
|
||||
|
||||
p.rx_time = gps.getValidTime(); // Record the time the packet arrived from the phone
|
||||
// (so we update our nodedb for the local node)
|
||||
p.rx_time = getValidTime(); // Record the time the packet arrived from the phone
|
||||
// (so we update our nodedb for the local node)
|
||||
|
||||
// Send the packet into the mesh
|
||||
|
||||
@ -258,7 +258,7 @@ void MeshService::sendToMesh(MeshPacket *p)
|
||||
// nodes shouldn't trust it anyways) Note: for now, we allow a device with a local GPS to include the time, so that gpsless
|
||||
// devices can get time.
|
||||
if (p->has_payload && p->payload.has_position) {
|
||||
if (!gps.isConnected) {
|
||||
if (!gps->isConnected) {
|
||||
DEBUG_MSG("Stripping time %u from position send\n", p->payload.position.time);
|
||||
p->payload.position.time = 0;
|
||||
} else
|
||||
@ -286,7 +286,7 @@ MeshPacket *MeshService::allocForSending()
|
||||
p->from = nodeDB.getNodeNum();
|
||||
p->to = NODENUM_BROADCAST;
|
||||
p->id = generatePacketId();
|
||||
p->rx_time = gps.getValidTime(); // Just in case we process the packet locally - make sure it has a valid timestamp
|
||||
p->rx_time = getValidTime(); // Just in case we process the packet locally - make sure it has a valid timestamp
|
||||
|
||||
return p;
|
||||
}
|
||||
@ -315,7 +315,7 @@ void MeshService::sendOurPosition(NodeNum dest, bool wantReplies)
|
||||
p->payload.has_position = true;
|
||||
p->payload.position = node->position;
|
||||
p->payload.want_response = wantReplies;
|
||||
p->payload.position.time = gps.getValidTime(); // This nodedb timestamp might be stale, so update it if our clock is valid.
|
||||
p->payload.position.time = getValidTime(); // This nodedb timestamp might be stale, so update it if our clock is valid.
|
||||
sendToMesh(p);
|
||||
}
|
||||
|
||||
@ -329,12 +329,12 @@ int MeshService::onGPSChanged(void *unused)
|
||||
|
||||
Position &pos = p->payload.position;
|
||||
// !zero or !zero lat/long means valid
|
||||
if (gps.latitude != 0 || gps.longitude != 0) {
|
||||
if (gps.altitude != 0)
|
||||
pos.altitude = gps.altitude;
|
||||
pos.latitude_i = gps.latitude;
|
||||
pos.longitude_i = gps.longitude;
|
||||
pos.time = gps.getValidTime();
|
||||
if (gps->latitude != 0 || gps->longitude != 0) {
|
||||
if (gps->altitude != 0)
|
||||
pos.altitude = gps->altitude;
|
||||
pos.latitude_i = gps->latitude;
|
||||
pos.longitude_i = gps->longitude;
|
||||
pos.time = getValidTime();
|
||||
}
|
||||
|
||||
// We limit our GPS broadcasts to a max rate
|
||||
|
@ -246,7 +246,7 @@ const NodeInfo *NodeDB::readNextInfo()
|
||||
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
|
||||
uint32_t sinceLastSeen(const NodeInfo *n)
|
||||
{
|
||||
uint32_t now = gps.getTime();
|
||||
uint32_t now = getTime();
|
||||
|
||||
uint32_t last_seen = n->position.time;
|
||||
int delta = (int)(now - last_seen);
|
||||
|
@ -68,7 +68,7 @@ void Router::handleReceived(MeshPacket *p)
|
||||
{
|
||||
// FIXME, this class shouldn't EVER need to know about the GPS, move getValidTime() into a non gps dependent function
|
||||
// Also, we should set the time from the ISR and it should have msec level resolution
|
||||
p->rx_time = gps.getValidTime(); // store the arrival timestamp for the phone
|
||||
p->rx_time = getValidTime(); // store the arrival timestamp for the phone
|
||||
|
||||
DEBUG_MSG("Notifying observers of received packet fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
|
||||
notifyPacketReceived.notifyObservers(p);
|
||||
|
@ -29,6 +29,7 @@ extern AXP20X_Class axp;
|
||||
Observable<void *> preflightSleep;
|
||||
|
||||
/// Called to tell observers we are now entering sleep and you should prepare. Must return 0
|
||||
/// notifySleep will be called for light or deep sleep, notifyDeepSleep is only called for deep sleep
|
||||
Observable<void *> notifySleep, notifyDeepSleep;
|
||||
|
||||
// deep sleep support
|
||||
@ -125,12 +126,6 @@ static bool doPreflightSleep()
|
||||
/// Tell devices we are going to sleep and wait for them to handle things
|
||||
static void waitEnterSleep()
|
||||
{
|
||||
/*
|
||||
former hardwired code - now moved into notifySleep callbacks:
|
||||
// Put radio in sleep mode (will still draw power but only 0.2uA)
|
||||
service.radio.radioIf.sleep();
|
||||
*/
|
||||
|
||||
uint32_t now = millis();
|
||||
while (!doPreflightSleep()) {
|
||||
delay(100); // Kinda yucky - wait until radio says say we can shutdown (finished in process sends/receives)
|
||||
@ -144,7 +139,6 @@ static void waitEnterSleep()
|
||||
// Code that still needs to be moved into notifyObservers
|
||||
Serial.flush(); // send all our characters before we stop cpu clock
|
||||
setBluetoothEnable(false); // has to be off before calling light sleep
|
||||
gps.prepareSleep(); // abandon in-process parsing
|
||||
|
||||
notifySleep.notifyObservers(NULL);
|
||||
}
|
||||
@ -157,6 +151,7 @@ void doDeepSleep(uint64_t msecToWake)
|
||||
// not using wifi yet, but once we are this is needed to shutoff the radio hw
|
||||
// esp_wifi_stop();
|
||||
waitEnterSleep();
|
||||
notifySleep.notifyObservers(NULL); // also tell the regular sleep handlers
|
||||
notifyDeepSleep.notifyObservers(NULL);
|
||||
|
||||
screen.setOn(false); // datasheet says this will draw only 10ua
|
||||
|
Loading…
Reference in New Issue
Block a user