InfiniTime.git

commit 67e0cad5733c6d3201f1414b89c8faf568dcb2bd

Author: Riku Isokoski <riksu9000@gmail.com>

Simplified stopwatch lap buffer

Overriding the earlier laps doesn't seem like a good idea.

 src/displayapp/screens/StopWatch.cpp | 62 ++++++++++-------------------
 src/displayapp/screens/StopWatch.h | 58 +++------------------------


diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp
index 614b21eaebb35d76a1abfa38cf31de42bed2c444..e705fcb0bf9748eda587d6a2ddecc0b378479c59 100644
--- a/src/displayapp/screens/StopWatch.cpp
+++ b/src/displayapp/screens/StopWatch.cpp
@@ -1,10 +1,6 @@
 #include "displayapp/screens/StopWatch.h"
 
-#include "displayapp/screens/Screen.h"
 #include "displayapp/screens/Symbols.h"
-#include <lvgl/lvgl.h>
-#include <FreeRTOS.h>
-#include <task.h>
 
 using namespace Pinetime::Applications::Screens;
 
@@ -30,15 +26,7 @@     stopWatch->stopLapBtnEventHandler(event);
   }
 }
 
-StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask)
-  : Screen(app),
-    systemTask {systemTask},
-    currentState {States::Init},
-    startTime {},
-    oldTimeElapsed {},
-    currentTimeSeparated {},
-    lapBuffer {},
-    lapNr {} {
+StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask) : Screen(app), systemTask {systemTask} {
 
   time = lv_label_create(lv_scr_act(), nullptr);
   lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76);
@@ -70,15 +58,10 @@   lv_label_set_text_static(txtStopLap, Symbols::stop);
   lv_obj_set_state(btnStopLap, LV_STATE_DISABLED);
   lv_obj_set_state(txtStopLap, LV_STATE_DISABLED);
 
-  lapOneText = lv_label_create(lv_scr_act(), nullptr);
-  lv_obj_set_style_local_text_color(lapOneText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
-  lv_obj_align(lapOneText, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 50, 30);
-  lv_label_set_text_static(lapOneText, "");
-
-  lapTwoText = lv_label_create(lv_scr_act(), nullptr);
-  lv_obj_set_style_local_text_color(lapTwoText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
-  lv_obj_align(lapTwoText, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 50, 55);
-  lv_label_set_text_static(lapTwoText, "");
+  lapText = lv_label_create(lv_scr_act(), nullptr);
+  lv_obj_set_style_local_text_color(lapText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
+  lv_obj_align(lapText, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 50, 30);
+  lv_label_set_text_static(lapText, "");
 
   taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
 }
@@ -98,10 +81,8 @@
   lv_label_set_text_static(time, "00:00");
   lv_label_set_text_static(msecTime, "00");
 
-  lv_label_set_text_static(lapOneText, "");
-  lv_label_set_text_static(lapTwoText, "");
-  lapBuffer.clearBuffer();
-  lapNr = 0;
+  lv_label_set_text_static(lapText, "");
+  lapsDone = 0;
   lv_obj_set_state(btnStopLap, LV_STATE_DISABLED);
   lv_obj_set_state(txtStopLap, LV_STATE_DISABLED);
 }
@@ -121,7 +102,7 @@
 void StopWatch::Pause() {
   startTime = 0;
   // Store the current time elapsed in cache
-  oldTimeElapsed += timeElapsed;
+  oldTimeElapsed = laps[lapsDone];
   currentState = States::Halted;
   lv_label_set_text_static(txtPlayPause, Symbols::play);
   lv_label_set_text_static(txtStopLap, Symbols::stop);
@@ -132,9 +113,9 @@ }
 
 void StopWatch::Refresh() {
   if (currentState == States::Running) {
-    timeElapsed = xTaskGetTickCount() - startTime;
-    currentTimeSeparated = convertTicksToTimeSegments((oldTimeElapsed + timeElapsed));
+    laps[lapsDone] = oldTimeElapsed + xTaskGetTickCount() - startTime;
 
+    TimeSeparated_t currentTimeSeparated = convertTicksToTimeSegments(laps[lapsDone]);
     lv_label_set_text_fmt(time, "%02d:%02d", currentTimeSeparated.mins, currentTimeSeparated.secs);
     lv_label_set_text_fmt(msecTime, "%02d", currentTimeSeparated.hundredths);
   }
@@ -159,18 +140,17 @@     return;
   }
   // If running, then this button is used to save laps
   if (currentState == States::Running) {
-    lapBuffer.addLaps(currentTimeSeparated);
-    lapNr++;
-    if (lapBuffer[1]) {
-      lv_label_set_text_fmt(lapOneText,
-                            "#%2d   %2d:%02d.%02d",
-                            (lapNr - 1),
-                            lapBuffer[1]->mins,
-                            lapBuffer[1]->secs,
-                            lapBuffer[1]->hundredths);
-    }
-    if (lapBuffer[0]) {
-      lv_label_set_text_fmt(lapTwoText, "#%2d   %2d:%02d.%02d", lapNr, lapBuffer[0]->mins, lapBuffer[0]->secs, lapBuffer[0]->hundredths);
+    lv_label_set_text(lapText, "");
+    lapsDone = std::min(lapsDone + 1, maxLapCount);
+    for (int i = lapsDone - displayedLaps; i < lapsDone; i++) {
+      if (i < 0) {
+        lv_label_ins_text(lapText, LV_LABEL_POS_LAST, "\n");
+        continue;
+      }
+      TimeSeparated_t times = convertTicksToTimeSegments(laps[i]);
+      char buffer[16];
+      sprintf(buffer, "#%2d   %2d:%02d.%02d\n", i + 1, times.mins, times.secs, times.hundredths);
+      lv_label_ins_text(lapText, LV_LABEL_POS_LAST, buffer);
     }
   } else if (currentState == States::Halted) {
     Reset();




diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h
index ef55e2d208bcc7913205e4536e5df58b577ab53c..f2f57110b07d566550402212897fe482351d593e 100644
--- a/src/displayapp/screens/StopWatch.h
+++ b/src/displayapp/screens/StopWatch.h
@@ -1,13 +1,11 @@
 #pragma once
 
 #include "displayapp/screens/Screen.h"
-#include "components/datetime/DateTimeController.h"
-#include "displayapp/LittleVgl.h"
+#include <lvgl/lvgl.h>
 
 #include <FreeRTOS.h>
 #include "portmacro_cmsis.h"
 
-#include <array>
 #include "systemtask/SystemTask.h"
 
 namespace Pinetime::Applications::Screens {
@@ -20,46 +18,6 @@     int secs;
     int hundredths;
   };
 
-  // A simple buffer to hold the latest two laps
-  template <int N> struct LapTextBuffer_t {
-    LapTextBuffer_t() : buffer {}, currentSize {}, capacity {N}, head {-1} {
-    }
-
-    void addLaps(const TimeSeparated_t& timeVal) {
-      head++;
-      head %= capacity;
-      buffer[head] = timeVal;
-
-      if (currentSize < capacity) {
-        currentSize++;
-      }
-    }
-
-    void clearBuffer() {
-      buffer = {};
-      currentSize = 0;
-      head = -1;
-    }
-
-    TimeSeparated_t* operator[](std::size_t idx) {
-      // Sanity check for out-of-bounds
-      if (idx >= 0 && idx < capacity) {
-        if (idx < currentSize) {
-          // This transformation is to ensure that head is always pointing to index 0.
-          const auto transformed_idx = (head - idx) % capacity;
-          return (&buffer[transformed_idx]);
-        }
-      }
-      return nullptr;
-    }
-
-  private:
-    std::array<TimeSeparated_t, N> buffer;
-    uint8_t currentSize;
-    uint8_t capacity;
-    int8_t head;
-  };
-
   class StopWatch : public Screen {
   public:
     StopWatch(DisplayApp* app, System::SystemTask& systemTask);
@@ -76,15 +34,15 @@     void Pause();
 
   private:
     Pinetime::System::SystemTask& systemTask;
-    TickType_t timeElapsed;
-    States currentState;
+    States currentState = States::Init;
     TickType_t startTime;
-    TickType_t oldTimeElapsed;
-    TimeSeparated_t currentTimeSeparated; // Holds Mins, Secs, millisecs
-    LapTextBuffer_t<2> lapBuffer;
-    int lapNr = 0;
+    TickType_t oldTimeElapsed = 0;
+    static constexpr int maxLapCount = 20;
+    TickType_t laps[maxLapCount + 1];
+    static constexpr int displayedLaps = 2;
+    int lapsDone = 0;
     lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap;
-    lv_obj_t *lapOneText, *lapTwoText;
+    lv_obj_t* lapText;
 
     lv_task_t* taskRefresh;
   };