Allows for a GPS module to be connected to a serial port and exposes an easy to use API to get the GPS data.

Fork of MODGPS by Andy K

Committer:
xanter
Date:
Sat Sep 29 20:31:31 2018 +0000
Revision:
7:049436bc2225
Parent:
6:64771e31464e
Fixed compiler errors/warnings; Removed hardcode for LPC17xx

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AjK 0:db98027c0bbb 1 /*
AjK 0:db98027c0bbb 2 Copyright (c) 2010 Andy Kirkham
AjK 0:db98027c0bbb 3
AjK 0:db98027c0bbb 4 Permission is hereby granted, free of charge, to any person obtaining a copy
AjK 0:db98027c0bbb 5 of this software and associated documentation files (the "Software"), to deal
AjK 0:db98027c0bbb 6 in the Software without restriction, including without limitation the rights
AjK 0:db98027c0bbb 7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
AjK 0:db98027c0bbb 8 copies of the Software, and to permit persons to whom the Software is
AjK 0:db98027c0bbb 9 furnished to do so, subject to the following conditions:
AjK 0:db98027c0bbb 10
AjK 0:db98027c0bbb 11 The above copyright notice and this permission notice shall be included in
AjK 0:db98027c0bbb 12 all copies or substantial portions of the Software.
AjK 0:db98027c0bbb 13
AjK 0:db98027c0bbb 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
AjK 0:db98027c0bbb 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
AjK 0:db98027c0bbb 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AjK 0:db98027c0bbb 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
AjK 0:db98027c0bbb 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
AjK 0:db98027c0bbb 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
AjK 0:db98027c0bbb 20 THE SOFTWARE.
AjK 0:db98027c0bbb 21 */
AjK 0:db98027c0bbb 22
AjK 0:db98027c0bbb 23 #include "GPS.h"
AjK 0:db98027c0bbb 24
xanter 7:049436bc2225 25 GPS::GPS(PinName tx, PinName rx, const char *name)
xanter 7:049436bc2225 26 : RawSerial(tx, rx)
xanter 7:049436bc2225 27 , _ppsInUse(false)
xanter 7:049436bc2225 28 , _pps(NULL)
xanter 7:049436bc2225 29 , _second100(new Ticker)
xanter 7:049436bc2225 30 , _lastByte(0)
xanter 7:049436bc2225 31 , _gga(NULL)
xanter 7:049436bc2225 32 , _rmc(NULL)
xanter 7:049436bc2225 33 , _vtg(NULL)
xanter 7:049436bc2225 34 , _ukn(NULL)
xanter 7:049436bc2225 35 , _nmeaOnUart0(false)
AjK 0:db98027c0bbb 36 {
xanter 7:049436bc2225 37 attach(callback(this, &GPS::rx_irq));
xanter 7:049436bc2225 38 _second100->attach_us(callback(this, &GPS::ticktock), GPS_TICKTOCK);
AjK 0:db98027c0bbb 39 }
AjK 0:db98027c0bbb 40
xanter 7:049436bc2225 41 void GPS::ppsAttach(PinName irq, ppsEdgeType type) {
xanter 7:049436bc2225 42 if (_pps != NULL)
xanter 7:049436bc2225 43 delete _pps;
AjK 0:db98027c0bbb 44 _pps = new InterruptIn(irq);
xanter 7:049436bc2225 45 if (type == ppsRise)
xanter 7:049436bc2225 46 _pps->rise(callback(this, &GPS::pps_irq));
xanter 7:049436bc2225 47 else
xanter 7:049436bc2225 48 _pps->fall(callback(this, &GPS::pps_irq));
AjK 0:db98027c0bbb 49 _ppsInUse = true;
AjK 0:db98027c0bbb 50 }
AjK 0:db98027c0bbb 51
xanter 7:049436bc2225 52 void GPS::ppsUnattach() {
xanter 7:049436bc2225 53 if (_pps != NULL)
xanter 7:049436bc2225 54 delete _pps;
AjK 0:db98027c0bbb 55 _ppsInUse = false;
AjK 0:db98027c0bbb 56 }
AjK 0:db98027c0bbb 57
xanter 7:049436bc2225 58 double GPS::latitude() {
AjK 0:db98027c0bbb 59 double a, b;
xanter 7:049436bc2225 60 do {
xanter 7:049436bc2225 61 a = thePlace.lat; b = thePlace.lat;
xanter 7:049436bc2225 62 } while (a != b);
AjK 0:db98027c0bbb 63 return a;
AjK 0:db98027c0bbb 64 }
AjK 0:db98027c0bbb 65
xanter 7:049436bc2225 66 double GPS::longitude() {
AjK 0:db98027c0bbb 67 double a, b;
xanter 7:049436bc2225 68 do {
xanter 7:049436bc2225 69 a = thePlace.lon; b = thePlace.lon;
xanter 7:049436bc2225 70 } while (a != b);
AjK 0:db98027c0bbb 71 return a;
AjK 0:db98027c0bbb 72 }
AjK 0:db98027c0bbb 73
xanter 7:049436bc2225 74 double GPS::altitude() {
AjK 0:db98027c0bbb 75 double a, b;
xanter 7:049436bc2225 76 do {
xanter 7:049436bc2225 77 a = thePlace.alt; b = thePlace.alt;
xanter 7:049436bc2225 78 } while (a != b);
AjK 0:db98027c0bbb 79 return a;
AjK 0:db98027c0bbb 80 }
AjK 0:db98027c0bbb 81
xanter 7:049436bc2225 82 GPS_Geodetic * GPS::geodetic(GPS_Geodetic *q) {
AjK 3:28a1b60b0f37 83 GPS_Geodetic a;
AjK 0:db98027c0bbb 84
xanter 7:049436bc2225 85 if (q == NULL)
xanter 7:049436bc2225 86 q = new GPS_Geodetic;
AjK 0:db98027c0bbb 87
AjK 0:db98027c0bbb 88 do {
AjK 0:db98027c0bbb 89 memcpy(&a, &thePlace, sizeof(GPS_Geodetic));
AjK 3:28a1b60b0f37 90 memcpy(q, &thePlace, sizeof(GPS_Geodetic));
AjK 0:db98027c0bbb 91 }
AjK 3:28a1b60b0f37 92 while (memcmp(&a, q, sizeof(GPS_Geodetic)) != 0);
AjK 0:db98027c0bbb 93
AjK 0:db98027c0bbb 94 return q;
AjK 0:db98027c0bbb 95 }
AjK 0:db98027c0bbb 96
xanter 7:049436bc2225 97 GPS_VTG * GPS::vtg(GPS_VTG *q) {
AjK 3:28a1b60b0f37 98 GPS_VTG a;
AjK 2:8aa059e7d8b1 99
xanter 7:049436bc2225 100 if (q == NULL)
xanter 7:049436bc2225 101 q = new GPS_VTG;
AjK 2:8aa059e7d8b1 102
AjK 2:8aa059e7d8b1 103 do {
AjK 2:8aa059e7d8b1 104 memcpy(&a, &theVTG, sizeof(GPS_VTG));
AjK 3:28a1b60b0f37 105 memcpy(q, &theVTG, sizeof(GPS_VTG));
AjK 2:8aa059e7d8b1 106 }
AjK 3:28a1b60b0f37 107 while (memcmp(&a, q, sizeof(GPS_VTG)) != 0);
AjK 2:8aa059e7d8b1 108
AjK 2:8aa059e7d8b1 109 return q;
AjK 2:8aa059e7d8b1 110 }
AjK 2:8aa059e7d8b1 111
xanter 7:049436bc2225 112 void GPS::ticktock() {
AjK 0:db98027c0bbb 113 // Increment the time structure by 1/100th of a second.
AjK 0:db98027c0bbb 114 ++theTime;
AjK 0:db98027c0bbb 115
AjK 0:db98027c0bbb 116 // Test the serial queue.
AjK 0:db98027c0bbb 117 if (process_required) {
AjK 0:db98027c0bbb 118 char *s = buffer[active_buffer == 0 ? 1 : 0];
AjK 0:db98027c0bbb 119 if (!strncmp(s, "$GPRMC", 6)) {
AjK 6:64771e31464e 120 if (_rmc) {
xanter 7:049436bc2225 121 int i;
xanter 7:049436bc2225 122 for(i = 0; s[i] != '\n'; i++)
AjK 6:64771e31464e 123 _rmc[i] = s[i];
AjK 6:64771e31464e 124 _rmc[i++] = '\n'; _rmc[i] = '\0';
AjK 6:64771e31464e 125 }
AjK 0:db98027c0bbb 126 theTime.nmea_rmc(s);
xanter 7:049436bc2225 127 if (cb_rmc)
xanter 7:049436bc2225 128 cb_rmc.call();
xanter 7:049436bc2225 129 if (!_ppsInUse)
xanter 7:049436bc2225 130 theTime.fractionalReset();
AjK 0:db98027c0bbb 131 }
AjK 0:db98027c0bbb 132 else if (!strncmp(s, "$GPGGA", 6)) {
AjK 6:64771e31464e 133 if (_gga) {
xanter 7:049436bc2225 134 int i;
xanter 7:049436bc2225 135 for(i = 0; s[i] != '\n'; i++)
AjK 6:64771e31464e 136 _gga[i] = s[i];
AjK 6:64771e31464e 137 _gga[i++] = '\n'; _gga[i] = '\0';
AjK 6:64771e31464e 138 }
xanter 7:049436bc2225 139 thePlace.nmea_gga(s);
xanter 7:049436bc2225 140 if (cb_gga)
xanter 7:049436bc2225 141 cb_gga.call();
AjK 0:db98027c0bbb 142 }
AjK 2:8aa059e7d8b1 143 else if (!strncmp(s, "$GPVTG", 6)) {
AjK 6:64771e31464e 144 if (_vtg) {
xanter 7:049436bc2225 145 int i;
xanter 7:049436bc2225 146 for(i = 0; s[i] != '\n'; i++)
AjK 6:64771e31464e 147 _vtg[i] = s[i];
AjK 6:64771e31464e 148 _vtg[i++] = '\n'; _vtg[i] = '\0';
AjK 6:64771e31464e 149 }
xanter 7:049436bc2225 150 theVTG.nmea_vtg(s);
xanter 7:049436bc2225 151 if (cb_vtg)
xanter 7:049436bc2225 152 cb_vtg.call();
AjK 2:8aa059e7d8b1 153 }
AjK 6:64771e31464e 154 else {
AjK 6:64771e31464e 155 if (_ukn) {
xanter 7:049436bc2225 156 int i;
xanter 7:049436bc2225 157 for(i = 0; s[i] != '\n'; i++)
AjK 6:64771e31464e 158 _ukn[i] = s[i];
AjK 6:64771e31464e 159 _ukn[i++] = '\n'; _ukn[i] = '\0';
xanter 7:049436bc2225 160 if (cb_ukn)
xanter 7:049436bc2225 161 cb_ukn.call();
AjK 6:64771e31464e 162 }
AjK 6:64771e31464e 163 }
AjK 0:db98027c0bbb 164 process_required = false;
AjK 0:db98027c0bbb 165 }
AjK 5:7f130f85d5a4 166
AjK 5:7f130f85d5a4 167 // If we have a valid GPS time then, once per minute, set the RTC.
AjK 5:7f130f85d5a4 168 if (theTime.status == 'A' && theTime.second == 0 && theTime.tenths == 0 && theTime.hundreths == 0) {
AjK 5:7f130f85d5a4 169 // set_time() is defined in rtc_time.h
AjK 5:7f130f85d5a4 170 // http://mbed.org/projects/libraries/svn/mbed/trunk/rtc_time.h
AjK 5:7f130f85d5a4 171 set_time(theTime.to_C_tm());
AjK 5:7f130f85d5a4 172 }
AjK 5:7f130f85d5a4 173
AjK 0:db98027c0bbb 174 }
AjK 0:db98027c0bbb 175
xanter 7:049436bc2225 176 void GPS::pps_irq() {
AjK 0:db98027c0bbb 177 theTime.fractionalReset();
AjK 0:db98027c0bbb 178 theTime++; // Increment the time/date by one second.
xanter 7:049436bc2225 179 if (cb_pps)
xanter 7:049436bc2225 180 cb_pps.call();
AjK 0:db98027c0bbb 181 }
AjK 2:8aa059e7d8b1 182
xanter 7:049436bc2225 183 void GPS::rx_irq() {
AjK 0:db98027c0bbb 184 char c;
xanter 7:049436bc2225 185 while(readable()) {
xanter 7:049436bc2225 186 c = static_cast<char>(getc());
xanter 7:049436bc2225 187
xanter 7:049436bc2225 188 // strtok workaround.
xanter 7:049436bc2225 189 // Found that ,, together (which some NMEA sentences
xanter 7:049436bc2225 190 // contain for a null/empty field) confuses strtok()
xanter 7:049436bc2225 191 // function. Solution:- Push a "zero" into the string
xanter 7:049436bc2225 192 // for missing/empty fields.
xanter 7:049436bc2225 193 if (c == ',' && _lastByte == ',') {
xanter 7:049436bc2225 194 buffer[active_buffer][rx_buffer_in] = '0';
AjK 3:28a1b60b0f37 195 if (++rx_buffer_in >= GPS_BUFFER_LEN) rx_buffer_in = 0;
AjK 0:db98027c0bbb 196 }
xanter 7:049436bc2225 197
xanter 7:049436bc2225 198 // Debugging/dumping data.
xanter 7:049436bc2225 199 // if (_nmeaOnUart0) LPC_UART0->RBR = c;
xanter 7:049436bc2225 200
xanter 7:049436bc2225 201 // Put the byte into the string.
xanter 7:049436bc2225 202 buffer[active_buffer][rx_buffer_in] = c;
xanter 7:049436bc2225 203 if (++rx_buffer_in >= GPS_BUFFER_LEN) rx_buffer_in = 0;
xanter 7:049436bc2225 204
xanter 7:049436bc2225 205 // Save for next time an irq occurs. See strtok() above.
xanter 7:049436bc2225 206 _lastByte = c;
xanter 7:049436bc2225 207
xanter 7:049436bc2225 208 // If end of NMEA sentence flag for processing.
xanter 7:049436bc2225 209 if (c == '\n') {
xanter 7:049436bc2225 210 active_buffer = active_buffer == 0 ? 1 : 0;
xanter 7:049436bc2225 211 process_required = true;
xanter 7:049436bc2225 212 rx_buffer_in = 0;
xanter 7:049436bc2225 213 }
AjK 0:db98027c0bbb 214 }
AjK 0:db98027c0bbb 215 }