SDP Code
Fork of MODGPS by
Embed:
(wiki syntax)
Show/hide line numbers
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) : Serial(tx, rx, name) 00026 { 00027 _nmeaOnUart0 = false; 00028 00029 _lastByte = 0; 00030 00031 _gga = (char *)NULL; 00032 00033 _rmc = (char *)NULL; 00034 00035 _vtg = (char *)NULL; 00036 00037 switch(_serial.index) { 00038 case 1: _base = LPC_UART1; break; 00039 case 2: _base = LPC_UART2; break; 00040 case 3: _base = LPC_UART3; break; 00041 default : _base = NULL; break; 00042 } 00043 00044 _pps = NULL; 00045 _ppsInUse = false; 00046 00047 if (_base != NULL) attach(this, &GPS::rx_irq); 00048 00049 _second100 = new Ticker; 00050 _second100->attach_us(this, &GPS::ticktock, GPS_TICKTOCK); 00051 } 00052 00053 void 00054 GPS::ppsAttach(PinName irq, ppsEdgeType type) 00055 { 00056 if (_pps != NULL) delete(_pps); 00057 _pps = new InterruptIn(irq); 00058 if (type == ppsRise ) _pps->rise(this, &GPS::pps_irq); 00059 else _pps->fall(this, &GPS::pps_irq); 00060 _ppsInUse = true; 00061 } 00062 00063 void 00064 GPS::ppsUnattach(void) 00065 { 00066 if (_pps != NULL) delete(_pps); 00067 _ppsInUse = false; 00068 } 00069 00070 double 00071 GPS::latitude(void) 00072 { 00073 double a, b; 00074 do { a = thePlace.lat; b = thePlace.lat; } while (a != b); 00075 return a; 00076 } 00077 00078 double 00079 GPS::longitude(void) 00080 { 00081 double a, b; 00082 do { a = thePlace.lon; b = thePlace.lon; } while (a != b); 00083 return a; 00084 } 00085 00086 double 00087 GPS::altitude(void) 00088 { 00089 double a, b; 00090 do { a = thePlace.alt; b = thePlace.alt; } while (a != b); 00091 return a; 00092 } 00093 00094 GPS_Geodetic * 00095 GPS::geodetic(GPS_Geodetic *q) 00096 { 00097 GPS_Geodetic a; 00098 00099 if (q == NULL) q = new GPS_Geodetic; 00100 00101 do { 00102 memcpy(&a, &thePlace, sizeof(GPS_Geodetic)); 00103 memcpy(q, &thePlace, sizeof(GPS_Geodetic)); 00104 } 00105 while (memcmp(&a, q, sizeof(GPS_Geodetic)) != 0); 00106 00107 return q; 00108 } 00109 00110 GPS_VTG * 00111 GPS::vtg(GPS_VTG *q) 00112 { 00113 GPS_VTG a; 00114 00115 if (q == NULL) q = new GPS_VTG; 00116 00117 do { 00118 memcpy(&a, &theVTG, sizeof(GPS_VTG)); 00119 memcpy(q, &theVTG, sizeof(GPS_VTG)); 00120 } 00121 while (memcmp(&a, q, sizeof(GPS_VTG)) != 0); 00122 00123 return q; 00124 } 00125 00126 void 00127 GPS::ticktock(void) 00128 { 00129 int i; 00130 00131 // Increment the time structure by 1/100th of a second. 00132 ++theTime; 00133 00134 // Test the serial queue. 00135 if (process_required) { 00136 char *s = buffer[active_buffer == 0 ? 1 : 0]; 00137 if (!strncmp(s, "$GPRMC", 6)) { 00138 if (_rmc) { 00139 for(i = 0; s[i] != '\n'; i++) { 00140 _rmc[i] = s[i]; 00141 } 00142 _rmc[i++] = '\n'; _rmc[i] = '\0'; 00143 } 00144 theTime.nmea_rmc(s); 00145 cb_rmc.call(); 00146 if (!_ppsInUse) theTime.fractionalReset(); 00147 } 00148 else if (!strncmp(s, "$GPGGA", 6)) { 00149 if (_gga) { 00150 for(int i = 0; s[i] != '\n'; i++) { 00151 _gga[i] = s[i]; 00152 } 00153 _gga[i++] = '\n'; _gga[i] = '\0'; 00154 } 00155 thePlace.nmea_gga(s); 00156 cb_gga.call(); 00157 } 00158 else if (!strncmp(s, "$GPVTG", 6)) { 00159 if (_vtg) { 00160 for(int i = 0; s[i] != '\n'; i++) { 00161 _vtg[i] = s[i]; 00162 } 00163 _vtg[i++] = '\n'; _vtg[i] = '\0'; 00164 } 00165 theVTG.nmea_vtg(s); 00166 cb_vtg.call(); 00167 } 00168 else { 00169 if (_ukn) { 00170 for(int i = 0; s[i] != '\n'; i++) { 00171 _ukn[i] = s[i]; 00172 } 00173 _ukn[i++] = '\n'; _ukn[i] = '\0'; 00174 cb_ukn.call(); 00175 } 00176 } 00177 process_required = false; 00178 } 00179 00180 // If we have a valid GPS time then, once per minute, set the RTC. 00181 if (theTime.status == 'A' && theTime.second == 0 && theTime.tenths == 0 && theTime.hundreths == 0) { 00182 // set_time() is defined in rtc_time.h 00183 // http://mbed.org/projects/libraries/svn/mbed/trunk/rtc_time.h 00184 set_time(theTime.to_C_tm()); 00185 } 00186 00187 } 00188 00189 void 00190 GPS::pps_irq(void) 00191 { 00192 theTime.fractionalReset(); 00193 theTime++; // Increment the time/date by one second. 00194 cb_pps.call(); 00195 } 00196 00197 void 00198 GPS::rx_irq(void) 00199 { 00200 uint32_t iir __attribute__((unused)); 00201 char c; 00202 00203 if (_base) { 00204 iir = (uint32_t)*((char *)_base + GPS_IIR); 00205 while((int)(*((char *)_base + GPS_LSR) & 0x1)) { 00206 c = (char)(*((char *)_base + GPS_RBR) & 0xFF); 00207 00208 // strtok workaround. 00209 // Found that ,, together (which some NMEA sentences 00210 // contain for a null/empty field) confuses strtok() 00211 // function. Solution:- Push a "zero" into the string 00212 // for missing/empty fields. 00213 if (c == ',' && _lastByte == ',') { 00214 buffer[active_buffer][rx_buffer_in] = '0'; 00215 if (++rx_buffer_in >= GPS_BUFFER_LEN) rx_buffer_in = 0; 00216 } 00217 00218 // Debugging/dumping data. 00219 if (_nmeaOnUart0) LPC_UART0->RBR = c; 00220 00221 // Put the byte into the string. 00222 buffer[active_buffer][rx_buffer_in] = c; 00223 if (++rx_buffer_in >= GPS_BUFFER_LEN) rx_buffer_in = 0; 00224 00225 // Save for next time an irq occurs. See strtok() above. 00226 _lastByte = c; 00227 00228 // If end of NMEA sentence flag for processing. 00229 if (c == '\n') { 00230 active_buffer = active_buffer == 0 ? 1 : 0; 00231 process_required = true; 00232 rx_buffer_in = 0; 00233 } 00234 } 00235 } 00236 }
Generated on Thu Jul 14 2022 03:46:43 by 1.7.2