From cc58b635a34cf89fa6301096a19e0a816817aa50 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Thu, 11 Mar 2021 10:54:14 +0100 Subject: [PATCH 01/14] Basic logic done. Need to change the timer source to get ms. Also need to replace with paddle app in displayApp.cpp and ApplicationList.cpp later. --- src/CMakeLists.txt | 2 + src/displayapp/Apps.h | 2 +- src/displayapp/DisplayApp.cpp | 4 +- src/displayapp/screens/ApplicationList.cpp | 3 +- src/displayapp/screens/StopWatch.cpp | 73 ++++++++++++++++++++++ src/displayapp/screens/StopWatch.h | 33 ++++++++++ 6 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 src/displayapp/screens/StopWatch.cpp create mode 100644 src/displayapp/screens/StopWatch.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7d21a805..ee697e01 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -474,6 +474,7 @@ list(APPEND SOURCE_FILES displayapp/screens/Meter.cpp displayapp/screens/InfiniPaint.cpp displayapp/screens/Paddle.cpp + displayapp/screens/StopWatch.cpp displayapp/screens/BatteryIcon.cpp displayapp/screens/BleIcon.cpp displayapp/screens/NotificationIcon.cpp @@ -566,6 +567,7 @@ set(INCLUDE_FILES displayapp/screens/Tile.h displayapp/screens/Meter.h displayapp/screens/InfiniPaint.h + displayapp/screens/StopWatch.h displayapp/screens/Paddle.h displayapp/screens/DropDownDemo.h displayapp/screens/BatteryIcon.h diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index 028fc80c..74b121df 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -2,6 +2,6 @@ namespace Pinetime { namespace Applications { - enum class Apps {None, Launcher, Clock, SysInfo, Meter, Brightness, Music, FirmwareValidation, Paint, Paddle, Notifications, Twos, HeartRate, Navigation}; + enum class Apps {None, Launcher, Clock, SysInfo, Meter, Brightness, Music, FirmwareValidation, Paint, Paddle, Notifications, Twos, HeartRate, Navigation, StopWatch}; } } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 6e3fd0bf..ad58e13d 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -12,6 +12,7 @@ #include "displayapp/screens/FirmwareValidation.h" #include "displayapp/screens/InfiniPaint.h" #include "displayapp/screens/Paddle.h" +#include "displayapp/screens/StopWatch.h" #include "displayapp/screens/Meter.h" #include "displayapp/screens/Music.h" #include "displayapp/screens/Navigation.h" @@ -203,7 +204,8 @@ void DisplayApp::RunningState() { case Apps::Meter: currentScreen.reset(new Screens::Meter(this)); break; case Apps::Twos: currentScreen.reset(new Screens::Twos(this)); break; case Apps::Paint: currentScreen.reset(new Screens::InfiniPaint(this, lvgl)); break; - case Apps::Paddle: currentScreen.reset(new Screens::Paddle(this, lvgl)); break; + //TODO: Change it back + case Apps::StopWatch: currentScreen.reset(new Screens::StopWatch(this, dateTimeController)); break; case Apps::Brightness : currentScreen.reset(new Screens::Brightness(this, brightnessController)); break; case Apps::Music : currentScreen.reset(new Screens::Music(this, systemTask.nimble().music())); break; case Apps::Navigation : currentScreen.reset(new Screens::Navigation(this, systemTask.nimble().navigation())); break; diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp index 531636eb..4f6ad53d 100644 --- a/src/displayapp/screens/ApplicationList.cpp +++ b/src/displayapp/screens/ApplicationList.cpp @@ -60,7 +60,8 @@ std::unique_ptr ApplicationList::CreateScreen2() { {Symbols::asterisk, Apps::Meter}, {Symbols::paintbrush, Apps::Paint}, {Symbols::info, Apps::Notifications}, - {Symbols::paddle, Apps::Paddle}, + //TODO: Change it back + {Symbols::paddle, Apps::StopWatch}, {"2", Apps::Twos} } }; diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp new file mode 100644 index 00000000..834471e0 --- /dev/null +++ b/src/displayapp/screens/StopWatch.cpp @@ -0,0 +1,73 @@ +#include "StopWatch.h" + +#include "Screen.h" +#include "lvgl/lvgl.h" + +#include + +// Anonymous namespace for local functions +namespace { + std::tuple convertMilliSecsToSegments(const int64_t& currentTime) { + const int milliSecs = (currentTime % 1000); // Get only the first two digits and ignore the last + const int secs = (currentTime / 1000) % 60; + const int mins = (currentTime / 1000) / 60; + return std::make_tuple(mins, secs, milliSecs); + } +} +using namespace Pinetime::Applications::Screens; + +StopWatch::StopWatch(DisplayApp* app, const Pinetime::Controllers::DateTime& dateTime) + : Screen(app), dateTime {dateTime}, running {true}, currentState {States::INIT}, currentEvent {Events::PLAY}, startTime {}, + timeElapsed {} { + + 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_extrabold_compressed); + lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0); + + 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_align(msecTime, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 115, 60); +} + +StopWatch::~StopWatch() { + lv_obj_clean(lv_scr_act()); +} + +bool StopWatch::Refresh() { + + switch (currentState) { + // Init state when an user first opens the app + // and when a stop/reset button is pressed + case States::INIT: { + // The initial default value + lv_label_set_text(time, "00:00"); + lv_label_set_text(msecTime, "00"); + if (currentEvent == Events::PLAY) { + startTime = dateTime.CurrentDateTime(); + currentState = States::RUNNING; + } + break; + } + case States::RUNNING: { + auto delta = std::chrono::duration_cast(dateTime.CurrentDateTime() - startTime); + timeElapsed = delta.count(); + auto timeSeparated = convertMilliSecsToSegments(timeElapsed); + lv_label_set_text_fmt(time, "%02d:%02d", std::get<0>(timeSeparated), std::get<1>(timeSeparated)); + break; + } + case States::HALTED: { + + break; + } + } + return running; +} + +bool StopWatch::OnButtonPushed() { + running = false; + return true; +} + +bool StopWatch::OnTouchEvent(uint16_t x, uint16_t y) { + return true; +} \ No newline at end of file diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h new file mode 100644 index 00000000..ecc1f276 --- /dev/null +++ b/src/displayapp/screens/StopWatch.h @@ -0,0 +1,33 @@ +#pragma once + +#include "Screen.h" +#include "components/datetime/DateTimeController.h" +#include "../LittleVgl.h" + +#include + +namespace Pinetime::Applications::Screens { + + enum class States { INIT, RUNNING, HALTED }; + + enum class Events { PLAY, PAUSE, STOP }; + + class StopWatch : public Screen { + public: + StopWatch(DisplayApp* app, const Pinetime::Controllers::DateTime& dateTime); + ~StopWatch() override; + bool Refresh() override; + bool OnButtonPushed() override; + bool OnTouchEvent(uint16_t x, uint16_t y) override; + + private: + using timeUnit = std::chrono::time_point; + const Pinetime::Controllers::DateTime& dateTime; + bool running; + States currentState; + Events currentEvent; + timeUnit startTime; + int64_t timeElapsed; + lv_obj_t *time, *msecTime; + }; +} \ No newline at end of file From ce91e1a7a6e7ccf674aabfb20770d13cb4eb3190 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Thu, 11 Mar 2021 11:56:58 +0100 Subject: [PATCH 02/14] Changed the clock source. Stopwatch works. Need to add butttons. --- src/displayapp/screens/StopWatch.cpp | 33 +++++++++++++++++++++------- src/displayapp/screens/StopWatch.h | 8 +++---- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 834471e0..2ccafb16 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -2,17 +2,34 @@ #include "Screen.h" #include "lvgl/lvgl.h" +#include "projdefs.h" +#include "FreeRTOSConfig.h" +#include "task.h" #include // Anonymous namespace for local functions namespace { - std::tuple convertMilliSecsToSegments(const int64_t& currentTime) { - const int milliSecs = (currentTime % 1000); // Get only the first two digits and ignore the last - const int secs = (currentTime / 1000) % 60; - const int mins = (currentTime / 1000) / 60; + std::tuple convertTicksToTimeSegments(const TickType_t timeElapsed) { + const int timeElapsedMillis = (static_cast(timeElapsed) / static_cast(configTICK_RATE_HZ)) * 1000; + + const int milliSecs = (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; return std::make_tuple(mins, secs, milliSecs); } + + 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; + } } using namespace Pinetime::Applications::Screens; @@ -43,16 +60,16 @@ bool StopWatch::Refresh() { lv_label_set_text(time, "00:00"); lv_label_set_text(msecTime, "00"); if (currentEvent == Events::PLAY) { - startTime = dateTime.CurrentDateTime(); + startTime = xTaskGetTickCount(); currentState = States::RUNNING; } break; } case States::RUNNING: { - auto delta = std::chrono::duration_cast(dateTime.CurrentDateTime() - startTime); - timeElapsed = delta.count(); - auto timeSeparated = convertMilliSecsToSegments(timeElapsed); + auto timeElapsed = calculateDelta(startTime, xTaskGetTickCount()); + auto timeSeparated = convertTicksToTimeSegments(timeElapsed); lv_label_set_text_fmt(time, "%02d:%02d", std::get<0>(timeSeparated), std::get<1>(timeSeparated)); + lv_label_set_text_fmt(msecTime, "%02d", std::get<2>(timeSeparated)); break; } case States::HALTED: { diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index ecc1f276..4763fd1e 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -4,7 +4,8 @@ #include "components/datetime/DateTimeController.h" #include "../LittleVgl.h" -#include +#include "FreeRTOS.h" +#include "portmacro_cmsis.h" namespace Pinetime::Applications::Screens { @@ -21,13 +22,12 @@ namespace Pinetime::Applications::Screens { bool OnTouchEvent(uint16_t x, uint16_t y) override; private: - using timeUnit = std::chrono::time_point; const Pinetime::Controllers::DateTime& dateTime; bool running; States currentState; Events currentEvent; - timeUnit startTime; - int64_t timeElapsed; + TickType_t startTime; + TickType_t timeElapsed; lv_obj_t *time, *msecTime; }; } \ No newline at end of file From 70373e734529fdd2e31f0080444360ba859ff567 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Thu, 11 Mar 2021 23:41:24 +0100 Subject: [PATCH 03/14] Added play/pause button. --- src/displayapp/screens/StopWatch.cpp | 58 ++++++++++++++++++++++++---- src/displayapp/screens/StopWatch.h | 6 ++- 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 2ccafb16..1a6ff598 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -1,6 +1,7 @@ #include "StopWatch.h" #include "Screen.h" +#include "Symbols.h" #include "lvgl/lvgl.h" #include "projdefs.h" #include "FreeRTOSConfig.h" @@ -8,6 +9,8 @@ #include +using namespace Pinetime::Applications::Screens; + // Anonymous namespace for local functions namespace { std::tuple convertTicksToTimeSegments(const TickType_t timeElapsed) { @@ -31,19 +34,30 @@ namespace { return delta; } } -using namespace Pinetime::Applications::Screens; + +static void play_pause_event_handler(lv_obj_t* obj, lv_event_t event) { + StopWatch* stopWatch = static_cast(obj->user_data); + stopWatch->playPauseBtnEventHandler(event); +} StopWatch::StopWatch(DisplayApp* app, const Pinetime::Controllers::DateTime& dateTime) - : Screen(app), dateTime {dateTime}, running {true}, currentState {States::INIT}, currentEvent {Events::PLAY}, startTime {}, - timeElapsed {} { + : Screen(app), dateTime {dateTime}, running {true}, currentState {States::INIT}, currentEvent {Events::STOP}, startTime {}, + oldTimeElapsed {} { 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_extrabold_compressed); - lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0); + lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -50); 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_align(msecTime, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 115, 60); + lv_obj_align(msecTime, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 113, 0); + + btnPlayPause = lv_btn_create(lv_scr_act(), nullptr); + btnPlayPause->user_data = this; + lv_obj_set_event_cb(btnPlayPause, play_pause_event_handler); + lv_obj_align(btnPlayPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); + txtPlayPause = lv_label_create(btnPlayPause, nullptr); + lv_label_set_text(txtPlayPause, Symbols::play); } StopWatch::~StopWatch() { @@ -66,14 +80,30 @@ bool StopWatch::Refresh() { break; } case States::RUNNING: { - auto timeElapsed = calculateDelta(startTime, xTaskGetTickCount()); - auto timeSeparated = convertTicksToTimeSegments(timeElapsed); + lv_label_set_text(txtPlayPause, Symbols::pause); + + const auto timeElapsed = calculateDelta(startTime, xTaskGetTickCount()); + const auto timeSeparated = convertTicksToTimeSegments((oldTimeElapsed + timeElapsed)); + lv_label_set_text_fmt(time, "%02d:%02d", std::get<0>(timeSeparated), std::get<1>(timeSeparated)); lv_label_set_text_fmt(msecTime, "%02d", std::get<2>(timeSeparated)); + + if (currentEvent == Events::PAUSE) { + // Reset the start time + startTime = 0; + // Store the current time elapsed in cache + oldTimeElapsed += timeElapsed; + currentState = States::HALTED; + } break; } case States::HALTED: { + lv_label_set_text(txtPlayPause, Symbols::play); + if (currentEvent == Events::PLAY) { + startTime = xTaskGetTickCount(); + currentState = States::RUNNING; + } break; } } @@ -86,5 +116,19 @@ bool StopWatch::OnButtonPushed() { } bool StopWatch::OnTouchEvent(uint16_t x, uint16_t y) { + if (y < 60) { + playPauseBtnEventHandler(LV_EVENT_CLICKED); + } return true; +} + +void StopWatch::playPauseBtnEventHandler(lv_event_t event) { + if (event == LV_EVENT_CLICKED) { + if (currentState == States::INIT) { + currentEvent = Events::PLAY; + } else { + // Simple Toggle for play/pause + currentEvent = (currentEvent == Events::PLAY ? Events::PAUSE : Events::PLAY); + } + } } \ No newline at end of file diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index 4763fd1e..9e5779a1 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -20,6 +20,8 @@ namespace Pinetime::Applications::Screens { bool Refresh() override; bool OnButtonPushed() override; bool OnTouchEvent(uint16_t x, uint16_t y) override; + void playPauseBtnEventHandler(lv_event_t event); + private: const Pinetime::Controllers::DateTime& dateTime; @@ -27,7 +29,7 @@ namespace Pinetime::Applications::Screens { States currentState; Events currentEvent; TickType_t startTime; - TickType_t timeElapsed; - lv_obj_t *time, *msecTime; + TickType_t oldTimeElapsed; + lv_obj_t *time, *msecTime, *btnPlayPause, *btnStop, *txtPlayPause, *txtStop; }; } \ No newline at end of file From a090664a4c1709a7925621632e579632e3f1e39a Mon Sep 17 00:00:00 2001 From: panky-codes Date: Fri, 12 Mar 2021 09:43:13 +0100 Subject: [PATCH 04/14] Added a button for stop lap. Logic works. Need to implement symbol and buffer for lap --- src/displayapp/screens/StopWatch.cpp | 54 ++++++++++++++++++++++++---- src/displayapp/screens/StopWatch.h | 13 +++++-- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 1a6ff598..fdd275c8 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -13,13 +13,13 @@ using namespace Pinetime::Applications::Screens; // Anonymous namespace for local functions namespace { - std::tuple convertTicksToTimeSegments(const TickType_t timeElapsed) { + TimeSeparated_t convertTicksToTimeSegments(const TickType_t timeElapsed) { const int timeElapsedMillis = (static_cast(timeElapsed) / static_cast(configTICK_RATE_HZ)) * 1000; const int milliSecs = (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; - return std::make_tuple(mins, secs, milliSecs); + return TimeSeparated_t {mins, secs, milliSecs}; } TickType_t calculateDelta(const TickType_t startTime, const TickType_t currentTime) { @@ -40,9 +40,14 @@ static void play_pause_event_handler(lv_obj_t* obj, lv_event_t event) { stopWatch->playPauseBtnEventHandler(event); } +static void stop_lap_event_handler(lv_obj_t* obj, lv_event_t event) { + StopWatch* stopWatch = static_cast(obj->user_data); + stopWatch->stopLapBtnEventHandler(event); +} + StopWatch::StopWatch(DisplayApp* app, const Pinetime::Controllers::DateTime& dateTime) : Screen(app), dateTime {dateTime}, running {true}, currentState {States::INIT}, currentEvent {Events::STOP}, startTime {}, - oldTimeElapsed {} { + oldTimeElapsed {}, timeSeparated {}, lapNr {} { 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_extrabold_compressed); @@ -58,6 +63,9 @@ StopWatch::StopWatch(DisplayApp* app, const Pinetime::Controllers::DateTime& dat lv_obj_align(btnPlayPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); txtPlayPause = lv_label_create(btnPlayPause, nullptr); lv_label_set_text(txtPlayPause, Symbols::play); + + // We don't want this button in the init state + btnStopLap = nullptr; } StopWatch::~StopWatch() { @@ -70,10 +78,22 @@ bool StopWatch::Refresh() { // Init state when an user first opens the app // and when a stop/reset button is pressed case States::INIT: { + if (btnStopLap) { + lv_obj_del(btnStopLap); + } // The initial default value lv_label_set_text(time, "00:00"); lv_label_set_text(msecTime, "00"); + if (currentEvent == Events::PLAY) { + btnStopLap = lv_btn_create(lv_scr_act(), nullptr); + btnStopLap->user_data = this; + lv_obj_set_event_cb(btnStopLap, stop_lap_event_handler); + lv_obj_align(btnStopLap, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); + txtStopLap = lv_label_create(btnStopLap, nullptr); + // TODO: Change to Lap symbol + lv_label_set_text(txtStopLap, Symbols::shoe); + startTime = xTaskGetTickCount(); currentState = States::RUNNING; } @@ -81,12 +101,14 @@ bool StopWatch::Refresh() { } case States::RUNNING: { lv_label_set_text(txtPlayPause, Symbols::pause); + // TODO: Change to Lap symbol + lv_label_set_text(txtStopLap, Symbols::shoe); const auto timeElapsed = calculateDelta(startTime, xTaskGetTickCount()); - const auto timeSeparated = convertTicksToTimeSegments((oldTimeElapsed + timeElapsed)); + timeSeparated = convertTicksToTimeSegments((oldTimeElapsed + timeElapsed)); - lv_label_set_text_fmt(time, "%02d:%02d", std::get<0>(timeSeparated), std::get<1>(timeSeparated)); - lv_label_set_text_fmt(msecTime, "%02d", std::get<2>(timeSeparated)); + lv_label_set_text_fmt(time, "%02d:%02d", timeSeparated.mins, timeSeparated.secs); + lv_label_set_text_fmt(msecTime, "%02d", timeSeparated.msecs); if (currentEvent == Events::PAUSE) { // Reset the start time @@ -99,11 +121,16 @@ bool StopWatch::Refresh() { } case States::HALTED: { lv_label_set_text(txtPlayPause, Symbols::play); + // TODO: Change to stop button + lv_label_set_text(txtStopLap, Symbols::stepBackward); if (currentEvent == Events::PLAY) { startTime = xTaskGetTickCount(); currentState = States::RUNNING; } + if (currentEvent == Events::STOP) { + currentState = States::INIT; + } break; } } @@ -131,4 +158,17 @@ void StopWatch::playPauseBtnEventHandler(lv_event_t event) { currentEvent = (currentEvent == Events::PLAY ? Events::PAUSE : Events::PLAY); } } -} \ No newline at end of file +} + +void StopWatch::stopLapBtnEventHandler(lv_event_t event) { + if (event == LV_EVENT_CLICKED) { + // If running, then this button is used to save laps + if (currentState == States::RUNNING) { + // Add to cirbuffer our new value + } else if (currentState == States::HALTED) { + currentEvent = Events::STOP; + } else { + // Not possible to reach here. Do nothing. + } + } +} diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index 9e5779a1..929813f8 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -13,6 +13,12 @@ namespace Pinetime::Applications::Screens { enum class Events { PLAY, PAUSE, STOP }; + struct TimeSeparated_t { + int mins; + int secs; + int msecs; + }; + class StopWatch : public Screen { public: StopWatch(DisplayApp* app, const Pinetime::Controllers::DateTime& dateTime); @@ -21,7 +27,7 @@ namespace Pinetime::Applications::Screens { bool OnButtonPushed() override; bool OnTouchEvent(uint16_t x, uint16_t y) override; void playPauseBtnEventHandler(lv_event_t event); - + void stopLapBtnEventHandler(lv_event_t event); private: const Pinetime::Controllers::DateTime& dateTime; @@ -30,6 +36,9 @@ namespace Pinetime::Applications::Screens { Events currentEvent; TickType_t startTime; TickType_t oldTimeElapsed; - lv_obj_t *time, *msecTime, *btnPlayPause, *btnStop, *txtPlayPause, *txtStop; + TimeSeparated_t timeSeparated; // Holds Mins, Secs, millisecs + int lapNr; + lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap; + lv_obj_t *lapOneText, *lapTwoText; }; } \ No newline at end of file From 00f2a053bf65058465c8b2f6913a66e85dbd6864 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Fri, 12 Mar 2021 20:24:53 +0100 Subject: [PATCH 05/14] Laps introduced. Tested. Need to change the icon. --- src/displayapp/screens/StopWatch.cpp | 38 ++++++++++++++++++++++++---- src/displayapp/screens/StopWatch.h | 38 +++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index fdd275c8..30468f74 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -47,7 +47,7 @@ static void stop_lap_event_handler(lv_obj_t* obj, lv_event_t event) { StopWatch::StopWatch(DisplayApp* app, const Pinetime::Controllers::DateTime& dateTime) : Screen(app), dateTime {dateTime}, running {true}, currentState {States::INIT}, currentEvent {Events::STOP}, startTime {}, - oldTimeElapsed {}, timeSeparated {}, lapNr {} { + oldTimeElapsed {}, currentTimeSeparated {}, lapBuffer {}, lapNr {}, lapPressed {false} { 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_extrabold_compressed); @@ -64,6 +64,16 @@ StopWatch::StopWatch(DisplayApp* app, const Pinetime::Controllers::DateTime& dat txtPlayPause = lv_label_create(btnPlayPause, nullptr); lv_label_set_text(txtPlayPause, Symbols::play); + 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_align(lapOneText, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 50, 25); + 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_align(lapTwoText, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 50, 50); + lv_label_set_text(lapTwoText, ""); + // We don't want this button in the init state btnStopLap = nullptr; } @@ -85,6 +95,9 @@ bool StopWatch::Refresh() { lv_label_set_text(time, "00:00"); lv_label_set_text(msecTime, "00"); + lv_label_set_text(lapOneText, ""); + lv_label_set_text(lapTwoText, ""); + if (currentEvent == Events::PLAY) { btnStopLap = lv_btn_create(lv_scr_act(), nullptr); btnStopLap->user_data = this; @@ -105,10 +118,21 @@ bool StopWatch::Refresh() { lv_label_set_text(txtStopLap, Symbols::shoe); const auto timeElapsed = calculateDelta(startTime, xTaskGetTickCount()); - timeSeparated = convertTicksToTimeSegments((oldTimeElapsed + timeElapsed)); + currentTimeSeparated = convertTicksToTimeSegments((oldTimeElapsed + timeElapsed)); - lv_label_set_text_fmt(time, "%02d:%02d", timeSeparated.mins, timeSeparated.secs); - lv_label_set_text_fmt(msecTime, "%02d", timeSeparated.msecs); + lv_label_set_text_fmt(time, "%02d:%02d", currentTimeSeparated.mins, currentTimeSeparated.secs); + lv_label_set_text_fmt(msecTime, "%02d", currentTimeSeparated.msecs); + + if (lapPressed == true) { + if (lapBuffer[0]) { + lv_label_set_text_fmt(lapOneText, "#%d %d:%d:%d", (lapNr - 1), lapBuffer[0]->mins, lapBuffer[0]->secs, lapBuffer[0]->msecs); + } + if (lapBuffer[1]) { + lv_label_set_text_fmt(lapTwoText, "#%d %d:%d:%d", lapNr, lapBuffer[1]->mins, lapBuffer[1]->secs, lapBuffer[1]->msecs); + } + // Reset the bool to avoid setting the text in each cycle + lapPressed = false; + } if (currentEvent == Events::PAUSE) { // Reset the start time @@ -130,6 +154,7 @@ bool StopWatch::Refresh() { } if (currentEvent == Events::STOP) { currentState = States::INIT; + oldTimeElapsed = 0; } break; } @@ -164,7 +189,10 @@ void StopWatch::stopLapBtnEventHandler(lv_event_t event) { if (event == LV_EVENT_CLICKED) { // If running, then this button is used to save laps if (currentState == States::RUNNING) { - // Add to cirbuffer our new value + lapBuffer.addLaps(currentTimeSeparated); + lapNr++; + lapPressed = true; + } else if (currentState == States::HALTED) { currentEvent = Events::STOP; } else { diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index 929813f8..c1dd0af9 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -7,6 +7,8 @@ #include "FreeRTOS.h" #include "portmacro_cmsis.h" +#include + namespace Pinetime::Applications::Screens { enum class States { INIT, RUNNING, HALTED }; @@ -19,6 +21,38 @@ namespace Pinetime::Applications::Screens { int msecs; }; + template struct LapTextBuffer_t { + LapTextBuffer_t() : _arr {}, currentSz {}, capacity {N}, head {-1} { + } + + void addLaps(const TimeSeparated_t& timeVal) { + head %= capacity; + _arr[head++] = timeVal; + + if (currentSz < capacity) { + currentSz++; + } + } + + // Optional return type would be much more appropriate here + TimeSeparated_t* operator[](std::size_t idx) { + // Sanity check for out-of-bounds + if (idx >= 0 && idx < capacity) { + if (idx < currentSz) { + const auto transformed_idx = (head + capacity - idx) % capacity; + return (&_arr[transformed_idx]); + } + } + return nullptr; + } + + private: + std::array _arr; + uint8_t currentSz; + uint8_t capacity; + int8_t head; + }; + class StopWatch : public Screen { public: StopWatch(DisplayApp* app, const Pinetime::Controllers::DateTime& dateTime); @@ -36,8 +70,10 @@ namespace Pinetime::Applications::Screens { Events currentEvent; TickType_t startTime; TickType_t oldTimeElapsed; - TimeSeparated_t timeSeparated; // Holds Mins, Secs, millisecs + TimeSeparated_t currentTimeSeparated; // Holds Mins, Secs, millisecs + LapTextBuffer_t<2> lapBuffer; int lapNr; + bool lapPressed; lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap; lv_obj_t *lapOneText, *lapTwoText; }; From 5d57b9054a9d30d8724fac87108d68a4f2c95e68 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Sat, 13 Mar 2021 13:59:54 +0100 Subject: [PATCH 06/14] Adding laps completed. --- src/displayapp/screens/StopWatch.cpp | 12 ++++++++---- src/displayapp/screens/StopWatch.h | 11 +++++++++-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 30468f74..972f3a08 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -52,10 +52,12 @@ StopWatch::StopWatch(DisplayApp* app, const Pinetime::Controllers::DateTime& dat 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_extrabold_compressed); lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -50); + lv_label_set_text(time, "00:00"); 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_align(msecTime, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 113, 0); + lv_label_set_text(msecTime, "00"); btnPlayPause = lv_btn_create(lv_scr_act(), nullptr); btnPlayPause->user_data = this; @@ -97,6 +99,8 @@ bool StopWatch::Refresh() { lv_label_set_text(lapOneText, ""); lv_label_set_text(lapTwoText, ""); + lapBuffer.clearBuffer(); + lapNr = 0; if (currentEvent == Events::PLAY) { btnStopLap = lv_btn_create(lv_scr_act(), nullptr); @@ -124,11 +128,11 @@ bool StopWatch::Refresh() { lv_label_set_text_fmt(msecTime, "%02d", currentTimeSeparated.msecs); if (lapPressed == true) { - if (lapBuffer[0]) { - lv_label_set_text_fmt(lapOneText, "#%d %d:%d:%d", (lapNr - 1), lapBuffer[0]->mins, lapBuffer[0]->secs, lapBuffer[0]->msecs); - } if (lapBuffer[1]) { - lv_label_set_text_fmt(lapTwoText, "#%d %d:%d:%d", lapNr, lapBuffer[1]->mins, lapBuffer[1]->secs, lapBuffer[1]->msecs); + lv_label_set_text_fmt(lapOneText, "#%d %d:%d:%d", (lapNr - 1), lapBuffer[1]->mins, lapBuffer[1]->secs, lapBuffer[1]->msecs); + } + if (lapBuffer[0]) { + lv_label_set_text_fmt(lapTwoText, "#%d %d:%d:%d", lapNr, lapBuffer[0]->mins, lapBuffer[0]->secs, lapBuffer[0]->msecs); } // Reset the bool to avoid setting the text in each cycle lapPressed = false; diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index c1dd0af9..0d425f72 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -26,20 +26,27 @@ namespace Pinetime::Applications::Screens { } void addLaps(const TimeSeparated_t& timeVal) { + head++; head %= capacity; - _arr[head++] = timeVal; + _arr[head] = timeVal; if (currentSz < capacity) { currentSz++; } } + void clearBuffer() { + _arr = {}; + currentSz = 0; + head = -1; + } + // Optional return type would be much more appropriate here TimeSeparated_t* operator[](std::size_t idx) { // Sanity check for out-of-bounds if (idx >= 0 && idx < capacity) { if (idx < currentSz) { - const auto transformed_idx = (head + capacity - idx) % capacity; + const auto transformed_idx = (head - idx) % capacity; return (&_arr[transformed_idx]); } } From 02824d0671b558e5a36188df4cbc729b571dad1a Mon Sep 17 00:00:00 2001 From: panky-codes Date: Sat, 13 Mar 2021 14:38:18 +0100 Subject: [PATCH 07/14] Stopwatch completed. Ready for PR --- src/displayapp/fonts/Readme.md | 2 +- src/displayapp/fonts/jetbrains_mono_bold_20.c | 105 +++++++++++------- src/displayapp/screens/ApplicationList.cpp | 4 +- src/displayapp/screens/StopWatch.cpp | 16 +-- src/displayapp/screens/Symbols.h | 3 + 5 files changed, 75 insertions(+), 55 deletions(-) diff --git a/src/displayapp/fonts/Readme.md b/src/displayapp/fonts/Readme.md index 8e50c297..79b36bca 100644 --- a/src/displayapp/fonts/Readme.md +++ b/src/displayapp/fonts/Readme.md @@ -10,7 +10,7 @@ * Bpp : 1 bit-per-pixel * Do not enable font compression and horizontal subpixel hinting * Load the file `JetBrainsMono-Bold.tff` and specify the following range : `0x20-0x7f, 0x410-0x44f` - * Add a 2nd font, load the file `FontAwesome5-Solid+Brands+Regular.woff` and specify the following range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd` + * Add a 2nd font, load the file `FontAwesome5-Solid+Brands+Regular.woff` and specify the following range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024` * Click on Convert, and download the file `jetbrains_mono_bold_20.c` and copy it in `src/DisplayApp/Fonts` Add new symbols: diff --git a/src/displayapp/fonts/jetbrains_mono_bold_20.c b/src/displayapp/fonts/jetbrains_mono_bold_20.c index dc30104a..f4050db8 100644 --- a/src/displayapp/fonts/jetbrains_mono_bold_20.c +++ b/src/displayapp/fonts/jetbrains_mono_bold_20.c @@ -466,8 +466,8 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0x66, 0x66, 0x66, 0x6c, 0x63, /* U+417 "З" */ - 0x1f, 0x8f, 0xfd, 0xc7, 0x80, 0x70, 0x1c, 0x3e, - 0x7, 0xf0, 0xf, 0x0, 0xe0, 0x1d, 0x83, 0xb8, + 0x1f, 0xf, 0xf3, 0xc7, 0x0, 0x60, 0x1c, 0x1e, + 0x3, 0xf0, 0xe, 0x0, 0xe0, 0x1f, 0x83, 0xf8, 0xf7, 0xfc, 0x3e, 0x0, /* U+418 "И" */ @@ -615,7 +615,7 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0x70, /* U+437 "з" */ - 0x3f, 0x1f, 0xfe, 0x1c, 0x7, 0x1f, 0x7, 0xe0, + 0x3f, 0x1f, 0xfe, 0x1c, 0x7, 0x1f, 0x87, 0xe0, 0x1c, 0x7, 0xe1, 0xdf, 0xe3, 0xf0, /* U+438 "и" */ @@ -738,6 +738,15 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0xcf, 0x9f, 0xff, 0xf1, 0xff, 0xfc, 0x1f, 0xff, 0x1, 0xff, 0xc0, 0x1f, 0xf0, 0x0, 0x70, 0x0, + /* U+F024 "" */ + 0x70, 0x0, 0xf, 0x80, 0x0, 0xf8, 0x0, 0xf, + 0xff, 0xf, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0x7f, + 0xff, 0xf7, 0xff, 0xff, 0x7f, 0xff, 0xf7, 0xff, + 0xff, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0x7f, 0xff, + 0xf7, 0xff, 0xff, 0x7f, 0x7f, 0xe7, 0x0, 0x78, + 0x70, 0x0, 0x7, 0x0, 0x0, 0x70, 0x0, 0x7, + 0x0, 0x0, + /* U+F027 "" */ 0x0, 0xc0, 0x3, 0x80, 0xf, 0x0, 0x3e, 0xf, 0xfc, 0x9f, 0xf9, 0xbf, 0xf1, 0xff, 0xe3, 0xff, @@ -789,6 +798,13 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0xff, 0xfc, 0xff, 0xff, 0x3f, 0xff, 0xcf, 0xff, 0xf3, 0xff, 0xfc, 0xff, 0x7e, 0x1f, 0x80, + /* U+F04D "" */ + 0x7f, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0x80, + /* U+F051 "" */ 0xe0, 0x3f, 0x81, 0xfe, 0xf, 0xf8, 0x7f, 0xe3, 0xff, 0x9f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -897,6 +913,13 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0x81, 0xf8, 0x6d, 0x99, 0x9a, 0x36, 0x7, 0x80, 0xe0, 0x18, 0x2, 0x0, 0x0, + /* U+F2F2 "" */ + 0x7, 0xe0, 0x7, 0xe0, 0x1, 0x80, 0x3, 0xc0, + 0xf, 0xf2, 0x1f, 0xff, 0x3e, 0x7e, 0x7e, 0x7e, + 0xfe, 0x7e, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, + 0xfe, 0x7f, 0xff, 0xff, 0x7f, 0xfe, 0x7f, 0xfe, + 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + /* U+F3DD "" */ 0x40, 0x0, 0x40, 0x70, 0x0, 0x7e, 0x3c, 0x0, 0x3f, 0x8f, 0x80, 0x1f, 0x81, 0xe0, 0x1f, 0xc0, @@ -1080,7 +1103,7 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 1514, .adv_w = 192, .box_w = 11, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, {.bitmap_index = 1538, .adv_w = 192, .box_w = 9, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, {.bitmap_index = 1554, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1575, .adv_w = 192, .box_w = 11, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1575, .adv_w = 192, .box_w = 11, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, {.bitmap_index = 1595, .adv_w = 192, .box_w = 9, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, {.bitmap_index = 1611, .adv_w = 192, .box_w = 9, .box_h = 19, .ofs_x = 1, .ofs_y = 0}, {.bitmap_index = 1633, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, @@ -1139,36 +1162,39 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 2498, .adv_w = 192, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, {.bitmap_index = 2511, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, {.bitmap_index = 2561, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 2609, .adv_w = 240, .box_w = 15, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2638, .adv_w = 360, .box_w = 23, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 2693, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 2732, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 2775, .adv_w = 280, .box_w = 13, .box_h = 17, .ofs_x = 2, .ofs_y = -1}, - {.bitmap_index = 2803, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 2851, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 2890, .adv_w = 280, .box_w = 13, .box_h = 17, .ofs_x = 2, .ofs_y = -1}, - {.bitmap_index = 2918, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 2966, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3019, .adv_w = 120, .box_w = 8, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3038, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3088, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3124, .adv_w = 320, .box_w = 20, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3172, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 3215, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3253, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3291, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3329, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3367, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3405, .adv_w = 280, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 3443, .adv_w = 200, .box_w = 11, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3472, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3538, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 3587, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3637, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3697, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3750, .adv_w = 360, .box_w = 22, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3805, .adv_w = 360, .box_w = 22, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3858, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0} + {.bitmap_index = 2609, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2659, .adv_w = 240, .box_w = 15, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2688, .adv_w = 360, .box_w = 23, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 2743, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 2782, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 2825, .adv_w = 280, .box_w = 13, .box_h = 17, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 2853, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2901, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 2940, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 2979, .adv_w = 280, .box_w = 13, .box_h = 17, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 3007, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3055, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3108, .adv_w = 120, .box_w = 8, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3127, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3177, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3213, .adv_w = 320, .box_w = 20, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3261, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3304, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3342, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3380, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3418, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3456, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3494, .adv_w = 280, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 3532, .adv_w = 200, .box_w = 11, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3561, .adv_w = 280, .box_w = 16, .box_h = 19, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 3599, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3665, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3714, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3764, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3824, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3877, .adv_w = 360, .box_w = 22, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3932, .adv_w = 360, .box_w = 22, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3985, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0} }; /*--------------------- @@ -1176,10 +1202,11 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { *--------------------*/ static const uint16_t unicode_list_2[] = { - 0x0, 0x16, 0x26, 0x27, 0x28, 0x39, 0x47, 0x4a, - 0x4b, 0x50, 0x68, 0x94, 0x128, 0x184, 0x1e5, 0x1fb, - 0x21d, 0x23f, 0x240, 0x241, 0x242, 0x243, 0x292, 0x293, - 0x3dc, 0x3fc, 0x45c, 0x54a, 0x55f, 0x59e, 0x59f, 0x6a8 + 0x0, 0x16, 0x23, 0x26, 0x27, 0x28, 0x39, 0x47, + 0x4a, 0x4b, 0x4c, 0x50, 0x68, 0x94, 0x128, 0x184, + 0x1e5, 0x1fb, 0x21d, 0x23f, 0x240, 0x241, 0x242, 0x243, + 0x292, 0x293, 0x2f1, 0x3dc, 0x3fc, 0x45c, 0x54a, 0x55f, + 0x59e, 0x59f, 0x6a8 }; /*Collect the unicode lists and glyph_id offsets*/ @@ -1195,7 +1222,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = }, { .range_start = 61441, .range_length = 1705, .glyph_id_start = 160, - .unicode_list = unicode_list_2, .glyph_id_ofs_list = NULL, .list_length = 32, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + .unicode_list = unicode_list_2, .glyph_id_ofs_list = NULL, .list_length = 35, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp index 4f6ad53d..6d4cc8d8 100644 --- a/src/displayapp/screens/ApplicationList.cpp +++ b/src/displayapp/screens/ApplicationList.cpp @@ -60,8 +60,8 @@ std::unique_ptr ApplicationList::CreateScreen2() { {Symbols::asterisk, Apps::Meter}, {Symbols::paintbrush, Apps::Paint}, {Symbols::info, Apps::Notifications}, - //TODO: Change it back - {Symbols::paddle, Apps::StopWatch}, + //TODO: Need to find the right place based on comments from JF + {Symbols::stopWatch, Apps::StopWatch}, {"2", Apps::Twos} } }; diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 972f3a08..9abf9842 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -108,8 +108,7 @@ bool StopWatch::Refresh() { lv_obj_set_event_cb(btnStopLap, stop_lap_event_handler); lv_obj_align(btnStopLap, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); txtStopLap = lv_label_create(btnStopLap, nullptr); - // TODO: Change to Lap symbol - lv_label_set_text(txtStopLap, Symbols::shoe); + lv_label_set_text(txtStopLap, Symbols::lapsFlag); startTime = xTaskGetTickCount(); currentState = States::RUNNING; @@ -118,8 +117,7 @@ bool StopWatch::Refresh() { } case States::RUNNING: { lv_label_set_text(txtPlayPause, Symbols::pause); - // TODO: Change to Lap symbol - lv_label_set_text(txtStopLap, Symbols::shoe); + lv_label_set_text(txtStopLap, Symbols::lapsFlag); const auto timeElapsed = calculateDelta(startTime, xTaskGetTickCount()); currentTimeSeparated = convertTicksToTimeSegments((oldTimeElapsed + timeElapsed)); @@ -149,8 +147,7 @@ bool StopWatch::Refresh() { } case States::HALTED: { lv_label_set_text(txtPlayPause, Symbols::play); - // TODO: Change to stop button - lv_label_set_text(txtStopLap, Symbols::stepBackward); + lv_label_set_text(txtStopLap, Symbols::stop); if (currentEvent == Events::PLAY) { startTime = xTaskGetTickCount(); @@ -171,13 +168,6 @@ bool StopWatch::OnButtonPushed() { return true; } -bool StopWatch::OnTouchEvent(uint16_t x, uint16_t y) { - if (y < 60) { - playPauseBtnEventHandler(LV_EVENT_CLICKED); - } - return true; -} - void StopWatch::playPauseBtnEventHandler(lv_event_t event) { if (event == LV_EVENT_CLICKED) { if (currentState == States::INIT) { diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index 1a6bbd7f..9a13a755 100644 --- a/src/displayapp/screens/Symbols.h +++ b/src/displayapp/screens/Symbols.h @@ -36,6 +36,9 @@ namespace Pinetime { static constexpr const char* stepBackward = "\xEF\x81\x88"; static constexpr const char* play = "\xEF\x81\x8B"; static constexpr const char* pause = "\xEF\x81\x8C"; + static constexpr const char* stop = "\xEF\x81\x8D"; + static constexpr const char* stopWatch = "\xEF\x8B\xB2"; + static constexpr const char* lapsFlag = "\xEF\x80\xA4"; } } } From d409643b8eadd934849e2ffb749590e2ea672fb3 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Sat, 13 Mar 2021 14:53:37 +0100 Subject: [PATCH 08/14] Added some comments for clarity. Ready for review. Tested. --- src/displayapp/screens/StopWatch.cpp | 14 +++++++++++++- src/displayapp/screens/StopWatch.h | 4 ++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 9abf9842..b00fc4b8 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -85,7 +85,19 @@ StopWatch::~StopWatch() { } bool StopWatch::Refresh() { + // @startuml CHIP8_state + // State "INIT" as init + // State "RUNNING" as run + // State "HALTED" as halt + // [*] --> init + // init -> run : press play + // run -> run : press lap + // run --> halt : press pause + // halt --> run : press play + // halt --> init : press stop + // @enduml + // Copy paste the above plantuml text to visualize the state diagram switch (currentState) { // Init state when an user first opens the app // and when a stop/reset button is pressed @@ -132,7 +144,7 @@ bool StopWatch::Refresh() { if (lapBuffer[0]) { lv_label_set_text_fmt(lapTwoText, "#%d %d:%d:%d", lapNr, lapBuffer[0]->mins, lapBuffer[0]->secs, lapBuffer[0]->msecs); } - // Reset the bool to avoid setting the text in each cycle + // Reset the bool to avoid setting the text in each cycle until there is a change lapPressed = false; } diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index 0d425f72..a5cf5ceb 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -21,6 +21,7 @@ namespace Pinetime::Applications::Screens { int msecs; }; + // A simple buffer to hold the latest two laps template struct LapTextBuffer_t { LapTextBuffer_t() : _arr {}, currentSz {}, capacity {N}, head {-1} { } @@ -41,11 +42,11 @@ namespace Pinetime::Applications::Screens { head = -1; } - // Optional return type would be much more appropriate here TimeSeparated_t* operator[](std::size_t idx) { // Sanity check for out-of-bounds if (idx >= 0 && idx < capacity) { if (idx < currentSz) { + // This transformation is to ensure that head is always pointing to index 0. const auto transformed_idx = (head - idx) % capacity; return (&_arr[transformed_idx]); } @@ -66,7 +67,6 @@ namespace Pinetime::Applications::Screens { ~StopWatch() override; bool Refresh() override; bool OnButtonPushed() override; - bool OnTouchEvent(uint16_t x, uint16_t y) override; void playPauseBtnEventHandler(lv_event_t event); void stopLapBtnEventHandler(lv_event_t event); From bc6d447a5f7b272047c8bb977f6a476413268782 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Sat, 13 Mar 2021 22:29:07 +0100 Subject: [PATCH 09/14] Increased the size of the button and realigned the layout a bit. Tested. --- src/displayapp/screens/StopWatch.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index b00fc4b8..733e92d9 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -51,29 +51,30 @@ StopWatch::StopWatch(DisplayApp* app, const Pinetime::Controllers::DateTime& dat 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_extrabold_compressed); - lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -50); + lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -45); lv_label_set_text(time, "00:00"); 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_align(msecTime, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 113, 0); + lv_obj_align(msecTime, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 108, 3); lv_label_set_text(msecTime, "00"); btnPlayPause = lv_btn_create(lv_scr_act(), nullptr); btnPlayPause->user_data = this; lv_obj_set_event_cb(btnPlayPause, play_pause_event_handler); - lv_obj_align(btnPlayPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); + lv_obj_align(btnPlayPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, -10); + lv_obj_set_height(btnPlayPause, 40); txtPlayPause = lv_label_create(btnPlayPause, nullptr); lv_label_set_text(txtPlayPause, Symbols::play); 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_align(lapOneText, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 50, 25); + 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_align(lapTwoText, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 50, 50); + lv_obj_align(lapTwoText, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 50, 55); lv_label_set_text(lapTwoText, ""); // We don't want this button in the init state @@ -119,6 +120,7 @@ bool StopWatch::Refresh() { btnStopLap->user_data = this; lv_obj_set_event_cb(btnStopLap, stop_lap_event_handler); lv_obj_align(btnStopLap, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); + lv_obj_set_height(btnStopLap, 40); txtStopLap = lv_label_create(btnStopLap, nullptr); lv_label_set_text(txtStopLap, Symbols::lapsFlag); From abc30028a2b3d0089bca880a73e7fbad9d7cd9bb Mon Sep 17 00:00:00 2001 From: panky-codes Date: Mon, 15 Mar 2021 21:35:36 +0100 Subject: [PATCH 10/14] Removed unused variables. Tested. --- src/displayapp/DisplayApp.cpp | 2 +- src/displayapp/screens/StopWatch.cpp | 10 +++++----- src/displayapp/screens/StopWatch.h | 5 ++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index ad58e13d..7fa2d127 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -205,7 +205,7 @@ void DisplayApp::RunningState() { case Apps::Twos: currentScreen.reset(new Screens::Twos(this)); break; case Apps::Paint: currentScreen.reset(new Screens::InfiniPaint(this, lvgl)); break; //TODO: Change it back - case Apps::StopWatch: currentScreen.reset(new Screens::StopWatch(this, dateTimeController)); break; + case Apps::StopWatch: currentScreen.reset(new Screens::StopWatch(this)); break; case Apps::Brightness : currentScreen.reset(new Screens::Brightness(this, brightnessController)); break; case Apps::Music : currentScreen.reset(new Screens::Music(this, systemTask.nimble().music())); break; case Apps::Navigation : currentScreen.reset(new Screens::Navigation(this, systemTask.nimble().navigation())); break; diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 733e92d9..b23194ab 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -36,18 +36,18 @@ namespace { } static void play_pause_event_handler(lv_obj_t* obj, lv_event_t event) { - StopWatch* stopWatch = static_cast(obj->user_data); + auto stopWatch = static_cast(obj->user_data); stopWatch->playPauseBtnEventHandler(event); } static void stop_lap_event_handler(lv_obj_t* obj, lv_event_t event) { - StopWatch* stopWatch = static_cast(obj->user_data); + auto stopWatch = static_cast(obj->user_data); stopWatch->stopLapBtnEventHandler(event); } -StopWatch::StopWatch(DisplayApp* app, const Pinetime::Controllers::DateTime& dateTime) - : Screen(app), dateTime {dateTime}, running {true}, currentState {States::INIT}, currentEvent {Events::STOP}, startTime {}, - oldTimeElapsed {}, currentTimeSeparated {}, lapBuffer {}, lapNr {}, lapPressed {false} { +StopWatch::StopWatch(DisplayApp* app) + : Screen(app), running {true}, currentState {States::INIT}, currentEvent {Events::STOP}, startTime {}, oldTimeElapsed {}, + currentTimeSeparated {}, lapBuffer {}, lapNr {}, lapPressed {false} { 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_extrabold_compressed); diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index a5cf5ceb..2b9c67a4 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -63,7 +63,7 @@ namespace Pinetime::Applications::Screens { class StopWatch : public Screen { public: - StopWatch(DisplayApp* app, const Pinetime::Controllers::DateTime& dateTime); + StopWatch(DisplayApp* app); ~StopWatch() override; bool Refresh() override; bool OnButtonPushed() override; @@ -71,7 +71,6 @@ namespace Pinetime::Applications::Screens { void stopLapBtnEventHandler(lv_event_t event); private: - const Pinetime::Controllers::DateTime& dateTime; bool running; States currentState; Events currentEvent; @@ -84,4 +83,4 @@ namespace Pinetime::Applications::Screens { lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap; lv_obj_t *lapOneText, *lapTwoText; }; -} \ No newline at end of file +} From 754ac233040af805ffa2e15b24539d5d02a876e5 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Sat, 20 Mar 2021 22:42:13 +0100 Subject: [PATCH 11/14] Reworked based on PR comments. --- .vscode/settings.json | 19 ++++++++++ src/displayapp/screens/ApplicationList.cpp | 9 +++-- src/displayapp/screens/StopWatch.cpp | 42 +++++++++++----------- src/displayapp/screens/StopWatch.h | 24 ++++++------- 4 files changed, 56 insertions(+), 38 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..2865af94 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,19 @@ +{ + "cmake.configureArgs": [ + "-DARM_NONE_EABI_TOOLCHAIN_PATH=/home/panky92/embedded/gcc-arm-none-eabi-9-2020-q2-update", + "-DNRF5_SDK_PATH=/home/panky92/embedded/nRF5_sdk", + "-DUSE_OPENOCD=1" + ], + "cmake.buildTask": true, + "files.associations": { + "streambuf": "cpp", + "chrono": "cpp", + "tuple": "cpp", + "functional": "cpp", + "*.tcc": "cpp", + "string": "cpp", + "fstream": "cpp", + "iosfwd": "cpp", + "nrf_rtc.h": "c" + } +} \ No newline at end of file diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp index 6d4cc8d8..f9ff49e3 100644 --- a/src/displayapp/screens/ApplicationList.cpp +++ b/src/displayapp/screens/ApplicationList.cpp @@ -57,12 +57,11 @@ std::unique_ptr ApplicationList::CreateScreen1() { std::unique_ptr ApplicationList::CreateScreen2() { std::array applications { {{Symbols::map, Apps::Navigation}, - {Symbols::asterisk, Apps::Meter}, + {Symbols::stopWatch, Apps::StopWatch}, {Symbols::paintbrush, Apps::Paint}, - {Symbols::info, Apps::Notifications}, - //TODO: Need to find the right place based on comments from JF - {Symbols::stopWatch, Apps::StopWatch}, - {"2", Apps::Twos} + {Symbols::info, Apps::Notifications}, + {Symbols::paddle, Apps::Paddle}, + {"2", Apps::Twos} } }; diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index b23194ab..63f18d4b 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -46,7 +46,7 @@ static void stop_lap_event_handler(lv_obj_t* obj, lv_event_t event) { } StopWatch::StopWatch(DisplayApp* app) - : Screen(app), running {true}, currentState {States::INIT}, currentEvent {Events::STOP}, startTime {}, oldTimeElapsed {}, + : Screen(app), running {true}, currentState {States::Init}, currentEvent {Events::Stop}, startTime {}, oldTimeElapsed {}, currentTimeSeparated {}, lapBuffer {}, lapNr {}, lapPressed {false} { time = lv_label_create(lv_scr_act(), nullptr); @@ -87,9 +87,9 @@ StopWatch::~StopWatch() { bool StopWatch::Refresh() { // @startuml CHIP8_state - // State "INIT" as init - // State "RUNNING" as run - // State "HALTED" as halt + // State "Init" as init + // State "Running" as run + // State "Halted" as halt // [*] --> init // init -> run : press play @@ -102,7 +102,7 @@ bool StopWatch::Refresh() { switch (currentState) { // Init state when an user first opens the app // and when a stop/reset button is pressed - case States::INIT: { + case States::Init: { if (btnStopLap) { lv_obj_del(btnStopLap); } @@ -115,7 +115,7 @@ bool StopWatch::Refresh() { lapBuffer.clearBuffer(); lapNr = 0; - if (currentEvent == Events::PLAY) { + if (currentEvent == Events::Play) { btnStopLap = lv_btn_create(lv_scr_act(), nullptr); btnStopLap->user_data = this; lv_obj_set_event_cb(btnStopLap, stop_lap_event_handler); @@ -125,11 +125,11 @@ bool StopWatch::Refresh() { lv_label_set_text(txtStopLap, Symbols::lapsFlag); startTime = xTaskGetTickCount(); - currentState = States::RUNNING; + currentState = States::Running; } break; } - case States::RUNNING: { + case States::Running: { lv_label_set_text(txtPlayPause, Symbols::pause); lv_label_set_text(txtStopLap, Symbols::lapsFlag); @@ -150,25 +150,25 @@ bool StopWatch::Refresh() { lapPressed = false; } - if (currentEvent == Events::PAUSE) { + if (currentEvent == Events::Pause) { // Reset the start time startTime = 0; // Store the current time elapsed in cache oldTimeElapsed += timeElapsed; - currentState = States::HALTED; + currentState = States::Halted; } break; } - case States::HALTED: { + case States::Halted: { lv_label_set_text(txtPlayPause, Symbols::play); lv_label_set_text(txtStopLap, Symbols::stop); - if (currentEvent == Events::PLAY) { + if (currentEvent == Events::Play) { startTime = xTaskGetTickCount(); - currentState = States::RUNNING; + currentState = States::Running; } - if (currentEvent == Events::STOP) { - currentState = States::INIT; + if (currentEvent == Events::Stop) { + currentState = States::Init; oldTimeElapsed = 0; } break; @@ -184,11 +184,11 @@ bool StopWatch::OnButtonPushed() { void StopWatch::playPauseBtnEventHandler(lv_event_t event) { if (event == LV_EVENT_CLICKED) { - if (currentState == States::INIT) { - currentEvent = Events::PLAY; + if (currentState == States::Init) { + currentEvent = Events::Play; } else { // Simple Toggle for play/pause - currentEvent = (currentEvent == Events::PLAY ? Events::PAUSE : Events::PLAY); + currentEvent = (currentEvent == Events::Play ? Events::Pause : Events::Play); } } } @@ -196,13 +196,13 @@ void StopWatch::playPauseBtnEventHandler(lv_event_t event) { void StopWatch::stopLapBtnEventHandler(lv_event_t event) { if (event == LV_EVENT_CLICKED) { // If running, then this button is used to save laps - if (currentState == States::RUNNING) { + if (currentState == States::Running) { lapBuffer.addLaps(currentTimeSeparated); lapNr++; lapPressed = true; - } else if (currentState == States::HALTED) { - currentEvent = Events::STOP; + } else if (currentState == States::Halted) { + currentEvent = Events::Stop; } else { // Not possible to reach here. Do nothing. } diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index 2b9c67a4..f9dd5c76 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -11,9 +11,9 @@ namespace Pinetime::Applications::Screens { - enum class States { INIT, RUNNING, HALTED }; + enum class States { Init, Running, Halted }; - enum class Events { PLAY, PAUSE, STOP }; + enum class Events { Play, Pause, Stop }; struct TimeSeparated_t { int mins; @@ -23,40 +23,40 @@ namespace Pinetime::Applications::Screens { // A simple buffer to hold the latest two laps template struct LapTextBuffer_t { - LapTextBuffer_t() : _arr {}, currentSz {}, capacity {N}, head {-1} { + LapTextBuffer_t() : buffer {}, currentSize {}, capacity {N}, head {-1} { } void addLaps(const TimeSeparated_t& timeVal) { head++; head %= capacity; - _arr[head] = timeVal; + buffer[head] = timeVal; - if (currentSz < capacity) { - currentSz++; + if (currentSize < capacity) { + currentSize++; } } void clearBuffer() { - _arr = {}; - currentSz = 0; + 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 < currentSz) { + if (idx < currentSize) { // This transformation is to ensure that head is always pointing to index 0. const auto transformed_idx = (head - idx) % capacity; - return (&_arr[transformed_idx]); + return (&buffer[transformed_idx]); } } return nullptr; } private: - std::array _arr; - uint8_t currentSz; + std::array buffer; + uint8_t currentSize; uint8_t capacity; int8_t head; }; From bb12ae9d6548ca2e106d39f1c117397f93a16669 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Sun, 21 Mar 2021 10:43:14 +0100 Subject: [PATCH 12/14] Updated lvgl submodule to match with develop branch --- src/libs/lvgl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/lvgl b/src/libs/lvgl index b89c30ea..69a50b97 160000 --- a/src/libs/lvgl +++ b/src/libs/lvgl @@ -1 +1 @@ -Subproject commit b89c30eafe1397a778ae5d65f108a0ef820de124 +Subproject commit 69a50b97dafffddd212e4b006776b473951be7a6 From dd9d6cd23ed6b65a33d4fc377ee304f2dfec2742 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Sun, 21 Mar 2021 11:15:31 +0100 Subject: [PATCH 13/14] Reverted the paddle app in displayapp.cpp --- src/displayapp/DisplayApp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index d29864e8..2e81c99b 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -205,10 +205,10 @@ void DisplayApp::RunningState() { break; case Apps::SysInfo: currentScreen.reset(new Screens::SystemInfo(this, dateTimeController, batteryController, brightnessController, bleController, watchdog)); break; case Apps::Meter: currentScreen.reset(new Screens::Meter(this)); break; + case Apps::StopWatch: currentScreen.reset(new Screens::StopWatch(this)); break; case Apps::Twos: currentScreen.reset(new Screens::Twos(this)); break; case Apps::Paint: currentScreen.reset(new Screens::InfiniPaint(this, lvgl)); break; - //TODO: Change it back - case Apps::StopWatch: currentScreen.reset(new Screens::StopWatch(this)); break; + case Apps::Paddle: currentScreen.reset(new Screens::Paddle(this, lvgl)); break; case Apps::Brightness : currentScreen.reset(new Screens::Brightness(this, brightnessController)); break; case Apps::Music : currentScreen.reset(new Screens::Music(this, systemTask.nimble().music())); break; case Apps::Navigation : currentScreen.reset(new Screens::Navigation(this, systemTask.nimble().navigation())); break; From 49f30189ef9243a9ed863d62c6673e381139bd79 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Sun, 21 Mar 2021 13:59:18 +0100 Subject: [PATCH 14/14] Added stopwatch app to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c277b36c..96e35d8f 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ As of now, here is the list of achievements of this project: * Notification (displays the last notification received) * Paddle (single player pong-like game) * Two (2048 clone game) + * Stopwatch (with all the necessary functions such as play, pause, lap, stop) - Supported by 2 companion apps (development is in progress): * [Gadgetbridge](https://codeberg.org/Freeyourgadget/Gadgetbridge/) (on Android) * [Amazfish](https://openrepos.net/content/piggz/amazfish) (on SailfishOS and Linux)