Forráskód Böngészése

Gate and debounce fix acquired/lost logging on completed epochs

Fix events were checked on every main-loop pass regardless of whether
a new epoch's GGA and GSA had actually both been parsed yet, so
sats=/hdop= in the log line could come from a stale epoch. Track epoch
completion (nmea_epoch_complete()) and only evaluate the fix state
then. Also require a state change to persist for FIX_HOLD_EPOCHS
epochs before logging it, so marginal reception flapping between
2D/3D/no-fix for a minute produces at most one or two log lines
instead of one per flip. A newly logged fix-lost event also requests
an immediate sync, since it can precede a real signal/power problem.

Mirrored into gps-test-tool so it exercises the same logging behavior.
k4be 1 hete
szülő
commit
b53f18165c
6 módosított fájl, 64 hozzáadás és 13 törlés
  1. 15 7
      gps-test-tool/main.c
  2. 4 0
      gps-test-tool/main.h
  3. 21 6
      soft/main.c
  4. 3 0
      soft/main.h
  5. 19 0
      soft/nmea.c
  6. 2 0
      soft/nmea.h

+ 15 - 7
gps-test-tool/main.c

@@ -135,7 +135,10 @@ int process_nmea_file(const char *input_file, const char *output_gpx,
     fprintf(debug_output, "Output: %s\n\n", output_gpx);
 
     /* Process NMEA file line by line */
+    /* Kept in sync with soft/main.c's FIX_HOLD_EPOCHS. */
+    #define FIX_HOLD_EPOCHS 5
     unsigned char fix_ok_prev = 0;
+    unsigned char fix_hold_counter = 0;
     unsigned char sbas_prev = 0xFF; /* 0xFF: not yet known, suppress the first (non-)transition */
     time_t next_status_utc = 0;
     time_t next_summary_utc = 0;
@@ -174,13 +177,18 @@ int process_nmea_file(const char *input_file, const char *output_gpx,
          * periodic status line/session summary off the NMEA timestamps
          * instead of uptime. */
         if (utc) {
-            unsigned char fix_ok_now = (FLAGS & F_GPSOK) && !System.sat_count_low;
-            if (fix_ok_now != fix_ok_prev) {
-                if (fix_ok_now)
-                    log_fix_event();
-                else
-                    log_fix_lost();
-                fix_ok_prev = fix_ok_now;
+            if (nmea_epoch_complete()) {
+                unsigned char fix_ok_now = (FLAGS & F_GPSOK) && !System.sat_count_low;
+                if (fix_ok_now == fix_ok_prev) {
+                    fix_hold_counter = 0;
+                } else if (++fix_hold_counter >= FIX_HOLD_EPOCHS) {
+                    fix_hold_counter = 0;
+                    fix_ok_prev = fix_ok_now;
+                    if (fix_ok_now)
+                        log_fix_event();
+                    else
+                        log_fix_lost();
+                }
             }
             if (System.sbas != sbas_prev) {
                 if (sbas_prev != 0xFF)

+ 4 - 0
gps-test-tool/main.h

@@ -240,6 +240,9 @@ struct system_s {
     unsigned sat_count_low:1;
     unsigned sbas:1;
     unsigned satellites_used:5;
+    unsigned epoch_gga_ok:1;
+    unsigned epoch_gsa_ok:1;
+    unsigned epoch_logged:1;
 };
 
 /* Location structure */
@@ -316,6 +319,7 @@ void gps_initialize(void);
 void add_distance(float dist);
 void add_elevation(float ele_change);
 float distance(struct location_s *pos1, struct location_s *pos2);
+unsigned char nmea_epoch_complete(void);
 
 /* The structured system log (soft/syslog.c) is compiled into this test tool
  * too (see syslog_wrapper.c), so its real log_reject()/log_jump()/log_prefix()

+ 21 - 6
soft/main.c

@@ -265,6 +265,12 @@ void beep (UINT len, BYTE cnt)
 	}
 }
 
+/* Number of consecutive epochs (nmea_epoch_complete() pulses) a new
+ * fix-acquired/lost state must hold before it's logged - coalesces the rapid
+ * flapping seen on marginal reception (e.g. 2D/3D/no-fix alternating for
+ * about a minute) into at most one or two log lines instead of one per flip. */
+#define FIX_HOLD_EPOCHS	5
+
 #define LOG_SIZE	300
 
 struct {
@@ -423,6 +429,7 @@ int main (void)
 	unsigned char prev_status;
 	unsigned char already_logging = 0;
 	static unsigned char fix_ok_prev = 0;
+	static unsigned char fix_hold_counter = 0;
 	static unsigned char sbas_prev = 0xFF; /* 0xFF: not yet known, suppress the first (non-)transition */
 	static unsigned long int last_summary_uptime = 0;
 
@@ -542,15 +549,23 @@ int main (void)
 			if (System.bat_volt > 0 && System.bat_volt < System.bat_volt_min)
 				System.bat_volt_min = System.bat_volt;
 
-			/* Fix acquired/lost events (a "fix" requires both a valid GPS status and enough satellites) */
-			{
+			/* Fix acquired/lost events (a "fix" requires both a valid GPS status and enough
+			 * satellites). Gated on nmea_epoch_complete() so sats=/hdop= are never read from a
+			 * stale epoch, and debounced so a single bad epoch on marginal reception doesn't log
+			 * a FIX/FIX LOST pair by itself - the new state must hold for FIX_HOLD_EPOCHS epochs. */
+			if (nmea_epoch_complete()) {
 				unsigned char fix_ok_now = (FLAGS & F_GPSOK) && !System.sat_count_low;
-				if (fix_ok_now != fix_ok_prev) {
-					if (fix_ok_now)
+				if (fix_ok_now == fix_ok_prev) {
+					fix_hold_counter = 0;
+				} else if (++fix_hold_counter >= FIX_HOLD_EPOCHS) {
+					fix_hold_counter = 0;
+					fix_ok_prev = fix_ok_now;
+					if (fix_ok_now) {
 						log_fix_event();
-					else
+					} else {
 						log_fix_lost();
-					fix_ok_prev = fix_ok_now;
+						request_immediate_sync();
+					}
 				}
 			}
 

+ 3 - 0
soft/main.h

@@ -214,6 +214,9 @@ struct system_s {
 	unsigned tracking_auto_paused:1;
 	unsigned open_new_file:1;
 	unsigned sat_count_low:1;
+	unsigned epoch_gga_ok:1; // set once GGA has been parsed for the current epoch (since the last RMC)
+	unsigned epoch_gsa_ok:1; // set once GSA has been parsed for the current epoch (since the last RMC)
+	unsigned epoch_logged:1; // set once nmea_epoch_complete() has fired for the current epoch
 };
 
 struct location_s {

+ 19 - 0
soft/nmea.c

@@ -156,6 +156,10 @@ 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;
+
 	p = gp_col(str, 1);		/* Get h:m:s */
 	if (!p)
 		return 0;
@@ -202,6 +206,7 @@ static void gp_gga_parse(const char *str) {
 
 	p = gp_col(str, 7); /* satellites used */
 	System.satellites_used = atoi(p);
+	System.epoch_gga_ok = 1;
 
 	if (System.satellites_used >= System.conf.min_sats) {
 		System.sat_count_low = 0;
@@ -284,6 +289,20 @@ 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;
+}
+
+/* Returns 1 exactly once per epoch (the moment both GGA and GSA have been
+ * parsed for it, whichever arrives second), so callers that need this
+ * epoch's satellite count and HDOP together (e.g. logging a fix event) never
+ * 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;
+		return 1;
+	}
+	return 0;
 }
 
 /*$PMTK355*31<CR><LF>

+ 2 - 0
soft/nmea.h

@@ -7,4 +7,6 @@ UINT get_line(char *buff, UINT sz_buf);
 void gps_initialize(void);
 void check_min_sat_limit(void);
 unsigned char gps_fix_trustworthy(void);
+unsigned char nmea_epoch_complete(void);
+unsigned char nmea_epoch_complete(void);