From 85f673ab68d5297b18c6e13e2cff95348da31ff8 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Wed, 25 Aug 2021 17:56:29 +0300 Subject: [PATCH 1/4] Add new lap buffer to Stopwatch --- src/displayapp/screens/StopWatch.cpp | 150 +++++++++++++-------------- src/displayapp/screens/StopWatch.h | 112 +++++++------------- 2 files changed, 109 insertions(+), 153 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 8749839f7d..39a487f711 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -1,14 +1,8 @@ #include "displayapp/screens/StopWatch.h" - -#include "displayapp/screens/Screen.h" #include "displayapp/screens/Symbols.h" -#include -#include -#include using namespace Pinetime::Applications::Screens; -// Anonymous namespace for local functions namespace { TimeSeparated_t convertTicksToTimeSegments(const TickType_t timeElapsed) { const int timeElapsedMillis = (static_cast(timeElapsed) / static_cast(configTICK_RATE_HZ)) * 1000; @@ -19,38 +13,18 @@ namespace { return TimeSeparated_t {mins, secs, hundredths}; } - TickType_t calculateDelta(const TickType_t startTime, const TickType_t currentTime) { - TickType_t delta = 0; - // Take care of overflow - if (startTime > currentTime) { - delta = 0xffffffff - startTime; - delta += (currentTime + 1); - } else { - delta = currentTime - startTime; - } - return delta; + void play_pause_event_handler(lv_obj_t* obj, lv_event_t event) { + auto* stopWatch = static_cast(obj->user_data); + stopWatch->playPauseBtnEventHandler(event); } -} - -static void play_pause_event_handler(lv_obj_t* obj, lv_event_t event) { - auto stopWatch = static_cast(obj->user_data); - stopWatch->playPauseBtnEventHandler(event); -} -static void stop_lap_event_handler(lv_obj_t* obj, lv_event_t event) { - auto stopWatch = static_cast(obj->user_data); - stopWatch->stopLapBtnEventHandler(event); + void stop_lap_event_handler(lv_obj_t* obj, lv_event_t event) { + auto* stopWatch = static_cast(obj->user_data); + 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); @@ -67,8 +41,7 @@ StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask) btnPlayPause = lv_btn_create(lv_scr_act(), nullptr); btnPlayPause->user_data = this; lv_obj_set_event_cb(btnPlayPause, play_pause_event_handler); - lv_obj_set_height(btnPlayPause, 50); - lv_obj_set_width(btnPlayPause, 115); + lv_obj_set_size(btnPlayPause, 115, 50); lv_obj_align(btnPlayPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); txtPlayPause = lv_label_create(btnPlayPause, nullptr); lv_label_set_text(txtPlayPause, Symbols::play); @@ -76,8 +49,7 @@ StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask) btnStopLap = lv_btn_create(lv_scr_act(), nullptr); btnStopLap->user_data = this; lv_obj_set_event_cb(btnStopLap, stop_lap_event_handler); - lv_obj_set_height(btnStopLap, 50); - lv_obj_set_width(btnStopLap, 115); + lv_obj_set_size(btnStopLap, 115, 50); lv_obj_align(btnStopLap, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); lv_obj_set_style_local_bg_color(btnStopLap, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x080808)); txtStopLap = lv_label_create(btnStopLap, nullptr); @@ -86,17 +58,10 @@ StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask) 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_font(lapOneText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); - 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(lapOneText, ""); - - lapTwoText = lv_label_create(lv_scr_act(), nullptr); - // lv_obj_set_style_local_text_font(lapTwoText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); - 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(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_TOP_LEFT, 0, 72); + lv_label_set_text(lapText, ""); taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); } @@ -107,24 +72,21 @@ StopWatch::~StopWatch() { lv_obj_clean(lv_scr_act()); } -void StopWatch::reset() { +void StopWatch::Reset() { currentState = States::Init; oldTimeElapsed = 0; lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); - lv_label_set_text(time, "00:00"); - lv_label_set_text(msecTime, "00"); - - lv_label_set_text(lapOneText, ""); - lv_label_set_text(lapTwoText, ""); - lapBuffer.clearBuffer(); - lapNr = 0; + lv_label_set_text(lapText, ""); + savedLapsCount = 0; lv_obj_set_state(btnStopLap, LV_STATE_DISABLED); lv_obj_set_state(txtStopLap, LV_STATE_DISABLED); + + SetTime(0); } -void StopWatch::start() { +void StopWatch::Start() { lv_obj_set_state(btnStopLap, LV_STATE_DEFAULT); lv_obj_set_state(txtStopLap, LV_STATE_DEFAULT); lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN); @@ -136,10 +98,10 @@ void StopWatch::start() { systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); } -void StopWatch::pause() { +void StopWatch::Pause() { startTime = 0; // Store the current time elapsed in cache - oldTimeElapsed += timeElapsed; + oldTimeElapsed = lapTimes[savedLapsCount]; currentState = States::Halted; lv_label_set_text(txtPlayPause, Symbols::play); lv_label_set_text(txtStopLap, Symbols::stop); @@ -148,13 +110,50 @@ void StopWatch::pause() { systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); } +void StopWatch::DisplayLaps(uint8_t startLap) { + char buffer[22]; + std::string allLapsText = ""; + TimeSeparated_t lapTime; + TimeSeparated_t runTime; + for (uint8_t i = startLap; i < savedLapsCount && i < startLap + 5 && i < maxLapCount; i++) { + runTime = convertTicksToTimeSegments(lapTimes[i]); + if (i > 0) { + lapTime = convertTicksToTimeSegments(lapTimes[i] - lapTimes[i - 1]); + } else { + lapTime = runTime; + } + sprintf(buffer, + "#%d %d:%02d.%02d %d:%02d.%02d\n", + i + 1, + lapTime.mins, + lapTime.secs, + lapTime.hundredths, + runTime.mins, + runTime.secs, + runTime.hundredths); + + allLapsText.append(buffer); + } + lv_label_set_text(lapText, allLapsText.c_str()); +} + +void StopWatch::SetTime(TickType_t timeToSet) { + TimeSeparated_t currentTimeSeparated = convertTicksToTimeSegments(timeToSet); + + lv_label_set_text_fmt(time, "%02d:%02d", currentTimeSeparated.mins, currentTimeSeparated.secs); + lv_label_set_text_fmt(msecTime, "%02d", currentTimeSeparated.hundredths); + + if (savedLapsCount > 0) { + lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); + } else { + lv_obj_align(time, lv_scr_act(), LV_ALIGN_CENTER, 0, -45); + } +} + void StopWatch::Refresh() { if (currentState == States::Running) { - timeElapsed = calculateDelta(startTime, xTaskGetTickCount()); - currentTimeSeparated = convertTicksToTimeSegments((oldTimeElapsed + timeElapsed)); - - lv_label_set_text_fmt(time, "%02d:%02d", currentTimeSeparated.mins, currentTimeSeparated.secs); - lv_label_set_text_fmt(msecTime, "%02d", currentTimeSeparated.hundredths); + lapTimes[savedLapsCount] = oldTimeElapsed + xTaskGetTickCount() - startTime; + SetTime(lapTimes[savedLapsCount]); } } @@ -163,11 +162,11 @@ void StopWatch::playPauseBtnEventHandler(lv_event_t event) { return; } if (currentState == States::Init) { - start(); + Start(); } else if (currentState == States::Running) { - pause(); + Pause(); } else if (currentState == States::Halted) { - start(); + Start(); } } @@ -177,23 +176,18 @@ void StopWatch::stopLapBtnEventHandler(lv_event_t event) { } // 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); + if (savedLapsCount < maxLapCount) { + savedLapsCount++; } + DisplayLaps(std::max(savedLapsCount - 5, 0)); } else if (currentState == States::Halted) { - reset(); + Reset(); } } bool StopWatch::OnButtonPushed() { if (currentState == States::Running) { - pause(); + Pause(); return true; } return false; diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index 06193f6886..30c46f329e 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -1,91 +1,53 @@ #pragma once #include "displayapp/screens/Screen.h" -#include "components/datetime/DateTimeController.h" -#include "displayapp/LittleVgl.h" - -#include -#include "portmacro_cmsis.h" - -#include +#include "lvgl/lvgl.h" #include "systemtask/SystemTask.h" -namespace Pinetime::Applications::Screens { - - enum class States { Init, Running, Halted }; - - struct TimeSeparated_t { - int mins; - int secs; - int hundredths; - }; - - // A simple buffer to hold the latest two laps - template struct LapTextBuffer_t { - LapTextBuffer_t() : buffer {}, currentSize {}, capacity {N}, head {-1} { - } +namespace Pinetime { + namespace Applications { + namespace Screens { - void addLaps(const TimeSeparated_t& timeVal) { - head++; - head %= capacity; - buffer[head] = timeVal; + enum class States { Init, Running, Halted }; - if (currentSize < capacity) { - currentSize++; - } - } + struct TimeSeparated_t { + int mins; + int secs; + int hundredths; + }; - void clearBuffer() { - buffer = {}; - currentSize = 0; - head = -1; - } + class StopWatch : public Screen { + public: + StopWatch(DisplayApp* app, System::SystemTask& systemTask); + ~StopWatch() override; + void Refresh() override; - 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; - } + void playPauseBtnEventHandler(lv_event_t event); + void stopLapBtnEventHandler(lv_event_t event); + bool OnButtonPushed() override; + void BackgroundEventHandler(lv_event_t event); - private: - std::array buffer; - uint8_t currentSize; - uint8_t capacity; - int8_t head; - }; + private: + void DisplayLaps(uint8_t startLap); + void SetTime(TickType_t timeToSet); - class StopWatch : public Screen { - public: - StopWatch(DisplayApp* app, System::SystemTask& systemTask); - ~StopWatch() override; - void Refresh() override; + void Reset(); + void Start(); + void Pause(); - void playPauseBtnEventHandler(lv_event_t event); - void stopLapBtnEventHandler(lv_event_t event); - bool OnButtonPushed() override; + Pinetime::System::SystemTask& systemTask; + States currentState = States::Init; + TickType_t startTime; + TickType_t oldTimeElapsed = 0; - void reset(); - void start(); - void pause(); + static constexpr uint8_t maxLapCount = 20; + TickType_t lapTimes[maxLapCount + 1] = {0}; - private: - Pinetime::System::SystemTask& systemTask; - TickType_t timeElapsed; - States currentState; - TickType_t startTime; - TickType_t oldTimeElapsed; - TimeSeparated_t currentTimeSeparated; // Holds Mins, Secs, millisecs - LapTextBuffer_t<2> lapBuffer; - int lapNr = 0; - lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap; - lv_obj_t *lapOneText, *lapTwoText; + uint8_t savedLapsCount = 0; - lv_task_t* taskRefresh; - }; + lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap; + lv_obj_t* lapText; + }; + } + } } From f324e3a2373f030907c69d412dc8cbd181a29713 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Wed, 25 Aug 2021 18:34:17 +0300 Subject: [PATCH 2/4] Improve Stopwatch laps --- src/displayapp/screens/StopWatch.cpp | 83 ++++++++++++++++++---------- src/displayapp/screens/StopWatch.h | 11 ++-- 2 files changed, 59 insertions(+), 35 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 39a487f711..c5f782b399 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -5,11 +5,11 @@ using namespace Pinetime::Applications::Screens; namespace { TimeSeparated_t convertTicksToTimeSegments(const TickType_t timeElapsed) { - const int timeElapsedMillis = (static_cast(timeElapsed) / static_cast(configTICK_RATE_HZ)) * 1000; + TickType_t timeElapsedCentis = timeElapsed * 100 / configTICK_RATE_HZ; - const int hundredths = (timeElapsedMillis % 1000) / 10; // Get only the first two digits and ignore the last - const int secs = (timeElapsedMillis / 1000) % 60; - const int mins = (timeElapsedMillis / 1000) / 60; + const uint8_t hundredths = (timeElapsedCentis % 100); + const uint8_t secs = (timeElapsedCentis / 100) % 60; + const uint32_t mins = (timeElapsedCentis / 100) / 60; return TimeSeparated_t {mins, secs, hundredths}; } @@ -33,7 +33,6 @@ StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask) : Screen(a lv_obj_align(time, lv_scr_act(), LV_ALIGN_CENTER, 0, -45); msecTime = lv_label_create(lv_scr_act(), nullptr); - // lv_obj_set_style_local_text_font(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); lv_label_set_text(msecTime, "00"); lv_obj_align(msecTime, lv_scr_act(), LV_ALIGN_CENTER, 0, 3); @@ -43,8 +42,7 @@ StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask) : Screen(a lv_obj_set_event_cb(btnPlayPause, play_pause_event_handler); lv_obj_set_size(btnPlayPause, 115, 50); lv_obj_align(btnPlayPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); - txtPlayPause = lv_label_create(btnPlayPause, nullptr); - lv_label_set_text(txtPlayPause, Symbols::play); + lv_obj_set_style_local_value_str(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::play); btnStopLap = lv_btn_create(lv_scr_act(), nullptr); btnStopLap->user_data = this; @@ -52,14 +50,13 @@ StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask) : Screen(a lv_obj_set_size(btnStopLap, 115, 50); lv_obj_align(btnStopLap, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); lv_obj_set_style_local_bg_color(btnStopLap, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x080808)); - txtStopLap = lv_label_create(btnStopLap, nullptr); - lv_obj_set_style_local_text_color(txtStopLap, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x888888)); - lv_label_set_text(txtStopLap, Symbols::stop); + lv_obj_set_style_local_text_color(btnStopLap, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x888888)); + lv_obj_set_style_local_value_str(btnStopLap, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::stop); + lv_obj_set_style_local_value_str(btnStopLap, LV_BTN_PART_MAIN, LV_STATE_DISABLED, Symbols::stop); lv_obj_set_state(btnStopLap, LV_STATE_DISABLED); - lv_obj_set_state(txtStopLap, LV_STATE_DISABLED); 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_set_style_local_text_color(lapText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_SILVER); lv_obj_align(lapText, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, 72); lv_label_set_text(lapText, ""); @@ -75,27 +72,33 @@ StopWatch::~StopWatch() { void StopWatch::Reset() { currentState = States::Init; oldTimeElapsed = 0; + lv_obj_set_hidden(msecTime, false); lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); lv_label_set_text(lapText, ""); savedLapsCount = 0; + displayedLapsStart = 0; lv_obj_set_state(btnStopLap, LV_STATE_DISABLED); - lv_obj_set_state(txtStopLap, LV_STATE_DISABLED); + lv_obj_align(time, lv_scr_act(), LV_ALIGN_CENTER, 0, -45); SetTime(0); } void StopWatch::Start() { lv_obj_set_state(btnStopLap, LV_STATE_DEFAULT); - lv_obj_set_state(txtStopLap, LV_STATE_DEFAULT); + lv_obj_set_style_local_value_str(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::pause); + lv_obj_set_style_local_value_str(btnStopLap, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::lapsFlag); + lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN); lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN); - lv_label_set_text(txtPlayPause, Symbols::pause); - lv_label_set_text(txtStopLap, Symbols::lapsFlag); + startTime = xTaskGetTickCount(); currentState = States::Running; systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); + + displayedLapsStart = std::max(savedLapsCount - 5, 0); + DisplayLaps(displayedLapsStart); } void StopWatch::Pause() { @@ -103,10 +106,13 @@ void StopWatch::Pause() { // Store the current time elapsed in cache oldTimeElapsed = lapTimes[savedLapsCount]; currentState = States::Halted; - lv_label_set_text(txtPlayPause, Symbols::play); - lv_label_set_text(txtStopLap, Symbols::stop); + + lv_obj_set_style_local_value_str(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::play); + lv_obj_set_style_local_value_str(btnStopLap, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::stop); + lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); + systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); } @@ -123,14 +129,14 @@ void StopWatch::DisplayLaps(uint8_t startLap) { lapTime = runTime; } sprintf(buffer, - "#%d %d:%02d.%02d %d:%02d.%02d\n", + "#%-2d %2d:%02d.%1d %2d:%02d.%1d\n", i + 1, - lapTime.mins, + std::min(lapTime.mins, 99), lapTime.secs, - lapTime.hundredths, - runTime.mins, + lapTime.hundredths / 10, + std::min(runTime.mins, 99), runTime.secs, - runTime.hundredths); + runTime.hundredths / 10); allLapsText.append(buffer); } @@ -142,12 +148,6 @@ void StopWatch::SetTime(TickType_t timeToSet) { lv_label_set_text_fmt(time, "%02d:%02d", currentTimeSeparated.mins, currentTimeSeparated.secs); lv_label_set_text_fmt(msecTime, "%02d", currentTimeSeparated.hundredths); - - if (savedLapsCount > 0) { - lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); - } else { - lv_obj_align(time, lv_scr_act(), LV_ALIGN_CENTER, 0, -45); - } } void StopWatch::Refresh() { @@ -179,7 +179,10 @@ void StopWatch::stopLapBtnEventHandler(lv_event_t event) { if (savedLapsCount < maxLapCount) { savedLapsCount++; } - DisplayLaps(std::max(savedLapsCount - 5, 0)); + lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); + lv_obj_set_hidden(msecTime, true); + displayedLapsStart = std::max(savedLapsCount - 5, 0); + DisplayLaps(displayedLapsStart); } else if (currentState == States::Halted) { Reset(); } @@ -192,3 +195,23 @@ bool StopWatch::OnButtonPushed() { } return false; } + +bool StopWatch::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + if (currentState != States::Halted) { + return false; + } + + switch (event) { + case TouchEvents::SwipeUp: + displayedLapsStart = std::min({displayedLapsStart + 5, maxLapCount - 5, savedLapsCount - 5}); + break; + case TouchEvents::SwipeDown: + displayedLapsStart = std::max(displayedLapsStart - 5, 0); + break; + default: + return false; + } + DisplayLaps(displayedLapsStart); + + return true; +} diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index 30c46f329e..e72d1ca01f 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -11,9 +11,9 @@ namespace Pinetime { enum class States { Init, Running, Halted }; struct TimeSeparated_t { - int mins; - int secs; - int hundredths; + uint32_t mins; + uint8_t secs; + uint8_t hundredths; }; class StopWatch : public Screen { @@ -25,7 +25,7 @@ namespace Pinetime { void playPauseBtnEventHandler(lv_event_t event); void stopLapBtnEventHandler(lv_event_t event); bool OnButtonPushed() override; - void BackgroundEventHandler(lv_event_t event); + bool OnTouchEvent(Pinetime::Applications::TouchEvents event) override; private: void DisplayLaps(uint8_t startLap); @@ -44,8 +44,9 @@ namespace Pinetime { TickType_t lapTimes[maxLapCount + 1] = {0}; uint8_t savedLapsCount = 0; + uint8_t displayedLapsStart = 0; - lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap; + lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap; lv_obj_t* lapText; }; } From d9e30d4b3164c94bf7512e8e6cce504596c6d127 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Wed, 25 Aug 2021 19:07:52 +0300 Subject: [PATCH 3/4] Small StopWatch cleanups --- src/displayapp/screens/StopWatch.cpp | 24 +++++++++++------------- src/displayapp/screens/StopWatch.h | 6 +++--- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index c5f782b399..ab2f2e6f35 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -5,22 +5,20 @@ using namespace Pinetime::Applications::Screens; namespace { TimeSeparated_t convertTicksToTimeSegments(const TickType_t timeElapsed) { - TickType_t timeElapsedCentis = timeElapsed * 100 / configTICK_RATE_HZ; - - const uint8_t hundredths = (timeElapsedCentis % 100); - const uint8_t secs = (timeElapsedCentis / 100) % 60; - const uint32_t mins = (timeElapsedCentis / 100) / 60; + const uint8_t hundredths = timeElapsed * 100 / configTICK_RATE_HZ % 100; + const uint8_t secs = (timeElapsed / configTICK_RATE_HZ) % 60; + const uint32_t mins = (timeElapsed / configTICK_RATE_HZ) / 60; return TimeSeparated_t {mins, secs, hundredths}; } void play_pause_event_handler(lv_obj_t* obj, lv_event_t event) { auto* stopWatch = static_cast(obj->user_data); - stopWatch->playPauseBtnEventHandler(event); + stopWatch->PlayPauseBtnEventHandler(event); } void stop_lap_event_handler(lv_obj_t* obj, lv_event_t event) { auto* stopWatch = static_cast(obj->user_data); - stopWatch->stopLapBtnEventHandler(event); + stopWatch->StopLapBtnEventHandler(event); } } @@ -119,8 +117,8 @@ void StopWatch::Pause() { void StopWatch::DisplayLaps(uint8_t startLap) { char buffer[22]; std::string allLapsText = ""; - TimeSeparated_t lapTime; - TimeSeparated_t runTime; + TimeSeparated_t lapTime = {0}; + TimeSeparated_t runTime = {0}; for (uint8_t i = startLap; i < savedLapsCount && i < startLap + 5 && i < maxLapCount; i++) { runTime = convertTicksToTimeSegments(lapTimes[i]); if (i > 0) { @@ -131,10 +129,10 @@ void StopWatch::DisplayLaps(uint8_t startLap) { sprintf(buffer, "#%-2d %2d:%02d.%1d %2d:%02d.%1d\n", i + 1, - std::min(lapTime.mins, 99), + static_cast(std::min(lapTime.mins, static_cast(99))), lapTime.secs, lapTime.hundredths / 10, - std::min(runTime.mins, 99), + static_cast(std::min(runTime.mins, static_cast(99))), runTime.secs, runTime.hundredths / 10); @@ -157,7 +155,7 @@ void StopWatch::Refresh() { } } -void StopWatch::playPauseBtnEventHandler(lv_event_t event) { +void StopWatch::PlayPauseBtnEventHandler(lv_event_t event) { if (event != LV_EVENT_CLICKED) { return; } @@ -170,7 +168,7 @@ void StopWatch::playPauseBtnEventHandler(lv_event_t event) { } } -void StopWatch::stopLapBtnEventHandler(lv_event_t event) { +void StopWatch::StopLapBtnEventHandler(lv_event_t event) { if (event != LV_EVENT_CLICKED) { return; } diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index e72d1ca01f..6a11af9f54 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -22,8 +22,8 @@ namespace Pinetime { ~StopWatch() override; void Refresh() override; - void playPauseBtnEventHandler(lv_event_t event); - void stopLapBtnEventHandler(lv_event_t event); + void PlayPauseBtnEventHandler(lv_event_t event); + void StopLapBtnEventHandler(lv_event_t event); bool OnButtonPushed() override; bool OnTouchEvent(Pinetime::Applications::TouchEvents event) override; @@ -37,7 +37,7 @@ namespace Pinetime { Pinetime::System::SystemTask& systemTask; States currentState = States::Init; - TickType_t startTime; + TickType_t startTime = 0; TickType_t oldTimeElapsed = 0; static constexpr uint8_t maxLapCount = 20; From a27312b0f3915bf349496a390d3295a50524d4e3 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Fri, 25 Mar 2022 16:24:56 +0200 Subject: [PATCH 4/4] Add missing declaration --- src/displayapp/screens/StopWatch.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index 6a11af9f54..53a6bb1e73 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -48,6 +48,7 @@ namespace Pinetime { lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap; lv_obj_t* lapText; + lv_task_t* taskRefresh; }; } }