summaryrefslogtreecommitdiff
path: root/driver_nmea0183.c
diff options
context:
space:
mode:
authorGary E. Miller <gem@rellim.com>2019-05-02 19:11:48 -0700
committerGary E. Miller <gem@rellim.com>2019-05-02 19:11:48 -0700
commitfacabfaa44bdb4d2c7c528f61de9cb963107312c (patch)
treefcb3ba972f11fcc4ee5a81a494f5ed858232d116 /driver_nmea0183.c
parent2773697c812b55acf88269c01a0336d1a5d28fd4 (diff)
downloadgpsd-facabfaa44bdb4d2c7c528f61de9cb963107312c.tar.gz
driver_nmea0183: Enforce NMEA 4.0 type PRNs.
Up until now, the PWN was whatever the GPS said it was. With NMEA 4.10 this is no longer sustainable. The u-blox 9 defaults to NMEA 4.10, sort of. It sometimes puts NMEA 4.0 PRNs into NMEA 4.10 sentences. Some people like to use both u-blox binary and NMEA sentences mixed together, so the time has come to enforce the PRN complies with NMEA 4.0 extended numbering. Sadly this can not map exactly into u-blox numbering, but is a start. Fixing this uncovered other examples of non NMEA compliant sentences in the regressions. So many regressions changed. The most obvious change is that NMEA 4.0 puts the SBAS PRN in the range 33-64 and 152-158, not 120-158 as u-blox does.
Diffstat (limited to 'driver_nmea0183.c')
-rw-r--r--driver_nmea0183.c213
1 files changed, 176 insertions, 37 deletions
diff --git a/driver_nmea0183.c b/driver_nmea0183.c
index 8aded2b0..9c0e5d41 100644
--- a/driver_nmea0183.c
+++ b/driver_nmea0183.c
@@ -801,7 +801,7 @@ static gps_mask_t processGGA(int c UNUSED, char *field[],
session->gpsdata.status = STATUS_NO_FIX;
session->newdata.mode = MODE_NO_FIX;
gpsd_log(&session->context->errout, LOG_PROG,
- "xxGSA: latch mode\n");
+ "xxGGA: latch mode\n");
} else
(void)strlcpy(session->nmea.last_gga_timestamp, field[1],
sizeof(session->nmea.last_gga_timestamp));
@@ -944,7 +944,7 @@ static unsigned char nmea_sigid_to_ubx(unsigned char nmea_sigid)
default:
/* FALLTHROUGH */
case 0:
- /* missing, assume GPS */
+ /* missing, assume GPS L1 */
ubx_sigid = 0;
break;
case 1:
@@ -981,10 +981,12 @@ static unsigned char nmea_sigid_to_ubx(unsigned char nmea_sigid)
* See struct satellite_t in gps.h for ubx and nmea gnssid and svid mappings
*
* char *talker -- NMEA talker string
- * int nmea_satnum -- NMEA satellite number (kinds tha PRN)
+ * int nmea_satnum -- NMEA (All ver) satellite number (kinda the PRN)
* int nmea_gnssid -- NMEA 4.10 gnssid, if known, otherwise zero
* unsigned char *ubx_gnssid -- returned u-blox gnssid
* unsigned char *ubx_svid -- returned u-blox gnssid
+ *
+ * Return the NMEA 2.x to 4.0 extended PRN
*/
static int nmeaid_to_prn(char *talker, int nmea_satnum,
int nmea_gnssid,
@@ -1019,23 +1021,94 @@ static int nmeaid_to_prn(char *talker, int nmea_satnum,
* effect, they're recorded by the order in which they occur
* rather than by PRN.
*/
+ int nmea2_prn = nmea_satnum;
+
*ubx_gnssid = 0; /* default to ubx_gnssid is GPS */
*ubx_svid = 0; /* default to unnknown ubx_svid */
- if (0 != nmea_satnum && 32 >= nmea_satnum) {
+
+ if (1 > nmea_satnum) {
+ /* uh, oh... */
+ nmea2_prn = 0;
+ } else if (0 < nmea_gnssid) {
+ /* this switch handles case where nmea_gnssid is known */
+ switch (nmea_gnssid) {
+ default:
+ /* x = IMES Not defined by NMEA 4.10 */
+ /* FALLTHROUGH */
+ case 0:
+ /* none given, ignore */
+ nmea2_prn = 0;
+ break;
+ case 1:
+ if (33 > nmea_satnum) {
+ /* 1 = GPS 1-32 */
+ *ubx_gnssid = 0;
+ *ubx_svid = nmea_satnum;
+ } else if (65 > nmea_satnum) {
+ /* 1 = SBAS 33-64 */
+ *ubx_gnssid = 1;
+ *ubx_svid = 87 + nmea_satnum;
+ } else if (152 > nmea_satnum) {
+ /* Huh? */
+ *ubx_gnssid = 0;
+ *ubx_svid = 0;
+ nmea2_prn = 0;
+ } else if (158 > nmea_satnum) {
+ /* 1 = SBAS 152-158 */
+ *ubx_gnssid = 1;
+ *ubx_svid = nmea_satnum;
+ } else if (193 > nmea_satnum) {
+ /* Huh? */
+ *ubx_gnssid = 0;
+ *ubx_svid = 0;
+ nmea2_prn = 0;
+ } else if (198 > nmea_satnum) {
+ /* 1 = QZSS 193-197 */
+ *ubx_gnssid = 3;
+ *ubx_svid = nmea_satnum - 192;
+ } else {
+ /* Huh? */
+ *ubx_gnssid = 0;
+ *ubx_svid = 0;
+ nmea2_prn = 0;
+ }
+ break;
+ case 2:
+ /* 2 = GLONASS 65-96, nul */
+ *ubx_gnssid = 6;
+ *ubx_svid = nmea_satnum;
+ break;
+ case 3:
+ /* 3 = Galileo 1-36 */
+ *ubx_gnssid = 2;
+ *ubx_svid = nmea_satnum;
+ nmea2_prn = 300 + nmea_satnum;
+ break;
+ case 4:
+ /* 4 - BeiDou 1-37 */
+ *ubx_gnssid = 3;
+ *ubx_svid = nmea_satnum;
+ nmea2_prn = 300 + nmea_satnum;
+ break;
+ }
+
+ /* left with NMEA 2.x to NMEA 4.0 satnums
+ * use talker ID to disambiguate */
+ } else if (32 >= nmea_satnum) {
*ubx_svid = nmea_satnum;
switch (talker[0]) {
case 'G':
if (talker[1] == 'A') {
/* Galileo */
- nmea_satnum += 300; /* Used by u-blox at least */
+ nmea2_prn = 300 + nmea_satnum;
*ubx_gnssid = 2;
} else if (talker[1] == 'B') {
- /* map Beidou IDs */
+ /* map Beidou IDs 1..37 to 401..437 */
*ubx_gnssid = 3;
- nmea_satnum += 200;
+ nmea2_prn = 400 + nmea_satnum;
} else if (talker[1] == 'L') {
/* GLONASS GL doesn't seem to do this, better safe than sorry */
- nmea_satnum += 64;
+ nmea2_prn = 64 + nmea_satnum;
*ubx_gnssid = 6;
} else if (talker[1] == 'N') {
/* all of them, but only GPS is 0 < PRN < 33 */
@@ -1046,14 +1119,14 @@ static int nmeaid_to_prn(char *talker, int nmea_satnum,
case 'B':
if (talker[1] == 'D') {
/* map Beidou IDs */
- nmea_satnum += 200;
+ nmea2_prn = 400 + nmea_satnum;
*ubx_gnssid = 3;
} /* else ?? */
break;
case 'Q':
if (talker[1] == 'Z') {
/* QZSS */
- nmea_satnum += 192;
+ nmea2_prn = 192 + nmea_satnum;
*ubx_gnssid = 5;
} /* else ? */
break;
@@ -1061,39 +1134,79 @@ static int nmeaid_to_prn(char *talker, int nmea_satnum,
/* huh? */
break;
}
- } else if ( 33 <= nmea_satnum && 64 >= nmea_satnum) {
+ } else if (64 >= nmea_satnum) {
// NMEA-ID (33..64) to SBAS PRN 120-151.
/* SBAS */
- nmea_satnum += 87;
*ubx_gnssid = 1;
- *ubx_svid = nmea_satnum;
- } else if (65 <= nmea_satnum && 96 >= nmea_satnum) {
- /* GLONASS */
+ *ubx_svid = 87 + nmea_satnum;
+ } else if (96 >= nmea_satnum) {
+ /* GLONASS 65..96 */
*ubx_gnssid = 6;
*ubx_svid = nmea_satnum - 64;
- } else if (120 <= nmea_satnum && 158 >= nmea_satnum) {
- /* SBAS */
+ } else if (120 > nmea_satnum) {
+ /* Huh? */
+ *ubx_gnssid = 0;
+ *ubx_svid = 0;
+ nmea2_prn = 0;
+ } else if (158 >= nmea_satnum) {
+ /* SBAS 120..158 */
*ubx_gnssid = 1;
*ubx_svid = nmea_satnum;
- } else if (173 <= nmea_satnum && 182 >= nmea_satnum) {
- /* IMES */
+ } else if (173 > nmea_satnum) {
+ /* Huh? */
+ *ubx_gnssid = 0;
+ *ubx_svid = 0;
+ nmea2_prn = 0;
+ } else if (182 >= nmea_satnum) {
+ /* IMES 173..182 */
*ubx_gnssid = 4;
*ubx_svid = nmea_satnum - 172;
- } else if (193 <= nmea_satnum && 197 >= nmea_satnum) {
- /* QZSS */
+ } else if (193 > nmea_satnum) {
+ /* Huh? */
+ *ubx_gnssid = 0;
+ *ubx_svid = 0;
+ nmea2_prn = 0;
+ } else if (197 >= nmea_satnum) {
+ /* QZSS 193..197 */
*ubx_gnssid = 5;
*ubx_svid = nmea_satnum - 192;
- } else if (301 <= nmea_satnum && 356 >= nmea_satnum) {
- /* QZSS */
+ } else if (201 > nmea_satnum) {
+ /* Huh? */
+ *ubx_gnssid = 0;
+ *ubx_svid = 0;
+ nmea2_prn = 0;
+ } else if (237 >= nmea_satnum) {
+ /* BeiDou, non-standard, some SiRF put BeiDou 201-237 */
+ /* $GBGSV,2,2,05,209,07,033,*62 */
+ *ubx_gnssid = 3;
+ *ubx_svid = nmea_satnum - 200;
+ nmea2_prn += 200; /* move up to 400 where NMEA 2.x wants it. */
+ } else if (301 > nmea_satnum) {
+ /* Huh? */
+ *ubx_gnssid = 0;
+ *ubx_svid = 0;
+ nmea2_prn = 0;
+ } else if (356 >= nmea_satnum) {
+ /* QZSS 301..356 */
*ubx_gnssid = 2;
*ubx_svid = nmea_satnum - 300;
- } else if (401 <= nmea_satnum && 437 >= nmea_satnum) {
+ } else if (401 > nmea_satnum) {
+ /* Huh? */
+ *ubx_gnssid = 0;
+ *ubx_svid = 0;
+ nmea2_prn = 0;
+ } else if (437 >= nmea_satnum) {
/* BeiDou */
*ubx_gnssid = 3;
*ubx_svid = nmea_satnum - 400;
+ } else {
+ /* greater than 437 Huh? */
+ *ubx_gnssid = 0;
+ *ubx_svid = 0;
+ nmea2_prn = 0;
}
- return nmea_satnum;
+ return nmea2_prn;
}
static gps_mask_t processGSA(int count, char *field[],
@@ -1146,15 +1259,19 @@ static gps_mask_t processGSA(int count, char *field[],
* seems like the first is GNSS and the second GLONASS
*
* u-blox 9 outputs one per GNSS on each cycle. Note the
- * extra last parameter which is NMEA gnssid
+ * extra last parameter which is NMEA gnssid:
* $GNGSA,A,3,13,16,21,15,10,29,27,20,,,,,1.05,0.64,0.83,1*03
* $GNGSA,A,3,82,66,81,,,,,,,,,,1.05,0.64,0.83,2*0C
* $GNGSA,A,3,07,12,33,,,,,,,,,,1.05,0.64,0.83,3*0A
* $GNGSA,A,3,13,12,22,19,08,21,,,,,,,1.05,0.64,0.83,4*0B
+ * Also note the NMEA 4.0 GLONASS PRN (82) in an NMEA 4.1
+ * sentence.
*/
gps_mask_t mask = ONLINE_SET;
char last_last_gsa_talker = session->nmea.last_gsa_talker;
int nmea_gnssid = 0;
+ int nmea_sigid = 0;
+ int ubx_sigid = 0;
/*
* One chipset called the i.Trek M3 issues GPGSA lines that look like
@@ -1200,8 +1317,10 @@ static gps_mask_t processGSA(int count, char *field[],
if (field[17][0] != '\0')
session->gpsdata.dop.vdop = safe_atof(field[17]);
if (19 == count && '\0' != field[18][0]) {
- /* get the NMEA 4.10 gnssid */
- nmea_gnssid = atoi(field[18]);
+ /* get the NMEA 4.10 sigid */
+ nmea_sigid = atoi(field[18]);
+ /* FIXME: ubx_sigid not used yet */
+ ubx_sigid = nmea_sigid_to_ubx(nmea_sigid);
}
}
/*
@@ -1231,15 +1350,28 @@ static gps_mask_t processGSA(int count, char *field[],
/* the magic 6 here counts the tag, two mode fields, and DOP fields */
for (i = 0; i < count - 6; i++) {
int prn;
+ int nmea_satnum;
unsigned char ubx_gnssid; /* UNUSED */
unsigned char ubx_svid; /* UNUSED */
/* skip empty fields, otherwise empty becomes prn=200 */
- if ( '\0' == field[i + 3][0] ) {
+ nmea_satnum = atoi(field[i + 3]);
+ if (1 > nmea_satnum) {
continue;
}
- prn = nmeaid_to_prn(field[0], atoi(field[i + 3]), nmea_gnssid,
+ prn = nmeaid_to_prn(field[0], nmea_satnum, nmea_gnssid,
&ubx_gnssid, &ubx_svid);
+
+#ifdef __UNUSED__
+ /* debug */
+ gpsd_log(&session->context->errout, LOG_ERROR,
+ "%s nmeaid_to_prn: nmea_gnssid %d nmea_satnum %d ubx_gnssid %d "
+ "ubx_svid %d nmea2_prn %d\n", field[0],
+ nmea_gnssid, nmea_satnum, ubx_gnssid, ubx_svid, prn);
+ gpsd_log(&session->context->errout, LOG_ERROR,
+ "%s count %d\n", field[0], count);
+#endif /* __UNUSED__ */
+
if (prn > 0) {
/* check first BEFORE over-writing memory */
if (MAXCHANNELS <= session->gpsdata.satellites_used) {
@@ -1254,12 +1386,13 @@ static gps_mask_t processGSA(int count, char *field[],
}
mask |= DOP_SET | USED_IS;
gpsd_log(&session->context->errout, LOG_DATA,
- "xxGSA: mode=%d used=%d pdop=%.2f hdop=%.2f vdop=%.2f\n",
+ "xxGSA: mode=%d used=%d pdop=%.2f hdop=%.2f vdop=%.2f "
+ "ubx_sigid %d\n",
session->newdata.mode,
session->gpsdata.satellites_used,
session->gpsdata.dop.pdop,
session->gpsdata.dop.hdop,
- session->gpsdata.dop.vdop);
+ session->gpsdata.dop.vdop, ubx_sigid);
}
/* assumes GLGSA or BDGSA, if present, is emitted directly
* after the GPGSA*/
@@ -1384,9 +1517,6 @@ static gps_mask_t processGSV(int count, char *field[],
/* NMEA 4.10, get the signal ID */
nmea_sigid = atoi(field[count - 1]);
ubx_sigid = nmea_sigid_to_ubx(nmea_sigid);
- gpsd_log(&session->context->errout, LOG_DATA,
- "GPGSV fieldcount %d %% 4 == 1, nmea_sigid %u ubx_sig %u\n",
- count, nmea_sigid, ubx_sigid);
break;
default:
/* bad count */
@@ -1455,7 +1585,7 @@ static gps_mask_t processGSV(int count, char *field[],
if (session->gpsdata.satellites_visible >= MAXCHANNELS) {
gpsd_log(&session->context->errout, LOG_ERROR,
- "internal error - too many satellites [%d]!\n",
+ "xxGSV: internal error - too many satellites [%d]!\n",
session->gpsdata.satellites_visible);
gpsd_zero_satellites(&session->gpsdata);
break;
@@ -1466,9 +1596,18 @@ static gps_mask_t processGSV(int count, char *field[],
/* skip bogus fields */
continue;
}
- /* FIXME: this ignores possible NMEA 4.1 nmea_gnssid hint */
+ /* FIXME: this ignores possible NMEA 4.1 Signal ID hint */
sp->PRN = (short)nmeaid_to_prn(field[0], nmea_svid, nmea_gnssid,
&sp->gnssid, &sp->svid);
+
+#ifdef __UNUSED__
+ /* debug */
+ gpsd_log(&session->context->errout, LOG_ERROR,
+ "%s nmeaid_to_prn: nmea_gnssid %d nmea_satnum %d "
+ "ubx_gnssid %d ubx_svid %d nmea2_prn %d\n", field[0],
+ nmea_gnssid, nmea_svid, sp->gnssid, sp->svid, sp->PRN);
+#endif /* __UNUSED__ */
+
sp->elevation = (short)atoi(field[fldnum++]);
sp->azimuth = (short)atoi(field[fldnum++]);
sp->ss = (float)atoi(field[fldnum++]);