mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-08-02 10:16:11 +00:00
fix(ui): trail elapsed/avg-speed driven by millis(), not RTC
The previous implementation derived "Time" and "Avg speed" from the RTC: first().ts and rtc_clock.getCurrentTime(). When the RTC isn't synced yet (no GPS time fix, no host sync), every point ts is 0, the current time is 0 too, and elapsed stays at 0 — Time never moves and Avg speed reads 0 even with the map filling in. Real-world breakage. Switch the elapsed/avg-speed timebase to millis(): - TrailStore gains _session_start_ms (millis() when the current start→stop window opened) and _accumulated_ms (banked time across previous windows). - setActive(true) records the start; setActive(false) banks the delta into the accumulator. - elapsedSeconds = (_accumulated_ms + active session delta) / 1000. - clear() zeroes both. Per-point ts stays RTC-derived (used for the HH:MM labels in List view where a wallclock is what the user actually wants). TrailScreen drops the now_ts argument it was passing in, and bumps the refresh interval to 1 s while active so the m:ss counter actually ticks every second. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
237dcbf524
commit
178a34d1ec
@@ -42,9 +42,18 @@ public:
|
|||||||
|
|
||||||
bool isActive() const { return _active; }
|
bool isActive() const { return _active; }
|
||||||
void setActive(bool a) {
|
void setActive(bool a) {
|
||||||
// Re-arming after a stop marks the next addPoint as a segment start, so
|
if (a && !_active) {
|
||||||
// the renderer doesn't draw a straight line through the dead time.
|
// off → on: start a new session timer.
|
||||||
if (_active && !a) _pending_seg_break = true;
|
_session_start_ms = millis();
|
||||||
|
} else if (_active && !a) {
|
||||||
|
// on → off: bank the elapsed of this session and arm a segment break
|
||||||
|
// so the renderer doesn't draw a straight line through the dead time.
|
||||||
|
if (_session_start_ms != 0) {
|
||||||
|
_accumulated_ms += millis() - _session_start_ms;
|
||||||
|
_session_start_ms = 0;
|
||||||
|
}
|
||||||
|
_pending_seg_break = true;
|
||||||
|
}
|
||||||
_active = a;
|
_active = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +65,12 @@ public:
|
|||||||
const TrailPoint& first() const { return at(0); }
|
const TrailPoint& first() const { return at(0); }
|
||||||
const TrailPoint& last() const { return at(_count - 1); }
|
const TrailPoint& last() const { return at(_count - 1); }
|
||||||
|
|
||||||
void clear() { _head = 0; _count = 0; _pending_seg_break = false; }
|
void clear() {
|
||||||
|
_head = 0; _count = 0;
|
||||||
|
_pending_seg_break = false;
|
||||||
|
_accumulated_ms = 0;
|
||||||
|
_session_start_ms = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true if the point was stored (passed the min-delta gate).
|
// Returns true if the point was stored (passed the min-delta gate).
|
||||||
// First point of the ring and the first point after a stop/start cycle
|
// First point of the ring and the first point after a stop/start cycle
|
||||||
@@ -96,20 +110,18 @@ public:
|
|||||||
return (uint32_t)d;
|
return (uint32_t)d;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seconds between the first sample and either the most recent sample (when
|
// Cumulative active tracking time across all start→stop sessions, in
|
||||||
// stopped) or the current RTC time passed in by the caller (when active).
|
// seconds. Counts ticks while the trail is on, freezes while it's off.
|
||||||
// Using `now_ts` while active lets the UI advance the displayed time
|
// millis()-based so it doesn't depend on RTC sync.
|
||||||
// smoothly even when samples land on the floor of the min-delta gate.
|
uint32_t elapsedSeconds() const {
|
||||||
uint32_t elapsedSeconds(uint32_t now_ts = 0) const {
|
uint32_t ms = _accumulated_ms;
|
||||||
if (_count == 0) return 0;
|
if (_active && _session_start_ms != 0) ms += millis() - _session_start_ms;
|
||||||
uint32_t start = first().ts;
|
return ms / 1000;
|
||||||
uint32_t end = (_active && now_ts > start) ? now_ts : last().ts;
|
|
||||||
return (end > start) ? (end - start) : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Average speed in km/h = total distance / elapsed time.
|
// Average speed in km/h = total distance / cumulative active time.
|
||||||
uint16_t avgSpeedKmh(uint32_t now_ts = 0) const {
|
uint16_t avgSpeedKmh() const {
|
||||||
uint32_t es = elapsedSeconds(now_ts);
|
uint32_t es = elapsedSeconds();
|
||||||
if (es == 0) return 0;
|
if (es == 0) return 0;
|
||||||
return (uint16_t)((float)totalDistanceMeters() / (float)es * 3.6f);
|
return (uint16_t)((float)totalDistanceMeters() / (float)es * 3.6f);
|
||||||
}
|
}
|
||||||
@@ -147,8 +159,10 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
TrailPoint _buf[CAPACITY];
|
TrailPoint _buf[CAPACITY];
|
||||||
int _head = 0;
|
int _head = 0;
|
||||||
int _count = 0;
|
int _count = 0;
|
||||||
bool _active = false;
|
bool _active = false;
|
||||||
bool _pending_seg_break = false; // next addPoint flags itself SEG_START
|
bool _pending_seg_break = false; // next addPoint flags itself SEG_START
|
||||||
|
uint32_t _accumulated_ms = 0; // banked active time across previous sessions
|
||||||
|
uint32_t _session_start_ms = 0; // millis() of the current active session, 0 if none
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public:
|
|||||||
display.setCursor(2, hint_y);
|
display.setCursor(2, hint_y);
|
||||||
display.print(hint);
|
display.print(hint);
|
||||||
|
|
||||||
return _store->isActive() ? 2000 : 5000;
|
return _store->isActive() ? 1000 : 5000;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handleInput(char c) override {
|
bool handleInput(char c) override {
|
||||||
@@ -107,7 +107,7 @@ private:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: {
|
case 3: {
|
||||||
uint32_t es = _store->elapsedSeconds((uint32_t)rtc_clock.getCurrentTime());
|
uint32_t es = _store->elapsedSeconds();
|
||||||
// Below 1 h show m:ss so the seconds counter updates visibly each refresh.
|
// Below 1 h show m:ss so the seconds counter updates visibly each refresh.
|
||||||
if (es < 3600) snprintf(buf, n, "Time: %lu:%02lu",
|
if (es < 3600) snprintf(buf, n, "Time: %lu:%02lu",
|
||||||
(unsigned long)(es / 60), (unsigned long)(es % 60));
|
(unsigned long)(es / 60), (unsigned long)(es % 60));
|
||||||
@@ -116,8 +116,7 @@ private:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4:
|
case 4:
|
||||||
snprintf(buf, n, "Avg speed: %u km/h",
|
snprintf(buf, n, "Avg speed: %u km/h", (unsigned)_store->avgSpeedKmh());
|
||||||
(unsigned)_store->avgSpeedKmh((uint32_t)rtc_clock.getCurrentTime()));
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
|
|||||||
Reference in New Issue
Block a user