An extension of original API for working with GPS devices.
Diff: GPSProvider.h
- Revision:
- 1:c1122f8eec82
- Parent:
- 0:792e9343fd39
- Child:
- 4:f35227b1f341
- Child:
- 5:900c3ab6c090
--- a/GPSProvider.h Thu Oct 30 14:42:27 2014 +0000 +++ b/GPSProvider.h Fri Oct 31 13:34:59 2014 +0000 @@ -21,14 +21,11 @@ extern GPSProviderImplBase *createGPSProviderInstance(void); // -// Here's a snippet showing how this API can be used. Please note that this is -// an asynchronous API--users can setup an asynchronous handler to receive -// location updates. The handler gets invoked from interrupt context. Users -// *should not* do any long running or blocking operations in the handler. +// Here's a snippet showing how this API can be used. The handler gets invoked +// from thread context--i.e. from the main application. // -// void handleGPSData(const LocationUpdateParams_t *newData) { -// /* Do something with the location update; but please don't make any -// * blocking calls or invoke long-running operations. */ +// void handleGPSData(const LocationUpdateParams_t *newLocation) { +// ... // } // // GPSProvider gps; @@ -36,30 +33,35 @@ // gps.setPowerMode(LOW_POWER); // gps.onLocationUpdate(handleGPSData); // -// gps.reset(); // implicitly calls powerOn(). +// gps.reset(); // gps.start(); // -// wait(/* some duration to allow controller to stabilize */); -// if (gps.haveDeviceInfo()) { -// printf("%s", gps.getDeviceInfo()); -// } +// while (true) { +// /* purely optional */ +// static bool printedDeviceInfo = false; +// if (!printedDeviceInfo && gps.haveDeviceInfo()) { +// printf("%s", gps.getDeviceInfo()); +// printedDeviceInfo = true; +// } // -// ... -// /* Period where the gps locationHandler gets invoked asynchronously. */ -// ... +// /* Main message processing activity; location callbacks are called +// * as a result of message processing. */ +// gps.process(); +// /* sleep(); */ // -// /* at some point in the future, either the following.. */ +// if (/* at some point in the future */) { +// break; +// } +// } // gps.stop(); -// gps.powerOff(); -// /* or simply destroy the gps object to achieve the same. */ // class GPSProvider { public: /** Power mode selection */ enum PowerMode_t { - POWER_FULL, - POWER_LOW, + POWER_FULL, /**< full-power mode typically results in high-accuracy location data updated at 1Hz. */ + POWER_LOW, /**< low-power mode involves longer periods of hibernation in between location updates. */ }; /** @@ -82,10 +84,14 @@ struct LocationUpdateParams_t { uint32_t version; /* Layout-version for the following structure; * this is to accommodate changes over time. */ + bool valid; /* Does this update contain a valid location. */ LocationType_t lat; LocationType_t lon; Altitude_t altitude; + unsigned numGPSSVs; /* num GPS Satellites */ + unsigned numGLOSVs; /* num GLONASS Satellites */ + union { GPSTime_t gpsTime; float utcTime; @@ -134,20 +140,48 @@ void stop(void); /** + * Process location data from chip and update location and satellite + * information. This API is supposed to be called repeatedly from the + * application in thread mode to process incoming messages as they are + * received from the GPS controller. Arriving data is first appended to + * something like a circular buffer by interrupts, and then parsed as + * messages in thread mode. + * + * The application typically enters a loop calling process() after + * initializing the GPS controller with start(). process() returns + * immediately if there is no work to be done, but it must get invoked + * frequently in order to keep pace with arriving data. + * + * Mbed's sleep() may be usefully thrown into the application's process() + * loop to save power--sleep() has the effect of putting the processor to + * sleep while waiting for an event (such as an interrupt). As always, some + * care must be taken in employing sleep(), because there is a small + * synchronization window where an interrupt may arrive and pend data which + * doesn't get processed (as illustrated below). + * + * while (true) { + * process(); + * <-- interrupt arrives now and appends new data + * sleep(); // but then we go to sleep without processing it. + * } + * + * There is a way around it: if sleep() boils down to the use of ARM's WFE + * instruction (as opposed to WFI), then its safe from the above-mentioned + * synchronization window. + */ + void process(void); + + /** * @return true if the initialization process has received enough * information to determine the hardware's version/device-info. */ - bool haveDeviceInfo(void) const { - return discoveredDeviceInfo; - } + bool haveDeviceInfo(void) const; /** * Fetch the device information string. This is expected to contain the * version number or any other device identifier. */ - const char *getDeviceInfo(void) const { - return deviceInfo; - } + const char *getDeviceInfo(void) const; /** * This is a wildcard API for sending controller specific commands. Use of @@ -166,16 +200,12 @@ * * @Note: This is cleared after reset(). */ - bool locationAvailable(void) const { - return haveValidLocation; - } + bool locationAvailable(void) const; /** * @return the last valid location if there is any; else NULL. */ - const LocationUpdateParams_t *getLastLocation(void) const { - return haveValidLocation ? &lastLocation : NULL; - } + const LocationUpdateParams_t *getLastLocation(void) const; /** * Type declaration for a callback to be invoked from interrupt context upon @@ -196,17 +226,21 @@ */ void onLocationUpdate(LocationUpdateCallback_t callback); + /** + * In low-power operation, the GPS controller may be expected to hibernate + * for extended periods and location updates may be infrequent. It should + * then be possible for an application to demand location data when needed. + * + * This calls results in a locationCallback if there is a useful location to + * report. + */ + void lpmGetImmediateLocation(void); + public: /** * Default constructor. */ - GPSProvider() : - impl(createGPSProviderInstance()), - havePoweredOn(false), - discoveredDeviceInfo(false), - haveValidLocation(false), - deviceInfo(NULL), - updateCallback(NULL) { + GPSProvider() : impl(createGPSProviderInstance()) { /* empty */ } @@ -224,15 +258,6 @@ */ GPSProviderImplBase *const impl; -private: - bool havePoweredOn; - bool discoveredDeviceInfo; - bool haveValidLocation; - - const char *deviceInfo; - LocationUpdateParams_t lastLocation; - LocationUpdateCallback_t *updateCallback; - /* disallow copy constructor and assignment operators */ private: GPSProvider(const GPSProvider&);