Files
firmware/src/gps/GPS.h

149 lines
4.7 KiB
C
Raw Normal View History

2020-02-06 07:39:21 -08:00
#pragma once
2020-07-10 11:43:14 -07:00
#include "GPSStatus.h"
#include "Observer.h"
2020-10-10 09:57:57 +08:00
#include "concurrency/OSThread.h"
2020-05-04 11:15:05 -07:00
2020-06-20 18:59:41 -07:00
// Generate a string representation of DOP
const char *getDOPString(uint32_t dop);
2020-02-06 07:39:21 -08:00
/**
* A gps class that only reads from the GPS periodically (and FIXME - eventually keeps the gps powered down except when reading)
*
2020-02-06 07:39:21 -08:00
* When new data is available it will notify observers.
*/
2020-10-10 09:57:57 +08:00
class GPS : private concurrency::OSThread
2020-02-06 07:39:21 -08:00
{
2020-10-01 09:11:54 -07:00
private:
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastWhileActiveMsec = 0;
2020-10-01 09:11:54 -07:00
2020-05-04 11:15:05 -07:00
bool hasValidLocation = false; // default to false, until we complete our first read
2020-02-19 08:17:28 -08:00
2020-10-01 09:11:54 -07:00
bool isAwake = false; // true if we want a location right now
bool wakeAllowed = true; // false if gps must be forced to sleep regardless of what time it is
2020-09-28 17:04:19 -07:00
bool shouldPublish = false; // If we've changed GPS state, this will force a publish the next loop()
bool hasGPS = false; // Do we have a GPS we are talking to
uint8_t numSatellites = 0;
2020-10-01 09:11:54 -07:00
CallbackObserver<GPS, void *> notifySleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareSleep);
2020-10-30 17:05:32 +08:00
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
2020-10-01 09:11:54 -07:00
2020-07-10 11:43:14 -07:00
public:
/** If !NULL we will use this serial port to construct our GPS */
static HardwareSerial *_serial_gps;
2020-02-19 10:53:09 -08:00
2020-07-10 11:43:14 -07:00
/** If !0 we will attempt to connect to the GPS over I2C */
static uint8_t i2cAddress;
2020-05-04 11:21:24 -07:00
int32_t latitude = 0, longitude = 0; // as an int mult by 1e-7 to get value as double
int32_t altitude = 0;
2020-07-10 11:43:14 -07:00
uint32_t dop = 0; // Diminution of position; PDOP where possible (UBlox), HDOP otherwise (TinyGPS) in 10^2 units (needs
// scaling before use)
uint32_t heading = 0; // Heading of motion, in degrees * 10^-5
2020-10-10 09:57:57 +08:00
GPS() : concurrency::OSThread("GPS") {}
2020-10-01 09:11:54 -07:00
virtual ~GPS() {} // FIXME, we really should unregister our sleep observer
/** We will notify this observable anytime GPS state has changed meaningfully */
2020-06-28 18:17:52 -07:00
Observable<const meshtastic::GPSStatus *> newStatus;
2020-05-04 11:15:05 -07:00
/**
* Returns true if we succeeded
*/
2020-10-01 09:11:54 -07:00
virtual bool setup();
2020-05-04 17:39:57 -07:00
/// Returns ture if we have acquired GPS lock.
bool hasLock() const { return hasValidLocation; }
/// Return true if we are connected to a GPS
bool isConnected() const { return hasGPS; }
2020-09-28 17:04:19 -07:00
/**
2020-10-01 09:11:54 -07:00
* Restart our lock attempt - try to get and broadcast a GPS reading ASAP
* called after the CPU wakes from light-sleep state
*
* Or set to false, to disallow any sort of waking
* */
void forceWake(bool on);
protected:
/// Do gps chipset specific init, return true for success
2020-10-25 17:07:54 +08:00
virtual bool setupGPS();
2020-10-01 09:11:54 -07:00
/// If possible force the GPS into sleep/low power mode
2020-10-13 13:59:06 +08:00
virtual void sleep();
2020-10-01 09:11:54 -07:00
/// wake the GPS into normal operation mode
2020-10-13 13:59:06 +08:00
virtual void wake();
2020-10-01 09:11:54 -07:00
/** Subclasses should look for serial rx characters here and feed it to their GPS parser
*
* Return true if we received a valid message from the GPS
2020-09-28 17:04:19 -07:00
*/
2020-10-01 09:11:54 -07:00
virtual bool whileIdle() = 0;
2020-09-28 17:04:19 -07:00
/** Idle processing while GPS is looking for lock, called once per secondish */
2020-10-05 14:43:44 +08:00
virtual void whileActive() {}
2020-05-04 11:15:05 -07:00
/**
2020-10-01 09:11:54 -07:00
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
*
* @return true if we've acquired a time
*/
virtual bool lookForTime() = 0;
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
*
* @return true if we've acquired a new location
*/
virtual bool lookForLocation() = 0;
2020-09-28 17:04:19 -07:00
/// Record that we have a GPS
void setConnected();
void setNumSatellites(uint8_t n);
2020-10-01 09:11:54 -07:00
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);
2020-09-28 17:04:19 -07:00
2020-10-30 17:05:32 +08:00
/// Prepare the GPS for the cpu entering deep sleep, expect to be gone for at least 100s of msecs
/// always returns 0 to indicate okay to sleep
int prepareDeepSleep(void *unused);
2020-10-01 09:11:54 -07:00
/**
* Switch the GPS into a mode where we are actively looking for a lock, or alternatively switch GPS into a low power mode
*
* calls sleep/wake
*/
void setAwake(bool on);
2020-10-05 14:43:44 +08:00
/** Get how long we should stay looking for each aquisition
*/
uint32_t getWakeTime() const;
/** Get how long we should sleep between aqusition attempts
*/
uint32_t getSleepTime() const;
GpsOperation getGpsOp() const;
2020-10-05 14:43:44 +08:00
/**
* Tell users we have new GPS readings
*/
void publishUpdate();
2020-10-10 09:57:57 +08:00
virtual int32_t runOnce();
2020-02-06 07:39:21 -08:00
};
2020-05-04 11:15:05 -07:00
extern GPS *gps;