/* * Auto-pause detection: shared between the firmware and gps-test-tool (see * autopause_wrapper.c), since it directly gates what ends up in * System.distance/elevation_gain/elevation_loss (excluded while paused) and * is a major part of what those tools' output actually looks like. */ #ifdef PC_BUILD #include "../gps-test-tool/main.h" #else #include "main.h" #endif struct auto_pause_s auto_pause; /* Resuming from a period of auto-pause because of apparent distance needs * more apparent movement than triggering the pause did in the first place: * position noise while genuinely stationary (multipath, poor sky view) can * still occasionally clear the plain auto_pause_dist threshold over enough * auto_pause_time windows, and unlike a false pause (which just costs one * quiet window before the speed-based check or the next window catches the * resume), a false resume pollutes the moving/stopped split and the * odometer for as long as it isn't caught. */ #define AUTO_PAUSE_RESUME_DIST_MULT_X100 150 /* 1.5x the configured distance threshold */ static void auto_unpause(void) { if (!System.tracking_auto_paused) return; System.tracking_auto_paused = 0; log_pause_event(0); beep(50, 4); } static void auto_pause_activate(void) { System.tracking_auto_paused = 1; /* Otherwise, speed-counter progress from just before this decision (e.g. * 2 of the 3 consecutive above-threshold samples the resume check below * wants) could carry over and complete on the very next sample, * instantly flip-flopping straight back out of the pause this just * activated. */ auto_pause.speed_counter = 0; log_pause_event(1); beep(50, 3); } void auto_pause_process(void) { if (System.tracking_paused || !get_flag(CONFFLAG_AUTO_PAUSE)) { /* remove auto-pause */ System.tracking_auto_paused = 0; auto_pause.prev_distance = System.distance; auto_pause.point_counter = 0; auto_pause.speed_counter = 0; return; } /* A poor/invalid fix must not be read as "moving": a single noisy sample * (e.g. a low-satellite, high-HDOP fix briefly reporting tens of km/h, * as seen on a real hike where reception dropped for a few seconds) * could otherwise satisfy the "3 consecutive" debounce below on its own * and resume a logger that is actually sitting still. Such a sample is * simply ignored - neither counted towards, nor resetting, the * consecutive-samples debounce - so it can't itself trigger a resume, * but also can't erase real progress made by genuine movement. */ if (gps_fix_trustworthy()) { if (System.speed >= System.conf.auto_pause_speed) { /* unpause when set speed is exceeded for 3 consecutive measurements */ if (++auto_pause.speed_counter >= 3) { auto_pause.point_counter = 0; auto_pause.speed_counter = 0; auto_unpause(); return; } } else { auto_pause.speed_counter = 0; } } if (++auto_pause.point_counter < System.conf.auto_pause_time) return; auto_pause.point_counter = 0; if (System.tracking_auto_paused) { unsigned long int resume_threshold = (unsigned long int)System.conf.auto_pause_dist * AUTO_PAUSE_RESUME_DIST_MULT_X100 / 100; if ((System.distance - auto_pause.prev_distance)/100 > resume_threshold) auto_unpause(); /* unpause when distance exceeded */ } else { /* Net displacement over this window can be small even while genuinely * moving throughout it - a winding path folding back on itself, or a * short out-and-back - and pausing on that alone, only to have the * very next sample or two immediately satisfy the speed-based resume * above, is itself a spurious (if brief) pause. If the logger is * already moving fast enough to resume on its own right now, don't * pause it in the first place. */ if ((System.distance - auto_pause.prev_distance)/100 <= System.conf.auto_pause_dist && System.speed < System.conf.auto_pause_speed) auto_pause_activate(); /* pause: not enough net movement, and not currently moving fast */ } auto_pause.prev_distance = System.distance; }