?? gps.c
字號:
/* don't update clock if 'delta' is '0' */ if (delta <= 0L) { return utFalse; } /* minimum delta */ if (delta < MIN_DELTA_CLOCK_TIME) { delta = MIN_DELTA_CLOCK_TIME; } /* check actual time delta */ long d = labs(fixtime - utcGetTimeSec()); // setting systime to fixtime if (d <= delta) { // actual time delta is within acceptable range return utFalse; } /* never update if we're running the GPS simulator */#if defined(GPS_DEVICE_SIMULATOR) if (gpsSimulator) { logDEBUG(LOGSRC,"System clock out-of-sync: %ld [delta %ld sec]", fixtime, d); return utFalse; }#endif /* update clock */ logDEBUG(LOGSRC,"System clock out-of-sync: %ld [delta %ld sec]", fixtime, d); utcSetTimeSec(fixtime); return utTrue;}// ----------------------------------------------------------------------------/* parse YMD/HMS into UTC Epoch seconds */static UInt32 _gpsGetUTCSeconds(UInt32 dmy, UInt32 hms){ /* time of day [TOD] */ int HH = (int)((hms / 10000L) % 100L); int MM = (int)((hms / 100L) % 100L); int SS = (int)(hms % 100L); UInt32 TOD = (HH * 3600L) + (MM * 60L) + SS; /* current UTC day */ long DAY = 0L; if (dmy) { int yy = (int)(dmy % 100L) + 2000; int mm = (int)((dmy / 100L) % 100L); int dd = (int)((dmy / 10000L) % 100L); long yr = ((long)yy * 1000L) + (long)(((mm - 3) * 1000) / 12); DAY = ((367L * yr + 625L) / 1000L) - (2L * (yr / 1000L)) + (yr / 4000L) - (yr / 100000L) + (yr / 400000L) + (long)dd - 719469L; } else { // we don't have the day, so we need to figure out as close as we can what it should be. UInt32 utc = utcGetTimeSec(); if (utc < MIN_CLOCK_TIME) { // the system clock time is not valid logWARNING(LOGSRC,"Current clock time is prior to minimum time! [%lu]", utc); DAY = 0L; } else { UInt32 tod = utc % DAY_SECONDS(1); DAY = utc / DAY_SECONDS(1); Int32 dif = tod - TOD; // difference should be small (ie. < 1 hour) if (labs(dif) > HOUR_SECONDS(12)) { // 12 to 18 hours // > 12 hour difference, assume we've crossed a day boundary if (tod > TOD) { // tod > TOD likely represents the next day DAY++; } else { // tod < TOD likely represents the previous day DAY--; } } } } /* return UTC seconds */ UInt32 sec = DAY_SECONDS(DAY) + TOD; return sec; }/* parse latitude */static double getLatitude(const char *s, const char *d){ double _lat = strParseDouble(s, 99999.0); if (_lat < 99999.0) { double lat = (double)((long)_lat / 100L); // _lat is always positive here lat += (_lat - (lat * 100.0)) / 60.0; return !strcmp(d,"S")? -lat : lat; } else { return 90.0; // invalid latitude }}/* parse longitude */static double getLongitude(const char *s, const char *d){ double _lon = strParseDouble(s, 99999.0); if (_lon < 99999.0) { double lon = (double)((long)_lon / 100L); // _lon is always positive here lon += (_lon - (lon * 100.0)) / 60.0; return !strcmp(d,"W")? -lon : lon; } else { return 180.0; // invalid longitude }}/* read a single line from the GPS receiver */static int _gpsReadLine(ComPort_t *com, char *data, int dataSize, long timeoutMS){#if defined(GPS_DEVICE_SIMULATOR)#define SIM_LAT(X) ( 37.0 + (X)) // 41#define SIM_LON(X) (-140.0 - (X)) // -87 if (gpsSimulator) { static int simCount = 0; threadSleepMS(1000L); double LL[][2] = {//#ifdef NOT_DEF { SIM_LAT(0.10000), SIM_LON(0.10000) }, { SIM_LAT(0.17000), SIM_LON(0.17000) }, { SIM_LAT(0.18000), SIM_LON(0.18000) }, { SIM_LAT(0.19000), SIM_LON(0.19000) }, { SIM_LAT(0.20000), SIM_LON(0.20000) }, { SIM_LAT(0.21000), SIM_LON(0.21000) }, { SIM_LAT(0.30000), SIM_LON(0.30000) }, { SIM_LAT(0.40000), SIM_LON(0.40000) }, { SIM_LAT(0.41000), SIM_LON(0.41000) }, { SIM_LAT(0.42000), SIM_LON(0.42000) }, { SIM_LAT(0.43000), SIM_LON(0.43000) },//#endif { SIM_LAT(0.50089), SIM_LON(0.56954) }, }; int LLCount = sizeof(LL) / sizeof(LL[0]); simCount++; char *d = data;#if defined(TARGET_WINCE) SYSTEMTIME st; GetSystemTime(&st); // UTC int hr = st.wHour, mn = st.wMinute, sc = st.wSecond; int dy = st.wDay, mo = st.wMonth, yr = st.wYear % 100;#else UInt32 tsc = utcGetTimeSec(); // - HOUR_SECONDS(8); // simulator struct tm *tmp = gmtime(&tsc); int hr = tmp->tm_hour, mn = tmp->tm_min, sc = tmp->tm_sec; int dy = tmp->tm_mday, mo = tmp->tm_mon + 1, yr = tmp->tm_year % 100;#endif int kts = ((simCount % 20) <= 10)? 20 : 0; // knots int x = ((simCount/1) % LLCount); double lat = ((100.0 * (long)LL[x][0]) + (60.0 * (LL[x][0] - (long)LL[x][0]))); double lon = ((100.0 * (long)LL[x][1]) + (60.0 * (LL[x][1] - (long)LL[x][1]))); if (lon < 0.0) { lon = -lon; } sprintf(d, "$GPRMC,"); d += strlen(d); sprintf(d, "%02d%02d%02d", hr, mn, sc); d += strlen(d); sprintf(d, ",A,"); d += strlen(d); sprintf(d, "%f,N,", (float)lat); d += strlen(d); sprintf(d, "%f,W,", (float)lon); d += strlen(d); sprintf(d, "%d", kts); d += strlen(d); sprintf(d, ",108.52,"); d += strlen(d); sprintf(d, "%02d%02d%02d", dy, mo, yr); d += strlen(d); sprintf(d, ",,"); d += strlen(d); ChecksumXOR_t cksum = 0x00; cksumCalcCharXOR(data+1,&cksum); sprintf(d, "*%02X", (int)cksum); d += strlen(d); //logDEBUG(LOGSRC,"GPS SIM[%d]: %s", simCount, data); return (d - data); }#endif return comPortReadLine(com, data, dataSize, timeoutMS);}/* read GPS fix */// If 'timeoutMS' is 0L, this function does not returnstatic int _gpsReadGPSFix(UInt32 timeoutMS){ ComPort_t *com = &gpsComPort; int dataLen = 0; char data[256]; TimerSec_t startTimer = utcGetTimer(); /* timeout */ // This function will exit when one of the following occurs: // - A valid GPRMC record is found (if timeout is in effect) // - A timeout occurs // - An error occurs UInt32 timeoutSec = (timeoutMS > 0L)? ((timeoutMS + 999L) / 1000L) : 0L; /* flush everything currently in the comport buffers */ // (Try to make sure this GPS device sends only the '$GPRMC' sentence.) comPortFlush(com, 0L); // '0' means don't do any reading, just use 'tcflush' /* read/parse NMEA-0183 data */ long readTimeoutMS = 5000L; long accumTimeoutMS = 0L; while (utTrue) {#if defined(GPS_THREAD) /* thread mode */ if (!gpsRunThread) { // this thread has been requested to stop return 0; // stop thread }#endif /* timeout mode */ if ((timeoutSec > 0L) && utcIsTimerExpired(startTimer,timeoutSec)) { // timeout return 0; // timeout } /* have we read a "$GPRMC" record in the last GPS_EVENT_INTERVAL seconds? */#if defined(GPS_THREAD) // [wait a few seconds before we start checking GPS errors (ie. skip first few passes)] if (utcIsTimerExpired(startTimer,60L)) { // If we've NEVER received a $GPRMC record, then 'gpsLastSampleTimer == 0L'. UInt32 gpsLostInterval = GPS_EVENT_INTERVAL; if (utcIsTimerExpired(gpsLastSampleTimer,gpsLostInterval)) { // We haven't receive *ANY* "$GPRMC" record in over GPS_EVENT_INTERVAL seconds! // One of the following may be the cause: // - The GPS module is not attached. // - The GPS module went to sleep (WindowsCE) // - The GPS module died (or was disconnected). // - The serial port connection is in a strange state. // [Note: a disconnected GPS antenna will NOT cause control to reach here.] // The best we can do is reopen the serial port and try again. if (utcIsTimerExpired(gpsLastLostErrorTimer,600L)) { if (gpsLastSampleTimer == 0L) { logERROR(LOGSRC,"No GPS communication: %lu", (gpsRestartCount + 1L)); } else { logERROR(LOGSRC,"Lost GPS communication: %lu", (gpsRestartCount + 1L)); } gpsLastLostErrorTimer = utcGetTimer(); } return -1; // error } }#endif /* read data */ dataLen = _gpsReadLine(com, data, sizeof(data), readTimeoutMS); if (dataLen < 0) { // com port closed? (not likely on the GumStix) if (utcIsTimerExpired(gpsLastReadErrorTimer,600L)) { gpsLastReadErrorTimer = utcGetTimer(); logWARNING(LOGSRC,"GPS read error: %lu", (gpsRestartCount + 1L)); } return -1; // error } else if (dataLen == 0) { if (COMERR_IsTimeout(com)) { // TIMEOUT? (if the GPS module is in place, this should never occur) // This indicates that we have lost communication with the GPS. accumTimeoutMS += readTimeoutMS; continue; } else { // zero length record continue; } } /* we've read at least something, reset timeout */ accumTimeoutMS = 0L; /* valid data? */ if (data[0] != '$') { // we must have started in the middle of the sentence continue; // try again } /* DEBUG: display data */#if defined(TARGET_WINCE) if (gpsPortDebug) { logDEBUG(LOGSRC,"%s", data); }#else //logDEBUG(LOGSRC,"%s", data);#endif#if defined(TARGET_WINCE) // skip handling of specific GPS receiver types#else /* unexpected sentences */ if (strStartsWith(data, "$PG") || // <-- Garmin sentence strStartsWith(data, "$GPGSV")) { // <-- Satellite info sentence // reconfigure Garmin device //logINFO(LOGSRC,"Unexpected sentence: %s", data); const char *receiver = propGetString(PROP_CFG_GPS_MODEL,""); if (strEqualsIgnoreCase(receiver,GPS_RECEIVER_GARMIN)) { // If the serial port is configured for RX-only, then this section should // be commented out. Otherwise the Garmin config strings will be continually // sent and may slow down communication with the receiver. _gpsConfigGarmin(com); } else { // don't know how to trim out these sentences } continue; }#endif /* NMEA-0183 sentence */ if (strStartsWith(data, "$GP")) { // http://www.scientificcomponent.com/nmea0183.htm // http://home.mira.net/~gnb/gps/nmea.html // $GPGGA - Global Positioning System Fix Data // $GPGGA|015402.240|0000.0000|N|00000.0000|E|0|00|50.0|0.0|M|18.0|M|0.0|0000*4B| // $GPGGA|025425.494|3509.0743|N|11907.6314|W|1|04|2.3|530.3|M|-21.9|M|0.0|0000*4D| // $GPGGA, 1 , 2 ,3, 4 ,5,6,7 , 8 , 9 ,10, 11,12,13 , 14 // 1 UTC time of position HHMMSS // 2 current latitude in ddmm.mm format // 3 latitude hemisphere ("N" = northern, "S" = southern) // 4 current longitude in dddmm.mm format // 5 longitude hemisphere ("E" = eastern, "W" = western) // 6 (0=no fix, 1=GPS, 2=DGPS, 3=PPS?, 6=dead-reckoning) // 7 number of satellites (00-12) // 8 Horizontal Dilution of Precision // 9 Height above/below mean geoid (above mean sea level, not WGS-84 ellipsoid height) // 10 Unit of height, always 'M' meters // 11 Geoidal separation (add to #9 to get WGS-84 ellipsoid height) // 12 Unit of Geoidal separation (meters) // 13 Age of differential GPS // 14 Differential reference station ID (always '0000') // $GPGLL - Geographic Position, Latitude/Longitude // $GPGLL|36000.0000|N|72000.0000|E|015402.240|V*17| // $GPGLL|3209.0943|N|11907.9313|W|025426.493|A*2F| // $GPGLL, 1 ,2, 3 ,4, 5 ,6 // 1 Current latitude // 2 North/South // 3 Current longitude // 4 East/West // 5 UTC in hhmmss format
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -