summaryrefslogtreecommitdiff
path: root/nmea_parse.c
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2005-03-26 16:47:50 +0000
committerEric S. Raymond <esr@thyrsus.com>2005-03-26 16:47:50 +0000
commitad2d7bf37f63229486016ed4c440a17f47ad1805 (patch)
tree5100c86ccb92f7b7bb336a26d317ba4016dc8d32 /nmea_parse.c
parent4e4c4694d007e763c0fc0370b2d023ba13dc5e0d (diff)
downloadgpsd-ad2d7bf37f63229486016ed4c440a17f47ad1805.tar.gz
We process GPZDA now, and deduce timestamps from old GPRMCs.
Diffstat (limited to 'nmea_parse.c')
-rw-r--r--nmea_parse.c58
1 files changed, 37 insertions, 21 deletions
diff --git a/nmea_parse.c b/nmea_parse.c
index 866e1fe4..e6d69c41 100644
--- a/nmea_parse.c
+++ b/nmea_parse.c
@@ -69,35 +69,29 @@ static void do_lat_lon(char *field[], struct gps_data_t *out)
*
* Scary timestamp fudging begins here
*
+ * Four sentences, GGA and GLL and RMC and ZDA, contain timestamps.
+ * Timestamps always look like hhmmss.ss, with the trailing .ss part
+ * optional. RMC has a date field, in the format ddmmyy. ZDA has
+ * separate fields for day/month/year, with a 4-digit year. This
+ * means that for RMC we must supply a century and for GGA and GGL we
+ * must supply a century, year, and day. We get the missing data from
+ * a previous RMC or ZDA; century in RMC is supplied by the host
+ * machine's clock time if there has been no previous RMC.
+ *
**************************************************************************/
-/*
- Three sentences, GGA and GLL and RMC, contain timestamps. Timestamps
- always look like hhmmss.ss, with the trailing .ss part optional.
- RMC alone has a date field, in the format ddmmyy. These functions
- generate a canonical form in ISO 8601 format:
-
- yyyy-mm-ddThh:mm:ss.sssZ
- 012345678901234567890123
-
- (where part or all of the decimal second suffix may be omitted).
- This means that for GPRMC we must supply a century and for GGA and
- GGL we must supply a century, year, and day. We get the missing data
- from the host machine's clock time.
-
- Sigh. This is only necessary because the design of NMEA 0183 is a crock.
- */
-
#define DD(s) ((s)[0]-'0')*10+((s)[1]-'0')
static void merge_ddmmyy(char *ddmmyy, struct gps_data_t *out)
/* sentence supplied ddmmyy, but no century part */
{
- struct tm tm;
- time_t now = time(NULL);
+ if (!out->nmea_date.tm_year) {
+ struct tm tm;
+ time_t now = time(NULL);
- gmtime_r(&now, &tm);
- out->nmea_date.tm_year = ((1900+tm.tm_year)/100)*100 + DD(ddmmyy+4) - 1900;
+ gmtime_r(&now, &tm);
+ out->nmea_date.tm_year = ((1900+tm.tm_year)/100)*100+DD(ddmmyy+4)-1900;
+ }
out->nmea_date.tm_mon = DD(ddmmyy+2)-1;
out->nmea_date.tm_mday = DD(ddmmyy);
}
@@ -407,6 +401,27 @@ static int processPGRME(int c UNUSED, char *field[], struct gps_data_t *out)
return HERR_SET | VERR_SET | PERR_SET;
}
+static int processGPZDA(int c UNUSED, char *field[], struct gps_data_t *out)
+/* Time & Date */
+{
+ /*
+ $GPZDA,160012.71,11,03,2004,-1,00*7D
+ 1) UTC time (hours, minutes, seconds, may have fractional subsecond)
+ 2) Day, 01 to 31
+ 3) Month, 01 to 12
+ 4) Year (4 digits)
+ 5) Local zone description, 00 to +- 13 hours
+ 6) Local zone minutes description, apply same sign as local hours
+ 7) Checksum
+ */
+ merge_hhmmss(field[1], out);
+ out->nmea_date.tm_year = atoi(field[4]) - 1900;
+ out->nmea_date.tm_mon = atoi(field[3]);
+ out->nmea_date.tm_mday = atoi(field[2]);
+ out->fix.time = mktime(&out->nmea_date) + out->subseconds;
+ return TIME_SET;
+}
+
static short nmea_checksum(char *sentence, unsigned char *correct_sum)
/* is the checksum on the specified sentence good? */
{
@@ -460,6 +475,7 @@ int nmea_parse(char *sentence, struct gps_data_t *outdata)
{"GPGLL", GPGLL, processGPGLL},
{"GPGSA", GPGSA, processGPGSA},
{"GPGSV", GPGSV, processGPGSV},
+ {"GZDA", GPZDA, processGPZDA},
{"PGRME", PGRME, processPGRME},
};