?? gps.c
字號:
// ----------------------------------------------------------------------------// Copyright 2006-2007, Martin D. Flynn// All rights reserved// ----------------------------------------------------------------------------//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// // http://www.apache.org/licenses/LICENSE-2.0// // Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.//// ----------------------------------------------------------------------------// Description:// Machine interface to GPS module.// Abstraction layer for the machine interface to the GPS module.// Notes:// - The code included here is only an example of how to parse NMEA-0183 GPS records.// This module should perform sufficient error checking to insure that the GPS module// is functioning properly.// - Ideally, GPS aquisition should occur in it's own thread in order to return// the latest GPS fix to the requestor immediately (without blocking). In non-thread// mode, this implementation will block until a new GPS fix has been aquired (or if a // timeout occurs).// ---// Change History:// 2006/01/04 Martin D. Flynn// -Initial release// 2006/02/09 Martin D. Flynn// -This module now maintains its "stale" state.// -"gpsGetDiagnostics" now returns a structure.// 2006/06/08 Martin D. Flynn// -Added support for parsing "$GPGSA" // (the DOP values are not currently used for fix discrimination).// 2007/01/28 Martin D. Flynn// -WindowsCE port// -Switched to generic thread access methods in 'tools/threads.h'// -Initial implementation of a 'power-save' mode feature that closes the GPS // comport if the sampling interval is greater than a minute (or so). The HP // hw6945 turns off the GPS receiver when the comport has been closed - to save // power. This feature allows GPS tracking on the HP hw6945 to conserve power// (at the expense of some event accuracy). Note: this feature is still under// development and may not currently produce the desired results if used.// ----------------------------------------------------------------------------#include "stdafx.h" // TARGET_WINCE#include "custom/defaults.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <time.h>#include <math.h>#include "custom/log.h"#include "custom/gps.h"#include "custom/gpsmods.h"#include "tools/stdtypes.h"#include "tools/utctools.h"#include "tools/strtools.h"#include "tools/checksum.h"#include "tools/comport.h"#include "base/events.h"#include "base/propman.h"#include "base/statcode.h"// ----------------------------------------------------------------------------#if !defined(GPS_COM_DATA_FORMAT)# define GPS_COM_DATA_FORMAT "8N1"#endif// ----------------------------------------------------------------------------/* compiling with thread support? */#if defined(GPS_THREAD)//# warning GPS thread support enabled# include "tools/threads.h"#else//# warning GPS thread support disabled#endif// ----------------------------------------------------------------------------// References:// "GPS Hackery": http://www.ualberta.ca/~ckuethe/gps/// "GPS Applications": http://www.codeproject.com/vb/net/WritingGPSApplications1.asp// ----------------------------------------------------------------------------/* default GPS port */// This default value is not used if the GPS comport property is in effect.// The real default value is specified in 'propman.c'#if defined(TARGET_WINCE)# define DEFAULT_GPS_PORT ""#else# define DEFAULT_GPS_PORT "TTYS2"#endif/* simjulator port name */#define GPS_SIMULATOR_PORT "sim"/* GPS bps */#define DEFAULT_GPS_SPEED 4800L // 8N1 assumed/* maximum out-of-sync seconds between GPS time and system time */// set this value to '0' to ignore sync'ing with system clock #define MAX_DELTA_CLOCK_TIME 20L/* minimum out-of-sync seconds between GPS time and system time */// delta must be at least this value to cause a system clock update#define MIN_DELTA_CLOCK_TIME 5L/* maximum number of allowed seconds in a $GP record 'cycle' */// In most GPS receivers, the default 'cycle' is 1 second#define GP_EXPIRE 5L/* power-save threshold */// if PROP_GPS_SAMPLE_RATE is >= this value, the GPS port will not be openned// until 'gpsAquire' is called, and will be closed after a GPS fix is aquired.#define POWER_SAVE_THRESHOLD 45L // seconds// ----------------------------------------------------------------------------/* control characters */#define ASCII_XON 17 // DC1, CTL_Q#define ASCII_XOFF 19 // DC3, CTL_S// ----------------------------------------------------------------------------#define SUPPORT_TYPE_GPRMC 0x0001 // should always be defined#define SUPPORT_TYPE_GPGGA 0x0002 // altitude, HDOP#define SUPPORT_TYPE_GPGSA 0x0004 // PDOP, HDOP, VDOP// ----------------------------------------------------------------------------#if defined(GPS_DEVICE_SIMULATOR)static utBool gpsSimulator = utFalse;#endifstatic ComPort_t gpsComPort;static utBool gpsPortDebug;static GPS_t gpsFixLast;static GPS_t gpsFixUnsafe;static double gpsLastPDOP = GPS_UNDEFINED_DOP;static double gpsLastHDOP = GPS_UNDEFINED_DOP;static double gpsLastVDOP = GPS_UNDEFINED_DOP;static TimerSec_t gpsLastHDOPTimer = 0L;static utBool gpsIsStale = utFalse;static UInt32 gpsSampleCount_A = 0L; // validstatic UInt32 gpsSampleCount_V = 0L; // invalidstatic UInt32 gpsRestartCount = 0L;static TimerSec_t gpsLastSampleTimer = 0L;static TimerSec_t gpsLastValidTimer = 0L;static TimerSec_t gpsLastReadErrorTimer = 0L;static TimerSec_t gpsLastLostErrorTimer = 0L;static utBool gpsAquireRequest = utFalse;static UInt32 gpsAquireTimeoutMS = 0L;#if defined(GPS_THREAD)static utBool gpsRunThread = utFalse;static threadThread_t gpsThread;static threadMutex_t gpsMutex;static threadMutex_t gpsSampleMutex;static threadMutex_t gpsAquireMutex;static threadCond_t gpsAquireCond;#define SAMPLE_LOCK MUTEX_LOCK(&gpsSampleMutex);#define SAMPLE_UNLOCK MUTEX_UNLOCK(&gpsSampleMutex);#define GPS_LOCK MUTEX_LOCK(&gpsMutex);#define GPS_UNLOCK MUTEX_UNLOCK(&gpsMutex);#define AQUIRE_LOCK MUTEX_LOCK(&gpsAquireMutex);#define AQUIRE_UNLOCK MUTEX_UNLOCK(&gpsAquireMutex);#define AQUIRE_WAIT CONDITION_WAIT(&gpsAquireCond, &gpsAquireMutex);#define AQUIRE_NOTIFY CONDITION_NOTIFY(&gpsAquireCond);#else#define SAMPLE_LOCK #define SAMPLE_UNLOCK #define GPS_LOCK #define GPS_UNLOCK #define AQUIRE_LOCK #define AQUIRE_UNLOCK #define AQUIRE_WAIT #define AQUIRE_NOTIFY #endif// ----------------------------------------------------------------------------static GPSDiagnostics_t gpsStats = { 0L, 0L, 0L, 0L, 0L };GPSDiagnostics_t *gpsGetDiagnostics(GPSDiagnostics_t *stats){#if !defined(GPS_THREAD)// These values will not be accurate if not running in thread mode# warning GPS is not running in thread mode, diagnostic values will not be accurate.#endif GPSDiagnostics_t *s = stats? stats : &gpsStats; SAMPLE_LOCK { s->lastSampleTime = TIMER_TO_UTC(gpsLastSampleTimer); s->lastValidTime = TIMER_TO_UTC(gpsLastValidTimer); s->sampleCount_A = gpsSampleCount_A; s->sampleCount_V = gpsSampleCount_V; s->restartCount = gpsRestartCount; } SAMPLE_UNLOCK return s;}// ----------------------------------------------------------------------------#if defined(TARGET_WINCE)// skip handling of specific GPS receiver types#elsestatic void _gpsConfigGarmin(ComPort_t *com){ // This configures a Garmin receiver to send only GPRMC & GPGGA records, // and send them only once every 2 seconds. // disable all sentences comPortWriteString(com, "$PGRMO,,2\r\r\n"); // "$PGRMO,,4" restores factory default sentences comPortFlush(com, 100L); // Fix mode: Automatic // Differential mode: Automatic comPortWriteString(com, "$PGRMC,A,,,,,,,,A\r\r\n"); comPortFlush(com, 100L); // output every 2 seconds // automatic position averaging when stopped // NMEA-0183 v2.30 off // enable WAAS comPortWriteString(com, "$PGRMC1,2,,2,,,,1,W\r\r\n"); // "$PGRMC1,1" set it back to 1/sec // "$PGRMC1E" queries current config comPortFlush(com, 100L); // enable GPRMC sentence comPortWriteString(com, "$PGRMO,GPRMC,1\r\r\n"); comPortFlush(com, 100L); // enable GPGGA sentence comPortWriteString(com, "$PGRMO,GPGGA,1\r\r\n"); comPortFlush(com, 100L); /* done */ logDEBUG(LOGSRC,"Garmin GPS configured");}#endif// ----------------------------------------------------------------------------/* open gps serial port */static utBool _gpsOpen(){ ComPort_t *com = &gpsComPort; comPortInitStruct(com); /* check port */ const char *portName = propGetString(PROP_CFG_GPS_PORT, ""); if (!portName || !*portName) { portName = DEFAULT_GPS_PORT; } /* simulator mode? */#if defined(GPS_DEVICE_SIMULATOR) gpsSimulator = strEqualsIgnoreCase(portName,GPS_SIMULATOR_PORT); if (gpsSimulator) { // should not be here if we are running in simulator mode return utFalse; }#endif /* speed */ long bpsSpeed = (long)propGetUInt32(PROP_CFG_GPS_BPS, -1L); if (bpsSpeed <= 0L) { bpsSpeed = DEFAULT_GPS_SPEED; } /* open */ if (comPortOpen(com,portName,bpsSpeed,GPS_COM_DATA_FORMAT,utFalse) == (ComPort_t*)0) { // The outer loop will retry the open later // Generally, this should not occur on the GumStix //logWARNING(LOGSRC,"Unable to open GPS port '%s' [%s]", portName, strerror(errno)); logWARNING(LOGSRC,"Unable to open GPS port '%s'", portName); return utFalse; } logDEBUG(LOGSRC,"Opened GPS port: %s [%ld bps]", comPortName(com), bpsSpeed); threadSleepMS(500L); // wait for connection to settle /* comport logging */ gpsPortDebug = propGetBoolean(PROP_CFG_GPS_DEBUG,utFalse);#if defined(TARGET_WINCE) // TODO: implement comport logging feature#else if (gpsPortDebug) { comPortSetDebugLogger(com, 0); }#endif /* specific GPS device configuration */#if defined(TARGET_WINCE) // skip handling of specific GPS receiver types#else const char *receiver = propGetString(PROP_CFG_GPS_MODEL,""); if (strEqualsIgnoreCase(receiver,GPS_RECEIVER_GARMIN)) { // Garmin 15, 18PC _gpsConfigGarmin(com); }#endif /* return success */ return utTrue;}/* close gps serial port */static void _gpsClose(){ comPortClose(&gpsComPort);}// ----------------------------------------------------------------------------/* update system clock time */static utBool gpsUpdateSystemClock(long fixtime){ long delta = (long)propGetUInt32(PROP_GPS_CLOCK_DELTA, MAX_DELTA_CLOCK_TIME);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -