A controller-neutral API for working with GPS devices.

Dependents:   CsrLocationDemo CsrLocationDemo

Committer:
rgrover1
Date:
Fri Nov 07 08:24:48 2014 +0000
Revision:
4:f35227b1f341
Parent:
1:c1122f8eec82
making the destructor for GPSProvider non-virtual; moving it to GPSProvider.cpp.; The destructor should forward control to the impl.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 0:792e9343fd39 1 /* mbed Microcontroller Library
rgrover1 0:792e9343fd39 2 * Copyright (c) 2006-2014 ARM Limited
rgrover1 0:792e9343fd39 3 *
rgrover1 0:792e9343fd39 4 * Licensed under the Apache License, Version 2.0 (the "License");
rgrover1 0:792e9343fd39 5 * you may not use this file except in compliance with the License.
rgrover1 0:792e9343fd39 6 * You may obtain a copy of the License at
rgrover1 0:792e9343fd39 7 *
rgrover1 0:792e9343fd39 8 * http://www.apache.org/licenses/LICENSE-2.0
rgrover1 0:792e9343fd39 9 *
rgrover1 0:792e9343fd39 10 * Unless required by applicable law or agreed to in writing, software
rgrover1 0:792e9343fd39 11 * distributed under the License is distributed on an "AS IS" BASIS,
rgrover1 0:792e9343fd39 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rgrover1 0:792e9343fd39 13 * See the License for the specific language governing permissions and
rgrover1 0:792e9343fd39 14 * limitations under the License.
rgrover1 0:792e9343fd39 15 */
rgrover1 0:792e9343fd39 16
rgrover1 0:792e9343fd39 17 #ifndef __GPS_PROVIDER_H__
rgrover1 0:792e9343fd39 18 #define __GPS_PROVIDER_H__
rgrover1 0:792e9343fd39 19
rgrover1 0:792e9343fd39 20 class GPSProviderImplBase; /* forward declaration */
rgrover1 0:792e9343fd39 21 extern GPSProviderImplBase *createGPSProviderInstance(void);
rgrover1 0:792e9343fd39 22
rgrover1 0:792e9343fd39 23 //
rgrover1 1:c1122f8eec82 24 // Here's a snippet showing how this API can be used. The handler gets invoked
rgrover1 1:c1122f8eec82 25 // from thread context--i.e. from the main application.
rgrover1 0:792e9343fd39 26 //
rgrover1 1:c1122f8eec82 27 // void handleGPSData(const LocationUpdateParams_t *newLocation) {
rgrover1 1:c1122f8eec82 28 // ...
rgrover1 0:792e9343fd39 29 // }
rgrover1 0:792e9343fd39 30 //
rgrover1 0:792e9343fd39 31 // GPSProvider gps;
rgrover1 0:792e9343fd39 32 //
rgrover1 0:792e9343fd39 33 // gps.setPowerMode(LOW_POWER);
rgrover1 0:792e9343fd39 34 // gps.onLocationUpdate(handleGPSData);
rgrover1 0:792e9343fd39 35 //
rgrover1 1:c1122f8eec82 36 // gps.reset();
rgrover1 0:792e9343fd39 37 // gps.start();
rgrover1 0:792e9343fd39 38 //
rgrover1 1:c1122f8eec82 39 // while (true) {
rgrover1 1:c1122f8eec82 40 // /* purely optional */
rgrover1 1:c1122f8eec82 41 // static bool printedDeviceInfo = false;
rgrover1 1:c1122f8eec82 42 // if (!printedDeviceInfo && gps.haveDeviceInfo()) {
rgrover1 1:c1122f8eec82 43 // printf("%s", gps.getDeviceInfo());
rgrover1 1:c1122f8eec82 44 // printedDeviceInfo = true;
rgrover1 1:c1122f8eec82 45 // }
rgrover1 0:792e9343fd39 46 //
rgrover1 1:c1122f8eec82 47 // /* Main message processing activity; location callbacks are called
rgrover1 1:c1122f8eec82 48 // * as a result of message processing. */
rgrover1 1:c1122f8eec82 49 // gps.process();
rgrover1 1:c1122f8eec82 50 // /* sleep(); */
rgrover1 0:792e9343fd39 51 //
rgrover1 1:c1122f8eec82 52 // if (/* at some point in the future */) {
rgrover1 1:c1122f8eec82 53 // break;
rgrover1 1:c1122f8eec82 54 // }
rgrover1 1:c1122f8eec82 55 // }
rgrover1 0:792e9343fd39 56 // gps.stop();
rgrover1 0:792e9343fd39 57 //
rgrover1 0:792e9343fd39 58
rgrover1 0:792e9343fd39 59 class GPSProvider {
rgrover1 0:792e9343fd39 60 public:
rgrover1 0:792e9343fd39 61 /** Power mode selection */
rgrover1 0:792e9343fd39 62 enum PowerMode_t {
rgrover1 1:c1122f8eec82 63 POWER_FULL, /**< full-power mode typically results in high-accuracy location data updated at 1Hz. */
rgrover1 1:c1122f8eec82 64 POWER_LOW, /**< low-power mode involves longer periods of hibernation in between location updates. */
rgrover1 0:792e9343fd39 65 };
rgrover1 0:792e9343fd39 66
rgrover1 0:792e9343fd39 67 /**
rgrover1 0:792e9343fd39 68 * GPS time starts from UTC 01/06/1980(MM/DD/YYYY) and includes 2 fields:
rgrover1 0:792e9343fd39 69 * week and tow. For a given GPS time, week is the passed week number since
rgrover1 0:792e9343fd39 70 * the GPS start time, and tow(time of week) is the passed seconds since the
rgrover1 0:792e9343fd39 71 * last Sunday. For example, a given UTC time [10/30/3014
rgrover1 0:792e9343fd39 72 * 01:10:00](MM/DD/YYYY HH:MM:SS) can be converted into GPS time [1816,
rgrover1 0:792e9343fd39 73 * 4200](week, seconds).
rgrover1 0:792e9343fd39 74 *
rgrover1 0:792e9343fd39 75 * GPS time can be used as a quite accurate time once position is fixed.
rgrover1 0:792e9343fd39 76 */
rgrover1 0:792e9343fd39 77 struct GPSTime_t {
rgrover1 0:792e9343fd39 78 uint16_t gps_week;
rgrover1 0:792e9343fd39 79 uint32_t tow; /* time of week (in seconds) */
rgrover1 0:792e9343fd39 80 };
rgrover1 0:792e9343fd39 81
rgrover1 0:792e9343fd39 82 typedef float LocationType_t;
rgrover1 0:792e9343fd39 83 typedef float Altitude_t;
rgrover1 0:792e9343fd39 84 struct LocationUpdateParams_t {
rgrover1 0:792e9343fd39 85 uint32_t version; /* Layout-version for the following structure;
rgrover1 0:792e9343fd39 86 * this is to accommodate changes over time. */
rgrover1 1:c1122f8eec82 87 bool valid; /* Does this update contain a valid location. */
rgrover1 0:792e9343fd39 88 LocationType_t lat;
rgrover1 0:792e9343fd39 89 LocationType_t lon;
rgrover1 0:792e9343fd39 90 Altitude_t altitude;
rgrover1 0:792e9343fd39 91
rgrover1 1:c1122f8eec82 92 unsigned numGPSSVs; /* num GPS Satellites */
rgrover1 1:c1122f8eec82 93 unsigned numGLOSVs; /* num GLONASS Satellites */
rgrover1 1:c1122f8eec82 94
rgrover1 0:792e9343fd39 95 union {
rgrover1 0:792e9343fd39 96 GPSTime_t gpsTime;
rgrover1 0:792e9343fd39 97 float utcTime;
rgrover1 0:792e9343fd39 98 } u;
rgrover1 0:792e9343fd39 99 };
rgrover1 0:792e9343fd39 100
rgrover1 0:792e9343fd39 101 public:
rgrover1 0:792e9343fd39 102 /**
rgrover1 0:792e9343fd39 103 * Set the operating mode for power. Typically this allows the user to
rgrover1 0:792e9343fd39 104 * choose between various low-power modes. Entering low-power modes often
rgrover1 0:792e9343fd39 105 * results in a trade-off between accuracy and power consumption.
rgrover1 0:792e9343fd39 106 *
rgrover1 0:792e9343fd39 107 * The new mode takes effect upon calling start().
rgrover1 0:792e9343fd39 108 *
rgrover1 0:792e9343fd39 109 * @param power The new power mode.
rgrover1 0:792e9343fd39 110 * @return true if the update was successful.
rgrover1 0:792e9343fd39 111 */
rgrover1 0:792e9343fd39 112 bool setPowerMode(PowerMode_t power);
rgrover1 0:792e9343fd39 113
rgrover1 0:792e9343fd39 114 /**
rgrover1 0:792e9343fd39 115 * HW reset to get location chip into hibernation mode, but in readiness for
rgrover1 0:792e9343fd39 116 * starting operation. The GPS controller emerges from hibernation when
rgrover1 0:792e9343fd39 117 * start() is called.
rgrover1 0:792e9343fd39 118 *
rgrover1 0:792e9343fd39 119 * The typical initialization sequence is:
rgrover1 0:792e9343fd39 120 * reset();
rgrover1 0:792e9343fd39 121 * start(); // and thereafter receive location-update callbacks.
rgrover1 0:792e9343fd39 122 */
rgrover1 0:792e9343fd39 123 void reset(void);
rgrover1 0:792e9343fd39 124
rgrover1 0:792e9343fd39 125 /**
rgrover1 0:792e9343fd39 126 * Start the GPS operation, taking into account the operation mode set
rgrover1 0:792e9343fd39 127 * previously. Following this call, the user may expect to receive location
rgrover1 0:792e9343fd39 128 * notifications in interrupt context if a handler has previously been set.
rgrover1 0:792e9343fd39 129 *
rgrover1 0:792e9343fd39 130 * @note: calling start repeatedly doesn't hurt.
rgrover1 0:792e9343fd39 131 */
rgrover1 0:792e9343fd39 132 void start(void);
rgrover1 0:792e9343fd39 133
rgrover1 0:792e9343fd39 134 /**
rgrover1 0:792e9343fd39 135 * Stop active operation of the GPS; and put it to hibernation.
rgrover1 0:792e9343fd39 136 *
rgrover1 0:792e9343fd39 137 * @note: You don't need to call reset() afterwards to enter hibernation.
rgrover1 0:792e9343fd39 138 * @note: Calling stop() repeatedly doesn't hurt.
rgrover1 0:792e9343fd39 139 */
rgrover1 0:792e9343fd39 140 void stop(void);
rgrover1 0:792e9343fd39 141
rgrover1 0:792e9343fd39 142 /**
rgrover1 1:c1122f8eec82 143 * Process location data from chip and update location and satellite
rgrover1 1:c1122f8eec82 144 * information. This API is supposed to be called repeatedly from the
rgrover1 1:c1122f8eec82 145 * application in thread mode to process incoming messages as they are
rgrover1 1:c1122f8eec82 146 * received from the GPS controller. Arriving data is first appended to
rgrover1 1:c1122f8eec82 147 * something like a circular buffer by interrupts, and then parsed as
rgrover1 1:c1122f8eec82 148 * messages in thread mode.
rgrover1 1:c1122f8eec82 149 *
rgrover1 1:c1122f8eec82 150 * The application typically enters a loop calling process() after
rgrover1 1:c1122f8eec82 151 * initializing the GPS controller with start(). process() returns
rgrover1 1:c1122f8eec82 152 * immediately if there is no work to be done, but it must get invoked
rgrover1 1:c1122f8eec82 153 * frequently in order to keep pace with arriving data.
rgrover1 1:c1122f8eec82 154 *
rgrover1 1:c1122f8eec82 155 * Mbed's sleep() may be usefully thrown into the application's process()
rgrover1 1:c1122f8eec82 156 * loop to save power--sleep() has the effect of putting the processor to
rgrover1 1:c1122f8eec82 157 * sleep while waiting for an event (such as an interrupt). As always, some
rgrover1 1:c1122f8eec82 158 * care must be taken in employing sleep(), because there is a small
rgrover1 1:c1122f8eec82 159 * synchronization window where an interrupt may arrive and pend data which
rgrover1 1:c1122f8eec82 160 * doesn't get processed (as illustrated below).
rgrover1 1:c1122f8eec82 161 *
rgrover1 1:c1122f8eec82 162 * while (true) {
rgrover1 1:c1122f8eec82 163 * process();
rgrover1 1:c1122f8eec82 164 * <-- interrupt arrives now and appends new data
rgrover1 1:c1122f8eec82 165 * sleep(); // but then we go to sleep without processing it.
rgrover1 1:c1122f8eec82 166 * }
rgrover1 1:c1122f8eec82 167 *
rgrover1 1:c1122f8eec82 168 * There is a way around it: if sleep() boils down to the use of ARM's WFE
rgrover1 1:c1122f8eec82 169 * instruction (as opposed to WFI), then its safe from the above-mentioned
rgrover1 1:c1122f8eec82 170 * synchronization window.
rgrover1 1:c1122f8eec82 171 */
rgrover1 1:c1122f8eec82 172 void process(void);
rgrover1 1:c1122f8eec82 173
rgrover1 1:c1122f8eec82 174 /**
rgrover1 0:792e9343fd39 175 * @return true if the initialization process has received enough
rgrover1 0:792e9343fd39 176 * information to determine the hardware's version/device-info.
rgrover1 0:792e9343fd39 177 */
rgrover1 1:c1122f8eec82 178 bool haveDeviceInfo(void) const;
rgrover1 0:792e9343fd39 179
rgrover1 0:792e9343fd39 180 /**
rgrover1 0:792e9343fd39 181 * Fetch the device information string. This is expected to contain the
rgrover1 0:792e9343fd39 182 * version number or any other device identifier.
rgrover1 0:792e9343fd39 183 */
rgrover1 1:c1122f8eec82 184 const char *getDeviceInfo(void) const;
rgrover1 0:792e9343fd39 185
rgrover1 0:792e9343fd39 186 /**
rgrover1 0:792e9343fd39 187 * This is a wildcard API for sending controller specific commands. Use of
rgrover1 0:792e9343fd39 188 * this API will make programs non-portable, but then there may arise a
rgrover1 0:792e9343fd39 189 * genuine need to access special functionality.
rgrover1 0:792e9343fd39 190 *
rgrover1 0:792e9343fd39 191 * @param command A controller specific command.
rgrover1 0:792e9343fd39 192 * @param arg Argument to the command; interpreted according to the command.
rgrover1 0:792e9343fd39 193 * @return any return from the command.
rgrover1 0:792e9343fd39 194 */
rgrover1 0:792e9343fd39 195 uint32_t ioctl(uint32_t command, void *arg);
rgrover1 0:792e9343fd39 196
rgrover1 0:792e9343fd39 197 /**
rgrover1 0:792e9343fd39 198 * @return true if we've obtained at least one valid location since last
rgrover1 0:792e9343fd39 199 * calling start().
rgrover1 0:792e9343fd39 200 *
rgrover1 0:792e9343fd39 201 * @Note: This is cleared after reset().
rgrover1 0:792e9343fd39 202 */
rgrover1 1:c1122f8eec82 203 bool locationAvailable(void) const;
rgrover1 0:792e9343fd39 204
rgrover1 0:792e9343fd39 205 /**
rgrover1 0:792e9343fd39 206 * @return the last valid location if there is any; else NULL.
rgrover1 0:792e9343fd39 207 */
rgrover1 1:c1122f8eec82 208 const LocationUpdateParams_t *getLastLocation(void) const;
rgrover1 0:792e9343fd39 209
rgrover1 0:792e9343fd39 210 /**
rgrover1 0:792e9343fd39 211 * Type declaration for a callback to be invoked from interrupt context upon
rgrover1 0:792e9343fd39 212 * receiving new location data.
rgrover1 0:792e9343fd39 213 *
rgrover1 0:792e9343fd39 214 * @Note: Please note that the handler gets invoked from interrupt context.
rgrover1 0:792e9343fd39 215 * Users *should not* do any long running or blocking operations in the
rgrover1 0:792e9343fd39 216 * handler.
rgrover1 0:792e9343fd39 217 */
rgrover1 0:792e9343fd39 218 typedef void (* LocationUpdateCallback_t)(const LocationUpdateParams_t *params);
rgrover1 0:792e9343fd39 219
rgrover1 0:792e9343fd39 220 /**
rgrover1 0:792e9343fd39 221 * Setup the locationUpdate callback.
rgrover1 0:792e9343fd39 222 *
rgrover1 0:792e9343fd39 223 * @Note: Please note that the handler gets invoked from interrupt context.
rgrover1 0:792e9343fd39 224 * Users *should not* do any long running or blocking operations in the
rgrover1 0:792e9343fd39 225 * handler.
rgrover1 0:792e9343fd39 226 */
rgrover1 0:792e9343fd39 227 void onLocationUpdate(LocationUpdateCallback_t callback);
rgrover1 0:792e9343fd39 228
rgrover1 1:c1122f8eec82 229 /**
rgrover1 1:c1122f8eec82 230 * In low-power operation, the GPS controller may be expected to hibernate
rgrover1 1:c1122f8eec82 231 * for extended periods and location updates may be infrequent. It should
rgrover1 1:c1122f8eec82 232 * then be possible for an application to demand location data when needed.
rgrover1 1:c1122f8eec82 233 *
rgrover1 1:c1122f8eec82 234 * This calls results in a locationCallback if there is a useful location to
rgrover1 1:c1122f8eec82 235 * report.
rgrover1 1:c1122f8eec82 236 */
rgrover1 1:c1122f8eec82 237 void lpmGetImmediateLocation(void);
rgrover1 1:c1122f8eec82 238
rgrover1 0:792e9343fd39 239 public:
rgrover1 0:792e9343fd39 240 /**
rgrover1 0:792e9343fd39 241 * Default constructor.
rgrover1 0:792e9343fd39 242 */
rgrover1 1:c1122f8eec82 243 GPSProvider() : impl(createGPSProviderInstance()) {
rgrover1 0:792e9343fd39 244 /* empty */
rgrover1 0:792e9343fd39 245 }
rgrover1 0:792e9343fd39 246
rgrover1 4:f35227b1f341 247 ~GPSProvider();
rgrover1 0:792e9343fd39 248
rgrover1 0:792e9343fd39 249 private:
rgrover1 0:792e9343fd39 250 /**
rgrover1 0:792e9343fd39 251 * We use 'composition' to combine a driver-implementation object to the
rgrover1 0:792e9343fd39 252 * GPSProvider interface. The implementation object will come to life
rgrover1 0:792e9343fd39 253 * through the createGPSProviderInstance(), which must be defined by the
rgrover1 0:792e9343fd39 254 * driver library. The mechanics of the implementation are to be hidden
rgrover1 0:792e9343fd39 255 * behind the abstract interface provided by GPSProvider.
rgrover1 0:792e9343fd39 256 */
rgrover1 4:f35227b1f341 257 GPSProviderImplBase *impl;
rgrover1 0:792e9343fd39 258
rgrover1 0:792e9343fd39 259 /* disallow copy constructor and assignment operators */
rgrover1 0:792e9343fd39 260 private:
rgrover1 0:792e9343fd39 261 GPSProvider(const GPSProvider&);
rgrover1 0:792e9343fd39 262 GPSProvider & operator= (const GPSProvider&);
rgrover1 0:792e9343fd39 263 };
rgrover1 0:792e9343fd39 264
rgrover1 0:792e9343fd39 265 #endif /*__GPS_PROVIDER_H__*/