From e334735697d2d10fe3e5e6038c51bacaec729ceb Mon Sep 17 00:00:00 2001 From: josh Date: Wed, 20 Sep 2023 16:12:14 -0400 Subject: [PATCH 01/61] Added swipe left to show music controls and a green $ to the prompt in terminal watch face --- src/displayapp/DisplayApp.cpp | 3 +++ src/displayapp/screens/WatchFaceTerminal.cpp | 11 +++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index cd941f16..b788e0cc 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -301,6 +301,9 @@ void DisplayApp::Refresh() { case TouchEvents::SwipeRight: LoadNewScreen(Apps::QuickSettings, DisplayApp::FullRefreshDirections::RightAnim); break; + case TouchEvents::SwipeLeft: + LoadNewScreen(Apps::Music, DisplayApp::FullRefreshDirections::LeftAnim); + break; case TouchEvents::DoubleTap: PushMessageToSystemTask(System::Messages::GoToSleep); break; diff --git a/src/displayapp/screens/WatchFaceTerminal.cpp b/src/displayapp/screens/WatchFaceTerminal.cpp index 72383729..ac00f5a3 100644 --- a/src/displayapp/screens/WatchFaceTerminal.cpp +++ b/src/displayapp/screens/WatchFaceTerminal.cpp @@ -10,8 +10,11 @@ #include "components/motion/MotionController.h" #include "components/settings/Settings.h" + + using namespace Pinetime::Applications::Screens; + WatchFaceTerminal::WatchFaceTerminal(Controllers::DateTime& dateTimeController, const Controllers::Battery& batteryController, const Controllers::Ble& bleController, @@ -43,12 +46,14 @@ WatchFaceTerminal::WatchFaceTerminal(Controllers::DateTime& dateTimeController, lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -40); label_prompt_1 = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(label_prompt_1, true); lv_obj_align(label_prompt_1, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -80); - lv_label_set_text_static(label_prompt_1, "user@watch:~ $ now"); + lv_label_set_text_static(label_prompt_1, "user@watch:~ #00ff00 $# now"); label_prompt_2 = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(label_prompt_1, true); lv_obj_align(label_prompt_2, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60); - lv_label_set_text_static(label_prompt_2, "user@watch:~ $"); + lv_label_set_text_static(label_prompt_2, "user@watch:~ #00ff00 $#"); label_time = lv_label_create(lv_scr_act(), nullptr); lv_label_set_recolor(label_time, true); @@ -143,6 +148,8 @@ void WatchFaceTerminal::Refresh() { lv_label_set_text_static(heartbeatValue, "[L_HR]#ee3311 ---#"); } } + + stepCount = motionController.NbSteps(); if (stepCount.IsUpdated()) { From 292b7e3fb1b46cc526607a2d377260de6a322041 Mon Sep 17 00:00:00 2001 From: josh Date: Thu, 21 Sep 2023 21:01:37 -0400 Subject: [PATCH 02/61] Replaced am/pm with seconds on digital watchface --- src/displayapp/screens/WatchFaceDigital.cpp | 17 ++++++++++++----- src/displayapp/screens/WatchFaceDigital.h | 5 +++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index ca53691b..1fbfc15a 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -35,6 +35,10 @@ WatchFaceDigital::WatchFaceDigital(Controllers::DateTime& dateTimeController, lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(false)); lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); + label_seconds = lv_label_create(lv_scr_act(), nullptr); // for secs + lv_obj_align(label_seconds, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, -55); + lv_obj_set_style_local_text_color(label_seconds, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x999999)); + 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)); @@ -44,9 +48,9 @@ WatchFaceDigital::WatchFaceDigital(Controllers::DateTime& dateTimeController, 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); + /*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); + lv_obj_align(label_time_ampm, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -30, -55);*/ heartbeatIcon = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(heartbeatIcon, Symbols::heartBeat); @@ -85,14 +89,15 @@ void WatchFaceDigital::Refresh() { lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(notificationState.Get())); } - currentDateTime = std::chrono::time_point_cast(dateTimeController.CurrentDateTime()); + currentDateTime = std::chrono::time_point_cast(dateTimeController.CurrentDateTime()); if (currentDateTime.IsUpdated()) { uint8_t hour = dateTimeController.Hours(); uint8_t minute = dateTimeController.Minutes(); + uint8_t second = dateTimeController.Seconds(); if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { - char ampmChar[3] = "AM"; + /*char ampmChar[3] = "AM"; if (hour == 0) { hour = 12; } else if (hour == 12) { @@ -101,13 +106,15 @@ void WatchFaceDigital::Refresh() { hour = hour - 12; ampmChar[0] = 'P'; } - lv_label_set_text(label_time_ampm, ampmChar); + lv_label_set_text(label_time_ampm, ampmChar);*/ lv_label_set_text_fmt(label_time, "%2d:%02d", hour, minute); lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0); } else { lv_label_set_text_fmt(label_time, "%02d:%02d", hour, minute); lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); } + + lv_label_set_text_fmt(label_seconds, "%02d", second); // for secs currentDate = std::chrono::time_point_cast(currentDateTime.Get()); if (currentDate.IsUpdated()) { diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h index f2409880..5b0ce672 100644 --- a/src/displayapp/screens/WatchFaceDigital.h +++ b/src/displayapp/screens/WatchFaceDigital.h @@ -44,7 +44,7 @@ namespace Pinetime { Utility::DirtyValue powerPresent {}; Utility::DirtyValue bleState {}; Utility::DirtyValue bleRadioEnabled {}; - Utility::DirtyValue> currentDateTime {}; + Utility::DirtyValue> currentDateTime {}; Utility::DirtyValue stepCount {}; Utility::DirtyValue heartbeat {}; Utility::DirtyValue heartbeatRunning {}; @@ -53,7 +53,8 @@ namespace Pinetime { Utility::DirtyValue> currentDate; lv_obj_t* label_time; - lv_obj_t* label_time_ampm; + lv_obj_t* label_seconds; //for secs + //lv_obj_t* label_time_ampm; lv_obj_t* label_date; lv_obj_t* heartbeatIcon; lv_obj_t* heartbeatValue; From ecb91712fdeecea6480fd54ae0604df0b9dd965c Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Fri, 22 Sep 2023 13:02:40 +0000 Subject: [PATCH 03/61] Fix errors in documentation Signed-off-by: tofasthacker --- doc/buildWithDocker.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/buildWithDocker.md b/doc/buildWithDocker.md index 670590a6..2907b3fa 100644 --- a/doc/buildWithDocker.md +++ b/doc/buildWithDocker.md @@ -33,7 +33,7 @@ For cloning the repo, see [these instructions](../doc/buildAndProgram.md#clone-t ```bash cd # e.g. cd ./work/Pinetime -docker run --rm -it -v ${PWD}:/sources --user $(id -u):$(id -g) infinitime-build +docker run --rm -it -v ${PWD}:/sources --user $(id -u):$(id -g) infinitime/infinitime-build ``` By default, the container runs as `root`, which is not convenient as all the files generated by the build will also belong to `root`. @@ -45,7 +45,7 @@ This means calling the script explicitly as it will override the `CMD`. Here's an example for `pinetime-app`: ```bash -docker run --rm -it -v ${PWD}:/sources --user $(id -u):$(id -g) infinitime-build /opt/build.sh pinetime-app +docker run --rm -it -v ${PWD}:/sources --user $(id -u):$(id -g) infinitime/infinitime-build /opt/build.sh pinetime-app ``` ## Using the image from Docker Hub From 329e42c5d42dbe0bf5baab992a734a6bd4b2daac Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sat, 23 Sep 2023 13:33:35 -0400 Subject: [PATCH 04/61] added TestApp --- src/CMakeLists.txt | 1 + src/displayapp/Apps.h | 3 +- src/displayapp/DisplayApp.cpp | 7 ++ src/displayapp/screens/ApplicationList.h | 3 +- src/displayapp/screens/TestApp.cpp | 128 +++++++++++++++++++++++ src/displayapp/screens/TestApp.h | 38 +++++++ 6 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 src/displayapp/screens/TestApp.cpp create mode 100644 src/displayapp/screens/TestApp.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8e8e9686..822f67eb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -393,6 +393,7 @@ list(APPEND SOURCE_FILES displayapp/screens/ApplicationList.cpp displayapp/screens/Notifications.cpp displayapp/screens/Twos.cpp + displayapp/screens/TestApp.cpp displayapp/screens/HeartRate.cpp displayapp/screens/Motion.cpp displayapp/screens/FlashLight.cpp diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index f253bc03..0ca6a989 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -37,7 +37,8 @@ namespace Pinetime { SettingChimes, SettingShakeThreshold, SettingBluetooth, - Error + Error, + TestApp }; } } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index b788e0cc..1971ad27 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -31,6 +31,9 @@ #include "displayapp/screens/Error.h" #include "displayapp/screens/Weather.h" +// My New Apps +#include "displayapp/screens/TestApp.h" + #include "drivers/Cst816s.h" #include "drivers/St7789.h" #include "drivers/Watchdog.h" @@ -551,6 +554,10 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio case Apps::Steps: currentScreen = std::make_unique(motionController, settingsController); break; + // My Apps + case Apps::TestApp: + currentScreen = std::make_unique(*systemTask, brightnessController); + break; } currentApp = app; } diff --git a/src/displayapp/screens/ApplicationList.h b/src/displayapp/screens/ApplicationList.h index 371ee710..7475f092 100644 --- a/src/displayapp/screens/ApplicationList.h +++ b/src/displayapp/screens/ApplicationList.h @@ -55,7 +55,8 @@ namespace Pinetime { {"2", Apps::Twos, true}, {Symbols::drum, Apps::Metronome, true}, {Symbols::map, Apps::Navigation, Applications::Screens::Navigation::IsAvailable(filesystem)}, - {Symbols::none, Apps::None, false}, + {"T", Apps::TestApp, true}, + //{Symbols::none, Apps::None, false}, // {"M", Apps::Motion}, }}; diff --git a/src/displayapp/screens/TestApp.cpp b/src/displayapp/screens/TestApp.cpp new file mode 100644 index 00000000..f313776e --- /dev/null +++ b/src/displayapp/screens/TestApp.cpp @@ -0,0 +1,128 @@ +#include "displayapp/screens/TestApp.h" +#include "displayapp/DisplayApp.h" +#include "displayapp/screens/Symbols.h" +#include "displayapp/InfiniTimeTheme.h" + +using namespace Pinetime::Applications::Screens; + +namespace { + void EventHandler(lv_obj_t* obj, lv_event_t event) { + if (event == LV_EVENT_CLICKED) { + auto* screen = static_cast(obj->user_data); + screen->Toggle(); + } + } +} + +TestApp::TestApp(System::SystemTask& systemTask, Controllers::BrightnessController& brightnessController) + : systemTask {systemTask}, brightnessController {brightnessController} { + + brightnessController.Set(Controllers::BrightnessController::Levels::Low); + + flashLight = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(flashLight, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48); + lv_label_set_text_static(flashLight, Symbols::flashlight); + lv_obj_align(flashLight, nullptr, LV_ALIGN_CENTER, 0, 0); + + for (auto& indicator : indicators) { + indicator = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_size(indicator, 15, 10); + lv_obj_set_style_local_border_width(indicator, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, 2); + } + + lv_obj_align(indicators[1], flashLight, LV_ALIGN_OUT_BOTTOM_MID, 0, 5); + lv_obj_align(indicators[0], indicators[1], LV_ALIGN_OUT_LEFT_MID, -8, 0); + lv_obj_align(indicators[2], indicators[1], LV_ALIGN_OUT_RIGHT_MID, 8, 0); + + SetIndicators(); + SetColors(); + + backgroundAction = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_long_mode(backgroundAction, LV_LABEL_LONG_CROP); + lv_obj_set_size(backgroundAction, 240, 240); + lv_obj_set_pos(backgroundAction, 0, 0); + lv_label_set_text_static(backgroundAction, ""); + lv_obj_set_click(backgroundAction, true); + backgroundAction->user_data = this; + lv_obj_set_event_cb(backgroundAction, EventHandler); + + systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); +} + +TestApp::~TestApp() { + lv_obj_clean(lv_scr_act()); + lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); +} + +void TestApp::SetColors() { + lv_color_t bgColor = isOn ? LV_COLOR_WHITE : LV_COLOR_BLACK; + lv_color_t fgColor = isOn ? Colors::lightGray : LV_COLOR_WHITE; + + lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, bgColor); + lv_obj_set_style_local_text_color(flashLight, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, fgColor); + for (auto& indicator : indicators) { + lv_obj_set_style_local_bg_color(indicator, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, fgColor); + lv_obj_set_style_local_bg_color(indicator, LV_OBJ_PART_MAIN, LV_STATE_DISABLED, bgColor); + lv_obj_set_style_local_border_color(indicator, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, fgColor); + } +} + +void TestApp::SetIndicators() { + using namespace Pinetime::Controllers; + + if (brightnessLevel == BrightnessController::Levels::High) { + lv_obj_set_state(indicators[1], LV_STATE_DEFAULT); + lv_obj_set_state(indicators[2], LV_STATE_DEFAULT); + } else if (brightnessLevel == BrightnessController::Levels::Medium) { + lv_obj_set_state(indicators[1], LV_STATE_DEFAULT); + lv_obj_set_state(indicators[2], LV_STATE_DISABLED); + } else { + lv_obj_set_state(indicators[1], LV_STATE_DISABLED); + lv_obj_set_state(indicators[2], LV_STATE_DISABLED); + } +} + +void TestApp::Toggle() { + isOn = !isOn; + SetColors(); + if (isOn) { + brightnessController.Set(brightnessLevel); + } else { + brightnessController.Set(Controllers::BrightnessController::Levels::Low); + } +} + +bool TestApp::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + using namespace Pinetime::Controllers; + + auto SetState = [this]() { + if (isOn) { + brightnessController.Set(brightnessLevel); + } + SetIndicators(); + }; + + if (event == TouchEvents::SwipeLeft) { + if (brightnessLevel == BrightnessController::Levels::High) { + brightnessLevel = BrightnessController::Levels::Medium; + SetState(); + } else if (brightnessLevel == BrightnessController::Levels::Medium) { + brightnessLevel = BrightnessController::Levels::Low; + SetState(); + } + return true; + } + if (event == TouchEvents::SwipeRight) { + if (brightnessLevel == BrightnessController::Levels::Low) { + brightnessLevel = BrightnessController::Levels::Medium; + SetState(); + } else if (brightnessLevel == BrightnessController::Levels::Medium) { + brightnessLevel = BrightnessController::Levels::High; + SetState(); + } + return true; + } + + return false; +} diff --git a/src/displayapp/screens/TestApp.h b/src/displayapp/screens/TestApp.h new file mode 100644 index 00000000..164e67c0 --- /dev/null +++ b/src/displayapp/screens/TestApp.h @@ -0,0 +1,38 @@ +#pragma once + +#include "displayapp/screens/Screen.h" +#include "components/brightness/BrightnessController.h" +#include "systemtask/SystemTask.h" +#include +#include + +namespace Pinetime { + + namespace Applications { + namespace Screens { + + class TestApp : public Screen { + public: + TestApp(System::SystemTask& systemTask, Controllers::BrightnessController& brightness); + ~TestApp() override; + + bool OnTouchEvent(Pinetime::Applications::TouchEvents event) override; + void Toggle(); + + private: + void SetIndicators(); + void SetColors(); + + Pinetime::System::SystemTask& systemTask; + Controllers::BrightnessController& brightnessController; + + Controllers::BrightnessController::Levels brightnessLevel = Controllers::BrightnessController::Levels::High; + + lv_obj_t* flashLight; + lv_obj_t* backgroundAction; + lv_obj_t* indicators[3]; + bool isOn = false; + }; + } + } +} \ No newline at end of file From 3bb0ac29e2422675da9e79460fadddea58fb0ac7 Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sat, 23 Sep 2023 14:17:56 -0400 Subject: [PATCH 05/61] Switched TestApp for calculator app --- src/displayapp/DisplayApp.cpp | 2 +- src/displayapp/screens/TestApp.cpp | 473 ++++++++++++++++++++++------- src/displayapp/screens/TestApp.h | 70 +++-- 3 files changed, 422 insertions(+), 123 deletions(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 1971ad27..66fea1ce 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -556,7 +556,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio break; // My Apps case Apps::TestApp: - currentScreen = std::make_unique(*systemTask, brightnessController); + currentScreen = std::make_unique(); break; } currentApp = app; diff --git a/src/displayapp/screens/TestApp.cpp b/src/displayapp/screens/TestApp.cpp index f313776e..11b385e0 100644 --- a/src/displayapp/screens/TestApp.cpp +++ b/src/displayapp/screens/TestApp.cpp @@ -1,128 +1,397 @@ -#include "displayapp/screens/TestApp.h" -#include "displayapp/DisplayApp.h" -#include "displayapp/screens/Symbols.h" +#include +#include +#include +#include "TestApp.h" #include "displayapp/InfiniTimeTheme.h" +#include "Symbols.h" using namespace Pinetime::Applications::Screens; -namespace { - void EventHandler(lv_obj_t* obj, lv_event_t event) { - if (event == LV_EVENT_CLICKED) { - auto* screen = static_cast(obj->user_data); - screen->Toggle(); - } - } -} - -TestApp::TestApp(System::SystemTask& systemTask, Controllers::BrightnessController& brightnessController) - : systemTask {systemTask}, brightnessController {brightnessController} { - - brightnessController.Set(Controllers::BrightnessController::Levels::Low); - - flashLight = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_font(flashLight, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48); - lv_label_set_text_static(flashLight, Symbols::flashlight); - lv_obj_align(flashLight, nullptr, LV_ALIGN_CENTER, 0, 0); - - for (auto& indicator : indicators) { - indicator = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_size(indicator, 15, 10); - lv_obj_set_style_local_border_width(indicator, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, 2); - } - - lv_obj_align(indicators[1], flashLight, LV_ALIGN_OUT_BOTTOM_MID, 0, 5); - lv_obj_align(indicators[0], indicators[1], LV_ALIGN_OUT_LEFT_MID, -8, 0); - lv_obj_align(indicators[2], indicators[1], LV_ALIGN_OUT_RIGHT_MID, 8, 0); - - SetIndicators(); - SetColors(); - - backgroundAction = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_long_mode(backgroundAction, LV_LABEL_LONG_CROP); - lv_obj_set_size(backgroundAction, 240, 240); - lv_obj_set_pos(backgroundAction, 0, 0); - lv_label_set_text_static(backgroundAction, ""); - lv_obj_set_click(backgroundAction, true); - backgroundAction->user_data = this; - lv_obj_set_event_cb(backgroundAction, EventHandler); - - systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); +static void eventHandler(lv_obj_t* obj, lv_event_t event) { + auto app = static_cast(obj->user_data); + app->OnButtonEvent(obj, event); } TestApp::~TestApp() { lv_obj_clean(lv_scr_act()); - lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); - systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); } -void TestApp::SetColors() { - lv_color_t bgColor = isOn ? LV_COLOR_WHITE : LV_COLOR_BLACK; - lv_color_t fgColor = isOn ? Colors::lightGray : LV_COLOR_WHITE; +static const char* buttonMap[] = { + "7", "8", "9", "B"/*Symbols::backspace*/, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ".", "(-)", "=", ""}; - lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, bgColor); - lv_obj_set_style_local_text_color(flashLight, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, fgColor); - for (auto& indicator : indicators) { - lv_obj_set_style_local_bg_color(indicator, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, fgColor); - lv_obj_set_style_local_bg_color(indicator, LV_OBJ_PART_MAIN, LV_STATE_DISABLED, bgColor); - lv_obj_set_style_local_border_color(indicator, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, fgColor); +TestApp::TestApp() { + resultLabel = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_long_mode(resultLabel, LV_LABEL_LONG_CROP); + lv_label_set_align(resultLabel, LV_LABEL_ALIGN_RIGHT); + lv_label_set_text_fmt(resultLabel, "%" PRId64, result); + lv_obj_set_size(resultLabel, 200, 20); + lv_obj_set_pos(resultLabel, 10, 5); + + valueLabel = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_long_mode(valueLabel, LV_LABEL_LONG_CROP); + lv_label_set_align(valueLabel, LV_LABEL_ALIGN_RIGHT); + lv_label_set_text_fmt(valueLabel, "%" PRId64, value); + lv_obj_set_size(valueLabel, 200, 20); + lv_obj_set_pos(valueLabel, 10, 35); + + buttonMatrix = lv_btnmatrix_create(lv_scr_act(), nullptr); + buttonMatrix->user_data = this; + lv_obj_set_event_cb(buttonMatrix, eventHandler); + lv_btnmatrix_set_map(buttonMatrix, buttonMap); + lv_btnmatrix_set_one_check(buttonMatrix, true); + lv_obj_set_size(buttonMatrix, 238, 180); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_pad_inner(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); + lv_obj_set_style_local_pad_top(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); + lv_obj_set_style_local_pad_bottom(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); + lv_obj_set_style_local_pad_left(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); + lv_obj_set_style_local_pad_right(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); + lv_obj_align(buttonMatrix, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0); + + lv_obj_set_style_local_bg_opa(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_OPA_COVER); + lv_obj_set_style_local_bg_grad_stop(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, 128); + lv_obj_set_style_local_bg_main_stop(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, 128); +} + +void TestApp::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { + if ((obj == buttonMatrix) && (event == LV_EVENT_PRESSED)) { + HandleInput(); } } -void TestApp::SetIndicators() { - using namespace Pinetime::Controllers; +void TestApp::HandleInput() { + const char* buttonText = lv_btnmatrix_get_active_btn_text(buttonMatrix); - if (brightnessLevel == BrightnessController::Levels::High) { - lv_obj_set_state(indicators[1], LV_STATE_DEFAULT); - lv_obj_set_state(indicators[2], LV_STATE_DEFAULT); - } else if (brightnessLevel == BrightnessController::Levels::Medium) { - lv_obj_set_state(indicators[1], LV_STATE_DEFAULT); - lv_obj_set_state(indicators[2], LV_STATE_DISABLED); + if (buttonText == nullptr) { + return; + } + + if ((equalSignPressed && (*buttonText != '=')) || (error != Error::None)) { + ResetInput(); + UpdateOperation(); + } + + // we only compare the first char because it is enough + switch (*buttonText) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + // *buttonText is the first char in buttonText + // "- '0'" results in the int value of the char + auto digit = (*buttonText) - '0'; + auto sign = (value < 0) ? -1 : 1; + + // if this is true, we already pressed the . button + if (offset < FIXED_POINT_OFFSET) { + value += sign * offset * digit; + offset /= 10; + } else if (value <= MAX_VALUE / 10) { + value *= 10; + value += sign * offset * digit; + } + + NRF_LOG_INFO(". offset: %" PRId64, offset); + NRF_LOG_INFO(". value: %" PRId64, value); + NRF_LOG_INFO(". result: %" PRId64, result); + } break; + + // unary minus + case '(': + value = -value; + + NRF_LOG_INFO(". offset: %" PRId64, offset); + NRF_LOG_INFO(". value: %" PRId64, value); + NRF_LOG_INFO(". result: %" PRId64, result); + + break; + + case '.': + if (offset == FIXED_POINT_OFFSET) { + offset /= 10; + } + + NRF_LOG_INFO(". offset: %" PRId64, offset); + NRF_LOG_INFO(". value: %" PRId64, value); + NRF_LOG_INFO(". result: %" PRId64, result); + break; + + // for every operator we: + // - eval the current operator if value > FIXED_POINT_OFFSET + // - then set the new operator + // - + and - as well as * and / cycle on the same button + case '+': + if (value != 0) { + Eval(); + ResetInput(); + } + + switch (operation) { + case '+': + operation = '-'; + break; + case '-': + operation = ' '; + break; + default: + operation = '+'; + break; + } + UpdateOperation(); + break; + + case '*': + if (value != 0) { + Eval(); + ResetInput(); + } + + switch (operation) { + case '*': + operation = '/'; + break; + case '/': + operation = ' '; + break; + default: + operation = '*'; + break; + } + UpdateOperation(); + break; + + // this is a little hacky because it matches only the first char + case 'B': + if (value != 0) { + // delete one value digit + if (offset < FIXED_POINT_OFFSET) { + if (offset == 0) { + offset = 1; + } else { + offset *= 10; + } + } else { + value /= 10; + } + if (offset < FIXED_POINT_OFFSET) { + value -= value % (10 * offset); + } else { + value -= value % offset; + } + } else if (offset < FIXED_POINT_OFFSET) { + if (offset == 0) { + offset = 1; + } else { + offset *= 10; + } + } else { + // reset the result + result = 0; + } + + NRF_LOG_INFO(". offset: %" PRId64, offset); + NRF_LOG_INFO(". value: %" PRId64, value); + NRF_LOG_INFO(". result: %" PRId64, result); + + operation = ' '; + UpdateOperation(); + break; + + case '=': + equalSignPressed = true; + Eval(); + // If the operation is ' ' then we move the value to the result. + // We reset the input after this. + // This seems more convenient. + if (operation == ' ') { + ResetInput(); + } + + NRF_LOG_INFO(". offset: %" PRId64, offset); + NRF_LOG_INFO(". value: %" PRId64, value); + NRF_LOG_INFO(". result: %" PRId64, result); + + break; + } + + UpdateValueLabel(); + UpdateResultLabel(); +} + +void TestApp::UpdateOperation() const { + switch (operation) { + case '+': + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::bgAlt); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 7, LV_BTNMATRIX_CTRL_CHECK_STATE); + break; + case '-': + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::bgAlt); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 7, LV_BTNMATRIX_CTRL_CHECK_STATE); + break; + case '*': + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::bgAlt); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); + break; + case '/': + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::bgAlt); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); + break; + default: + lv_btnmatrix_clear_btn_ctrl_all(buttonMatrix, LV_BTNMATRIX_CTRL_CHECK_STATE); + break; + } +} + +void TestApp::ResetInput() { + value = 0; + offset = FIXED_POINT_OFFSET; + operation = ' '; + equalSignPressed = false; + error = Error::None; +} + +void TestApp::UpdateResultLabel() const { + int64_t integer = result / FIXED_POINT_OFFSET; + int64_t remainder = result % FIXED_POINT_OFFSET; + bool negative = (remainder < 0); + + if (remainder == 0) { + lv_label_set_text_fmt(resultLabel, "%" PRId64, integer); + return; + } + + if (remainder < 0) { + remainder = -remainder; + } + + uint8_t min_width = N_DECIMALS; + + // cut "0"-digits on the right + while ((remainder > 0) && (remainder % 10 == 0)) { + remainder /= 10; + min_width--; + } + + if ((integer == 0) && negative) { + lv_label_set_text_fmt(resultLabel, "-0.%0*" PRId64, min_width, remainder); } else { - lv_obj_set_state(indicators[1], LV_STATE_DISABLED); - lv_obj_set_state(indicators[2], LV_STATE_DISABLED); + lv_label_set_text_fmt(resultLabel, "%" PRId64 ".%0*" PRId64, integer, min_width, remainder); } } -void TestApp::Toggle() { - isOn = !isOn; - SetColors(); - if (isOn) { - brightnessController.Set(brightnessLevel); - } else { - brightnessController.Set(Controllers::BrightnessController::Levels::Low); +void TestApp::UpdateValueLabel() { + switch (error) { + case Error::TooLarge: + lv_label_set_text_static(valueLabel, "too large"); + break; + case Error::ZeroDivision: + lv_label_set_text_static(valueLabel, "zero division"); + break; + case Error::None: + default: { + int64_t integer = value / FIXED_POINT_OFFSET; + int64_t remainder = value % FIXED_POINT_OFFSET; + bool negative = (remainder < 0); + + int64_t printRemainder = remainder < 0 ? -remainder : remainder; + + uint8_t min_width = 0; + int64_t tmp_offset = offset; + + // TODO there has to be a simpler way to do this + if (tmp_offset == 0) { + tmp_offset = 1; + min_width = 1; + } + while (tmp_offset < FIXED_POINT_OFFSET) { + tmp_offset *= 10; + min_width++; + } + min_width--; + + for (uint8_t i = min_width; i < N_DECIMALS; i++) { + printRemainder /= 10; + } + + if ((integer == 0) && negative) { + lv_label_set_text_fmt(valueLabel, "-0.%0*" PRId64, min_width, printRemainder); + } else if (offset == FIXED_POINT_OFFSET) { + lv_label_set_text_fmt(valueLabel, "%" PRId64, integer); + } else if ((offset == (FIXED_POINT_OFFSET / 10)) && (remainder == 0)) { + lv_label_set_text_fmt(valueLabel, "%" PRId64 ".", integer); + } else { + lv_label_set_text_fmt(valueLabel, "%" PRId64 ".%0*" PRId64, integer, min_width, printRemainder); + } + } break; } } -bool TestApp::OnTouchEvent(Pinetime::Applications::TouchEvents event) { - using namespace Pinetime::Controllers; +// update the result based on value and operation +void TestApp::Eval() { + switch (operation) { + case ' ': + result = value; + break; - auto SetState = [this]() { - if (isOn) { - brightnessController.Set(brightnessLevel); - } - SetIndicators(); - }; + case '+': + // check for overflow + if (((result > 0) && (value > (MAX_VALUE - result))) || ((result < 0) && (value < (MIN_VALUE - result)))) { + error = Error::TooLarge; + break; + } - if (event == TouchEvents::SwipeLeft) { - if (brightnessLevel == BrightnessController::Levels::High) { - brightnessLevel = BrightnessController::Levels::Medium; - SetState(); - } else if (brightnessLevel == BrightnessController::Levels::Medium) { - brightnessLevel = BrightnessController::Levels::Low; - SetState(); - } - return true; + result += value; + break; + case '-': + // check for overflow + if (((result < 0) && (value > (MAX_VALUE + result))) || ((result > 0) && (value < (MIN_VALUE + result)))) { + error = Error::TooLarge; + break; + } + + result -= value; + break; + case '*': + // check for overflow + // while dividing we eliminate the fixed point offset + // therefore we have to multiply it again for the comparison with value + // we also assume here that MAX_VALUE == -MIN_VALUE + if ((result != 0) && (std::abs(value) > (FIXED_POINT_OFFSET * (MAX_VALUE / std::abs(result))))) { + error = Error::TooLarge; + break; + } + + result *= value; + // fixed point offset was multiplied too + result /= FIXED_POINT_OFFSET; + break; + case '/': + // check for zero division + if (value == 0) { + error = Error::ZeroDivision; + break; + } + + // fixed point offset will be divided too + result *= FIXED_POINT_OFFSET; + result /= value; + break; + + default: + break; } - if (event == TouchEvents::SwipeRight) { - if (brightnessLevel == BrightnessController::Levels::Low) { - brightnessLevel = BrightnessController::Levels::Medium; - SetState(); - } else if (brightnessLevel == BrightnessController::Levels::Medium) { - brightnessLevel = BrightnessController::Levels::High; - SetState(); - } - return true; - } - - return false; } diff --git a/src/displayapp/screens/TestApp.h b/src/displayapp/screens/TestApp.h index 164e67c0..91b94f9b 100644 --- a/src/displayapp/screens/TestApp.h +++ b/src/displayapp/screens/TestApp.h @@ -1,38 +1,68 @@ #pragma once -#include "displayapp/screens/Screen.h" -#include "components/brightness/BrightnessController.h" -#include "systemtask/SystemTask.h" -#include -#include +#include "Screen.h" + +namespace { + int64_t constexpr powi(int64_t base, uint8_t exponent) { + int64_t value = 1; + while (exponent) { + value *= base; + exponent--; + } + return value; + } +} namespace Pinetime { - namespace Applications { namespace Screens { - class TestApp : public Screen { public: - TestApp(System::SystemTask& systemTask, Controllers::BrightnessController& brightness); ~TestApp() override; - bool OnTouchEvent(Pinetime::Applications::TouchEvents event) override; - void Toggle(); + TestApp(); + + void OnButtonEvent(lv_obj_t* obj, lv_event_t event); private: - void SetIndicators(); - void SetColors(); + lv_obj_t* buttonMatrix {}; + lv_obj_t* valueLabel {}; + lv_obj_t* resultLabel {}; - Pinetime::System::SystemTask& systemTask; - Controllers::BrightnessController& brightnessController; + void Eval(); + void ResetInput(); + void HandleInput(); + void UpdateValueLabel(); + void UpdateResultLabel() const; + void UpdateOperation() const; - Controllers::BrightnessController::Levels brightnessLevel = Controllers::BrightnessController::Levels::High; + // change this if you want to change the number of decimals + static constexpr uint8_t N_DECIMALS = 4; + // this is the constant default offset + static constexpr int64_t FIXED_POINT_OFFSET = powi(10, N_DECIMALS); + // this is the current offset, may wary after pressing '.' + int64_t offset = FIXED_POINT_OFFSET; - lv_obj_t* flashLight; - lv_obj_t* backgroundAction; - lv_obj_t* indicators[3]; - bool isOn = false; + // the screen can show 12 chars + // but two are needed for '.' and '-' + static constexpr uint8_t MAX_DIGITS = 15; + static constexpr int64_t MAX_VALUE = powi(10, MAX_DIGITS) - 1; + // this is assumed in the multiplication overflow! + static constexpr int64_t MIN_VALUE = -MAX_VALUE; + + int64_t value = 0; + int64_t result = 0; + char operation = ' '; + bool equalSignPressed = false; + + enum Error { + TooLarge, + ZeroDivision, + None, + }; + + Error error = Error::None; }; } } -} \ No newline at end of file +} From b0019da9ddbdbfcba546f9944ecc453759048125 Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sat, 23 Sep 2023 19:03:16 -0400 Subject: [PATCH 06/61] renamed calculator class and added calculator and backspace icon --- src/CMakeLists.txt | 2 +- src/displayapp/Apps.h | 2 +- src/displayapp/DisplayApp.cpp | 6 ++--- src/displayapp/fonts/fonts.json | 2 +- src/displayapp/screens/ApplicationList.h | 2 +- .../screens/{TestApp.cpp => Calculator.cpp} | 26 +++++++++---------- .../screens/{TestApp.h => Calculator.h} | 6 ++--- src/displayapp/screens/Symbols.h | 4 +++ 8 files changed, 27 insertions(+), 23 deletions(-) rename src/displayapp/screens/{TestApp.cpp => Calculator.cpp} (95%) rename src/displayapp/screens/{TestApp.h => Calculator.h} (94%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 822f67eb..a01311b6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -393,7 +393,7 @@ list(APPEND SOURCE_FILES displayapp/screens/ApplicationList.cpp displayapp/screens/Notifications.cpp displayapp/screens/Twos.cpp - displayapp/screens/TestApp.cpp + displayapp/screens/Calculator.cpp displayapp/screens/HeartRate.cpp displayapp/screens/Motion.cpp displayapp/screens/FlashLight.cpp diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index 0ca6a989..c8a48228 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -38,7 +38,7 @@ namespace Pinetime { SettingShakeThreshold, SettingBluetooth, Error, - TestApp + Calculator }; } } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 66fea1ce..61cee716 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -32,7 +32,7 @@ #include "displayapp/screens/Weather.h" // My New Apps -#include "displayapp/screens/TestApp.h" +#include "displayapp/screens/Calculator.h" #include "drivers/Cst816s.h" #include "drivers/St7789.h" @@ -555,8 +555,8 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio currentScreen = std::make_unique(motionController, settingsController); break; // My Apps - case Apps::TestApp: - currentScreen = std::make_unique(); + case Apps::Calculator: + currentScreen = std::make_unique(); break; } currentApp = app; diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index bcfc365f..beac37ff 100644 --- a/src/displayapp/fonts/fonts.json +++ b/src/displayapp/fonts/fonts.json @@ -7,7 +7,7 @@ }, { "file": "FontAwesome5-Solid+Brands+Regular.woff", - "range": "0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf06e, 0xf015, 0xf00c" + "range": "0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf06e, 0xf015, 0xf00c, 0xf1ec, 0xf55a" } ], "bpp": 1, diff --git a/src/displayapp/screens/ApplicationList.h b/src/displayapp/screens/ApplicationList.h index 7475f092..31ad64b9 100644 --- a/src/displayapp/screens/ApplicationList.h +++ b/src/displayapp/screens/ApplicationList.h @@ -55,7 +55,7 @@ namespace Pinetime { {"2", Apps::Twos, true}, {Symbols::drum, Apps::Metronome, true}, {Symbols::map, Apps::Navigation, Applications::Screens::Navigation::IsAvailable(filesystem)}, - {"T", Apps::TestApp, true}, + {Symbols::calculator, Apps::Calculator, true}, //{Symbols::none, Apps::None, false}, // {"M", Apps::Motion}, diff --git a/src/displayapp/screens/TestApp.cpp b/src/displayapp/screens/Calculator.cpp similarity index 95% rename from src/displayapp/screens/TestApp.cpp rename to src/displayapp/screens/Calculator.cpp index 11b385e0..e5d38810 100644 --- a/src/displayapp/screens/TestApp.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -1,25 +1,25 @@ #include #include #include -#include "TestApp.h" +#include "Calculator.h" #include "displayapp/InfiniTimeTheme.h" #include "Symbols.h" using namespace Pinetime::Applications::Screens; static void eventHandler(lv_obj_t* obj, lv_event_t event) { - auto app = static_cast(obj->user_data); + auto app = static_cast(obj->user_data); app->OnButtonEvent(obj, event); } -TestApp::~TestApp() { +Calculator::~Calculator() { lv_obj_clean(lv_scr_act()); } static const char* buttonMap[] = { - "7", "8", "9", "B"/*Symbols::backspace*/, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ".", "(-)", "=", ""}; + "7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ".", "(-)", "=", ""}; -TestApp::TestApp() { +Calculator::Calculator() { resultLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(resultLabel, LV_LABEL_LONG_CROP); lv_label_set_align(resultLabel, LV_LABEL_ALIGN_RIGHT); @@ -53,13 +53,13 @@ TestApp::TestApp() { lv_obj_set_style_local_bg_main_stop(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, 128); } -void TestApp::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { +void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { if ((obj == buttonMatrix) && (event == LV_EVENT_PRESSED)) { HandleInput(); } } -void TestApp::HandleInput() { +void Calculator::HandleInput() { const char* buttonText = lv_btnmatrix_get_active_btn_text(buttonMatrix); if (buttonText == nullptr) { @@ -167,7 +167,7 @@ void TestApp::HandleInput() { break; // this is a little hacky because it matches only the first char - case 'B': + case Symbols::backspace[0]: if (value != 0) { // delete one value digit if (offset < FIXED_POINT_OFFSET) { @@ -224,7 +224,7 @@ void TestApp::HandleInput() { UpdateResultLabel(); } -void TestApp::UpdateOperation() const { +void Calculator::UpdateOperation() const { switch (operation) { case '+': lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); @@ -256,7 +256,7 @@ void TestApp::UpdateOperation() const { } } -void TestApp::ResetInput() { +void Calculator::ResetInput() { value = 0; offset = FIXED_POINT_OFFSET; operation = ' '; @@ -264,7 +264,7 @@ void TestApp::ResetInput() { error = Error::None; } -void TestApp::UpdateResultLabel() const { +void Calculator::UpdateResultLabel() const { int64_t integer = result / FIXED_POINT_OFFSET; int64_t remainder = result % FIXED_POINT_OFFSET; bool negative = (remainder < 0); @@ -293,7 +293,7 @@ void TestApp::UpdateResultLabel() const { } } -void TestApp::UpdateValueLabel() { +void Calculator::UpdateValueLabel() { switch (error) { case Error::TooLarge: lv_label_set_text_static(valueLabel, "too large"); @@ -341,7 +341,7 @@ void TestApp::UpdateValueLabel() { } // update the result based on value and operation -void TestApp::Eval() { +void Calculator::Eval() { switch (operation) { case ' ': result = value; diff --git a/src/displayapp/screens/TestApp.h b/src/displayapp/screens/Calculator.h similarity index 94% rename from src/displayapp/screens/TestApp.h rename to src/displayapp/screens/Calculator.h index 91b94f9b..17513861 100644 --- a/src/displayapp/screens/TestApp.h +++ b/src/displayapp/screens/Calculator.h @@ -16,11 +16,11 @@ namespace { namespace Pinetime { namespace Applications { namespace Screens { - class TestApp : public Screen { + class Calculator : public Screen { public: - ~TestApp() override; + ~Calculator() override; - TestApp(); + Calculator(); void OnButtonEvent(lv_obj_t* obj, lv_event_t event); diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index 7154ff44..b4dadfb2 100644 --- a/src/displayapp/screens/Symbols.h +++ b/src/displayapp/screens/Symbols.h @@ -37,6 +37,10 @@ namespace Pinetime { static constexpr const char* eye = "\xEF\x81\xAE"; static constexpr const char* home = "\xEF\x80\x95"; static constexpr const char* sleep = "\xEE\xBD\x84"; + static constexpr const char* calculator = "\xEF\x87\xAC"; + static constexpr const char* backspace = "\xEF\x95\x9A"; + + // fontawesome_weathericons.c // static constexpr const char* sun = "\xEF\x86\x85"; From b95823e745a08a47c56c803ed7eabe794131a9a5 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 23 Sep 2023 19:32:01 -0400 Subject: [PATCH 07/61] Fixed second $ in terminal watch face --- src/displayapp/screens/WatchFaceTerminal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/WatchFaceTerminal.cpp b/src/displayapp/screens/WatchFaceTerminal.cpp index ac00f5a3..bd0a9f17 100644 --- a/src/displayapp/screens/WatchFaceTerminal.cpp +++ b/src/displayapp/screens/WatchFaceTerminal.cpp @@ -51,7 +51,7 @@ WatchFaceTerminal::WatchFaceTerminal(Controllers::DateTime& dateTimeController, lv_label_set_text_static(label_prompt_1, "user@watch:~ #00ff00 $# now"); label_prompt_2 = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_recolor(label_prompt_1, true); + lv_label_set_recolor(label_prompt_2, true); lv_obj_align(label_prompt_2, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60); lv_label_set_text_static(label_prompt_2, "user@watch:~ #00ff00 $#"); From 5fc831542fba0f27e1ea126b0db07d6192d1a588 Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sat, 23 Sep 2023 19:39:53 -0400 Subject: [PATCH 08/61] fixed terminal $ --- src/displayapp/screens/WatchFaceTerminal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/WatchFaceTerminal.cpp b/src/displayapp/screens/WatchFaceTerminal.cpp index ac00f5a3..bd0a9f17 100644 --- a/src/displayapp/screens/WatchFaceTerminal.cpp +++ b/src/displayapp/screens/WatchFaceTerminal.cpp @@ -51,7 +51,7 @@ WatchFaceTerminal::WatchFaceTerminal(Controllers::DateTime& dateTimeController, lv_label_set_text_static(label_prompt_1, "user@watch:~ #00ff00 $# now"); label_prompt_2 = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_recolor(label_prompt_1, true); + lv_label_set_recolor(label_prompt_2, true); lv_obj_align(label_prompt_2, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60); lv_label_set_text_static(label_prompt_2, "user@watch:~ #00ff00 $#"); From cbabd8914c2200b4f0d0700944724b5ab868ac5c Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sat, 23 Sep 2023 19:42:18 -0400 Subject: [PATCH 09/61] fixed colored $ in terminal watch face --- src/displayapp/screens/WatchFaceTerminal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/WatchFaceTerminal.cpp b/src/displayapp/screens/WatchFaceTerminal.cpp index ac00f5a3..bd0a9f17 100644 --- a/src/displayapp/screens/WatchFaceTerminal.cpp +++ b/src/displayapp/screens/WatchFaceTerminal.cpp @@ -51,7 +51,7 @@ WatchFaceTerminal::WatchFaceTerminal(Controllers::DateTime& dateTimeController, lv_label_set_text_static(label_prompt_1, "user@watch:~ #00ff00 $# now"); label_prompt_2 = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_recolor(label_prompt_1, true); + lv_label_set_recolor(label_prompt_2, true); lv_obj_align(label_prompt_2, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60); lv_label_set_text_static(label_prompt_2, "user@watch:~ #00ff00 $#"); From c04bd3bd7d17caf2884cad64cdde8a87c90d4c02 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 23 Sep 2023 22:09:00 -0400 Subject: [PATCH 10/61] Added todo list --- README.md | 98 +++++++------------------------------------------- README_orig.md | 88 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 86 deletions(-) create mode 100644 README_orig.md diff --git a/README.md b/README.md index 2d397818..bd9baf4f 100644 --- a/README.md +++ b/README.md @@ -1,88 +1,14 @@ -# [InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime) +# TODO +## Medium priority +- [ ] Temp sensor w/ arduino +- [/] Countdown timer presistant buzz +- [/] Seconds on digital watchface +- [ ] Flashlight starts on +- [ ] Homeassistant control +- [ ] Swipe down exits music control +- [ ] Periodic heart rate measurement -![InfiniTime logo](doc/logo/infinitime-logo-small.jpg "InfiniTime Logo") -Fast open-source firmware for the [PineTime smartwatch](https://www.pine64.org/pinetime/) with many features, written in modern C++. - -## New to InfiniTime? - -- [Getting started with InfiniTime](doc/gettingStarted/gettingStarted-1.0.md) -- [Updating the software](doc/gettingStarted/updating-software.md) -- [About the firmware and bootloader](doc/gettingStarted/about-software.md) -- [PineTimeStyle Watch face](https://wiki.pine64.org/wiki/PineTimeStyle) - - [Weather integration](https://wiki.pine64.org/wiki/Infinitime-Weather) - -### Companion apps - -- [Gadgetbridge](https://gadgetbridge.org/) (Android) -- [AmazFish](https://openrepos.net/content/piggz/amazfish/) (SailfishOS) -- [Siglo](https://github.com/alexr4535/siglo) (Linux) -- [InfiniLink](https://github.com/InfiniTimeOrg/InfiniLink) (iOS) **[Looking for a new maintainer]** -- [ITD](https://gitea.elara.ws/Elara6331/itd) (Linux) -- [WatchMate](https://github.com/azymohliad/watchmate) (Linux) - -***Note** : We removed mentions to NRFConnect as this app is closed source and recent versions do not work anymore with InfiniTime (the last version known to work is 4.24.3). If you used NRFConnect in the past, we recommend you switch to [Gadgetbridge](https://gadgetbridge.org/).* - -## Development - -- [InfiniTime Vision](doc/InfiniTimeVision.md) -- [Rough structure of the code](doc/code/Intro.md) -- [How to implement an application](doc/code/Apps.md) -- [Generate the fonts and symbols](src/displayapp/fonts/README.md) -- [Tips on designing an app UI](doc/ui_guidelines.md) -- [Bootloader, OTA and DFU](bootloader/README.md) -- [External resources](doc/ExternalResources.md) - -### Contributing - -- [How to contribute?](CONTRIBUTING.md) -- [Coding conventions](doc/coding-convention.md) - -### Build, flash and debug - -- [InfiniTime simulator](https://github.com/InfiniTimeOrg/InfiniSim) -- [Build the project](doc/buildAndProgram.md) -- [Build the project with Docker](doc/buildWithDocker.md) -- [Build the project with VSCode](doc/buildWithVScode.md) -- [Flash the firmware using OpenOCD and STLinkV2](doc/openOCD.md) -- [Flash the firmware using SWD interface](doc/SWD.md) -- [Flash the firmware using JLink](doc/jlink.md) -- [Flash the firmware using GDB](doc/gdb.md) -- [Stub using NRF52-DK](doc/PinetimeStubWithNrf52DK.md) - -### API - -- [BLE implementation and API](doc/ble.md) - -### Architecture and technical topics - -- [Memory analysis](doc/MemoryAnalysis.md) - -### Project management - -- [Maintainer's guide](doc/maintainer-guide.md) -- [Versioning](doc/versioning.md) -- [Project branches](doc/branches.md) -- [Files included in the release notes](doc/filesInReleaseNotes.md) -- [Files needed by the factory](doc/files-needed-by-factory.md) - -## Licenses - -This project is released under the GNU General Public License version 3 or, at your option, any later version. - -It integrates the following projects: - -- RTOS : **[FreeRTOS](https://freertos.org)** under the MIT license -- UI : **[LittleVGL/LVGL](https://lvgl.io/)** under the MIT license -- BLE stack : **[NimBLE](https://github.com/apache/mynewt-nimble)** under the Apache 2.0 license -- Font : **[Jetbrains Mono](https://www.jetbrains.com/fr-fr/lp/mono/)** under the Apache 2.0 license - -## Credits - -I’m not working alone on this project. First, many people create PR for this project. Then, there is the whole #pinetime community : a lot of people all around the world who are hacking, searching, experimenting and programming the Pinetime. We exchange our ideas, experiments and code in the chat rooms and forums. - -Here are some people I would like to highlight: - -- [Atc1441](https://github.com/atc1441/) : He works on an Arduino based firmware for the Pinetime and many other smartwatches based on similar hardware. He was of great help when I was implementing support for the BMA421 motion sensor and I²C driver. -- [Koen](https://github.com/bosmoment) : He’s working on a firmware based on RiotOS. He integrated similar libs as me : NimBLE, LittleVGL,… His help was invaluable too! -- [Lup Yuen Lee](https://github.com/lupyuen) : He is everywhere: he works on a Rust firmware, builds a MCUBoot based bootloader for the Pinetime, designs a Flutter based companion app for smartphones and writes a lot of articles about the Pinetime! +## Lower priority +- [ ] Rearrange quick acces and apps +- [ ] Maybe some prank watchfaces diff --git a/README_orig.md b/README_orig.md new file mode 100644 index 00000000..2d397818 --- /dev/null +++ b/README_orig.md @@ -0,0 +1,88 @@ +# [InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime) + +![InfiniTime logo](doc/logo/infinitime-logo-small.jpg "InfiniTime Logo") + +Fast open-source firmware for the [PineTime smartwatch](https://www.pine64.org/pinetime/) with many features, written in modern C++. + +## New to InfiniTime? + +- [Getting started with InfiniTime](doc/gettingStarted/gettingStarted-1.0.md) +- [Updating the software](doc/gettingStarted/updating-software.md) +- [About the firmware and bootloader](doc/gettingStarted/about-software.md) +- [PineTimeStyle Watch face](https://wiki.pine64.org/wiki/PineTimeStyle) + - [Weather integration](https://wiki.pine64.org/wiki/Infinitime-Weather) + +### Companion apps + +- [Gadgetbridge](https://gadgetbridge.org/) (Android) +- [AmazFish](https://openrepos.net/content/piggz/amazfish/) (SailfishOS) +- [Siglo](https://github.com/alexr4535/siglo) (Linux) +- [InfiniLink](https://github.com/InfiniTimeOrg/InfiniLink) (iOS) **[Looking for a new maintainer]** +- [ITD](https://gitea.elara.ws/Elara6331/itd) (Linux) +- [WatchMate](https://github.com/azymohliad/watchmate) (Linux) + +***Note** : We removed mentions to NRFConnect as this app is closed source and recent versions do not work anymore with InfiniTime (the last version known to work is 4.24.3). If you used NRFConnect in the past, we recommend you switch to [Gadgetbridge](https://gadgetbridge.org/).* + +## Development + +- [InfiniTime Vision](doc/InfiniTimeVision.md) +- [Rough structure of the code](doc/code/Intro.md) +- [How to implement an application](doc/code/Apps.md) +- [Generate the fonts and symbols](src/displayapp/fonts/README.md) +- [Tips on designing an app UI](doc/ui_guidelines.md) +- [Bootloader, OTA and DFU](bootloader/README.md) +- [External resources](doc/ExternalResources.md) + +### Contributing + +- [How to contribute?](CONTRIBUTING.md) +- [Coding conventions](doc/coding-convention.md) + +### Build, flash and debug + +- [InfiniTime simulator](https://github.com/InfiniTimeOrg/InfiniSim) +- [Build the project](doc/buildAndProgram.md) +- [Build the project with Docker](doc/buildWithDocker.md) +- [Build the project with VSCode](doc/buildWithVScode.md) +- [Flash the firmware using OpenOCD and STLinkV2](doc/openOCD.md) +- [Flash the firmware using SWD interface](doc/SWD.md) +- [Flash the firmware using JLink](doc/jlink.md) +- [Flash the firmware using GDB](doc/gdb.md) +- [Stub using NRF52-DK](doc/PinetimeStubWithNrf52DK.md) + +### API + +- [BLE implementation and API](doc/ble.md) + +### Architecture and technical topics + +- [Memory analysis](doc/MemoryAnalysis.md) + +### Project management + +- [Maintainer's guide](doc/maintainer-guide.md) +- [Versioning](doc/versioning.md) +- [Project branches](doc/branches.md) +- [Files included in the release notes](doc/filesInReleaseNotes.md) +- [Files needed by the factory](doc/files-needed-by-factory.md) + +## Licenses + +This project is released under the GNU General Public License version 3 or, at your option, any later version. + +It integrates the following projects: + +- RTOS : **[FreeRTOS](https://freertos.org)** under the MIT license +- UI : **[LittleVGL/LVGL](https://lvgl.io/)** under the MIT license +- BLE stack : **[NimBLE](https://github.com/apache/mynewt-nimble)** under the Apache 2.0 license +- Font : **[Jetbrains Mono](https://www.jetbrains.com/fr-fr/lp/mono/)** under the Apache 2.0 license + +## Credits + +I’m not working alone on this project. First, many people create PR for this project. Then, there is the whole #pinetime community : a lot of people all around the world who are hacking, searching, experimenting and programming the Pinetime. We exchange our ideas, experiments and code in the chat rooms and forums. + +Here are some people I would like to highlight: + +- [Atc1441](https://github.com/atc1441/) : He works on an Arduino based firmware for the Pinetime and many other smartwatches based on similar hardware. He was of great help when I was implementing support for the BMA421 motion sensor and I²C driver. +- [Koen](https://github.com/bosmoment) : He’s working on a firmware based on RiotOS. He integrated similar libs as me : NimBLE, LittleVGL,… His help was invaluable too! +- [Lup Yuen Lee](https://github.com/lupyuen) : He is everywhere: he works on a Rust firmware, builds a MCUBoot based bootloader for the Pinetime, designs a Flutter based companion app for smartphones and writes a lot of articles about the Pinetime! From 4e6b1c421fbf9f5fafa295de6ce7742eac17a080 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 23 Sep 2023 22:11:45 -0400 Subject: [PATCH 11/61] Fix todo formatting --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bd9baf4f..dd4c5dd0 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,15 @@ # TODO +## In progress +- [ ] Countdown timer presistant buzz +- [ ] Seconds on digital watchface + ## Medium priority - [ ] Temp sensor w/ arduino -- [/] Countdown timer presistant buzz -- [/] Seconds on digital watchface - [ ] Flashlight starts on - [ ] Homeassistant control - [ ] Swipe down exits music control - [ ] Periodic heart rate measurement - ## Lower priority - [ ] Rearrange quick acces and apps - [ ] Maybe some prank watchfaces From 4449a48de7e0994ba70a78eaf34e37cb494530ff Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 23 Sep 2023 22:15:44 -0400 Subject: [PATCH 12/61] Update todo --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index dd4c5dd0..782c4455 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ # TODO +## Completed +- [x] Make $s in terminal watch face green +- [x] Swipe left to access music control + ## In progress - [ ] Countdown timer presistant buzz - [ ] Seconds on digital watchface From 1fbd00b43dd3d9e408392de33d840c04b0badf25 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 23 Sep 2023 22:25:36 -0400 Subject: [PATCH 13/61] Turn on flashlight on flashlight app launch --- src/displayapp/screens/FlashLight.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/displayapp/screens/FlashLight.cpp b/src/displayapp/screens/FlashLight.cpp index 1b7cf39c..16f25df0 100644 --- a/src/displayapp/screens/FlashLight.cpp +++ b/src/displayapp/screens/FlashLight.cpp @@ -47,6 +47,8 @@ FlashLight::FlashLight(System::SystemTask& systemTask, Controllers::BrightnessCo lv_obj_set_event_cb(backgroundAction, EventHandler); systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); + + Toggle(); } FlashLight::~FlashLight() { From 62e89c1bd3d3f1a239b9d7d59b66ec1bcfdf0127 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 23 Sep 2023 22:28:03 -0400 Subject: [PATCH 14/61] Update todo --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 782c4455..69f7e289 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,15 @@ - [x] Make $s in terminal watch face green - [x] Swipe left to access music control +## Pending merge +- [x] Flashlight starts on + ## In progress - [ ] Countdown timer presistant buzz - [ ] Seconds on digital watchface ## Medium priority - [ ] Temp sensor w/ arduino -- [ ] Flashlight starts on - [ ] Homeassistant control - [ ] Swipe down exits music control - [ ] Periodic heart rate measurement From 9258331e9c32d88d1946ad08e208025ae7b8052e Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 23 Sep 2023 22:39:49 -0400 Subject: [PATCH 15/61] update TODO --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 69f7e289..9602aa51 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,9 @@ ## Medium priority - [ ] Temp sensor w/ arduino - [ ] Homeassistant control -- [ ] Swipe down exits music control +- [ ] Redo music control gestures + - [ ] Swipe up toggles control mode and swipe down exits + - [ ] Swipe left/right goes to watchface/another app - [ ] Periodic heart rate measurement ## Lower priority From c74ae787aea3fba64a89fbc54f3434ee09000f3e Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sun, 24 Sep 2023 02:52:48 +0000 Subject: [PATCH 16/61] Update README.md --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 9602aa51..9412f317 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,16 @@ - [x] Flashlight starts on ## In progress +Elijah - [ ] Countdown timer presistant buzz + +Josh - [ ] Seconds on digital watchface +Moses +- [ ] Redo music control gestures + - [ ] Swipe up toggles control mode and swipe down exits + - [ ] Swipe left/right goes to watchface/another app ## Medium priority - [ ] Temp sensor w/ arduino - [ ] Homeassistant control From a2da74d93abc1a2f569148eef4841e490a9843dd Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 23 Sep 2023 23:01:54 -0400 Subject: [PATCH 17/61] update todo --- README.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9412f317..f5b7e7b6 100644 --- a/README.md +++ b/README.md @@ -2,27 +2,26 @@ ## Completed - [x] Make $s in terminal watch face green - [x] Swipe left to access music control +- [x] Flashlight starts on +- [x] Calculator ## Pending merge -- [x] Flashlight starts on ## In progress -Elijah +### Elijah - [ ] Countdown timer presistant buzz -Josh +### Josh - [ ] Seconds on digital watchface -Moses +### Moses - [ ] Redo music control gestures - [ ] Swipe up toggles control mode and swipe down exits - [ ] Swipe left/right goes to watchface/another app + ## Medium priority - [ ] Temp sensor w/ arduino - [ ] Homeassistant control -- [ ] Redo music control gestures - - [ ] Swipe up toggles control mode and swipe down exits - - [ ] Swipe left/right goes to watchface/another app - [ ] Periodic heart rate measurement ## Lower priority From 09f7306e31a3b7ac96a2ddf05f6012c3759fae6c Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 23 Sep 2023 23:19:10 -0400 Subject: [PATCH 18/61] update todo --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f5b7e7b6..099479a4 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ - [ ] Temp sensor w/ arduino - [ ] Homeassistant control - [ ] Periodic heart rate measurement +- [ ] Exponent button on calculator ## Lower priority - [ ] Rearrange quick acces and apps From 21e86c4220bf4a16b30574fb3728832d8491031c Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sun, 24 Sep 2023 22:17:11 -0400 Subject: [PATCH 19/61] laid down main frame work. Need to add app class --- src/displayapp/DisplayApp.cpp | 2 +- src/displayapp/screens/Music.cpp | 30 ++++++++++++++++++------------ src/displayapp/screens/Music.h | 3 ++- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 61cee716..4220ed76 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -535,7 +535,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio currentScreen = std::make_unique(lvgl); break; case Apps::Music: - currentScreen = std::make_unique(systemTask->nimble().music()); + currentScreen = std::make_unique(this, systemTask->nimble().music()); break; case Apps::Navigation: currentScreen = std::make_unique(systemTask->nimble().navigation()); diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 0763da0f..fe380763 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -47,7 +47,9 @@ inline void lv_img_set_src_arr(lv_obj_t* img, const lv_img_dsc_t* src_img) { * * TODO: Investigate Apple Media Service and AVRCPv1.6 support for seamless integration */ -Music::Music(Pinetime::Controllers::MusicService& music) : musicService(music) { + + +Music::Music(DisplayApp* app, Pinetime::Controllers::MusicService& music) : app {app}, musicService(music) { lv_obj_t* label; lv_style_init(&btn_style); @@ -251,14 +253,6 @@ void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event) { bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) { switch (event) { case TouchEvents::SwipeUp: { - lv_obj_set_hidden(btnVolDown, false); - lv_obj_set_hidden(btnVolUp, false); - - lv_obj_set_hidden(btnNext, true); - lv_obj_set_hidden(btnPrev, true); - return true; - } - case TouchEvents::SwipeDown: { if (lv_obj_get_hidden(btnNext)) { lv_obj_set_hidden(btnNext, false); lv_obj_set_hidden(btnPrev, false); @@ -266,14 +260,26 @@ bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) { lv_obj_set_hidden(btnVolUp, true); return true; } - return false; + else{ + lv_obj_set_hidden(btnVolDown, false); + lv_obj_set_hidden(btnVolUp, false); + + lv_obj_set_hidden(btnNext, true); + lv_obj_set_hidden(btnPrev, true); + } + + return true; + } + case TouchEvents::SwipeDown: { + app->SetFullRefresh(DisplayApp::FullRefreshDirections::Down); + return true; } case TouchEvents::SwipeLeft: { - musicService.event(Controllers::MusicService::EVENT_MUSIC_NEXT); + app->StartApp(Apps::FlashLight, DisplayApp::FullRefreshDirections::LeftAnim); return true; } case TouchEvents::SwipeRight: { - musicService.event(Controllers::MusicService::EVENT_MUSIC_PREV); + app->SetFullRefresh(DisplayApp::FullRefreshDirections::RightAnim); return true; } default: { diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index 847c6e74..b73072bf 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -18,6 +18,7 @@ #pragma once #include +#include "displayapp/DisplayApp.h" #include #include #include "displayapp/screens/Screen.h" @@ -31,7 +32,7 @@ namespace Pinetime { namespace Screens { class Music : public Screen { public: - Music(Pinetime::Controllers::MusicService& music); + Music(DisplayApp* app, Pinetime::Controllers::MusicService& music); ~Music() override; From 163eaf5ab40d97b470c441515ae39533ba9e78bc Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Tue, 26 Sep 2023 21:39:20 -0400 Subject: [PATCH 20/61] Change gestures in Music app and added quick ring --- src/displayapp/DisplayApp.cpp | 33 ++++++++++++++++++++++------ src/displayapp/screens/Music.cpp | 37 ++++++++++---------------------- src/displayapp/screens/Music.h | 2 +- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 4220ed76..31fe135a 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -292,20 +292,41 @@ void DisplayApp::Refresh() { return TouchEvents::SwipeLeft; } }; + if (!currentScreen->OnTouchEvent(gesture)) { - if (currentApp == Apps::Clock) { + if (currentApp == Apps::Clock || currentApp == Apps::Music || currentApp == Apps::Calculator || currentApp == Apps::QuickSettings) { switch (gesture) { case TouchEvents::SwipeUp: - LoadNewScreen(Apps::Launcher, DisplayApp::FullRefreshDirections::Up); + if (currentApp == Apps::Clock) { + LoadNewScreen(Apps::Launcher, DisplayApp::FullRefreshDirections::Up); + } break; case TouchEvents::SwipeDown: - LoadNewScreen(Apps::Notifications, DisplayApp::FullRefreshDirections::Down); + if (currentApp == Apps::Clock) { + LoadNewScreen(Apps::Notifications, DisplayApp::FullRefreshDirections::Down); + } break; case TouchEvents::SwipeRight: - LoadNewScreen(Apps::QuickSettings, DisplayApp::FullRefreshDirections::RightAnim); + if (currentApp == Apps::Clock) { + LoadNewScreen(Apps::QuickSettings, DisplayApp::FullRefreshDirections::RightAnim); + } else if (currentApp == Apps::QuickSettings) { + LoadNewScreen(Apps::Calculator, DisplayApp::FullRefreshDirections::RightAnim); + } else if (currentApp == Apps::Calculator) { + LoadNewScreen(Apps::Music, DisplayApp::FullRefreshDirections::RightAnim); + } else { + LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::RightAnim); + } break; case TouchEvents::SwipeLeft: - LoadNewScreen(Apps::Music, DisplayApp::FullRefreshDirections::LeftAnim); + if (currentApp == Apps::Clock) { + LoadNewScreen(Apps::Music, DisplayApp::FullRefreshDirections::LeftAnim); + } else if (currentApp == Apps::Music) { + LoadNewScreen(Apps::Calculator, DisplayApp::FullRefreshDirections::LeftAnim); + } else if (currentApp == Apps::Calculator) { + LoadNewScreen(Apps::QuickSettings, DisplayApp::FullRefreshDirections::LeftAnim); + } else { + LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::LeftAnim); + } break; case TouchEvents::DoubleTap: PushMessageToSystemTask(System::Messages::GoToSleep); @@ -535,7 +556,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio currentScreen = std::make_unique(lvgl); break; case Apps::Music: - currentScreen = std::make_unique(this, systemTask->nimble().music()); + currentScreen = std::make_unique(systemTask->nimble().music()); break; case Apps::Navigation: currentScreen = std::make_unique(systemTask->nimble().navigation()); diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index fe380763..806132c0 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -49,7 +49,7 @@ inline void lv_img_set_src_arr(lv_obj_t* img, const lv_img_dsc_t* src_img) { */ -Music::Music(DisplayApp* app, Pinetime::Controllers::MusicService& music) : app {app}, musicService(music) { +Music::Music(Pinetime::Controllers::MusicService& music) : musicService(music) { lv_obj_t* label; lv_style_init(&btn_style); @@ -252,34 +252,19 @@ void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event) { bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) { switch (event) { - case TouchEvents::SwipeUp: { - if (lv_obj_get_hidden(btnNext)) { - lv_obj_set_hidden(btnNext, false); - lv_obj_set_hidden(btnPrev, false); - lv_obj_set_hidden(btnVolDown, true); - lv_obj_set_hidden(btnVolUp, true); - return true; - } - else{ - lv_obj_set_hidden(btnVolDown, false); - lv_obj_set_hidden(btnVolUp, false); - - lv_obj_set_hidden(btnNext, true); - lv_obj_set_hidden(btnPrev, true); - } - - return true; - } case TouchEvents::SwipeDown: { - app->SetFullRefresh(DisplayApp::FullRefreshDirections::Down); + lv_obj_set_hidden(btnNext, false); + lv_obj_set_hidden(btnPrev, false); + lv_obj_set_hidden(btnVolDown, true); + lv_obj_set_hidden(btnVolUp, true); return true; } - case TouchEvents::SwipeLeft: { - app->StartApp(Apps::FlashLight, DisplayApp::FullRefreshDirections::LeftAnim); - return true; - } - case TouchEvents::SwipeRight: { - app->SetFullRefresh(DisplayApp::FullRefreshDirections::RightAnim); + case TouchEvents::SwipeUp: { + lv_obj_set_hidden(btnVolDown, false); + lv_obj_set_hidden(btnVolUp, false); + + lv_obj_set_hidden(btnNext, true); + lv_obj_set_hidden(btnPrev, true); return true; } default: { diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index b73072bf..9c5c0945 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -32,7 +32,7 @@ namespace Pinetime { namespace Screens { class Music : public Screen { public: - Music(DisplayApp* app, Pinetime::Controllers::MusicService& music); + Music(Pinetime::Controllers::MusicService& music); ~Music() override; From c8de75ccd90a8a61a44901beaf7a3bc64679f2a0 Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Wed, 27 Sep 2023 16:38:10 -0400 Subject: [PATCH 21/61] Updated Readme and adjusted quicksettings --- README.md | 9 +++++---- src/displayapp/DisplayApp.cpp | 6 +++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 099479a4..b4046005 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,11 @@ - [x] Swipe left to access music control - [x] Flashlight starts on - [x] Calculator +- [x] Redo music control gestures + - [x] Swipe up toggles control mode and swipe down exits + - [x] Swipe left/right goes to watchface/another app +- [x] Rearrange quick acces and apps + ## Pending merge @@ -15,9 +20,6 @@ - [ ] Seconds on digital watchface ### Moses -- [ ] Redo music control gestures - - [ ] Swipe up toggles control mode and swipe down exits - - [ ] Swipe left/right goes to watchface/another app ## Medium priority - [ ] Temp sensor w/ arduino @@ -26,5 +28,4 @@ - [ ] Exponent button on calculator ## Lower priority -- [ ] Rearrange quick acces and apps - [ ] Maybe some prank watchfaces diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 31fe135a..a547cfbc 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -299,12 +299,16 @@ void DisplayApp::Refresh() { case TouchEvents::SwipeUp: if (currentApp == Apps::Clock) { LoadNewScreen(Apps::Launcher, DisplayApp::FullRefreshDirections::Up); + } else if (currentApp == Apps::QuickSettings) { + LoadNewScreen(Apps::Settings, DisplayApp::FullRefreshDirections::Up); } break; case TouchEvents::SwipeDown: if (currentApp == Apps::Clock) { LoadNewScreen(Apps::Notifications, DisplayApp::FullRefreshDirections::Down); - } + } else if (currentApp == Apps::QuickSettings) { + LoadNewScreen(Apps::FlashLight, DisplayApp::FullRefreshDirections::Down); + } break; case TouchEvents::SwipeRight: if (currentApp == Apps::Clock) { From 86695db8833eac21a7e093fc2715b15ecef27c6b Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Wed, 27 Sep 2023 21:27:44 -0400 Subject: [PATCH 22/61] working exponent math --- src/displayapp/screens/Calculator.cpp | 52 ++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index e5d38810..ed81d093 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -17,7 +17,7 @@ Calculator::~Calculator() { } static const char* buttonMap[] = { - "7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ".", "(-)", "=", ""}; + "7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ". ^", "(-)", "=", ""}; Calculator::Calculator() { resultLabel = lv_label_create(lv_scr_act(), nullptr); @@ -72,6 +72,7 @@ void Calculator::HandleInput() { } // we only compare the first char because it is enough + NRF_LOG_INFO("Operation Start: %c", operation); switch (*buttonText) { case '0': case '1': @@ -113,10 +114,29 @@ void Calculator::HandleInput() { break; case '.': - if (offset == FIXED_POINT_OFFSET) { - offset /= 10; - } + NRF_LOG_INFO("Button Pressed"); + switch (operation) { + case ' ': + if (value != 0) { + Eval(); + ResetInput(); + } + operation = '^'; + break; + case '^': + operation = ' '; + break; + default: + if (offset == FIXED_POINT_OFFSET) { + offset /= 10; + } + operation = '.'; + + break; + } + UpdateOperation(); + NRF_LOG_INFO(". offset: %" PRId64, offset); NRF_LOG_INFO(". value: %" PRId64, value); NRF_LOG_INFO(". result: %" PRId64, result); @@ -219,7 +239,7 @@ void Calculator::HandleInput() { break; } - + NRF_LOG_INFO("Operation End: %c", operation); UpdateValueLabel(); UpdateResultLabel(); } @@ -250,6 +270,18 @@ void Calculator::UpdateOperation() const { lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); lv_btnmatrix_set_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); break; + case '^': + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::bgAlt); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 13, LV_BTNMATRIX_CTRL_CHECK_STATE); + break; + case '.': + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::bgAlt); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 13, LV_BTNMATRIX_CTRL_CHECK_STATE); + break; default: lv_btnmatrix_clear_btn_ctrl_all(buttonMatrix, LV_BTNMATRIX_CTRL_CHECK_STATE); break; @@ -390,6 +422,16 @@ void Calculator::Eval() { result *= FIXED_POINT_OFFSET; result /= value; break; + case '^': + // check for zero division + if (value == 0) { + error = Error::ZeroDivision; + break; + } + + result /= FIXED_POINT_OFFSET; + result = pow(result, (value*0.0001))*10000; + break; default: break; From 65976a2b232a55647ce57e3c84c2ff28554a1b5b Mon Sep 17 00:00:00 2001 From: josh Date: Wed, 27 Sep 2023 22:29:08 -0400 Subject: [PATCH 23/61] Added enviroment_setup.md --- enviroment_setup.md | 94 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100755 enviroment_setup.md diff --git a/enviroment_setup.md b/enviroment_setup.md new file mode 100755 index 00000000..3566c56d --- /dev/null +++ b/enviroment_setup.md @@ -0,0 +1,94 @@ +## Clone repositories +1. Clone InfiniTime: +```bash +git clone https://github.com/InfiniTimeOrg/InfiniTime.git +cd InfiniTime +git submodule update --init +``` + +2. Clone InfiniSim: +```bash +cd .. #Ignore this line if you already cd'd into the diretory you want it cloned into +git clone --recursive https://github.com/InfiniTimeOrg/InfiniSim.git +``` + +## Install dependencies +### For building InfiniTime +1. Install Docker +2. Pull docker container (optional, container will be pulled when running the docker container if not pulled now). +```bash +sudo docker pull infinitime/infinitime-build +``` + +### For building InfiniSim +This was the most difficult part for me to get right since the steps on the github page are not entirely complete for my setup. If you encounter errors while building, it's probably because one of the dependencies are missing or have the wrong version installed. If you do have an error while building, check out the issues on github and see if you can find some help there: https://github.com/InfiniTimeOrg/InfiniSim/issues +1. The apt install part. This is almost exactly the same as what is on the github page except for npm. When I added npm in to here, I got an older version that didn't work. We'll install the correct version in step 2. +```bash +sudo apt install -y cmake libsdl2-dev g++ libpng-dev +``` + +2. Install the correct node version. (At least v14.0.0 is required). Commands from https://github.com/nodesource/distributions First, choose the node version by running one of these lines: +```bash +NODE_MAJOR=16 +NODE_MAJOR=18 +NODE_MAJOR=20 +``` +I'm not sure which is the best to use, I went with 16 since that is the closest to the version required by InfiniSim, but I doubt it makes much of a difference. Once you've done that, then install it with these commands: +```bash +sudo apt-get update +sudo apt-get install -y ca-certificates curl gnupg +sudo mkdir -p /etc/apt/keyrings +curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg + +NODE_MAJOR=20 +echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list + +sudo apt-get update +sudo apt-get install nodejs -y +``` + +3. Install npm packages +```bash +npm install lv_font_conv@1.5.2 -g +npm install ts-node@10.9.1 @swc/core@1.3.82 lv_img_conv@0.3.0 -g +``` + + +## Build InfiniSim +### Building with stock InfiniTime +Now to see if we did everything the way our computer wants it. First cd into the directory where InfinSim was cloned (`cd InfiniSim` if you are still in the directory you started in). Now you should be able to build InfiniSim with the InfiniTime version that was included with InfiniSim: +```bash +cmake -S . -B build +cmake --build build -j4 +``` + +If that didn't produce any error, now run it! +```bash +./build/infinisim +``` + +### Building with your own version of InfiniTime +To test your own modifications of InfiniTime: +```bash +cmake -S . -B build -DInfiniTime_DIR=../InfiniTime +cmake --build build -j4 +``` +Assuming that the git clone command was run in the same directory for both InfiniSim and InfiniTime. If not, replace `../InfiniTime` with the path to the directory where InfiniTime was cloned to. +And now run it if there were no errors! +```bash +./build/infinisim +``` + +## Build InfiniTime +Now is the fun part, building your own version of InfiniTime and flashing it to your watch! +First, cd into the directory into which InfiniTime cloned (`cd ~/InfiniTime` if you cloned from your home directory). Now run the docker container (for more info on this command, see https://github.com/InfiniTimeOrg/InfiniTime/blob/main/doc/buildWithDocker.md): +```bash +docker run --rm -it -v ${PWD}:/sources --user $(id -u):$(id -g) infinitime/infinitime-build +``` + +If that doesn't have any errors, it will save the files to build/output/. The file you will want to flash to your watch is `pinetime-mcuboot-app-dfu-x.x.x.zip`. I found a pretty nice program called WatchMate that you can use to flash it from linux, but I think you can also use Gadgetbridge to flash the file. In WatchMate, just scroll down to the "Firmware Version" dropdown and click on "Upload from file" > +"Firmware" and select the zip file mentioned above. Once that's done, you may also want to send it the `infinitime-resources-x.x.x.zip` if some features are greyed out on the watch (for me it was a couple watch faces and the navigation app that were greyed out). In WatchMate, you'll want to use the "Resources" option instead of the "Firmware" option to upload this file. + +## Celebrate +There you go, you've just flashed your own custom os to your watch! If you got all this far without running into any error, you have something to celebrate about as it took me a couple of days to get to this point. If you did have some errors and figured them out, then great, you've got it all figured out now! +One final thing, I would recommend making use of git commits and branches so that you can revert if you totally mess something up and don't have to clone the entire repository and dependencies again like I had to do several times before I decided to start doing that. \ No newline at end of file From 15e525a5bafad548aed2db6f680405e1131b9dfd Mon Sep 17 00:00:00 2001 From: josh Date: Wed, 27 Sep 2023 22:49:58 -0400 Subject: [PATCH 24/61] Update todo and fix docker command in enviroment_setup.md --- README.md | 2 ++ enviroment_setup.md | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 099479a4..b1170874 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ ### Josh - [ ] Seconds on digital watchface +- [ ] Battery on digital watchface +- [ ] Remap button double click (to music app) ### Moses - [ ] Redo music control gestures diff --git a/enviroment_setup.md b/enviroment_setup.md index 3566c56d..1c06b908 100755 --- a/enviroment_setup.md +++ b/enviroment_setup.md @@ -83,7 +83,7 @@ And now run it if there were no errors! Now is the fun part, building your own version of InfiniTime and flashing it to your watch! First, cd into the directory into which InfiniTime cloned (`cd ~/InfiniTime` if you cloned from your home directory). Now run the docker container (for more info on this command, see https://github.com/InfiniTimeOrg/InfiniTime/blob/main/doc/buildWithDocker.md): ```bash -docker run --rm -it -v ${PWD}:/sources --user $(id -u):$(id -g) infinitime/infinitime-build +sudo docker run --rm -it -v ${PWD}:/sources --user $(id -u):$(id -g) infinitime/infinitime-build ``` If that doesn't have any errors, it will save the files to build/output/. The file you will want to flash to your watch is `pinetime-mcuboot-app-dfu-x.x.x.zip`. I found a pretty nice program called WatchMate that you can use to flash it from linux, but I think you can also use Gadgetbridge to flash the file. In WatchMate, just scroll down to the "Firmware Version" dropdown and click on "Upload from file" > @@ -91,4 +91,4 @@ If that doesn't have any errors, it will save the files to build/output/. The fi ## Celebrate There you go, you've just flashed your own custom os to your watch! If you got all this far without running into any error, you have something to celebrate about as it took me a couple of days to get to this point. If you did have some errors and figured them out, then great, you've got it all figured out now! -One final thing, I would recommend making use of git commits and branches so that you can revert if you totally mess something up and don't have to clone the entire repository and dependencies again like I had to do several times before I decided to start doing that. \ No newline at end of file +One final thing, I would recommend making use of git commits and branches so that you can revert if you totally mess something up and don't have to clone the entire repository and dependencies again like I had to do several times before I decided to start doing that. From c87a297a2fa5da6cff58b7c24e4faa321d6001fd Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Thu, 28 Sep 2023 20:35:36 -0400 Subject: [PATCH 25/61] moved backspace and changed around the math for exponent --- src/displayapp/screens/Calculator.cpp | 169 +++++++++++++++----------- src/displayapp/screens/Calculator.h | 3 + 2 files changed, 98 insertions(+), 74 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index ed81d093..f2bbae6e 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -17,7 +17,7 @@ Calculator::~Calculator() { } static const char* buttonMap[] = { - "7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ". ^", "(-)", "=", ""}; + "7", "8", "9", "^", "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ".", "(-)", "=", ""}; Calculator::Calculator() { resultLabel = lv_label_create(lv_scr_act(), nullptr); @@ -25,14 +25,14 @@ Calculator::Calculator() { lv_label_set_align(resultLabel, LV_LABEL_ALIGN_RIGHT); lv_label_set_text_fmt(resultLabel, "%" PRId64, result); lv_obj_set_size(resultLabel, 200, 20); - lv_obj_set_pos(resultLabel, 10, 5); + lv_obj_set_pos(resultLabel, -30, 5); valueLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(valueLabel, LV_LABEL_LONG_CROP); lv_label_set_align(valueLabel, LV_LABEL_ALIGN_RIGHT); lv_label_set_text_fmt(valueLabel, "%" PRId64, value); lv_obj_set_size(valueLabel, 200, 20); - lv_obj_set_pos(valueLabel, 10, 35); + lv_obj_set_pos(valueLabel, -30, 35); buttonMatrix = lv_btnmatrix_create(lv_scr_act(), nullptr); buttonMatrix->user_data = this; @@ -51,17 +51,84 @@ Calculator::Calculator() { lv_obj_set_style_local_bg_opa(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_OPA_COVER); lv_obj_set_style_local_bg_grad_stop(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, 128); lv_obj_set_style_local_bg_main_stop(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, 128); + + // BackSpace Button + /* + lv_style_init(&btn_style); + lv_style_set_radius(&btn_style, LV_STATE_DEFAULT, 10); + lv_style_set_bg_color(&btn_style, LV_STATE_DEFAULT, Colors::bgAlt); + /* + back = lv_btn_create(lv_scr_act(), nullptr); + back->user_data = this; + lv_obj_set_event_cb(back, eventHandler); + + lv_obj_set_style_local_text_font(back, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); + //lv_label_set_text_static(back, "A"); + //lv_label_set_align(back, LV_LABEL_ALIGN_CENTER); + lv_label_set_text_static(back, "A"); + + lv_obj_set_size(back, 59, 44); + lv_obj_align(back, nullptr, LV_ALIGN_IN_TOP_LEFT, 179, 16); +*/ + + + back = lv_btn_create(lv_scr_act(), nullptr); + back->user_data = this; + lv_obj_set_event_cb(back, eventHandler); + lv_obj_set_size(back, 59, 44); + lv_obj_align(back, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 179, 16); + txtback = lv_label_create(back, nullptr); + lv_obj_set_style_local_bg_color(back, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_label_set_text_static(txtback, Symbols::backspace); } + + + + void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { if ((obj == buttonMatrix) && (event == LV_EVENT_PRESSED)) { HandleInput(); + } + + if (obj == back && event == LV_EVENT_PRESSED) { + if (value != 0) { + // delete one value digit + if (offset < FIXED_POINT_OFFSET) { + if (offset == 0) { + offset = 1; + } else { + offset *= 10; + } + } else { + value /= 10; + } + if (offset < FIXED_POINT_OFFSET) { + value -= value % (10 * offset); + } else { + value -= value % offset; + } + } else if (offset < FIXED_POINT_OFFSET) { + if (offset == 0) { + offset = 1; + } else { + offset *= 10; + } + } else { + // reset the result + result = 0; + } + operation = ' '; + UpdateOperation(); + UpdateValueLabel(); + UpdateResultLabel(); } } void Calculator::HandleInput() { const char* buttonText = lv_btnmatrix_get_active_btn_text(buttonMatrix); + if (buttonText == nullptr) { return; } @@ -72,7 +139,6 @@ void Calculator::HandleInput() { } // we only compare the first char because it is enough - NRF_LOG_INFO("Operation Start: %c", operation); switch (*buttonText) { case '0': case '1': @@ -113,30 +179,12 @@ void Calculator::HandleInput() { break; + // Decimal case '.': - NRF_LOG_INFO("Button Pressed"); - - switch (operation) { - case ' ': - if (value != 0) { - Eval(); - ResetInput(); - } - operation = '^'; - break; - case '^': - operation = ' '; - break; - default: - if (offset == FIXED_POINT_OFFSET) { - offset /= 10; - } - operation = '.'; - - break; + if (offset == FIXED_POINT_OFFSET) { + offset /= 10; } - UpdateOperation(); - + NRF_LOG_INFO(". offset: %" PRId64, offset); NRF_LOG_INFO(". value: %" PRId64, value); NRF_LOG_INFO(". result: %" PRId64, result); @@ -146,6 +194,22 @@ void Calculator::HandleInput() { // - eval the current operator if value > FIXED_POINT_OFFSET // - then set the new operator // - + and - as well as * and / cycle on the same button + case '^': + if (value != 0) { + Eval(); + ResetInput(); + } + switch (operation) { + case ' ': + operation = '^'; + break; + default: + operation = ' '; + break; + } + UpdateOperation(); + break; + case '+': if (value != 0) { Eval(); @@ -186,43 +250,6 @@ void Calculator::HandleInput() { UpdateOperation(); break; - // this is a little hacky because it matches only the first char - case Symbols::backspace[0]: - if (value != 0) { - // delete one value digit - if (offset < FIXED_POINT_OFFSET) { - if (offset == 0) { - offset = 1; - } else { - offset *= 10; - } - } else { - value /= 10; - } - if (offset < FIXED_POINT_OFFSET) { - value -= value % (10 * offset); - } else { - value -= value % offset; - } - } else if (offset < FIXED_POINT_OFFSET) { - if (offset == 0) { - offset = 1; - } else { - offset *= 10; - } - } else { - // reset the result - result = 0; - } - - NRF_LOG_INFO(". offset: %" PRId64, offset); - NRF_LOG_INFO(". value: %" PRId64, value); - NRF_LOG_INFO(". result: %" PRId64, result); - - operation = ' '; - UpdateOperation(); - break; - case '=': equalSignPressed = true; Eval(); @@ -271,16 +298,10 @@ void Calculator::UpdateOperation() const { lv_btnmatrix_set_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); break; case '^': - lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); - lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::bgAlt); - lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); - lv_btnmatrix_set_btn_ctrl(buttonMatrix, 13, LV_BTNMATRIX_CTRL_CHECK_STATE); - break; - case '.': lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); - lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::bgAlt); - lv_btnmatrix_set_btn_ctrl(buttonMatrix, 13, LV_BTNMATRIX_CTRL_CHECK_STATE); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 3, LV_BTNMATRIX_CTRL_CHECK_STATE); break; default: lv_btnmatrix_clear_btn_ctrl_all(buttonMatrix, LV_BTNMATRIX_CTRL_CHECK_STATE); @@ -428,9 +449,9 @@ void Calculator::Eval() { error = Error::ZeroDivision; break; } - - result /= FIXED_POINT_OFFSET; - result = pow(result, (value*0.0001))*10000; + place_holder = result; + place_holder /= FIXED_POINT_OFFSET; + result = pow(place_holder, (value*0.0001))*10000; break; default: diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 17513861..4b03faf7 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -28,6 +28,9 @@ namespace Pinetime { lv_obj_t* buttonMatrix {}; lv_obj_t* valueLabel {}; lv_obj_t* resultLabel {}; + lv_obj_t* back; + lv_obj_t* txtback; + double place_holder; void Eval(); void ResetInput(); From 8a40eaa9c5ded0690efedfc347c92989b6742ed1 Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Thu, 28 Sep 2023 20:38:01 -0400 Subject: [PATCH 26/61] fixed calculator comments --- src/displayapp/screens/Calculator.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index f2bbae6e..2f77c5dd 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -53,24 +53,6 @@ Calculator::Calculator() { lv_obj_set_style_local_bg_main_stop(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, 128); // BackSpace Button - /* - lv_style_init(&btn_style); - lv_style_set_radius(&btn_style, LV_STATE_DEFAULT, 10); - lv_style_set_bg_color(&btn_style, LV_STATE_DEFAULT, Colors::bgAlt); - /* - back = lv_btn_create(lv_scr_act(), nullptr); - back->user_data = this; - lv_obj_set_event_cb(back, eventHandler); - - lv_obj_set_style_local_text_font(back, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); - //lv_label_set_text_static(back, "A"); - //lv_label_set_align(back, LV_LABEL_ALIGN_CENTER); - lv_label_set_text_static(back, "A"); - - lv_obj_set_size(back, 59, 44); - lv_obj_align(back, nullptr, LV_ALIGN_IN_TOP_LEFT, 179, 16); -*/ - back = lv_btn_create(lv_scr_act(), nullptr); back->user_data = this; From 1fd2496ee224a48cd2aa12bf40b588053b966192 Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Fri, 29 Sep 2023 01:46:02 +0000 Subject: [PATCH 27/61] Update README.md --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b1170874..5ed317db 100644 --- a/README.md +++ b/README.md @@ -17,16 +17,17 @@ - [ ] Remap button double click (to music app) ### Moses -- [ ] Redo music control gestures - - [ ] Swipe up toggles control mode and swipe down exits - - [ ] Swipe left/right goes to watchface/another app - +- [x] Redo music control gestures + - [x] Swipe up toggles control mode and swipe down exits + - [x] Swipe left/right goes to watchface/another app +- [x] Exponent button on calculator +- [x] Rearrange quick acces and apps +- [ ] Add quick ring settings + ## Medium priority - [ ] Temp sensor w/ arduino - [ ] Homeassistant control - [ ] Periodic heart rate measurement -- [ ] Exponent button on calculator ## Lower priority -- [ ] Rearrange quick acces and apps - [ ] Maybe some prank watchfaces From cdd97b387113aa04fe5a241676487f86621e9d20 Mon Sep 17 00:00:00 2001 From: josh Date: Fri, 29 Sep 2023 23:15:07 -0400 Subject: [PATCH 28/61] Added battery percent to digital watch face --- src/displayapp/screens/WatchFaceDigital.cpp | 11 +++++++++++ src/displayapp/screens/WatchFaceDigital.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index 1fbfc15a..df481806 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -23,6 +23,7 @@ WatchFaceDigital::WatchFaceDigital(Controllers::DateTime& dateTimeController, : currentDateTime {{}}, dateTimeController {dateTimeController}, notificationManager {notificationManager}, + batteryController {batteryController}, settingsController {settingsController}, heartRateController {heartRateController}, motionController {motionController}, @@ -34,6 +35,11 @@ WatchFaceDigital::WatchFaceDigital(Controllers::DateTime& dateTimeController, lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_LIME); lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(false)); lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); + + + batteryValue = lv_label_create(lv_scr_act(), nullptr); + //lv_label_set_recolor(batteryValue, true); + lv_obj_align(batteryValue, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -3, -110); label_seconds = lv_label_create(lv_scr_act(), nullptr); // for secs lv_obj_align(label_seconds, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, -55); @@ -83,6 +89,11 @@ WatchFaceDigital::~WatchFaceDigital() { void WatchFaceDigital::Refresh() { statusIcons.Update(); + + batteryPercentRemaining = batteryController.PercentRemaining(); + if (batteryPercentRemaining.IsUpdated()) { + lv_label_set_text_fmt(batteryValue, "%d%%", batteryPercentRemaining.Get()); + } notificationState = notificationManager.AreNewNotificationsAvailable(); if (notificationState.IsUpdated()) { diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h index 5b0ce672..4b66ae0b 100644 --- a/src/displayapp/screens/WatchFaceDigital.h +++ b/src/displayapp/screens/WatchFaceDigital.h @@ -55,6 +55,7 @@ namespace Pinetime { lv_obj_t* label_time; lv_obj_t* label_seconds; //for secs //lv_obj_t* label_time_ampm; + lv_obj_t* batteryValue; lv_obj_t* label_date; lv_obj_t* heartbeatIcon; lv_obj_t* heartbeatValue; @@ -63,6 +64,7 @@ namespace Pinetime { lv_obj_t* notificationIcon; Controllers::DateTime& dateTimeController; + const Controllers::Battery& batteryController; Controllers::NotificationManager& notificationManager; Controllers::Settings& settingsController; Controllers::HeartRateController& heartRateController; From e19e87029019a324e86858b4438da34b63ff4dfe Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sun, 1 Oct 2023 17:47:08 -0400 Subject: [PATCH 29/61] created a working quick ring setting gui --- src/components/settings/Settings.h | 31 ++++++++ src/displayapp/Apps.h | 3 +- src/displayapp/DisplayApp.cpp | 17 +++- .../screens/settings/SettingQuickR.cpp | 77 +++++++++++++++++++ .../screens/settings/SettingQuickR.h | 42 ++++++++++ src/displayapp/screens/settings/Settings.h | 7 +- 6 files changed, 170 insertions(+), 7 deletions(-) create mode 100644 src/displayapp/screens/settings/SettingQuickR.cpp create mode 100644 src/displayapp/screens/settings/SettingQuickR.h diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index 81cf4923..f2561ec8 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -13,6 +13,7 @@ namespace Pinetime { enum class Notification : uint8_t { On, Off, Sleep }; enum class ChimesOption : uint8_t { None, Hours, HalfHours }; enum class WakeUpMode : uint8_t { SingleTap = 0, DoubleTap = 1, RaiseWrist = 2, Shake = 3, LowerWrist = 4 }; + enum class QuickApp : uint8_t { MusicPlayer = 0, Calculator = 1, Flashlight = 2, Step = 3, HeartRate = 4 }; //, Alarm = 5, Timer = 6, Stopwatch = 7 }; enum class Colors : uint8_t { White, Silver, @@ -241,6 +242,34 @@ namespace Pinetime { return getWakeUpModes()[static_cast(mode)]; } + + + + + // New Settings + void SetQuickRModes(QuickApp App_now, bool enabled) { + if (enabled != isQuickROn(App_now)) { + settingsChanged = true; + } + settings.quickApp.set(static_cast(App_now), enabled); + }; + + std::bitset<5> getQuickRModes() const { + return settings.quickApp; + } + + bool isQuickROn(const QuickApp app_holder) const { + return getQuickRModes()[static_cast(app_holder)]; + } + + + + + + + + + void SetBrightness(Controllers::BrightnessController::Levels level) { if (level != settings.brightLevel) { settingsChanged = true; @@ -279,6 +308,7 @@ namespace Pinetime { struct SettingsData { uint32_t version = settingsVersion; uint32_t stepsGoal = 10000; + uint32_t setquickr = 10000; uint32_t screenTimeOut = 15000; ClockType clockType = ClockType::H24; @@ -292,6 +322,7 @@ namespace Pinetime { WatchFaceInfineat watchFaceInfineat; std::bitset<5> wakeUpMode {0}; + std::bitset<5> quickApp {0}; uint16_t shakeWakeThreshold = 150; Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium; diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index c8a48228..1e951938 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -38,7 +38,8 @@ namespace Pinetime { SettingShakeThreshold, SettingBluetooth, Error, - Calculator + Calculator, + SettingQuickR }; } } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index a547cfbc..4cfdd344 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -51,6 +51,7 @@ #include "displayapp/screens/settings/SettingChimes.h" #include "displayapp/screens/settings/SettingShakeThreshold.h" #include "displayapp/screens/settings/SettingBluetooth.h" +#include "displayapp/screens/settings/SettingQuickR.h" #include "libs/lv_conf.h" @@ -293,6 +294,11 @@ void DisplayApp::Refresh() { } }; + std::bitset<5> quick_app = settingsController.getQuickRModes(); + bool value = (quick_app[0] ? 1 : 0 ); + NRF_LOG_INFO("Value of Quick app: %i", value); + + if (!currentScreen->OnTouchEvent(gesture)) { if (currentApp == Apps::Clock || currentApp == Apps::Music || currentApp == Apps::Calculator || currentApp == Apps::QuickSettings) { switch (gesture) { @@ -313,18 +319,18 @@ void DisplayApp::Refresh() { case TouchEvents::SwipeRight: if (currentApp == Apps::Clock) { LoadNewScreen(Apps::QuickSettings, DisplayApp::FullRefreshDirections::RightAnim); - } else if (currentApp == Apps::QuickSettings) { + } else if (currentApp == Apps::QuickSettings && quick_app[1]) { LoadNewScreen(Apps::Calculator, DisplayApp::FullRefreshDirections::RightAnim); - } else if (currentApp == Apps::Calculator) { + } else if (currentApp == Apps::Calculator && quick_app[0]) { LoadNewScreen(Apps::Music, DisplayApp::FullRefreshDirections::RightAnim); } else { LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::RightAnim); } break; case TouchEvents::SwipeLeft: - if (currentApp == Apps::Clock) { + if (currentApp == Apps::Clock && quick_app[0]) { LoadNewScreen(Apps::Music, DisplayApp::FullRefreshDirections::LeftAnim); - } else if (currentApp == Apps::Music) { + } else if (currentApp == Apps::Music && quick_app[1]) { LoadNewScreen(Apps::Calculator, DisplayApp::FullRefreshDirections::LeftAnim); } else if (currentApp == Apps::Calculator) { LoadNewScreen(Apps::QuickSettings, DisplayApp::FullRefreshDirections::LeftAnim); @@ -583,6 +589,9 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio case Apps::Calculator: currentScreen = std::make_unique(); break; + case Apps::SettingQuickR: + currentScreen = std::make_unique(settingsController); + break; } currentApp = app; } diff --git a/src/displayapp/screens/settings/SettingQuickR.cpp b/src/displayapp/screens/settings/SettingQuickR.cpp new file mode 100644 index 00000000..6b4e98a9 --- /dev/null +++ b/src/displayapp/screens/settings/SettingQuickR.cpp @@ -0,0 +1,77 @@ +#include "displayapp/screens/settings/SettingQuickR.h" +#include +#include "displayapp/DisplayApp.h" +#include "displayapp/screens/Symbols.h" +#include "displayapp/InfiniTimeTheme.h" + +using namespace Pinetime::Applications::Screens; + + + +namespace { + void event_handler(lv_obj_t* obj, lv_event_t event) { + auto* screen = static_cast(obj->user_data); + if (event == LV_EVENT_VALUE_CHANGED) { + screen->UpdateSelected(obj); + } + } +} + +SettingQuickR::SettingQuickR(Pinetime::Controllers::Settings& settingsController) : settingsController {settingsController} { + lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr); + + lv_obj_set_style_local_bg_opa(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); + lv_obj_set_style_local_pad_all(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 10); + lv_obj_set_style_local_pad_inner(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5); + lv_obj_set_style_local_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); + + lv_obj_set_pos(container1, 10, 35); + lv_obj_set_width(container1, LV_HOR_RES - 20); + lv_obj_set_height(container1, LV_VER_RES - 20); + lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT); + + lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(title, "Quick Ring"); + lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); + lv_obj_align(title, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 15, 15); + + lv_obj_t* icon = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); + lv_label_set_text_static(icon, Symbols::check); + lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); + lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); + + for (unsigned int i = 0; i < options.size(); i++) { + cbOption[i] = lv_checkbox_create(container1, nullptr); + lv_checkbox_set_text(cbOption[i], options[i].name); + if (settingsController.isQuickROn(static_cast(i))) { + lv_checkbox_set_checked(cbOption[i], true); + } + cbOption[i]->user_data = this; + lv_obj_set_event_cb(cbOption[i], event_handler); + } +} + +SettingQuickR::~SettingQuickR() { + lv_obj_clean(lv_scr_act()); + settingsController.SaveSettings(); +} + +void SettingQuickR::UpdateSelected(lv_obj_t* object) { + // Find the index of the checkbox that triggered the event + for (size_t i = 0; i < options.size(); i++) { + if (cbOption[i] == object) { + bool currentState = settingsController.isQuickROn(options[i].quickApp); + settingsController.SetQuickRModes(options[i].quickApp, !currentState); + break; + } + } + + // Update checkbox according to current wakeup modes. + // This is needed because we can have extra logic when setting or unsetting wakeup modes, + // for example, when setting SingleTap, DoubleTap is unset and vice versa. + auto modes = settingsController.getQuickRModes(); + for (size_t i = 0; i < options.size(); ++i) { + lv_checkbox_set_checked(cbOption[i], modes[i]); + } +} diff --git a/src/displayapp/screens/settings/SettingQuickR.h b/src/displayapp/screens/settings/SettingQuickR.h new file mode 100644 index 00000000..c7d7c74a --- /dev/null +++ b/src/displayapp/screens/settings/SettingQuickR.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include +#include "components/settings/Settings.h" +#include "displayapp/screens/Screen.h" + +namespace Pinetime { + + namespace Applications { + namespace Screens { + + class SettingQuickR : public Screen { + public: + SettingQuickR(Pinetime::Controllers::Settings& settingsController); + ~SettingQuickR() override; + void UpdateSelected(lv_obj_t* object); + + private: + struct Option { + Controllers::Settings::QuickApp quickApp; + const char* name; + }; + + static constexpr std::array options = {{ + {Controllers::Settings::QuickApp::MusicPlayer, "Music Player"}, + {Controllers::Settings::QuickApp::Calculator, "Calculator"}, + {Controllers::Settings::QuickApp::Flashlight, "Flashlight"}, + {Controllers::Settings::QuickApp::Step, "Steps"}, + {Controllers::Settings::QuickApp::HeartRate, "Heart Rate"}, +// {Controllers::Settings::QuickApp::Alarm, "Alarm"}, +// {Controllers::Settings::QuickApp::Timer, "Timer"}, +// {Controllers::Settings::QuickApp::Stopwatch, "Stopwatch"}, + }}; + + lv_obj_t* cbOption[options.size()]; + Controllers::Settings& settingsController; + }; + } + } +} diff --git a/src/displayapp/screens/settings/Settings.h b/src/displayapp/screens/settings/Settings.h index 3f809753..c21fa234 100644 --- a/src/displayapp/screens/settings/Settings.h +++ b/src/displayapp/screens/settings/Settings.h @@ -29,7 +29,7 @@ namespace Pinetime { static constexpr int entriesPerScreen = 4; // Increment this when more space is needed - static constexpr int nScreens = 3; + static constexpr int nScreens = 4; static constexpr std::array entries {{ {Symbols::sun, "Display", Apps::SettingDisplay}, @@ -40,11 +40,14 @@ namespace Pinetime { {Symbols::shoe, "Steps", Apps::SettingSteps}, {Symbols::clock, "Date&Time", Apps::SettingSetDateTime}, {Symbols::batteryHalf, "Battery", Apps::BatteryInfo}, - {Symbols::clock, "Chimes", Apps::SettingChimes}, + {Symbols::check, "QuickRing", Apps::SettingQuickR}, + + {Symbols::clock, "Chimes", Apps::SettingChimes}, {Symbols::tachometer, "Shake Calib.", Apps::SettingShakeThreshold}, {Symbols::check, "Firmware", Apps::FirmwareValidation}, {Symbols::bluetooth, "Bluetooth", Apps::SettingBluetooth}, + {Symbols::list, "About", Apps::SysInfo}, // {Symbols::none, "None", Apps::None}, From b488811f7f70dd45c839d5c113e99f04c6d28f1c Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Tue, 3 Oct 2023 19:02:33 -0400 Subject: [PATCH 30/61] working sim --- src/CMakeLists.txt | 1 + src/components/settings/Settings.h | 2 +- src/displayapp/DisplayApp.cpp | 110 ++++++++++++++---- src/displayapp/DisplayApp.h | 4 + .../screens/settings/SettingQuickR.cpp | 6 +- .../screens/settings/SettingQuickR.h | 9 +- 6 files changed, 98 insertions(+), 34 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a01311b6..68f94328 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -426,6 +426,7 @@ list(APPEND SOURCE_FILES displayapp/screens/settings/SettingChimes.cpp displayapp/screens/settings/SettingShakeThreshold.cpp displayapp/screens/settings/SettingBluetooth.cpp + displayapp/screens/settings/SettingQuickR.cpp ## Watch faces displayapp/screens/WatchFaceAnalog.cpp diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index f2561ec8..8b42b298 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -13,7 +13,7 @@ namespace Pinetime { enum class Notification : uint8_t { On, Off, Sleep }; enum class ChimesOption : uint8_t { None, Hours, HalfHours }; enum class WakeUpMode : uint8_t { SingleTap = 0, DoubleTap = 1, RaiseWrist = 2, Shake = 3, LowerWrist = 4 }; - enum class QuickApp : uint8_t { MusicPlayer = 0, Calculator = 1, Flashlight = 2, Step = 3, HeartRate = 4 }; //, Alarm = 5, Timer = 6, Stopwatch = 7 }; + enum class QuickApp : uint8_t { MusicPlayer = 0, Calculator = 1, Timer = 2, Alarm = 3, HeartRate = 4 }; //, Alarm = 5, Timer = 6, Stopwatch = 7 }; enum class Colors : uint8_t { White, Silver, diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 4cfdd344..a7ef1e54 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -293,14 +293,9 @@ void DisplayApp::Refresh() { return TouchEvents::SwipeLeft; } }; - - std::bitset<5> quick_app = settingsController.getQuickRModes(); - bool value = (quick_app[0] ? 1 : 0 ); - NRF_LOG_INFO("Value of Quick app: %i", value); - if (!currentScreen->OnTouchEvent(gesture)) { - if (currentApp == Apps::Clock || currentApp == Apps::Music || currentApp == Apps::Calculator || currentApp == Apps::QuickSettings) { + if (currentApp == Apps::Clock || currentApp == Apps::QuickSettings || (currentApp == Apps::Music && quick_app[0]) || (currentApp == Apps::Calculator && quick_app[1]) || (currentApp == Apps::Alarm && quick_app[2]) || (currentApp == Apps::Timer && quick_app[3]) || (currentApp == Apps::HeartRate && quick_app[4])) { switch (gesture) { case TouchEvents::SwipeUp: if (currentApp == Apps::Clock) { @@ -317,26 +312,10 @@ void DisplayApp::Refresh() { } break; case TouchEvents::SwipeRight: - if (currentApp == Apps::Clock) { - LoadNewScreen(Apps::QuickSettings, DisplayApp::FullRefreshDirections::RightAnim); - } else if (currentApp == Apps::QuickSettings && quick_app[1]) { - LoadNewScreen(Apps::Calculator, DisplayApp::FullRefreshDirections::RightAnim); - } else if (currentApp == Apps::Calculator && quick_app[0]) { - LoadNewScreen(Apps::Music, DisplayApp::FullRefreshDirections::RightAnim); - } else { - LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::RightAnim); - } + gotoquickapp(-1); break; case TouchEvents::SwipeLeft: - if (currentApp == Apps::Clock && quick_app[0]) { - LoadNewScreen(Apps::Music, DisplayApp::FullRefreshDirections::LeftAnim); - } else if (currentApp == Apps::Music && quick_app[1]) { - LoadNewScreen(Apps::Calculator, DisplayApp::FullRefreshDirections::LeftAnim); - } else if (currentApp == Apps::Calculator) { - LoadNewScreen(Apps::QuickSettings, DisplayApp::FullRefreshDirections::LeftAnim); - } else { - LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::LeftAnim); - } + gotoquickapp(1); break; case TouchEvents::DoubleTap: PushMessageToSystemTask(System::Messages::GoToSleep); @@ -355,6 +334,7 @@ void DisplayApp::Refresh() { if (!currentScreen->OnButtonPushed()) { if (currentApp == Apps::Clock) { PushMessageToSystemTask(System::Messages::GoToSleep); + } else { LoadPreviousScreen(); } @@ -448,6 +428,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio // break; case Apps::None: case Apps::Clock: + currentQ_app = 2; currentScreen = std::make_unique(dateTimeController, batteryController, bleController, @@ -651,3 +632,84 @@ void DisplayApp::ApplyBrightness() { } brightnessController.Set(brightness); } + + void DisplayApp::gotoquickapp(int app_step){ + NRF_LOG_INFO("QuickRing Swiped"); + currentQ_app += app_step; + + quick_app = settingsController.getQuickRModes(); + + while(true) + { + if(currentQ_app > 7) + { + currentQ_app = 1; + } else if(currentQ_app < 1) + { + currentQ_app = 7; + } + + if(currentQ_app != 1 && currentQ_app != 2) + { + if(quick_app[currentQ_app-3]) + { + break; + } + else + { + currentQ_app += (app_step); + } + } + else + { + break; + } + } + + + int quickringtotal = 2; + for(int i = 0; i < 5; i++){ + quickringtotal += (quick_app[i] ? 1 : 0 ); + } + + + + NRF_LOG_INFO("case number current Q: %i", currentQ_app); + Apps app = Apps::Clock; + switch (currentQ_app) { + case 1: + app = Apps::QuickSettings; + break; + case 2: + app = Apps::Clock; + break; + case 3: + app = Apps::Music; + break; + case 4: + app = Apps::Calculator; + break; + case 5: + app = Apps::Alarm; + break; + case 6: + app = Apps::Timer; + break; + case 7: + app = Apps::HeartRate; + break; + default: + break; + } + + + if(app_step < 0){ + LoadNewScreen(app, DisplayApp::FullRefreshDirections::RightAnim); + } + else + { + LoadNewScreen(app, DisplayApp::FullRefreshDirections::LeftAnim); + } + //appStackDirections.Pop(); + //returnAppStack.Pop(); + } \ No newline at end of file diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index f537651d..a42b539d 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -118,6 +118,8 @@ namespace Pinetime { void LoadNewScreen(Apps app, DisplayApp::FullRefreshDirections direction); void LoadScreen(Apps app, DisplayApp::FullRefreshDirections direction); void PushMessageToSystemTask(Pinetime::System::Messages message); + void gotoquickapp(int app_step); + Apps nextApp = Apps::None; DisplayApp::FullRefreshDirections nextDirection; @@ -129,6 +131,8 @@ namespace Pinetime { Utility::StaticStack appStackDirections; bool isDimmed = false; + int currentQ_app = 2; + std::bitset<5> quick_app; }; } } diff --git a/src/displayapp/screens/settings/SettingQuickR.cpp b/src/displayapp/screens/settings/SettingQuickR.cpp index 6b4e98a9..2035aefd 100644 --- a/src/displayapp/screens/settings/SettingQuickR.cpp +++ b/src/displayapp/screens/settings/SettingQuickR.cpp @@ -41,7 +41,7 @@ SettingQuickR::SettingQuickR(Pinetime::Controllers::Settings& settingsController lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); - for (unsigned int i = 0; i < options.size(); i++) { + for (unsigned int i = 0; i < 5; i++) { cbOption[i] = lv_checkbox_create(container1, nullptr); lv_checkbox_set_text(cbOption[i], options[i].name); if (settingsController.isQuickROn(static_cast(i))) { @@ -59,7 +59,7 @@ SettingQuickR::~SettingQuickR() { void SettingQuickR::UpdateSelected(lv_obj_t* object) { // Find the index of the checkbox that triggered the event - for (size_t i = 0; i < options.size(); i++) { + for (size_t i = 0; i < 5; i++) { if (cbOption[i] == object) { bool currentState = settingsController.isQuickROn(options[i].quickApp); settingsController.SetQuickRModes(options[i].quickApp, !currentState); @@ -71,7 +71,7 @@ void SettingQuickR::UpdateSelected(lv_obj_t* object) { // This is needed because we can have extra logic when setting or unsetting wakeup modes, // for example, when setting SingleTap, DoubleTap is unset and vice versa. auto modes = settingsController.getQuickRModes(); - for (size_t i = 0; i < options.size(); ++i) { + for (size_t i = 0; i < 5; ++i) { lv_checkbox_set_checked(cbOption[i], modes[i]); } } diff --git a/src/displayapp/screens/settings/SettingQuickR.h b/src/displayapp/screens/settings/SettingQuickR.h index c7d7c74a..cf70d19e 100644 --- a/src/displayapp/screens/settings/SettingQuickR.h +++ b/src/displayapp/screens/settings/SettingQuickR.h @@ -26,15 +26,12 @@ namespace Pinetime { static constexpr std::array options = {{ {Controllers::Settings::QuickApp::MusicPlayer, "Music Player"}, {Controllers::Settings::QuickApp::Calculator, "Calculator"}, - {Controllers::Settings::QuickApp::Flashlight, "Flashlight"}, - {Controllers::Settings::QuickApp::Step, "Steps"}, + {Controllers::Settings::QuickApp::Alarm, "Alarms"}, + {Controllers::Settings::QuickApp::Timer, "Timer"}, {Controllers::Settings::QuickApp::HeartRate, "Heart Rate"}, -// {Controllers::Settings::QuickApp::Alarm, "Alarm"}, -// {Controllers::Settings::QuickApp::Timer, "Timer"}, -// {Controllers::Settings::QuickApp::Stopwatch, "Stopwatch"}, }}; - lv_obj_t* cbOption[options.size()]; + lv_obj_t* cbOption[5]; Controllers::Settings& settingsController; }; } From 8ff6bd9cae64a901fc362780c083c109fdcc5dde Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Fri, 6 Oct 2023 21:04:42 -0400 Subject: [PATCH 31/61] changed chime --- src/displayapp/DisplayApp.cpp | 13 ++++++++++++- src/displayapp/DisplayApp.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index a547cfbc..4c670a8e 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -389,7 +389,18 @@ void DisplayApp::Refresh() { break; case Messages::Chime: LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::None); - motorController.RunForDuration(35); + time_var = dateTimeController.Minutes(); + if (time_var == 30){ + NRF_LOG_INFO("Short: %d", time_var); + motorController.RunForDuration(25); + } + else + { + NRF_LOG_INFO("Long: %d", time_var); + motorController.RunForDuration(200); + } + + break; case Messages::OnChargingEvent: RestoreBrightness(); diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index f537651d..2c8a3b64 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -128,6 +128,7 @@ namespace Pinetime { Utility::StaticStack returnAppStack; Utility::StaticStack appStackDirections; + int time_var; bool isDimmed = false; }; } From 9d749434b560babd05611a8edac9d82f26de6351 Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sat, 7 Oct 2023 11:41:36 -0400 Subject: [PATCH 32/61] added red flashlight --- src/displayapp/DisplayApp.cpp | 2 +- src/displayapp/screens/FlashLight.cpp | 51 +++++++++++++++++++++++---- src/displayapp/screens/FlashLight.h | 6 ++-- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 4c670a8e..0d3cc441 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -556,7 +556,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio touchPanel); break; case Apps::FlashLight: - currentScreen = std::make_unique(*systemTask, brightnessController); + currentScreen = std::make_unique(*systemTask, brightnessController, dateTimeController); break; case Apps::StopWatch: currentScreen = std::make_unique(*systemTask); diff --git a/src/displayapp/screens/FlashLight.cpp b/src/displayapp/screens/FlashLight.cpp index 16f25df0..62c36805 100644 --- a/src/displayapp/screens/FlashLight.cpp +++ b/src/displayapp/screens/FlashLight.cpp @@ -2,6 +2,7 @@ #include "displayapp/DisplayApp.h" #include "displayapp/screens/Symbols.h" #include "displayapp/InfiniTimeTheme.h" +#include using namespace Pinetime::Applications::Screens; @@ -14,11 +15,24 @@ namespace { } } -FlashLight::FlashLight(System::SystemTask& systemTask, Controllers::BrightnessController& brightnessController) - : systemTask {systemTask}, brightnessController {brightnessController} { +FlashLight::FlashLight(System::SystemTask& systemTask, Controllers::BrightnessController& brightnessController, Controllers::DateTime& dateTimeController) + : systemTask {systemTask}, brightnessController {brightnessController}, dateTimeController {dateTimeController} { brightnessController.Set(Controllers::BrightnessController::Levels::Low); + + + + int time_var = dateTimeController.Hours(); + if(time_var > 21 || time_var < 6){ + State_l = 1; + NRF_LOG_INFO("Loop Hour Red: %d", time_var); + } + else { + State_l = 0; + NRF_LOG_INFO("Loop Hour White: %d", time_var); + } + flashLight = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(flashLight, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48); lv_label_set_text_static(flashLight, Symbols::flashlight); @@ -58,8 +72,17 @@ FlashLight::~FlashLight() { } void FlashLight::SetColors() { - lv_color_t bgColor = isOn ? LV_COLOR_WHITE : LV_COLOR_BLACK; - lv_color_t fgColor = isOn ? Colors::lightGray : LV_COLOR_WHITE; + lv_color_t bgColor = LV_COLOR_BLACK; + if(State_l == 0){ + bgColor = LV_COLOR_BLACK; + } else if (State_l == 1){ + bgColor = LV_COLOR_WHITE; + } + else { + bgColor = lv_color_hex(0xff0000); + } + + lv_color_t fgColor = State_l ? Colors::lightGray : LV_COLOR_WHITE; lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, bgColor); lv_obj_set_style_local_text_color(flashLight, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, fgColor); @@ -86,9 +109,11 @@ void FlashLight::SetIndicators() { } void FlashLight::Toggle() { - isOn = !isOn; + State_l++; + if(State_l > 2) + State_l = 0; SetColors(); - if (isOn) { + if (State_l) { brightnessController.Set(brightnessLevel); } else { brightnessController.Set(Controllers::BrightnessController::Levels::Low); @@ -99,7 +124,7 @@ bool FlashLight::OnTouchEvent(Pinetime::Applications::TouchEvents event) { using namespace Pinetime::Controllers; auto SetState = [this]() { - if (isOn) { + if (State_l) { brightnessController.Set(brightnessLevel); } SetIndicators(); @@ -128,3 +153,15 @@ bool FlashLight::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return false; } +/* + time_var = dateTimeController.Minutes(); + if (time_var == 30){ + NRF_LOG_INFO("Short: %d", time_var); + motorController.RunForDuration(25); + } + else + { + NRF_LOG_INFO("Long: %d", time_var); + motorController.RunForDuration(200); + } +*/ \ No newline at end of file diff --git a/src/displayapp/screens/FlashLight.h b/src/displayapp/screens/FlashLight.h index 2b710ed5..1481838e 100644 --- a/src/displayapp/screens/FlashLight.h +++ b/src/displayapp/screens/FlashLight.h @@ -2,6 +2,7 @@ #include "displayapp/screens/Screen.h" #include "components/brightness/BrightnessController.h" +#include "components/datetime/DateTimeController.h" #include "systemtask/SystemTask.h" #include #include @@ -13,7 +14,7 @@ namespace Pinetime { class FlashLight : public Screen { public: - FlashLight(System::SystemTask& systemTask, Controllers::BrightnessController& brightness); + FlashLight(System::SystemTask& systemTask, Controllers::BrightnessController& brightness, Controllers::DateTime& dateTimeController); ~FlashLight() override; bool OnTouchEvent(Pinetime::Applications::TouchEvents event) override; @@ -25,13 +26,14 @@ namespace Pinetime { Pinetime::System::SystemTask& systemTask; Controllers::BrightnessController& brightnessController; + Controllers::DateTime& dateTimeController; Controllers::BrightnessController::Levels brightnessLevel = Controllers::BrightnessController::Levels::High; lv_obj_t* flashLight; lv_obj_t* backgroundAction; lv_obj_t* indicators[3]; - bool isOn = false; + int State_l = 1; }; } } From 3d75a7dc9f29bc01942fb74cae8dc02b456de539 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Thu, 16 Feb 2023 11:21:21 +0200 Subject: [PATCH 33/61] added motor pattern --- src/components/motor/MotorController.cpp | 53 ++++++++++++++++++++++++ src/components/motor/MotorController.h | 3 ++ 2 files changed, 56 insertions(+) diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index 4e392416..96963381 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -5,14 +5,58 @@ using namespace Pinetime::Controllers; +namespace { + TimerHandle_t vibTimer; + + void PatternStep(TimerHandle_t xTimer) { + /* Vibration pattern format: + * { + * durationOfVibration, + * durationOfPause, + * durationOfVibration, + * durationOfPause, + * ..., + * durationOfVibration, + * zeroTerminator + * } + * + * Patterns can be any length + * The pattern must end with a duration of vibration and a terminator. + */ + + static constexpr uint8_t vibrationPattern[] = {30, 150, 30, 150, 30, 0}; + + static size_t patternPosition = 0; + if (vibrationPattern[patternPosition] != 0 && xTimerChangePeriod(vibTimer, vibrationPattern[patternPosition] << 1, 0) == pdPASS && + xTimerStart(vibTimer, 0) == pdPASS) { + if (patternPosition % 2 == 0) { + nrf_gpio_pin_clear(Pinetime::PinMap::Motor); + } else { + nrf_gpio_pin_set(Pinetime::PinMap::Motor); + } + patternPosition++; + } else { + patternPosition = 0; + nrf_gpio_pin_set(Pinetime::PinMap::Motor); + auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); + motorController->PatternFinished(); + } + } +} + void MotorController::Init() { nrf_gpio_cfg_output(PinMap::Motor); nrf_gpio_pin_set(PinMap::Motor); + vibTimer = xTimerCreate("vibration", 1, pdFALSE, this, PatternStep); shortVib = xTimerCreate("shortVib", 1, pdFALSE, nullptr, StopMotor); longVib = xTimerCreate("longVib", pdMS_TO_TICKS(1000), pdTRUE, this, Ring); } +void MotorController::PatternFinished() { + patternPlaying = false; +} + void MotorController::Ring(TimerHandle_t xTimer) { auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); motorController->RunForDuration(50); @@ -24,6 +68,15 @@ void MotorController::RunForDuration(uint8_t motorDuration) { } } +bool MotorController::StartPattern() { + if (!patternPlaying) { + patternPlaying = true; + PatternStep(vibTimer); + return true; + } + return false; +} + void MotorController::StartRinging() { RunForDuration(50); xTimerStart(longVib, 0); diff --git a/src/components/motor/MotorController.h b/src/components/motor/MotorController.h index 6dea6d1f..2f6ca59b 100644 --- a/src/components/motor/MotorController.h +++ b/src/components/motor/MotorController.h @@ -15,10 +15,13 @@ namespace Pinetime { void RunForDuration(uint8_t motorDuration); void StartRinging(); void StopRinging(); + void PatternFinished(); + bool StartPattern(); private: static void Ring(TimerHandle_t xTimer); static void StopMotor(TimerHandle_t xTimer); + bool patternPlaying; TimerHandle_t shortVib; TimerHandle_t longVib; }; From bf8c4dfef8a0445f25966ca2f2b7aea9f3df6cbf Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sat, 14 Oct 2023 22:50:41 -0400 Subject: [PATCH 34/61] change motor patern on half hour --- src/components/motor/MotorController.cpp | 2 +- src/displayapp/DisplayApp.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index 96963381..2bbd2a03 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -24,7 +24,7 @@ namespace { * The pattern must end with a duration of vibration and a terminator. */ - static constexpr uint8_t vibrationPattern[] = {30, 150, 30, 150, 30, 0}; + static constexpr uint8_t vibrationPattern[] = {10, 100, 50, 200, 10, 0}; static size_t patternPosition = 0; if (vibrationPattern[patternPosition] != 0 && xTimerChangePeriod(vibTimer, vibrationPattern[patternPosition] << 1, 0) == pdPASS && diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 0d3cc441..46375698 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -392,7 +392,7 @@ void DisplayApp::Refresh() { time_var = dateTimeController.Minutes(); if (time_var == 30){ NRF_LOG_INFO("Short: %d", time_var); - motorController.RunForDuration(25); + motorController.StartPattern(); } else { From 270d15a8ea3fc52fcc4d83f8f9498941784684a9 Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sat, 14 Oct 2023 22:55:41 -0400 Subject: [PATCH 35/61] switched red flash light off night default --- src/displayapp/DisplayApp.cpp | 2 +- src/displayapp/screens/FlashLight.cpp | 31 +++------------------------ src/displayapp/screens/FlashLight.h | 7 +++--- 3 files changed, 7 insertions(+), 33 deletions(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 46375698..1ae59f05 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -556,7 +556,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio touchPanel); break; case Apps::FlashLight: - currentScreen = std::make_unique(*systemTask, brightnessController, dateTimeController); + currentScreen = std::make_unique(*systemTask, brightnessController); break; case Apps::StopWatch: currentScreen = std::make_unique(*systemTask); diff --git a/src/displayapp/screens/FlashLight.cpp b/src/displayapp/screens/FlashLight.cpp index 62c36805..f560fef7 100644 --- a/src/displayapp/screens/FlashLight.cpp +++ b/src/displayapp/screens/FlashLight.cpp @@ -15,24 +15,11 @@ namespace { } } -FlashLight::FlashLight(System::SystemTask& systemTask, Controllers::BrightnessController& brightnessController, Controllers::DateTime& dateTimeController) - : systemTask {systemTask}, brightnessController {brightnessController}, dateTimeController {dateTimeController} { +FlashLight::FlashLight(System::SystemTask& systemTask, Controllers::BrightnessController& brightnessController) + : systemTask {systemTask}, brightnessController {brightnessController} { brightnessController.Set(Controllers::BrightnessController::Levels::Low); - - - - int time_var = dateTimeController.Hours(); - if(time_var > 21 || time_var < 6){ - State_l = 1; - NRF_LOG_INFO("Loop Hour Red: %d", time_var); - } - else { - State_l = 0; - NRF_LOG_INFO("Loop Hour White: %d", time_var); - } - flashLight = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(flashLight, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48); lv_label_set_text_static(flashLight, Symbols::flashlight); @@ -152,16 +139,4 @@ bool FlashLight::OnTouchEvent(Pinetime::Applications::TouchEvents event) { } return false; -} -/* - time_var = dateTimeController.Minutes(); - if (time_var == 30){ - NRF_LOG_INFO("Short: %d", time_var); - motorController.RunForDuration(25); - } - else - { - NRF_LOG_INFO("Long: %d", time_var); - motorController.RunForDuration(200); - } -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/src/displayapp/screens/FlashLight.h b/src/displayapp/screens/FlashLight.h index 1481838e..4f5d4ac3 100644 --- a/src/displayapp/screens/FlashLight.h +++ b/src/displayapp/screens/FlashLight.h @@ -2,7 +2,6 @@ #include "displayapp/screens/Screen.h" #include "components/brightness/BrightnessController.h" -#include "components/datetime/DateTimeController.h" #include "systemtask/SystemTask.h" #include #include @@ -14,7 +13,7 @@ namespace Pinetime { class FlashLight : public Screen { public: - FlashLight(System::SystemTask& systemTask, Controllers::BrightnessController& brightness, Controllers::DateTime& dateTimeController); + FlashLight(System::SystemTask& systemTask, Controllers::BrightnessController& brightness); ~FlashLight() override; bool OnTouchEvent(Pinetime::Applications::TouchEvents event) override; @@ -26,14 +25,14 @@ namespace Pinetime { Pinetime::System::SystemTask& systemTask; Controllers::BrightnessController& brightnessController; - Controllers::DateTime& dateTimeController; + Controllers::BrightnessController::Levels brightnessLevel = Controllers::BrightnessController::Levels::High; lv_obj_t* flashLight; lv_obj_t* backgroundAction; lv_obj_t* indicators[3]; - int State_l = 1; + int State_l = 0; }; } } From 16998a8ca8c05215907f90dc29fd070b0bb78ae3 Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sun, 15 Oct 2023 03:01:24 +0000 Subject: [PATCH 36/61] Update README.md --- README.md | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 4dff72be..bde614d3 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ - [x] Calculator - [x] Redo music control gestures - [x] Swipe up toggles control mode and swipe down exits - - [x] Swipe left/right goes to watchface/another app +- [x] Swipe left/right goes to watchface/another app - [x] Rearrange quick acces and apps - +- [x] Exponent button on calculator ## Pending merge @@ -22,21 +22,13 @@ - [ ] Remap button double click (to music app) ### Moses -<<<<<<< HEAD - -======= -- [x] Redo music control gestures - - [x] Swipe up toggles control mode and swipe down exits - - [x] Swipe left/right goes to watchface/another app -- [x] Exponent button on calculator -- [x] Rearrange quick acces and apps + + - [ ] Add quick ring settings ->>>>>>> refs/remotes/origin/main ## Medium priority - [ ] Temp sensor w/ arduino - [ ] Homeassistant control -- [ ] Periodic heart rate measurement ## Lower priority - [ ] Maybe some prank watchfaces From 886e425461346ae211106ba89c9c8f2b298c34f6 Mon Sep 17 00:00:00 2001 From: Josh Date: Sun, 15 Oct 2023 23:18:20 -0400 Subject: [PATCH 37/61] Start swapping steps with heart rate variables --- .../screens/WatchFaceCasioStyleG7710.cpp | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp b/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp index 72bfaaa3..bbce8304 100644 --- a/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp +++ b/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp @@ -148,25 +148,27 @@ WatchFaceCasioStyleG7710::WatchFaceCasioStyleG7710(Controllers::DateTime& dateTi lv_obj_set_pos(backgroundLabel, 0, 0); lv_label_set_text_static(backgroundLabel, ""); - heartbeatIcon = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_static(heartbeatIcon, Symbols::heartBeat); - lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); - lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2); +//Working here + + stepIcon = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(stepIcon, Symbols::shoe); + lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); + lv_obj_align(stepIcon, 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, color_text); lv_label_set_text_static(heartbeatValue, ""); - lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0); + lv_obj_align(heartbeatValue, stepIcon, 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, color_text); - lv_label_set_text_static(stepValue, "0"); - lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2); + oldStepValue = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(oldStepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); + lv_label_set_text_static(oldStepValue, "0"); + lv_obj_align(oldStepValue, 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, color_text); - lv_label_set_text_static(stepIcon, Symbols::shoe); - lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0); + oldStepIcon = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(oldStepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); + lv_label_set_text_static(oldStepIcon, Symbols::shoe); + lv_obj_align(oldStepIcon, oldStepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0); taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); Refresh(); @@ -293,22 +295,22 @@ void WatchFaceCasioStyleG7710::Refresh() { heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped; if (heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) { if (heartbeatRunning.Get()) { - lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); + lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); lv_label_set_text_fmt(heartbeatValue, "%d", heartbeat.Get()); } else { - lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x1B1B1B)); + lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x1B1B1B)); lv_label_set_text_static(heartbeatValue, ""); } - lv_obj_realign(heartbeatIcon); + lv_obj_realign(stepIcon); lv_obj_realign(heartbeatValue); } stepCount = motionController.NbSteps(); if (stepCount.IsUpdated()) { - lv_label_set_text_fmt(stepValue, "%lu", stepCount.Get()); - lv_obj_realign(stepValue); - lv_obj_realign(stepIcon); + lv_label_set_text_fmt(oldStepValue, "%lu", stepCount.Get()); + lv_obj_realign(oldStepValue); + lv_obj_realign(oldStepIcon); } } From bbfef9ee5c8e607f2bac52779d3e7d8a305f33b0 Mon Sep 17 00:00:00 2001 From: Josh Date: Thu, 19 Oct 2023 22:39:49 -0400 Subject: [PATCH 38/61] continue swapping variables --- src/displayapp/screens/WatchFaceCasioStyleG7710.cpp | 8 ++++---- src/displayapp/screens/WatchFaceCasioStyleG7710.h | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp b/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp index bbce8304..f240faae 100644 --- a/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp +++ b/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp @@ -155,10 +155,10 @@ WatchFaceCasioStyleG7710::WatchFaceCasioStyleG7710(Controllers::DateTime& dateTi lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); lv_obj_align(stepIcon, 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, color_text); - lv_label_set_text_static(heartbeatValue, ""); - lv_obj_align(heartbeatValue, stepIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0); + oldStepValue = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(oldStepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); + lv_label_set_text_static(oldStepValue, ""); + lv_obj_align(oldStepValue, stepIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0); oldStepValue = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(oldStepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); diff --git a/src/displayapp/screens/WatchFaceCasioStyleG7710.h b/src/displayapp/screens/WatchFaceCasioStyleG7710.h index f84db7b5..0b90d93d 100644 --- a/src/displayapp/screens/WatchFaceCasioStyleG7710.h +++ b/src/displayapp/screens/WatchFaceCasioStyleG7710.h @@ -79,8 +79,10 @@ namespace Pinetime { lv_obj_t* label_battery_value; lv_obj_t* heartbeatIcon; lv_obj_t* heartbeatValue; - lv_obj_t* stepIcon; + lv_obj_t* stepIcon; //TODO: remove unused variables + lv_obj_t* oldStepIcon; lv_obj_t* stepValue; + lv_obj_t* oldStepValue; lv_obj_t* notificationIcon; lv_obj_t* line_icons; From 8ada9410a1cf2410fbfbc1f5073b9aaea877230d Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 21 Oct 2023 14:17:25 -0400 Subject: [PATCH 39/61] continue swapping variables --- src/displayapp/screens/WatchFaceCasioStyleG7710.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp b/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp index f240faae..cc41b1d5 100644 --- a/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp +++ b/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp @@ -155,10 +155,10 @@ WatchFaceCasioStyleG7710::WatchFaceCasioStyleG7710(Controllers::DateTime& dateTi lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); lv_obj_align(stepIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2); - oldStepValue = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(oldStepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); - lv_label_set_text_static(oldStepValue, ""); - lv_obj_align(oldStepValue, stepIcon, 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, color_text); + lv_label_set_text_static(stepValue, ""); + lv_obj_align(stepValue, stepIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0); oldStepValue = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(oldStepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); From 191f99904c862c3f32b0ce156a5ff56c579367e4 Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 21 Oct 2023 19:15:42 -0400 Subject: [PATCH 40/61] Heartrate removed, steps moved, and seconds label added --- src/displayapp/screens/Clock.cpp | 1 - .../screens/WatchFaceCasioStyleG7710.cpp | 37 ++++--------------- .../screens/WatchFaceCasioStyleG7710.h | 12 +----- 3 files changed, 9 insertions(+), 41 deletions(-) diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp index 4219b090..eeb7f0e1 100644 --- a/src/displayapp/screens/Clock.cpp +++ b/src/displayapp/screens/Clock.cpp @@ -127,7 +127,6 @@ std::unique_ptr Clock::WatchFaceCasioStyleG7710() { bleController, notificationManager, settingsController, - heartRateController, motionController, filesystem); } diff --git a/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp b/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp index cc41b1d5..05689e2e 100644 --- a/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp +++ b/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp @@ -9,7 +9,6 @@ #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "components/ble/NotificationManager.h" -#include "components/heartrate/HeartRateController.h" #include "components/motion/MotionController.h" #include "components/settings/Settings.h" using namespace Pinetime::Applications::Screens; @@ -19,7 +18,6 @@ WatchFaceCasioStyleG7710::WatchFaceCasioStyleG7710(Controllers::DateTime& dateTi const Controllers::Ble& bleController, Controllers::NotificationManager& notificatioManager, Controllers::Settings& settingsController, - Controllers::HeartRateController& heartRateController, Controllers::MotionController& motionController, Controllers::FS& filesystem) : currentDateTime {{}}, @@ -29,7 +27,6 @@ WatchFaceCasioStyleG7710::WatchFaceCasioStyleG7710(Controllers::DateTime& dateTi bleController {bleController}, notificatioManager {notificatioManager}, settingsController {settingsController}, - heartRateController {heartRateController}, motionController {motionController} { lfs_file f = {}; @@ -160,15 +157,10 @@ WatchFaceCasioStyleG7710::WatchFaceCasioStyleG7710(Controllers::DateTime& dateTi lv_label_set_text_static(stepValue, ""); lv_obj_align(stepValue, stepIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0); - oldStepValue = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(oldStepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); - lv_label_set_text_static(oldStepValue, "0"); - lv_obj_align(oldStepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2); - - oldStepIcon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(oldStepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); - lv_label_set_text_static(oldStepIcon, Symbols::shoe); - lv_obj_align(oldStepIcon, oldStepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0); + label_seconds = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(label_seconds, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); + lv_label_set_text_static(label_seconds, "0"); + lv_obj_align(label_seconds, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2); taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); Refresh(); @@ -291,26 +283,11 @@ void WatchFaceCasioStyleG7710::Refresh() { } } - heartbeat = heartRateController.HeartRate(); - heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped; - if (heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) { - if (heartbeatRunning.Get()) { - lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); - lv_label_set_text_fmt(heartbeatValue, "%d", heartbeat.Get()); - } else { - lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x1B1B1B)); - lv_label_set_text_static(heartbeatValue, ""); - } - - lv_obj_realign(stepIcon); - lv_obj_realign(heartbeatValue); - } - stepCount = motionController.NbSteps(); if (stepCount.IsUpdated()) { - lv_label_set_text_fmt(oldStepValue, "%lu", stepCount.Get()); - lv_obj_realign(oldStepValue); - lv_obj_realign(oldStepIcon); + lv_label_set_text_fmt(stepValue, "%lu", stepCount.Get()); + lv_obj_realign(stepValue); + lv_obj_realign(stepValue); } } diff --git a/src/displayapp/screens/WatchFaceCasioStyleG7710.h b/src/displayapp/screens/WatchFaceCasioStyleG7710.h index 0b90d93d..ccf3c2b8 100644 --- a/src/displayapp/screens/WatchFaceCasioStyleG7710.h +++ b/src/displayapp/screens/WatchFaceCasioStyleG7710.h @@ -16,7 +16,6 @@ namespace Pinetime { class Battery; class Ble; class NotificationManager; - class HeartRateController; class MotionController; } @@ -30,7 +29,6 @@ namespace Pinetime { const Controllers::Ble& bleController, Controllers::NotificationManager& notificatioManager, Controllers::Settings& settingsController, - Controllers::HeartRateController& heartRateController, Controllers::MotionController& motionController, Controllers::FS& filesystem); ~WatchFaceCasioStyleG7710() override; @@ -46,8 +44,6 @@ namespace Pinetime { Utility::DirtyValue bleRadioEnabled {}; Utility::DirtyValue> currentDateTime {}; Utility::DirtyValue stepCount {}; - Utility::DirtyValue heartbeat {}; - Utility::DirtyValue heartbeatRunning {}; Utility::DirtyValue notificationState {}; using days = std::chrono::duration>; // TODO: days is standard in c++20 Utility::DirtyValue> currentDate; @@ -64,6 +60,7 @@ namespace Pinetime { lv_style_t style_border; lv_obj_t* label_time; + lv_obj_t* label_seconds; lv_obj_t* line_time; lv_obj_t* label_time_ampm; lv_obj_t* label_date; @@ -77,12 +74,8 @@ namespace Pinetime { lv_obj_t* bleIcon; lv_obj_t* batteryPlug; lv_obj_t* label_battery_value; - lv_obj_t* heartbeatIcon; - lv_obj_t* heartbeatValue; - lv_obj_t* stepIcon; //TODO: remove unused variables - lv_obj_t* oldStepIcon; + lv_obj_t* stepIcon; lv_obj_t* stepValue; - lv_obj_t* oldStepValue; lv_obj_t* notificationIcon; lv_obj_t* line_icons; @@ -93,7 +86,6 @@ namespace Pinetime { const Controllers::Ble& bleController; Controllers::NotificationManager& notificatioManager; Controllers::Settings& settingsController; - Controllers::HeartRateController& heartRateController; Controllers::MotionController& motionController; lv_task_t* taskRefresh; From 6a772e7e8e660c08ed025e805d7b5ab55e23d47f Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 21 Oct 2023 20:16:20 -0400 Subject: [PATCH 41/61] Finish adding seconds --- src/displayapp/screens/WatchFaceCasioStyleG7710.cpp | 10 ++++++---- src/displayapp/screens/WatchFaceCasioStyleG7710.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp b/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp index 05689e2e..565d0986 100644 --- a/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp +++ b/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp @@ -145,8 +145,6 @@ WatchFaceCasioStyleG7710::WatchFaceCasioStyleG7710(Controllers::DateTime& dateTi lv_obj_set_pos(backgroundLabel, 0, 0); lv_label_set_text_static(backgroundLabel, ""); -//Working here - stepIcon = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(stepIcon, Symbols::shoe); lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); @@ -160,7 +158,7 @@ WatchFaceCasioStyleG7710::WatchFaceCasioStyleG7710(Controllers::DateTime& dateTi label_seconds = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(label_seconds, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text); lv_label_set_text_static(label_seconds, "0"); - lv_obj_align(label_seconds, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2); + lv_obj_align(label_seconds, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -9, -2); taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); Refresh(); @@ -216,10 +214,11 @@ void WatchFaceCasioStyleG7710::Refresh() { lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(notificationState.Get())); } - currentDateTime = std::chrono::time_point_cast(dateTimeController.CurrentDateTime()); + currentDateTime = std::chrono::time_point_cast(dateTimeController.CurrentDateTime()); if (currentDateTime.IsUpdated()) { uint8_t hour = dateTimeController.Hours(); uint8_t minute = dateTimeController.Minutes(); + uint8_t second = dateTimeController.Seconds(); if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { char ampmChar[2] = "A"; @@ -238,6 +237,9 @@ void WatchFaceCasioStyleG7710::Refresh() { } lv_obj_realign(label_time); + lv_label_set_text_fmt(label_seconds, "%02d", second); + lv_obj_realign(label_seconds); + currentDate = std::chrono::time_point_cast(currentDateTime.Get()); if (currentDate.IsUpdated()) { const char* weekNumberFormat = "%V"; diff --git a/src/displayapp/screens/WatchFaceCasioStyleG7710.h b/src/displayapp/screens/WatchFaceCasioStyleG7710.h index ccf3c2b8..166ba468 100644 --- a/src/displayapp/screens/WatchFaceCasioStyleG7710.h +++ b/src/displayapp/screens/WatchFaceCasioStyleG7710.h @@ -42,7 +42,7 @@ namespace Pinetime { Utility::DirtyValue powerPresent {}; Utility::DirtyValue bleState {}; Utility::DirtyValue bleRadioEnabled {}; - Utility::DirtyValue> currentDateTime {}; + Utility::DirtyValue> currentDateTime {}; Utility::DirtyValue stepCount {}; Utility::DirtyValue notificationState {}; using days = std::chrono::duration>; // TODO: days is standard in c++20 From 13af2bb96cb55bdcf2fb2c9c5da0f3c7e9f45b0f Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sat, 21 Oct 2023 21:24:58 -0400 Subject: [PATCH 42/61] Fixed battary order in digital watch face --- src/displayapp/screens/WatchFaceDigital.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index df481806..1720f372 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -22,8 +22,8 @@ WatchFaceDigital::WatchFaceDigital(Controllers::DateTime& dateTimeController, Controllers::MotionController& motionController) : currentDateTime {{}}, dateTimeController {dateTimeController}, - notificationManager {notificationManager}, batteryController {batteryController}, + notificationManager {notificationManager}, settingsController {settingsController}, heartRateController {heartRateController}, motionController {motionController}, From 1487a16f4ae4787ceb074cc4e903213e00602abe Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sat, 21 Oct 2023 21:55:18 -0400 Subject: [PATCH 43/61] compiles on watch --- src/displayapp/screens/settings/SettingQuickR.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/settings/SettingQuickR.cpp b/src/displayapp/screens/settings/SettingQuickR.cpp index 2035aefd..63bf13f9 100644 --- a/src/displayapp/screens/settings/SettingQuickR.cpp +++ b/src/displayapp/screens/settings/SettingQuickR.cpp @@ -6,7 +6,7 @@ using namespace Pinetime::Applications::Screens; - +constexpr std::array SettingQuickR::options; namespace { void event_handler(lv_obj_t* obj, lv_event_t event) { From 858bf4f96eea5dbf596024843ac3ee30d51248a2 Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Sat, 21 Oct 2023 22:01:12 -0400 Subject: [PATCH 44/61] fix arrangement of alarm and timer --- src/components/settings/Settings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index 8b42b298..a18a1ed8 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -13,7 +13,7 @@ namespace Pinetime { enum class Notification : uint8_t { On, Off, Sleep }; enum class ChimesOption : uint8_t { None, Hours, HalfHours }; enum class WakeUpMode : uint8_t { SingleTap = 0, DoubleTap = 1, RaiseWrist = 2, Shake = 3, LowerWrist = 4 }; - enum class QuickApp : uint8_t { MusicPlayer = 0, Calculator = 1, Timer = 2, Alarm = 3, HeartRate = 4 }; //, Alarm = 5, Timer = 6, Stopwatch = 7 }; + enum class QuickApp : uint8_t { MusicPlayer = 0, Calculator = 1, Alarm = 2, Timer = 3, HeartRate = 4 }; //, Alarm = 5, Timer = 6, Stopwatch = 7 }; enum class Colors : uint8_t { White, Silver, From 94044d2fdca09a3d663f1ba98276f778e6037a70 Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 21 Oct 2023 23:14:41 -0400 Subject: [PATCH 45/61] Removed battery percent from digital watch face --- src/displayapp/screens/WatchFaceDigital.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index 1720f372..d37391e2 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -22,7 +22,6 @@ WatchFaceDigital::WatchFaceDigital(Controllers::DateTime& dateTimeController, Controllers::MotionController& motionController) : currentDateTime {{}}, dateTimeController {dateTimeController}, - batteryController {batteryController}, notificationManager {notificationManager}, settingsController {settingsController}, heartRateController {heartRateController}, @@ -36,11 +35,6 @@ WatchFaceDigital::WatchFaceDigital(Controllers::DateTime& dateTimeController, lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(false)); lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); - - batteryValue = lv_label_create(lv_scr_act(), nullptr); - //lv_label_set_recolor(batteryValue, true); - lv_obj_align(batteryValue, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -3, -110); - label_seconds = lv_label_create(lv_scr_act(), nullptr); // for secs lv_obj_align(label_seconds, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, -55); lv_obj_set_style_local_text_color(label_seconds, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x999999)); @@ -89,11 +83,6 @@ WatchFaceDigital::~WatchFaceDigital() { void WatchFaceDigital::Refresh() { statusIcons.Update(); - - batteryPercentRemaining = batteryController.PercentRemaining(); - if (batteryPercentRemaining.IsUpdated()) { - lv_label_set_text_fmt(batteryValue, "%d%%", batteryPercentRemaining.Get()); - } notificationState = notificationManager.AreNewNotificationsAvailable(); if (notificationState.IsUpdated()) { From 2ffc63b1d81f50cd8387267281a7ef5795453d83 Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 21 Oct 2023 23:44:29 -0400 Subject: [PATCH 46/61] cleanup code and fix 12h time not working on digital face --- src/displayapp/screens/WatchFaceDigital.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h index 4b66ae0b..0c3c5ac5 100644 --- a/src/displayapp/screens/WatchFaceDigital.h +++ b/src/displayapp/screens/WatchFaceDigital.h @@ -64,7 +64,6 @@ namespace Pinetime { lv_obj_t* notificationIcon; Controllers::DateTime& dateTimeController; - const Controllers::Battery& batteryController; Controllers::NotificationManager& notificationManager; Controllers::Settings& settingsController; Controllers::HeartRateController& heartRateController; From e4b4fba5a18d525c16a2ecdc399b201a1c3cacff Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 21 Oct 2023 23:45:41 -0400 Subject: [PATCH 47/61] cleanup code and fix 12hour time on digital face --- src/displayapp/screens/WatchFaceDigital.cpp | 9 --------- src/displayapp/screens/WatchFaceDigital.h | 1 - 2 files changed, 10 deletions(-) diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index d37391e2..37b6f53a 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -48,10 +48,6 @@ WatchFaceDigital::WatchFaceDigital(Controllers::DateTime& dateTimeController, 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);*/ - heartbeatIcon = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(heartbeatIcon, Symbols::heartBeat); lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B)); @@ -97,16 +93,11 @@ void WatchFaceDigital::Refresh() { uint8_t second = dateTimeController.Seconds(); if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { - /*char ampmChar[3] = "AM"; if (hour == 0) { hour = 12; - } else if (hour == 12) { - ampmChar[0] = 'P'; } else if (hour > 12) { hour = hour - 12; - ampmChar[0] = 'P'; } - lv_label_set_text(label_time_ampm, ampmChar);*/ lv_label_set_text_fmt(label_time, "%2d:%02d", hour, minute); lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0); } else { diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h index 0c3c5ac5..94870f85 100644 --- a/src/displayapp/screens/WatchFaceDigital.h +++ b/src/displayapp/screens/WatchFaceDigital.h @@ -54,7 +54,6 @@ namespace Pinetime { lv_obj_t* label_time; lv_obj_t* label_seconds; //for secs - //lv_obj_t* label_time_ampm; lv_obj_t* batteryValue; lv_obj_t* label_date; lv_obj_t* heartbeatIcon; From ab03504d0c6f3b28a7c89e84a0493a094932bb4c Mon Sep 17 00:00:00 2001 From: Josh Date: Sun, 22 Oct 2023 21:38:52 -0400 Subject: [PATCH 48/61] Fix bug causing quickring to be missing in settings and some settings not remembered correctly --- src/components/settings/Settings.h | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index a18a1ed8..3fa667cc 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -246,26 +246,6 @@ namespace Pinetime { - // New Settings - void SetQuickRModes(QuickApp App_now, bool enabled) { - if (enabled != isQuickROn(App_now)) { - settingsChanged = true; - } - settings.quickApp.set(static_cast(App_now), enabled); - }; - - std::bitset<5> getQuickRModes() const { - return settings.quickApp; - } - - bool isQuickROn(const QuickApp app_holder) const { - return getQuickRModes()[static_cast(app_holder)]; - } - - - - - @@ -300,6 +280,26 @@ namespace Pinetime { return bleRadioEnabled; }; + + + // New Settings + void SetQuickRModes(QuickApp App_now, bool enabled) { + if (enabled != isQuickROn(App_now)) { + settingsChanged = true; + } + settings.quickApp.set(static_cast(App_now), enabled); + }; + + std::bitset<5> getQuickRModes() const { + return settings.quickApp; + } + + bool isQuickROn(const QuickApp app_holder) const { + return getQuickRModes()[static_cast(app_holder)]; + } + + + private: Pinetime::Controllers::FS& fs; From ce136ea148397f42581c95e835e07d4ada717df4 Mon Sep 17 00:00:00 2001 From: Josh Date: Sun, 22 Oct 2023 22:37:53 -0400 Subject: [PATCH 49/61] Added duplicate of analog face --- src/CMakeLists.txt | 1 + src/displayapp/WatchFaces.h | 1 + src/displayapp/screens/Clock.cpp | 13 + src/displayapp/screens/Clock.h | 1 + src/displayapp/screens/WatchFaceFace.cpp | 264 ++++++++++++++++++ src/displayapp/screens/WatchFaceFace.h | 92 ++++++ .../screens/settings/SettingWatchFace.h | 6 +- 7 files changed, 376 insertions(+), 2 deletions(-) create mode 100644 src/displayapp/screens/WatchFaceFace.cpp create mode 100644 src/displayapp/screens/WatchFaceFace.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 68f94328..9c8dd1ee 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -435,6 +435,7 @@ list(APPEND SOURCE_FILES displayapp/screens/WatchFaceTerminal.cpp displayapp/screens/WatchFacePineTimeStyle.cpp displayapp/screens/WatchFaceCasioStyleG7710.cpp + displayapp/screens/WatchFaceFace.cpp ## diff --git a/src/displayapp/WatchFaces.h b/src/displayapp/WatchFaces.h index 2982347a..8f065285 100644 --- a/src/displayapp/WatchFaces.h +++ b/src/displayapp/WatchFaces.h @@ -9,6 +9,7 @@ namespace Pinetime { Terminal = 3, Infineat = 4, CasioStyleG7710 = 5, + Face = 6, }; } } diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp index eeb7f0e1..747bcab3 100644 --- a/src/displayapp/screens/Clock.cpp +++ b/src/displayapp/screens/Clock.cpp @@ -13,6 +13,7 @@ #include "displayapp/screens/WatchFaceAnalog.h" #include "displayapp/screens/WatchFacePineTimeStyle.h" #include "displayapp/screens/WatchFaceCasioStyleG7710.h" +#include "displayapp/screens/WatchFaceFace.h" using namespace Pinetime::Applications::Screens; using namespace Pinetime::Applications; @@ -55,6 +56,9 @@ Clock::Clock(Controllers::DateTime& dateTimeController, case WatchFace::CasioStyleG7710: return WatchFaceCasioStyleG7710(); break; + case WatchFace::Face: + return WatchFaceFaceScreen(); + break; } return WatchFaceDigitalScreen(); }()} { @@ -130,3 +134,12 @@ std::unique_ptr Clock::WatchFaceCasioStyleG7710() { motionController, filesystem); } + + +std::unique_ptr Clock::WatchFaceFaceScreen() { + return std::make_unique(dateTimeController, + batteryController, + bleController, + notificationManager, + settingsController); +} diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h index f3591f43..9e484867 100644 --- a/src/displayapp/screens/Clock.h +++ b/src/displayapp/screens/Clock.h @@ -54,6 +54,7 @@ namespace Pinetime { std::unique_ptr WatchFaceTerminalScreen(); std::unique_ptr WatchFaceInfineatScreen(); std::unique_ptr WatchFaceCasioStyleG7710(); + std::unique_ptr WatchFaceFaceScreen(); }; } } diff --git a/src/displayapp/screens/WatchFaceFace.cpp b/src/displayapp/screens/WatchFaceFace.cpp new file mode 100644 index 00000000..1109643c --- /dev/null +++ b/src/displayapp/screens/WatchFaceFace.cpp @@ -0,0 +1,264 @@ +#include "displayapp/screens/WatchFaceAnalog.h" +#include +#include +#include "displayapp/screens/BatteryIcon.h" +#include "displayapp/screens/BleIcon.h" +#include "displayapp/screens/Symbols.h" +#include "displayapp/screens/NotificationIcon.h" +#include "components/settings/Settings.h" +#include "displayapp/InfiniTimeTheme.h" + +using namespace Pinetime::Applications::Screens; + +namespace { + constexpr int16_t HourLength = 70; + constexpr int16_t MinuteLength = 90; + constexpr int16_t SecondLength = 110; + + // sin(90) = 1 so the value of _lv_trigo_sin(90) is the scaling factor + const auto LV_TRIG_SCALE = _lv_trigo_sin(90); + + int16_t Cosine(int16_t angle) { + return _lv_trigo_sin(angle + 90); + } + + int16_t Sine(int16_t angle) { + return _lv_trigo_sin(angle); + } + + int16_t CoordinateXRelocate(int16_t x) { + return (x + LV_HOR_RES / 2); + } + + int16_t CoordinateYRelocate(int16_t y) { + return std::abs(y - LV_HOR_RES / 2); + } + + lv_point_t CoordinateRelocate(int16_t radius, int16_t angle) { + return lv_point_t {.x = CoordinateXRelocate(radius * static_cast(Sine(angle)) / LV_TRIG_SCALE), + .y = CoordinateYRelocate(radius * static_cast(Cosine(angle)) / LV_TRIG_SCALE)}; + } + +} + +WatchFaceAnalog::WatchFaceFace(Controllers::DateTime& dateTimeController, + const Controllers::Battery& batteryController, + const Controllers::Ble& bleController, + Controllers::NotificationManager& notificationManager, + Controllers::Settings& settingsController) + : currentDateTime {{}}, + batteryIcon(true), + dateTimeController {dateTimeController}, + batteryController {batteryController}, + bleController {bleController}, + notificationManager {notificationManager}, + settingsController {settingsController} { + + sHour = 99; + sMinute = 99; + sSecond = 99; + + minor_scales = lv_linemeter_create(lv_scr_act(), nullptr); + lv_linemeter_set_scale(minor_scales, 300, 51); + lv_linemeter_set_angle_offset(minor_scales, 180); + lv_obj_set_size(minor_scales, 240, 240); + lv_obj_align(minor_scales, nullptr, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_opa(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); + lv_obj_set_style_local_scale_width(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4); + lv_obj_set_style_local_scale_end_line_width(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 1); + lv_obj_set_style_local_scale_end_color(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); + + major_scales = lv_linemeter_create(lv_scr_act(), nullptr); + lv_linemeter_set_scale(major_scales, 300, 11); + lv_linemeter_set_angle_offset(major_scales, 180); + lv_obj_set_size(major_scales, 240, 240); + lv_obj_align(major_scales, nullptr, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_opa(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); + lv_obj_set_style_local_scale_width(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 6); + lv_obj_set_style_local_scale_end_line_width(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4); + lv_obj_set_style_local_scale_end_color(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); + + large_scales = lv_linemeter_create(lv_scr_act(), nullptr); + lv_linemeter_set_scale(large_scales, 180, 3); + lv_linemeter_set_angle_offset(large_scales, 180); + lv_obj_set_size(large_scales, 240, 240); + lv_obj_align(large_scales, nullptr, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_opa(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); + lv_obj_set_style_local_scale_width(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 20); + lv_obj_set_style_local_scale_end_line_width(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4); + lv_obj_set_style_local_scale_end_color(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA); + + twelve = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_align(twelve, LV_LABEL_ALIGN_CENTER); + lv_label_set_text_static(twelve, "12"); + lv_obj_set_pos(twelve, 110, 10); + lv_obj_set_style_local_text_color(twelve, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA); + + batteryIcon.Create(lv_scr_act()); + lv_obj_align(batteryIcon.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); + + plugIcon = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(plugIcon, Symbols::plug); + lv_obj_align(plugIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); + + bleIcon = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(bleIcon, ""); + lv_obj_align(bleIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, -30, 0); + + notificationIcon = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_LIME); + lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(false)); + lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); + + // Date - Day / Week day + + label_date_day = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(label_date_day, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange); + 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, nullptr, LV_ALIGN_CENTER, 50, 0); + + minute_body = lv_line_create(lv_scr_act(), nullptr); + minute_body_trace = lv_line_create(lv_scr_act(), nullptr); + hour_body = lv_line_create(lv_scr_act(), nullptr); + hour_body_trace = lv_line_create(lv_scr_act(), nullptr); + second_body = lv_line_create(lv_scr_act(), nullptr); + + 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); + + taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); + + Refresh(); +} + +WatchFaceFace::~WatchFaceFace() { + lv_task_del(taskRefresh); + + 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() { + uint8_t hour = dateTimeController.Hours(); + uint8_t minute = dateTimeController.Minutes(); + uint8_t second = dateTimeController.Seconds(); + + if (sMinute != minute) { + auto const angle = minute * 6; + minute_point[0] = CoordinateRelocate(30, angle); + minute_point[1] = CoordinateRelocate(MinuteLength, angle); + + minute_point_trace[0] = CoordinateRelocate(5, angle); + minute_point_trace[1] = CoordinateRelocate(31, angle); + + 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; + auto const angle = (hour * 30 + minute / 2); + + hour_point[0] = CoordinateRelocate(30, angle); + hour_point[1] = CoordinateRelocate(HourLength, angle); + + hour_point_trace[0] = CoordinateRelocate(5, angle); + hour_point_trace[1] = CoordinateRelocate(31, angle); + + 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; + auto const angle = second * 6; + + second_point[0] = CoordinateRelocate(-20, angle); + second_point[1] = CoordinateRelocate(SecondLength, angle); + lv_line_set_points(second_body, second_point, 2); + } +} + +void WatchFaceAnalog::SetBatteryIcon() { + auto batteryPercent = batteryPercentRemaining.Get(); + batteryIcon.SetBatteryPercentage(batteryPercent); +} + +void WatchFaceAnalog::Refresh() { + isCharging = batteryController.IsCharging(); + if (isCharging.IsUpdated()) { + if (isCharging.Get()) { + lv_obj_set_hidden(batteryIcon.GetObject(), true); + lv_obj_set_hidden(plugIcon, false); + } else { + lv_obj_set_hidden(batteryIcon.GetObject(), false); + lv_obj_set_hidden(plugIcon, true); + SetBatteryIcon(); + } + } + if (!isCharging.Get()) { + batteryPercentRemaining = batteryController.PercentRemaining(); + if (batteryPercentRemaining.IsUpdated()) { + SetBatteryIcon(); + } + } + + bleState = bleController.IsConnected(); + if (bleState.IsUpdated()) { + if (bleState.Get()) { + lv_label_set_text_static(bleIcon, Symbols::bluetooth); + } else { + lv_label_set_text_static(bleIcon, ""); + } + } + + notificationState = notificationManager.AreNewNotificationsAvailable(); + + if (notificationState.IsUpdated()) { + lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(notificationState.Get())); + } + + currentDateTime = dateTimeController.CurrentDateTime(); + if (currentDateTime.IsUpdated()) { + UpdateClock(); + + currentDate = std::chrono::time_point_cast(currentDateTime.Get()); + if (currentDate.IsUpdated()) { + lv_label_set_text_fmt(label_date_day, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), dateTimeController.Day()); + } + } +} diff --git a/src/displayapp/screens/WatchFaceFace.h b/src/displayapp/screens/WatchFaceFace.h new file mode 100644 index 00000000..fb2ae36d --- /dev/null +++ b/src/displayapp/screens/WatchFaceFace.h @@ -0,0 +1,92 @@ +#pragma once + +#include +#include +#include +#include +#include "displayapp/screens/Screen.h" +#include "components/datetime/DateTimeController.h" +#include "components/battery/BatteryController.h" +#include "components/ble/BleController.h" +#include "components/ble/NotificationManager.h" +#include "displayapp/screens/BatteryIcon.h" +#include "utility/DirtyValue.h" + +namespace Pinetime { + namespace Controllers { + class Settings; + class Battery; + class Ble; + class NotificationManager; + } + + namespace Applications { + namespace Screens { + + class WatchFaceFace : public Screen { + public: + WatchFaceFace(Controllers::DateTime& dateTimeController, + const Controllers::Battery& batteryController, + const Controllers::Ble& bleController, + Controllers::NotificationManager& notificationManager, + Controllers::Settings& settingsController); + + ~WatchFaceFace() override; + + void Refresh() override; + + private: + uint8_t sHour, sMinute, sSecond; + + Utility::DirtyValue batteryPercentRemaining {0}; + Utility::DirtyValue isCharging {}; + Utility::DirtyValue bleState {}; + Utility::DirtyValue> currentDateTime; + Utility::DirtyValue notificationState {false}; + using days = std::chrono::duration>; // TODO: days is standard in c++20 + Utility::DirtyValue> currentDate; + + lv_obj_t* minor_scales; + lv_obj_t* major_scales; + lv_obj_t* large_scales; + lv_obj_t* twelve; + + 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* plugIcon; + lv_obj_t* notificationIcon; + lv_obj_t* bleIcon; + + BatteryIcon batteryIcon; + + const Controllers::DateTime& dateTimeController; + const Controllers::Battery& batteryController; + const Controllers::Ble& bleController; + Controllers::NotificationManager& notificationManager; + Controllers::Settings& settingsController; + + void UpdateClock(); + void SetBatteryIcon(); + + lv_task_t* taskRefresh; + }; + } + } +} diff --git a/src/displayapp/screens/settings/SettingWatchFace.h b/src/displayapp/screens/settings/SettingWatchFace.h index 45a50e3d..d1db546e 100644 --- a/src/displayapp/screens/settings/SettingWatchFace.h +++ b/src/displayapp/screens/settings/SettingWatchFace.h @@ -11,6 +11,7 @@ #include "displayapp/screens/CheckboxList.h" #include "displayapp/screens/WatchFaceInfineat.h" #include "displayapp/screens/WatchFaceCasioStyleG7710.h" +#include "displayapp/screens/WatchFaceFace.h" namespace Pinetime { @@ -47,8 +48,9 @@ namespace Pinetime { {"Terminal", true}, {"Infineat face", Applications::Screens::WatchFaceInfineat::IsAvailable(filesystem)}, {"Casio G7710", Applications::Screens::WatchFaceCasioStyleG7710::IsAvailable(filesystem)}, - {"", false}, - {"", false}}}; + {"Face face", true}, + {"", false} + }}; ScreenList screens; }; } From cbfd82959e55799fe580047ab9a0da90fda4ac4c Mon Sep 17 00:00:00 2001 From: Josh Date: Sun, 22 Oct 2023 23:31:15 -0400 Subject: [PATCH 50/61] Update reademe todo --- README.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index bde614d3..7a696936 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # TODO ## Completed +### Pending version + +### v1.13.1 - [x] Make $s in terminal watch face green - [x] Swipe left to access music control - [x] Flashlight starts on @@ -9,6 +12,8 @@ - [x] Swipe left/right goes to watchface/another app - [x] Rearrange quick acces and apps - [x] Exponent button on calculator +- [x] Seconds on digital watchface +- [x] Add quick ring settings ## Pending merge @@ -17,18 +22,17 @@ - [ ] Countdown timer presistant buzz ### Josh -- [ ] Seconds on digital watchface -- [ ] Battery on digital watchface -- [ ] Remap button double click (to music app) +- [ ] Smiley face watchface :) +- [ ] Remap button double click ### Moses -- [ ] Add quick ring settings ## Medium priority -- [ ] Temp sensor w/ arduino -- [ ] Homeassistant control +- [ ] Battery on digital watchface +- [ ] More watchfaces! ## Lower priority -- [ ] Maybe some prank watchfaces +- [ ] Temp sensor w/ arduino +- [ ] Homeassistant control From 2cb36d6e80cb2191eba6a5f558923ab48e303fc5 Mon Sep 17 00:00:00 2001 From: Josh Date: Sun, 22 Oct 2023 23:34:22 -0400 Subject: [PATCH 51/61] Working face watchface --- src/displayapp/screens/WatchFaceFace.cpp | 52 ++++++++++++++---------- src/displayapp/screens/WatchFaceFace.h | 9 ++-- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/displayapp/screens/WatchFaceFace.cpp b/src/displayapp/screens/WatchFaceFace.cpp index 1109643c..502f7cb5 100644 --- a/src/displayapp/screens/WatchFaceFace.cpp +++ b/src/displayapp/screens/WatchFaceFace.cpp @@ -1,4 +1,4 @@ -#include "displayapp/screens/WatchFaceAnalog.h" +#include "displayapp/screens/WatchFaceFace.h" #include #include #include "displayapp/screens/BatteryIcon.h" @@ -11,7 +11,7 @@ using namespace Pinetime::Applications::Screens; namespace { - constexpr int16_t HourLength = 70; + constexpr int16_t HourLength = 100; constexpr int16_t MinuteLength = 90; constexpr int16_t SecondLength = 110; @@ -41,7 +41,7 @@ namespace { } -WatchFaceAnalog::WatchFaceFace(Controllers::DateTime& dateTimeController, +WatchFaceFace::WatchFaceFace(Controllers::DateTime& dateTimeController, const Controllers::Battery& batteryController, const Controllers::Ble& bleController, Controllers::NotificationManager& notificationManager, @@ -58,6 +58,23 @@ WatchFaceAnalog::WatchFaceFace(Controllers::DateTime& dateTimeController, sMinute = 99; sSecond = 99; + mouth = lv_arc_create(lv_scr_act(), nullptr); + lv_arc_set_angles(mouth, 30, 110); + lv_arc_set_bg_angles(mouth, 45, 135); + lv_obj_set_size(mouth, 130, 130); + lv_obj_align(mouth, nullptr, LV_ALIGN_CENTER, 0, 0); + + leye = lv_arc_create(lv_scr_act(), nullptr); + lv_arc_set_angles(leye, 0, 360); + lv_obj_set_size(leye, 30, 30); + lv_obj_align(leye, nullptr, LV_ALIGN_CENTER, -35, -35); + + reye = lv_arc_create(lv_scr_act(), nullptr); + lv_arc_set_angles(reye, 0, 360); + lv_obj_set_size(reye, 30, 30); + lv_obj_align(reye, nullptr, LV_ALIGN_CENTER, 35, -35); + + minor_scales = lv_linemeter_create(lv_scr_act(), nullptr); lv_linemeter_set_scale(minor_scales, 300, 51); lv_linemeter_set_angle_offset(minor_scales, 180); @@ -116,7 +133,7 @@ WatchFaceAnalog::WatchFaceFace(Controllers::DateTime& dateTimeController, lv_obj_set_style_local_text_color(label_date_day, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange); 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, nullptr, LV_ALIGN_CENTER, 50, 0); + lv_obj_align(label_date_day, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); minute_body = lv_line_create(lv_scr_act(), nullptr); minute_body_trace = lv_line_create(lv_scr_act(), nullptr); @@ -131,7 +148,7 @@ WatchFaceAnalog::WatchFaceFace(Controllers::DateTime& dateTimeController, 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_width(&minute_line_style, LV_STATE_DEFAULT, 3); 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); @@ -171,21 +188,18 @@ WatchFaceFace::~WatchFaceFace() { lv_obj_clean(lv_scr_act()); } -void WatchFaceAnalog::UpdateClock() { +void WatchFaceFace::UpdateClock() { uint8_t hour = dateTimeController.Hours(); uint8_t minute = dateTimeController.Minutes(); uint8_t second = dateTimeController.Seconds(); if (sMinute != minute) { auto const angle = minute * 6; - minute_point[0] = CoordinateRelocate(30, angle); + minute_point[0] = CoordinateRelocate(10, angle - 90); minute_point[1] = CoordinateRelocate(MinuteLength, angle); + minute_point[2] = CoordinateRelocate(10, angle + 90); - minute_point_trace[0] = CoordinateRelocate(5, angle); - minute_point_trace[1] = CoordinateRelocate(31, angle); - - lv_line_set_points(minute_body, minute_point, 2); - lv_line_set_points(minute_body_trace, minute_point_trace, 2); + lv_line_set_points(minute_body, minute_point, 3); } if (sHour != hour || sMinute != minute) { @@ -193,32 +207,28 @@ void WatchFaceAnalog::UpdateClock() { sMinute = minute; auto const angle = (hour * 30 + minute / 2); - hour_point[0] = CoordinateRelocate(30, angle); + hour_point[0] = CoordinateRelocate(90, angle); hour_point[1] = CoordinateRelocate(HourLength, angle); - hour_point_trace[0] = CoordinateRelocate(5, angle); - hour_point_trace[1] = CoordinateRelocate(31, angle); - 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; auto const angle = second * 6; - second_point[0] = CoordinateRelocate(-20, angle); + second_point[0] = CoordinateRelocate(105, angle); second_point[1] = CoordinateRelocate(SecondLength, angle); lv_line_set_points(second_body, second_point, 2); - } + }//TODO: redo seconds } -void WatchFaceAnalog::SetBatteryIcon() { +void WatchFaceFace::SetBatteryIcon() { auto batteryPercent = batteryPercentRemaining.Get(); batteryIcon.SetBatteryPercentage(batteryPercent); } -void WatchFaceAnalog::Refresh() { +void WatchFaceFace::Refresh() { isCharging = batteryController.IsCharging(); if (isCharging.IsUpdated()) { if (isCharging.Get()) { diff --git a/src/displayapp/screens/WatchFaceFace.h b/src/displayapp/screens/WatchFaceFace.h index fb2ae36d..448ef327 100644 --- a/src/displayapp/screens/WatchFaceFace.h +++ b/src/displayapp/screens/WatchFaceFace.h @@ -58,9 +58,7 @@ namespace Pinetime { 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 minute_point[3]; lv_point_t second_point[2]; lv_style_t hour_line_style; @@ -74,6 +72,11 @@ namespace Pinetime { lv_obj_t* notificationIcon; lv_obj_t* bleIcon; + lv_obj_t* mouth; + lv_obj_t* leye; + lv_obj_t* reye; + + BatteryIcon batteryIcon; const Controllers::DateTime& dateTimeController; From 415ff6c05ca40331b983bf8d3a457444f54762f4 Mon Sep 17 00:00:00 2001 From: Josh Date: Sun, 22 Oct 2023 23:31:15 -0400 Subject: [PATCH 52/61] Update reademe todo (cherry picked from commit cbfd82959e55799fe580047ab9a0da90fda4ac4c) --- README.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index bde614d3..7a696936 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # TODO ## Completed +### Pending version + +### v1.13.1 - [x] Make $s in terminal watch face green - [x] Swipe left to access music control - [x] Flashlight starts on @@ -9,6 +12,8 @@ - [x] Swipe left/right goes to watchface/another app - [x] Rearrange quick acces and apps - [x] Exponent button on calculator +- [x] Seconds on digital watchface +- [x] Add quick ring settings ## Pending merge @@ -17,18 +22,17 @@ - [ ] Countdown timer presistant buzz ### Josh -- [ ] Seconds on digital watchface -- [ ] Battery on digital watchface -- [ ] Remap button double click (to music app) +- [ ] Smiley face watchface :) +- [ ] Remap button double click ### Moses -- [ ] Add quick ring settings ## Medium priority -- [ ] Temp sensor w/ arduino -- [ ] Homeassistant control +- [ ] Battery on digital watchface +- [ ] More watchfaces! ## Lower priority -- [ ] Maybe some prank watchfaces +- [ ] Temp sensor w/ arduino +- [ ] Homeassistant control From 5d7e1ae1f32b235bd44c7f3978cb2cacf7e8175d Mon Sep 17 00:00:00 2001 From: Josh Date: Sun, 22 Oct 2023 23:41:43 -0400 Subject: [PATCH 53/61] Update version to 1.13.1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 83c6e98d..91c3dd53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10) set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release") -project(pinetime VERSION 1.13.0 LANGUAGES C CXX ASM) +project(pinetime VERSION 1.13.1 LANGUAGES C CXX ASM) set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 14) From 1ff782cb0e7daebb8833609a174d802ecc357c0e Mon Sep 17 00:00:00 2001 From: Josh Date: Sun, 22 Oct 2023 23:41:43 -0400 Subject: [PATCH 54/61] Update version to 1.13.1 (cherry picked from commit 5d7e1ae1f32b235bd44c7f3978cb2cacf7e8175d) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 83c6e98d..91c3dd53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10) set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release") -project(pinetime VERSION 1.13.0 LANGUAGES C CXX ASM) +project(pinetime VERSION 1.13.1 LANGUAGES C CXX ASM) set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 14) From 79820669b64fd22bfadd1ef1757c7dd86cdf9113 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 25 Oct 2023 22:32:28 -0400 Subject: [PATCH 55/61] Small rename --- src/displayapp/WatchFaces.h | 2 +- src/displayapp/screens/Clock.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/displayapp/WatchFaces.h b/src/displayapp/WatchFaces.h index 8f065285..b3a13f43 100644 --- a/src/displayapp/WatchFaces.h +++ b/src/displayapp/WatchFaces.h @@ -9,7 +9,7 @@ namespace Pinetime { Terminal = 3, Infineat = 4, CasioStyleG7710 = 5, - Face = 6, + FaceFace = 6, }; } } diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp index 747bcab3..a2280a43 100644 --- a/src/displayapp/screens/Clock.cpp +++ b/src/displayapp/screens/Clock.cpp @@ -56,7 +56,7 @@ Clock::Clock(Controllers::DateTime& dateTimeController, case WatchFace::CasioStyleG7710: return WatchFaceCasioStyleG7710(); break; - case WatchFace::Face: + case WatchFace::FaceFace: return WatchFaceFaceScreen(); break; } From e24323b4548d9831b67229d0faeccbb71769ec01 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 25 Oct 2023 22:33:30 -0400 Subject: [PATCH 56/61] Incriment version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 91c3dd53..0a31c732 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10) set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release") -project(pinetime VERSION 1.13.1 LANGUAGES C CXX ASM) +project(pinetime VERSION 1.13.1.1 LANGUAGES C CXX ASM) set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 14) From dd5d65d315c8dcd664702f1991325bec95f233d5 Mon Sep 17 00:00:00 2001 From: Josh Date: Sun, 22 Oct 2023 22:37:53 -0400 Subject: [PATCH 57/61] Added duplicate of analog face --- src/CMakeLists.txt | 1 + src/displayapp/WatchFaces.h | 1 + src/displayapp/screens/Clock.cpp | 13 + src/displayapp/screens/Clock.h | 1 + src/displayapp/screens/WatchFaceFace.cpp | 264 ++++++++++++++++++ src/displayapp/screens/WatchFaceFace.h | 92 ++++++ .../screens/settings/SettingWatchFace.h | 6 +- 7 files changed, 376 insertions(+), 2 deletions(-) create mode 100644 src/displayapp/screens/WatchFaceFace.cpp create mode 100644 src/displayapp/screens/WatchFaceFace.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 68f94328..9c8dd1ee 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -435,6 +435,7 @@ list(APPEND SOURCE_FILES displayapp/screens/WatchFaceTerminal.cpp displayapp/screens/WatchFacePineTimeStyle.cpp displayapp/screens/WatchFaceCasioStyleG7710.cpp + displayapp/screens/WatchFaceFace.cpp ## diff --git a/src/displayapp/WatchFaces.h b/src/displayapp/WatchFaces.h index 2982347a..8f065285 100644 --- a/src/displayapp/WatchFaces.h +++ b/src/displayapp/WatchFaces.h @@ -9,6 +9,7 @@ namespace Pinetime { Terminal = 3, Infineat = 4, CasioStyleG7710 = 5, + Face = 6, }; } } diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp index eeb7f0e1..747bcab3 100644 --- a/src/displayapp/screens/Clock.cpp +++ b/src/displayapp/screens/Clock.cpp @@ -13,6 +13,7 @@ #include "displayapp/screens/WatchFaceAnalog.h" #include "displayapp/screens/WatchFacePineTimeStyle.h" #include "displayapp/screens/WatchFaceCasioStyleG7710.h" +#include "displayapp/screens/WatchFaceFace.h" using namespace Pinetime::Applications::Screens; using namespace Pinetime::Applications; @@ -55,6 +56,9 @@ Clock::Clock(Controllers::DateTime& dateTimeController, case WatchFace::CasioStyleG7710: return WatchFaceCasioStyleG7710(); break; + case WatchFace::Face: + return WatchFaceFaceScreen(); + break; } return WatchFaceDigitalScreen(); }()} { @@ -130,3 +134,12 @@ std::unique_ptr Clock::WatchFaceCasioStyleG7710() { motionController, filesystem); } + + +std::unique_ptr Clock::WatchFaceFaceScreen() { + return std::make_unique(dateTimeController, + batteryController, + bleController, + notificationManager, + settingsController); +} diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h index f3591f43..9e484867 100644 --- a/src/displayapp/screens/Clock.h +++ b/src/displayapp/screens/Clock.h @@ -54,6 +54,7 @@ namespace Pinetime { std::unique_ptr WatchFaceTerminalScreen(); std::unique_ptr WatchFaceInfineatScreen(); std::unique_ptr WatchFaceCasioStyleG7710(); + std::unique_ptr WatchFaceFaceScreen(); }; } } diff --git a/src/displayapp/screens/WatchFaceFace.cpp b/src/displayapp/screens/WatchFaceFace.cpp new file mode 100644 index 00000000..1109643c --- /dev/null +++ b/src/displayapp/screens/WatchFaceFace.cpp @@ -0,0 +1,264 @@ +#include "displayapp/screens/WatchFaceAnalog.h" +#include +#include +#include "displayapp/screens/BatteryIcon.h" +#include "displayapp/screens/BleIcon.h" +#include "displayapp/screens/Symbols.h" +#include "displayapp/screens/NotificationIcon.h" +#include "components/settings/Settings.h" +#include "displayapp/InfiniTimeTheme.h" + +using namespace Pinetime::Applications::Screens; + +namespace { + constexpr int16_t HourLength = 70; + constexpr int16_t MinuteLength = 90; + constexpr int16_t SecondLength = 110; + + // sin(90) = 1 so the value of _lv_trigo_sin(90) is the scaling factor + const auto LV_TRIG_SCALE = _lv_trigo_sin(90); + + int16_t Cosine(int16_t angle) { + return _lv_trigo_sin(angle + 90); + } + + int16_t Sine(int16_t angle) { + return _lv_trigo_sin(angle); + } + + int16_t CoordinateXRelocate(int16_t x) { + return (x + LV_HOR_RES / 2); + } + + int16_t CoordinateYRelocate(int16_t y) { + return std::abs(y - LV_HOR_RES / 2); + } + + lv_point_t CoordinateRelocate(int16_t radius, int16_t angle) { + return lv_point_t {.x = CoordinateXRelocate(radius * static_cast(Sine(angle)) / LV_TRIG_SCALE), + .y = CoordinateYRelocate(radius * static_cast(Cosine(angle)) / LV_TRIG_SCALE)}; + } + +} + +WatchFaceAnalog::WatchFaceFace(Controllers::DateTime& dateTimeController, + const Controllers::Battery& batteryController, + const Controllers::Ble& bleController, + Controllers::NotificationManager& notificationManager, + Controllers::Settings& settingsController) + : currentDateTime {{}}, + batteryIcon(true), + dateTimeController {dateTimeController}, + batteryController {batteryController}, + bleController {bleController}, + notificationManager {notificationManager}, + settingsController {settingsController} { + + sHour = 99; + sMinute = 99; + sSecond = 99; + + minor_scales = lv_linemeter_create(lv_scr_act(), nullptr); + lv_linemeter_set_scale(minor_scales, 300, 51); + lv_linemeter_set_angle_offset(minor_scales, 180); + lv_obj_set_size(minor_scales, 240, 240); + lv_obj_align(minor_scales, nullptr, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_opa(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); + lv_obj_set_style_local_scale_width(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4); + lv_obj_set_style_local_scale_end_line_width(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 1); + lv_obj_set_style_local_scale_end_color(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); + + major_scales = lv_linemeter_create(lv_scr_act(), nullptr); + lv_linemeter_set_scale(major_scales, 300, 11); + lv_linemeter_set_angle_offset(major_scales, 180); + lv_obj_set_size(major_scales, 240, 240); + lv_obj_align(major_scales, nullptr, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_opa(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); + lv_obj_set_style_local_scale_width(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 6); + lv_obj_set_style_local_scale_end_line_width(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4); + lv_obj_set_style_local_scale_end_color(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); + + large_scales = lv_linemeter_create(lv_scr_act(), nullptr); + lv_linemeter_set_scale(large_scales, 180, 3); + lv_linemeter_set_angle_offset(large_scales, 180); + lv_obj_set_size(large_scales, 240, 240); + lv_obj_align(large_scales, nullptr, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_opa(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); + lv_obj_set_style_local_scale_width(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 20); + lv_obj_set_style_local_scale_end_line_width(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4); + lv_obj_set_style_local_scale_end_color(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA); + + twelve = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_align(twelve, LV_LABEL_ALIGN_CENTER); + lv_label_set_text_static(twelve, "12"); + lv_obj_set_pos(twelve, 110, 10); + lv_obj_set_style_local_text_color(twelve, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA); + + batteryIcon.Create(lv_scr_act()); + lv_obj_align(batteryIcon.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); + + plugIcon = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(plugIcon, Symbols::plug); + lv_obj_align(plugIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); + + bleIcon = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(bleIcon, ""); + lv_obj_align(bleIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, -30, 0); + + notificationIcon = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_LIME); + lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(false)); + lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); + + // Date - Day / Week day + + label_date_day = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(label_date_day, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange); + 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, nullptr, LV_ALIGN_CENTER, 50, 0); + + minute_body = lv_line_create(lv_scr_act(), nullptr); + minute_body_trace = lv_line_create(lv_scr_act(), nullptr); + hour_body = lv_line_create(lv_scr_act(), nullptr); + hour_body_trace = lv_line_create(lv_scr_act(), nullptr); + second_body = lv_line_create(lv_scr_act(), nullptr); + + 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); + + taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); + + Refresh(); +} + +WatchFaceFace::~WatchFaceFace() { + lv_task_del(taskRefresh); + + 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() { + uint8_t hour = dateTimeController.Hours(); + uint8_t minute = dateTimeController.Minutes(); + uint8_t second = dateTimeController.Seconds(); + + if (sMinute != minute) { + auto const angle = minute * 6; + minute_point[0] = CoordinateRelocate(30, angle); + minute_point[1] = CoordinateRelocate(MinuteLength, angle); + + minute_point_trace[0] = CoordinateRelocate(5, angle); + minute_point_trace[1] = CoordinateRelocate(31, angle); + + 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; + auto const angle = (hour * 30 + minute / 2); + + hour_point[0] = CoordinateRelocate(30, angle); + hour_point[1] = CoordinateRelocate(HourLength, angle); + + hour_point_trace[0] = CoordinateRelocate(5, angle); + hour_point_trace[1] = CoordinateRelocate(31, angle); + + 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; + auto const angle = second * 6; + + second_point[0] = CoordinateRelocate(-20, angle); + second_point[1] = CoordinateRelocate(SecondLength, angle); + lv_line_set_points(second_body, second_point, 2); + } +} + +void WatchFaceAnalog::SetBatteryIcon() { + auto batteryPercent = batteryPercentRemaining.Get(); + batteryIcon.SetBatteryPercentage(batteryPercent); +} + +void WatchFaceAnalog::Refresh() { + isCharging = batteryController.IsCharging(); + if (isCharging.IsUpdated()) { + if (isCharging.Get()) { + lv_obj_set_hidden(batteryIcon.GetObject(), true); + lv_obj_set_hidden(plugIcon, false); + } else { + lv_obj_set_hidden(batteryIcon.GetObject(), false); + lv_obj_set_hidden(plugIcon, true); + SetBatteryIcon(); + } + } + if (!isCharging.Get()) { + batteryPercentRemaining = batteryController.PercentRemaining(); + if (batteryPercentRemaining.IsUpdated()) { + SetBatteryIcon(); + } + } + + bleState = bleController.IsConnected(); + if (bleState.IsUpdated()) { + if (bleState.Get()) { + lv_label_set_text_static(bleIcon, Symbols::bluetooth); + } else { + lv_label_set_text_static(bleIcon, ""); + } + } + + notificationState = notificationManager.AreNewNotificationsAvailable(); + + if (notificationState.IsUpdated()) { + lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(notificationState.Get())); + } + + currentDateTime = dateTimeController.CurrentDateTime(); + if (currentDateTime.IsUpdated()) { + UpdateClock(); + + currentDate = std::chrono::time_point_cast(currentDateTime.Get()); + if (currentDate.IsUpdated()) { + lv_label_set_text_fmt(label_date_day, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), dateTimeController.Day()); + } + } +} diff --git a/src/displayapp/screens/WatchFaceFace.h b/src/displayapp/screens/WatchFaceFace.h new file mode 100644 index 00000000..fb2ae36d --- /dev/null +++ b/src/displayapp/screens/WatchFaceFace.h @@ -0,0 +1,92 @@ +#pragma once + +#include +#include +#include +#include +#include "displayapp/screens/Screen.h" +#include "components/datetime/DateTimeController.h" +#include "components/battery/BatteryController.h" +#include "components/ble/BleController.h" +#include "components/ble/NotificationManager.h" +#include "displayapp/screens/BatteryIcon.h" +#include "utility/DirtyValue.h" + +namespace Pinetime { + namespace Controllers { + class Settings; + class Battery; + class Ble; + class NotificationManager; + } + + namespace Applications { + namespace Screens { + + class WatchFaceFace : public Screen { + public: + WatchFaceFace(Controllers::DateTime& dateTimeController, + const Controllers::Battery& batteryController, + const Controllers::Ble& bleController, + Controllers::NotificationManager& notificationManager, + Controllers::Settings& settingsController); + + ~WatchFaceFace() override; + + void Refresh() override; + + private: + uint8_t sHour, sMinute, sSecond; + + Utility::DirtyValue batteryPercentRemaining {0}; + Utility::DirtyValue isCharging {}; + Utility::DirtyValue bleState {}; + Utility::DirtyValue> currentDateTime; + Utility::DirtyValue notificationState {false}; + using days = std::chrono::duration>; // TODO: days is standard in c++20 + Utility::DirtyValue> currentDate; + + lv_obj_t* minor_scales; + lv_obj_t* major_scales; + lv_obj_t* large_scales; + lv_obj_t* twelve; + + 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* plugIcon; + lv_obj_t* notificationIcon; + lv_obj_t* bleIcon; + + BatteryIcon batteryIcon; + + const Controllers::DateTime& dateTimeController; + const Controllers::Battery& batteryController; + const Controllers::Ble& bleController; + Controllers::NotificationManager& notificationManager; + Controllers::Settings& settingsController; + + void UpdateClock(); + void SetBatteryIcon(); + + lv_task_t* taskRefresh; + }; + } + } +} diff --git a/src/displayapp/screens/settings/SettingWatchFace.h b/src/displayapp/screens/settings/SettingWatchFace.h index 45a50e3d..d1db546e 100644 --- a/src/displayapp/screens/settings/SettingWatchFace.h +++ b/src/displayapp/screens/settings/SettingWatchFace.h @@ -11,6 +11,7 @@ #include "displayapp/screens/CheckboxList.h" #include "displayapp/screens/WatchFaceInfineat.h" #include "displayapp/screens/WatchFaceCasioStyleG7710.h" +#include "displayapp/screens/WatchFaceFace.h" namespace Pinetime { @@ -47,8 +48,9 @@ namespace Pinetime { {"Terminal", true}, {"Infineat face", Applications::Screens::WatchFaceInfineat::IsAvailable(filesystem)}, {"Casio G7710", Applications::Screens::WatchFaceCasioStyleG7710::IsAvailable(filesystem)}, - {"", false}, - {"", false}}}; + {"Face face", true}, + {"", false} + }}; ScreenList screens; }; } From d758394ce99a225c4392a521f37dbbdeefc0d0e2 Mon Sep 17 00:00:00 2001 From: Josh Date: Sun, 22 Oct 2023 23:34:22 -0400 Subject: [PATCH 58/61] Working face watchface --- src/displayapp/screens/WatchFaceFace.cpp | 52 ++++++++++++++---------- src/displayapp/screens/WatchFaceFace.h | 9 ++-- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/displayapp/screens/WatchFaceFace.cpp b/src/displayapp/screens/WatchFaceFace.cpp index 1109643c..502f7cb5 100644 --- a/src/displayapp/screens/WatchFaceFace.cpp +++ b/src/displayapp/screens/WatchFaceFace.cpp @@ -1,4 +1,4 @@ -#include "displayapp/screens/WatchFaceAnalog.h" +#include "displayapp/screens/WatchFaceFace.h" #include #include #include "displayapp/screens/BatteryIcon.h" @@ -11,7 +11,7 @@ using namespace Pinetime::Applications::Screens; namespace { - constexpr int16_t HourLength = 70; + constexpr int16_t HourLength = 100; constexpr int16_t MinuteLength = 90; constexpr int16_t SecondLength = 110; @@ -41,7 +41,7 @@ namespace { } -WatchFaceAnalog::WatchFaceFace(Controllers::DateTime& dateTimeController, +WatchFaceFace::WatchFaceFace(Controllers::DateTime& dateTimeController, const Controllers::Battery& batteryController, const Controllers::Ble& bleController, Controllers::NotificationManager& notificationManager, @@ -58,6 +58,23 @@ WatchFaceAnalog::WatchFaceFace(Controllers::DateTime& dateTimeController, sMinute = 99; sSecond = 99; + mouth = lv_arc_create(lv_scr_act(), nullptr); + lv_arc_set_angles(mouth, 30, 110); + lv_arc_set_bg_angles(mouth, 45, 135); + lv_obj_set_size(mouth, 130, 130); + lv_obj_align(mouth, nullptr, LV_ALIGN_CENTER, 0, 0); + + leye = lv_arc_create(lv_scr_act(), nullptr); + lv_arc_set_angles(leye, 0, 360); + lv_obj_set_size(leye, 30, 30); + lv_obj_align(leye, nullptr, LV_ALIGN_CENTER, -35, -35); + + reye = lv_arc_create(lv_scr_act(), nullptr); + lv_arc_set_angles(reye, 0, 360); + lv_obj_set_size(reye, 30, 30); + lv_obj_align(reye, nullptr, LV_ALIGN_CENTER, 35, -35); + + minor_scales = lv_linemeter_create(lv_scr_act(), nullptr); lv_linemeter_set_scale(minor_scales, 300, 51); lv_linemeter_set_angle_offset(minor_scales, 180); @@ -116,7 +133,7 @@ WatchFaceAnalog::WatchFaceFace(Controllers::DateTime& dateTimeController, lv_obj_set_style_local_text_color(label_date_day, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange); 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, nullptr, LV_ALIGN_CENTER, 50, 0); + lv_obj_align(label_date_day, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); minute_body = lv_line_create(lv_scr_act(), nullptr); minute_body_trace = lv_line_create(lv_scr_act(), nullptr); @@ -131,7 +148,7 @@ WatchFaceAnalog::WatchFaceFace(Controllers::DateTime& dateTimeController, 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_width(&minute_line_style, LV_STATE_DEFAULT, 3); 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); @@ -171,21 +188,18 @@ WatchFaceFace::~WatchFaceFace() { lv_obj_clean(lv_scr_act()); } -void WatchFaceAnalog::UpdateClock() { +void WatchFaceFace::UpdateClock() { uint8_t hour = dateTimeController.Hours(); uint8_t minute = dateTimeController.Minutes(); uint8_t second = dateTimeController.Seconds(); if (sMinute != minute) { auto const angle = minute * 6; - minute_point[0] = CoordinateRelocate(30, angle); + minute_point[0] = CoordinateRelocate(10, angle - 90); minute_point[1] = CoordinateRelocate(MinuteLength, angle); + minute_point[2] = CoordinateRelocate(10, angle + 90); - minute_point_trace[0] = CoordinateRelocate(5, angle); - minute_point_trace[1] = CoordinateRelocate(31, angle); - - lv_line_set_points(minute_body, minute_point, 2); - lv_line_set_points(minute_body_trace, minute_point_trace, 2); + lv_line_set_points(minute_body, minute_point, 3); } if (sHour != hour || sMinute != minute) { @@ -193,32 +207,28 @@ void WatchFaceAnalog::UpdateClock() { sMinute = minute; auto const angle = (hour * 30 + minute / 2); - hour_point[0] = CoordinateRelocate(30, angle); + hour_point[0] = CoordinateRelocate(90, angle); hour_point[1] = CoordinateRelocate(HourLength, angle); - hour_point_trace[0] = CoordinateRelocate(5, angle); - hour_point_trace[1] = CoordinateRelocate(31, angle); - 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; auto const angle = second * 6; - second_point[0] = CoordinateRelocate(-20, angle); + second_point[0] = CoordinateRelocate(105, angle); second_point[1] = CoordinateRelocate(SecondLength, angle); lv_line_set_points(second_body, second_point, 2); - } + }//TODO: redo seconds } -void WatchFaceAnalog::SetBatteryIcon() { +void WatchFaceFace::SetBatteryIcon() { auto batteryPercent = batteryPercentRemaining.Get(); batteryIcon.SetBatteryPercentage(batteryPercent); } -void WatchFaceAnalog::Refresh() { +void WatchFaceFace::Refresh() { isCharging = batteryController.IsCharging(); if (isCharging.IsUpdated()) { if (isCharging.Get()) { diff --git a/src/displayapp/screens/WatchFaceFace.h b/src/displayapp/screens/WatchFaceFace.h index fb2ae36d..448ef327 100644 --- a/src/displayapp/screens/WatchFaceFace.h +++ b/src/displayapp/screens/WatchFaceFace.h @@ -58,9 +58,7 @@ namespace Pinetime { 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 minute_point[3]; lv_point_t second_point[2]; lv_style_t hour_line_style; @@ -74,6 +72,11 @@ namespace Pinetime { lv_obj_t* notificationIcon; lv_obj_t* bleIcon; + lv_obj_t* mouth; + lv_obj_t* leye; + lv_obj_t* reye; + + BatteryIcon batteryIcon; const Controllers::DateTime& dateTimeController; From 0cc8017cbd26f3346e005d5526db2ed3fc45a6de Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 25 Oct 2023 22:32:28 -0400 Subject: [PATCH 59/61] Small rename --- src/displayapp/WatchFaces.h | 2 +- src/displayapp/screens/Clock.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/displayapp/WatchFaces.h b/src/displayapp/WatchFaces.h index 8f065285..b3a13f43 100644 --- a/src/displayapp/WatchFaces.h +++ b/src/displayapp/WatchFaces.h @@ -9,7 +9,7 @@ namespace Pinetime { Terminal = 3, Infineat = 4, CasioStyleG7710 = 5, - Face = 6, + FaceFace = 6, }; } } diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp index 747bcab3..a2280a43 100644 --- a/src/displayapp/screens/Clock.cpp +++ b/src/displayapp/screens/Clock.cpp @@ -56,7 +56,7 @@ Clock::Clock(Controllers::DateTime& dateTimeController, case WatchFace::CasioStyleG7710: return WatchFaceCasioStyleG7710(); break; - case WatchFace::Face: + case WatchFace::FaceFace: return WatchFaceFaceScreen(); break; } From 4fa8e0228961881f41fae1ad88129ca0ee2a6d14 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 25 Oct 2023 22:33:30 -0400 Subject: [PATCH 60/61] Incriment version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 91c3dd53..0a31c732 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10) set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release") -project(pinetime VERSION 1.13.1 LANGUAGES C CXX ASM) +project(pinetime VERSION 1.13.1.1 LANGUAGES C CXX ASM) set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 14) From 77f1a3e230fefaeac8a3b2fae68d376bb11b6576 Mon Sep 17 00:00:00 2001 From: tofasthacker Date: Mon, 13 Nov 2023 23:11:09 -0500 Subject: [PATCH 61/61] fixed watchface memery error --- src/displayapp/DisplayApp.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 8d4e50d8..16b898fa 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -374,18 +374,18 @@ void DisplayApp::Refresh() { // What should happen here? break; case Messages::Chime: - LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::None); + time_var = dateTimeController.Minutes(); if (time_var == 30){ - NRF_LOG_INFO("Short: %d", time_var); + //NRF_LOG_INFO("Short: %d", time_var); motorController.StartPattern(); } else { - NRF_LOG_INFO("Long: %d", time_var); + //NRF_LOG_INFO("Long: %d", time_var); motorController.RunForDuration(200); } - + //LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::None); break; case Messages::OnChargingEvent: