A controller-neutral API for working with GPS devices.

Dependents:   CsrLocationDemo CsrLocationDemo

Committer:
zhjcpi
Date:
Wed Nov 19 01:34:29 2014 +0000
Revision:
7:820997be26cb
Parent:
6:8afa9ac0da9b
add comments for utcTime field.

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;
zhjcpi 7:820997be26cb 79 uint32_t tow; /* time of week (in millisecond) */
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
zhjcpi 7:820997be26cb 95 GPSTime_t gpsTime; /* gps time */
zhjcpi 7:820997be26cb 96 uint64_t utcTime; /* UTC time in millisecond */
rgrover1 0:792e9343fd39 97 };
rgrover1 0:792e9343fd39 98
rgrover1 0:792e9343fd39 99 public:
rgrover1 0:792e9343fd39 100 /**
rgrover1 0:792e9343fd39 101 * Set the operating mode for power. Typically this allows the user to
rgrover1 0:792e9343fd39 102 * choose between various low-power modes. Entering low-power modes often
rgrover1 0:792e9343fd39 103 * results in a trade-off between accuracy and power consumption.
rgrover1 0:792e9343fd39 104 *
rgrover1 0:792e9343fd39 105 * The new mode takes effect upon calling start().
rgrover1 0:792e9343fd39 106 *
rgrover1 0:792e9343fd39 107 * @param power The new power mode.
rgrover1 0:792e9343fd39 108 * @return true if the update was successful.
rgrover1 0:792e9343fd39 109 */
rgrover1 0:792e9343fd39 110 bool setPowerMode(PowerMode_t power);
rgrover1 0:792e9343fd39 111
rgrover1 0:792e9343fd39 112 /**
rgrover1 0:792e9343fd39 113 * HW reset to get location chip into hibernation mode, but in readiness for
rgrover1 0:792e9343fd39 114 * starting operation. The GPS controller emerges from hibernation when
rgrover1 0:792e9343fd39 115 * start() is called.
rgrover1 0:792e9343fd39 116 *
rgrover1 0:792e9343fd39 117 * The typical initialization sequence is:
rgrover1 0:792e9343fd39 118 * reset();
rgrover1 0:792e9343fd39 119 * start(); // and thereafter receive location-update callbacks.
rgrover1 0:792e9343fd39 120 */
rgrover1 0:792e9343fd39 121 void reset(void);
rgrover1 0:792e9343fd39 122
rgrover1 0:792e9343fd39 123 /**
rgrover1 0:792e9343fd39 124 * Start the GPS operation, taking into account the operation mode set
rgrover1 0:792e9343fd39 125 * previously. Following this call, the user may expect to receive location
rgrover1 0:792e9343fd39 126 * notifications in interrupt context if a handler has previously been set.
rgrover1 0:792e9343fd39 127 *
rgrover1 0:792e9343fd39 128 * @note: calling start repeatedly doesn't hurt.
rgrover1 0:792e9343fd39 129 */
rgrover1 0:792e9343fd39 130 void start(void);
rgrover1 0:792e9343fd39 131
rgrover1 0:792e9343fd39 132 /**
rgrover1 0:792e9343fd39 133 * Stop active operation of the GPS; and put it to hibernation.
rgrover1 0:792e9343fd39 134 *
rgrover1 0:792e9343fd39 135 * @note: You don't need to call reset() afterwards to enter hibernation.
rgrover1 0:792e9343fd39 136 * @note: Calling stop() repeatedly doesn't hurt.
rgrover1 0:792e9343fd39 137 */
rgrover1 0:792e9343fd39 138 void stop(void);
rgrover1 0:792e9343fd39 139
rgrover1 0:792e9343fd39 140 /**
rgrover1 1:c1122f8eec82 141 * Process location data from chip and update location and satellite
rgrover1 1:c1122f8eec82 142 * information. This API is supposed to be called repeatedly from the
rgrover1 1:c1122f8eec82 143 * application in thread mode to process incoming messages as they are
rgrover1 1:c1122f8eec82 144 * received from the GPS controller. Arriving data is first appended to
rgrover1 1:c1122f8eec82 145 * something like a circular buffer by interrupts, and then parsed as
rgrover1 1:c1122f8eec82 146 * messages in thread mode.
rgrover1 1:c1122f8eec82 147 *
rgrover1 1:c1122f8eec82 148 * The application typically enters a loop calling process() after
rgrover1 1:c1122f8eec82 149 * initializing the GPS controller with start(). process() returns
rgrover1 1:c1122f8eec82 150 * immediately if there is no work to be done, but it must get invoked
rgrover1 1:c1122f8eec82 151 * frequently in order to keep pace with arriving data.
rgrover1 1:c1122f8eec82 152 *
rgrover1 1:c1122f8eec82 153 * Mbed's sleep() may be usefully thrown into the application's process()
rgrover1 1:c1122f8eec82 154 * loop to save power--sleep() has the effect of putting the processor to
rgrover1 1:c1122f8eec82 155 * sleep while waiting for an event (such as an interrupt). As always, some
rgrover1 1:c1122f8eec82 156 * care must be taken in employing sleep(), because there is a small
rgrover1 1:c1122f8eec82 157 * synchronization window where an interrupt may arrive and pend data which
rgrover1 1:c1122f8eec82 158 * doesn't get processed (as illustrated below).
rgrover1 1:c1122f8eec82 159 *
rgrover1 1:c1122f8eec82 160 * while (true) {
rgrover1 1:c1122f8eec82 161 * process();
rgrover1 1:c1122f8eec82 162 * <-- interrupt arrives now and appends new data
rgrover1 1:c1122f8eec82 163 * sleep(); // but then we go to sleep without processing it.
rgrover1 1:c1122f8eec82 164 * }
rgrover1 1:c1122f8eec82 165 *
rgrover1 1:c1122f8eec82 166 * There is a way around it: if sleep() boils down to the use of ARM's WFE
rgrover1 1:c1122f8eec82 167 * instruction (as opposed to WFI), then its safe from the above-mentioned
rgrover1 1:c1122f8eec82 168 * synchronization window.
rgrover1 1:c1122f8eec82 169 */
rgrover1 1:c1122f8eec82 170 void process(void);
rgrover1 1:c1122f8eec82 171
rgrover1 1:c1122f8eec82 172 /**
rgrover1 0:792e9343fd39 173 * @return true if the initialization process has received enough
rgrover1 0:792e9343fd39 174 * information to determine the hardware's version/device-info.
rgrover1 0:792e9343fd39 175 */
rgrover1 1:c1122f8eec82 176 bool haveDeviceInfo(void) const;
rgrover1 0:792e9343fd39 177
rgrover1 0:792e9343fd39 178 /**
rgrover1 0:792e9343fd39 179 * Fetch the device information string. This is expected to contain the
rgrover1 0:792e9343fd39 180 * version number or any other device identifier.
rgrover1 0:792e9343fd39 181 */
rgrover1 1:c1122f8eec82 182 const char *getDeviceInfo(void) const;
rgrover1 0:792e9343fd39 183
rgrover1 0:792e9343fd39 184 /**
rgrover1 0:792e9343fd39 185 * This is a wildcard API for sending controller specific commands. Use of
rgrover1 0:792e9343fd39 186 * this API will make programs non-portable, but then there may arise a
rgrover1 0:792e9343fd39 187 * genuine need to access special functionality.
rgrover1 0:792e9343fd39 188 *
rgrover1 0:792e9343fd39 189 * @param command A controller specific command.
rgrover1 0:792e9343fd39 190 * @param arg Argument to the command; interpreted according to the command.
rgrover1 0:792e9343fd39 191 * @return any return from the command.
rgrover1 0:792e9343fd39 192 */
rgrover1 0:792e9343fd39 193 uint32_t ioctl(uint32_t command, void *arg);
rgrover1 0:792e9343fd39 194
rgrover1 0:792e9343fd39 195 /**
rgrover1 0:792e9343fd39 196 * @return true if we've obtained at least one valid location since last
rgrover1 0:792e9343fd39 197 * calling start().
rgrover1 0:792e9343fd39 198 *
rgrover1 0:792e9343fd39 199 * @Note: This is cleared after reset().
rgrover1 0:792e9343fd39 200 */
rgrover1 1:c1122f8eec82 201 bool locationAvailable(void) const;
rgrover1 0:792e9343fd39 202
rgrover1 0:792e9343fd39 203 /**
rgrover1 0:792e9343fd39 204 * @return the last valid location if there is any; else NULL.
rgrover1 0:792e9343fd39 205 */
rgrover1 1:c1122f8eec82 206 const LocationUpdateParams_t *getLastLocation(void) const;
rgrover1 0:792e9343fd39 207
rgrover1 0:792e9343fd39 208 /**
rgrover1 0:792e9343fd39 209 * Type declaration for a callback to be invoked from interrupt context upon
rgrover1 0:792e9343fd39 210 * receiving new location data.
rgrover1 0:792e9343fd39 211 *
rgrover1 0:792e9343fd39 212 * @Note: Please note that the handler gets invoked from interrupt context.
rgrover1 0:792e9343fd39 213 * Users *should not* do any long running or blocking operations in the
rgrover1 0:792e9343fd39 214 * handler.
rgrover1 0:792e9343fd39 215 */
rgrover1 0:792e9343fd39 216 typedef void (* LocationUpdateCallback_t)(const LocationUpdateParams_t *params);
rgrover1 0:792e9343fd39 217
rgrover1 0:792e9343fd39 218 /**
rgrover1 0:792e9343fd39 219 * Setup the locationUpdate callback.
rgrover1 0:792e9343fd39 220 *
rgrover1 0:792e9343fd39 221 * @Note: Please note that the handler gets invoked from interrupt context.
rgrover1 0:792e9343fd39 222 * Users *should not* do any long running or blocking operations in the
rgrover1 0:792e9343fd39 223 * handler.
rgrover1 0:792e9343fd39 224 */
rgrover1 0:792e9343fd39 225 void onLocationUpdate(LocationUpdateCallback_t callback);
rgrover1 0:792e9343fd39 226
rgrover1 1:c1122f8eec82 227 /**
rgrover1 1:c1122f8eec82 228 * In low-power operation, the GPS controller may be expected to hibernate
rgrover1 1:c1122f8eec82 229 * for extended periods and location updates may be infrequent. It should
rgrover1 1:c1122f8eec82 230 * then be possible for an application to demand location data when needed.
rgrover1 1:c1122f8eec82 231 *
rgrover1 1:c1122f8eec82 232 * This calls results in a locationCallback if there is a useful location to
rgrover1 1:c1122f8eec82 233 * report.
rgrover1 1:c1122f8eec82 234 */
rgrover1 1:c1122f8eec82 235 void lpmGetImmediateLocation(void);
rgrover1 1:c1122f8eec82 236
rgrover1 0:792e9343fd39 237 public:
rgrover1 0:792e9343fd39 238 /**
rgrover1 0:792e9343fd39 239 * Default constructor.
rgrover1 0:792e9343fd39 240 */
rgrover1 1:c1122f8eec82 241 GPSProvider() : impl(createGPSProviderInstance()) {
rgrover1 0:792e9343fd39 242 /* empty */
rgrover1 0:792e9343fd39 243 }
rgrover1 0:792e9343fd39 244
rgrover1 0:792e9343fd39 245 virtual ~GPSProvider() {
rgrover1 0:792e9343fd39 246 stop();
rgrover1 0:792e9343fd39 247 }
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 0:792e9343fd39 257 GPSProviderImplBase *const 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__*/