|
|
@@ -66,6 +66,15 @@ BYTE gp_comp (const char *str1, __flash const char *str2)
|
|
|
return c;
|
|
|
}
|
|
|
|
|
|
+/* Per-epoch GGA/GSA/logged tracking for nmea_epoch_complete() - partial parse
|
|
|
+ * state, not global "fully cooked" data, so kept local to this file rather
|
|
|
+ * than on System. */
|
|
|
+static struct {
|
|
|
+ unsigned char gga_ok : 1;
|
|
|
+ unsigned char gsa_ok : 1;
|
|
|
+ unsigned char logged : 1;
|
|
|
+} epoch;
|
|
|
+
|
|
|
#define FIELD_BUF_LEN 32
|
|
|
|
|
|
/* Get a column item */
|
|
|
@@ -126,7 +135,7 @@ unsigned int gp_val(const char *db, unsigned char count) {
|
|
|
static unsigned char speed_sample_high_history;
|
|
|
|
|
|
static void speed_sample_process(double speed_kmh) {
|
|
|
- unsigned char paused = System.tracking_paused || System.tracking_auto_paused;
|
|
|
+ unsigned char paused = tracking_is_paused();
|
|
|
unsigned char fix_trustworthy = gps_fix_trustworthy();
|
|
|
|
|
|
System.speed = speed_kmh+0.5;
|
|
|
@@ -156,9 +165,9 @@ static time_t gp_rmc_parse(const char *str) {
|
|
|
struct tm tmc;
|
|
|
double speed_knots;
|
|
|
|
|
|
- System.epoch_gga_ok = 0;
|
|
|
- System.epoch_gsa_ok = 0;
|
|
|
- System.epoch_logged = 0;
|
|
|
+ epoch.gga_ok = 0;
|
|
|
+ epoch.gsa_ok = 0;
|
|
|
+ epoch.logged = 0;
|
|
|
|
|
|
p = gp_col(str, 1); /* Get h:m:s */
|
|
|
if (!p)
|
|
|
@@ -205,8 +214,10 @@ static void gp_gga_parse(const char *str) {
|
|
|
double tmp;
|
|
|
|
|
|
p = gp_col(str, 7); /* satellites used */
|
|
|
+ if (!p)
|
|
|
+ return;
|
|
|
System.satellites_used = atoi(p);
|
|
|
- System.epoch_gga_ok = 1;
|
|
|
+ epoch.gga_ok = 1;
|
|
|
|
|
|
if (System.satellites_used >= System.conf.min_sats) {
|
|
|
System.sat_count_low = 0;
|
|
|
@@ -216,16 +227,20 @@ static void gp_gga_parse(const char *str) {
|
|
|
|
|
|
/* check validity */
|
|
|
p = gp_col(str, 6);
|
|
|
+ if (!p)
|
|
|
+ return;
|
|
|
if (*p == '0') {
|
|
|
System.location_valid = LOC_INVALID;
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if (!System.sat_count_low)
|
|
|
System.location_valid = LOC_VALID_NEW; /* don't accept the coordinates otherwise, even if reported valid */
|
|
|
|
|
|
/* parse location */
|
|
|
p = gp_col(str, 2); /* latitude */
|
|
|
+ if (!p)
|
|
|
+ return;
|
|
|
location.lat = gp_val(p, 2); /* degrees */
|
|
|
p += 2;
|
|
|
xatof(&p, &tmp); /* minutes */
|
|
|
@@ -233,10 +248,14 @@ static void gp_gga_parse(const char *str) {
|
|
|
location.lat += tmp;
|
|
|
|
|
|
p = gp_col(str, 3); /* N/S */
|
|
|
+ if (!p)
|
|
|
+ return;
|
|
|
if (*p != 'N')
|
|
|
location.lat = -location.lat;
|
|
|
-
|
|
|
+
|
|
|
p = gp_col(str, 4); /* longitude */
|
|
|
+ if (!p)
|
|
|
+ return;
|
|
|
location.lon = gp_val(p, 3); /* degrees */
|
|
|
p += 3;
|
|
|
xatof(&p, &tmp); /* minutes */
|
|
|
@@ -244,16 +263,22 @@ static void gp_gga_parse(const char *str) {
|
|
|
location.lon += tmp;
|
|
|
|
|
|
p = gp_col(str, 5); /* E/W */
|
|
|
+ if (!p)
|
|
|
+ return;
|
|
|
if (*p != 'E')
|
|
|
location.lon = -location.lon;
|
|
|
-
|
|
|
+
|
|
|
p = gp_col(str, 6); /* fix type */
|
|
|
+ if (!p)
|
|
|
+ return;
|
|
|
if (*p == '2')
|
|
|
System.sbas = 1;
|
|
|
else
|
|
|
System.sbas = 0;
|
|
|
-
|
|
|
+
|
|
|
p = gp_col(str, 9); /* MSL altitude */
|
|
|
+ if (!p)
|
|
|
+ return;
|
|
|
xatof(&p, &tmp);
|
|
|
location.alt = tmp;
|
|
|
|
|
|
@@ -289,7 +314,7 @@ static void gp_gsa_parse(const char *str) {
|
|
|
xatof(&p, &hdop);
|
|
|
System.hdop_x100 = (unsigned int)(hdop*100.0 + 0.5);
|
|
|
}
|
|
|
- System.epoch_gsa_ok = 1;
|
|
|
+ epoch.gsa_ok = 1;
|
|
|
}
|
|
|
|
|
|
/* Returns 1 exactly once per epoch (the moment both GGA and GSA have been
|
|
|
@@ -298,8 +323,8 @@ static void gp_gsa_parse(const char *str) {
|
|
|
* see a stale value left over from a previous epoch or an earlier line -
|
|
|
* regardless of which order the receiver sends GGA/GSA in. */
|
|
|
unsigned char nmea_epoch_complete(void) {
|
|
|
- if (System.epoch_gga_ok && System.epoch_gsa_ok && !System.epoch_logged) {
|
|
|
- System.epoch_logged = 1;
|
|
|
+ if (epoch.gga_ok && epoch.gsa_ok && !epoch.logged) {
|
|
|
+ epoch.logged = 1;
|
|
|
return 1;
|
|
|
}
|
|
|
return 0;
|
|
|
@@ -408,11 +433,57 @@ void uart0_put_wrap(int c) {
|
|
|
uart0_put((char)c);
|
|
|
}
|
|
|
|
|
|
-void gps_initialize(void) {
|
|
|
+/* Sends the SBAS-enable/disable and GNSS-mode commands for the currently
|
|
|
+ * configured settings. Used both as the second step of gps_initialize()'s
|
|
|
+ * boot sequence, and directly as the settings menu's .changed callback for
|
|
|
+ * the SBAS/GNSS-mode entries - the latter must apply the just-changed
|
|
|
+ * setting immediately, regardless of System.gps_initialized, rather than
|
|
|
+ * going through gps_initialize()'s boot state machine (which would instead
|
|
|
+ * re-send the GNSS-mode query if called before the module's PMTK011 boot
|
|
|
+ * line has been seen). */
|
|
|
+void gps_settings_changed(void) {
|
|
|
/*
|
|
|
- * PMTK355: query gnss search mode (will fail if only GPS is supported)
|
|
|
* PMTK353: set gnss search mode (GPS/Galileo/Glonass/Beidou)
|
|
|
* PMTK313: enable SBAS
|
|
|
+ */
|
|
|
+ if (get_flag(CONFFLAG_ENABLE_SBAS)) {
|
|
|
+ xfprintf(uart0_put_wrap, PSTR("$PMTK313,1*2E\r\n"));
|
|
|
+ xputs_P(PSTR("SBAS enable sent\r\n"));
|
|
|
+ } else {
|
|
|
+ xfprintf(uart0_put_wrap, PSTR("$PMTK313,0*2F\r\n"));
|
|
|
+ xputs_P(PSTR("SBAS disable sent\r\n"));
|
|
|
+ }
|
|
|
+ if (!System.gps_only) {
|
|
|
+ switch (System.conf.gnss_mode) {
|
|
|
+ default:
|
|
|
+ case GNSS_MODE_GPS_GLONASS_GALILEO:
|
|
|
+ xfprintf(uart0_put_wrap, PSTR("$PMTK353,1,1,1,0,0*2A\r\n"));
|
|
|
+ break;
|
|
|
+ case GNSS_MODE_GPS:
|
|
|
+ xfprintf(uart0_put_wrap, PSTR("$PMTK353,1,0,0,0,0*2A\r\n"));
|
|
|
+ break;
|
|
|
+ case GNSS_MODE_GPS_GALILEO:
|
|
|
+ xfprintf(uart0_put_wrap, PSTR("$PMTK353,1,0,1,0,0*2B\r\n"));
|
|
|
+ break;
|
|
|
+ case GNSS_MODE_GALILEO:
|
|
|
+ xfprintf(uart0_put_wrap, PSTR("$PMTK353,0,0,1,0,0*2A\r\n"));
|
|
|
+ break;
|
|
|
+ case GNSS_MODE_GPS_BEIDOU:
|
|
|
+ xfprintf(uart0_put_wrap, PSTR("$PMTK353,1,0,0,0,1*2B\r\n"));
|
|
|
+ break;
|
|
|
+ case GNSS_MODE_BEIDOU:
|
|
|
+ xfprintf(uart0_put_wrap, PSTR("$PMTK353,0,0,0,0,1*2A\r\n"));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ xputs_P(PSTR("GNSS mode setting sent\r\n"));
|
|
|
+ } else {
|
|
|
+ System.conf.gnss_mode = GNSS_MODE_GPS;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void gps_initialize(void) {
|
|
|
+ /*
|
|
|
+ * PMTK355: query gnss search mode (will fail if only GPS is supported)
|
|
|
* PMTK605: query firmware release; the reply (PMTK705) is logged
|
|
|
* verbatim by the generic PMTK passthrough in gps_parse()
|
|
|
*/
|
|
|
@@ -424,39 +495,7 @@ void gps_initialize(void) {
|
|
|
System.gps_initialized = GPS_INIT_QUERY_SENT;
|
|
|
break;
|
|
|
case GPS_INIT_QUERY_SENT:
|
|
|
- if (get_flag(CONFFLAG_ENABLE_SBAS)) {
|
|
|
- xfprintf(uart0_put_wrap, PSTR("$PMTK313,1*2E\r\n"));
|
|
|
- xputs_P(PSTR("SBAS enable sent\r\n"));
|
|
|
- } else {
|
|
|
- xfprintf(uart0_put_wrap, PSTR("$PMTK313,0*2F\r\n"));
|
|
|
- xputs_P(PSTR("SBAS disable sent\r\n"));
|
|
|
- }
|
|
|
- if (!System.gps_only) {
|
|
|
- switch (System.conf.gnss_mode) {
|
|
|
- default:
|
|
|
- case GNSS_MODE_GPS_GLONASS_GALILEO:
|
|
|
- xfprintf(uart0_put_wrap, PSTR("$PMTK353,1,1,1,0,0*2A\r\n"));
|
|
|
- break;
|
|
|
- case GNSS_MODE_GPS:
|
|
|
- xfprintf(uart0_put_wrap, PSTR("$PMTK353,1,0,0,0,0*2A\r\n"));
|
|
|
- break;
|
|
|
- case GNSS_MODE_GPS_GALILEO:
|
|
|
- xfprintf(uart0_put_wrap, PSTR("$PMTK353,1,0,1,0,0*2B\r\n"));
|
|
|
- break;
|
|
|
- case GNSS_MODE_GALILEO:
|
|
|
- xfprintf(uart0_put_wrap, PSTR("$PMTK353,0,0,1,0,0*2A\r\n"));
|
|
|
- break;
|
|
|
- case GNSS_MODE_GPS_BEIDOU:
|
|
|
- xfprintf(uart0_put_wrap, PSTR("$PMTK353,1,0,0,0,1*2B\r\n"));
|
|
|
- break;
|
|
|
- case GNSS_MODE_BEIDOU:
|
|
|
- xfprintf(uart0_put_wrap, PSTR("$PMTK353,0,0,0,0,1*2A\r\n"));
|
|
|
- break;
|
|
|
- }
|
|
|
- xputs_P(PSTR("GNSS mode setting sent\r\n"));
|
|
|
- } else {
|
|
|
- System.conf.gnss_mode = GNSS_MODE_GPS;
|
|
|
- }
|
|
|
+ gps_settings_changed();
|
|
|
break;
|
|
|
default:
|
|
|
break;
|