| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- /*
- * 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;
- }
|