autopause.c 3.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. * Auto-pause detection: shared between the firmware and gps-test-tool (see
  3. * autopause_wrapper.c), since it directly gates what ends up in
  4. * System.distance/elevation_gain/elevation_loss (excluded while paused) and
  5. * is a major part of what those tools' output actually looks like.
  6. */
  7. #ifdef PC_BUILD
  8. #include "../gps-test-tool/main.h"
  9. #else
  10. #include "main.h"
  11. #endif
  12. struct auto_pause_s auto_pause;
  13. /* Resuming from a period of auto-pause because of apparent distance needs
  14. * more apparent movement than triggering the pause did in the first place:
  15. * position noise while genuinely stationary (multipath, poor sky view) can
  16. * still occasionally clear the plain auto_pause_dist threshold over enough
  17. * auto_pause_time windows, and unlike a false pause (which just costs one
  18. * quiet window before the speed-based check or the next window catches the
  19. * resume), a false resume pollutes the moving/stopped split and the
  20. * odometer for as long as it isn't caught. */
  21. #define AUTO_PAUSE_RESUME_DIST_MULT_X100 150 /* 1.5x the configured distance threshold */
  22. static void auto_unpause(void) {
  23. if (!System.tracking_auto_paused)
  24. return;
  25. System.tracking_auto_paused = 0;
  26. log_pause_event(0);
  27. beep(50, 4);
  28. }
  29. static void auto_pause_activate(void) {
  30. System.tracking_auto_paused = 1;
  31. /* Otherwise, speed-counter progress from just before this decision (e.g.
  32. * 2 of the 3 consecutive above-threshold samples the resume check below
  33. * wants) could carry over and complete on the very next sample,
  34. * instantly flip-flopping straight back out of the pause this just
  35. * activated. */
  36. auto_pause.speed_counter = 0;
  37. log_pause_event(1);
  38. beep(50, 3);
  39. }
  40. void auto_pause_process(void) {
  41. if (System.tracking_paused || !get_flag(CONFFLAG_AUTO_PAUSE)) { /* remove auto-pause */
  42. System.tracking_auto_paused = 0;
  43. auto_pause.prev_distance = System.distance;
  44. auto_pause.point_counter = 0;
  45. auto_pause.speed_counter = 0;
  46. return;
  47. }
  48. /* A poor/invalid fix must not be read as "moving": a single noisy sample
  49. * (e.g. a low-satellite, high-HDOP fix briefly reporting tens of km/h,
  50. * as seen on a real hike where reception dropped for a few seconds)
  51. * could otherwise satisfy the "3 consecutive" debounce below on its own
  52. * and resume a logger that is actually sitting still. Such a sample is
  53. * simply ignored - neither counted towards, nor resetting, the
  54. * consecutive-samples debounce - so it can't itself trigger a resume,
  55. * but also can't erase real progress made by genuine movement. */
  56. if (gps_fix_trustworthy()) {
  57. if (System.speed >= System.conf.auto_pause_speed) { /* unpause when set speed is exceeded for 3 consecutive measurements */
  58. if (++auto_pause.speed_counter >= 3) {
  59. auto_pause.point_counter = 0;
  60. auto_pause.speed_counter = 0;
  61. auto_unpause();
  62. return;
  63. }
  64. } else {
  65. auto_pause.speed_counter = 0;
  66. }
  67. }
  68. if (++auto_pause.point_counter < System.conf.auto_pause_time)
  69. return;
  70. auto_pause.point_counter = 0;
  71. if (System.tracking_auto_paused) {
  72. unsigned long int resume_threshold = (unsigned long int)System.conf.auto_pause_dist
  73. * AUTO_PAUSE_RESUME_DIST_MULT_X100 / 100;
  74. if ((System.distance - auto_pause.prev_distance)/100 > resume_threshold)
  75. auto_unpause(); /* unpause when distance exceeded */
  76. } else {
  77. /* Net displacement over this window can be small even while genuinely
  78. * moving throughout it - a winding path folding back on itself, or a
  79. * short out-and-back - and pausing on that alone, only to have the
  80. * very next sample or two immediately satisfy the speed-based resume
  81. * above, is itself a spurious (if brief) pause. If the logger is
  82. * already moving fast enough to resume on its own right now, don't
  83. * pause it in the first place. */
  84. if ((System.distance - auto_pause.prev_distance)/100 <= System.conf.auto_pause_dist
  85. && System.speed < System.conf.auto_pause_speed)
  86. auto_pause_activate(); /* pause: not enough net movement, and not currently moving fast */
  87. }
  88. auto_pause.prev_distance = System.distance;
  89. }