⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gps.c

📁 Open DMT Client C Source code
💻 C
📖 第 1 页 / 共 4 页
字号:
        /* 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 + -