Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of MODGPS by
GPS.cpp
00001 /* 00002 Copyright (c) 2010 Andy Kirkham 00003 00004 Permission is hereby granted, free of charge, to any person obtaining a copy 00005 of this software and associated documentation files (the "Software"), to deal 00006 in the Software without restriction, including without limitation the rights 00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 copies of the Software, and to permit persons to whom the Software is 00009 furnished to do so, subject to the following conditions: 00010 00011 The above copyright notice and this permission notice shall be included in 00012 all copies or substantial portions of the Software. 00013 00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 THE SOFTWARE. 00021 */ 00022 00023 #include "GPS.h" 00024 00025 GPS::GPS(PinName tx, PinName rx, const char *name) 00026 : RawSerial(tx, rx) 00027 , _ppsInUse(false) 00028 , _pps(NULL) 00029 , _second100(new Ticker) 00030 , _lastByte(0) 00031 , _gga(NULL) 00032 , _rmc(NULL) 00033 , _vtg(NULL) 00034 , _ukn(NULL) 00035 , _nmeaOnUart0(false) 00036 { 00037 attach(callback(this, &GPS::rx_irq)); 00038 _second100->attach_us(callback(this, &GPS::ticktock), GPS_TICKTOCK); 00039 } 00040 00041 void GPS::ppsAttach(PinName irq, ppsEdgeType type) { 00042 if (_pps != NULL) 00043 delete _pps; 00044 _pps = new InterruptIn(irq); 00045 if (type == ppsRise ) 00046 _pps->rise(callback(this, &GPS::pps_irq)); 00047 else 00048 _pps->fall(callback(this, &GPS::pps_irq)); 00049 _ppsInUse = true; 00050 } 00051 00052 void GPS::ppsUnattach() { 00053 if (_pps != NULL) 00054 delete _pps; 00055 _ppsInUse = false; 00056 } 00057 00058 double GPS::latitude() { 00059 double a, b; 00060 do { 00061 a = thePlace.lat; b = thePlace.lat; 00062 } while (a != b); 00063 return a; 00064 } 00065 00066 double GPS::longitude() { 00067 double a, b; 00068 do { 00069 a = thePlace.lon; b = thePlace.lon; 00070 } while (a != b); 00071 return a; 00072 } 00073 00074 double GPS::altitude() { 00075 double a, b; 00076 do { 00077 a = thePlace.alt; b = thePlace.alt; 00078 } while (a != b); 00079 return a; 00080 } 00081 00082 GPS_Geodetic * GPS::geodetic(GPS_Geodetic *q) { 00083 GPS_Geodetic a; 00084 00085 if (q == NULL) 00086 q = new GPS_Geodetic; 00087 00088 do { 00089 memcpy(&a, &thePlace, sizeof(GPS_Geodetic)); 00090 memcpy(q, &thePlace, sizeof(GPS_Geodetic)); 00091 } 00092 while (memcmp(&a, q, sizeof(GPS_Geodetic)) != 0); 00093 00094 return q; 00095 } 00096 00097 GPS_VTG * GPS::vtg(GPS_VTG *q) { 00098 GPS_VTG a; 00099 00100 if (q == NULL) 00101 q = new GPS_VTG; 00102 00103 do { 00104 memcpy(&a, &theVTG, sizeof(GPS_VTG)); 00105 memcpy(q, &theVTG, sizeof(GPS_VTG)); 00106 } 00107 while (memcmp(&a, q, sizeof(GPS_VTG)) != 0); 00108 00109 return q; 00110 } 00111 00112 void GPS::ticktock() { 00113 // Increment the time structure by 1/100th of a second. 00114 ++theTime; 00115 00116 // Test the serial queue. 00117 if (process_required) { 00118 char *s = buffer[active_buffer == 0 ? 1 : 0]; 00119 if (!strncmp(s, "$GPRMC", 6)) { 00120 if (_rmc) { 00121 int i; 00122 for(i = 0; s[i] != '\n'; i++) 00123 _rmc[i] = s[i]; 00124 _rmc[i++] = '\n'; _rmc[i] = '\0'; 00125 } 00126 theTime.nmea_rmc(s); 00127 if (cb_rmc) 00128 cb_rmc.call(); 00129 if (!_ppsInUse) 00130 theTime.fractionalReset(); 00131 } 00132 else if (!strncmp(s, "$GPGGA", 6)) { 00133 if (_gga) { 00134 int i; 00135 for(i = 0; s[i] != '\n'; i++) 00136 _gga[i] = s[i]; 00137 _gga[i++] = '\n'; _gga[i] = '\0'; 00138 } 00139 thePlace.nmea_gga(s); 00140 if (cb_gga) 00141 cb_gga.call(); 00142 } 00143 else if (!strncmp(s, "$GPVTG", 6)) { 00144 if (_vtg) { 00145 int i; 00146 for(i = 0; s[i] != '\n'; i++) 00147 _vtg[i] = s[i]; 00148 _vtg[i++] = '\n'; _vtg[i] = '\0'; 00149 } 00150 theVTG.nmea_vtg(s); 00151 if (cb_vtg) 00152 cb_vtg.call(); 00153 } 00154 else { 00155 if (_ukn) { 00156 int i; 00157 for(i = 0; s[i] != '\n'; i++) 00158 _ukn[i] = s[i]; 00159 _ukn[i++] = '\n'; _ukn[i] = '\0'; 00160 if (cb_ukn) 00161 cb_ukn.call(); 00162 } 00163 } 00164 process_required = false; 00165 } 00166 00167 // If we have a valid GPS time then, once per minute, set the RTC. 00168 if (theTime.status == 'A' && theTime.second == 0 && theTime.tenths == 0 && theTime.hundreths == 0) { 00169 // set_time() is defined in rtc_time.h 00170 // http://mbed.org/projects/libraries/svn/mbed/trunk/rtc_time.h 00171 set_time(theTime.to_C_tm()); 00172 } 00173 00174 } 00175 00176 void GPS::pps_irq() { 00177 theTime.fractionalReset(); 00178 theTime++; // Increment the time/date by one second. 00179 if (cb_pps) 00180 cb_pps.call(); 00181 } 00182 00183 void GPS::rx_irq() { 00184 char c; 00185 while(readable()) { 00186 c = static_cast<char>(getc()); 00187 00188 // strtok workaround. 00189 // Found that ,, together (which some NMEA sentences 00190 // contain for a null/empty field) confuses strtok() 00191 // function. Solution:- Push a "zero" into the string 00192 // for missing/empty fields. 00193 if (c == ',' && _lastByte == ',') { 00194 buffer[active_buffer][rx_buffer_in] = '0'; 00195 if (++rx_buffer_in >= GPS_BUFFER_LEN) rx_buffer_in = 0; 00196 } 00197 00198 // Debugging/dumping data. 00199 // if (_nmeaOnUart0) LPC_UART0->RBR = c; 00200 00201 // Put the byte into the string. 00202 buffer[active_buffer][rx_buffer_in] = c; 00203 if (++rx_buffer_in >= GPS_BUFFER_LEN) rx_buffer_in = 0; 00204 00205 // Save for next time an irq occurs. See strtok() above. 00206 _lastByte = c; 00207 00208 // If end of NMEA sentence flag for processing. 00209 if (c == '\n') { 00210 active_buffer = active_buffer == 0 ? 1 : 0; 00211 process_required = true; 00212 rx_buffer_in = 0; 00213 } 00214 } 00215 }
Generated on Thu Jul 14 2022 07:39:12 by
1.7.2
