From 8c53d0b70baa03c2b07360444a7cd0ad99bb8381 Mon Sep 17 00:00:00 2001 From: Joaquim Date: Wed, 24 Feb 2021 19:40:24 +0000 Subject: Multi face support, analog clock, 12/24 config --- src/displayapp/screens/ApplicationList.cpp | 17 +- src/displayapp/screens/ApplicationList.h | 6 +- src/displayapp/screens/Clock.cpp | 256 +++++----------------------- src/displayapp/screens/Clock.h | 69 ++------ src/displayapp/screens/Screen.h | 20 +++ src/displayapp/screens/ScreenList.h | 111 +++++++++--- src/displayapp/screens/SystemInfo.cpp | 7 +- src/displayapp/screens/Tile.cpp | 5 +- src/displayapp/screens/Tile.h | 3 +- src/displayapp/screens/WatchFaceAnalog.cpp | 214 +++++++++++++++++++++++ src/displayapp/screens/WatchFaceAnalog.h | 90 ++++++++++ src/displayapp/screens/WatchFaceDigital.cpp | 254 +++++++++++++++++++++++++++ src/displayapp/screens/WatchFaceDigital.h | 82 +++++++++ 13 files changed, 832 insertions(+), 302 deletions(-) create mode 100644 src/displayapp/screens/WatchFaceAnalog.cpp create mode 100644 src/displayapp/screens/WatchFaceAnalog.h create mode 100644 src/displayapp/screens/WatchFaceDigital.cpp create mode 100644 src/displayapp/screens/WatchFaceDigital.h (limited to 'src/displayapp/screens') diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp index 531636eb..0f3286df 100644 --- a/src/displayapp/screens/ApplicationList.cpp +++ b/src/displayapp/screens/ApplicationList.cpp @@ -8,13 +8,18 @@ using namespace Pinetime::Applications::Screens; -ApplicationList::ApplicationList(Pinetime::Applications::DisplayApp *app) : +ApplicationList::ApplicationList(Pinetime::Applications::DisplayApp *app, + Pinetime::Controllers::Settings &settingsController) : Screen(app), - screens{app, { + settingsController{settingsController}, + screens{app, + settingsController.GetAppMenu(), + { [this]() -> std::unique_ptr { return CreateScreen1(); }, [this]() -> std::unique_ptr { return CreateScreen2(); }, //[this]() -> std::unique_ptr { return CreateScreen3(); } - } + }, + Screens::ScreenListModes::UpDown } {} @@ -51,7 +56,7 @@ std::unique_ptr ApplicationList::CreateScreen1() { }; - return std::unique_ptr(new Screens::Tile(app, applications)); + return std::unique_ptr(new Screens::Tile(0, app, settingsController, applications)); } std::unique_ptr ApplicationList::CreateScreen2() { @@ -65,7 +70,7 @@ std::unique_ptr ApplicationList::CreateScreen2() { } }; - return std::unique_ptr(new Screens::Tile(app, applications)); + return std::unique_ptr(new Screens::Tile(1, app, settingsController, applications)); } std::unique_ptr ApplicationList::CreateScreen3() { @@ -79,6 +84,6 @@ std::unique_ptr ApplicationList::CreateScreen3() { } }; - return std::unique_ptr(new Screens::Tile(app, applications)); + return std::unique_ptr(new Screens::Tile(2, app, settingsController, applications)); } diff --git a/src/displayapp/screens/ApplicationList.h b/src/displayapp/screens/ApplicationList.h index aefb2385..0a0c6388 100644 --- a/src/displayapp/screens/ApplicationList.h +++ b/src/displayapp/screens/ApplicationList.h @@ -10,12 +10,16 @@ namespace Pinetime { namespace Screens { class ApplicationList : public Screen { public: - explicit ApplicationList(DisplayApp* app); + explicit ApplicationList(DisplayApp* app, + Pinetime::Controllers::Settings &settingsController); ~ApplicationList() override; bool Refresh() override; bool OnButtonPushed() override; bool OnTouchEvent(TouchEvents event) override; private: + + Controllers::Settings& settingsController; + bool running = true; ScreenList<2> screens; diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp index 4b280adb..ea9ddd56 100644 --- a/src/displayapp/screens/Clock.cpp +++ b/src/displayapp/screens/Clock.cpp @@ -10,243 +10,73 @@ #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "components/ble/NotificationManager.h" -#include "components/heartrate/HeartRateController.h" #include "../DisplayApp.h" +#include "WatchFaceDigital.h" +#include "WatchFaceAnalog.h" -using namespace Pinetime::Applications::Screens; -static void event_handler(lv_obj_t * obj, lv_event_t event) { - Clock* screen = static_cast(obj->user_data); - screen->OnObjectEvent(obj, event); -} +using namespace Pinetime::Applications::Screens; Clock::Clock(DisplayApp* app, Controllers::DateTime& dateTimeController, Controllers::Battery& batteryController, Controllers::Ble& bleController, Controllers::NotificationManager& notificatioManager, - Controllers::HeartRateController& heartRateController): Screen(app), currentDateTime{{}}, - dateTimeController{dateTimeController}, batteryController{batteryController}, - bleController{bleController}, notificatioManager{notificatioManager}, - heartRateController{heartRateController} { - displayedChar[0] = 0; - displayedChar[1] = 0; - displayedChar[2] = 0; - displayedChar[3] = 0; - displayedChar[4] = 0; - - batteryIcon = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text(batteryIcon, Symbols::batteryFull); - lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 2); - - batteryPlug = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text(batteryPlug, Symbols::plug); - lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0); - - bleIcon = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text(bleIcon, Symbols::bluetooth); - lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0); - - notificationIcon = lv_label_create(lv_scr_act(), NULL); - lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false)); - lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 10, 0); - - label_date = lv_label_create(lv_scr_act(), nullptr); - - lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60); - - label_time = lv_label_create(lv_scr_act(), nullptr); - - lv_obj_set_style_local_text_font(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_extrabold_compressed); - - lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0); - - backgroundLabel = lv_label_create(lv_scr_act(), nullptr); - backgroundLabel->user_data = this; - lv_obj_set_click(backgroundLabel, true); - lv_obj_set_event_cb(backgroundLabel, event_handler); - lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP); - lv_obj_set_size(backgroundLabel, 240, 240); - lv_obj_set_pos(backgroundLabel, 0, 0); - lv_label_set_text(backgroundLabel, ""); - - - heartbeatIcon = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text(heartbeatIcon, Symbols::heartBeat); - lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2); - - heartbeatValue = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text(heartbeatValue, "0"); - lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0); - - heartbeatBpm = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text(heartbeatBpm, "BPM"); - lv_obj_align(heartbeatBpm, heartbeatValue, LV_ALIGN_OUT_RIGHT_MID, 5, 0); - - stepValue = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text(stepValue, "0"); - lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2); - - stepIcon = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text(stepIcon, Symbols::shoe); - lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0); -} + Controllers::Settings &settingsController, + Controllers::HeartRateController& heartRateController) : Screen(app), + dateTimeController{dateTimeController}, batteryController{batteryController}, + bleController{bleController}, notificatioManager{notificatioManager}, + settingsController{settingsController}, + heartRateController{heartRateController}, + screens{app, + settingsController.GetClockFace(), + { + [this]() -> std::unique_ptr { return WatchFaceDigitalScreen(); }, + [this]() -> std::unique_ptr { return WatchFaceAnalogScreen(); }, + //[this]() -> std::unique_ptr { return WatchFaceMinimalScreen(); }, + //[this]() -> std::unique_ptr { return WatchFaceCustomScreen(); } + }, + Screens::ScreenListModes::LongPress + } { + + settingsController.SetAppMenu(0); + + } Clock::~Clock() { lv_obj_clean(lv_scr_act()); } -bool Clock::Refresh() { - batteryPercentRemaining = batteryController.PercentRemaining(); - if (batteryPercentRemaining.IsUpdated()) { - auto batteryPercent = batteryPercentRemaining.Get(); - lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent)); - auto isCharging = batteryController.IsCharging() || batteryController.IsPowerPresent(); - lv_label_set_text(batteryPlug, BatteryIcon::GetPlugIcon(isCharging)); - } - - bleState = bleController.IsConnected(); - if (bleState.IsUpdated()) { - if(bleState.Get() == true) { - lv_label_set_text(bleIcon, BleIcon::GetIcon(true)); - } else { - lv_label_set_text(bleIcon, BleIcon::GetIcon(false)); - } - } - lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 5); - lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0); - lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0); - - notificationState = notificatioManager.AreNewNotificationsAvailable(); - if(notificationState.IsUpdated()) { - if(notificationState.Get() == true) - lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(true)); - else - lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false)); - } - - currentDateTime = dateTimeController.CurrentDateTime(); - - if(currentDateTime.IsUpdated()) { - auto newDateTime = currentDateTime.Get(); - - auto dp = date::floor(newDateTime); - auto time = date::make_time(newDateTime-dp); - auto yearMonthDay = date::year_month_day(dp); - - auto year = (int)yearMonthDay.year(); - auto month = static_cast((unsigned)yearMonthDay.month()); - auto day = (unsigned)yearMonthDay.day(); - auto dayOfWeek = static_cast(date::weekday(yearMonthDay).iso_encoding()); - - auto hour = time.hours().count(); - auto minute = time.minutes().count(); - - char minutesChar[3]; - sprintf(minutesChar, "%02d", static_cast(minute)); - - char hoursChar[3]; - sprintf(hoursChar, "%02d", static_cast(hour)); - - char timeStr[6]; - sprintf(timeStr, "%c%c:%c%c", hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]); - - if(hoursChar[0] != displayedChar[0] || hoursChar[1] != displayedChar[1] || minutesChar[0] != displayedChar[2] || minutesChar[1] != displayedChar[3]) { - displayedChar[0] = hoursChar[0]; - displayedChar[1] = hoursChar[1]; - displayedChar[2] = minutesChar[0]; - displayedChar[3] = minutesChar[1]; - - lv_label_set_text(label_time, timeStr); - } - - if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) { - char dateStr[22]; - sprintf(dateStr, "%s %d %s %d", DayOfWeekToString(dayOfWeek), day, MonthToString(month), year); - lv_label_set_text(label_date, dateStr); - - - currentYear = year; - currentMonth = month; - currentDayOfWeek = dayOfWeek; - currentDay = day; - } - } - - heartbeat = heartRateController.HeartRate(); - heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped; - if(heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) { - char heartbeatBuffer[4]; - if(heartbeatRunning.Get()) - sprintf(heartbeatBuffer, "%d", heartbeat.Get()); - else - sprintf(heartbeatBuffer, "---"); - - lv_label_set_text(heartbeatValue, heartbeatBuffer); - lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2); - lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0); - lv_obj_align(heartbeatBpm, heartbeatValue, LV_ALIGN_OUT_RIGHT_MID, 5, 0); - } - - // TODO stepCount = stepController.GetValue(); - if(stepCount.IsUpdated()) { - char stepBuffer[5]; - sprintf(stepBuffer, "%lu", stepCount.Get()); - lv_label_set_text(stepValue, stepBuffer); - lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2); - lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0); - } +bool Clock::Refresh() { + screens.Refresh(); return running; } -const char *Clock::MonthToString(Pinetime::Controllers::DateTime::Months month) { - return Clock::MonthsString[static_cast(month)]; +bool Clock::OnButtonPushed() { + running = false; + return false; } -const char *Clock::DayOfWeekToString(Pinetime::Controllers::DateTime::Days dayOfWeek) { - return Clock::DaysString[static_cast(dayOfWeek)]; +bool Clock::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + return screens.OnTouchEvent(event); } -char const *Clock::DaysString[] = { - "", - "MONDAY", - "TUESDAY", - "WEDNESDAY", - "THURSDAY", - "FRIDAY", - "SATURDAY", - "SUNDAY" -}; - -char const *Clock::MonthsString[] = { - "", - "JAN", - "FEB", - "MAR", - "APR", - "MAY", - "JUN", - "JUL", - "AUG", - "SEP", - "OCT", - "NOV", - "DEC" -}; - -void Clock::OnObjectEvent(lv_obj_t *obj, lv_event_t event) { - if(obj == backgroundLabel) { - if (event == LV_EVENT_CLICKED) { - - running = false; - } - } +std::unique_ptr Clock::WatchFaceDigitalScreen() { + return std::unique_ptr(new Screens::WatchFaceDigital(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController, heartRateController)); } -bool Clock::OnButtonPushed() { - running = false; - return false; +std::unique_ptr Clock::WatchFaceAnalogScreen() { + return std::unique_ptr(new Screens::WatchFaceAnalog(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController)); } +/* +// examples +std::unique_ptr Clock::WatchFaceMinimalScreen() { + return std::unique_ptr(new Screens::WatchFaceMinimal(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController)); +} +std::unique_ptr Clock::WatchFaceCustomScreen() { + return std::unique_ptr(new Screens::WatchFaceCustom(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController)); +} +*/ \ No newline at end of file diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h index 18d70532..2b1be4ac 100644 --- a/src/displayapp/screens/Clock.h +++ b/src/displayapp/screens/Clock.h @@ -5,38 +5,22 @@ #include #include #include "Screen.h" +#include "ScreenList.h" #include "components/datetime/DateTimeController.h" namespace Pinetime { + namespace Drivers { + class BMA421; + } namespace Controllers { + class Settings; class Battery; class Ble; class NotificationManager; - class HeartRateController; } namespace Applications { namespace Screens { - - template - class DirtyValue { - public: - DirtyValue() = default; // Use NSDMI - explicit DirtyValue(T const& v):value{v}{} // Use MIL and const-lvalue-ref - bool IsUpdated() const { return isUpdated; } - T const& Get() { this->isUpdated = false; return value; } // never expose a non-const lvalue-ref - DirtyValue& operator=(const T& other) { - if (this->value != other) { - this->value = other; - this->isUpdated = true; - } - return *this; - } - private: - T value{}; // NSDMI - default initialise type - bool isUpdated{true}; // NSDMI - use brace initilisation - }; - class Clock : public Screen { public: Clock(DisplayApp* app, @@ -44,53 +28,30 @@ namespace Pinetime { Controllers::Battery& batteryController, Controllers::Ble& bleController, Controllers::NotificationManager& notificatioManager, + Controllers::Settings &settingsController, Controllers::HeartRateController& heartRateController); ~Clock() override; bool Refresh() override; bool OnButtonPushed() override; + bool OnTouchEvent(TouchEvents event) override; - void OnObjectEvent(lv_obj_t *pObj, lv_event_t i); private: - static const char* MonthToString(Pinetime::Controllers::DateTime::Months month); - static const char* DayOfWeekToString(Pinetime::Controllers::DateTime::Days dayOfWeek); - static char const *DaysString[]; - static char const *MonthsString[]; - - char displayedChar[5]; - - uint16_t currentYear = 1970; - Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown; - Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; - uint8_t currentDay = 0; - - DirtyValue batteryPercentRemaining {}; - DirtyValue bleState {}; - DirtyValue> currentDateTime{}; - DirtyValue stepCount {}; - DirtyValue heartbeat {}; - DirtyValue heartbeatRunning {}; - DirtyValue notificationState {}; - - lv_obj_t* label_time; - lv_obj_t* label_date; - lv_obj_t* backgroundLabel; - lv_obj_t* batteryIcon; - lv_obj_t* bleIcon; - lv_obj_t* batteryPlug; - lv_obj_t* heartbeatIcon; - lv_obj_t* heartbeatValue; - lv_obj_t* heartbeatBpm; - lv_obj_t* stepIcon; - lv_obj_t* stepValue; - lv_obj_t* notificationIcon; Controllers::DateTime& dateTimeController; Controllers::Battery& batteryController; Controllers::Ble& bleController; Controllers::NotificationManager& notificatioManager; + Controllers::Settings& settingsController; Controllers::HeartRateController& heartRateController; + + ScreenList<2> screens; + std::unique_ptr WatchFaceDigitalScreen(); + std::unique_ptr WatchFaceAnalogScreen(); + std::unique_ptr WatchFaceMinimalScreen(); + std::unique_ptr WatchFaceCustomScreen(); + bool running = true; }; diff --git a/src/displayapp/screens/Screen.h b/src/displayapp/screens/Screen.h index 6b1d0eec..638dac99 100644 --- a/src/displayapp/screens/Screen.h +++ b/src/displayapp/screens/Screen.h @@ -7,6 +7,26 @@ namespace Pinetime { namespace Applications { class DisplayApp; namespace Screens { + + template + class DirtyValue { + public: + DirtyValue() = default; // Use NSDMI + explicit DirtyValue(T const& v):value{v}{} // Use MIL and const-lvalue-ref + bool IsUpdated() const { return isUpdated; } + T const& Get() { this->isUpdated = false; return value; } // never expose a non-const lvalue-ref + DirtyValue& operator=(const T& other) { + if (this->value != other) { + this->value = other; + this->isUpdated = true; + } + return *this; + } + private: + T value{}; // NSDMI - default initialise type + bool isUpdated{true}; // NSDMI - use brace initilisation + }; + class Screen { public: explicit Screen(DisplayApp* app) : app{app} {} diff --git a/src/displayapp/screens/ScreenList.h b/src/displayapp/screens/ScreenList.h index 736e3634..56d9abe0 100644 --- a/src/displayapp/screens/ScreenList.h +++ b/src/displayapp/screens/ScreenList.h @@ -9,16 +9,33 @@ namespace Pinetime { namespace Applications { namespace Screens { + + enum class ScreenListModes {UpDown, RightLeft, LongPress}; template class ScreenList : public Screen { public: - ScreenList(DisplayApp* app, std::array()>, N>&& screens) - : Screen(app), screens{std::move(screens)}, current{this->screens[0]()} { + ScreenList( + DisplayApp* app, + uint8_t initScreen, + std::array()>, N>&& screens, + ScreenListModes mode + ) + : Screen(app), + initScreen{initScreen}, + screens{std::move(screens)}, + mode{mode}, + current{this->screens[initScreen]()} + { + screenIndex = initScreen; } ~ScreenList() override { - + current.reset(nullptr); + /*for(uint8_t i = 0; i < screens.size(); i++) { + screens[i]().reset(nullptr); + }*/ + lv_obj_clean(lv_scr_act()); } bool Refresh() override { @@ -32,34 +49,80 @@ namespace Pinetime { } bool OnTouchEvent(TouchEvents event) override { - switch (event) { - case TouchEvents::SwipeDown: - if (screenIndex > 0) { - current.reset(nullptr); - app->SetFullRefresh(DisplayApp::FullRefreshDirections::Down); - screenIndex--; - current = screens[screenIndex](); - } - return true; - case TouchEvents::SwipeUp: - if (screenIndex < screens.size() - 1) { - current.reset(nullptr); - app->SetFullRefresh(DisplayApp::FullRefreshDirections::Up); - screenIndex++; - current = screens[screenIndex](); - } - return true; - default: - return false; + + if ( mode == ScreenListModes::UpDown) { + switch (event) { + case TouchEvents::SwipeDown: + if (screenIndex > 0) { + current.reset(nullptr); + app->SetFullRefresh(DisplayApp::FullRefreshDirections::Down); + screenIndex--; + current = screens[screenIndex](); + return true; + } else { + return false; + } + + case TouchEvents::SwipeUp: + if (screenIndex < screens.size() - 1) { + current.reset(nullptr); + app->SetFullRefresh(DisplayApp::FullRefreshDirections::Up); + screenIndex++; + current = screens[screenIndex](); + } + return true; + default: + return false; + } + } else if ( mode == ScreenListModes::RightLeft) { + switch (event) { + case TouchEvents::SwipeRight: + if (screenIndex > 0) { + current.reset(nullptr); + app->SetFullRefresh(DisplayApp::FullRefreshDirections::None); + screenIndex--; + current = screens[screenIndex](); + return true; + } else { + return false; + } + + case TouchEvents::SwipeLeft: + if (screenIndex < screens.size() - 1) { + current.reset(nullptr); + app->SetFullRefresh(DisplayApp::FullRefreshDirections::None); + screenIndex++; + current = screens[screenIndex](); + } + return true; + default: + return false; + } + } else if ( event == TouchEvents::LongTap ) { + if (screenIndex < screens.size() - 1) { + screenIndex++; + } else { + screenIndex = 0; + } + current.reset(nullptr); + app->SetFullRefresh(DisplayApp::FullRefreshDirections::None); + current = screens[screenIndex](); + return true; } + return false; } private: - bool running = true; - uint8_t screenIndex = 0; + + uint8_t initScreen = 0; std::array()>, N> screens; + ScreenListModes mode = ScreenListModes::UpDown; + + uint8_t screenIndex = 0; std::unique_ptr current; + + bool running = true; }; } } diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index 2de5dada..3c6d1d9d 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -20,11 +20,14 @@ SystemInfo::SystemInfo(Pinetime::Applications::DisplayApp *app, Screen(app), dateTimeController{dateTimeController}, batteryController{batteryController}, brightnessController{brightnessController}, bleController{bleController}, watchdog{watchdog}, - screens{app, { + screens{app, + 0, + { [this]() -> std::unique_ptr { return CreateScreen1(); }, [this]() -> std::unique_ptr { return CreateScreen2(); }, [this]() -> std::unique_ptr { return CreateScreen3(); } - } + }, + Screens::ScreenListModes::UpDown } {} diff --git a/src/displayapp/screens/Tile.cpp b/src/displayapp/screens/Tile.cpp index 3b82b060..ca753db9 100644 --- a/src/displayapp/screens/Tile.cpp +++ b/src/displayapp/screens/Tile.cpp @@ -10,7 +10,10 @@ static void event_handler(lv_obj_t * obj, lv_event_t event) { screen->OnObjectEvent(obj, event, eventData); } -Tile::Tile(DisplayApp* app, std::array& applications) : Screen(app) { +Tile::Tile(uint8_t screenID, DisplayApp* app, Controllers::Settings& settingsController, std::array& applications) : Screen(app) { + + settingsController.SetAppMenu(screenID); + for(int i = 0, appIndex = 0; i < 8; i++) { if(i == 3) btnm_map1[i] = "\n"; else if(i == 7) btnm_map1[i] = ""; diff --git a/src/displayapp/screens/Tile.h b/src/displayapp/screens/Tile.h index 55ed45e3..f717a220 100644 --- a/src/displayapp/screens/Tile.h +++ b/src/displayapp/screens/Tile.h @@ -5,6 +5,7 @@ #include #include "Screen.h" #include "../Apps.h" +#include "components/settings/Settings.h" namespace Pinetime { namespace Applications { @@ -16,7 +17,7 @@ namespace Pinetime { Pinetime::Applications::Apps application; }; - explicit Tile(DisplayApp* app, std::array& applications); + explicit Tile(uint8_t screenID, DisplayApp* app, Controllers::Settings& settingsController, std::array& applications); ~Tile() override; bool Refresh() override; diff --git a/src/displayapp/screens/WatchFaceAnalog.cpp b/src/displayapp/screens/WatchFaceAnalog.cpp new file mode 100644 index 00000000..efca10c2 --- /dev/null +++ b/src/displayapp/screens/WatchFaceAnalog.cpp @@ -0,0 +1,214 @@ +#include +#include "WatchFaceAnalog.h" +#include "BatteryIcon.h" +#include "BleIcon.h" +#include "Symbols.h" +#include "NotificationIcon.h" + +LV_IMG_DECLARE(bg_clock); + +using namespace Pinetime::Applications::Screens; + +#define HOUR_LENGTH 70 +#define MINUTE_LENGTH 90 +#define SECOND_LENGTH 110 +#define PI 3.14159265358979323846 + +// ## +static int16_t coordinate_x_relocate(int16_t x) +{ + return ((x) + LV_HOR_RES / 2); +} + +// ## +static int16_t coordinate_y_relocate(int16_t y) +{ + return (((y) - LV_HOR_RES / 2) < 0) ? (0 - ((y) - LV_HOR_RES / 2)) : ((y) - LV_HOR_RES / 2); +} + +WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp *app, + Controllers::DateTime& dateTimeController, + Controllers::Battery& batteryController, + Controllers::Ble& bleController, + Controllers::NotificationManager& notificatioManager, + Controllers::Settings &settingsController) : Screen(app), currentDateTime{{}}, + dateTimeController{dateTimeController}, batteryController{batteryController}, + bleController{bleController}, notificatioManager{notificatioManager}, + settingsController{settingsController} { + settingsController.SetClockFace(1); + + sHour = 99; + sMinute = 99; + sSecond = 99; + + lv_obj_t * bg_clock_img = lv_img_create(lv_scr_act(), NULL); + lv_img_set_src(bg_clock_img, &bg_clock); + lv_obj_align(bg_clock_img, NULL, LV_ALIGN_CENTER, 0, 0); + + batteryIcon = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text(batteryIcon, Symbols::batteryHalf); + lv_obj_align(batteryIcon, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, -8, -4); + + + notificationIcon = lv_label_create(lv_scr_act(), NULL); + lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00)); + lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false)); + lv_obj_align(notificationIcon, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 8, -4); + + // Date - Day / Week day + + label_date_day = lv_label_create(lv_scr_act(), NULL); + lv_obj_set_style_local_text_color(label_date_day, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xf0a500)); + lv_label_set_text_fmt(label_date_day, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), dateTimeController.Day()); + lv_label_set_align( label_date_day, LV_LABEL_ALIGN_CENTER ); + lv_obj_align(label_date_day, NULL, LV_ALIGN_CENTER, 50, 0); + + minute_body = lv_line_create(lv_scr_act(), NULL); + minute_body_trace = lv_line_create(lv_scr_act(), NULL); + hour_body = lv_line_create(lv_scr_act(), NULL); + hour_body_trace = lv_line_create(lv_scr_act(), NULL); + second_body = lv_line_create(lv_scr_act(), NULL); + + + lv_style_init(&second_line_style); + lv_style_set_line_width(&second_line_style, LV_STATE_DEFAULT, 3); + lv_style_set_line_color(&second_line_style, LV_STATE_DEFAULT, LV_COLOR_RED); + lv_style_set_line_rounded(&second_line_style, LV_STATE_DEFAULT, true); + lv_obj_add_style(second_body, LV_LINE_PART_MAIN, &second_line_style); + + lv_style_init(&minute_line_style); + lv_style_set_line_width(&minute_line_style, LV_STATE_DEFAULT, 7); + lv_style_set_line_color(&minute_line_style, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_style_set_line_rounded(&minute_line_style, LV_STATE_DEFAULT, true); + lv_obj_add_style(minute_body, LV_LINE_PART_MAIN, &minute_line_style); + + lv_style_init(&minute_line_style_trace); + lv_style_set_line_width(&minute_line_style_trace, LV_STATE_DEFAULT, 3); + lv_style_set_line_color(&minute_line_style_trace, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_style_set_line_rounded(&minute_line_style_trace, LV_STATE_DEFAULT, false); + lv_obj_add_style(minute_body_trace, LV_LINE_PART_MAIN, &minute_line_style_trace); + + + lv_style_init(&hour_line_style); + lv_style_set_line_width(&hour_line_style, LV_STATE_DEFAULT, 7); + lv_style_set_line_color(&hour_line_style, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_style_set_line_rounded(&hour_line_style, LV_STATE_DEFAULT, true); + lv_obj_add_style(hour_body, LV_LINE_PART_MAIN, &hour_line_style); + + lv_style_init(&hour_line_style_trace); + lv_style_set_line_width(&hour_line_style_trace, LV_STATE_DEFAULT, 3); + lv_style_set_line_color(&hour_line_style_trace, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_style_set_line_rounded(&hour_line_style_trace, LV_STATE_DEFAULT, false); + lv_obj_add_style(hour_body_trace, LV_LINE_PART_MAIN, &hour_line_style_trace); + + UpdateClock(); + + /*lv_obj_t* backgroundLabel = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP); + lv_obj_set_size(backgroundLabel, 240, 240); + lv_obj_set_pos(backgroundLabel, 0, 0); + lv_label_set_text_static(backgroundLabel, "");*/ + +} + +WatchFaceAnalog::~WatchFaceAnalog() { + + lv_style_reset(&hour_line_style); + lv_style_reset(&hour_line_style_trace); + lv_style_reset(&minute_line_style); + lv_style_reset(&minute_line_style_trace); + lv_style_reset(&second_line_style); + + lv_obj_clean(lv_scr_act()); +} + +void WatchFaceAnalog::UpdateClock() { + + hour = dateTimeController.Hours(); + minute = dateTimeController.Minutes(); + second = dateTimeController.Seconds(); + + if(sMinute != minute) { + minute_point[0].x = coordinate_x_relocate(30 * sin(minute * 6 * PI / 180)); + minute_point[0].y = coordinate_y_relocate(30 * cos(minute * 6 * PI / 180)); + minute_point[1].x = coordinate_x_relocate(MINUTE_LENGTH * sin(minute * 6 * PI / 180)); + minute_point[1].y = coordinate_y_relocate(MINUTE_LENGTH * cos(minute * 6 * PI / 180)); + + minute_point_trace[0].x = coordinate_x_relocate(5 * sin(minute * 6 * PI / 180)); + minute_point_trace[0].y = coordinate_y_relocate(5 * cos(minute * 6 * PI / 180)); + minute_point_trace[1].x = coordinate_x_relocate(31 * sin(minute * 6 * PI / 180)); + minute_point_trace[1].y = coordinate_y_relocate(31 * cos(minute * 6 * PI / 180)); + + lv_line_set_points(minute_body, minute_point, 2); + lv_line_set_points(minute_body_trace, minute_point_trace, 2); + } + + if(sHour != hour || sMinute != minute) { + sHour = hour; + sMinute = minute; + hour_point[0].x = coordinate_x_relocate(30 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); + hour_point[0].y = coordinate_y_relocate(30 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); + hour_point[1].x = coordinate_x_relocate(HOUR_LENGTH * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); + hour_point[1].y = coordinate_y_relocate(HOUR_LENGTH * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); + + hour_point_trace[0].x = coordinate_x_relocate(5 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); + hour_point_trace[0].y = coordinate_y_relocate(5 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); + hour_point_trace[1].x = coordinate_x_relocate(31 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); + hour_point_trace[1].y = coordinate_y_relocate(31 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180)); + + lv_line_set_points(hour_body, hour_point, 2); + lv_line_set_points(hour_body_trace, hour_point_trace, 2); + } + + if(sSecond != second) { + sSecond = second; + second_point[0].x = coordinate_x_relocate(20 * sin((180 + second * 6) * PI / 180)); + second_point[0].y = coordinate_y_relocate(20 * cos((180 + second * 6) * PI / 180)); + second_point[1].x = coordinate_x_relocate(SECOND_LENGTH * sin(second * 6 * PI / 180)); + second_point[1].y = coordinate_y_relocate(SECOND_LENGTH * cos(second * 6 * PI / 180)); + lv_line_set_points(second_body, second_point, 2); + + } +} + + +bool WatchFaceAnalog::Refresh() { + + batteryPercentRemaining = batteryController.PercentRemaining(); + if (batteryPercentRemaining.IsUpdated()) { + auto batteryPercent = batteryPercentRemaining.Get(); + lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent)); + } + + + notificationState = notificatioManager.AreNewNotificationsAvailable(); + + if(notificationState.IsUpdated()) { + if(notificationState.Get() == true) + lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(true)); + else + lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false)); + } + + currentDateTime = dateTimeController.CurrentDateTime(); + + if(currentDateTime.IsUpdated()) { + + month = dateTimeController.Month(); + day = dateTimeController.Day(); + dayOfWeek = dateTimeController.DayOfWeek(); + + UpdateClock(); + + if ((month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) { + + lv_label_set_text_fmt(label_date_day, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), day); + + currentMonth = month; + currentDayOfWeek = dayOfWeek; + currentDay = day; + } + } + + return true; +} \ No newline at end of file diff --git a/src/displayapp/screens/WatchFaceAnalog.h b/src/displayapp/screens/WatchFaceAnalog.h new file mode 100644 index 00000000..56b086ab --- /dev/null +++ b/src/displayapp/screens/WatchFaceAnalog.h @@ -0,0 +1,90 @@ +#pragma once + +#include +#include +#include +#include +#include "Screen.h" +#include "ScreenList.h" +#include "components/datetime/DateTimeController.h" +#include "components/battery/BatteryController.h" +#include "components/ble/BleController.h" +#include "components/ble/NotificationManager.h" + +namespace Pinetime { + namespace Controllers { + class Settings; + class Battery; + class Ble; + class NotificationManager; + } + namespace Applications { + namespace Screens { + + class WatchFaceAnalog : public Screen { + public: + WatchFaceAnalog(DisplayApp* app, + Controllers::DateTime& dateTimeController, + Controllers::Battery& batteryController, + Controllers::Ble& bleController, + Controllers::NotificationManager& notificatioManager, + Controllers::Settings &settingsController); + + ~WatchFaceAnalog() override; + + bool Refresh() override; + + private: + uint8_t sHour, sMinute, sSecond; + uint8_t hour; + uint8_t minute; + uint8_t second; + + Pinetime::Controllers::DateTime::Months month; + uint8_t day; + Pinetime::Controllers::DateTime::Days dayOfWeek; + + Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown; + Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; + uint8_t currentDay = 0; + + DirtyValue batteryPercentRemaining {0}; + DirtyValue> currentDateTime; + DirtyValue notificationState {false}; + + lv_obj_t *hour_body; + lv_obj_t *hour_body_trace; + lv_obj_t *minute_body; + lv_obj_t *minute_body_trace; + lv_obj_t *second_body; + + // ## + lv_point_t hour_point[2]; + lv_point_t hour_point_trace[2]; + lv_point_t minute_point[2]; + lv_point_t minute_point_trace[2]; + lv_point_t second_point[2]; + + // ## + lv_style_t hour_line_style; + lv_style_t hour_line_style_trace; + lv_style_t minute_line_style; + lv_style_t minute_line_style_trace; + lv_style_t second_line_style; + + lv_obj_t* label_date_day; + lv_obj_t* batteryIcon; + lv_obj_t* notificationIcon; + + + Controllers::DateTime& dateTimeController; + Controllers::Battery& batteryController; + Controllers::Ble& bleController; + Controllers::NotificationManager& notificatioManager; + Controllers::Settings& settingsController; + + void UpdateClock(); + }; + } + } +} \ No newline at end of file diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp new file mode 100644 index 00000000..99df318a --- /dev/null +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -0,0 +1,254 @@ +#include "WatchFaceDigital.h" + +#include +#include +#include +#include "BatteryIcon.h" +#include "BleIcon.h" +#include "NotificationIcon.h" +#include "Symbols.h" +#include "components/battery/BatteryController.h" +#include "components/ble/BleController.h" +#include "components/ble/NotificationManager.h" +#include "components/heartrate/HeartRateController.h" +#include "components/settings/Settings.h" +#include "../DisplayApp.h" + +using namespace Pinetime::Applications::Screens; + + +WatchFaceDigital::WatchFaceDigital(DisplayApp* app, + Controllers::DateTime& dateTimeController, + Controllers::Battery& batteryController, + Controllers::Ble& bleController, + Controllers::NotificationManager& notificatioManager, + Controllers::Settings &settingsController, + Controllers::HeartRateController& heartRateController): Screen(app), currentDateTime{{}}, + dateTimeController{dateTimeController}, batteryController{batteryController}, + bleController{bleController}, notificatioManager{notificatioManager}, + settingsController{settingsController}, + heartRateController{heartRateController} { + settingsController.SetClockFace(0); + + // init + /*currentDateTime = dateTimeController.CurrentDateTime(); + batteryPercentRemaining = batteryController.PercentRemaining(); + bleState = bleController.IsConnected(); + notificationState = notificatioManager.AreNewNotificationsAvailable(); + heartbeat = heartRateController.HeartRate();*/ + + displayedChar[0] = 0; + displayedChar[1] = 0; + displayedChar[2] = 0; + displayedChar[3] = 0; + displayedChar[4] = 0; + + batteryIcon = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text(batteryIcon, Symbols::batteryFull); + lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 2); + + batteryPlug = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(batteryPlug, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFF0000)); + lv_label_set_text(batteryPlug, Symbols::plug); + lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0); + + bleIcon = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x0000FF)); + lv_label_set_text(bleIcon, Symbols::bluetooth); + lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0); + + notificationIcon = lv_label_create(lv_scr_act(), NULL); + lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00)); + lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false)); + lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 10, 0); + + label_date = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_CENTER, 0, 60); + lv_obj_set_style_local_text_color(label_date, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x999999)); + + label_time = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_extrabold_compressed); + + lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0); + + label_time_ampm = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(label_time_ampm, ""); + lv_obj_align(label_time_ampm, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -30, -55); + + backgroundLabel = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_click(backgroundLabel, true); + lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP); + lv_obj_set_size(backgroundLabel, 240, 240); + lv_obj_set_pos(backgroundLabel, 0, 0); + lv_label_set_text(backgroundLabel, ""); + + + heartbeatIcon = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text(heartbeatIcon, Symbols::heartBeat); + lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B)); + lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2); + + heartbeatValue = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B)); + lv_label_set_text(heartbeatValue, "---"); + lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0); + + heartbeatBpm = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(heartbeatBpm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B)); + lv_label_set_text(heartbeatBpm, "BPM"); + lv_obj_align(heartbeatBpm, heartbeatValue, LV_ALIGN_OUT_RIGHT_MID, 5, 0); + + stepValue = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FFE7)); + lv_label_set_text(stepValue, "0"); + lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2); + + stepIcon = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FFE7)); + lv_label_set_text(stepIcon, Symbols::shoe); + lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0); +} + +WatchFaceDigital::~WatchFaceDigital() { + lv_obj_clean(lv_scr_act()); +} + +bool WatchFaceDigital::Refresh() { + batteryPercentRemaining = batteryController.PercentRemaining(); + if (batteryPercentRemaining.IsUpdated()) { + auto batteryPercent = batteryPercentRemaining.Get(); + lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent)); + auto isCharging = batteryController.IsCharging() || batteryController.IsPowerPresent(); + lv_label_set_text(batteryPlug, BatteryIcon::GetPlugIcon(isCharging)); + } + + bleState = bleController.IsConnected(); + if (bleState.IsUpdated()) { + if(bleState.Get() == true) { + lv_label_set_text(bleIcon, BleIcon::GetIcon(true)); + } else { + lv_label_set_text(bleIcon, BleIcon::GetIcon(false)); + } + } + lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 5); + lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0); + lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0); + + notificationState = notificatioManager.AreNewNotificationsAvailable(); + if(notificationState.IsUpdated()) { + if(notificationState.Get() == true) + lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(true)); + else + lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false)); + } + + currentDateTime = dateTimeController.CurrentDateTime(); + + if(currentDateTime.IsUpdated()) { + auto newDateTime = currentDateTime.Get(); + + auto dp = date::floor(newDateTime); + auto time = date::make_time(newDateTime-dp); + auto yearMonthDay = date::year_month_day(dp); + + auto year = (int)yearMonthDay.year(); + auto month = static_cast((unsigned)yearMonthDay.month()); + auto day = (unsigned)yearMonthDay.day(); + auto dayOfWeek = static_cast(date::weekday(yearMonthDay).iso_encoding()); + + int hour = time.hours().count(); + auto minute = time.minutes().count(); + + char minutesChar[3]; + sprintf(minutesChar, "%02d", static_cast(minute)); + + char hoursChar[3]; + char ampmChar[3]; + if ( settingsController.GetClockType() == Controllers::Settings::ClockType::H24 ) { + sprintf(hoursChar, "%02d", hour); + } else { + if (hour > 12) { + hour -= 12; + sprintf(ampmChar, "PM"); + } else { + sprintf(ampmChar, "AM"); + } + sprintf(hoursChar, "%02d", hour); + } + + if(hoursChar[0] != displayedChar[0] || hoursChar[1] != displayedChar[1] || minutesChar[0] != displayedChar[2] || minutesChar[1] != displayedChar[3]) { + displayedChar[0] = hoursChar[0]; + displayedChar[1] = hoursChar[1]; + displayedChar[2] = minutesChar[0]; + displayedChar[3] = minutesChar[1]; + + char timeStr[6]; + + if ( settingsController.GetClockType() == Controllers::Settings::ClockType::H12 ) { + lv_label_set_text(label_time_ampm, ampmChar); + if ( hoursChar[0] == '0' ) { hoursChar[0] = ' '; } + } + + sprintf(timeStr, "%c%c:%c%c", hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]); + lv_label_set_text(label_time, timeStr); + + if ( settingsController.GetClockType() == Controllers::Settings::ClockType::H12 ) { + lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0); + } else { + lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + } + + } + + if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) { + char dateStr[22]; + if ( settingsController.GetClockType() == Controllers::Settings::ClockType::H24 ) { + sprintf(dateStr, "%s %d %s %d", dateTimeController.DayOfWeekShortToString(), day, dateTimeController.MonthShortToString(), year); + } else { + sprintf(dateStr, "%s %s %d %d", dateTimeController.DayOfWeekShortToString(), dateTimeController.MonthShortToString(), day, year); + } + lv_label_set_text(label_date, dateStr); + lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_CENTER, 0, 60); + + + currentYear = year; + currentMonth = month; + currentDayOfWeek = dayOfWeek; + currentDay = day; + } + } + + heartbeat = heartRateController.HeartRate(); + heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped; + if(heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) { + char heartbeatBuffer[4]; + if(heartbeatRunning.Get()) + sprintf(heartbeatBuffer, "%d", heartbeat.Get()); + else + sprintf(heartbeatBuffer, "---"); + + lv_label_set_text(heartbeatValue, heartbeatBuffer); + lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2); + lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0); + lv_obj_align(heartbeatBpm, heartbeatValue, LV_ALIGN_OUT_RIGHT_MID, 5, 0); + } + + // TODO stepCount = stepController.GetValue(); + if(stepCount.IsUpdated()) { + char stepBuffer[5]; + sprintf(stepBuffer, "%lu", stepCount.Get()); + lv_label_set_text(stepValue, stepBuffer); + lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2); + lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0); + } + + return running; +} + + +bool WatchFaceDigital::OnButtonPushed() { + running = false; + return false; +} + + diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h new file mode 100644 index 00000000..70a9ce5d --- /dev/null +++ b/src/displayapp/screens/WatchFaceDigital.h @@ -0,0 +1,82 @@ +#pragma once + +#include +#include +#include +#include +#include "Screen.h" +#include "ScreenList.h" +#include "components/datetime/DateTimeController.h" + +namespace Pinetime { + namespace Controllers { + class Settings; + class Battery; + class Ble; + class NotificationManager; + class HeartRateController; + } + + namespace Applications { + namespace Screens { + + class WatchFaceDigital : public Screen { + public: + WatchFaceDigital(DisplayApp* app, + Controllers::DateTime& dateTimeController, + Controllers::Battery& batteryController, + Controllers::Ble& bleController, + Controllers::NotificationManager& notificatioManager, + Controllers::Settings &settingsController, + Controllers::HeartRateController& heartRateController); + ~WatchFaceDigital() override; + + bool Refresh() override; + bool OnButtonPushed() override; + + void OnObjectEvent(lv_obj_t *pObj, lv_event_t i); + private: + + + char displayedChar[5]; + + uint16_t currentYear = 1970; + Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown; + Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; + uint8_t currentDay = 0; + + DirtyValue batteryPercentRemaining {}; + DirtyValue bleState {}; + DirtyValue> currentDateTime{}; + DirtyValue stepCount {}; + DirtyValue heartbeat {}; + DirtyValue heartbeatRunning {}; + DirtyValue notificationState {}; + + lv_obj_t* label_time; + lv_obj_t* label_time_ampm; + lv_obj_t* label_date; + lv_obj_t* backgroundLabel; + lv_obj_t* batteryIcon; + lv_obj_t* bleIcon; + lv_obj_t* batteryPlug; + lv_obj_t* heartbeatIcon; + lv_obj_t* heartbeatValue; + lv_obj_t* heartbeatBpm; + lv_obj_t* stepIcon; + lv_obj_t* stepValue; + lv_obj_t* notificationIcon; + + Controllers::DateTime& dateTimeController; + Controllers::Battery& batteryController; + Controllers::Ble& bleController; + Controllers::NotificationManager& notificatioManager; + Controllers::Settings& settingsController; + Controllers::HeartRateController& heartRateController; + + bool running = true; + + }; + } + } +} -- cgit v1.2.3-70-g09d2 From 3d6e8c3bebbdaafa764b06ebc2769f2eaac05298 Mon Sep 17 00:00:00 2001 From: Joaquim Date: Sat, 6 Mar 2021 19:55:36 +0000 Subject: Merge from upstream --- README.md | 4 +++- images/0.14.0/collage1.png | Bin 0 -> 621336 bytes images/0.14.0/collage2.png | Bin 0 -> 639600 bytes images/infinitime-logo-github.jpg | Bin 0 -> 37430 bytes src/CMakeLists.txt | 29 ++++++++++++++++++++--------- src/displayapp/screens/Clock.cpp | 3 ++- 6 files changed, 25 insertions(+), 11 deletions(-) create mode 100644 images/0.14.0/collage1.png create mode 100644 images/0.14.0/collage2.png create mode 100644 images/infinitime-logo-github.jpg (limited to 'src/displayapp/screens') diff --git a/README.md b/README.md index 929d3404..3f89ec7d 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,8 @@ The goal of this project is to design an open-source firmware for the Pinetime s ## Overview -![Pinetime screens](images/0.7.0/montage.jpg "PinetimeScreens") +![Pinetime screens](images/0.14.0/collage1.png "PinetimeScreens") +![Pinetime screens](images/0.14.0/collage2.png "PinetimeScreens") As of now, here is the list of achievements of this project: @@ -46,6 +47,7 @@ As of now, here is the list of achievements of this project: - 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) + * **[Experimental]** [WebBLEWatch](https://hubmartin.github.io/WebBLEWatch/) Synchronize time directly from your web browser. [video](https://youtu.be/IakiuhVDdrY) - **[Experimental]** OTA (Over-the-air) update via BLE - **[Experimental]** Bootloader based on [MCUBoot](https://juullabs-oss.github.io/mcuboot/) diff --git a/images/0.14.0/collage1.png b/images/0.14.0/collage1.png new file mode 100644 index 00000000..fd5f27ba Binary files /dev/null and b/images/0.14.0/collage1.png differ diff --git a/images/0.14.0/collage2.png b/images/0.14.0/collage2.png new file mode 100644 index 00000000..293147dd Binary files /dev/null and b/images/0.14.0/collage2.png differ diff --git a/images/infinitime-logo-github.jpg b/images/infinitime-logo-github.jpg new file mode 100644 index 00000000..cf19e35c Binary files /dev/null and b/images/infinitime-logo-github.jpg differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6029f142..e26b52f7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,17 @@ cmake_minimum_required(VERSION 3.10) project(pinetime-app C CXX ASM) + +set(CMAKE_C_STANDARD 99) +set(CMAKE_CXX_STANDARD 14) + +# set(CMAKE_GENERATOR "Unix Makefiles") +set(CMAKE_C_EXTENSIONS OFF) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + # define some variables just for this example to determine file locations set(NRF_PROJECT_NAME pinetime-app) set(NRF_BOARD pca10040) @@ -760,7 +771,7 @@ target_compile_options(nrf-sdk PRIVATE $<$,$>: ${COMMON_FLAGS} -O3> $<$,$>: ${COMMON_FLAGS} -O0> $<$,$>: ${COMMON_FLAGS} -O3> - $<$: -MP -MD -std=c99 -x assembler-with-cpp> + $<$: -MP -MD -x assembler-with-cpp> ) # NimBLE @@ -772,7 +783,7 @@ target_compile_options(nimble PRIVATE $<$,$>: ${COMMON_FLAGS} -O3 -Wno-unused-but-set-variable -Wno-maybe-uninitialized> $<$,$>: ${COMMON_FLAGS} -O0 -g3 -Wno-unused-but-set-variable -Wno-maybe-uninitialized> $<$,$>: ${COMMON_FLAGS} -O3 -Wno-unused-but-set-variable -Wno-maybe-uninitialized> - $<$: -MP -MD -std=c99 -x assembler-with-cpp> + $<$: -MP -MD -x assembler-with-cpp> ) # lvgl @@ -784,7 +795,7 @@ target_compile_options(lvgl PRIVATE $<$,$>: ${COMMON_FLAGS} -O3> $<$,$>: ${COMMON_FLAGS} -O0 -g3> $<$,$>: ${COMMON_FLAGS} -O3> - $<$: -MP -MD -std=c99 -x assembler-with-cpp> + $<$: -MP -MD -x assembler-with-cpp> ) # Build autonomous binary (without support for bootloader) @@ -799,12 +810,12 @@ target_compile_options(${EXECUTABLE_NAME} PUBLIC $<$,$>: ${COMMON_FLAGS} -O3> $<$,$>: ${COMMON_FLAGS} -O0 -g3> $<$,$>: ${COMMON_FLAGS} -O3> - $<$: -MP -MD -std=c99 -x assembler-with-cpp> + $<$: -MP -MD -x assembler-with-cpp> ) set_target_properties(${EXECUTABLE_NAME} PROPERTIES SUFFIX ".out" - LINK_FLAGS "-mthumb -mabi=aapcs -std=gnu++98 -std=c99 -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_FILE_NAME}.map" + LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_FILE_NAME}.map" CXX_STANDARD 11 C_STANDARD 99 ) @@ -831,12 +842,12 @@ target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC $<$,$>: ${COMMON_FLAGS} -O3> $<$,$>: ${COMMON_FLAGS} -O0 -g3> $<$,$>: ${COMMON_FLAGS} -O3> - $<$: -MP -MD -std=c99 -x assembler-with-cpp> + $<$: -MP -MD -x assembler-with-cpp> ) set_target_properties(${EXECUTABLE_MCUBOOT_NAME} PROPERTIES SUFFIX ".out" - LINK_FLAGS "-mthumb -mabi=aapcs -std=gnu++98 -std=c99 -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT_MCUBOOT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_MCUBOOT_FILE_NAME}.map" + LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT_MCUBOOT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_MCUBOOT_FILE_NAME}.map" CXX_STANDARD 11 C_STANDARD 99 ) @@ -860,12 +871,12 @@ target_compile_options(${EXECUTABLE_GRAPHICS_NAME} PUBLIC $<$,$>: ${COMMON_FLAGS} -O3> $<$,$>: ${COMMON_FLAGS} -O0 -g3> $<$,$>: ${COMMON_FLAGS} -O3> - $<$: -MP -MD -std=c99 -x assembler-with-cpp> + $<$: -MP -MD -x assembler-with-cpp> ) set_target_properties(${EXECUTABLE_GRAPHICS_NAME} PROPERTIES SUFFIX ".out" - LINK_FLAGS "-mthumb -mabi=aapcs -std=gnu++98 -std=c99 -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_GRAPHICS_FILE_NAME}.map" + LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_GRAPHICS_FILE_NAME}.map" CXX_STANDARD 11 C_STANDARD 99 ) diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp index ea9ddd56..342dd222 100644 --- a/src/displayapp/screens/Clock.cpp +++ b/src/displayapp/screens/Clock.cpp @@ -33,6 +33,7 @@ Clock::Clock(DisplayApp* app, { [this]() -> std::unique_ptr { return WatchFaceDigitalScreen(); }, [this]() -> std::unique_ptr { return WatchFaceAnalogScreen(); }, + // Examples for more watch faces //[this]() -> std::unique_ptr { return WatchFaceMinimalScreen(); }, //[this]() -> std::unique_ptr { return WatchFaceCustomScreen(); } }, @@ -71,7 +72,7 @@ std::unique_ptr Clock::WatchFaceAnalogScreen() { } /* -// examples +// Examples for more watch faces std::unique_ptr Clock::WatchFaceMinimalScreen() { return std::unique_ptr(new Screens::WatchFaceMinimal(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController)); } -- cgit v1.2.3-70-g09d2 From 97deb43fb78b581535887938a0c3c0813896fcbe Mon Sep 17 00:00:00 2001 From: Joaquim Date: Sat, 6 Mar 2021 19:55:53 +0000 Subject: Update from JF comments to PR --- src/components/settings/Settings.cpp | 2 -- src/displayapp/screens/Clock.h | 6 ++++-- src/displayapp/screens/ScreenList.h | 18 ++---------------- src/displayapp/screens/WatchFaceAnalog.cpp | 6 ------ src/displayapp/screens/WatchFaceDigital.cpp | 7 ------- 5 files changed, 6 insertions(+), 33 deletions(-) (limited to 'src/displayapp/screens') diff --git a/src/components/settings/Settings.cpp b/src/components/settings/Settings.cpp index 87cfe885..0c6cf610 100644 --- a/src/components/settings/Settings.cpp +++ b/src/components/settings/Settings.cpp @@ -6,9 +6,7 @@ using namespace Pinetime::Controllers; // TODO (team): // Read and write the settings to Flash // - void Settings::Init() { - // default Clock face clockFace = 0; diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h index 2b1be4ac..964ccbf6 100644 --- a/src/displayapp/screens/Clock.h +++ b/src/displayapp/screens/Clock.h @@ -49,8 +49,10 @@ namespace Pinetime { ScreenList<2> screens; std::unique_ptr WatchFaceDigitalScreen(); std::unique_ptr WatchFaceAnalogScreen(); - std::unique_ptr WatchFaceMinimalScreen(); - std::unique_ptr WatchFaceCustomScreen(); + + // Examples for more watch faces + //std::unique_ptr WatchFaceMinimalScreen(); + //std::unique_ptr WatchFaceCustomScreen(); bool running = true; diff --git a/src/displayapp/screens/ScreenList.h b/src/displayapp/screens/ScreenList.h index 56d9abe0..43b33f40 100644 --- a/src/displayapp/screens/ScreenList.h +++ b/src/displayapp/screens/ScreenList.h @@ -15,26 +15,12 @@ namespace Pinetime { class ScreenList : public Screen { public: - ScreenList( - DisplayApp* app, - uint8_t initScreen, - std::array()>, N>&& screens, - ScreenListModes mode - ) - : Screen(app), - initScreen{initScreen}, - screens{std::move(screens)}, - mode{mode}, - current{this->screens[initScreen]()} - { + ScreenList(DisplayApp* app, uint8_t initScreen, std::array()>, N>&& screens, ScreenListModes mode) + : Screen(app), initScreen{initScreen}, screens{std::move(screens)}, mode{mode}, current{this->screens[initScreen]()} { screenIndex = initScreen; } ~ScreenList() override { - current.reset(nullptr); - /*for(uint8_t i = 0; i < screens.size(); i++) { - screens[i]().reset(nullptr); - }*/ lv_obj_clean(lv_scr_act()); } diff --git a/src/displayapp/screens/WatchFaceAnalog.cpp b/src/displayapp/screens/WatchFaceAnalog.cpp index efca10c2..b51d48c7 100644 --- a/src/displayapp/screens/WatchFaceAnalog.cpp +++ b/src/displayapp/screens/WatchFaceAnalog.cpp @@ -103,12 +103,6 @@ WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp *app, UpdateClock(); - /*lv_obj_t* backgroundLabel = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP); - lv_obj_set_size(backgroundLabel, 240, 240); - lv_obj_set_pos(backgroundLabel, 0, 0); - lv_label_set_text_static(backgroundLabel, "");*/ - } WatchFaceAnalog::~WatchFaceAnalog() { diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index 99df318a..4560ccdb 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -30,13 +30,6 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app, heartRateController{heartRateController} { settingsController.SetClockFace(0); - // init - /*currentDateTime = dateTimeController.CurrentDateTime(); - batteryPercentRemaining = batteryController.PercentRemaining(); - bleState = bleController.IsConnected(); - notificationState = notificatioManager.AreNewNotificationsAvailable(); - heartbeat = heartRateController.HeartRate();*/ - displayedChar[0] = 0; displayedChar[1] = 0; displayedChar[2] = 0; -- cgit v1.2.3-70-g09d2 From 282e34dca14ddc799b9511643e50a4f9023003ed Mon Sep 17 00:00:00 2001 From: Joaquim José Almeida Pereira Date: Mon, 8 Mar 2021 12:23:32 +0000 Subject: fix AM/PM --- src/displayapp/screens/WatchFaceDigital.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src/displayapp/screens') diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index 4560ccdb..c39fe496 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -160,11 +160,21 @@ bool WatchFaceDigital::Refresh() { if ( settingsController.GetClockType() == Controllers::Settings::ClockType::H24 ) { sprintf(hoursChar, "%02d", hour); } else { - if (hour > 12) { - hour -= 12; - sprintf(ampmChar, "PM"); - } else { - sprintf(ampmChar, "AM"); + if (hour == 0 && hour != 12) { + hour = 12; + sprintf(ampmChar, "AM"); + } + else if (hour == 12 && hour != 0) { + hour = 12; + sprintf(ampmChar, "PM"); + } + else if (hour < 12 && hour != 0) { + sprintf(ampmChar, "AM"); + } + else if (hour > 12 && hour != 0) + { + hour = hour - 12; + sprintf(ampmChar, "PM"); } sprintf(hoursChar, "%02d", hour); } -- cgit v1.2.3-70-g09d2 From cc58b635a34cf89fa6301096a19e0a816817aa50 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Thu, 11 Mar 2021 10:54:14 +0100 Subject: 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 (limited to 'src/displayapp/screens') 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 -- cgit v1.2.3-70-g09d2 From ce91e1a7a6e7ccf674aabfb20770d13cb4eb3190 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Thu, 11 Mar 2021 11:56:58 +0100 Subject: 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(-) (limited to 'src/displayapp/screens') 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 -- cgit v1.2.3-70-g09d2 From 70373e734529fdd2e31f0080444360ba859ff567 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Thu, 11 Mar 2021 23:41:24 +0100 Subject: Added play/pause button. --- src/displayapp/screens/StopWatch.cpp | 58 +++++++++++++++++++++++++++++++----- src/displayapp/screens/StopWatch.h | 6 ++-- 2 files changed, 55 insertions(+), 9 deletions(-) (limited to 'src/displayapp/screens') 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 -- cgit v1.2.3-70-g09d2 From a090664a4c1709a7925621632e579632e3f1e39a Mon Sep 17 00:00:00 2001 From: panky-codes Date: Fri, 12 Mar 2021 09:43:13 +0100 Subject: 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(-) (limited to 'src/displayapp/screens') 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 -- cgit v1.2.3-70-g09d2 From 00f2a053bf65058465c8b2f6913a66e85dbd6864 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Fri, 12 Mar 2021 20:24:53 +0100 Subject: Laps introduced. Tested. Need to change the icon. --- src/displayapp/screens/StopWatch.cpp | 40 ++++++++++++++++++++++++++++++------ src/displayapp/screens/StopWatch.h | 38 +++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 7 deletions(-) (limited to 'src/displayapp/screens') 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)); - - lv_label_set_text_fmt(time, "%02d:%02d", timeSeparated.mins, timeSeparated.secs); - lv_label_set_text_fmt(msecTime, "%02d", timeSeparated.msecs); + currentTimeSeparated = convertTicksToTimeSegments((oldTimeElapsed + timeElapsed)); + + 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; }; -- cgit v1.2.3-70-g09d2 From 5d57b9054a9d30d8724fac87108d68a4f2c95e68 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Sat, 13 Mar 2021 13:59:54 +0100 Subject: Adding laps completed. --- src/displayapp/screens/StopWatch.cpp | 12 ++++++++---- src/displayapp/screens/StopWatch.h | 11 +++++++++-- 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'src/displayapp/screens') 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]); } } -- cgit v1.2.3-70-g09d2 From 02824d0671b558e5a36188df4cbc729b571dad1a Mon Sep 17 00:00:00 2001 From: panky-codes Date: Sat, 13 Mar 2021 14:38:18 +0100 Subject: 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(-) (limited to 'src/displayapp/screens') 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"; } } } -- cgit v1.2.3-70-g09d2 From d409643b8eadd934849e2ffb749590e2ea672fb3 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Sat, 13 Mar 2021 14:53:37 +0100 Subject: Added some comments for clarity. Ready for review. Tested. --- src/displayapp/screens/StopWatch.cpp | 16 ++++++++++++++-- src/displayapp/screens/StopWatch.h | 4 ++-- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'src/displayapp/screens') 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); -- cgit v1.2.3-70-g09d2 From bc6d447a5f7b272047c8bb977f6a476413268782 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Sat, 13 Mar 2021 22:29:07 +0100 Subject: 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(-) (limited to 'src/displayapp/screens') 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); -- cgit v1.2.3-70-g09d2 From abc30028a2b3d0089bca880a73e7fbad9d7cd9bb Mon Sep 17 00:00:00 2001 From: panky-codes Date: Mon, 15 Mar 2021 21:35:36 +0100 Subject: 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(-) (limited to 'src/displayapp/screens') 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 +} -- cgit v1.2.3-70-g09d2 From 509ac066d48f5b60b1b69015cff067bbca90e2a1 Mon Sep 17 00:00:00 2001 From: Christian Muehlhaeuser Date: Tue, 16 Mar 2021 04:01:22 +0100 Subject: Update project URL in SystemInfo Pinetime -> InfiniTime --- src/displayapp/screens/SystemInfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/displayapp/screens') diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index 2de5dada..b1ff41bb 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -119,6 +119,6 @@ std::unique_ptr SystemInfo::CreateScreen3() { "Public License v3\n" "Source code:\n" "https://github.com/\n" - " JF002/Pinetime"); + " JF002/InfiniTime"); return std::unique_ptr(new Screens::Label(app, t3)); } -- cgit v1.2.3-70-g09d2 From 754ac233040af805ffa2e15b24539d5d02a876e5 Mon Sep 17 00:00:00 2001 From: panky-codes Date: Sat, 20 Mar 2021 22:42:13 +0100 Subject: 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 (limited to 'src/displayapp/screens') 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; }; -- cgit v1.2.3-70-g09d2