From 3be4b6f207fc245a7437213ea3fa13f0bdfd9a07 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 2 Oct 2024 15:27:11 -0500 Subject: [PATCH 001/123] Started working on SleepTracker --- src/displayapp/DisplayApp.cpp | 1 + src/displayapp/apps/Apps.h.in | 1 + src/displayapp/apps/CMakeLists.txt | 1 + src/displayapp/fonts/fonts.json | 2 +- src/displayapp/screens/SleepTracker.cpp | 21 +++++++++++++++++ src/displayapp/screens/SleepTracker.h | 30 +++++++++++++++++++++++++ src/displayapp/screens/Symbols.h | 1 + 7 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/displayapp/screens/SleepTracker.cpp create mode 100644 src/displayapp/screens/SleepTracker.h diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index bfd7dbed6d..8232aaf762 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -31,6 +31,7 @@ #include "displayapp/screens/PassKey.h" #include "displayapp/screens/Error.h" #include "displayapp/screens/Calculator.h" +#include "displayapp/screens/SleepTracker.h" #include "drivers/Cst816s.h" #include "drivers/St7789.h" diff --git a/src/displayapp/apps/Apps.h.in b/src/displayapp/apps/Apps.h.in index f6feeb7b6d..70510c9a28 100644 --- a/src/displayapp/apps/Apps.h.in +++ b/src/displayapp/apps/Apps.h.in @@ -22,6 +22,7 @@ namespace Pinetime { Paddle, Twos, HeartRate, + SleepTracker, Navigation, StopWatch, Metronome, diff --git a/src/displayapp/apps/CMakeLists.txt b/src/displayapp/apps/CMakeLists.txt index 93196ed6a0..5cad71053f 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -17,6 +17,7 @@ else () set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Weather") #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Motion") set(USERAPP_TYPES "${DEFAULT_USER_APP_TYPES}" CACHE STRING "List of user apps to build into the firmware") + set(USERAPP_TYPES "${USERAPP_TYPES}, Apps::SleepTracker") endif () if(DEFINED ENABLE_WATCHFACES) diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index fea3160572..204ca977d1 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, 0xf0f3, 0xf522, 0xf743, 0xf1ec, 0xf55a" + "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, 0xf0f3, 0xf522, 0xf743, 0xf236, 0xf1ec, 0xf55a" } ], "bpp": 1, diff --git a/src/displayapp/screens/SleepTracker.cpp b/src/displayapp/screens/SleepTracker.cpp new file mode 100644 index 0000000000..b4803be9e4 --- /dev/null +++ b/src/displayapp/screens/SleepTracker.cpp @@ -0,0 +1,21 @@ +#include "displayapp/screens/SleepTracker.h" + +using namespace Pinetime::Applications::Screens; + +SleepTracker::SleepTracker() { + lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(title, "My test application"); + lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); + lv_obj_align(title, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + + // Create the HR Data Task + +} + +SleepTracker::~SleepTracker() { + lv_obj_clean(lv_scr_act()); +} + +void SleepTracker::GetBPM() { + +} \ No newline at end of file diff --git a/src/displayapp/screens/SleepTracker.h b/src/displayapp/screens/SleepTracker.h new file mode 100644 index 0000000000..748d2cdec5 --- /dev/null +++ b/src/displayapp/screens/SleepTracker.h @@ -0,0 +1,30 @@ +#pragma once + +#include "displayapp/apps/Apps.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/Controllers.h" +#include "Symbols.h" + +namespace Pinetime { + namespace Applications { + namespace Screens { + class SleepTracker : public Screen { + public: + SleepTracker(); + ~SleepTracker() override; + + private: + void GetBPM(); + }; + } + + template <> + struct AppTraits { + static constexpr Apps app = Apps::SleepTracker; + static constexpr const char* icon = Screens::Symbols::bed; + static Screens::Screen* Create(AppControllers& controllers) { + return new Screens::SleepTracker(); + } + }; + } +} \ No newline at end of file diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index 40699b3d65..0395d63af2 100644 --- a/src/displayapp/screens/Symbols.h +++ b/src/displayapp/screens/Symbols.h @@ -41,6 +41,7 @@ namespace Pinetime { static constexpr const char* sleep = "\xEE\xBD\x84"; static constexpr const char* calculator = "\xEF\x87\xAC"; static constexpr const char* backspace = "\xEF\x95\x9A"; + static constexpr const char* bed = "\xEF\x88\xB6"; // fontawesome_weathericons.c // static constexpr const char* sun = "\xEF\x86\x85"; From 717db5e95c943d095d953d74592af83297e675d2 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 3 Oct 2024 18:29:54 -0500 Subject: [PATCH 002/123] Began adding BPM data collection --- src/displayapp/screens/SleepTracker.cpp | 60 +++++++++++++++++++++++-- src/displayapp/screens/SleepTracker.h | 24 ++++++++-- 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/src/displayapp/screens/SleepTracker.cpp b/src/displayapp/screens/SleepTracker.cpp index b4803be9e4..64e0425148 100644 --- a/src/displayapp/screens/SleepTracker.cpp +++ b/src/displayapp/screens/SleepTracker.cpp @@ -1,21 +1,75 @@ #include "displayapp/screens/SleepTracker.h" +#include +#include +#include +#include + using namespace Pinetime::Applications::Screens; -SleepTracker::SleepTracker() { +namespace { + + void BpmDataCallback(lv_task_t* task) { + auto* screen = static_cast(task->user_data); + screen->GetBPM(); + } + +} + +SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController, Controllers::DateTime& dateTimeController, System::SystemTask& systemTask) + : heartRateController {heartRateController}, dateTimeController {dateTimeController}, wakeLock(systemTask) { + + wakeLock.Lock(); + lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(title, "My test application"); lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); lv_obj_align(title, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); - // Create the HR Data Task - + label_hr = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); + + // Create the refresh task + mainRefreshTask = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this); + hrRefreshTask = lv_task_create(BpmDataCallback, 3000, LV_TASK_PRIO_MID, this); } SleepTracker::~SleepTracker() { + wakeLock.Release(); + lv_obj_clean(lv_scr_act()); + lv_task_del(mainRefreshTask); + lv_task_del(hrRefreshTask); +} + +// This function is called periodically from the refresh task +void SleepTracker::Refresh() { + // Get the current heart rate } void SleepTracker::GetBPM() { + // Get the heart rate from the controller + prevBpm = bpm; + bpm = heartRateController.HeartRate(); + + if(prevBpm != 0) + rollingBpm = (rollingBpm + bpm) / 2; + else + rollingBpm = bpm; + + // Get the current time from DateTimeController + //auto now = dateTimeController.CurrentDateTime(); + int hours = dateTimeController.Hours(); + int minutes = dateTimeController.Minutes(); + int seconds = dateTimeController.Seconds(); + + // Log the BPM and current time + NRF_LOG_INFO("BPM: %d at %02d:%02d:%02d", rollingBpm, hours, minutes, seconds); + + // if (bpm == 0) { + // lv_label_set_text_static(label_hr, "---"); + // } else { + // lv_label_set_text_fmt(label_hr, "%03d", bpm); + // } } \ No newline at end of file diff --git a/src/displayapp/screens/SleepTracker.h b/src/displayapp/screens/SleepTracker.h index 748d2cdec5..ad387b5222 100644 --- a/src/displayapp/screens/SleepTracker.h +++ b/src/displayapp/screens/SleepTracker.h @@ -3,6 +3,8 @@ #include "displayapp/apps/Apps.h" #include "displayapp/screens/Screen.h" #include "displayapp/Controllers.h" +#include "systemtask/SystemTask.h" +#include "systemtask/WakeLock.h" #include "Symbols.h" namespace Pinetime { @@ -10,11 +12,27 @@ namespace Pinetime { namespace Screens { class SleepTracker : public Screen { public: - SleepTracker(); + SleepTracker(Controllers::HeartRateController& HeartRateController, Controllers::DateTime& DateTimeController, System::SystemTask& systemTask); ~SleepTracker() override; - private: + void Refresh() override; + void GetBPM(); + + + private: + Controllers::HeartRateController& heartRateController; + Controllers::DateTime& dateTimeController; + Pinetime::System::WakeLock wakeLock; + + int bpm = 0; + int prevBpm = 0; + int rollingBpm = 0; + + lv_obj_t* label_hr; + + lv_task_t* mainRefreshTask; + lv_task_t* hrRefreshTask; }; } @@ -23,7 +41,7 @@ namespace Pinetime { static constexpr Apps app = Apps::SleepTracker; static constexpr const char* icon = Screens::Symbols::bed; static Screens::Screen* Create(AppControllers& controllers) { - return new Screens::SleepTracker(); + return new Screens::SleepTracker(controllers.heartRateController, controllers.dateTimeController, *controllers.systemTask); } }; } From f19114da6793be8cee9247e64d25c73052de83be Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 3 Oct 2024 19:45:57 -0500 Subject: [PATCH 003/123] Started on data saving --- src/displayapp/screens/SleepTracker.cpp | 55 ++++++++++++++++++++++++- src/displayapp/screens/SleepTracker.h | 11 ++++- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/displayapp/screens/SleepTracker.cpp b/src/displayapp/screens/SleepTracker.cpp index 64e0425148..15c231f3b0 100644 --- a/src/displayapp/screens/SleepTracker.cpp +++ b/src/displayapp/screens/SleepTracker.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include using namespace Pinetime::Applications::Screens; @@ -16,8 +17,8 @@ namespace { } -SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController, Controllers::DateTime& dateTimeController, System::SystemTask& systemTask) - : heartRateController {heartRateController}, dateTimeController {dateTimeController}, wakeLock(systemTask) { +SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController, Controllers::DateTime& dateTimeController, Controllers::FS& fsController, System::SystemTask& systemTask) + : heartRateController {heartRateController}, dateTimeController {dateTimeController}, fsController {fsController}, wakeLock(systemTask) { wakeLock.Lock(); @@ -66,10 +67,60 @@ void SleepTracker::GetBPM() { // Log the BPM and current time NRF_LOG_INFO("BPM: %d at %02d:%02d:%02d", rollingBpm, hours, minutes, seconds); + // Write data to CSV + int motion = 0; // Placeholder for motion data + std::vector> data = {std::make_tuple(hours, minutes, seconds, rollingBpm, motion)}; + WriteDataCSV("SleepTracker_Data.csv", data); // if (bpm == 0) { // lv_label_set_text_static(label_hr, "---"); // } else { // lv_label_set_text_fmt(label_hr, "%03d", bpm); // } +} + +// File IO Stuff + +/* +* Write data to a CSV file +* Format: Time,BPM,Motion +*/ +void SleepTracker::WriteDataCSV(const char* fileName, const std::vector>& data) { + lfs_file_t file; + int err = fsController.FileOpen(&file, fileName, LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND); + if (err < 0) { + // Handle error + NRF_LOG_INFO("Error opening file: %d", err); + return; + } + + // Check if the file is empty + // int fileSize = fsController.FileSeek(&file, 0); + // if (fileSize == 0) { + // // Write header if file is empty + // const char* header = "Time,BPM,Motion\n"; + // err = fsController.FileWrite(&file, reinterpret_cast(header), strlen(header)); + // if (err < 0) { + // // Handle error + // NRF_LOG_INFO("Error writing to file: %d", err); + // fsController.FileClose(&file); + // return; + // } + // } + + // Write data + for (const auto& entry : data) { + int hours, minutes, seconds, bpm, motion; + std::tie(hours, minutes, seconds, bpm, motion) = entry; + char buffer[64]; + int len = snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d,%d,%d\n", hours, minutes, seconds, bpm, motion); + int err = fsController.FileWrite(&file, reinterpret_cast(buffer), len); + if (err < 0) { + // Handle error + NRF_LOG_INFO("Error writing to file: %d", err); + return; + } + } + + fsController.FileClose(&file); } \ No newline at end of file diff --git a/src/displayapp/screens/SleepTracker.h b/src/displayapp/screens/SleepTracker.h index ad387b5222..6f3bf2aba9 100644 --- a/src/displayapp/screens/SleepTracker.h +++ b/src/displayapp/screens/SleepTracker.h @@ -7,12 +7,14 @@ #include "systemtask/WakeLock.h" #include "Symbols.h" +#include + namespace Pinetime { namespace Applications { namespace Screens { class SleepTracker : public Screen { public: - SleepTracker(Controllers::HeartRateController& HeartRateController, Controllers::DateTime& DateTimeController, System::SystemTask& systemTask); + SleepTracker(Controllers::HeartRateController& HeartRateController, Controllers::DateTime& DateTimeController, Controllers::FS& fsController, System::SystemTask& systemTask); ~SleepTracker() override; void Refresh() override; @@ -23,8 +25,13 @@ namespace Pinetime { private: Controllers::HeartRateController& heartRateController; Controllers::DateTime& dateTimeController; + Controllers::FS& fsController; Pinetime::System::WakeLock wakeLock; + // For File IO + void WriteDataCSV(const char* fileName, const std::vector>& data); + std::vector> ReadDataCSV(const char* fileName); + int bpm = 0; int prevBpm = 0; int rollingBpm = 0; @@ -41,7 +48,7 @@ namespace Pinetime { static constexpr Apps app = Apps::SleepTracker; static constexpr const char* icon = Screens::Symbols::bed; static Screens::Screen* Create(AppControllers& controllers) { - return new Screens::SleepTracker(controllers.heartRateController, controllers.dateTimeController, *controllers.systemTask); + return new Screens::SleepTracker(controllers.heartRateController, controllers.dateTimeController, controllers.filesystem, *controllers.systemTask); } }; } From 0ec217d9eb3decb0a5e773a24fcca9300a041539 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 4 Oct 2024 13:43:39 -0500 Subject: [PATCH 004/123] Added basic data reading and clear data button --- src/displayapp/screens/SleepTracker.cpp | 87 ++++++++++++++++++++++++- src/displayapp/screens/SleepTracker.h | 2 + 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/displayapp/screens/SleepTracker.cpp b/src/displayapp/screens/SleepTracker.cpp index 15c231f3b0..018dc30957 100644 --- a/src/displayapp/screens/SleepTracker.cpp +++ b/src/displayapp/screens/SleepTracker.cpp @@ -6,6 +6,8 @@ #include #include +#include + using namespace Pinetime::Applications::Screens; namespace { @@ -15,6 +17,14 @@ namespace { screen->GetBPM(); } + void ClearDataCallback(lv_obj_t* btn, lv_event_t event) { + if (event == LV_EVENT_CLICKED) { + // Clear data + auto* screen = static_cast(lv_obj_get_user_data(btn)); + screen->ClearDataCSV("SleepTracker_Data.csv"); + } + } + } SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController, Controllers::DateTime& dateTimeController, Controllers::FS& fsController, System::SystemTask& systemTask) @@ -23,7 +33,7 @@ SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController wakeLock.Lock(); lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_static(title, "My test application"); + lv_label_set_text_static(title, "Sleep Tracker"); lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); lv_obj_align(title, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); @@ -33,6 +43,23 @@ SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController // Create the refresh task mainRefreshTask = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this); hrRefreshTask = lv_task_create(BpmDataCallback, 3000, LV_TASK_PRIO_MID, this); + + // Create the clear data button + lv_obj_t* btn = lv_btn_create(lv_scr_act(), nullptr); + lv_obj_set_event_cb(btn, ClearDataCallback); + lv_obj_set_user_data(btn, this); + lv_obj_align(btn, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, -10); + + lv_obj_t* label = lv_label_create(btn, nullptr); + lv_label_set_text(label, "X"); + + std::vector> data = ReadDataCSV("SleepTracker_Data.csv"); + for (const auto& entry : data) { + int hours, minutes, seconds, bpm, motion; + std::tie(hours, minutes, seconds, bpm, motion) = entry; + NRF_LOG_INFO("Read data: %02d:%02d:%02d, %d, %d", hours, minutes, seconds, bpm, motion); + } + NRF_LOG_INFO("-------------------------------"); } SleepTracker::~SleepTracker() { @@ -123,4 +150,62 @@ void SleepTracker::WriteDataCSV(const char* fileName, const std::vector> SleepTracker::ReadDataCSV(const char* filename) { + lfs_file_t file; + int err = fsController.FileOpen(&file, filename, LFS_O_RDONLY); + if (err < 0) { + // Handle error + NRF_LOG_INFO("Error opening file: %d", err); + return {}; + } + + std::vector> data; + char buffer[128]; + int bytesRead; + + // Skip header + // bytesRead = fsController.FileRead(&file, reinterpret_cast(buffer), sizeof(buffer)); + // std::istringstream headerStream(buffer); + // std::string headerLine; + // std::getline(headerStream, headerLine); + + // Read data + while ((bytesRead = fsController.FileRead(&file, reinterpret_cast(buffer), sizeof(buffer))) > 0) { + std::istringstream dataStream(buffer); + std::string line; + while (std::getline(dataStream, line)) { + int hours, minutes, seconds, bpm, motion; + char colon1, colon2, comma1, comma2; + std::istringstream lineStream(line); + if (lineStream >> hours >> colon1 >> minutes >> colon2 >> seconds >> comma1 >> bpm >> comma2 >> motion) { + if (colon1 == ':' && colon2 == ':' && comma1 == ',' && comma2 == ',') { + data.emplace_back(hours, minutes, seconds, bpm, motion); + } else { + NRF_LOG_INFO("Parsing error: incorrect format in line: %s", line.c_str()); + } + } else { + NRF_LOG_INFO("Parsing error: failed to parse line: %s", line.c_str()); + } + } + } + + fsController.FileClose(&file); + return data; +} + +// Clear data in CSV +void SleepTracker::ClearDataCSV(const char* filename) { + lfs_file_t file; + int err = fsController.FileOpen(&file, filename, LFS_O_WRONLY | LFS_O_TRUNC); + if (err < 0) { + // Handle error + NRF_LOG_INFO("Error opening file: %d", err); + return; + } + + fsController.FileClose(&file); + NRF_LOG_INFO("CSV data cleared"); } \ No newline at end of file diff --git a/src/displayapp/screens/SleepTracker.h b/src/displayapp/screens/SleepTracker.h index 6f3bf2aba9..e2f75fb3fd 100644 --- a/src/displayapp/screens/SleepTracker.h +++ b/src/displayapp/screens/SleepTracker.h @@ -21,6 +21,8 @@ namespace Pinetime { void GetBPM(); + void ClearDataCSV(const char* filename); + private: Controllers::HeartRateController& heartRateController; From 3936aaedd1f1af63911fb9f384ce6e7f5dda5404 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 4 Oct 2024 23:56:53 -0500 Subject: [PATCH 005/123] Added functions for sleeptracking time detection. (First night of testing) --- src/displayapp/screens/SleepTracker.cpp | 157 ++++++++++++++++++++++-- src/displayapp/screens/SleepTracker.h | 14 ++- 2 files changed, 163 insertions(+), 8 deletions(-) diff --git a/src/displayapp/screens/SleepTracker.cpp b/src/displayapp/screens/SleepTracker.cpp index 018dc30957..bcbf410ff6 100644 --- a/src/displayapp/screens/SleepTracker.cpp +++ b/src/displayapp/screens/SleepTracker.cpp @@ -25,12 +25,23 @@ namespace { } } + void GetSleepInfoCallback(lv_obj_t* btn, lv_event_t event) { + if (event == LV_EVENT_CLICKED) { + // Get sleep info + auto* screen = static_cast(lv_obj_get_user_data(btn)); + screen->GetSleepInfo(screen->ReadDataCSV("SleepTracker_Data.csv")); + } + } + } SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController, Controllers::DateTime& dateTimeController, Controllers::FS& fsController, System::SystemTask& systemTask) : heartRateController {heartRateController}, dateTimeController {dateTimeController}, fsController {fsController}, wakeLock(systemTask) { wakeLock.Lock(); + + static constexpr uint8_t btnWidth = 115; + static constexpr uint8_t btnHeight = 80; lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(title, "Sleep Tracker"); @@ -45,13 +56,24 @@ SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController hrRefreshTask = lv_task_create(BpmDataCallback, 3000, LV_TASK_PRIO_MID, this); // Create the clear data button - lv_obj_t* btn = lv_btn_create(lv_scr_act(), nullptr); - lv_obj_set_event_cb(btn, ClearDataCallback); - lv_obj_set_user_data(btn, this); - lv_obj_align(btn, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, -10); + lv_obj_t* btnClear = lv_btn_create(lv_scr_act(), nullptr); + btnClear->user_data = this; + lv_obj_set_event_cb(btnClear, ClearDataCallback); + lv_obj_set_size(btnClear, btnWidth, btnHeight); + lv_obj_align(btnClear, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); + lv_obj_t* txtClear = lv_label_create(btnClear, nullptr); + lv_label_set_text(txtClear, "X"); + + // Create the get info button + lv_obj_t* btnInfo = lv_btn_create(lv_scr_act(), nullptr); + btnInfo->user_data = this; + lv_obj_set_event_cb(btnInfo, GetSleepInfoCallback); + lv_obj_set_size(btnInfo, btnWidth, btnHeight); + lv_obj_align(btnInfo, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + lv_obj_t* txtInfo = lv_label_create(btnInfo, nullptr); + lv_label_set_text(txtInfo, "?"); + - lv_obj_t* label = lv_label_create(btn, nullptr); - lv_label_set_text(label, "X"); std::vector> data = ReadDataCSV("SleepTracker_Data.csv"); for (const auto& entry : data) { @@ -75,6 +97,127 @@ void SleepTracker::Refresh() { // Get the current heart rate } +// Convert time to minutes +double SleepTracker::ConvertToMinutes(int hours, int minutes, int seconds) { + return hours * 60 + minutes + seconds / 60.0; +} + +// Get the moving average of BPM Values +std::vector SleepTracker::MovingAverage(const std::vector& bpmData, int windowSize) { + std::vector smoothedBpm; + + int n = bpmData.size(); + + for (int i = 0; i < n - windowSize + 1; ++i) { + double sum = 0; + for (int j = 0; j < windowSize; ++j) { + sum += bpmData[i + j]; + } + smoothedBpm.push_back(sum / windowSize); + } + + return smoothedBpm; +} + +// Detect the sleep regions +std::vector> SleepTracker::DetectSleepRegions(const std::vector& bpmData, const std::vector& time, double threshold) { + std::vector> sleep_regions; + double start_time = -1; + bool in_sleep = false; + + for (int i = 0; i < bpmData.size(); ++i) { + if (bpmData[i] < threshold) { + if (!in_sleep) { + start_time = time[i]; // Mark the start of sleep + in_sleep = true; + } + } else { + if (in_sleep) { + double end_time = time[i]; // Mark the end of sleep + sleep_regions.push_back({start_time, end_time}); + in_sleep = false; + } + } + } + + // In case the last region extends to the end of the data + if (in_sleep) { + sleep_regions.push_back({start_time, time.back()}); + } + + return sleep_regions; +} + +// Get Sleep Info +void SleepTracker::GetSleepInfo(std::vector> data) { + std::vector time; + std::vector bpm; + + // Extract the time (in minutes) and bpm from the data + for (const auto& entry : data) { + int hours, minutes, seconds, bpm_value, motion; + std::tie(hours, minutes, seconds, bpm_value, motion) = entry; + time.push_back(ConvertToMinutes(hours, minutes, seconds)); + bpm.push_back(bpm_value); + } + + // Compute the moving average with a window size of 5 (15 minutes smoothing, since each data point is 3 minutes) + std::vector smoothed_bpm = MovingAverage(bpm, 5); + + // Calculate a threshold as 80% of the average BPM + double average_bpm = std::accumulate(bpm.begin(), bpm.end(), 0.0) / bpm.size(); + double threshold = average_bpm * 0.8; + + // Detect multiple sleep regions + std::vector> sleep_regions = DetectSleepRegions(smoothed_bpm, time, threshold); + + // Output sleep regions + if (!sleep_regions.empty()) { + for (const auto& region : sleep_regions) { + NRF_LOG_INFO("Sleep detected from %.2f minutes to %.2f minutes.", region.first, region.second); + } + } else { + NRF_LOG_INFO("No significant sleep regions detected."); + } + + // Open the output file + lfs_file_t file; + int err = fsController.FileOpen(&file, "SleepTracker_SleepInfo.csv", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC); + if (err < 0) { + // Handle error + NRF_LOG_INFO("Error opening file: %d", err); + return; + } + + // Write sleep regions to the file + if (!sleep_regions.empty()) { + for (const auto& region : sleep_regions) { + char buffer[64]; + int len = snprintf(buffer, sizeof(buffer), "Sleep detected from %.2f minutes to %.2f minutes.\n", region.first, region.second); + err = fsController.FileWrite(&file, reinterpret_cast(buffer), len); + if (err < 0) { + // Handle error + NRF_LOG_INFO("Error writing to file: %d", err); + fsController.FileClose(&file); + return; + } + } + } else { + const char* noSleepMsg = "No significant sleep regions detected.\n"; + err = fsController.FileWrite(&file, reinterpret_cast(noSleepMsg), strlen(noSleepMsg)); + if (err < 0) { + // Handle error + NRF_LOG_INFO("Error writing to file: %d", err); + fsController.FileClose(&file); + return; + } + } + + // Close the file + fsController.FileClose(&file); + NRF_LOG_INFO("Sleep info written to SleepTracker_SleepInfo.csv"); +} + void SleepTracker::GetBPM() { // Get the heart rate from the controller prevBpm = bpm; @@ -96,7 +239,7 @@ void SleepTracker::GetBPM() { // Write data to CSV int motion = 0; // Placeholder for motion data - std::vector> data = {std::make_tuple(hours, minutes, seconds, rollingBpm, motion)}; + std::vector> data = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; WriteDataCSV("SleepTracker_Data.csv", data); // if (bpm == 0) { diff --git a/src/displayapp/screens/SleepTracker.h b/src/displayapp/screens/SleepTracker.h index e2f75fb3fd..76861833c8 100644 --- a/src/displayapp/screens/SleepTracker.h +++ b/src/displayapp/screens/SleepTracker.h @@ -8,6 +8,8 @@ #include "Symbols.h" #include +#include // for accumulate +#include // for abs namespace Pinetime { namespace Applications { @@ -23,6 +25,17 @@ namespace Pinetime { void ClearDataCSV(const char* filename); + // Data Processing functions + double ConvertToMinutes(int hours, int minutes, int seconds); + // Get the moving average of BPM Values + std::vector MovingAverage(const std::vector& bpm, int windowSize); + // Detect the sleep regions + std::vector> DetectSleepRegions(const std::vector& bpmData, const std::vector& time, double threshold); + // Get the sleep info + void GetSleepInfo(std::vector> data); + + // Read IO + std::vector> ReadDataCSV(const char* fileName); private: Controllers::HeartRateController& heartRateController; @@ -32,7 +45,6 @@ namespace Pinetime { // For File IO void WriteDataCSV(const char* fileName, const std::vector>& data); - std::vector> ReadDataCSV(const char* fileName); int bpm = 0; int prevBpm = 0; From e7160ffde44fa9a69e612cac84c978cde12c9fea Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 5 Oct 2024 13:30:53 -0500 Subject: [PATCH 006/123] More changes tyo get the app on the watch --- src/CMakeLists.txt | 2 ++ src/displayapp/apps/CMakeLists.txt | 12 ++++++------ src/displayapp/screens/SleepTracker.cpp | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5cd2e656a4..34ab5e321c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -396,6 +396,7 @@ list(APPEND SOURCE_FILES displayapp/screens/PassKey.cpp displayapp/screens/Error.cpp displayapp/screens/Alarm.cpp + displayapp/screens/SleepTracker.cpp displayapp/screens/Styles.cpp displayapp/screens/WeatherSymbols.cpp displayapp/Colors.cpp @@ -615,6 +616,7 @@ set(INCLUDE_FILES displayapp/screens/Timer.h displayapp/screens/Dice.h displayapp/screens/Alarm.h + displayapp/screens/SleepTracker.h displayapp/Colors.h displayapp/widgets/Counter.h displayapp/widgets/PageIndicator.h diff --git a/src/displayapp/apps/CMakeLists.txt b/src/displayapp/apps/CMakeLists.txt index 5cad71053f..dca62123c1 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -6,18 +6,18 @@ else () set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Timer") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Steps") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::HeartRate") - set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Music") - set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paint") - set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paddle") + #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Music") + #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paint") + #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paddle") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Twos") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Dice") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Metronome") - set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Navigation") + #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Navigation") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Calculator") - set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Weather") + #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Weather") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::SleepTracker") #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Motion") set(USERAPP_TYPES "${DEFAULT_USER_APP_TYPES}" CACHE STRING "List of user apps to build into the firmware") - set(USERAPP_TYPES "${USERAPP_TYPES}, Apps::SleepTracker") endif () if(DEFINED ENABLE_WATCHFACES) diff --git a/src/displayapp/screens/SleepTracker.cpp b/src/displayapp/screens/SleepTracker.cpp index bcbf410ff6..dbbff8f5dc 100644 --- a/src/displayapp/screens/SleepTracker.cpp +++ b/src/displayapp/screens/SleepTracker.cpp @@ -53,7 +53,7 @@ SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController // Create the refresh task mainRefreshTask = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this); - hrRefreshTask = lv_task_create(BpmDataCallback, 3000, LV_TASK_PRIO_MID, this); + hrRefreshTask = lv_task_create(BpmDataCallback, 180000, LV_TASK_PRIO_MID, this); // Create the clear data button lv_obj_t* btnClear = lv_btn_create(lv_scr_act(), nullptr); @@ -125,7 +125,7 @@ std::vector> SleepTracker::DetectSleepRegions(const st double start_time = -1; bool in_sleep = false; - for (int i = 0; i < bpmData.size(); ++i) { + for (unsigned int i = 0; i < bpmData.size(); ++i) { if (bpmData[i] < threshold) { if (!in_sleep) { start_time = time[i]; // Mark the start of sleep From 3cf99215b4d41fdf3879d448318088bba59125b2 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 6 Oct 2024 09:19:40 -0500 Subject: [PATCH 007/123] trying to decrease flash and ram size --- src/CMakeLists.txt | 10 +- src/FreeRTOSConfig.h | 1 + src/displayapp/DisplayApp.cpp | 4 +- src/displayapp/apps/Apps.h.in | 4 +- src/displayapp/apps/CMakeLists.txt | 2 +- src/displayapp/screens/SleepTracker.cpp | 148 ++++++++++-------------- src/displayapp/screens/SleepTracker.h | 14 +-- 7 files changed, 77 insertions(+), 106 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 34ab5e321c..549dac89dd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -367,7 +367,7 @@ list(APPEND SOURCE_FILES displayapp/screens/Screen.cpp displayapp/screens/Tile.cpp displayapp/screens/InfiniPaint.cpp - displayapp/screens/Paddle.cpp + #displayapp/screens/Paddle.cpp displayapp/screens/StopWatch.cpp displayapp/screens/BatteryIcon.cpp displayapp/screens/BleIcon.cpp @@ -376,7 +376,7 @@ list(APPEND SOURCE_FILES displayapp/screens/Label.cpp displayapp/screens/FirmwareUpdate.cpp displayapp/screens/Music.cpp - displayapp/screens/Navigation.cpp + #displayapp/screens/Navigation.cpp displayapp/screens/Metronome.cpp displayapp/screens/Motion.cpp displayapp/screens/Weather.cpp @@ -458,7 +458,7 @@ list(APPEND SOURCE_FILES components/ble/AlertNotificationService.cpp components/ble/MusicService.cpp components/ble/SimpleWeatherService.cpp - components/ble/NavigationService.cpp + #components/ble/NavigationService.cpp components/ble/BatteryInformationService.cpp components/ble/FSService.cpp components/ble/ImmediateAlertService.cpp @@ -532,7 +532,7 @@ list(APPEND RECOVERY_SOURCE_FILES components/ble/FSService.cpp components/ble/ImmediateAlertService.cpp components/ble/ServiceDiscovery.cpp - components/ble/NavigationService.cpp + #components/ble/NavigationService.cpp components/ble/HeartRateService.cpp components/ble/MotionService.cpp components/firmwarevalidator/FirmwareValidator.cpp @@ -597,7 +597,7 @@ set(INCLUDE_FILES displayapp/screens/Tile.h displayapp/screens/InfiniPaint.h displayapp/screens/StopWatch.h - displayapp/screens/Paddle.h + #displayapp/screens/Paddle.h displayapp/screens/BatteryIcon.h displayapp/screens/BleIcon.h displayapp/screens/NotificationIcon.h diff --git a/src/FreeRTOSConfig.h b/src/FreeRTOSConfig.h index fce5005485..08336302ee 100644 --- a/src/FreeRTOSConfig.h +++ b/src/FreeRTOSConfig.h @@ -62,6 +62,7 @@ #define configTICK_RATE_HZ 1024 #define configMAX_PRIORITIES (3) #define configMINIMAL_STACK_SIZE (120) +#define configTOTAL_HEAP_SIZE (1024 * 30) #define configMAX_TASK_NAME_LEN (4) #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 8232aaf762..81fa79749f 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -14,11 +14,11 @@ #include "displayapp/screens/FirmwareUpdate.h" #include "displayapp/screens/FirmwareValidation.h" #include "displayapp/screens/InfiniPaint.h" -#include "displayapp/screens/Paddle.h" +//#include "displayapp/screens/Paddle.h" #include "displayapp/screens/StopWatch.h" #include "displayapp/screens/Metronome.h" #include "displayapp/screens/Music.h" -#include "displayapp/screens/Navigation.h" +//#include "displayapp/screens/Navigation.h" #include "displayapp/screens/Notifications.h" #include "displayapp/screens/SystemInfo.h" #include "displayapp/screens/Tile.h" diff --git a/src/displayapp/apps/Apps.h.in b/src/displayapp/apps/Apps.h.in index 70510c9a28..c1f90cc20d 100644 --- a/src/displayapp/apps/Apps.h.in +++ b/src/displayapp/apps/Apps.h.in @@ -19,11 +19,11 @@ namespace Pinetime { BatteryInfo, Music, Paint, - Paddle, + //Paddle, Twos, HeartRate, SleepTracker, - Navigation, + //Navigation, StopWatch, Metronome, Motion, diff --git a/src/displayapp/apps/CMakeLists.txt b/src/displayapp/apps/CMakeLists.txt index dca62123c1..dc26a4285c 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -24,7 +24,7 @@ if(DEFINED ENABLE_WATCHFACES) set(WATCHFACE_TYPES ${ENABLE_WATCHFACES} CACHE STRING "List of watch faces to build into the firmware") else() set(DEFAULT_WATCHFACE_TYPES "WatchFace::Digital") - set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Analog") + #set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Analog") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::PineTimeStyle") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Terminal") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Infineat") diff --git a/src/displayapp/screens/SleepTracker.cpp b/src/displayapp/screens/SleepTracker.cpp index dbbff8f5dc..412db8275f 100644 --- a/src/displayapp/screens/SleepTracker.cpp +++ b/src/displayapp/screens/SleepTracker.cpp @@ -7,6 +7,7 @@ #include #include +#include using namespace Pinetime::Applications::Screens; @@ -19,7 +20,6 @@ namespace { void ClearDataCallback(lv_obj_t* btn, lv_event_t event) { if (event == LV_EVENT_CLICKED) { - // Clear data auto* screen = static_cast(lv_obj_get_user_data(btn)); screen->ClearDataCSV("SleepTracker_Data.csv"); } @@ -27,7 +27,6 @@ namespace { void GetSleepInfoCallback(lv_obj_t* btn, lv_event_t event) { if (event == LV_EVENT_CLICKED) { - // Get sleep info auto* screen = static_cast(lv_obj_get_user_data(btn)); screen->GetSleepInfo(screen->ReadDataCSV("SleepTracker_Data.csv")); } @@ -40,8 +39,8 @@ SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController wakeLock.Lock(); - static constexpr uint8_t btnWidth = 115; - static constexpr uint8_t btnHeight = 80; + constexpr uint8_t btnWidth = 115; + constexpr uint8_t btnHeight = 80; lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(title, "Sleep Tracker"); @@ -73,9 +72,7 @@ SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController lv_obj_t* txtInfo = lv_label_create(btnInfo, nullptr); lv_label_set_text(txtInfo, "?"); - - - std::vector> data = ReadDataCSV("SleepTracker_Data.csv"); + const auto data = ReadDataCSV("SleepTracker_Data.csv"); for (const auto& entry : data) { int hours, minutes, seconds, bpm, motion; std::tie(hours, minutes, seconds, bpm, motion) = entry; @@ -98,86 +95,85 @@ void SleepTracker::Refresh() { } // Convert time to minutes -double SleepTracker::ConvertToMinutes(int hours, int minutes, int seconds) { - return hours * 60 + minutes + seconds / 60.0; +float SleepTracker::ConvertToMinutes(int hours, int minutes, int seconds) const { + return hours * 60 + minutes + seconds / 60.0f; } // Get the moving average of BPM Values -std::vector SleepTracker::MovingAverage(const std::vector& bpmData, int windowSize) { - std::vector smoothedBpm; - - int n = bpmData.size(); +std::vector SleepTracker::MovingAverage(const std::vector& bpmData, int windowSize) const { + std::vector smoothedBpm; + const int n = bpmData.size(); - for (int i = 0; i < n - windowSize + 1; ++i) { - double sum = 0; - for (int j = 0; j < windowSize; ++j) { - sum += bpmData[i + j]; - } - smoothedBpm.push_back(sum / windowSize); + for (int i = 0; i < n - windowSize + 1; ++i) { + float sum = 0; + for (int j = 0; j < windowSize; ++j) { + sum += bpmData[i + j]; } + smoothedBpm.push_back(sum / windowSize); + } - return smoothedBpm; + return smoothedBpm; } // Detect the sleep regions -std::vector> SleepTracker::DetectSleepRegions(const std::vector& bpmData, const std::vector& time, double threshold) { - std::vector> sleep_regions; - double start_time = -1; - bool in_sleep = false; +std::vector> SleepTracker::DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const { + std::vector> sleep_regions; + float start_time = -1; + bool in_sleep = false; - for (unsigned int i = 0; i < bpmData.size(); ++i) { - if (bpmData[i] < threshold) { - if (!in_sleep) { - start_time = time[i]; // Mark the start of sleep - in_sleep = true; - } - } else { - if (in_sleep) { - double end_time = time[i]; // Mark the end of sleep - sleep_regions.push_back({start_time, end_time}); - in_sleep = false; - } - } + for (size_t i = 0; i < bpmData.size(); ++i) { + if (bpmData[i] < threshold) { + if (!in_sleep) { + start_time = time[i]; // Mark the start of sleep + in_sleep = true; + } + } else { + if (in_sleep) { + float end_time = time[i]; // Mark the end of sleep + sleep_regions.emplace_back(start_time, end_time); + in_sleep = false; + } } + } - // In case the last region extends to the end of the data - if (in_sleep) { - sleep_regions.push_back({start_time, time.back()}); - } + // In case the last region extends to the end of the data + if (in_sleep) { + sleep_regions.emplace_back(start_time, time.back()); + } - return sleep_regions; + return sleep_regions; } // Get Sleep Info -void SleepTracker::GetSleepInfo(std::vector> data) { - std::vector time; +void SleepTracker::GetSleepInfo(const std::vector>& data) const { + std::vector time; std::vector bpm; // Extract the time (in minutes) and bpm from the data for (const auto& entry : data) { - int hours, minutes, seconds, bpm_value, motion; - std::tie(hours, minutes, seconds, bpm_value, motion) = entry; - time.push_back(ConvertToMinutes(hours, minutes, seconds)); - bpm.push_back(bpm_value); + int hours, minutes, seconds, bpm_value, motion; + std::tie(hours, minutes, seconds, bpm_value, motion) = entry; + time.push_back(ConvertToMinutes(hours, minutes, seconds)); + bpm.push_back(bpm_value); } // Compute the moving average with a window size of 5 (15 minutes smoothing, since each data point is 3 minutes) - std::vector smoothed_bpm = MovingAverage(bpm, 5); + const auto smoothed_bpm = MovingAverage(bpm, 5); // Calculate a threshold as 80% of the average BPM - double average_bpm = std::accumulate(bpm.begin(), bpm.end(), 0.0) / bpm.size(); - double threshold = average_bpm * 0.8; + const float average_bpm = std::accumulate(bpm.begin(), bpm.end(), 0.0f) / bpm.size(); + const float threshold = average_bpm * 0.8f; // Detect multiple sleep regions - std::vector> sleep_regions = DetectSleepRegions(smoothed_bpm, time, threshold); + const auto sleep_regions = DetectSleepRegions(smoothed_bpm, time, threshold); // Output sleep regions if (!sleep_regions.empty()) { - for (const auto& region : sleep_regions) { - NRF_LOG_INFO("Sleep detected from %.2f minutes to %.2f minutes.", region.first, region.second); - } + for (const auto& region : sleep_regions) { + NRF_LOG_INFO("Sleep detected from %.2f minutes to %.2f minutes.", region.first, region.second); + } } else { - NRF_LOG_INFO("No significant sleep regions detected."); + NRF_LOG_INFO("No significant sleep regions detected."); } // Open the output file @@ -229,7 +225,6 @@ void SleepTracker::GetBPM() { rollingBpm = bpm; // Get the current time from DateTimeController - //auto now = dateTimeController.CurrentDateTime(); int hours = dateTimeController.Hours(); int minutes = dateTimeController.Minutes(); int seconds = dateTimeController.Seconds(); @@ -238,15 +233,9 @@ void SleepTracker::GetBPM() { NRF_LOG_INFO("BPM: %d at %02d:%02d:%02d", rollingBpm, hours, minutes, seconds); // Write data to CSV - int motion = 0; // Placeholder for motion data - std::vector> data = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; + const int motion = 0; // Placeholder for motion data + const std::vector> data = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; WriteDataCSV("SleepTracker_Data.csv", data); - - // if (bpm == 0) { - // lv_label_set_text_static(label_hr, "---"); - // } else { - // lv_label_set_text_fmt(label_hr, "%03d", bpm); - // } } // File IO Stuff @@ -255,7 +244,7 @@ void SleepTracker::GetBPM() { * Write data to a CSV file * Format: Time,BPM,Motion */ -void SleepTracker::WriteDataCSV(const char* fileName, const std::vector>& data) { +void SleepTracker::WriteDataCSV(const char* fileName, const std::vector>& data) const { lfs_file_t file; int err = fsController.FileOpen(&file, fileName, LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND); if (err < 0) { @@ -264,30 +253,17 @@ void SleepTracker::WriteDataCSV(const char* fileName, const std::vector(header), strlen(header)); - // if (err < 0) { - // // Handle error - // NRF_LOG_INFO("Error writing to file: %d", err); - // fsController.FileClose(&file); - // return; - // } - // } - // Write data for (const auto& entry : data) { int hours, minutes, seconds, bpm, motion; std::tie(hours, minutes, seconds, bpm, motion) = entry; char buffer[64]; int len = snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d,%d,%d\n", hours, minutes, seconds, bpm, motion); - int err = fsController.FileWrite(&file, reinterpret_cast(buffer), len); + err = fsController.FileWrite(&file, reinterpret_cast(buffer), len); if (err < 0) { // Handle error NRF_LOG_INFO("Error writing to file: %d", err); + fsController.FileClose(&file); return; } } @@ -296,7 +272,7 @@ void SleepTracker::WriteDataCSV(const char* fileName, const std::vector> SleepTracker::ReadDataCSV(const char* filename) { +std::vector> SleepTracker::ReadDataCSV(const char* filename) const { lfs_file_t file; int err = fsController.FileOpen(&file, filename, LFS_O_RDONLY); if (err < 0) { @@ -309,12 +285,6 @@ std::vector> SleepTracker::ReadDataCSV(const char buffer[128]; int bytesRead; - // Skip header - // bytesRead = fsController.FileRead(&file, reinterpret_cast(buffer), sizeof(buffer)); - // std::istringstream headerStream(buffer); - // std::string headerLine; - // std::getline(headerStream, headerLine); - // Read data while ((bytesRead = fsController.FileRead(&file, reinterpret_cast(buffer), sizeof(buffer))) > 0) { std::istringstream dataStream(buffer); @@ -340,7 +310,7 @@ std::vector> SleepTracker::ReadDataCSV(const } // Clear data in CSV -void SleepTracker::ClearDataCSV(const char* filename) { +void SleepTracker::ClearDataCSV(const char* filename) const { lfs_file_t file; int err = fsController.FileOpen(&file, filename, LFS_O_WRONLY | LFS_O_TRUNC); if (err < 0) { diff --git a/src/displayapp/screens/SleepTracker.h b/src/displayapp/screens/SleepTracker.h index 76861833c8..c120fa1932 100644 --- a/src/displayapp/screens/SleepTracker.h +++ b/src/displayapp/screens/SleepTracker.h @@ -23,19 +23,19 @@ namespace Pinetime { void GetBPM(); - void ClearDataCSV(const char* filename); + void ClearDataCSV(const char* filename) const; // Data Processing functions - double ConvertToMinutes(int hours, int minutes, int seconds); + float ConvertToMinutes(int hours, int minutes, int seconds) const; // Get the moving average of BPM Values - std::vector MovingAverage(const std::vector& bpm, int windowSize); + std::vector MovingAverage(const std::vector& bpm, int windowSize) const; // Detect the sleep regions - std::vector> DetectSleepRegions(const std::vector& bpmData, const std::vector& time, double threshold); + std::vector> DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const; // Get the sleep info - void GetSleepInfo(std::vector> data); + void GetSleepInfo(const std::vector>& data) const; // Read IO - std::vector> ReadDataCSV(const char* fileName); + std::vector> ReadDataCSV(const char* fileName) const; private: Controllers::HeartRateController& heartRateController; @@ -44,7 +44,7 @@ namespace Pinetime { Pinetime::System::WakeLock wakeLock; // For File IO - void WriteDataCSV(const char* fileName, const std::vector>& data); + void WriteDataCSV(const char* fileName, const std::vector>& data) const; int bpm = 0; int prevBpm = 0; From f1f80061e6a49a5097ad9acb52ff19ed302110e5 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 9 Oct 2024 12:36:05 -0500 Subject: [PATCH 008/123] Got rid of Nevigation & removed vectors and proccessing in SleepTracker --- src/FreeRTOSConfig.h | 2 +- src/components/ble/NimbleController.cpp | 2 +- src/components/ble/NimbleController.h | 10 +- src/displayapp/apps/CMakeLists.txt | 2 +- src/displayapp/screens/SleepTracker.cpp | 325 ++++++++++++------------ src/displayapp/screens/SleepTracker.h | 16 +- src/systemtask/SystemTask.cpp | 2 +- 7 files changed, 179 insertions(+), 180 deletions(-) diff --git a/src/FreeRTOSConfig.h b/src/FreeRTOSConfig.h index 08336302ee..d82b250abd 100644 --- a/src/FreeRTOSConfig.h +++ b/src/FreeRTOSConfig.h @@ -62,7 +62,7 @@ #define configTICK_RATE_HZ 1024 #define configMAX_PRIORITIES (3) #define configMINIMAL_STACK_SIZE (120) -#define configTOTAL_HEAP_SIZE (1024 * 30) +#define configTOTAL_HEAP_SIZE (1024 * 40) #define configMAX_TASK_NAME_LEN (4) #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 5059007ab9..046870c9aa 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -90,7 +90,7 @@ void NimbleController::Init() { currentTimeService.Init(); musicService.Init(); weatherService.Init(); - navService.Init(); + //navService.Init(); anService.Init(); dfuService.Init(); batteryInformationService.Init(); diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 597ef0cc34..0ea422ef31 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -18,7 +18,7 @@ #include "components/ble/HeartRateService.h" #include "components/ble/ImmediateAlertService.h" #include "components/ble/MusicService.h" -#include "components/ble/NavigationService.h" +//#include "components/ble/NavigationService.h" #include "components/ble/ServiceDiscovery.h" #include "components/ble/MotionService.h" #include "components/ble/SimpleWeatherService.h" @@ -59,9 +59,9 @@ namespace Pinetime { return musicService; }; - Pinetime::Controllers::NavigationService& navigation() { - return navService; - }; + // Pinetime::Controllers::NavigationService& navigation() { + // return navService; + // }; Pinetime::Controllers::AlertNotificationService& alertService() { return anService; @@ -100,7 +100,7 @@ namespace Pinetime { CurrentTimeService currentTimeService; MusicService musicService; SimpleWeatherService weatherService; - NavigationService navService; + //NavigationService navService; BatteryInformationService batteryInformationService; ImmediateAlertService immediateAlertService; HeartRateService heartRateService; diff --git a/src/displayapp/apps/CMakeLists.txt b/src/displayapp/apps/CMakeLists.txt index dc26a4285c..dca62123c1 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -24,7 +24,7 @@ if(DEFINED ENABLE_WATCHFACES) set(WATCHFACE_TYPES ${ENABLE_WATCHFACES} CACHE STRING "List of watch faces to build into the firmware") else() set(DEFAULT_WATCHFACE_TYPES "WatchFace::Digital") - #set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Analog") + set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Analog") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::PineTimeStyle") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Terminal") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Infineat") diff --git a/src/displayapp/screens/SleepTracker.cpp b/src/displayapp/screens/SleepTracker.cpp index 412db8275f..925381dd18 100644 --- a/src/displayapp/screens/SleepTracker.cpp +++ b/src/displayapp/screens/SleepTracker.cpp @@ -25,12 +25,12 @@ namespace { } } - void GetSleepInfoCallback(lv_obj_t* btn, lv_event_t event) { - if (event == LV_EVENT_CLICKED) { - auto* screen = static_cast(lv_obj_get_user_data(btn)); - screen->GetSleepInfo(screen->ReadDataCSV("SleepTracker_Data.csv")); - } - } + // void GetSleepInfoCallback(lv_obj_t* btn, lv_event_t event) { + // if (event == LV_EVENT_CLICKED) { + // auto* screen = static_cast(lv_obj_get_user_data(btn)); + // screen->GetSleepInfo(screen->ReadDataCSV("SleepTracker_Data.csv")); + // } + // } } @@ -64,21 +64,21 @@ SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController lv_label_set_text(txtClear, "X"); // Create the get info button - lv_obj_t* btnInfo = lv_btn_create(lv_scr_act(), nullptr); - btnInfo->user_data = this; - lv_obj_set_event_cb(btnInfo, GetSleepInfoCallback); - lv_obj_set_size(btnInfo, btnWidth, btnHeight); - lv_obj_align(btnInfo, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); - lv_obj_t* txtInfo = lv_label_create(btnInfo, nullptr); - lv_label_set_text(txtInfo, "?"); - - const auto data = ReadDataCSV("SleepTracker_Data.csv"); - for (const auto& entry : data) { - int hours, minutes, seconds, bpm, motion; - std::tie(hours, minutes, seconds, bpm, motion) = entry; - NRF_LOG_INFO("Read data: %02d:%02d:%02d, %d, %d", hours, minutes, seconds, bpm, motion); - } - NRF_LOG_INFO("-------------------------------"); + // lv_obj_t* btnInfo = lv_btn_create(lv_scr_act(), nullptr); + // btnInfo->user_data = this; + // lv_obj_set_event_cb(btnInfo, GetSleepInfoCallback); + // lv_obj_set_size(btnInfo, btnWidth, btnHeight); + // lv_obj_align(btnInfo, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + // lv_obj_t* txtInfo = lv_label_create(btnInfo, nullptr); + // lv_label_set_text(txtInfo, "?"); + + // const auto data = ReadDataCSV("SleepTracker_Data.csv"); + // for (const auto& entry : data) { + // int hours, minutes, seconds, bpm, motion; + // std::tie(hours, minutes, seconds, bpm, motion) = entry; + // NRF_LOG_INFO("Read data: %02d:%02d:%02d, %d, %d", hours, minutes, seconds, bpm, motion); + // } + // NRF_LOG_INFO("-------------------------------"); } SleepTracker::~SleepTracker() { @@ -100,119 +100,119 @@ float SleepTracker::ConvertToMinutes(int hours, int minutes, int seconds) const } // Get the moving average of BPM Values -std::vector SleepTracker::MovingAverage(const std::vector& bpmData, int windowSize) const { - std::vector smoothedBpm; - const int n = bpmData.size(); +// std::vector SleepTracker::MovingAverage(const std::vector& bpmData, int windowSize) const { +// std::vector smoothedBpm; +// const int n = bpmData.size(); - for (int i = 0; i < n - windowSize + 1; ++i) { - float sum = 0; - for (int j = 0; j < windowSize; ++j) { - sum += bpmData[i + j]; - } - smoothedBpm.push_back(sum / windowSize); - } +// for (int i = 0; i < n - windowSize + 1; ++i) { +// float sum = 0; +// for (int j = 0; j < windowSize; ++j) { +// sum += bpmData[i + j]; +// } +// smoothedBpm.push_back(sum / windowSize); +// } - return smoothedBpm; -} +// return smoothedBpm; +// } // Detect the sleep regions -std::vector> SleepTracker::DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const { - std::vector> sleep_regions; - float start_time = -1; - bool in_sleep = false; +// std::vector> SleepTracker::DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const { +// std::vector> sleep_regions; +// float start_time = -1; +// bool in_sleep = false; - for (size_t i = 0; i < bpmData.size(); ++i) { - if (bpmData[i] < threshold) { - if (!in_sleep) { - start_time = time[i]; // Mark the start of sleep - in_sleep = true; - } - } else { - if (in_sleep) { - float end_time = time[i]; // Mark the end of sleep - sleep_regions.emplace_back(start_time, end_time); - in_sleep = false; - } - } - } +// for (size_t i = 0; i < bpmData.size(); ++i) { +// if (bpmData[i] < threshold) { +// if (!in_sleep) { +// start_time = time[i]; // Mark the start of sleep +// in_sleep = true; +// } +// } else { +// if (in_sleep) { +// float end_time = time[i]; // Mark the end of sleep +// sleep_regions.emplace_back(start_time, end_time); +// in_sleep = false; +// } +// } +// } - // In case the last region extends to the end of the data - if (in_sleep) { - sleep_regions.emplace_back(start_time, time.back()); - } +// // In case the last region extends to the end of the data +// if (in_sleep) { +// sleep_regions.emplace_back(start_time, time.back()); +// } - return sleep_regions; -} +// return sleep_regions; +// } -// Get Sleep Info -void SleepTracker::GetSleepInfo(const std::vector>& data) const { - std::vector time; - std::vector bpm; +// // Get Sleep Info +// void SleepTracker::GetSleepInfo(const std::vector>& data) const { +// std::vector time; +// std::vector bpm; - // Extract the time (in minutes) and bpm from the data - for (const auto& entry : data) { - int hours, minutes, seconds, bpm_value, motion; - std::tie(hours, minutes, seconds, bpm_value, motion) = entry; - time.push_back(ConvertToMinutes(hours, minutes, seconds)); - bpm.push_back(bpm_value); - } +// // Extract the time (in minutes) and bpm from the data +// for (const auto& entry : data) { +// int hours, minutes, seconds, bpm_value, motion; +// std::tie(hours, minutes, seconds, bpm_value, motion) = entry; +// time.push_back(ConvertToMinutes(hours, minutes, seconds)); +// bpm.push_back(bpm_value); +// } - // Compute the moving average with a window size of 5 (15 minutes smoothing, since each data point is 3 minutes) - const auto smoothed_bpm = MovingAverage(bpm, 5); +// // Compute the moving average with a window size of 5 (15 minutes smoothing, since each data point is 3 minutes) +// const auto smoothed_bpm = MovingAverage(bpm, 5); - // Calculate a threshold as 80% of the average BPM - const float average_bpm = std::accumulate(bpm.begin(), bpm.end(), 0.0f) / bpm.size(); - const float threshold = average_bpm * 0.8f; +// // Calculate a threshold as 80% of the average BPM +// const float average_bpm = std::accumulate(bpm.begin(), bpm.end(), 0.0f) / bpm.size(); +// const float threshold = average_bpm * 0.8f; - // Detect multiple sleep regions - const auto sleep_regions = DetectSleepRegions(smoothed_bpm, time, threshold); +// // Detect multiple sleep regions +// const auto sleep_regions = DetectSleepRegions(smoothed_bpm, time, threshold); - // Output sleep regions - if (!sleep_regions.empty()) { - for (const auto& region : sleep_regions) { - NRF_LOG_INFO("Sleep detected from %.2f minutes to %.2f minutes.", region.first, region.second); - } - } else { - NRF_LOG_INFO("No significant sleep regions detected."); - } - - // Open the output file - lfs_file_t file; - int err = fsController.FileOpen(&file, "SleepTracker_SleepInfo.csv", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC); - if (err < 0) { - // Handle error - NRF_LOG_INFO("Error opening file: %d", err); - return; - } - - // Write sleep regions to the file - if (!sleep_regions.empty()) { - for (const auto& region : sleep_regions) { - char buffer[64]; - int len = snprintf(buffer, sizeof(buffer), "Sleep detected from %.2f minutes to %.2f minutes.\n", region.first, region.second); - err = fsController.FileWrite(&file, reinterpret_cast(buffer), len); - if (err < 0) { - // Handle error - NRF_LOG_INFO("Error writing to file: %d", err); - fsController.FileClose(&file); - return; - } - } - } else { - const char* noSleepMsg = "No significant sleep regions detected.\n"; - err = fsController.FileWrite(&file, reinterpret_cast(noSleepMsg), strlen(noSleepMsg)); - if (err < 0) { - // Handle error - NRF_LOG_INFO("Error writing to file: %d", err); - fsController.FileClose(&file); - return; - } - } - - // Close the file - fsController.FileClose(&file); - NRF_LOG_INFO("Sleep info written to SleepTracker_SleepInfo.csv"); -} +// // Output sleep regions +// if (!sleep_regions.empty()) { +// for (const auto& region : sleep_regions) { +// NRF_LOG_INFO("Sleep detected from %.2f minutes to %.2f minutes.", region.first, region.second); +// } +// } else { +// NRF_LOG_INFO("No significant sleep regions detected."); +// } + +// // Open the output file +// lfs_file_t file; +// int err = fsController.FileOpen(&file, "SleepTracker_SleepInfo.csv", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC); +// if (err < 0) { +// // Handle error +// NRF_LOG_INFO("Error opening file: %d", err); +// return; +// } + +// // Write sleep regions to the file +// if (!sleep_regions.empty()) { +// for (const auto& region : sleep_regions) { +// char buffer[64]; +// int len = snprintf(buffer, sizeof(buffer), "Sleep detected from %.2f minutes to %.2f minutes.\n", region.first, region.second); +// err = fsController.FileWrite(&file, reinterpret_cast(buffer), len); +// if (err < 0) { +// // Handle error +// NRF_LOG_INFO("Error writing to file: %d", err); +// fsController.FileClose(&file); +// return; +// } +// } +// } else { +// const char* noSleepMsg = "No significant sleep regions detected.\n"; +// err = fsController.FileWrite(&file, reinterpret_cast(noSleepMsg), strlen(noSleepMsg)); +// if (err < 0) { +// // Handle error +// NRF_LOG_INFO("Error writing to file: %d", err); +// fsController.FileClose(&file); +// return; +// } +// } + +// // Close the file +// fsController.FileClose(&file); +// NRF_LOG_INFO("Sleep info written to SleepTracker_SleepInfo.csv"); +// } void SleepTracker::GetBPM() { // Get the heart rate from the controller @@ -234,8 +234,8 @@ void SleepTracker::GetBPM() { // Write data to CSV const int motion = 0; // Placeholder for motion data - const std::vector> data = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; - WriteDataCSV("SleepTracker_Data.csv", data); + std::tuple data[1] = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; + WriteDataCSV("SleepTracker_Data.csv", data, 1); } // File IO Stuff @@ -244,7 +244,7 @@ void SleepTracker::GetBPM() { * Write data to a CSV file * Format: Time,BPM,Motion */ -void SleepTracker::WriteDataCSV(const char* fileName, const std::vector>& data) const { +void SleepTracker::WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const { lfs_file_t file; int err = fsController.FileOpen(&file, fileName, LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND); if (err < 0) { @@ -253,10 +253,9 @@ void SleepTracker::WriteDataCSV(const char* fileName, const std::vector(buffer), len); @@ -272,42 +271,42 @@ void SleepTracker::WriteDataCSV(const char* fileName, const std::vector> SleepTracker::ReadDataCSV(const char* filename) const { - lfs_file_t file; - int err = fsController.FileOpen(&file, filename, LFS_O_RDONLY); - if (err < 0) { - // Handle error - NRF_LOG_INFO("Error opening file: %d", err); - return {}; - } - - std::vector> data; - char buffer[128]; - int bytesRead; - - // Read data - while ((bytesRead = fsController.FileRead(&file, reinterpret_cast(buffer), sizeof(buffer))) > 0) { - std::istringstream dataStream(buffer); - std::string line; - while (std::getline(dataStream, line)) { - int hours, minutes, seconds, bpm, motion; - char colon1, colon2, comma1, comma2; - std::istringstream lineStream(line); - if (lineStream >> hours >> colon1 >> minutes >> colon2 >> seconds >> comma1 >> bpm >> comma2 >> motion) { - if (colon1 == ':' && colon2 == ':' && comma1 == ',' && comma2 == ',') { - data.emplace_back(hours, minutes, seconds, bpm, motion); - } else { - NRF_LOG_INFO("Parsing error: incorrect format in line: %s", line.c_str()); - } - } else { - NRF_LOG_INFO("Parsing error: failed to parse line: %s", line.c_str()); - } - } - } - - fsController.FileClose(&file); - return data; -} +// std::vector> SleepTracker::ReadDataCSV(const char* filename) const { +// lfs_file_t file; +// int err = fsController.FileOpen(&file, filename, LFS_O_RDONLY); +// if (err < 0) { +// // Handle error +// NRF_LOG_INFO("Error opening file: %d", err); +// return {}; +// } + +// std::vector> data; +// char buffer[128]; +// int bytesRead; + +// // Read data +// while ((bytesRead = fsController.FileRead(&file, reinterpret_cast(buffer), sizeof(buffer))) > 0) { +// std::istringstream dataStream(buffer); +// std::string line; +// while (std::getline(dataStream, line)) { +// int hours, minutes, seconds, bpm, motion; +// char colon1, colon2, comma1, comma2; +// std::istringstream lineStream(line); +// if (lineStream >> hours >> colon1 >> minutes >> colon2 >> seconds >> comma1 >> bpm >> comma2 >> motion) { +// if (colon1 == ':' && colon2 == ':' && comma1 == ',' && comma2 == ',') { +// data.emplace_back(hours, minutes, seconds, bpm, motion); +// } else { +// NRF_LOG_INFO("Parsing error: incorrect format in line: %s", line.c_str()); +// } +// } else { +// NRF_LOG_INFO("Parsing error: failed to parse line: %s", line.c_str()); +// } +// } +// } + +// fsController.FileClose(&file); +// return data; +// } // Clear data in CSV void SleepTracker::ClearDataCSV(const char* filename) const { diff --git a/src/displayapp/screens/SleepTracker.h b/src/displayapp/screens/SleepTracker.h index c120fa1932..11196fb3a4 100644 --- a/src/displayapp/screens/SleepTracker.h +++ b/src/displayapp/screens/SleepTracker.h @@ -7,9 +7,9 @@ #include "systemtask/WakeLock.h" #include "Symbols.h" -#include -#include // for accumulate -#include // for abs +//#include +//#include // for accumulate +//#include // for abs namespace Pinetime { namespace Applications { @@ -28,14 +28,14 @@ namespace Pinetime { // Data Processing functions float ConvertToMinutes(int hours, int minutes, int seconds) const; // Get the moving average of BPM Values - std::vector MovingAverage(const std::vector& bpm, int windowSize) const; + //std::vector MovingAverage(const std::vector& bpm, int windowSize) const; // Detect the sleep regions - std::vector> DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const; + //std::vector> DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const; // Get the sleep info - void GetSleepInfo(const std::vector>& data) const; + //void GetSleepInfo(const std::vector>& data) const; // Read IO - std::vector> ReadDataCSV(const char* fileName) const; + //std::vector> ReadDataCSV(const char* fileName) const; private: Controllers::HeartRateController& heartRateController; @@ -44,7 +44,7 @@ namespace Pinetime { Pinetime::System::WakeLock wakeLock; // For File IO - void WriteDataCSV(const char* fileName, const std::vector>& data) const; + void WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const; int bpm = 0; int prevBpm = 0; diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 8e0435e372..16a4a03812 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -140,7 +140,7 @@ void SystemTask::Work() { displayApp.Register(this); displayApp.Register(&nimbleController.weather()); displayApp.Register(&nimbleController.music()); - displayApp.Register(&nimbleController.navigation()); + //displayApp.Register(&nimbleController.navigation()); displayApp.Start(bootError); heartRateSensor.Init(); From 4c6b06824ceacf877bed8a86e0f120e9755e2621 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 9 Oct 2024 13:46:07 -0500 Subject: [PATCH 009/123] Put Navigation back for Sim to work, decreased bpm log interval for debugging --- src/CMakeLists.txt | 8 ++++---- src/components/ble/NimbleController.cpp | 2 +- src/components/ble/NimbleController.h | 10 +++++----- src/displayapp/DisplayApp.cpp | 4 ++-- src/displayapp/apps/Apps.h.in | 4 ++-- src/displayapp/screens/SleepTracker.cpp | 3 ++- src/systemtask/SystemTask.cpp | 2 +- 7 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 549dac89dd..82b2f21d0f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -367,7 +367,7 @@ list(APPEND SOURCE_FILES displayapp/screens/Screen.cpp displayapp/screens/Tile.cpp displayapp/screens/InfiniPaint.cpp - #displayapp/screens/Paddle.cpp + displayapp/screens/Paddle.cpp displayapp/screens/StopWatch.cpp displayapp/screens/BatteryIcon.cpp displayapp/screens/BleIcon.cpp @@ -376,7 +376,7 @@ list(APPEND SOURCE_FILES displayapp/screens/Label.cpp displayapp/screens/FirmwareUpdate.cpp displayapp/screens/Music.cpp - #displayapp/screens/Navigation.cpp + displayapp/screens/Navigation.cpp displayapp/screens/Metronome.cpp displayapp/screens/Motion.cpp displayapp/screens/Weather.cpp @@ -458,7 +458,7 @@ list(APPEND SOURCE_FILES components/ble/AlertNotificationService.cpp components/ble/MusicService.cpp components/ble/SimpleWeatherService.cpp - #components/ble/NavigationService.cpp + components/ble/NavigationService.cpp components/ble/BatteryInformationService.cpp components/ble/FSService.cpp components/ble/ImmediateAlertService.cpp @@ -597,7 +597,7 @@ set(INCLUDE_FILES displayapp/screens/Tile.h displayapp/screens/InfiniPaint.h displayapp/screens/StopWatch.h - #displayapp/screens/Paddle.h + displayapp/screens/Paddle.h displayapp/screens/BatteryIcon.h displayapp/screens/BleIcon.h displayapp/screens/NotificationIcon.h diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 046870c9aa..5059007ab9 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -90,7 +90,7 @@ void NimbleController::Init() { currentTimeService.Init(); musicService.Init(); weatherService.Init(); - //navService.Init(); + navService.Init(); anService.Init(); dfuService.Init(); batteryInformationService.Init(); diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 0ea422ef31..597ef0cc34 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -18,7 +18,7 @@ #include "components/ble/HeartRateService.h" #include "components/ble/ImmediateAlertService.h" #include "components/ble/MusicService.h" -//#include "components/ble/NavigationService.h" +#include "components/ble/NavigationService.h" #include "components/ble/ServiceDiscovery.h" #include "components/ble/MotionService.h" #include "components/ble/SimpleWeatherService.h" @@ -59,9 +59,9 @@ namespace Pinetime { return musicService; }; - // Pinetime::Controllers::NavigationService& navigation() { - // return navService; - // }; + Pinetime::Controllers::NavigationService& navigation() { + return navService; + }; Pinetime::Controllers::AlertNotificationService& alertService() { return anService; @@ -100,7 +100,7 @@ namespace Pinetime { CurrentTimeService currentTimeService; MusicService musicService; SimpleWeatherService weatherService; - //NavigationService navService; + NavigationService navService; BatteryInformationService batteryInformationService; ImmediateAlertService immediateAlertService; HeartRateService heartRateService; diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 81fa79749f..8232aaf762 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -14,11 +14,11 @@ #include "displayapp/screens/FirmwareUpdate.h" #include "displayapp/screens/FirmwareValidation.h" #include "displayapp/screens/InfiniPaint.h" -//#include "displayapp/screens/Paddle.h" +#include "displayapp/screens/Paddle.h" #include "displayapp/screens/StopWatch.h" #include "displayapp/screens/Metronome.h" #include "displayapp/screens/Music.h" -//#include "displayapp/screens/Navigation.h" +#include "displayapp/screens/Navigation.h" #include "displayapp/screens/Notifications.h" #include "displayapp/screens/SystemInfo.h" #include "displayapp/screens/Tile.h" diff --git a/src/displayapp/apps/Apps.h.in b/src/displayapp/apps/Apps.h.in index c1f90cc20d..70510c9a28 100644 --- a/src/displayapp/apps/Apps.h.in +++ b/src/displayapp/apps/Apps.h.in @@ -19,11 +19,11 @@ namespace Pinetime { BatteryInfo, Music, Paint, - //Paddle, + Paddle, Twos, HeartRate, SleepTracker, - //Navigation, + Navigation, StopWatch, Metronome, Motion, diff --git a/src/displayapp/screens/SleepTracker.cpp b/src/displayapp/screens/SleepTracker.cpp index 925381dd18..bca330df47 100644 --- a/src/displayapp/screens/SleepTracker.cpp +++ b/src/displayapp/screens/SleepTracker.cpp @@ -52,7 +52,7 @@ SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController // Create the refresh task mainRefreshTask = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this); - hrRefreshTask = lv_task_create(BpmDataCallback, 180000, LV_TASK_PRIO_MID, this); + hrRefreshTask = lv_task_create(BpmDataCallback, 3000, LV_TASK_PRIO_MID, this); // Create the clear data button lv_obj_t* btnClear = lv_btn_create(lv_scr_act(), nullptr); @@ -263,6 +263,7 @@ void SleepTracker::WriteDataCSV(const char* fileName, const std::tuple Date: Wed, 9 Oct 2024 20:45:04 -0400 Subject: [PATCH 010/123] Reenable user apps --- src/CMakeLists.txt | 2 +- src/displayapp/apps/CMakeLists.txt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 82b2f21d0f..34ab5e321c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -532,7 +532,7 @@ list(APPEND RECOVERY_SOURCE_FILES components/ble/FSService.cpp components/ble/ImmediateAlertService.cpp components/ble/ServiceDiscovery.cpp - #components/ble/NavigationService.cpp + components/ble/NavigationService.cpp components/ble/HeartRateService.cpp components/ble/MotionService.cpp components/firmwarevalidator/FirmwareValidator.cpp diff --git a/src/displayapp/apps/CMakeLists.txt b/src/displayapp/apps/CMakeLists.txt index dca62123c1..7f812c3da0 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -6,15 +6,15 @@ else () set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Timer") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Steps") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::HeartRate") - #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Music") - #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paint") - #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paddle") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Music") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paint") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paddle") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Twos") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Dice") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Metronome") #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Navigation") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Calculator") - #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Weather") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Weather") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::SleepTracker") #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Motion") set(USERAPP_TYPES "${DEFAULT_USER_APP_TYPES}" CACHE STRING "List of user apps to build into the firmware") From 419dc859eb6e0ce3912e8b77002fc89d9054ba09 Mon Sep 17 00:00:00 2001 From: Liam Willey Date: Fri, 11 Oct 2024 00:18:07 -0400 Subject: [PATCH 011/123] Rename SleepTracker update button size --- src/CMakeLists.txt | 4 +-- src/displayapp/DisplayApp.cpp | 2 +- src/displayapp/apps/Apps.h.in | 2 +- src/displayapp/apps/CMakeLists.txt | 2 +- .../screens/{SleepTracker.cpp => Sleep.cpp} | 34 +++++++++---------- .../screens/{SleepTracker.h => Sleep.h} | 12 +++---- 6 files changed, 28 insertions(+), 28 deletions(-) rename src/displayapp/screens/{SleepTracker.cpp => Sleep.cpp} (87%) rename src/displayapp/screens/{SleepTracker.h => Sleep.h} (78%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 34ab5e321c..a7f79a6cc4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -396,7 +396,7 @@ list(APPEND SOURCE_FILES displayapp/screens/PassKey.cpp displayapp/screens/Error.cpp displayapp/screens/Alarm.cpp - displayapp/screens/SleepTracker.cpp + displayapp/screens/Sleep.cpp displayapp/screens/Styles.cpp displayapp/screens/WeatherSymbols.cpp displayapp/Colors.cpp @@ -616,7 +616,7 @@ set(INCLUDE_FILES displayapp/screens/Timer.h displayapp/screens/Dice.h displayapp/screens/Alarm.h - displayapp/screens/SleepTracker.h + displayapp/screens/Sleep.h displayapp/Colors.h displayapp/widgets/Counter.h displayapp/widgets/PageIndicator.h diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 8232aaf762..0030cf6697 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -31,7 +31,7 @@ #include "displayapp/screens/PassKey.h" #include "displayapp/screens/Error.h" #include "displayapp/screens/Calculator.h" -#include "displayapp/screens/SleepTracker.h" +#include "displayapp/screens/Sleep.h" #include "drivers/Cst816s.h" #include "drivers/St7789.h" diff --git a/src/displayapp/apps/Apps.h.in b/src/displayapp/apps/Apps.h.in index 70510c9a28..a690be8c80 100644 --- a/src/displayapp/apps/Apps.h.in +++ b/src/displayapp/apps/Apps.h.in @@ -22,7 +22,7 @@ namespace Pinetime { Paddle, Twos, HeartRate, - SleepTracker, + Sleep, Navigation, StopWatch, Metronome, diff --git a/src/displayapp/apps/CMakeLists.txt b/src/displayapp/apps/CMakeLists.txt index 7f812c3da0..eed998c456 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -15,7 +15,7 @@ else () #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Navigation") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Calculator") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Weather") - set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::SleepTracker") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Sleep") #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Motion") set(USERAPP_TYPES "${DEFAULT_USER_APP_TYPES}" CACHE STRING "List of user apps to build into the firmware") endif () diff --git a/src/displayapp/screens/SleepTracker.cpp b/src/displayapp/screens/Sleep.cpp similarity index 87% rename from src/displayapp/screens/SleepTracker.cpp rename to src/displayapp/screens/Sleep.cpp index bca330df47..543f987235 100644 --- a/src/displayapp/screens/SleepTracker.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -1,4 +1,4 @@ -#include "displayapp/screens/SleepTracker.h" +#include "displayapp/screens/Sleep.h" #include #include @@ -14,33 +14,33 @@ using namespace Pinetime::Applications::Screens; namespace { void BpmDataCallback(lv_task_t* task) { - auto* screen = static_cast(task->user_data); + auto* screen = static_cast(task->user_data); screen->GetBPM(); } void ClearDataCallback(lv_obj_t* btn, lv_event_t event) { if (event == LV_EVENT_CLICKED) { - auto* screen = static_cast(lv_obj_get_user_data(btn)); - screen->ClearDataCSV("SleepTracker_Data.csv"); + auto* screen = static_cast(lv_obj_get_user_data(btn)); + screen->ClearDataCSV("Sleep_Data.csv"); } } // void GetSleepInfoCallback(lv_obj_t* btn, lv_event_t event) { // if (event == LV_EVENT_CLICKED) { - // auto* screen = static_cast(lv_obj_get_user_data(btn)); + // auto* screen = static_cast(lv_obj_get_user_data(btn)); // screen->GetSleepInfo(screen->ReadDataCSV("SleepTracker_Data.csv")); // } // } } -SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController, Controllers::DateTime& dateTimeController, Controllers::FS& fsController, System::SystemTask& systemTask) +Sleep::Sleep(Controllers::HeartRateController& heartRateController, Controllers::DateTime& dateTimeController, Controllers::FS& fsController, System::SystemTask& systemTask) : heartRateController {heartRateController}, dateTimeController {dateTimeController}, fsController {fsController}, wakeLock(systemTask) { wakeLock.Lock(); constexpr uint8_t btnWidth = 115; - constexpr uint8_t btnHeight = 80; + constexpr uint8_t btnHeight = 45; lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(title, "Sleep Tracker"); @@ -81,7 +81,7 @@ SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController // NRF_LOG_INFO("-------------------------------"); } -SleepTracker::~SleepTracker() { +Sleep::~Sleep() { wakeLock.Release(); lv_obj_clean(lv_scr_act()); @@ -90,17 +90,17 @@ SleepTracker::~SleepTracker() { } // This function is called periodically from the refresh task -void SleepTracker::Refresh() { +void Sleep::Refresh() { // Get the current heart rate } // Convert time to minutes -float SleepTracker::ConvertToMinutes(int hours, int minutes, int seconds) const { +float Sleep::ConvertToMinutes(int hours, int minutes, int seconds) const { return hours * 60 + minutes + seconds / 60.0f; } // Get the moving average of BPM Values -// std::vector SleepTracker::MovingAverage(const std::vector& bpmData, int windowSize) const { +// std::vector Sleep::MovingAverage(const std::vector& bpmData, int windowSize) const { // std::vector smoothedBpm; // const int n = bpmData.size(); @@ -116,7 +116,7 @@ float SleepTracker::ConvertToMinutes(int hours, int minutes, int seconds) const // } // Detect the sleep regions -// std::vector> SleepTracker::DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const { +// std::vector> Sleep::DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const { // std::vector> sleep_regions; // float start_time = -1; // bool in_sleep = false; @@ -145,7 +145,7 @@ float SleepTracker::ConvertToMinutes(int hours, int minutes, int seconds) const // } // // Get Sleep Info -// void SleepTracker::GetSleepInfo(const std::vector>& data) const { +// void Sleep::GetSleepInfo(const std::vector>& data) const { // std::vector time; // std::vector bpm; @@ -214,7 +214,7 @@ float SleepTracker::ConvertToMinutes(int hours, int minutes, int seconds) const // NRF_LOG_INFO("Sleep info written to SleepTracker_SleepInfo.csv"); // } -void SleepTracker::GetBPM() { +void Sleep::GetBPM() { // Get the heart rate from the controller prevBpm = bpm; bpm = heartRateController.HeartRate(); @@ -244,7 +244,7 @@ void SleepTracker::GetBPM() { * Write data to a CSV file * Format: Time,BPM,Motion */ -void SleepTracker::WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const { +void Sleep::WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const { lfs_file_t file; int err = fsController.FileOpen(&file, fileName, LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND); if (err < 0) { @@ -272,7 +272,7 @@ void SleepTracker::WriteDataCSV(const char* fileName, const std::tuple> SleepTracker::ReadDataCSV(const char* filename) const { +// std::vector> Sleep::ReadDataCSV(const char* filename) const { // lfs_file_t file; // int err = fsController.FileOpen(&file, filename, LFS_O_RDONLY); // if (err < 0) { @@ -310,7 +310,7 @@ void SleepTracker::WriteDataCSV(const char* fileName, const std::tuple - struct AppTraits { - static constexpr Apps app = Apps::SleepTracker; + struct AppTraits { + static constexpr Apps app = Apps::Sleep; static constexpr const char* icon = Screens::Symbols::bed; static Screens::Screen* Create(AppControllers& controllers) { - return new Screens::SleepTracker(controllers.heartRateController, controllers.dateTimeController, controllers.filesystem, *controllers.systemTask); + return new Screens::Sleep(controllers.heartRateController, controllers.dateTimeController, controllers.filesystem, *controllers.systemTask); } }; } From e6cfc5a0540d250e31318c740278ea32062a4a6a Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 28 Oct 2024 01:58:22 -0500 Subject: [PATCH 012/123] Work on new Sleep Controller --- src/CMakeLists.txt | 3 + .../infinisleep/InfiniSleepController.cpp | 166 ++++++++++++++++++ .../infinisleep/InfiniSleepController.h | 78 ++++++++ src/main.cpp | 5 +- src/systemtask/Messages.h | 1 + src/systemtask/SystemTask.cpp | 10 +- src/systemtask/SystemTask.h | 5 +- 7 files changed, 264 insertions(+), 4 deletions(-) create mode 100644 src/components/infinisleep/InfiniSleepController.cpp create mode 100644 src/components/infinisleep/InfiniSleepController.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a7f79a6cc4..1f1946b2f7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -470,6 +470,7 @@ list(APPEND SOURCE_FILES components/settings/Settings.cpp components/timer/Timer.cpp components/alarm/AlarmController.cpp + components/infinisleep/InfiniSleepController.cpp components/fs/FS.cpp drivers/Cst816s.cpp FreeRTOS/port.c @@ -539,6 +540,7 @@ list(APPEND RECOVERY_SOURCE_FILES components/settings/Settings.cpp components/timer/Timer.cpp components/alarm/AlarmController.cpp + components/infinisleep/InfiniSleepController.cpp drivers/Cst816s.cpp FreeRTOS/port.c FreeRTOS/port_cmsis_systick.c @@ -659,6 +661,7 @@ set(INCLUDE_FILES components/settings/Settings.h components/timer/Timer.h components/alarm/AlarmController.h + components/infinisleep/InfiniSleepController.h drivers/Cst816s.h FreeRTOS/portmacro.h FreeRTOS/portmacro_cmsis.h diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp new file mode 100644 index 0000000000..f9bedfbf36 --- /dev/null +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -0,0 +1,166 @@ +# include "components/infinisleep/InfiniSleepController.h" +#include "systemtask/SystemTask.h" +#include "task.h" +#include +#include + +using namespace Pinetime::Controllers; +using namespace std::chrono_literals; + +InfiniSleepController::InfiniSleepController(Controllers::DateTime& dateTimeController, Controllers::FS& fs) + : dateTimeController {dateTimeController}, fs {fs} { +} + +namespace { + void SetOffWakeAlarm(TimerHandle_t xTimer) { + auto* controller = static_cast(pvTimerGetTimerID(xTimer)); + controller->SetOffWakeAlarmNow(); + } +} + +void InfiniSleepController::Init(System::SystemTask* systemTask) { + this->systemTask = systemTask; + wakeAlarmTimer = xTimerCreate("WakeAlarm", 1, pdFALSE, this, SetOffWakeAlarm); + LoadSettingsFromFile(); + if (wakeAlarm.isEnabled) { + NRF_LOG_INFO("[InfiniSleepController] Loaded wake alarm was enabled, scheduling"); + ScheduleWakeAlarm(); + } +} + +void InfiniSleepController::SaveWakeAlarm() { + // verify is save needed + if (wakeAlarmChanged) { + SaveSettingsToFile(); + } + wakeAlarmChanged = false; +} + +void InfiniSleepController::SetWakeAlarmTime(uint8_t wakeAlarmHr, uint8_t wakeAlarmMin) { + if (wakeAlarm.hours == wakeAlarmHr && wakeAlarm.minutes == wakeAlarmMin) { + return; + } + wakeAlarm.hours = wakeAlarmHr; + wakeAlarm.minutes = wakeAlarmMin; + wakeAlarmChanged = true; +} + +void InfiniSleepController::ScheduleWakeAlarm() { + // Determine the next time the wake alarm needs to go off and set the timer + xTimerStop(wakeAlarmTimer, 0); + + auto now = dateTimeController.CurrentDateTime(); + wakeAlarmTime = now; + time_t ttWakeAlarmTime = std::chrono::system_clock::to_time_t(std::chrono::time_point_cast(wakeAlarmTime)); + tm* tmWakeAlarmTime = std::localtime(&ttWakeAlarmTime); + + // If the time being set has already passed today, the wake alarm should be set for tomorrow + if (wakeAlarm.hours < dateTimeController.Hours() || + (wakeAlarm.hours == dateTimeController.Hours() && wakeAlarm.minutes <= dateTimeController.Minutes())) { + tmWakeAlarmTime->tm_mday += 1; + // tm_wday doesn't update automatically + tmWakeAlarmTime->tm_wday = (tmWakeAlarmTime->tm_wday + 1) % 7; + } + + tmWakeAlarmTime->tm_hour = wakeAlarm.hours; + tmWakeAlarmTime->tm_min = wakeAlarm.minutes; + tmWakeAlarmTime->tm_sec = 0; + + // if alarm is in weekday-only mode, make sure it shifts to the next weekday + if (wakeAlarm.recurrence == RecurType::Weekdays) { + if (tmWakeAlarmTime->tm_wday == 0) {// Sunday, shift 1 day + tmWakeAlarmTime->tm_mday += 1; + } else if (tmWakeAlarmTime->tm_wday == 6) { // Saturday, shift 2 days + tmWakeAlarmTime->tm_mday += 2; + } + } + tmWakeAlarmTime->tm_isdst = -1; // use system timezone setting to determine DST + + // now can convert back to a time_point + wakeAlarmTime = std::chrono::system_clock::from_time_t(std::mktime(tmWakeAlarmTime)); + auto secondsToWakeAlarm = std::chrono::duration_cast(wakeAlarmTime - now).count(); + xTimerChangePeriod(wakeAlarmTimer, secondsToWakeAlarm * configTICK_RATE_HZ, 0); + xTimerStart(wakeAlarmTimer, 0); + + if (!wakeAlarm.isEnabled) { + wakeAlarm.isEnabled = true; + wakeAlarmChanged = true; + } +} + +uint32_t InfiniSleepController::SecondsToWakeAlarm() const { + return std::chrono::duration_cast(wakeAlarmTime - dateTimeController.CurrentDateTime()).count(); +} + +void InfiniSleepController::DisableWakeAlarm() { + xTimerStop(wakeAlarmTimer, 0); + isAlerting = false; + if (wakeAlarm.isEnabled) { + wakeAlarm.isEnabled = false; + wakeAlarmChanged = true; + } +} + +void InfiniSleepController::SetOffWakeAlarmNow() { + isAlerting = true; + systemTask->PushMessage(System::Messages::SetOffWakeAlarm); +} + +void InfiniSleepController::StopAlerting() { + isAlerting = false; + // Disable the alarm unless it is recurring + if (wakeAlarm.recurrence == RecurType::None) { + wakeAlarm.isEnabled = false; + wakeAlarmChanged = true; + } else { + // Schedule the alarm for the next day + ScheduleWakeAlarm(); + } +} + +void InfiniSleepController::SetRecurrence(RecurType recurrence) { + if (wakeAlarm.recurrence == recurrence) { + return; + } + wakeAlarm.recurrence = recurrence; + wakeAlarmChanged = true; +} + +void InfiniSleepController::LoadSettingsFromFile() { + lfs_file_t wakeAlarmFile; + WakeAlarmSettings wakeAlarmBuffer; + + if (fs.FileOpen(&wakeAlarmFile, "/.system/wakeAlarm.dat", LFS_O_RDONLY) != LFS_ERR_OK) { + NRF_LOG_WARNING("[AlarmController] Failed to open alarm data file"); + return; + } + + fs.FileRead(&wakeAlarmFile, reinterpret_cast(&wakeAlarmBuffer), sizeof(wakeAlarmBuffer)); + fs.FileClose(&wakeAlarmFile); + if (wakeAlarmBuffer.version != wakeAlarmFormatVersion) { + NRF_LOG_WARNING("[AlarmController] Loaded alarm settings has version %u instead of %u, discarding", + wakeAlarmBuffer.version, + wakeAlarmFormatVersion); + return; + } + + wakeAlarm = wakeAlarmBuffer; + NRF_LOG_INFO("[AlarmController] Loaded alarm settings from file"); +} + +void InfiniSleepController::SaveSettingsToFile() const { + lfs_dir systemDir; + if (fs.DirOpen("/.system", &systemDir) != LFS_ERR_OK) { + fs.DirCreate("/.system"); + } + fs.DirClose(&systemDir); + lfs_file_t alarmFile; + if (fs.FileOpen(&alarmFile, "/.system/wakeAlarm.dat", LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) { + NRF_LOG_WARNING("[AlarmController] Failed to open alarm data file for saving"); + return; + } + + fs.FileWrite(&alarmFile, reinterpret_cast(&wakeAlarm), sizeof(wakeAlarm)); + fs.FileClose(&alarmFile); + NRF_LOG_INFO("[AlarmController] Saved alarm settings with format version %u to file", wakeAlarm.version); +} \ No newline at end of file diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h new file mode 100644 index 0000000000..2864a1659f --- /dev/null +++ b/src/components/infinisleep/InfiniSleepController.h @@ -0,0 +1,78 @@ +#pragma once + +#include +#include +#include +#include "components/datetime/DateTimeController.h" + +namespace Pinetime { + namespace System { + class SystemTask; + } + + namespace Controllers { + class InfiniSleepController { + public: + InfiniSleepController(Controllers::DateTime& dateTimeCOntroller, Controllers::FS& fs); + + void Init(System::SystemTask* systemTask); + void SaveWakeAlarm(); + void SetWakeAlarmTime(uint8_t wakeAlarmHr, uint8_t wakeAlarmMin); + void ScheduleWakeAlarm(); + void DisableWakeAlarm(); + void SetOffWakeAlarmNow(); + uint32_t SecondsToWakeAlarm() const; + void StopAlerting(); + enum class RecurType { None, Daily, Weekdays }; + + uint8_t Hours() const { + return wakeAlarm.hours; + } + + uint8_t Minutes() const { + return wakeAlarm.minutes; + } + + bool IsAlerting() const { + return isAlerting; + } + + bool IsEnabled() const { + return wakeAlarm.isEnabled; + } + + RecurType Recurrence() const { + return wakeAlarm.recurrence; + } + + void SetRecurrence(RecurType recurrence); + + private: + // Versions 255 is reserved for now, so the version field can be made + // bigger, should it ever be needed. + static constexpr uint8_t wakeAlarmFormatVersion = 1; + + struct WakeAlarmSettings { + uint8_t version = wakeAlarmFormatVersion; + uint8_t hours = 7; + uint8_t minutes = 0; + RecurType recurrence = RecurType::None; + bool isEnabled = false; + }; + + bool isAlerting = false; + bool wakeAlarmChanged = false; + + Controllers::DateTime& dateTimeController; + Controllers::FS& fs; + System::SystemTask* systemTask = nullptr; + TimerHandle_t wakeAlarmTimer; + WakeAlarmSettings wakeAlarm; + std::chrono::time_point wakeAlarmTime; + + void LoadSettingsFromFile(); + void SaveSettingsToFile() const; + }; + } + +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 24f13caddd..14a3dba8bb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -105,6 +105,8 @@ Pinetime::Drivers::Watchdog watchdog; Pinetime::Controllers::NotificationManager notificationManager; Pinetime::Controllers::MotionController motionController; Pinetime::Controllers::AlarmController alarmController {dateTimeController, fs}; +Pinetime::Controllers::InfiniSleepController infiniSleepController {dateTimeController, fs}; + Pinetime::Controllers::TouchHandler touchHandler; Pinetime::Controllers::ButtonHandler buttonHandler; Pinetime::Controllers::BrightnessController brightnessController {}; @@ -145,7 +147,8 @@ Pinetime::System::SystemTask systemTask(spi, heartRateApp, fs, touchHandler, - buttonHandler); + buttonHandler, + infiniSleepController); int mallocFailedCount = 0; int stackOverflowCount = 0; extern "C" { diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h index fee94bb747..d00b27c150 100644 --- a/src/systemtask/Messages.h +++ b/src/systemtask/Messages.h @@ -25,6 +25,7 @@ namespace Pinetime { OnChargingEvent, OnPairing, SetOffAlarm, + SetOffWakeAlarm, MeasureBatteryTimerExpired, BatteryPercentageUpdated, StartFileTransfer, diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 8e0435e372..391b4ec3aa 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -51,7 +51,8 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi, Pinetime::Applications::HeartRateTask& heartRateApp, Pinetime::Controllers::FS& fs, Pinetime::Controllers::TouchHandler& touchHandler, - Pinetime::Controllers::ButtonHandler& buttonHandler) + Pinetime::Controllers::ButtonHandler& buttonHandler, + Pinetime::Controllers::InfiniSleepController& infiniSleepController) : spi {spi}, spiNorFlash {spiNorFlash}, twiMaster {twiMaster}, @@ -80,7 +81,8 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi, spiNorFlash, heartRateController, motionController, - fs) { + fs), + infiniSleepController {infiniSleepController} { } void SystemTask::Start() { @@ -128,6 +130,7 @@ void SystemTask::Work() { batteryController.Register(this); motionSensor.SoftReset(); alarmController.Init(this); + infiniSleepController.Init(this); // Reset the TWI device because the motion sensor chip most probably crashed it... twiMaster.Sleep(); @@ -218,6 +221,9 @@ void SystemTask::Work() { GoToRunning(); displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered); break; + case Messages::SetOffWakeAlarm: + // Code the screen trigger here + break; case Messages::BleConnected: displayApp.PushMessage(Pinetime::Applications::Display::Messages::NotifyDeviceActivity); isBleDiscoveryTimerRunning = true; diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index 0060e36096..f456a8fd3e 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -16,6 +16,7 @@ #include "components/ble/NimbleController.h" #include "components/ble/NotificationManager.h" #include "components/alarm/AlarmController.h" +#include "components/infinisleep/InfiniSleepController.h" #include "components/fs/FS.h" #include "touchhandler/TouchHandler.h" #include "buttonhandler/ButtonHandler.h" @@ -72,7 +73,8 @@ namespace Pinetime { Pinetime::Applications::HeartRateTask& heartRateApp, Pinetime::Controllers::FS& fs, Pinetime::Controllers::TouchHandler& touchHandler, - Pinetime::Controllers::ButtonHandler& buttonHandler); + Pinetime::Controllers::ButtonHandler& buttonHandler, + Pinetime::Controllers::InfiniSleepController& infiniSleepController); void Start(); void PushMessage(Messages msg); @@ -116,6 +118,7 @@ namespace Pinetime { Pinetime::Controllers::TouchHandler& touchHandler; Pinetime::Controllers::ButtonHandler& buttonHandler; Pinetime::Controllers::NimbleController nimbleController; + Pinetime::Controllers::InfiniSleepController& infiniSleepController; static void Process(void* instance); void Work(); From 0472fdd0cc671e870f895f73cafb995597123b81 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 01:03:40 -0500 Subject: [PATCH 013/123] Ported Main Alarm into InfiniSleep, Need to add natural and gradual wake next --- .../infinisleep/InfiniSleepController.cpp | 8 +- src/displayapp/Controllers.h | 2 + src/displayapp/DisplayApp.cpp | 13 +- src/displayapp/DisplayApp.h | 4 +- src/displayapp/Messages.h | 1 + src/displayapp/screens/Sleep.cpp | 537 ++++++++---------- src/displayapp/screens/Sleep.h | 70 ++- src/main.cpp | 3 +- src/systemtask/SystemTask.cpp | 2 + 9 files changed, 324 insertions(+), 316 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index f9bedfbf36..17e2ba9a79 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -130,7 +130,7 @@ void InfiniSleepController::LoadSettingsFromFile() { lfs_file_t wakeAlarmFile; WakeAlarmSettings wakeAlarmBuffer; - if (fs.FileOpen(&wakeAlarmFile, "/.system/wakeAlarm.dat", LFS_O_RDONLY) != LFS_ERR_OK) { + if (fs.FileOpen(&wakeAlarmFile, "/.system/sleep/wakeAlarm.dat", LFS_O_RDONLY) != LFS_ERR_OK) { NRF_LOG_WARNING("[AlarmController] Failed to open alarm data file"); return; } @@ -150,12 +150,12 @@ void InfiniSleepController::LoadSettingsFromFile() { void InfiniSleepController::SaveSettingsToFile() const { lfs_dir systemDir; - if (fs.DirOpen("/.system", &systemDir) != LFS_ERR_OK) { - fs.DirCreate("/.system"); + if (fs.DirOpen("/.system/sleep", &systemDir) != LFS_ERR_OK) { + fs.DirCreate("/.system/sleep"); } fs.DirClose(&systemDir); lfs_file_t alarmFile; - if (fs.FileOpen(&alarmFile, "/.system/wakeAlarm.dat", LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) { + if (fs.FileOpen(&alarmFile, "/.system/sleep/wakeAlarm.dat", LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) { NRF_LOG_WARNING("[AlarmController] Failed to open alarm data file for saving"); return; } diff --git a/src/displayapp/Controllers.h b/src/displayapp/Controllers.h index 9992426c5d..5116398e2e 100644 --- a/src/displayapp/Controllers.h +++ b/src/displayapp/Controllers.h @@ -19,6 +19,7 @@ namespace Pinetime { class MotorController; class MotionController; class AlarmController; + class InfiniSleepController; class BrightnessController; class SimpleWeatherService; class FS; @@ -42,6 +43,7 @@ namespace Pinetime { Pinetime::Controllers::MotorController& motorController; Pinetime::Controllers::MotionController& motionController; Pinetime::Controllers::AlarmController& alarmController; + Pinetime::Controllers::InfiniSleepController& infiniSleepController; Pinetime::Controllers::BrightnessController& brightnessController; Pinetime::Controllers::SimpleWeatherService* weatherController; Pinetime::Controllers::FS& filesystem; diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 0030cf6697..d0526c21b6 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -86,7 +86,8 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, Pinetime::Controllers::BrightnessController& brightnessController, Pinetime::Controllers::TouchHandler& touchHandler, Pinetime::Controllers::FS& filesystem, - Pinetime::Drivers::SpiNorFlash& spiNorFlash) + Pinetime::Drivers::SpiNorFlash& spiNorFlash, + Pinetime::Controllers::InfiniSleepController& infiniSleepController) : lcd {lcd}, touchPanel {touchPanel}, batteryController {batteryController}, @@ -103,6 +104,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, touchHandler {touchHandler}, filesystem {filesystem}, spiNorFlash {spiNorFlash}, + infiniSleepController {infiniSleepController}, lvgl {lcd, filesystem}, timer(this, TimerCallback), controllers {batteryController, @@ -114,6 +116,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, motorController, motionController, alarmController, + infiniSleepController, brightnessController, nullptr, filesystem, @@ -385,6 +388,14 @@ void DisplayApp::Refresh() { LoadNewScreen(Apps::Alarm, DisplayApp::FullRefreshDirections::None); } break; + case Messages::WakeAlarmTriggered: + if (currentApp == Apps::Sleep) { + auto* sleep = static_cast(currentScreen.get()); + sleep->SetAlerting(); + } else { + LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); + } + break; case Messages::ShowPairingKey: LoadNewScreen(Apps::PassKey, DisplayApp::FullRefreshDirections::Up); motorController.RunForDuration(35); diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index dabed99ea7..57e1483743 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -67,7 +67,8 @@ namespace Pinetime { Pinetime::Controllers::BrightnessController& brightnessController, Pinetime::Controllers::TouchHandler& touchHandler, Pinetime::Controllers::FS& filesystem, - Pinetime::Drivers::SpiNorFlash& spiNorFlash); + Pinetime::Drivers::SpiNorFlash& spiNorFlash, + Pinetime::Controllers::InfiniSleepController& infiniSleepController); void Start(System::BootErrors error); void PushMessage(Display::Messages msg); @@ -98,6 +99,7 @@ namespace Pinetime { Pinetime::Controllers::TouchHandler& touchHandler; Pinetime::Controllers::FS& filesystem; Pinetime::Drivers::SpiNorFlash& spiNorFlash; + Pinetime::Controllers::InfiniSleepController& infiniSleepController; Pinetime::Controllers::FirmwareValidator validator; Pinetime::Components::LittleVgl lvgl; diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index 1fcd72d278..d2062a32b4 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -22,6 +22,7 @@ namespace Pinetime { NotifyDeviceActivity, ShowPairingKey, AlarmTriggered, + WakeAlarmTriggered, Chime, BleRadioEnableToggle, }; diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 543f987235..0b3321abb6 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -1,324 +1,281 @@ #include "displayapp/screens/Sleep.h" - -#include -#include -#include -#include -#include - -#include -#include +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/Symbols.h" +#include "displayapp/InfiniTimeTheme.h" +#include "components/settings/Settings.h" +#include "components/alarm/AlarmController.h" +#include "components/motor/MotorController.h" +#include "systemtask/SystemTask.h" using namespace Pinetime::Applications::Screens; +using Pinetime::Controllers::InfiniSleepController; namespace { - - void BpmDataCallback(lv_task_t* task) { - auto* screen = static_cast(task->user_data); - screen->GetBPM(); + void ValueChangedHandler(void* userData) { + auto* screen = static_cast(userData); + screen->OnValueChanged(); } +} - void ClearDataCallback(lv_obj_t* btn, lv_event_t event) { - if (event == LV_EVENT_CLICKED) { - auto* screen = static_cast(lv_obj_get_user_data(btn)); - screen->ClearDataCSV("Sleep_Data.csv"); - } - } +static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { + auto* screen = static_cast(obj->user_data); + screen->OnButtonEvent(obj, event); +} - // void GetSleepInfoCallback(lv_obj_t* btn, lv_event_t event) { - // if (event == LV_EVENT_CLICKED) { - // auto* screen = static_cast(lv_obj_get_user_data(btn)); - // screen->GetSleepInfo(screen->ReadDataCSV("SleepTracker_Data.csv")); - // } - // } +static void StopAlarmTaskCallback(lv_task_t* task) { + auto* screen = static_cast(task->user_data); + screen->StopAlerting(); +} +Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, + Controllers::Settings::ClockType clockType, + System::SystemTask& systemTask, + Controllers::MotorController& motorController) + : infiniSleepController {infiniSleepController}, wakeLock(systemTask), motorController {motorController} { + + hourCounter.Create(); + lv_obj_align(hourCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); + if (clockType == Controllers::Settings::ClockType::H12) { + hourCounter.EnableTwelveHourMode(); + + lblampm = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(lblampm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); + lv_label_set_text_static(lblampm, "AM"); + lv_label_set_align(lblampm, LV_LABEL_ALIGN_CENTER); + lv_obj_align(lblampm, lv_scr_act(), LV_ALIGN_CENTER, 0, 30); + } + hourCounter.SetValue(infiniSleepController.Hours()); + hourCounter.SetValueChangedEventCallback(this, ValueChangedHandler); + + minuteCounter.Create(); + lv_obj_align(minuteCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); + minuteCounter.SetValue(infiniSleepController.Minutes()); + minuteCounter.SetValueChangedEventCallback(this, ValueChangedHandler); + + lv_obj_t* colonLabel = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); + lv_label_set_text_static(colonLabel, ":"); + lv_obj_align(colonLabel, lv_scr_act(), LV_ALIGN_CENTER, 0, -29); + + btnStop = lv_btn_create(lv_scr_act(), nullptr); + btnStop->user_data = this; + lv_obj_set_event_cb(btnStop, btnEventHandler); + lv_obj_set_size(btnStop, 115, 50); + lv_obj_align(btnStop, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); + lv_obj_set_style_local_bg_color(btnStop, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); + txtStop = lv_label_create(btnStop, nullptr); + lv_label_set_text_static(txtStop, Symbols::stop); + lv_obj_set_hidden(btnStop, true); + + static constexpr lv_color_t bgColor = Colors::bgAlt; + + btnRecur = lv_btn_create(lv_scr_act(), nullptr); + btnRecur->user_data = this; + lv_obj_set_event_cb(btnRecur, btnEventHandler); + lv_obj_set_size(btnRecur, 115, 50); + lv_obj_align(btnRecur, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + txtRecur = lv_label_create(btnRecur, nullptr); + SetRecurButtonState(); + lv_obj_set_style_local_bg_color(btnRecur, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, bgColor); + + btnInfo = lv_btn_create(lv_scr_act(), nullptr); + btnInfo->user_data = this; + lv_obj_set_event_cb(btnInfo, btnEventHandler); + lv_obj_set_size(btnInfo, 50, 50); + lv_obj_align(btnInfo, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, -4); + lv_obj_set_style_local_bg_color(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, bgColor); + lv_obj_set_style_local_border_width(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 4); + lv_obj_set_style_local_border_color(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + + lv_obj_t* txtInfo = lv_label_create(btnInfo, nullptr); + lv_label_set_text_static(txtInfo, "i"); + + enableSwitch = lv_switch_create(lv_scr_act(), nullptr); + enableSwitch->user_data = this; + lv_obj_set_event_cb(enableSwitch, btnEventHandler); + lv_obj_set_size(enableSwitch, 100, 50); + // Align to the center of 115px from edge + lv_obj_align(enableSwitch, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 7, 0); + lv_obj_set_style_local_bg_color(enableSwitch, LV_SWITCH_PART_BG, LV_STATE_DEFAULT, bgColor); + + UpdateWakeAlarmTime(); + + if (infiniSleepController.IsAlerting()) { + SetAlerting(); + } else { + SetSwitchState(LV_ANIM_OFF); + } } -Sleep::Sleep(Controllers::HeartRateController& heartRateController, Controllers::DateTime& dateTimeController, Controllers::FS& fsController, System::SystemTask& systemTask) - : heartRateController {heartRateController}, dateTimeController {dateTimeController}, fsController {fsController}, wakeLock(systemTask) { +Sleep::~Sleep() { + if (infiniSleepController.IsAlerting()) { + StopAlerting(); + } + lv_obj_clean(lv_scr_act()); + infiniSleepController.SaveWakeAlarm(); +} - wakeLock.Lock(); +void Sleep::DisableWakeAlarm() { + if (infiniSleepController.IsEnabled()) { + infiniSleepController.DisableWakeAlarm(); + lv_switch_off(enableSwitch, LV_ANIM_ON); + } +} - constexpr uint8_t btnWidth = 115; - constexpr uint8_t btnHeight = 45; - - lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_static(title, "Sleep Tracker"); - lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); - lv_obj_align(title, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); - - label_hr = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_font(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); - - // Create the refresh task - mainRefreshTask = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this); - hrRefreshTask = lv_task_create(BpmDataCallback, 3000, LV_TASK_PRIO_MID, this); - - // Create the clear data button - lv_obj_t* btnClear = lv_btn_create(lv_scr_act(), nullptr); - btnClear->user_data = this; - lv_obj_set_event_cb(btnClear, ClearDataCallback); - lv_obj_set_size(btnClear, btnWidth, btnHeight); - lv_obj_align(btnClear, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); - lv_obj_t* txtClear = lv_label_create(btnClear, nullptr); - lv_label_set_text(txtClear, "X"); - - // Create the get info button - // lv_obj_t* btnInfo = lv_btn_create(lv_scr_act(), nullptr); - // btnInfo->user_data = this; - // lv_obj_set_event_cb(btnInfo, GetSleepInfoCallback); - // lv_obj_set_size(btnInfo, btnWidth, btnHeight); - // lv_obj_align(btnInfo, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); - // lv_obj_t* txtInfo = lv_label_create(btnInfo, nullptr); - // lv_label_set_text(txtInfo, "?"); - - // const auto data = ReadDataCSV("SleepTracker_Data.csv"); - // for (const auto& entry : data) { - // int hours, minutes, seconds, bpm, motion; - // std::tie(hours, minutes, seconds, bpm, motion) = entry; - // NRF_LOG_INFO("Read data: %02d:%02d:%02d, %d, %d", hours, minutes, seconds, bpm, motion); - // } - // NRF_LOG_INFO("-------------------------------"); +void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { + if (event == LV_EVENT_CLICKED) { + if (obj == btnStop) { + StopAlerting(); + return; + } + if (obj == btnInfo) { + ShowAlarmInfo(); + return; + } + if (obj == btnMessage) { + HideAlarmInfo(); + return; + } + if (obj == enableSwitch) { + if (lv_switch_get_state(enableSwitch)) { + infiniSleepController.ScheduleWakeAlarm(); + } else { + infiniSleepController.DisableWakeAlarm(); + } + return; + } + if (obj == btnRecur) { + DisableWakeAlarm(); + ToggleRecurrence(); + } + } } -Sleep::~Sleep() { - wakeLock.Release(); +bool Sleep::OnButtonPushed() { + if (txtMessage != nullptr && btnMessage != nullptr) { + HideAlarmInfo(); + return true; + } + if (infiniSleepController.IsAlerting()) { + StopAlerting(); + return true; + } + return false; +} - lv_obj_clean(lv_scr_act()); - lv_task_del(mainRefreshTask); - lv_task_del(hrRefreshTask); +bool Sleep::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + // Don't allow closing the screen by swiping while the alarm is alerting + return infiniSleepController.IsAlerting() && event == TouchEvents::SwipeDown; } -// This function is called periodically from the refresh task -void Sleep::Refresh() { - // Get the current heart rate +void Sleep::OnValueChanged() { + DisableWakeAlarm(); + UpdateWakeAlarmTime(); } -// Convert time to minutes -float Sleep::ConvertToMinutes(int hours, int minutes, int seconds) const { - return hours * 60 + minutes + seconds / 60.0f; +void Sleep::UpdateWakeAlarmTime() { + if (lblampm != nullptr) { + if (hourCounter.GetValue() >= 12) { + lv_label_set_text_static(lblampm, "PM"); + } else { + lv_label_set_text_static(lblampm, "AM"); + } + } + infiniSleepController.SetWakeAlarmTime(hourCounter.GetValue(), minuteCounter.GetValue()); } -// Get the moving average of BPM Values -// std::vector Sleep::MovingAverage(const std::vector& bpmData, int windowSize) const { -// std::vector smoothedBpm; -// const int n = bpmData.size(); - -// for (int i = 0; i < n - windowSize + 1; ++i) { -// float sum = 0; -// for (int j = 0; j < windowSize; ++j) { -// sum += bpmData[i + j]; -// } -// smoothedBpm.push_back(sum / windowSize); -// } - -// return smoothedBpm; -// } - -// Detect the sleep regions -// std::vector> Sleep::DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const { -// std::vector> sleep_regions; -// float start_time = -1; -// bool in_sleep = false; - -// for (size_t i = 0; i < bpmData.size(); ++i) { -// if (bpmData[i] < threshold) { -// if (!in_sleep) { -// start_time = time[i]; // Mark the start of sleep -// in_sleep = true; -// } -// } else { -// if (in_sleep) { -// float end_time = time[i]; // Mark the end of sleep -// sleep_regions.emplace_back(start_time, end_time); -// in_sleep = false; -// } -// } -// } - -// // In case the last region extends to the end of the data -// if (in_sleep) { -// sleep_regions.emplace_back(start_time, time.back()); -// } - -// return sleep_regions; -// } - -// // Get Sleep Info -// void Sleep::GetSleepInfo(const std::vector>& data) const { -// std::vector time; -// std::vector bpm; - -// // Extract the time (in minutes) and bpm from the data -// for (const auto& entry : data) { -// int hours, minutes, seconds, bpm_value, motion; -// std::tie(hours, minutes, seconds, bpm_value, motion) = entry; -// time.push_back(ConvertToMinutes(hours, minutes, seconds)); -// bpm.push_back(bpm_value); -// } - -// // Compute the moving average with a window size of 5 (15 minutes smoothing, since each data point is 3 minutes) -// const auto smoothed_bpm = MovingAverage(bpm, 5); - -// // Calculate a threshold as 80% of the average BPM -// const float average_bpm = std::accumulate(bpm.begin(), bpm.end(), 0.0f) / bpm.size(); -// const float threshold = average_bpm * 0.8f; - -// // Detect multiple sleep regions -// const auto sleep_regions = DetectSleepRegions(smoothed_bpm, time, threshold); - -// // Output sleep regions -// if (!sleep_regions.empty()) { -// for (const auto& region : sleep_regions) { -// NRF_LOG_INFO("Sleep detected from %.2f minutes to %.2f minutes.", region.first, region.second); -// } -// } else { -// NRF_LOG_INFO("No significant sleep regions detected."); -// } - -// // Open the output file -// lfs_file_t file; -// int err = fsController.FileOpen(&file, "SleepTracker_SleepInfo.csv", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC); -// if (err < 0) { -// // Handle error -// NRF_LOG_INFO("Error opening file: %d", err); -// return; -// } - -// // Write sleep regions to the file -// if (!sleep_regions.empty()) { -// for (const auto& region : sleep_regions) { -// char buffer[64]; -// int len = snprintf(buffer, sizeof(buffer), "Sleep detected from %.2f minutes to %.2f minutes.\n", region.first, region.second); -// err = fsController.FileWrite(&file, reinterpret_cast(buffer), len); -// if (err < 0) { -// // Handle error -// NRF_LOG_INFO("Error writing to file: %d", err); -// fsController.FileClose(&file); -// return; -// } -// } -// } else { -// const char* noSleepMsg = "No significant sleep regions detected.\n"; -// err = fsController.FileWrite(&file, reinterpret_cast(noSleepMsg), strlen(noSleepMsg)); -// if (err < 0) { -// // Handle error -// NRF_LOG_INFO("Error writing to file: %d", err); -// fsController.FileClose(&file); -// return; -// } -// } - -// // Close the file -// fsController.FileClose(&file); -// NRF_LOG_INFO("Sleep info written to SleepTracker_SleepInfo.csv"); -// } - -void Sleep::GetBPM() { - // Get the heart rate from the controller - prevBpm = bpm; - bpm = heartRateController.HeartRate(); - - if(prevBpm != 0) - rollingBpm = (rollingBpm + bpm) / 2; - else - rollingBpm = bpm; - - // Get the current time from DateTimeController - int hours = dateTimeController.Hours(); - int minutes = dateTimeController.Minutes(); - int seconds = dateTimeController.Seconds(); - - // Log the BPM and current time - NRF_LOG_INFO("BPM: %d at %02d:%02d:%02d", rollingBpm, hours, minutes, seconds); - - // Write data to CSV - const int motion = 0; // Placeholder for motion data - std::tuple data[1] = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; - WriteDataCSV("SleepTracker_Data.csv", data, 1); +void Sleep::SetAlerting() { + lv_obj_set_hidden(enableSwitch, true); + lv_obj_set_hidden(btnStop, false); + taskStopWakeAlarm = lv_task_create(StopAlarmTaskCallback, pdMS_TO_TICKS(60 * 1000), LV_TASK_PRIO_MID, this); + motorController.StartRinging(); + wakeLock.Lock(); } -// File IO Stuff - -/* -* Write data to a CSV file -* Format: Time,BPM,Motion -*/ -void Sleep::WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const { - lfs_file_t file; - int err = fsController.FileOpen(&file, fileName, LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND); - if (err < 0) { - // Handle error - NRF_LOG_INFO("Error opening file: %d", err); - return; +void Sleep::StopAlerting() { + infiniSleepController.StopAlerting(); + motorController.StopRinging(); + SetSwitchState(LV_ANIM_OFF); + if (taskStopWakeAlarm != nullptr) { + lv_task_del(taskStopWakeAlarm); + taskStopWakeAlarm = nullptr; } + wakeLock.Release(); + lv_obj_set_hidden(enableSwitch, false); + lv_obj_set_hidden(btnStop, true); +} - for (int i = 0; i < dataSize; ++i) { - int hours, minutes, seconds, bpm, motion; - std::tie(hours, minutes, seconds, bpm, motion) = data[i]; - char buffer[64]; - int len = snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d,%d,%d\n", hours, minutes, seconds, bpm, motion); - err = fsController.FileWrite(&file, reinterpret_cast(buffer), len); - if (err < 0) { - // Handle error - NRF_LOG_INFO("Error writing to file: %d", err); - fsController.FileClose(&file); +void Sleep::SetSwitchState(lv_anim_enable_t anim) { + if (infiniSleepController.IsEnabled()) { + lv_switch_on(enableSwitch, anim); + } else { + lv_switch_off(enableSwitch, anim); + } +} - return; - } +void Sleep::ShowAlarmInfo() { + if (btnMessage != nullptr) { + return; + } + btnMessage = lv_btn_create(lv_scr_act(), nullptr); + btnMessage->user_data = this; + lv_obj_set_event_cb(btnMessage, btnEventHandler); + lv_obj_set_height(btnMessage, 200); + lv_obj_set_width(btnMessage, 150); + lv_obj_align(btnMessage, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + txtMessage = lv_label_create(btnMessage, nullptr); + lv_obj_set_style_local_bg_color(btnMessage, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_NAVY); + + if (infiniSleepController.IsEnabled()) { + auto timeToAlarm = infiniSleepController.SecondsToWakeAlarm(); + + auto daysToAlarm = timeToAlarm / 86400; + auto hrsToAlarm = (timeToAlarm % 86400) / 3600; + auto minToAlarm = (timeToAlarm % 3600) / 60; + auto secToAlarm = timeToAlarm % 60; + + lv_label_set_text_fmt(txtMessage, + "Time to\nalarm:\n%2lu Days\n%2lu Hours\n%2lu Minutes\n%2lu Seconds", + daysToAlarm, + hrsToAlarm, + minToAlarm, + secToAlarm); + } else { + lv_label_set_text_static(txtMessage, "Alarm\nis not\nset."); } +} - fsController.FileClose(&file); +void Sleep::HideAlarmInfo() { + lv_obj_del(btnMessage); + txtMessage = nullptr; + btnMessage = nullptr; } -// Read data from CSV -// std::vector> Sleep::ReadDataCSV(const char* filename) const { -// lfs_file_t file; -// int err = fsController.FileOpen(&file, filename, LFS_O_RDONLY); -// if (err < 0) { -// // Handle error -// NRF_LOG_INFO("Error opening file: %d", err); -// return {}; -// } - -// std::vector> data; -// char buffer[128]; -// int bytesRead; - -// // Read data -// while ((bytesRead = fsController.FileRead(&file, reinterpret_cast(buffer), sizeof(buffer))) > 0) { -// std::istringstream dataStream(buffer); -// std::string line; -// while (std::getline(dataStream, line)) { -// int hours, minutes, seconds, bpm, motion; -// char colon1, colon2, comma1, comma2; -// std::istringstream lineStream(line); -// if (lineStream >> hours >> colon1 >> minutes >> colon2 >> seconds >> comma1 >> bpm >> comma2 >> motion) { -// if (colon1 == ':' && colon2 == ':' && comma1 == ',' && comma2 == ',') { -// data.emplace_back(hours, minutes, seconds, bpm, motion); -// } else { -// NRF_LOG_INFO("Parsing error: incorrect format in line: %s", line.c_str()); -// } -// } else { -// NRF_LOG_INFO("Parsing error: failed to parse line: %s", line.c_str()); -// } -// } -// } - -// fsController.FileClose(&file); -// return data; -// } - -// Clear data in CSV -void Sleep::ClearDataCSV(const char* filename) const { - lfs_file_t file; - int err = fsController.FileOpen(&file, filename, LFS_O_WRONLY | LFS_O_TRUNC); - if (err < 0) { - // Handle error - NRF_LOG_INFO("Error opening file: %d", err); - return; +void Sleep::SetRecurButtonState() { + using Pinetime::Controllers::AlarmController; + switch (infiniSleepController.Recurrence()) { + case InfiniSleepController::RecurType::None: + lv_label_set_text_static(txtRecur, "ONCE"); + break; + case InfiniSleepController::RecurType::Daily: + lv_label_set_text_static(txtRecur, "DAILY"); + break; + case InfiniSleepController::RecurType::Weekdays: + lv_label_set_text_static(txtRecur, "MON-FRI"); } +} - fsController.FileClose(&file); - NRF_LOG_INFO("CSV data cleared"); +void Sleep::ToggleRecurrence() { + using Pinetime::Controllers::AlarmController; + switch (infiniSleepController.Recurrence()) { + case InfiniSleepController::RecurType::None: + infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::Daily); + break; + case InfiniSleepController::RecurType::Daily: + infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::Weekdays); + break; + case InfiniSleepController::RecurType::Weekdays: + infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::None); + } + SetRecurButtonState(); } \ No newline at end of file diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index c4d4dba5b2..b115efa8f7 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -1,7 +1,9 @@ #pragma once #include "displayapp/apps/Apps.h" +#include "components/settings/Settings.h" #include "displayapp/screens/Screen.h" +#include "displayapp/widgets/Counter.h" #include "displayapp/Controllers.h" #include "systemtask/SystemTask.h" #include "systemtask/WakeLock.h" @@ -16,17 +18,24 @@ namespace Pinetime { namespace Screens { class Sleep : public Screen { public: - Sleep(Controllers::HeartRateController& HeartRateController, Controllers::DateTime& DateTimeController, Controllers::FS& fsController, System::SystemTask& systemTask); + //explicit Sleep(Controllers::HeartRateController& HeartRateController, Controllers::DateTime& DateTimeController, Controllers::FS& fsController, System::SystemTask& systemTask); + explicit Sleep(Controllers::InfiniSleepController& infiniSleepController, Controllers::Settings::ClockType clockType, System::SystemTask& systemTask, Controllers::MotorController& motorController); ~Sleep() override; + void SetAlerting(); + void OnButtonEvent(lv_obj_t* obj, lv_event_t event); + bool OnButtonPushed() override; + bool OnTouchEvent(TouchEvents event) override; + void OnValueChanged(); + void StopAlerting(); - void Refresh() override; + // void Refresh() override; - void GetBPM(); + // void GetBPM(); - void ClearDataCSV(const char* filename) const; + // void ClearDataCSV(const char* filename) const; - // Data Processing functions - float ConvertToMinutes(int hours, int minutes, int seconds) const; + // // Data Processing functions + // float ConvertToMinutes(int hours, int minutes, int seconds) const; // Get the moving average of BPM Values //std::vector MovingAverage(const std::vector& bpm, int windowSize) const; // Detect the sleep regions @@ -38,22 +47,44 @@ namespace Pinetime { //std::vector> ReadDataCSV(const char* fileName) const; private: - Controllers::HeartRateController& heartRateController; - Controllers::DateTime& dateTimeController; - Controllers::FS& fsController; - Pinetime::System::WakeLock wakeLock; + Controllers::InfiniSleepController& infiniSleepController; + System::WakeLock wakeLock; + Controllers::MotorController& motorController; - // For File IO - void WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const; + lv_obj_t *btnStop, *txtStop, *btnRecur, *txtRecur, *btnInfo, *enableSwitch; + lv_obj_t* lblampm = nullptr; + lv_obj_t* txtMessage = nullptr; + lv_obj_t* btnMessage = nullptr; + lv_task_t* taskStopWakeAlarm = nullptr; - int bpm = 0; - int prevBpm = 0; - int rollingBpm = 0; + enum class EnableButtonState { On, Off, Alerting }; + void DisableWakeAlarm(); + void SetRecurButtonState(); + void SetSwitchState(lv_anim_enable_t anim); + void SetWakeAlarm(); + void ShowAlarmInfo(); + void HideAlarmInfo(); + void ToggleRecurrence(); + void UpdateWakeAlarmTime(); + Widgets::Counter hourCounter = Widgets::Counter(0, 23, jetbrains_mono_76); + Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_76); - lv_obj_t* label_hr; + // Controllers::HeartRateController& heartRateController; + // Controllers::DateTime& dateTimeController; + // Controllers::FS& fsController; + // Pinetime::System::WakeLock wakeLock; - lv_task_t* mainRefreshTask; - lv_task_t* hrRefreshTask; + // // For File IO + // void WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const; + + // int bpm = 0; + // int prevBpm = 0; + // int rollingBpm = 0; + + // lv_obj_t* label_hr; + + // lv_task_t* mainRefreshTask; + // lv_task_t* hrRefreshTask; }; } @@ -62,7 +93,8 @@ namespace Pinetime { static constexpr Apps app = Apps::Sleep; static constexpr const char* icon = Screens::Symbols::bed; static Screens::Screen* Create(AppControllers& controllers) { - return new Screens::Sleep(controllers.heartRateController, controllers.dateTimeController, controllers.filesystem, *controllers.systemTask); + //return new Screens::Sleep(controllers.heartRateController, controllers.dateTimeController, controllers.filesystem, *controllers.systemTask); + return new Screens::Sleep(controllers.infiniSleepController, controllers.settingsController.GetClockType(), *controllers.systemTask, controllers.motorController); } }; } diff --git a/src/main.cpp b/src/main.cpp index 14a3dba8bb..c588211bd7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -126,7 +126,8 @@ Pinetime::Applications::DisplayApp displayApp(lcd, brightnessController, touchHandler, fs, - spiNorFlash); + spiNorFlash, + infiniSleepController); Pinetime::System::SystemTask systemTask(spi, spiNorFlash, diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 391b4ec3aa..de64c806bc 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -223,6 +223,8 @@ void SystemTask::Work() { break; case Messages::SetOffWakeAlarm: // Code the screen trigger here + GoToRunning(); + displayApp.PushMessage(Pinetime::Applications::Display::Messages::WakeAlarmTriggered); break; case Messages::BleConnected: displayApp.PushMessage(Pinetime::Applications::Display::Messages::NotifyDeviceActivity); From 0087ee473424e726c77805a384d729cf274a4f7a Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 13:55:24 -0500 Subject: [PATCH 014/123] updated log messages --- src/components/infinisleep/InfiniSleepController.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 17e2ba9a79..e3f680ff12 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -131,21 +131,21 @@ void InfiniSleepController::LoadSettingsFromFile() { WakeAlarmSettings wakeAlarmBuffer; if (fs.FileOpen(&wakeAlarmFile, "/.system/sleep/wakeAlarm.dat", LFS_O_RDONLY) != LFS_ERR_OK) { - NRF_LOG_WARNING("[AlarmController] Failed to open alarm data file"); + NRF_LOG_WARNING("[InfiniSleepController] Failed to open alarm data file"); return; } fs.FileRead(&wakeAlarmFile, reinterpret_cast(&wakeAlarmBuffer), sizeof(wakeAlarmBuffer)); fs.FileClose(&wakeAlarmFile); if (wakeAlarmBuffer.version != wakeAlarmFormatVersion) { - NRF_LOG_WARNING("[AlarmController] Loaded alarm settings has version %u instead of %u, discarding", + NRF_LOG_WARNING("[InfiniSleepController] Loaded alarm settings has version %u instead of %u, discarding", wakeAlarmBuffer.version, wakeAlarmFormatVersion); return; } wakeAlarm = wakeAlarmBuffer; - NRF_LOG_INFO("[AlarmController] Loaded alarm settings from file"); + NRF_LOG_INFO("[InfiniSleepController] Loaded alarm settings from file"); } void InfiniSleepController::SaveSettingsToFile() const { @@ -156,11 +156,11 @@ void InfiniSleepController::SaveSettingsToFile() const { fs.DirClose(&systemDir); lfs_file_t alarmFile; if (fs.FileOpen(&alarmFile, "/.system/sleep/wakeAlarm.dat", LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) { - NRF_LOG_WARNING("[AlarmController] Failed to open alarm data file for saving"); + NRF_LOG_WARNING("[InfiniSleepController] Failed to open alarm data file for saving"); return; } fs.FileWrite(&alarmFile, reinterpret_cast(&wakeAlarm), sizeof(wakeAlarm)); fs.FileClose(&alarmFile); - NRF_LOG_INFO("[AlarmController] Saved alarm settings with format version %u to file", wakeAlarm.version); + NRF_LOG_INFO("[InfiniSleepController] Saved alarm settings with format version %u to file", wakeAlarm.version); } \ No newline at end of file From 37adfbaf445740b38c22bdb475fb2a973ac02b7c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 14:29:24 -0500 Subject: [PATCH 015/123] Started working on screen states --- src/displayapp/screens/Sleep.cpp | 23 +++++++++++++++++++++-- src/displayapp/screens/Sleep.h | 3 +++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 0b3321abb6..aaf882d674 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -7,6 +7,8 @@ #include "components/motor/MotorController.h" #include "systemtask/SystemTask.h" +#include + using namespace Pinetime::Applications::Screens; using Pinetime::Controllers::InfiniSleepController; @@ -164,6 +166,23 @@ bool Sleep::OnButtonPushed() { } bool Sleep::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + + // The cases for swiping to change page on app + switch (event) { + case TouchEvents::SwipeLeft: + if (displayState != SleepDisplayState::Alarm) { + displayState = static_cast(static_cast(displayState) - 1); + } + NRF_LOG_INFO("SwipeLeft: %d", static_cast(displayState)); + return true; + case TouchEvents::SwipeRight: + if (displayState != SleepDisplayState::Settings) { + displayState = static_cast(static_cast(displayState) + 1); + } + NRF_LOG_INFO("SwipeRight: %d", static_cast(displayState)); + return true; + } + // Don't allow closing the screen by swiping while the alarm is alerting return infiniSleepController.IsAlerting() && event == TouchEvents::SwipeDown; } @@ -252,7 +271,7 @@ void Sleep::HideAlarmInfo() { } void Sleep::SetRecurButtonState() { - using Pinetime::Controllers::AlarmController; + using Pinetime::Controllers::InfiniSleepController; switch (infiniSleepController.Recurrence()) { case InfiniSleepController::RecurType::None: lv_label_set_text_static(txtRecur, "ONCE"); @@ -266,7 +285,7 @@ void Sleep::SetRecurButtonState() { } void Sleep::ToggleRecurrence() { - using Pinetime::Controllers::AlarmController; + using Pinetime::Controllers::InfiniSleepController; switch (infiniSleepController.Recurrence()) { case InfiniSleepController::RecurType::None: infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::Daily); diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index b115efa8f7..81f6dc45c3 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -27,6 +27,9 @@ namespace Pinetime { bool OnTouchEvent(TouchEvents event) override; void OnValueChanged(); void StopAlerting(); + + enum class SleepDisplayState { Alarm, Info, Settings }; + SleepDisplayState displayState = SleepDisplayState::Alarm; // void Refresh() override; From bd5bcaa132994674f5ddc26fc208e37d5169edfd Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 14:47:01 -0500 Subject: [PATCH 016/123] Implemented Alarm page Function --- src/displayapp/screens/Sleep.cpp | 55 +++++++++++++++++++++++++------- src/displayapp/screens/Sleep.h | 7 +++- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index aaf882d674..644c1a11ed 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -33,8 +33,44 @@ Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, Controllers::Settings::ClockType clockType, System::SystemTask& systemTask, Controllers::MotorController& motorController) - : infiniSleepController {infiniSleepController}, wakeLock(systemTask), motorController {motorController} { + : infiniSleepController {infiniSleepController}, wakeLock(systemTask), motorController {motorController}, clockType {clockType} { + UpdateDisplay(); +} + +Sleep::~Sleep() { + if (infiniSleepController.IsAlerting()) { + StopAlerting(); + } + lv_obj_clean(lv_scr_act()); + infiniSleepController.SaveWakeAlarm(); +} + +void Sleep::DisableWakeAlarm() { + if (infiniSleepController.IsEnabled()) { + infiniSleepController.DisableWakeAlarm(); + lv_switch_off(enableSwitch, LV_ANIM_ON); + } +} + +void Sleep::UpdateDisplay() { + // Clear the screen + lv_obj_clean(lv_scr_act()); + // Draw the screen + switch (displayState) { + case SleepDisplayState::Alarm: + DrawAlarmScreen(); + break; + case SleepDisplayState::Info: + DrawInfoScreen(); + break; + case SleepDisplayState::Settings: + DrawSettingsScreen(); + break; + } +} + +void Sleep::DrawAlarmScreen() { hourCounter.Create(); lv_obj_align(hourCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); if (clockType == Controllers::Settings::ClockType::H12) { @@ -109,19 +145,12 @@ Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, } } -Sleep::~Sleep() { - if (infiniSleepController.IsAlerting()) { - StopAlerting(); - } - lv_obj_clean(lv_scr_act()); - infiniSleepController.SaveWakeAlarm(); +void Sleep::DrawInfoScreen() { + } -void Sleep::DisableWakeAlarm() { - if (infiniSleepController.IsEnabled()) { - infiniSleepController.DisableWakeAlarm(); - lv_switch_off(enableSwitch, LV_ANIM_ON); - } +void Sleep::DrawSettingsScreen() { + } void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { @@ -172,12 +201,14 @@ bool Sleep::OnTouchEvent(Pinetime::Applications::TouchEvents event) { case TouchEvents::SwipeLeft: if (displayState != SleepDisplayState::Alarm) { displayState = static_cast(static_cast(displayState) - 1); + UpdateDisplay(); } NRF_LOG_INFO("SwipeLeft: %d", static_cast(displayState)); return true; case TouchEvents::SwipeRight: if (displayState != SleepDisplayState::Settings) { displayState = static_cast(static_cast(displayState) + 1); + UpdateDisplay(); } NRF_LOG_INFO("SwipeRight: %d", static_cast(displayState)); return true; diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 81f6dc45c3..454ff79895 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -27,7 +27,7 @@ namespace Pinetime { bool OnTouchEvent(TouchEvents event) override; void OnValueChanged(); void StopAlerting(); - + void UpdateDisplay(); enum class SleepDisplayState { Alarm, Info, Settings }; SleepDisplayState displayState = SleepDisplayState::Alarm; @@ -53,6 +53,7 @@ namespace Pinetime { Controllers::InfiniSleepController& infiniSleepController; System::WakeLock wakeLock; Controllers::MotorController& motorController; + Controllers::Settings::ClockType clockType; lv_obj_t *btnStop, *txtStop, *btnRecur, *txtRecur, *btnInfo, *enableSwitch; lv_obj_t* lblampm = nullptr; @@ -72,6 +73,10 @@ namespace Pinetime { Widgets::Counter hourCounter = Widgets::Counter(0, 23, jetbrains_mono_76); Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_76); + void DrawAlarmScreen(); + void DrawInfoScreen(); + void DrawSettingsScreen(); + // Controllers::HeartRateController& heartRateController; // Controllers::DateTime& dateTimeController; // Controllers::FS& fsController; From a01a99178601c6924927f7a2e85377e8c0bbc26c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 15:18:49 -0500 Subject: [PATCH 017/123] Started Framework for settings page --- src/displayapp/screens/Sleep.cpp | 36 +++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 644c1a11ed..b2a7368307 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -146,11 +146,45 @@ void Sleep::DrawAlarmScreen() { } void Sleep::DrawInfoScreen() { - + lv_obj_t* lblInfo = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(lblInfo, "InfiniTime\nSleep\nApp"); + lv_obj_align(lblInfo, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); } void Sleep::DrawSettingsScreen() { + lv_obj_t* lblSettings = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(lblSettings, "Settings"); + lv_obj_align(lblSettings, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 10); + + struct Setting { + const char* name; + bool enabled; + int offsetAfter = 30; + }; + + Setting settings[] = { + {"Body Tracking", false}, + {"Heart Rate\nTracking", false, 60}, + {"Gradual Wake", false}, + {"Smart Alarm\n(alpha)", false} + }; + + int y_offset = 50; + for (const auto& setting : settings) { + lv_obj_t* lblSetting = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(lblSetting, setting.name); + lv_obj_align(lblSetting, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); + + lv_obj_t* toggle = lv_switch_create(lv_scr_act(), nullptr); + if (setting.enabled) { + lv_switch_on(toggle, LV_ANIM_OFF); + } else { + lv_switch_off(toggle, LV_ANIM_OFF); + } + lv_obj_align(toggle, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -10, y_offset); + y_offset += setting.offsetAfter; // Increase the offset to provide better spacing + } } void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { From f605a299faec4dc5a46a07e066ede0bce8ec2140 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 30 Oct 2024 13:25:43 -0500 Subject: [PATCH 018/123] Made a sleep tracker settings struct in controller and made settings page save to variables --- .../infinisleep/InfiniSleepController.h | 42 +++++++++++++++++++ src/displayapp/screens/Sleep.cpp | 31 ++++++++++++-- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 2864a1659f..7dd1811d5d 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -47,6 +47,38 @@ namespace Pinetime { void SetRecurrence(RecurType recurrence); + bool BodyTrackingEnabled() const { + return infiniSleepSettings.bodyTracking; + } + + void SetBodyTrackingEnabled(bool enabled) { + infiniSleepSettings.bodyTracking = enabled; + } + + bool HeartRateTrackingEnabled() const { + return infiniSleepSettings.heartRateTracking; + } + + void SetHeartRateTrackingEnabled(bool enabled) { + infiniSleepSettings.heartRateTracking = enabled; + } + + bool GradualWakeEnabled() const { + return infiniSleepSettings.graddualWake; + } + + void SetGradualWakeEnabled(bool enabled) { + infiniSleepSettings.graddualWake = enabled; + } + + bool SmartAlarmEnabled() const { + return infiniSleepSettings.smartAlarm; + } + + void SetSmartAlarmEnabled(bool enabled) { + infiniSleepSettings.smartAlarm = enabled; + } + private: // Versions 255 is reserved for now, so the version field can be made // bigger, should it ever be needed. @@ -60,8 +92,18 @@ namespace Pinetime { bool isEnabled = false; }; + struct InfiniSleepSettings { + bool bodyTracking = false; + bool heartRateTracking = true; + bool graddualWake = false; + bool smartAlarm = false; + }; + bool isAlerting = false; bool wakeAlarmChanged = false; + bool isEnabled = false; + + InfiniSleepSettings infiniSleepSettings; Controllers::DateTime& dateTimeController; Controllers::FS& fs; diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index b2a7368307..019b2d4820 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -8,6 +8,7 @@ #include "systemtask/SystemTask.h" #include +#include using namespace Pinetime::Applications::Screens; using Pinetime::Controllers::InfiniSleepController; @@ -19,6 +20,25 @@ namespace { } } +extern InfiniSleepController infiniSleepController; + +static void settingsToggleEventHandler(lv_obj_t* obj, lv_event_t e) { + lv_obj_t* toggle = obj; + const char* setting_name = static_cast(obj->user_data); + + bool enabled = lv_switch_get_state(toggle); + + if (strcmp(setting_name, "Body Tracking") == 0) { + infiniSleepController.SetBodyTrackingEnabled(enabled); + } else if (strcmp(setting_name, "Heart Rate\nTracking") == 0) { + infiniSleepController.SetHeartRateTrackingEnabled(enabled); + } else if (strcmp(setting_name, "Gradual Wake") == 0) { + infiniSleepController.SetGradualWakeEnabled(enabled); + } else if (strcmp(setting_name, "Smart Alarm\n(alpha)") == 0) { + infiniSleepController.SetSmartAlarmEnabled(enabled); + } + } + static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { auto* screen = static_cast(obj->user_data); screen->OnButtonEvent(obj, event); @@ -163,10 +183,10 @@ void Sleep::DrawSettingsScreen() { }; Setting settings[] = { - {"Body Tracking", false}, - {"Heart Rate\nTracking", false, 60}, - {"Gradual Wake", false}, - {"Smart Alarm\n(alpha)", false} + {"Body Tracking", infiniSleepController.BodyTrackingEnabled()}, + {"Heart Rate\nTracking", infiniSleepController.HeartRateTrackingEnabled(), 60}, + {"Gradual Wake", infiniSleepController.GradualWakeEnabled()}, + {"Smart Alarm\n(alpha)", infiniSleepController.SmartAlarmEnabled()} }; int y_offset = 50; @@ -176,6 +196,7 @@ void Sleep::DrawSettingsScreen() { lv_obj_align(lblSetting, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); lv_obj_t* toggle = lv_switch_create(lv_scr_act(), nullptr); + toggle->user_data = const_cast(setting.name); if (setting.enabled) { lv_switch_on(toggle, LV_ANIM_OFF); } else { @@ -183,6 +204,8 @@ void Sleep::DrawSettingsScreen() { } lv_obj_align(toggle, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -10, y_offset); + lv_obj_set_event_cb(toggle, settingsToggleEventHandler); + y_offset += setting.offsetAfter; // Increase the offset to provide better spacing } } From 2d27608344dd1cb964b9a289984f558f92879324 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 30 Oct 2024 13:40:39 -0500 Subject: [PATCH 019/123] Updated toggleEventHandler to check event type --- src/displayapp/screens/Sleep.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 019b2d4820..45981e4141 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -23,9 +23,12 @@ namespace { extern InfiniSleepController infiniSleepController; static void settingsToggleEventHandler(lv_obj_t* obj, lv_event_t e) { + if (e != LV_EVENT_VALUE_CHANGED) { + return; + } lv_obj_t* toggle = obj; const char* setting_name = static_cast(obj->user_data); - + bool enabled = lv_switch_get_state(toggle); if (strcmp(setting_name, "Body Tracking") == 0) { @@ -269,6 +272,8 @@ bool Sleep::OnTouchEvent(Pinetime::Applications::TouchEvents event) { } NRF_LOG_INFO("SwipeRight: %d", static_cast(displayState)); return true; + default: + break; } // Don't allow closing the screen by swiping while the alarm is alerting From 46891cfa9e3e4e64ad343e209515a8745736f3ba Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 30 Oct 2024 21:10:33 -0500 Subject: [PATCH 020/123] added saving and reading of InfiniSleepSettings --- .../infinisleep/InfiniSleepController.cpp | 32 +++++++++++++++++++ .../infinisleep/InfiniSleepController.h | 9 +++++- src/displayapp/screens/Sleep.cpp | 5 +++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index e3f680ff12..781c0a102c 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -36,6 +36,14 @@ void InfiniSleepController::SaveWakeAlarm() { wakeAlarmChanged = false; } +void InfiniSleepController::SaveInfiniSleepSettings() { + // verify is save needed + if (settingsChanged) { + SaveSettingsToFile(); + } + settingsChanged = false; +} + void InfiniSleepController::SetWakeAlarmTime(uint8_t wakeAlarmHr, uint8_t wakeAlarmMin) { if (wakeAlarm.hours == wakeAlarmHr && wakeAlarm.minutes == wakeAlarmMin) { return; @@ -146,6 +154,20 @@ void InfiniSleepController::LoadSettingsFromFile() { wakeAlarm = wakeAlarmBuffer; NRF_LOG_INFO("[InfiniSleepController] Loaded alarm settings from file"); + + lfs_file_t infiniSleepSettingsFile; + InfiniSleepSettings infiniSleepSettingsBuffer; + + if (fs.FileOpen(&infiniSleepSettingsFile, "/.system/sleep/infiniSleepSettings.dat", LFS_O_RDONLY) != LFS_ERR_OK) { + NRF_LOG_WARNING("[InfiniSleepController] Failed to open InfiniSleep settings file"); + return; + } + + fs.FileRead(&infiniSleepSettingsFile, reinterpret_cast(&infiniSleepSettingsBuffer), sizeof(infiniSleepSettingsBuffer)); + fs.FileClose(&infiniSleepSettingsFile); + + infiniSleepSettings = infiniSleepSettingsBuffer; + NRF_LOG_INFO("[InfiniSleepController] Loaded InfiniSleep settings from file"); } void InfiniSleepController::SaveSettingsToFile() const { @@ -163,4 +185,14 @@ void InfiniSleepController::SaveSettingsToFile() const { fs.FileWrite(&alarmFile, reinterpret_cast(&wakeAlarm), sizeof(wakeAlarm)); fs.FileClose(&alarmFile); NRF_LOG_INFO("[InfiniSleepController] Saved alarm settings with format version %u to file", wakeAlarm.version); + + lfs_file_t settingsFile; + if (fs.FileOpen(&settingsFile, "/.system/sleep/infiniSleepSettings.dat", LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) { + NRF_LOG_WARNING("[InfiniSleepController] Failed to open InfiniSleep settings file for saving"); + return; + } + + fs.FileWrite(&settingsFile, reinterpret_cast(&infiniSleepSettings), sizeof(infiniSleepSettings)); + fs.FileClose(&settingsFile); + NRF_LOG_INFO("[InfiniSleepController] Saved InfiniSleep settings"); } \ No newline at end of file diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 7dd1811d5d..1e39cb1fae 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -17,6 +17,7 @@ namespace Pinetime { void Init(System::SystemTask* systemTask); void SaveWakeAlarm(); + void SaveInfiniSleepSettings(); void SetWakeAlarmTime(uint8_t wakeAlarmHr, uint8_t wakeAlarmMin); void ScheduleWakeAlarm(); void DisableWakeAlarm(); @@ -79,6 +80,10 @@ namespace Pinetime { infiniSleepSettings.smartAlarm = enabled; } + void SetSettingsChanged() { + settingsChanged = true; + } + private: // Versions 255 is reserved for now, so the version field can be made // bigger, should it ever be needed. @@ -90,7 +95,8 @@ namespace Pinetime { uint8_t minutes = 0; RecurType recurrence = RecurType::None; bool isEnabled = false; - }; + uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; + };; struct InfiniSleepSettings { bool bodyTracking = false; @@ -102,6 +108,7 @@ namespace Pinetime { bool isAlerting = false; bool wakeAlarmChanged = false; bool isEnabled = false; + bool settingsChanged = false; InfiniSleepSettings infiniSleepSettings; diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 45981e4141..3483e80089 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -33,12 +33,16 @@ static void settingsToggleEventHandler(lv_obj_t* obj, lv_event_t e) { if (strcmp(setting_name, "Body Tracking") == 0) { infiniSleepController.SetBodyTrackingEnabled(enabled); + infiniSleepController.SetSettingsChanged(); } else if (strcmp(setting_name, "Heart Rate\nTracking") == 0) { infiniSleepController.SetHeartRateTrackingEnabled(enabled); + infiniSleepController.SetSettingsChanged(); } else if (strcmp(setting_name, "Gradual Wake") == 0) { infiniSleepController.SetGradualWakeEnabled(enabled); + infiniSleepController.SetSettingsChanged(); } else if (strcmp(setting_name, "Smart Alarm\n(alpha)") == 0) { infiniSleepController.SetSmartAlarmEnabled(enabled); + infiniSleepController.SetSettingsChanged(); } } @@ -67,6 +71,7 @@ Sleep::~Sleep() { } lv_obj_clean(lv_scr_act()); infiniSleepController.SaveWakeAlarm(); + infiniSleepController.SaveInfiniSleepSettings(); } void Sleep::DisableWakeAlarm() { From 9508312ca938505adffd6a14f8900e62ba96eb1d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 31 Oct 2024 00:40:29 -0500 Subject: [PATCH 021/123] Started working on gradual wake, but not being triggered right now. --- .../infinisleep/InfiniSleepController.cpp | 40 ++++++++++++++++++- .../infinisleep/InfiniSleepController.h | 23 +++++++++-- src/displayapp/DisplayApp.cpp | 10 +++++ src/displayapp/Messages.h | 1 + src/displayapp/screens/Sleep.cpp | 2 +- src/systemtask/Messages.h | 1 + src/systemtask/SystemTask.cpp | 4 ++ 7 files changed, 76 insertions(+), 5 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 781c0a102c..e3c43cf04b 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -16,11 +16,21 @@ namespace { auto* controller = static_cast(pvTimerGetTimerID(xTimer)); controller->SetOffWakeAlarmNow(); } + + void SetOffGradualWake(TimerHandle_t xTimer) { + auto* controller = static_cast(pvTimerGetTimerID(xTimer)); + if (controller->GetInfiniSleepSettings().graddualWake) { + return; + } + controller->SetOffGradualWakeNow(); + } } void InfiniSleepController::Init(System::SystemTask* systemTask) { this->systemTask = systemTask; wakeAlarmTimer = xTimerCreate("WakeAlarm", 1, pdFALSE, this, SetOffWakeAlarm); + gradualWakeTimer = xTimerCreate("GradualWake", 1, pdFALSE, this, SetOffGradualWake); + LoadSettingsFromFile(); if (wakeAlarm.isEnabled) { NRF_LOG_INFO("[InfiniSleepController] Loaded wake alarm was enabled, scheduling"); @@ -56,6 +66,9 @@ void InfiniSleepController::SetWakeAlarmTime(uint8_t wakeAlarmHr, uint8_t wakeAl void InfiniSleepController::ScheduleWakeAlarm() { // Determine the next time the wake alarm needs to go off and set the timer xTimerStop(wakeAlarmTimer, 0); + xTimerStop(gradualWakeTimer, 0); + + gradualWakeStep = 2; auto now = dateTimeController.CurrentDateTime(); wakeAlarmTime = now; @@ -86,10 +99,22 @@ void InfiniSleepController::ScheduleWakeAlarm() { // now can convert back to a time_point wakeAlarmTime = std::chrono::system_clock::from_time_t(std::mktime(tmWakeAlarmTime)); - auto secondsToWakeAlarm = std::chrono::duration_cast(wakeAlarmTime - now).count(); + secondsToWakeAlarm = std::chrono::duration_cast(wakeAlarmTime - now).count(); xTimerChangePeriod(wakeAlarmTimer, secondsToWakeAlarm * configTICK_RATE_HZ, 0); xTimerStart(wakeAlarmTimer, 0); + // make sure graudal wake steps are possible + while (gradualWakeStep > -1 && secondsToWakeAlarm <= wakeAlarm.gradualWakeSteps[gradualWakeStep]) { + gradualWakeStep--; + } + + // Calculate the period for the gradualWakeTimer + if (infiniSleepSettings.graddualWake && gradualWakeStep >= 0) { + int64_t gradualWakePeriod = ((secondsToWakeAlarm - wakeAlarm.gradualWakeSteps[gradualWakeStep--])) / (configTICK_RATE_HZ); + xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); + xTimerStart(gradualWakeTimer, 0); + } + if (!wakeAlarm.isEnabled) { wakeAlarm.isEnabled = true; wakeAlarmChanged = true; @@ -102,6 +127,8 @@ uint32_t InfiniSleepController::SecondsToWakeAlarm() const { void InfiniSleepController::DisableWakeAlarm() { xTimerStop(wakeAlarmTimer, 0); + xTimerStop(gradualWakeTimer, 0); + gradualWakeStep = 9; isAlerting = false; if (wakeAlarm.isEnabled) { wakeAlarm.isEnabled = false; @@ -114,6 +141,17 @@ void InfiniSleepController::SetOffWakeAlarmNow() { systemTask->PushMessage(System::Messages::SetOffWakeAlarm); } +void InfiniSleepController::SetOffGradualWakeNow() { + //isGradualWakeAlerting = true; + systemTask->PushMessage(System::Messages::SetOffGradualWake); + // Calculate the period for the gradualWakeTimer + if (infiniSleepSettings.graddualWake && gradualWakeStep >= 0) { + int64_t gradualWakePeriod = ((secondsToWakeAlarm - wakeAlarm.gradualWakeSteps[gradualWakeStep--])) / (configTICK_RATE_HZ); + xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); + xTimerStart(gradualWakeTimer, 0); + } +} + void InfiniSleepController::StopAlerting() { isAlerting = false; // Disable the alarm unless it is recurring diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 1e39cb1fae..5613542227 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -5,6 +5,8 @@ #include #include "components/datetime/DateTimeController.h" +#include + namespace Pinetime { namespace System { class SystemTask; @@ -22,6 +24,7 @@ namespace Pinetime { void ScheduleWakeAlarm(); void DisableWakeAlarm(); void SetOffWakeAlarmNow(); + void SetOffGradualWakeNow(); uint32_t SecondsToWakeAlarm() const; void StopAlerting(); enum class RecurType { None, Daily, Weekdays }; @@ -84,7 +87,6 @@ namespace Pinetime { settingsChanged = true; } - private: // Versions 255 is reserved for now, so the version field can be made // bigger, should it ever be needed. static constexpr uint8_t wakeAlarmFormatVersion = 1; @@ -95,8 +97,12 @@ namespace Pinetime { uint8_t minutes = 0; RecurType recurrence = RecurType::None; bool isEnabled = false; - uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; - };; + uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; // In seconds + }; + + WakeAlarmSettings GetWakeAlarm() const { + return wakeAlarm; + } struct InfiniSleepSettings { bool bodyTracking = false; @@ -105,7 +111,17 @@ namespace Pinetime { bool smartAlarm = false; }; + InfiniSleepSettings GetInfiniSleepSettings() const { + return infiniSleepSettings; + } + + int64_t secondsToWakeAlarm = 0; + + private: + bool isAlerting = false; + bool isGradualWakeAlerting = false; + uint8_t gradualWakeStep = 8; // used to keep track of which step to use bool wakeAlarmChanged = false; bool isEnabled = false; bool settingsChanged = false; @@ -116,6 +132,7 @@ namespace Pinetime { Controllers::FS& fs; System::SystemTask* systemTask = nullptr; TimerHandle_t wakeAlarmTimer; + TimerHandle_t gradualWakeTimer; WakeAlarmSettings wakeAlarm; std::chrono::time_point wakeAlarmTime; diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index d0526c21b6..bb83827998 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -396,6 +396,16 @@ void DisplayApp::Refresh() { LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); } break; + case Messages::GradualWakeTriggered: + if (currentApp == Apps::Sleep) { + //auto* sleep = static_cast(currentScreen.get()); + //sleep->SetGradualWakeAlerting(); + } else { + LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); + } + motorController.RunForDuration(static_cast(3000)); + NRF_LOG_INFO("Gradual wake triggered"); + break; case Messages::ShowPairingKey: LoadNewScreen(Apps::PassKey, DisplayApp::FullRefreshDirections::Up); motorController.RunForDuration(35); diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index d2062a32b4..6143591e67 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -23,6 +23,7 @@ namespace Pinetime { ShowPairingKey, AlarmTriggered, WakeAlarmTriggered, + GradualWakeTriggered, Chime, BleRadioEnableToggle, }; diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 3483e80089..e49ed4127e 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -323,7 +323,7 @@ void Sleep::StopAlerting() { } void Sleep::SetSwitchState(lv_anim_enable_t anim) { - if (infiniSleepController.IsEnabled()) { + if (infiniSleepController.GetWakeAlarm().isEnabled) { lv_switch_on(enableSwitch, anim); } else { lv_switch_off(enableSwitch, anim); diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h index d00b27c150..7e844b37f7 100644 --- a/src/systemtask/Messages.h +++ b/src/systemtask/Messages.h @@ -26,6 +26,7 @@ namespace Pinetime { OnPairing, SetOffAlarm, SetOffWakeAlarm, + SetOffGradualWake, MeasureBatteryTimerExpired, BatteryPercentageUpdated, StartFileTransfer, diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index de64c806bc..52ee9cf7ff 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -226,6 +226,10 @@ void SystemTask::Work() { GoToRunning(); displayApp.PushMessage(Pinetime::Applications::Display::Messages::WakeAlarmTriggered); break; + case Messages::SetOffGradualWake: + GoToRunning(); + displayApp.PushMessage(Pinetime::Applications::Display::Messages::GradualWakeTriggered); + break; case Messages::BleConnected: displayApp.PushMessage(Pinetime::Applications::Display::Messages::NotifyDeviceActivity); isBleDiscoveryTimerRunning = true; From bd34483bf6b03000645be3beed06ca6450791ef3 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 31 Oct 2024 10:27:30 -0500 Subject: [PATCH 022/123] Fixed gradual wake triggers --- src/components/infinisleep/InfiniSleepController.cpp | 10 +++++----- src/components/infinisleep/InfiniSleepController.h | 2 +- src/displayapp/screens/Sleep.cpp | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index e3c43cf04b..cc24c7c0b2 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -19,7 +19,7 @@ namespace { void SetOffGradualWake(TimerHandle_t xTimer) { auto* controller = static_cast(pvTimerGetTimerID(xTimer)); - if (controller->GetInfiniSleepSettings().graddualWake) { + if (controller->GetInfiniSleepSettings().graddualWake == false) { return; } controller->SetOffGradualWakeNow(); @@ -68,7 +68,7 @@ void InfiniSleepController::ScheduleWakeAlarm() { xTimerStop(wakeAlarmTimer, 0); xTimerStop(gradualWakeTimer, 0); - gradualWakeStep = 2; + gradualWakeStep = 8; auto now = dateTimeController.CurrentDateTime(); wakeAlarmTime = now; @@ -99,7 +99,7 @@ void InfiniSleepController::ScheduleWakeAlarm() { // now can convert back to a time_point wakeAlarmTime = std::chrono::system_clock::from_time_t(std::mktime(tmWakeAlarmTime)); - secondsToWakeAlarm = std::chrono::duration_cast(wakeAlarmTime - now).count(); + int64_t secondsToWakeAlarm = std::chrono::duration_cast(wakeAlarmTime - now).count(); xTimerChangePeriod(wakeAlarmTimer, secondsToWakeAlarm * configTICK_RATE_HZ, 0); xTimerStart(wakeAlarmTimer, 0); @@ -110,7 +110,7 @@ void InfiniSleepController::ScheduleWakeAlarm() { // Calculate the period for the gradualWakeTimer if (infiniSleepSettings.graddualWake && gradualWakeStep >= 0) { - int64_t gradualWakePeriod = ((secondsToWakeAlarm - wakeAlarm.gradualWakeSteps[gradualWakeStep--])) / (configTICK_RATE_HZ); + int64_t gradualWakePeriod = ((secondsToWakeAlarm - wakeAlarm.gradualWakeSteps[gradualWakeStep--])) * (configTICK_RATE_HZ); xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); } @@ -146,7 +146,7 @@ void InfiniSleepController::SetOffGradualWakeNow() { systemTask->PushMessage(System::Messages::SetOffGradualWake); // Calculate the period for the gradualWakeTimer if (infiniSleepSettings.graddualWake && gradualWakeStep >= 0) { - int64_t gradualWakePeriod = ((secondsToWakeAlarm - wakeAlarm.gradualWakeSteps[gradualWakeStep--])) / (configTICK_RATE_HZ); + int64_t gradualWakePeriod = ((SecondsToWakeAlarm() - wakeAlarm.gradualWakeSteps[gradualWakeStep--])) * (configTICK_RATE_HZ); xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); } diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 5613542227..8c1c8d270c 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -115,7 +115,7 @@ namespace Pinetime { return infiniSleepSettings; } - int64_t secondsToWakeAlarm = 0; + //int64_t secondsToWakeAlarm = 0; private: diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index e49ed4127e..5dfa26c78a 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -75,7 +75,7 @@ Sleep::~Sleep() { } void Sleep::DisableWakeAlarm() { - if (infiniSleepController.IsEnabled()) { + if (infiniSleepController.GetWakeAlarm().isEnabled) { infiniSleepController.DisableWakeAlarm(); lv_switch_off(enableSwitch, LV_ANIM_ON); } @@ -343,7 +343,7 @@ void Sleep::ShowAlarmInfo() { txtMessage = lv_label_create(btnMessage, nullptr); lv_obj_set_style_local_bg_color(btnMessage, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_NAVY); - if (infiniSleepController.IsEnabled()) { + if (infiniSleepController.GetWakeAlarm().isEnabled) { auto timeToAlarm = infiniSleepController.SecondsToWakeAlarm(); auto daysToAlarm = timeToAlarm / 86400; From e0fb70ba17cb70246c97dbede41596efca0159dd Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 31 Oct 2024 11:44:46 -0500 Subject: [PATCH 023/123] fixed build error for always true conditions (dataType issues) --- src/components/infinisleep/InfiniSleepController.cpp | 12 ++++++------ src/components/infinisleep/InfiniSleepController.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index cc24c7c0b2..cab15f5022 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -68,7 +68,7 @@ void InfiniSleepController::ScheduleWakeAlarm() { xTimerStop(wakeAlarmTimer, 0); xTimerStop(gradualWakeTimer, 0); - gradualWakeStep = 8; + gradualWakeStep = 9; auto now = dateTimeController.CurrentDateTime(); wakeAlarmTime = now; @@ -104,13 +104,13 @@ void InfiniSleepController::ScheduleWakeAlarm() { xTimerStart(wakeAlarmTimer, 0); // make sure graudal wake steps are possible - while (gradualWakeStep > -1 && secondsToWakeAlarm <= wakeAlarm.gradualWakeSteps[gradualWakeStep]) { + while (gradualWakeStep != 0 && secondsToWakeAlarm <= wakeAlarm.gradualWakeSteps[gradualWakeStep-1]) { gradualWakeStep--; } // Calculate the period for the gradualWakeTimer - if (infiniSleepSettings.graddualWake && gradualWakeStep >= 0) { - int64_t gradualWakePeriod = ((secondsToWakeAlarm - wakeAlarm.gradualWakeSteps[gradualWakeStep--])) * (configTICK_RATE_HZ); + if (infiniSleepSettings.graddualWake && gradualWakeStep != 0) { + int64_t gradualWakePeriod = ((secondsToWakeAlarm - wakeAlarm.gradualWakeSteps[-1+gradualWakeStep--])) * (configTICK_RATE_HZ); xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); } @@ -145,8 +145,8 @@ void InfiniSleepController::SetOffGradualWakeNow() { //isGradualWakeAlerting = true; systemTask->PushMessage(System::Messages::SetOffGradualWake); // Calculate the period for the gradualWakeTimer - if (infiniSleepSettings.graddualWake && gradualWakeStep >= 0) { - int64_t gradualWakePeriod = ((SecondsToWakeAlarm() - wakeAlarm.gradualWakeSteps[gradualWakeStep--])) * (configTICK_RATE_HZ); + if (infiniSleepSettings.graddualWake && gradualWakeStep != 0) { + int64_t gradualWakePeriod = ((SecondsToWakeAlarm() - wakeAlarm.gradualWakeSteps[-1+gradualWakeStep--])) * (configTICK_RATE_HZ); xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); } diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 8c1c8d270c..27944addc7 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -121,7 +121,7 @@ namespace Pinetime { bool isAlerting = false; bool isGradualWakeAlerting = false; - uint8_t gradualWakeStep = 8; // used to keep track of which step to use + uint8_t gradualWakeStep = 9; // used to keep track of which step to use, in position form not idex bool wakeAlarmChanged = false; bool isEnabled = false; bool settingsChanged = false; From cf3a6a25bb77d96379a707ae6c35a886d52712e9 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 1 Nov 2024 23:57:15 -0500 Subject: [PATCH 024/123] Moved gradualSteps array out of settings Struct, updated motor controller to handle longer run times as input, fixed swipe motions in sleep app --- .../infinisleep/InfiniSleepController.cpp | 24 +++++++++---------- .../infinisleep/InfiniSleepController.h | 4 +++- src/components/motor/MotorController.cpp | 2 +- src/components/motor/MotorController.h | 2 +- src/displayapp/screens/Sleep.cpp | 6 ++--- src/displayapp/screens/Sleep.h | 2 ++ 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index cab15f5022..e4c0a26fc3 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -104,13 +104,13 @@ void InfiniSleepController::ScheduleWakeAlarm() { xTimerStart(wakeAlarmTimer, 0); // make sure graudal wake steps are possible - while (gradualWakeStep != 0 && secondsToWakeAlarm <= wakeAlarm.gradualWakeSteps[gradualWakeStep-1]) { + while (gradualWakeStep != 0 && secondsToWakeAlarm <= gradualWakeSteps[gradualWakeStep-1]) { gradualWakeStep--; } // Calculate the period for the gradualWakeTimer if (infiniSleepSettings.graddualWake && gradualWakeStep != 0) { - int64_t gradualWakePeriod = ((secondsToWakeAlarm - wakeAlarm.gradualWakeSteps[-1+gradualWakeStep--])) * (configTICK_RATE_HZ); + int64_t gradualWakePeriod = ((secondsToWakeAlarm - gradualWakeSteps[-1+gradualWakeStep--])) * (configTICK_RATE_HZ); xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); } @@ -146,7 +146,7 @@ void InfiniSleepController::SetOffGradualWakeNow() { systemTask->PushMessage(System::Messages::SetOffGradualWake); // Calculate the period for the gradualWakeTimer if (infiniSleepSettings.graddualWake && gradualWakeStep != 0) { - int64_t gradualWakePeriod = ((SecondsToWakeAlarm() - wakeAlarm.gradualWakeSteps[-1+gradualWakeStep--])) * (configTICK_RATE_HZ); + int64_t gradualWakePeriod = ((SecondsToWakeAlarm() - gradualWakeSteps[-1+gradualWakeStep--])) * (configTICK_RATE_HZ); xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); } @@ -176,7 +176,7 @@ void InfiniSleepController::LoadSettingsFromFile() { lfs_file_t wakeAlarmFile; WakeAlarmSettings wakeAlarmBuffer; - if (fs.FileOpen(&wakeAlarmFile, "/.system/sleep/wakeAlarm.dat", LFS_O_RDONLY) != LFS_ERR_OK) { + if (fs.FileOpen(&wakeAlarmFile, "wakeAlarm.dat", LFS_O_RDONLY) != LFS_ERR_OK) { NRF_LOG_WARNING("[InfiniSleepController] Failed to open alarm data file"); return; } @@ -196,7 +196,7 @@ void InfiniSleepController::LoadSettingsFromFile() { lfs_file_t infiniSleepSettingsFile; InfiniSleepSettings infiniSleepSettingsBuffer; - if (fs.FileOpen(&infiniSleepSettingsFile, "/.system/sleep/infiniSleepSettings.dat", LFS_O_RDONLY) != LFS_ERR_OK) { + if (fs.FileOpen(&infiniSleepSettingsFile, "infiniSleepSettings.dat", LFS_O_RDONLY) != LFS_ERR_OK) { NRF_LOG_WARNING("[InfiniSleepController] Failed to open InfiniSleep settings file"); return; } @@ -209,13 +209,13 @@ void InfiniSleepController::LoadSettingsFromFile() { } void InfiniSleepController::SaveSettingsToFile() const { - lfs_dir systemDir; - if (fs.DirOpen("/.system/sleep", &systemDir) != LFS_ERR_OK) { - fs.DirCreate("/.system/sleep"); - } - fs.DirClose(&systemDir); + // lfs_dir systemDir; + // if (fs.DirOpen("/system/sleep", &systemDir) != LFS_ERR_OK) { + // fs.DirCreate("/system/sleep"); + // } + // fs.DirClose(&systemDir); lfs_file_t alarmFile; - if (fs.FileOpen(&alarmFile, "/.system/sleep/wakeAlarm.dat", LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) { + if (fs.FileOpen(&alarmFile, "wakeAlarm.dat", LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) { NRF_LOG_WARNING("[InfiniSleepController] Failed to open alarm data file for saving"); return; } @@ -225,7 +225,7 @@ void InfiniSleepController::SaveSettingsToFile() const { NRF_LOG_INFO("[InfiniSleepController] Saved alarm settings with format version %u to file", wakeAlarm.version); lfs_file_t settingsFile; - if (fs.FileOpen(&settingsFile, "/.system/sleep/infiniSleepSettings.dat", LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) { + if (fs.FileOpen(&settingsFile, "infiniSleepSettings.dat", LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) { NRF_LOG_WARNING("[InfiniSleepController] Failed to open InfiniSleep settings file for saving"); return; } diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 27944addc7..8544833f78 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -97,9 +97,11 @@ namespace Pinetime { uint8_t minutes = 0; RecurType recurrence = RecurType::None; bool isEnabled = false; - uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; // In seconds }; + uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; // In seconds + + WakeAlarmSettings GetWakeAlarm() const { return wakeAlarm; } diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index 4e392416ae..b280c2f988 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -18,7 +18,7 @@ void MotorController::Ring(TimerHandle_t xTimer) { motorController->RunForDuration(50); } -void MotorController::RunForDuration(uint8_t motorDuration) { +void MotorController::RunForDuration(uint16_t motorDuration) { if (motorDuration > 0 && xTimerChangePeriod(shortVib, pdMS_TO_TICKS(motorDuration), 0) == pdPASS && xTimerStart(shortVib, 0) == pdPASS) { nrf_gpio_pin_clear(PinMap::Motor); } diff --git a/src/components/motor/MotorController.h b/src/components/motor/MotorController.h index 6dea6d1f9e..1437349e5c 100644 --- a/src/components/motor/MotorController.h +++ b/src/components/motor/MotorController.h @@ -12,7 +12,7 @@ namespace Pinetime { MotorController() = default; void Init(); - void RunForDuration(uint8_t motorDuration); + void RunForDuration(uint16_t motorDuration); void StartRinging(); void StopRinging(); diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 5dfa26c78a..4b74ee961f 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -263,14 +263,14 @@ bool Sleep::OnTouchEvent(Pinetime::Applications::TouchEvents event) { // The cases for swiping to change page on app switch (event) { - case TouchEvents::SwipeLeft: + case TouchEvents::SwipeRight: if (displayState != SleepDisplayState::Alarm) { displayState = static_cast(static_cast(displayState) - 1); UpdateDisplay(); } NRF_LOG_INFO("SwipeLeft: %d", static_cast(displayState)); return true; - case TouchEvents::SwipeRight: + case TouchEvents::SwipeLeft: if (displayState != SleepDisplayState::Settings) { displayState = static_cast(static_cast(displayState) + 1); UpdateDisplay(); @@ -304,7 +304,7 @@ void Sleep::UpdateWakeAlarmTime() { void Sleep::SetAlerting() { lv_obj_set_hidden(enableSwitch, true); lv_obj_set_hidden(btnStop, false); - taskStopWakeAlarm = lv_task_create(StopAlarmTaskCallback, pdMS_TO_TICKS(60 * 1000), LV_TASK_PRIO_MID, this); + taskStopWakeAlarm = lv_task_create(StopAlarmTaskCallback, pdMS_TO_TICKS(600 * 1000), LV_TASK_PRIO_MID, this); motorController.StartRinging(); wakeLock.Lock(); } diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 454ff79895..749a58f1db 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -9,6 +9,8 @@ #include "systemtask/WakeLock.h" #include "Symbols.h" +#define GRADUAL_WAKE_MOTOR_DURATION_MS 1000 + //#include //#include // for accumulate //#include // for abs From 54b8427de7f7282360628d630c0b1a7983f86485 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 1 Nov 2024 23:58:07 -0500 Subject: [PATCH 025/123] updated gradualWakeTriggered to use the defined constant --- src/displayapp/DisplayApp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index bb83827998..e1d583f655 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -403,7 +403,7 @@ void DisplayApp::Refresh() { } else { LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); } - motorController.RunForDuration(static_cast(3000)); + motorController.RunForDuration(GRADUAL_WAKE_MOTOR_DURATION_MS); NRF_LOG_INFO("Gradual wake triggered"); break; case Messages::ShowPairingKey: From 44c68347c38b851eccbbe8e7596e94add61b6cfe Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 2 Nov 2024 11:59:27 -0500 Subject: [PATCH 026/123] Switched settings to checkboxes --- src/displayapp/screens/Sleep.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 4b74ee961f..f030607719 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -26,10 +26,9 @@ static void settingsToggleEventHandler(lv_obj_t* obj, lv_event_t e) { if (e != LV_EVENT_VALUE_CHANGED) { return; } - lv_obj_t* toggle = obj; + const char* setting_name = static_cast(obj->user_data); - - bool enabled = lv_switch_get_state(toggle); + bool enabled = lv_checkbox_is_checked(obj); if (strcmp(setting_name, "Body Tracking") == 0) { infiniSleepController.SetBodyTrackingEnabled(enabled); @@ -199,20 +198,23 @@ void Sleep::DrawSettingsScreen() { int y_offset = 50; for (const auto& setting : settings) { - lv_obj_t* lblSetting = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_static(lblSetting, setting.name); - lv_obj_align(lblSetting, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); + //lv_obj_t* lblSetting = lv_label_create(lv_scr_act(), nullptr); + // lv_label_set_text_static(lblSetting, setting.name); + // lv_obj_align(lblSetting, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); + + lv_obj_t* checkbox = lv_checkbox_create(lv_scr_act(), nullptr); + checkbox->user_data = const_cast(setting.name); + lv_checkbox_set_text_static(checkbox, const_cast(setting.name)); - lv_obj_t* toggle = lv_switch_create(lv_scr_act(), nullptr); - toggle->user_data = const_cast(setting.name); if (setting.enabled) { - lv_switch_on(toggle, LV_ANIM_OFF); + lv_checkbox_set_checked(checkbox, true); } else { - lv_switch_off(toggle, LV_ANIM_OFF); + lv_checkbox_set_checked(checkbox, false); } - lv_obj_align(toggle, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -10, y_offset); + lv_obj_align(checkbox, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); - lv_obj_set_event_cb(toggle, settingsToggleEventHandler); + lv_obj_set_event_cb(checkbox, settingsToggleEventHandler); + //lv_obj_set_event_cb(lblSetting, settingsToggleEventHandler); y_offset += setting.offsetAfter; // Increase the offset to provide better spacing } From 05542f73602dd61a6693215c12cb404264442ce0 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 2 Nov 2024 12:01:21 -0500 Subject: [PATCH 027/123] Changed start page and made update display go to alarm if alerting --- src/displayapp/screens/Sleep.cpp | 3 +++ src/displayapp/screens/Sleep.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index f030607719..eba76b9183 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -83,6 +83,9 @@ void Sleep::DisableWakeAlarm() { void Sleep::UpdateDisplay() { // Clear the screen lv_obj_clean(lv_scr_act()); + if (infiniSleepController.IsAlerting()) { + displayState = SleepDisplayState::Alarm; + } // Draw the screen switch (displayState) { case SleepDisplayState::Alarm: diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 749a58f1db..bca10bafcf 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -31,7 +31,7 @@ namespace Pinetime { void StopAlerting(); void UpdateDisplay(); enum class SleepDisplayState { Alarm, Info, Settings }; - SleepDisplayState displayState = SleepDisplayState::Alarm; + SleepDisplayState displayState = SleepDisplayState::Info; // void Refresh() override; From 30cd1ddebb923d8e79e7f8612e4cbc8f0fc3b8b6 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 2 Nov 2024 18:24:42 -0500 Subject: [PATCH 028/123] Removed timer on alerting so alerts indeffinately, started working on start tracking button --- src/displayapp/screens/Sleep.cpp | 20 +++++++++++++------- src/displayapp/screens/Sleep.h | 1 + 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index eba76b9183..5874dc8c4d 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -50,10 +50,10 @@ static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { screen->OnButtonEvent(obj, event); } -static void StopAlarmTaskCallback(lv_task_t* task) { - auto* screen = static_cast(task->user_data); - screen->StopAlerting(); -} +// static void StopAlarmTaskCallback(lv_task_t* task) { +// auto* screen = static_cast(task->user_data); +// screen->StopAlerting(); +// } Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, Controllers::Settings::ClockType clockType, @@ -177,8 +177,14 @@ void Sleep::DrawAlarmScreen() { void Sleep::DrawInfoScreen() { lv_obj_t* lblInfo = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_static(lblInfo, "InfiniTime\nSleep\nApp"); - lv_obj_align(lblInfo, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + lv_label_set_text_static(lblInfo, "InfiniSleep"); + lv_obj_align(lblInfo, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 5); + + trackerToggleBtn = lv_btn_create(lv_scr_act(), nullptr); + lv_obj_align(trackerToggleBtn, lv_scr_act(), LV_ALIGN_CENTER, 0, 40); + + trackerToggleLabel = lv_label_create(trackerToggleBtn, nullptr); + lv_label_set_text(trackerToggleLabel, "Start"); } void Sleep::DrawSettingsScreen() { @@ -309,7 +315,7 @@ void Sleep::UpdateWakeAlarmTime() { void Sleep::SetAlerting() { lv_obj_set_hidden(enableSwitch, true); lv_obj_set_hidden(btnStop, false); - taskStopWakeAlarm = lv_task_create(StopAlarmTaskCallback, pdMS_TO_TICKS(600 * 1000), LV_TASK_PRIO_MID, this); + //taskStopWakeAlarm = lv_task_create(StopAlarmTaskCallback, pdMS_TO_TICKS(60 * 1000), LV_TASK_PRIO_MID, this); motorController.StartRinging(); wakeLock.Lock(); } diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index bca10bafcf..975667f855 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -58,6 +58,7 @@ namespace Pinetime { Controllers::Settings::ClockType clockType; lv_obj_t *btnStop, *txtStop, *btnRecur, *txtRecur, *btnInfo, *enableSwitch; + lv_obj_t *trackerToggleBtn, *trackerToggleLabel; lv_obj_t* lblampm = nullptr; lv_obj_t* txtMessage = nullptr; lv_obj_t* btnMessage = nullptr; From 92e4417e5c1be952c5a441862acdfb721417fdc9 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 2 Nov 2024 19:07:41 -0500 Subject: [PATCH 029/123] Made tracker toggle btn --- .../infinisleep/InfiniSleepController.h | 9 +++++++++ src/displayapp/screens/Sleep.cpp | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 8544833f78..a2f84d1d9b 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -117,6 +117,15 @@ namespace Pinetime { return infiniSleepSettings; } + bool ToggleTracker() { + isEnabled = !isEnabled; + return isEnabled; + } + + bool IsTrackerEnabled() const { + return isEnabled; + } + //int64_t secondsToWakeAlarm = 0; private: diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 5874dc8c4d..c7105d8f4b 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -181,10 +181,18 @@ void Sleep::DrawInfoScreen() { lv_obj_align(lblInfo, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 5); trackerToggleBtn = lv_btn_create(lv_scr_act(), nullptr); + trackerToggleBtn->user_data = this; lv_obj_align(trackerToggleBtn, lv_scr_act(), LV_ALIGN_CENTER, 0, 40); trackerToggleLabel = lv_label_create(trackerToggleBtn, nullptr); - lv_label_set_text(trackerToggleLabel, "Start"); + if (infiniSleepController.IsTrackerEnabled()) { + lv_label_set_text_static(trackerToggleLabel, "Stop"); + lv_obj_set_style_local_bg_color(trackerToggleBtn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); + } else { + lv_label_set_text_static(trackerToggleLabel, "Start"); + lv_obj_set_style_local_bg_color(trackerToggleBtn, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN); + } + lv_obj_set_event_cb(trackerToggleBtn, btnEventHandler); } void Sleep::DrawSettingsScreen() { @@ -251,6 +259,11 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } return; } + if (obj == trackerToggleBtn) { + infiniSleepController.ToggleTracker(); + UpdateDisplay(); + return; + } if (obj == btnRecur) { DisableWakeAlarm(); ToggleRecurrence(); From e2515d47252cba82e05002ac52b589a981d80d6c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 00:18:54 -0600 Subject: [PATCH 030/123] Updated rescheduling of wake alarm when system time changed --- src/systemtask/SystemTask.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 52ee9cf7ff..66018eced5 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -208,6 +208,9 @@ void SystemTask::Work() { if (alarmController.IsEnabled()) { alarmController.ScheduleAlarm(); } + if (infiniSleepController.GetWakeAlarm().isEnabled) { + infiniSleepController.ScheduleWakeAlarm(); + } break; case Messages::OnNewNotification: if (settingsController.GetNotificationStatus() == Pinetime::Controllers::Settings::Notification::On) { From 6b7c5ffd595f13617dbb086ab165d2be95ddc614 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 00:37:07 -0600 Subject: [PATCH 031/123] accoutning for abnormal data --- src/displayapp/screens/Sleep.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index c7105d8f4b..3d4a8e1adf 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -403,6 +403,11 @@ void Sleep::SetRecurButtonState() { break; case InfiniSleepController::RecurType::Weekdays: lv_label_set_text_static(txtRecur, "MON-FRI"); + break; + default: + infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::None); + SetRecurButtonState(); + break; } } From 4b8c4d41779cf69de4bbd87264f1b5a3fd40957d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 00:43:10 -0600 Subject: [PATCH 032/123] removed recursive --- src/displayapp/screens/Sleep.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 3d4a8e1adf..a7d1a3fb41 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -406,7 +406,7 @@ void Sleep::SetRecurButtonState() { break; default: infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::None); - SetRecurButtonState(); + lv_label_set_text_static(txtRecur, "ONCE"); break; } } From fbe5111646b5d66758fc28f60ede4127957a05c4 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 01:16:02 -0600 Subject: [PATCH 033/123] moved else logic --- src/displayapp/screens/Sleep.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index a7d1a3fb41..66a9f3760f 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -404,10 +404,6 @@ void Sleep::SetRecurButtonState() { case InfiniSleepController::RecurType::Weekdays: lv_label_set_text_static(txtRecur, "MON-FRI"); break; - default: - infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::None); - lv_label_set_text_static(txtRecur, "ONCE"); - break; } } @@ -422,6 +418,10 @@ void Sleep::ToggleRecurrence() { break; case InfiniSleepController::RecurType::Weekdays: infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::None); + break; + default: + infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::None); + break; } SetRecurButtonState(); } \ No newline at end of file From 21e2debdc838dbb766414a2cb02f1b7b43970eab Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 01:45:05 -0600 Subject: [PATCH 034/123] undid stuff, works now ?? idek --- src/displayapp/screens/Sleep.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 66a9f3760f..f9ff51c357 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -419,9 +419,6 @@ void Sleep::ToggleRecurrence() { case InfiniSleepController::RecurType::Weekdays: infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::None); break; - default: - infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::None); - break; } SetRecurButtonState(); } \ No newline at end of file From d3d1df60c223fe04984fb94abbd9be5bee37e9dd Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 10:06:58 -0600 Subject: [PATCH 035/123] removed swiping while alerting --- src/displayapp/screens/Sleep.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index f9ff51c357..a4ce3cd5b5 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -285,6 +285,12 @@ bool Sleep::OnButtonPushed() { bool Sleep::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + // Swiping should be ignored when in alerting state + if (infiniSleepController.IsAlerting() && + (event != TouchEvents::SwipeDown && event != TouchEvents::SwipeUp && event != TouchEvents::SwipeLeft && event != TouchEvents::SwipeRight)) { + return true; + } + // The cases for swiping to change page on app switch (event) { case TouchEvents::SwipeRight: From ac1f9613d467f90b0fb2eaf3fd9bdb608e2e43b8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 13:22:31 -0600 Subject: [PATCH 036/123] Added snoozing and made side button require 5 presses --- .../infinisleep/InfiniSleepController.cpp | 2 ++ .../infinisleep/InfiniSleepController.h | 28 +++++++++++++++++ src/displayapp/screens/Sleep.cpp | 30 +++++++++++++++++-- src/displayapp/screens/Sleep.h | 1 + 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index e4c0a26fc3..32600e7b68 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -68,6 +68,8 @@ void InfiniSleepController::ScheduleWakeAlarm() { xTimerStop(wakeAlarmTimer, 0); xTimerStop(gradualWakeTimer, 0); + pushesLeftToStopWakeAlarm = PSUHES_TO_STOP_ALARM; + gradualWakeStep = 9; auto now = dateTimeController.CurrentDateTime(); diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index a2f84d1d9b..85e75d1a72 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -7,6 +7,8 @@ #include +#define PSUHES_TO_STOP_ALARM 5 + namespace Pinetime { namespace System { class SystemTask; @@ -29,6 +31,23 @@ namespace Pinetime { void StopAlerting(); enum class RecurType { None, Daily, Weekdays }; + uint8_t pushesLeftToStopWakeAlarm = PSUHES_TO_STOP_ALARM; + + bool isSnoozing = false; + uint8_t preSnoozeMinutes = 10; + uint8_t preSnnoozeHours = 0; + + void SetPreSnoozeTime() { + preSnoozeMinutes = wakeAlarm.minutes; + preSnnoozeHours = wakeAlarm.hours; + } + + void RestorePreSnoozeTime() { + wakeAlarm.minutes = preSnoozeMinutes; + wakeAlarm.hours = preSnnoozeHours; + } + + uint8_t Hours() const { return wakeAlarm.hours; } @@ -126,6 +145,14 @@ namespace Pinetime { return isEnabled; } + uint8_t GetCurrentHour() { + return dateTimeController.Hours(); + } + + uint8_t GetCurrentMinute() { + return dateTimeController.Minutes(); + } + //int64_t secondsToWakeAlarm = 0; private: @@ -144,6 +171,7 @@ namespace Pinetime { System::SystemTask* systemTask = nullptr; TimerHandle_t wakeAlarmTimer; TimerHandle_t gradualWakeTimer; + TimerHandle_t trackerUpdateTimer; WakeAlarmSettings wakeAlarm; std::chrono::time_point wakeAlarmTime; diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index a4ce3cd5b5..0a93148eba 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -130,7 +130,7 @@ void Sleep::DrawAlarmScreen() { lv_obj_set_event_cb(btnStop, btnEventHandler); lv_obj_set_size(btnStop, 115, 50); lv_obj_align(btnStop, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); - lv_obj_set_style_local_bg_color(btnStop, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); + lv_obj_set_style_local_bg_color(btnStop, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); txtStop = lv_label_create(btnStop, nullptr); lv_label_set_text_static(txtStop, Symbols::stop); lv_obj_set_hidden(btnStop, true); @@ -241,6 +241,7 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { if (event == LV_EVENT_CLICKED) { if (obj == btnStop) { StopAlerting(); + SnoozeWakeAlarm(); return; } if (obj == btnInfo) { @@ -277,8 +278,16 @@ bool Sleep::OnButtonPushed() { return true; } if (infiniSleepController.IsAlerting()) { - StopAlerting(); - return true; + if (infiniSleepController.pushesLeftToStopWakeAlarm > 1) { + infiniSleepController.pushesLeftToStopWakeAlarm--; + return true; + } else { + infiniSleepController.isSnoozing = false; + infiniSleepController.RestorePreSnoozeTime(); + StopAlerting(); + UpdateDisplay(); + return true; + } } return false; } @@ -320,6 +329,21 @@ void Sleep::OnValueChanged() { UpdateWakeAlarmTime(); } +// Currently snoozes 5 minutes +void Sleep::SnoozeWakeAlarm() { + if (minuteCounter.GetValue() >= 55) { + minuteCounter.SetValue(0); + hourCounter.SetValue((infiniSleepController.GetCurrentHour() + 1)); + } else { + minuteCounter.SetValue(infiniSleepController.GetCurrentMinute() + 5); + } + infiniSleepController.SetPreSnoozeTime(); + infiniSleepController.isSnoozing = true; + UpdateWakeAlarmTime(); + SetSwitchState(LV_ANIM_OFF); + infiniSleepController.ScheduleWakeAlarm(); +} + void Sleep::UpdateWakeAlarmTime() { if (lblampm != nullptr) { if (hourCounter.GetValue() >= 12) { diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 975667f855..49cbf3330c 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -69,6 +69,7 @@ namespace Pinetime { void SetRecurButtonState(); void SetSwitchState(lv_anim_enable_t anim); void SetWakeAlarm(); + void SnoozeWakeAlarm(); void ShowAlarmInfo(); void HideAlarmInfo(); void ToggleRecurrence(); From 9689389578f12481c1d94280931627f3f88587c7 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 21:44:43 -0600 Subject: [PATCH 037/123] More setup for sleep tracking --- .../infinisleep/InfiniSleepController.cpp | 25 +++++++++++++++++++ .../infinisleep/InfiniSleepController.h | 13 ++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 32600e7b68..01f1950b9d 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -24,6 +24,11 @@ namespace { } controller->SetOffGradualWakeNow(); } + + void SetOffTrackerUpdate(TimerHandle_t xTimer) { + auto* controller = static_cast(pvTimerGetTimerID(xTimer)); + controller->UpdateTracker(); + } } void InfiniSleepController::Init(System::SystemTask* systemTask) { @@ -38,6 +43,26 @@ void InfiniSleepController::Init(System::SystemTask* systemTask) { } } +void InfiniSleepController::EnableTracker() { + DisableTracker(); + NRF_LOG_INFO("[InfiniSleepController] Enabling tracker"); + isEnabled = true; + trackerUpdateTimer = xTimerCreate("TrackerUpdate", 5 * configTICK_RATE_HZ, pdFALSE, this, SetOffTrackerUpdate); + xTimerStart(trackerUpdateTimer, 0); +} + +void InfiniSleepController::DisableTracker() { + NRF_LOG_INFO("[InfiniSleepController] Disabling tracker"); + xTimerStop(trackerUpdateTimer, 0); + isEnabled = false; +} + +void InfiniSleepController::UpdateTracker() { + NRF_LOG_INFO("[InfiniSleepController] Updating tracker"); + xTimerStop(trackerUpdateTimer, 0); + xTimerStart(trackerUpdateTimer, 0); +} + void InfiniSleepController::SaveWakeAlarm() { // verify is save needed if (wakeAlarmChanged) { diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 85e75d1a72..ad3bc0e460 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -8,6 +8,7 @@ #include #define PSUHES_TO_STOP_ALARM 5 +#define TRACKER_UPDATE_INTERVAL_MINS 5 namespace Pinetime { namespace System { @@ -61,9 +62,13 @@ namespace Pinetime { } bool IsEnabled() const { - return wakeAlarm.isEnabled; + return isEnabled; } + void EnableTracker(); + void DisableTracker(); + void UpdateTracker(); + RecurType Recurrence() const { return wakeAlarm.recurrence; } @@ -137,7 +142,11 @@ namespace Pinetime { } bool ToggleTracker() { - isEnabled = !isEnabled; + if (isEnabled) { + DisableTracker(); + } else { + EnableTracker(); + } return isEnabled; } From 38f2f96b0d5f4fce4d76d5c20f97c10cdc0020b8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 22:01:43 -0600 Subject: [PATCH 038/123] Fixed bug that doesnt restore original alarm time after multiple snooze --- src/components/infinisleep/InfiniSleepController.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index ad3bc0e460..267358cc60 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -39,6 +39,9 @@ namespace Pinetime { uint8_t preSnnoozeHours = 0; void SetPreSnoozeTime() { + if (preSnoozeMinutes != 255 || preSnnoozeHours != 255) { + return; + } preSnoozeMinutes = wakeAlarm.minutes; preSnnoozeHours = wakeAlarm.hours; } @@ -46,6 +49,8 @@ namespace Pinetime { void RestorePreSnoozeTime() { wakeAlarm.minutes = preSnoozeMinutes; wakeAlarm.hours = preSnnoozeHours; + preSnoozeMinutes = 255; + preSnnoozeHours = 255; } From a8c527fd03ef2a4b9491f5fc12938d469c5bbd63 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 6 Nov 2024 23:48:16 -0600 Subject: [PATCH 039/123] Added basic HR periodic reading for sleep tracking and Fixed gradual wake alarm bug --- .../infinisleep/InfiniSleepController.cpp | 77 ++++++++++++++++++- .../infinisleep/InfiniSleepController.h | 22 +++++- src/displayapp/Messages.h | 2 + src/displayapp/screens/Sleep.cpp | 6 ++ src/displayapp/screens/Sleep.h | 2 +- src/systemtask/Messages.h | 3 +- src/systemtask/SystemTask.cpp | 3 + 7 files changed, 108 insertions(+), 7 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 01f1950b9d..0dc199d2a8 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -7,8 +7,8 @@ using namespace Pinetime::Controllers; using namespace std::chrono_literals; -InfiniSleepController::InfiniSleepController(Controllers::DateTime& dateTimeController, Controllers::FS& fs) - : dateTimeController {dateTimeController}, fs {fs} { +InfiniSleepController::InfiniSleepController(Controllers::DateTime& dateTimeController, Controllers::FS& fs, Controllers::HeartRateController& heartRateController) + : dateTimeController {dateTimeController}, fs {fs}, heartRateController {heartRateController} { } namespace { @@ -59,6 +59,10 @@ void InfiniSleepController::DisableTracker() { void InfiniSleepController::UpdateTracker() { NRF_LOG_INFO("[InfiniSleepController] Updating tracker"); + + UpdateBPM(); + systemTask->PushMessage(System::Messages::SleepTrackerUpdate); + xTimerStop(trackerUpdateTimer, 0); xTimerStart(trackerUpdateTimer, 0); } @@ -199,6 +203,75 @@ void InfiniSleepController::SetRecurrence(RecurType recurrence) { wakeAlarmChanged = true; } +/* Sleep Tracking Section */ + +void InfiniSleepController::UpdateBPM() { + // Get the heart rate from the controller + prevBpm = bpm; + bpm = heartRateController.HeartRate(); + + if(prevBpm != 0) + rollingBpm = (rollingBpm + bpm) / 2; + else + rollingBpm = bpm; + + // Get the current time from DateTimeController + int hours = dateTimeController.Hours(); + int minutes = dateTimeController.Minutes(); + int seconds = dateTimeController.Seconds(); + + // Log the BPM and current time + NRF_LOG_INFO("BPM: %d at %02d:%02d:%02d", rollingBpm, hours, minutes, seconds); + + // Write data to CSV + const int motion = 0; // Placeholder for motion data + std::tuple data[1] = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; + WriteDataCSV("SleepTracker_Data.csv", data, 1); +} + +void InfiniSleepController::WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const { + lfs_file_t file; + int err = fs.FileOpen(&file, fileName, LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND); + if (err < 0) { + // Handle error + NRF_LOG_INFO("Error opening file: %d", err); + return; + } + + for (int i = 0; i < dataSize; ++i) { + int hours, minutes, seconds, bpm, motion; + std::tie(hours, minutes, seconds, bpm, motion) = data[i]; + char buffer[64]; + int len = snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d,%d,%d\n", hours, minutes, seconds, bpm, motion); + err = fs.FileWrite(&file, reinterpret_cast(buffer), len); + if (err < 0) { + // Handle error + NRF_LOG_INFO("Error writing to file: %d", err); + fs.FileClose(&file); + + return; + } + } + + fs.FileClose(&file); +} + +// Clear data in CSV +void InfiniSleepController::ClearDataCSV(const char* filename) const { + lfs_file_t file; + int err = fs.FileOpen(&file, filename, LFS_O_WRONLY | LFS_O_TRUNC); + if (err < 0) { + // Handle error + NRF_LOG_INFO("Error opening file: %d", err); + return; + } + + fs.FileClose(&file); + NRF_LOG_INFO("CSV data cleared"); +} + +/* Sleep Tracking Section End */ + void InfiniSleepController::LoadSettingsFromFile() { lfs_file_t wakeAlarmFile; WakeAlarmSettings wakeAlarmBuffer; diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 267358cc60..7b1c6e1172 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -4,6 +4,8 @@ #include #include #include "components/datetime/DateTimeController.h" +#include "components/fs/FS.h" +#include "components/heartrate/HeartRateController.h" #include @@ -18,7 +20,7 @@ namespace Pinetime { namespace Controllers { class InfiniSleepController { public: - InfiniSleepController(Controllers::DateTime& dateTimeCOntroller, Controllers::FS& fs); + InfiniSleepController(Controllers::DateTime& dateTimeCOntroller, Controllers::FS& , Controllers::HeartRateController& heartRateController); void Init(System::SystemTask* systemTask); void SaveWakeAlarm(); @@ -35,8 +37,8 @@ namespace Pinetime { uint8_t pushesLeftToStopWakeAlarm = PSUHES_TO_STOP_ALARM; bool isSnoozing = false; - uint8_t preSnoozeMinutes = 10; - uint8_t preSnnoozeHours = 0; + uint8_t preSnoozeMinutes = 255; + uint8_t preSnnoozeHours = 255; void SetPreSnoozeTime() { if (preSnoozeMinutes != 255 || preSnnoozeHours != 255) { @@ -47,6 +49,9 @@ namespace Pinetime { } void RestorePreSnoozeTime() { + if (preSnoozeMinutes == 255 || preSnnoozeHours == 255) { + return; + } wakeAlarm.minutes = preSnoozeMinutes; wakeAlarm.hours = preSnnoozeHours; preSnoozeMinutes = 255; @@ -169,6 +174,12 @@ namespace Pinetime { //int64_t secondsToWakeAlarm = 0; + int bpm = 0; + int prevBpm = 0; + int rollingBpm = 0; + + void UpdateBPM(); + private: bool isAlerting = false; @@ -182,6 +193,7 @@ namespace Pinetime { Controllers::DateTime& dateTimeController; Controllers::FS& fs; + Controllers::HeartRateController& heartRateController; System::SystemTask* systemTask = nullptr; TimerHandle_t wakeAlarmTimer; TimerHandle_t gradualWakeTimer; @@ -191,6 +203,10 @@ namespace Pinetime { void LoadSettingsFromFile(); void SaveSettingsToFile() const; + + // For File IO + void WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const; + void ClearDataCSV(const char* fileName) const; }; } diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index 6143591e67..ce25df5a7b 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -26,6 +26,8 @@ namespace Pinetime { GradualWakeTriggered, Chime, BleRadioEnableToggle, + OnChargingEvent, + SleepTrackerUpdate, }; } } diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 0a93148eba..4c34df42a2 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -179,6 +179,12 @@ void Sleep::DrawInfoScreen() { lv_obj_t* lblInfo = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(lblInfo, "InfiniSleep"); lv_obj_align(lblInfo, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 5); + lv_obj_set_style_local_text_color(lblInfo, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); + + label_hr = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_fmt(label_hr, "HR: %d", infiniSleepController.rollingBpm); + lv_obj_align(label_hr, lblInfo, LV_ALIGN_CENTER, 0, 50); + lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); trackerToggleBtn = lv_btn_create(lv_scr_act(), nullptr); trackerToggleBtn->user_data = this; diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 49cbf3330c..7927e37564 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -93,7 +93,7 @@ namespace Pinetime { // int prevBpm = 0; // int rollingBpm = 0; - // lv_obj_t* label_hr; + lv_obj_t* label_hr; // lv_task_t* mainRefreshTask; // lv_task_t* hrRefreshTask; diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h index 7e844b37f7..1f61239608 100644 --- a/src/systemtask/Messages.h +++ b/src/systemtask/Messages.h @@ -31,7 +31,8 @@ namespace Pinetime { BatteryPercentageUpdated, StartFileTransfer, StopFileTransfer, - BleRadioEnableToggle + BleRadioEnableToggle, + SleepTrackerUpdate, }; } } diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 66018eced5..378ed3304b 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -372,6 +372,9 @@ void SystemTask::Work() { nimbleController.DisableRadio(); } break; + case Messages::SleepTrackerUpdate: + displayApp.PushMessage(Pinetime::Applications::Display::Messages::SleepTrackerUpdate); + break; default: break; } From ba654f5403873d15842c6e87355a819c04391d33 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 7 Nov 2024 00:09:03 -0600 Subject: [PATCH 040/123] Made a define statement for file name --- src/components/infinisleep/InfiniSleepController.cpp | 2 +- src/components/infinisleep/InfiniSleepController.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 0dc199d2a8..2121c3fc58 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -226,7 +226,7 @@ void InfiniSleepController::UpdateBPM() { // Write data to CSV const int motion = 0; // Placeholder for motion data std::tuple data[1] = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; - WriteDataCSV("SleepTracker_Data.csv", data, 1); + WriteDataCSV(TrackerDataFile, data, 1); } void InfiniSleepController::WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const { diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 7b1c6e1172..a95335a9db 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -11,6 +11,7 @@ #define PSUHES_TO_STOP_ALARM 5 #define TRACKER_UPDATE_INTERVAL_MINS 5 +#define TrackerDataFile "SleepTracker_Data.csv" namespace Pinetime { namespace System { @@ -155,6 +156,7 @@ namespace Pinetime { if (isEnabled) { DisableTracker(); } else { + ClearDataCSV(TrackerDataFile); EnableTracker(); } return isEnabled; From 7f9ab41d3ea838831a79e55f7840965b6022445b Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 8 Nov 2024 15:06:44 -0600 Subject: [PATCH 041/123] Made a new alarm for sleep in motor controller --- src/components/motor/MotorController.cpp | 16 ++++++++++++++++ src/components/motor/MotorController.h | 4 ++++ src/displayapp/screens/Sleep.cpp | 4 ++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index b280c2f988..044bc24bd2 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -11,6 +11,7 @@ void MotorController::Init() { shortVib = xTimerCreate("shortVib", 1, pdFALSE, nullptr, StopMotor); longVib = xTimerCreate("longVib", pdMS_TO_TICKS(1000), pdTRUE, this, Ring); + alarmVib = xTimerCreate("alarmVib", pdMS_TO_TICKS(500), pdTRUE, this, AlarmRing); } void MotorController::Ring(TimerHandle_t xTimer) { @@ -18,6 +19,11 @@ void MotorController::Ring(TimerHandle_t xTimer) { motorController->RunForDuration(50); } +void MotorController::AlarmRing(TimerHandle_t xTimer) { + auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); + motorController->RunForDuration(300); +} + void MotorController::RunForDuration(uint16_t motorDuration) { if (motorDuration > 0 && xTimerChangePeriod(shortVib, pdMS_TO_TICKS(motorDuration), 0) == pdPASS && xTimerStart(shortVib, 0) == pdPASS) { nrf_gpio_pin_clear(PinMap::Motor); @@ -34,6 +40,16 @@ void MotorController::StopRinging() { nrf_gpio_pin_set(PinMap::Motor); } +void MotorController::StartAlarm() { + RunForDuration(300); + xTimerStart(alarmVib, 0); +} + +void MotorController::StopAlarm() { + xTimerStop(alarmVib, 0); + nrf_gpio_pin_set(PinMap::Motor); +} + void MotorController::StopMotor(TimerHandle_t /*xTimer*/) { nrf_gpio_pin_set(PinMap::Motor); } diff --git a/src/components/motor/MotorController.h b/src/components/motor/MotorController.h index 1437349e5c..4acbeda710 100644 --- a/src/components/motor/MotorController.h +++ b/src/components/motor/MotorController.h @@ -15,12 +15,16 @@ namespace Pinetime { void RunForDuration(uint16_t motorDuration); void StartRinging(); void StopRinging(); + void StartAlarm(); + void StopAlarm(); private: static void Ring(TimerHandle_t xTimer); + static void AlarmRing(TimerHandle_t xTimer); static void StopMotor(TimerHandle_t xTimer); TimerHandle_t shortVib; TimerHandle_t longVib; + TimerHandle_t alarmVib; }; } } diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 4c34df42a2..fff9070dc8 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -365,13 +365,13 @@ void Sleep::SetAlerting() { lv_obj_set_hidden(enableSwitch, true); lv_obj_set_hidden(btnStop, false); //taskStopWakeAlarm = lv_task_create(StopAlarmTaskCallback, pdMS_TO_TICKS(60 * 1000), LV_TASK_PRIO_MID, this); - motorController.StartRinging(); + motorController.StartAlarm(); wakeLock.Lock(); } void Sleep::StopAlerting() { infiniSleepController.StopAlerting(); - motorController.StopRinging(); + motorController.StopAlarm(); SetSwitchState(LV_ANIM_OFF); if (taskStopWakeAlarm != nullptr) { lv_task_del(taskStopWakeAlarm); From 7843dfe3432212942db8a9d2ffe37594e718c3be Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 8 Nov 2024 16:43:50 -0600 Subject: [PATCH 042/123] Added refresh task for sleep app and added to info screen --- .../infinisleep/InfiniSleepController.h | 4 +++ src/displayapp/screens/Sleep.cpp | 25 ++++++++++++++----- src/displayapp/screens/Sleep.h | 4 +++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index a95335a9db..13dce8751b 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -40,6 +40,8 @@ namespace Pinetime { bool isSnoozing = false; uint8_t preSnoozeMinutes = 255; uint8_t preSnnoozeHours = 255; + uint8_t startTimeHours = 0; + uint8_t startTimeMinutes = 0; void SetPreSnoozeTime() { if (preSnoozeMinutes != 255 || preSnnoozeHours != 255) { @@ -157,6 +159,8 @@ namespace Pinetime { DisableTracker(); } else { ClearDataCSV(TrackerDataFile); + startTimeHours = GetCurrentHour(); + startTimeMinutes = GetCurrentMinute(); EnableTracker(); } return isEnabled; diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index fff9070dc8..cbe2f78b63 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -62,12 +62,14 @@ Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, : infiniSleepController {infiniSleepController}, wakeLock(systemTask), motorController {motorController}, clockType {clockType} { UpdateDisplay(); + taskRefresh = lv_task_create(RefreshTaskCallback, 2000, LV_TASK_PRIO_MID, this); } Sleep::~Sleep() { if (infiniSleepController.IsAlerting()) { StopAlerting(); } + lv_task_del(taskRefresh); lv_obj_clean(lv_scr_act()); infiniSleepController.SaveWakeAlarm(); infiniSleepController.SaveInfiniSleepSettings(); @@ -80,6 +82,10 @@ void Sleep::DisableWakeAlarm() { } } +void Sleep::Refresh() { + UpdateDisplay(); +} + void Sleep::UpdateDisplay() { // Clear the screen lv_obj_clean(lv_scr_act()); @@ -176,16 +182,23 @@ void Sleep::DrawAlarmScreen() { } void Sleep::DrawInfoScreen() { - lv_obj_t* lblInfo = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_static(lblInfo, "InfiniSleep"); - lv_obj_align(lblInfo, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 5); - lv_obj_set_style_local_text_color(lblInfo, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); + lv_obj_t* lblTime = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_fmt(lblTime, "%02d:%02d", infiniSleepController.GetCurrentHour(), infiniSleepController.GetCurrentMinute()); + lv_obj_align(lblTime, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 5); + lv_obj_set_style_local_text_color(lblTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); label_hr = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_fmt(label_hr, "HR: %d", infiniSleepController.rollingBpm); - lv_obj_align(label_hr, lblInfo, LV_ALIGN_CENTER, 0, 50); + lv_obj_align(label_hr, lblTime, LV_ALIGN_CENTER, 0, 50); lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); - + + if (infiniSleepController.IsEnabled()) { + label_start_time = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_fmt(label_start_time, "Began at: %02d:%02d", infiniSleepController.startTimeHours, infiniSleepController.startTimeMinutes); + lv_obj_align(label_start_time, label_hr, LV_ALIGN_CENTER, 0, 20); + lv_obj_set_style_local_text_color(label_start_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); + } + trackerToggleBtn = lv_btn_create(lv_scr_act(), nullptr); trackerToggleBtn->user_data = this; lv_obj_align(trackerToggleBtn, lv_scr_act(), LV_ALIGN_CENTER, 0, 40); diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 7927e37564..e7863d55c3 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -23,6 +23,7 @@ namespace Pinetime { //explicit Sleep(Controllers::HeartRateController& HeartRateController, Controllers::DateTime& DateTimeController, Controllers::FS& fsController, System::SystemTask& systemTask); explicit Sleep(Controllers::InfiniSleepController& infiniSleepController, Controllers::Settings::ClockType clockType, System::SystemTask& systemTask, Controllers::MotorController& motorController); ~Sleep() override; + void Refresh() override; void SetAlerting(); void OnButtonEvent(lv_obj_t* obj, lv_event_t event); bool OnButtonPushed() override; @@ -64,6 +65,8 @@ namespace Pinetime { lv_obj_t* btnMessage = nullptr; lv_task_t* taskStopWakeAlarm = nullptr; + lv_task_t* taskRefresh = nullptr; + enum class EnableButtonState { On, Off, Alerting }; void DisableWakeAlarm(); void SetRecurButtonState(); @@ -94,6 +97,7 @@ namespace Pinetime { // int rollingBpm = 0; lv_obj_t* label_hr; + lv_obj_t* label_start_time; // lv_task_t* mainRefreshTask; // lv_task_t* hrRefreshTask; From 39072716a1dec1d6e0c38473d13f3b23c87e2b92 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 8 Nov 2024 16:50:50 -0600 Subject: [PATCH 043/123] Updated main.cpp and added display update when sleep tracker is updated --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index c588211bd7..3efc6bb59d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -105,7 +105,7 @@ Pinetime::Drivers::Watchdog watchdog; Pinetime::Controllers::NotificationManager notificationManager; Pinetime::Controllers::MotionController motionController; Pinetime::Controllers::AlarmController alarmController {dateTimeController, fs}; -Pinetime::Controllers::InfiniSleepController infiniSleepController {dateTimeController, fs}; +Pinetime::Controllers::InfiniSleepController infiniSleepController {dateTimeController, fs, heartRateController}; Pinetime::Controllers::TouchHandler touchHandler; Pinetime::Controllers::ButtonHandler buttonHandler; From 5a65b314f961c2fe8ab9a919c00f2417068d88fb Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 8 Nov 2024 16:52:03 -0600 Subject: [PATCH 044/123] Last commit didn't have the SleepTrackerUpdate message --- src/displayapp/DisplayApp.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index e1d583f655..032982f891 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -406,6 +406,12 @@ void DisplayApp::Refresh() { motorController.RunForDuration(GRADUAL_WAKE_MOTOR_DURATION_MS); NRF_LOG_INFO("Gradual wake triggered"); break; + case Messages::SleepTrackerUpdate: + if (currentApp == Apps::Sleep) { + auto* sleep = static_cast(currentScreen.get()); + sleep->UpdateDisplay(); + } + break; case Messages::ShowPairingKey: LoadNewScreen(Apps::PassKey, DisplayApp::FullRefreshDirections::Up); motorController.RunForDuration(35); From ebd97c15d76a97b70785c1190ddc883b07bb0112 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 10 Nov 2024 02:57:35 -0600 Subject: [PATCH 045/123] Fixed bug where snoozing and closing saved the snooze time as alarm instead of pre snooze time --- src/components/infinisleep/InfiniSleepController.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 2121c3fc58..4636e47c66 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -315,14 +315,19 @@ void InfiniSleepController::SaveSettingsToFile() const { // } // fs.DirClose(&systemDir); lfs_file_t alarmFile; + WakeAlarmSettings tempWakeAlarm = wakeAlarm; + if (isSnoozing) { + tempWakeAlarm.hours = preSnnoozeHours; + tempWakeAlarm.minutes = preSnoozeMinutes; + } if (fs.FileOpen(&alarmFile, "wakeAlarm.dat", LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) { NRF_LOG_WARNING("[InfiniSleepController] Failed to open alarm data file for saving"); return; } - fs.FileWrite(&alarmFile, reinterpret_cast(&wakeAlarm), sizeof(wakeAlarm)); + fs.FileWrite(&alarmFile, reinterpret_cast(&tempWakeAlarm), sizeof(tempWakeAlarm)); fs.FileClose(&alarmFile); - NRF_LOG_INFO("[InfiniSleepController] Saved alarm settings with format version %u to file", wakeAlarm.version); + NRF_LOG_INFO("[InfiniSleepController] Saved alarm settings with format version %u to file", tempWakeAlarm.version); lfs_file_t settingsFile; if (fs.FileOpen(&settingsFile, "infiniSleepSettings.dat", LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) { From e9a4999acef1420a62da0c7c0cf7b0c898cf911f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 18 Nov 2024 13:04:50 -0600 Subject: [PATCH 046/123] Added ability to customize gradual wake intensity at each step --- src/components/infinisleep/InfiniSleepController.cpp | 1 + src/components/infinisleep/InfiniSleepController.h | 9 +++++++++ src/displayapp/DisplayApp.cpp | 2 +- src/displayapp/screens/Sleep.h | 2 +- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 4636e47c66..3807efe79a 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -100,6 +100,7 @@ void InfiniSleepController::ScheduleWakeAlarm() { pushesLeftToStopWakeAlarm = PSUHES_TO_STOP_ALARM; gradualWakeStep = 9; + gradualWakeVibration = 9; auto now = dateTimeController.CurrentDateTime(); wakeAlarmTime = now; diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 13dce8751b..f75812036c 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -136,7 +136,12 @@ namespace Pinetime { bool isEnabled = false; }; + // Dertermine the steps for the gradual wake alarm, the corresponding vibration durations determine the power of the vibration uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; // In seconds + uint16_t gradualWakeVibrationDurations[9] = {1200, 1200, 1000, 1000, 1000, 700, 700, 700, 500}; // In ms + + uint8_t gradualWakeVibration = 9; // used to keep track of which vibration duration to use, in position form not idex + WakeAlarmSettings GetWakeAlarm() const { @@ -186,6 +191,10 @@ namespace Pinetime { void UpdateBPM(); + uint8_t GetGradualWakeStep() const { + return (9 - gradualWakeStep) + 1; + } + private: bool isAlerting = false; diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 032982f891..3783b4c3a9 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -403,7 +403,7 @@ void DisplayApp::Refresh() { } else { LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); } - motorController.RunForDuration(GRADUAL_WAKE_MOTOR_DURATION_MS); + motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1+infiniSleepController.gradualWakeVibration--]); NRF_LOG_INFO("Gradual wake triggered"); break; case Messages::SleepTrackerUpdate: diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index e7863d55c3..993789e1bc 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -9,7 +9,7 @@ #include "systemtask/WakeLock.h" #include "Symbols.h" -#define GRADUAL_WAKE_MOTOR_DURATION_MS 1000 +//#define GRADUAL_WAKE_MOTOR_DURATION_MS 1000 //#include //#include // for accumulate From 7c3dcd06b17ad0cff23c8b334f11aac84beac2f0 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 18 Nov 2024 20:52:48 -0600 Subject: [PATCH 047/123] Added to info page and fixded total sleep display. Also put back code to auto-snooze the wake alarm after 3 minutes. --- .../infinisleep/InfiniSleepController.h | 8 +++ src/displayapp/screens/Sleep.cpp | 64 +++++++++++++++---- src/displayapp/screens/Sleep.h | 8 ++- 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index f75812036c..0035bbd117 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -9,6 +9,7 @@ #include +#define SNOOZE_MINUTES 3 #define PSUHES_TO_STOP_ALARM 5 #define TRACKER_UPDATE_INTERVAL_MINS 5 #define TrackerDataFile "SleepTracker_Data.csv" @@ -142,7 +143,14 @@ namespace Pinetime { uint8_t gradualWakeVibration = 9; // used to keep track of which vibration duration to use, in position form not idex + uint16_t sleepCycleDuration = 90; // sleep cycle duration in minutes + uint16_t GetSleepCycles() { + uint8_t hours = GetCurrentHour() - startTimeHours; + uint8_t minutes = GetCurrentMinute() - startTimeMinutes; + uint16_t totalMinutes = hours * 60 + minutes; + return totalMinutes * 100 / sleepCycleDuration; + } WakeAlarmSettings GetWakeAlarm() const { return wakeAlarm; diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index cbe2f78b63..65ab14bd42 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -50,10 +50,11 @@ static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { screen->OnButtonEvent(obj, event); } -// static void StopAlarmTaskCallback(lv_task_t* task) { -// auto* screen = static_cast(task->user_data); -// screen->StopAlerting(); -// } +static void SnoozeAlarmTaskCallback(lv_task_t* task) { + auto* screen = static_cast(task->user_data); + screen->StopAlerting(); + screen->SnoozeWakeAlarm(); +} Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, Controllers::Settings::ClockType clockType, @@ -199,9 +200,50 @@ void Sleep::DrawInfoScreen() { lv_obj_set_style_local_text_color(label_start_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); } + // The alarm info + label_alarm_time = lv_label_create(lv_scr_act(), nullptr); + if (infiniSleepController.GetWakeAlarm().isEnabled) { + lv_label_set_text_fmt(label_alarm_time, "Alarm at: %02d:%02d", infiniSleepController.GetWakeAlarm().hours, infiniSleepController.GetWakeAlarm().minutes); + } else { + lv_label_set_text_static(label_alarm_time, "Alarm is not set."); + } + lv_obj_align(label_alarm_time, label_hr, LV_ALIGN_CENTER, 0, 40); + lv_obj_set_style_local_text_color(label_alarm_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); + + // Gradual Wake info + label_gradual_wake = lv_label_create(lv_scr_act(), nullptr); + if (infiniSleepController.GetInfiniSleepSettings().graddualWake) { + lv_label_set_text_fmt(label_gradual_wake, "Gradual Wake: %d/9", infiniSleepController.gradualWakeVibration); + } else { + lv_label_set_text_static(label_gradual_wake, "Gradual Wake: OFF"); + } + lv_obj_align(label_gradual_wake, label_hr, LV_ALIGN_CENTER, 0, 60); + lv_obj_set_style_local_text_color(label_gradual_wake, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); + + // Sleep Cycles Info + if (infiniSleepController.IsEnabled()) { + label_sleep_cycles = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_fmt(label_sleep_cycles, "Sleep Cycles: %1i.%02i", infiniSleepController.GetSleepCycles() / 100, infiniSleepController.GetSleepCycles() % 100); + lv_obj_align(label_sleep_cycles, label_hr, LV_ALIGN_CENTER, 0, 80); + lv_obj_set_style_local_text_color(label_sleep_cycles, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); + } + + // Total sleep time + if (infiniSleepController.IsEnabled()) { + label_total_sleep = lv_label_create(lv_scr_act(), nullptr); + + uint8_t hours = infiniSleepController.GetCurrentHour() - infiniSleepController.startTimeHours; + uint8_t minutes = infiniSleepController.GetCurrentMinute() - infiniSleepController.startTimeMinutes; + uint16_t totalMinutes = hours * 60 + minutes; + + lv_label_set_text_fmt(label_total_sleep, "Total Sleep: %dh%dm", totalMinutes / 60, totalMinutes % 60); + lv_obj_align(label_total_sleep, label_hr, LV_ALIGN_CENTER, 0, 100); + lv_obj_set_style_local_text_color(label_total_sleep, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); + } + trackerToggleBtn = lv_btn_create(lv_scr_act(), nullptr); trackerToggleBtn->user_data = this; - lv_obj_align(trackerToggleBtn, lv_scr_act(), LV_ALIGN_CENTER, 0, 40); + lv_obj_align(trackerToggleBtn, lv_scr_act(), LV_ALIGN_CENTER, 0, 100); trackerToggleLabel = lv_label_create(trackerToggleBtn, nullptr); if (infiniSleepController.IsTrackerEnabled()) { @@ -348,13 +390,13 @@ void Sleep::OnValueChanged() { UpdateWakeAlarmTime(); } -// Currently snoozes 5 minutes +// Currently snoozes baeed on define statement in InfiniSleepController.h void Sleep::SnoozeWakeAlarm() { if (minuteCounter.GetValue() >= 55) { minuteCounter.SetValue(0); hourCounter.SetValue((infiniSleepController.GetCurrentHour() + 1)); } else { - minuteCounter.SetValue(infiniSleepController.GetCurrentMinute() + 5); + minuteCounter.SetValue(infiniSleepController.GetCurrentMinute() + SNOOZE_MINUTES); } infiniSleepController.SetPreSnoozeTime(); infiniSleepController.isSnoozing = true; @@ -377,7 +419,7 @@ void Sleep::UpdateWakeAlarmTime() { void Sleep::SetAlerting() { lv_obj_set_hidden(enableSwitch, true); lv_obj_set_hidden(btnStop, false); - //taskStopWakeAlarm = lv_task_create(StopAlarmTaskCallback, pdMS_TO_TICKS(60 * 1000), LV_TASK_PRIO_MID, this); + taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, pdMS_TO_TICKS(180 * 1000), LV_TASK_PRIO_MID, this); motorController.StartAlarm(); wakeLock.Lock(); } @@ -386,9 +428,9 @@ void Sleep::StopAlerting() { infiniSleepController.StopAlerting(); motorController.StopAlarm(); SetSwitchState(LV_ANIM_OFF); - if (taskStopWakeAlarm != nullptr) { - lv_task_del(taskStopWakeAlarm); - taskStopWakeAlarm = nullptr; + if (taskSnoozeWakeAlarm != nullptr) { + lv_task_del(taskSnoozeWakeAlarm); + taskSnoozeWakeAlarm = nullptr; } wakeLock.Release(); lv_obj_set_hidden(enableSwitch, false); diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 993789e1bc..70f76ec20c 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -30,6 +30,7 @@ namespace Pinetime { bool OnTouchEvent(TouchEvents event) override; void OnValueChanged(); void StopAlerting(); + void SnoozeWakeAlarm(); void UpdateDisplay(); enum class SleepDisplayState { Alarm, Info, Settings }; SleepDisplayState displayState = SleepDisplayState::Info; @@ -63,7 +64,7 @@ namespace Pinetime { lv_obj_t* lblampm = nullptr; lv_obj_t* txtMessage = nullptr; lv_obj_t* btnMessage = nullptr; - lv_task_t* taskStopWakeAlarm = nullptr; + lv_task_t* taskSnoozeWakeAlarm = nullptr; lv_task_t* taskRefresh = nullptr; @@ -72,7 +73,6 @@ namespace Pinetime { void SetRecurButtonState(); void SetSwitchState(lv_anim_enable_t anim); void SetWakeAlarm(); - void SnoozeWakeAlarm(); void ShowAlarmInfo(); void HideAlarmInfo(); void ToggleRecurrence(); @@ -98,6 +98,10 @@ namespace Pinetime { lv_obj_t* label_hr; lv_obj_t* label_start_time; + lv_obj_t* label_alarm_time; + lv_obj_t* label_gradual_wake; + lv_obj_t* label_total_sleep; + lv_obj_t* label_sleep_cycles; // lv_task_t* mainRefreshTask; // lv_task_t* hrRefreshTask; From d7b656b986b5c2747b82bc5b6d8af8e46f287597 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 19 Nov 2024 09:53:26 -0600 Subject: [PATCH 048/123] Made info screen show info from last session after tracker stopped --- .../infinisleep/InfiniSleepController.cpp | 4 ++- .../infinisleep/InfiniSleepController.h | 22 +++++++++++----- src/displayapp/screens/Sleep.cpp | 25 ++++++++----------- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 3807efe79a..904bb439d6 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -60,7 +60,9 @@ void InfiniSleepController::DisableTracker() { void InfiniSleepController::UpdateTracker() { NRF_LOG_INFO("[InfiniSleepController] Updating tracker"); - UpdateBPM(); + if (infiniSleepSettings.heartRateTracking) { + UpdateBPM(); + } systemTask->PushMessage(System::Messages::SleepTrackerUpdate); xTimerStop(trackerUpdateTimer, 0); diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 0035bbd117..b0dc78f127 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -13,6 +13,7 @@ #define PSUHES_TO_STOP_ALARM 5 #define TRACKER_UPDATE_INTERVAL_MINS 5 #define TrackerDataFile "SleepTracker_Data.csv" +#define SLEEP_CYCLE_DURATION 90 // sleep cycle duration in minutes namespace Pinetime { namespace System { @@ -43,6 +44,8 @@ namespace Pinetime { uint8_t preSnnoozeHours = 255; uint8_t startTimeHours = 0; uint8_t startTimeMinutes = 0; + uint8_t endTimeHours = 0; + uint8_t endTimeMinutes = 0; void SetPreSnoozeTime() { if (preSnoozeMinutes != 255 || preSnnoozeHours != 255) { @@ -143,13 +146,18 @@ namespace Pinetime { uint8_t gradualWakeVibration = 9; // used to keep track of which vibration duration to use, in position form not idex - uint16_t sleepCycleDuration = 90; // sleep cycle duration in minutes - uint16_t GetSleepCycles() { - uint8_t hours = GetCurrentHour() - startTimeHours; - uint8_t minutes = GetCurrentMinute() - startTimeMinutes; - uint16_t totalMinutes = hours * 60 + minutes; - return totalMinutes * 100 / sleepCycleDuration; + uint16_t totalMinutes = GetTotalSleep(); + return (totalMinutes * 100 / SLEEP_CYCLE_DURATION); + } + + uint16_t GetTotalSleep() { + uint8_t hours = (IsEnabled() ? GetCurrentHour() : endTimeHours) - startTimeHours; + uint8_t minutes = (IsEnabled() ? GetCurrentMinute() : endTimeMinutes) - startTimeMinutes; + if (hours <= 0 && minutes <= 0) { + return 0; + } + return hours * 60 + minutes; } WakeAlarmSettings GetWakeAlarm() const { @@ -169,6 +177,8 @@ namespace Pinetime { bool ToggleTracker() { if (isEnabled) { + endTimeHours = GetCurrentHour(); + endTimeMinutes = GetCurrentMinute(); DisableTracker(); } else { ClearDataCSV(TrackerDataFile); diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 65ab14bd42..6dd5439d31 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -221,30 +221,25 @@ void Sleep::DrawInfoScreen() { lv_obj_set_style_local_text_color(label_gradual_wake, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); // Sleep Cycles Info - if (infiniSleepController.IsEnabled()) { - label_sleep_cycles = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_fmt(label_sleep_cycles, "Sleep Cycles: %1i.%02i", infiniSleepController.GetSleepCycles() / 100, infiniSleepController.GetSleepCycles() % 100); - lv_obj_align(label_sleep_cycles, label_hr, LV_ALIGN_CENTER, 0, 80); - lv_obj_set_style_local_text_color(label_sleep_cycles, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); - } + label_sleep_cycles = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_fmt(label_sleep_cycles, "Sleep Cycles: %d.%d", infiniSleepController.GetSleepCycles() / 100, infiniSleepController.GetSleepCycles() % 100); + lv_obj_align(label_sleep_cycles, label_hr, LV_ALIGN_CENTER, 0, 80); + lv_obj_set_style_local_text_color(label_sleep_cycles, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); // Total sleep time - if (infiniSleepController.IsEnabled()) { - label_total_sleep = lv_label_create(lv_scr_act(), nullptr); + label_total_sleep = lv_label_create(lv_scr_act(), nullptr); - uint8_t hours = infiniSleepController.GetCurrentHour() - infiniSleepController.startTimeHours; - uint8_t minutes = infiniSleepController.GetCurrentMinute() - infiniSleepController.startTimeMinutes; - uint16_t totalMinutes = hours * 60 + minutes; + uint16_t totalMinutes = infiniSleepController.GetTotalSleep(); - lv_label_set_text_fmt(label_total_sleep, "Total Sleep: %dh%dm", totalMinutes / 60, totalMinutes % 60); - lv_obj_align(label_total_sleep, label_hr, LV_ALIGN_CENTER, 0, 100); - lv_obj_set_style_local_text_color(label_total_sleep, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); - } + lv_label_set_text_fmt(label_total_sleep, "Total Sleep: %dh%dm", totalMinutes / 60, totalMinutes % 60); + lv_obj_align(label_total_sleep, label_hr, LV_ALIGN_CENTER, 0, 100); + lv_obj_set_style_local_text_color(label_total_sleep, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); trackerToggleBtn = lv_btn_create(lv_scr_act(), nullptr); trackerToggleBtn->user_data = this; lv_obj_align(trackerToggleBtn, lv_scr_act(), LV_ALIGN_CENTER, 0, 100); + // Tracker toggle button trackerToggleLabel = lv_label_create(trackerToggleBtn, nullptr); if (infiniSleepController.IsTrackerEnabled()) { lv_label_set_text_static(trackerToggleLabel, "Stop"); From bb9e3e73313362dab609ffca442d981f20375974 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 19 Nov 2024 10:26:36 -0600 Subject: [PATCH 049/123] Fixed bug with gradualWakeVibration not in sync with step when scheduling --- src/components/infinisleep/InfiniSleepController.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 904bb439d6..032c69c9d1 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -140,6 +140,7 @@ void InfiniSleepController::ScheduleWakeAlarm() { // make sure graudal wake steps are possible while (gradualWakeStep != 0 && secondsToWakeAlarm <= gradualWakeSteps[gradualWakeStep-1]) { gradualWakeStep--; + gradualWakeVibration = gradualWakeStep; } // Calculate the period for the gradualWakeTimer From a40b77aecb996cc8f0757e5ad8e10af281adab70 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 19 Nov 2024 14:17:48 -0600 Subject: [PATCH 050/123] Added suggestion alarm time based on desired sleep cycles constant Removed recurrence toggle since alarm would be adjusted each night. Updated tracker file name define name --- .../infinisleep/InfiniSleepController.cpp | 5 ++- .../infinisleep/InfiniSleepController.h | 11 +++-- src/displayapp/screens/Sleep.cpp | 43 +++++++++++++++---- src/displayapp/screens/Sleep.h | 1 + 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 032c69c9d1..02aae14042 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -95,6 +95,9 @@ void InfiniSleepController::SetWakeAlarmTime(uint8_t wakeAlarmHr, uint8_t wakeAl } void InfiniSleepController::ScheduleWakeAlarm() { + // This line essentially removes the ability to change recurrance type and sets it to daily + SetRecurrence(RecurType::Daily); + // Determine the next time the wake alarm needs to go off and set the timer xTimerStop(wakeAlarmTimer, 0); xTimerStop(gradualWakeTimer, 0); @@ -230,7 +233,7 @@ void InfiniSleepController::UpdateBPM() { // Write data to CSV const int motion = 0; // Placeholder for motion data std::tuple data[1] = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; - WriteDataCSV(TrackerDataFile, data, 1); + WriteDataCSV(TRACKER_DATA_FILE_NAME, data, 1); } void InfiniSleepController::WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const { diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index b0dc78f127..c260884c00 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -12,8 +12,9 @@ #define SNOOZE_MINUTES 3 #define PSUHES_TO_STOP_ALARM 5 #define TRACKER_UPDATE_INTERVAL_MINS 5 -#define TrackerDataFile "SleepTracker_Data.csv" +#define TRACKER_DATA_FILE_NAME "SleepTracker_Data.csv" #define SLEEP_CYCLE_DURATION 90 // sleep cycle duration in minutes +#define DESIRED_CYCLES 5 // desired number of sleep cycles namespace Pinetime { namespace System { @@ -136,7 +137,7 @@ namespace Pinetime { uint8_t version = wakeAlarmFormatVersion; uint8_t hours = 7; uint8_t minutes = 0; - RecurType recurrence = RecurType::None; + RecurType recurrence = RecurType::Daily; bool isEnabled = false; }; @@ -160,6 +161,10 @@ namespace Pinetime { return hours * 60 + minutes; } + uint16_t GetSuggestedSleepTime() { + return SLEEP_CYCLE_DURATION * DESIRED_CYCLES; + } + WakeAlarmSettings GetWakeAlarm() const { return wakeAlarm; } @@ -181,7 +186,7 @@ namespace Pinetime { endTimeMinutes = GetCurrentMinute(); DisableTracker(); } else { - ClearDataCSV(TrackerDataFile); + ClearDataCSV(TRACKER_DATA_FILE_NAME); startTimeHours = GetCurrentHour(); startTimeMinutes = GetCurrentMinute(); EnableTracker(); diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 6dd5439d31..6aaad63dd0 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -144,14 +144,22 @@ void Sleep::DrawAlarmScreen() { static constexpr lv_color_t bgColor = Colors::bgAlt; - btnRecur = lv_btn_create(lv_scr_act(), nullptr); - btnRecur->user_data = this; - lv_obj_set_event_cb(btnRecur, btnEventHandler); - lv_obj_set_size(btnRecur, 115, 50); - lv_obj_align(btnRecur, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); - txtRecur = lv_label_create(btnRecur, nullptr); - SetRecurButtonState(); - lv_obj_set_style_local_bg_color(btnRecur, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, bgColor); + btnSuggestedAlarm = lv_btn_create(lv_scr_act(), nullptr); + btnSuggestedAlarm->user_data = this; + lv_obj_set_event_cb(btnSuggestedAlarm, btnEventHandler); + lv_obj_set_size(btnSuggestedAlarm, 115, 50); + lv_obj_align(btnSuggestedAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + txtSuggestedAlarm = lv_label_create(btnSuggestedAlarm, nullptr); + lv_label_set_text_static(txtSuggestedAlarm, "Suggested"); + + // btnRecur = lv_btn_create(lv_scr_act(), nullptr); + // btnRecur->user_data = this; + // lv_obj_set_event_cb(btnRecur, btnEventHandler); + // lv_obj_set_size(btnRecur, 115, 50); + // lv_obj_align(btnRecur, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + // txtRecur = lv_label_create(btnRecur, nullptr); + // SetRecurButtonState(); + // lv_obj_set_style_local_bg_color(btnRecur, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, bgColor); btnInfo = lv_btn_create(lv_scr_act(), nullptr); btnInfo->user_data = this; @@ -321,6 +329,25 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { UpdateDisplay(); return; } + if (obj == btnSuggestedAlarm) { + // Set the suggested time + uint16_t totalSuggestedMinutes = infiniSleepController.GetSuggestedSleepTime(); + uint8_t suggestedHours = totalSuggestedMinutes / 60; + uint8_t suggestedMinutes = totalSuggestedMinutes % 60; + + // Time for alarm, current time + suggested sleep time + uint8_t alarmHour = (infiniSleepController.GetCurrentHour() + suggestedHours) % 24; + uint8_t alarmMinute = (infiniSleepController.GetCurrentMinute() + suggestedMinutes) % 60; + + hourCounter.SetValue(alarmHour); + minuteCounter.SetValue(alarmMinute); + + infiniSleepController.DisableWakeAlarm(); + UpdateWakeAlarmTime(); + lv_switch_on(enableSwitch, LV_ANIM_OFF); + infiniSleepController.ScheduleWakeAlarm(); + return; + } if (obj == btnRecur) { DisableWakeAlarm(); ToggleRecurrence(); diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 70f76ec20c..23b208b9c4 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -102,6 +102,7 @@ namespace Pinetime { lv_obj_t* label_gradual_wake; lv_obj_t* label_total_sleep; lv_obj_t* label_sleep_cycles; + lv_obj_t *btnSuggestedAlarm, *txtSuggestedAlarm; // lv_task_t* mainRefreshTask; // lv_task_t* hrRefreshTask; From a5dcba733d36412e313a8b39c7ee217b923bbf42 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 19 Nov 2024 20:06:27 -0600 Subject: [PATCH 051/123] Fixed total sleep calculation and cycles display bugs --- .../infinisleep/InfiniSleepController.cpp | 2 +- .../infinisleep/InfiniSleepController.h | 19 ++++++++++++++----- src/displayapp/screens/Sleep.cpp | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 02aae14042..bcb42e997f 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -47,7 +47,7 @@ void InfiniSleepController::EnableTracker() { DisableTracker(); NRF_LOG_INFO("[InfiniSleepController] Enabling tracker"); isEnabled = true; - trackerUpdateTimer = xTimerCreate("TrackerUpdate", 5 * configTICK_RATE_HZ, pdFALSE, this, SetOffTrackerUpdate); + trackerUpdateTimer = xTimerCreate("TrackerUpdate", pdMS_TO_TICKS(TRACKER_UPDATE_INTERVAL_MINS * 60 * 1000), pdFALSE, this, SetOffTrackerUpdate); xTimerStart(trackerUpdateTimer, 0); } diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index c260884c00..53af458988 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -153,12 +153,21 @@ namespace Pinetime { } uint16_t GetTotalSleep() { - uint8_t hours = (IsEnabled() ? GetCurrentHour() : endTimeHours) - startTimeHours; - uint8_t minutes = (IsEnabled() ? GetCurrentMinute() : endTimeMinutes) - startTimeMinutes; - if (hours <= 0 && minutes <= 0) { - return 0; + uint8_t endHours = IsEnabled() ? GetCurrentHour() : endTimeHours; + uint8_t endMinutes = IsEnabled() ? GetCurrentMinute() : endTimeMinutes; + + // Calculate total minutes for start and end times + uint16_t startTotalMinutes = startTimeHours * 60 + startTimeMinutes; + uint16_t endTotalMinutes = endHours * 60 + endMinutes; + + // If end time is before start time, add 24 hours to end time (handle crossing midnight) + if (endTotalMinutes < startTotalMinutes) { + endTotalMinutes += 24 * 60; } - return hours * 60 + minutes; + + uint16_t sleepMinutes = endTotalMinutes - startTotalMinutes; + + return sleepMinutes; } uint16_t GetSuggestedSleepTime() { diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 6aaad63dd0..dd768c0986 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -230,7 +230,7 @@ void Sleep::DrawInfoScreen() { // Sleep Cycles Info label_sleep_cycles = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_fmt(label_sleep_cycles, "Sleep Cycles: %d.%d", infiniSleepController.GetSleepCycles() / 100, infiniSleepController.GetSleepCycles() % 100); + lv_label_set_text_fmt(label_sleep_cycles, "Sleep Cycles: %d.%02d", infiniSleepController.GetSleepCycles() / 100, infiniSleepController.GetSleepCycles() % 100); lv_obj_align(label_sleep_cycles, label_hr, LV_ALIGN_CENTER, 0, 80); lv_obj_set_style_local_text_color(label_sleep_cycles, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); From 3c462a827ae50181ba4debd0a79ef80dda510587 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 20 Nov 2024 12:39:40 -0600 Subject: [PATCH 052/123] Added a timeout to pushes required to stop alarm so the presses dont carry over if some time has passed This can be adjusted with the PUSHES_TO_STOP_ALARM_TIMEOUT constant in InfiniSleepController.h --- .../infinisleep/InfiniSleepController.h | 1 + src/displayapp/screens/Sleep.cpp | 17 +++++++++++++++-- src/displayapp/screens/Sleep.h | 5 ++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 53af458988..62152d4882 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -15,6 +15,7 @@ #define TRACKER_DATA_FILE_NAME "SleepTracker_Data.csv" #define SLEEP_CYCLE_DURATION 90 // sleep cycle duration in minutes #define DESIRED_CYCLES 5 // desired number of sleep cycles +#define PUSHES_TO_STOP_ALARM_TIMEOUT 2 // in seconds namespace Pinetime { namespace System { diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index dd768c0986..cbc195dfaf 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -56,6 +56,12 @@ static void SnoozeAlarmTaskCallback(lv_task_t* task) { screen->SnoozeWakeAlarm(); } +static void PressesToStopAlarmTimeoutCallback(lv_task_t* task) { + auto* screen = static_cast(task->user_data); + screen->infiniSleepController.pushesLeftToStopWakeAlarm = PSUHES_TO_STOP_ALARM; + screen->UpdateDisplay(); +} + Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, Controllers::Settings::ClockType clockType, System::SystemTask& systemTask, @@ -71,6 +77,9 @@ Sleep::~Sleep() { StopAlerting(); } lv_task_del(taskRefresh); + if (taskPressesToStopAlarmTimeout != nullptr) { + lv_task_del(taskPressesToStopAlarmTimeout); + } lv_obj_clean(lv_scr_act()); infiniSleepController.SaveWakeAlarm(); infiniSleepController.SaveInfiniSleepSettings(); @@ -342,8 +351,7 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { hourCounter.SetValue(alarmHour); minuteCounter.SetValue(alarmMinute); - infiniSleepController.DisableWakeAlarm(); - UpdateWakeAlarmTime(); + OnValueChanged(); lv_switch_on(enableSwitch, LV_ANIM_OFF); infiniSleepController.ScheduleWakeAlarm(); return; @@ -362,6 +370,11 @@ bool Sleep::OnButtonPushed() { } if (infiniSleepController.IsAlerting()) { if (infiniSleepController.pushesLeftToStopWakeAlarm > 1) { + if (taskPressesToStopAlarmTimeout == nullptr) { + taskPressesToStopAlarmTimeout = lv_task_create(PressesToStopAlarmTimeoutCallback, PUSHES_TO_STOP_ALARM_TIMEOUT * 1000, LV_TASK_PRIO_MID, this); + } else { + lv_task_reset(taskPressesToStopAlarmTimeout); + } infiniSleepController.pushesLeftToStopWakeAlarm--; return true; } else { diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 23b208b9c4..a92810efb9 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -53,8 +53,9 @@ namespace Pinetime { // Read IO //std::vector> ReadDataCSV(const char* fileName) const; - private: Controllers::InfiniSleepController& infiniSleepController; + + private: System::WakeLock wakeLock; Controllers::MotorController& motorController; Controllers::Settings::ClockType clockType; @@ -68,6 +69,8 @@ namespace Pinetime { lv_task_t* taskRefresh = nullptr; + lv_task_t* taskPressesToStopAlarmTimeout = nullptr; + enum class EnableButtonState { On, Off, Alerting }; void DisableWakeAlarm(); void SetRecurButtonState(); From 931bc423e6531daa903f4c877e00ef8a9e82304a Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 20 Nov 2024 13:23:48 -0600 Subject: [PATCH 053/123] Made the watch open to the sleep app when in an active session --- src/displayapp/DisplayApp.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 3783b4c3a9..c6f04f0bbb 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -356,6 +356,11 @@ void DisplayApp::Refresh() { lcd.LowPowerOff(); } else { lcd.Wakeup(); + if (infiniSleepController.IsEnabled()) { + if (currentApp != Apps::Sleep) { + LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::Up); + } + } } lv_disp_trig_activity(nullptr); ApplyBrightness(); From 32392a72f351ad173f3fe79dbe98a06f8ddc4621 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 21 Nov 2024 09:41:50 -0600 Subject: [PATCH 054/123] Restructured pushes to stop timeout --- .../infinisleep/InfiniSleepController.cpp | 2 +- src/components/infinisleep/InfiniSleepController.h | 4 ++-- src/displayapp/screens/Sleep.cpp | 13 ++++--------- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index bcb42e997f..cdee6e7128 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -102,7 +102,7 @@ void InfiniSleepController::ScheduleWakeAlarm() { xTimerStop(wakeAlarmTimer, 0); xTimerStop(gradualWakeTimer, 0); - pushesLeftToStopWakeAlarm = PSUHES_TO_STOP_ALARM; + pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; gradualWakeStep = 9; gradualWakeVibration = 9; diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 62152d4882..5e95f9cc5b 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -10,7 +10,7 @@ #include #define SNOOZE_MINUTES 3 -#define PSUHES_TO_STOP_ALARM 5 +#define PUSHES_TO_STOP_ALARM 5 #define TRACKER_UPDATE_INTERVAL_MINS 5 #define TRACKER_DATA_FILE_NAME "SleepTracker_Data.csv" #define SLEEP_CYCLE_DURATION 90 // sleep cycle duration in minutes @@ -39,7 +39,7 @@ namespace Pinetime { void StopAlerting(); enum class RecurType { None, Daily, Weekdays }; - uint8_t pushesLeftToStopWakeAlarm = PSUHES_TO_STOP_ALARM; + uint8_t pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; bool isSnoozing = false; uint8_t preSnoozeMinutes = 255; diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index cbc195dfaf..679b40e8ce 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -58,7 +58,7 @@ static void SnoozeAlarmTaskCallback(lv_task_t* task) { static void PressesToStopAlarmTimeoutCallback(lv_task_t* task) { auto* screen = static_cast(task->user_data); - screen->infiniSleepController.pushesLeftToStopWakeAlarm = PSUHES_TO_STOP_ALARM; + screen->infiniSleepController.pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; screen->UpdateDisplay(); } @@ -70,6 +70,7 @@ Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, UpdateDisplay(); taskRefresh = lv_task_create(RefreshTaskCallback, 2000, LV_TASK_PRIO_MID, this); + taskPressesToStopAlarmTimeout = lv_task_create(PressesToStopAlarmTimeoutCallback, PUSHES_TO_STOP_ALARM_TIMEOUT * 1000, LV_TASK_PRIO_MID, this); } Sleep::~Sleep() { @@ -77,9 +78,7 @@ Sleep::~Sleep() { StopAlerting(); } lv_task_del(taskRefresh); - if (taskPressesToStopAlarmTimeout != nullptr) { - lv_task_del(taskPressesToStopAlarmTimeout); - } + lv_task_del(taskPressesToStopAlarmTimeout); lv_obj_clean(lv_scr_act()); infiniSleepController.SaveWakeAlarm(); infiniSleepController.SaveInfiniSleepSettings(); @@ -370,11 +369,7 @@ bool Sleep::OnButtonPushed() { } if (infiniSleepController.IsAlerting()) { if (infiniSleepController.pushesLeftToStopWakeAlarm > 1) { - if (taskPressesToStopAlarmTimeout == nullptr) { - taskPressesToStopAlarmTimeout = lv_task_create(PressesToStopAlarmTimeoutCallback, PUSHES_TO_STOP_ALARM_TIMEOUT * 1000, LV_TASK_PRIO_MID, this); - } else { - lv_task_reset(taskPressesToStopAlarmTimeout); - } + lv_task_reset(taskPressesToStopAlarmTimeout); infiniSleepController.pushesLeftToStopWakeAlarm--; return true; } else { From 3d1f74574f1aa7fca2be55736daeba058a6769fa Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 21 Nov 2024 10:31:30 -0600 Subject: [PATCH 055/123] Added saving of prev sleep session info in case watch crashes so it can be loaded --- .../infinisleep/InfiniSleepController.cpp | 25 ++++++++++++ .../infinisleep/InfiniSleepController.h | 38 ++++++++++++------- src/displayapp/screens/Sleep.cpp | 8 +++- 3 files changed, 55 insertions(+), 16 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index cdee6e7128..ebc36ff294 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -37,6 +37,7 @@ void InfiniSleepController::Init(System::SystemTask* systemTask) { gradualWakeTimer = xTimerCreate("GradualWake", 1, pdFALSE, this, SetOffGradualWake); LoadSettingsFromFile(); + LoadPrevSessionData(); if (wakeAlarm.isEnabled) { NRF_LOG_INFO("[InfiniSleepController] Loaded wake alarm was enabled, scheduling"); ScheduleWakeAlarm(); @@ -345,4 +346,28 @@ void InfiniSleepController::SaveSettingsToFile() const { fs.FileWrite(&settingsFile, reinterpret_cast(&infiniSleepSettings), sizeof(infiniSleepSettings)); fs.FileClose(&settingsFile); NRF_LOG_INFO("[InfiniSleepController] Saved InfiniSleep settings"); +} + +void InfiniSleepController::SavePrevSessionData() const { + lfs_file_t prevSessionFile; + if (fs.FileOpen(&prevSessionFile, PREV_SESSION_DATA_FILE_NAME, LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) { + NRF_LOG_WARNING("[InfiniSleepController] Failed to open previous session data file for saving"); + return; + } + + fs.FileWrite(&prevSessionFile, reinterpret_cast(&prevSessionData), sizeof(prevSessionData)); + fs.FileClose(&prevSessionFile); + NRF_LOG_INFO("[InfiniSleepController] Saved previous session data"); +} + +void InfiniSleepController::LoadPrevSessionData() { + lfs_file_t prevSessionFile; + if (fs.FileOpen(&prevSessionFile, PREV_SESSION_DATA_FILE_NAME, LFS_O_RDONLY) != LFS_ERR_OK) { + NRF_LOG_WARNING("[InfiniSleepController] Failed to open previous session data file"); + return; + } + + fs.FileRead(&prevSessionFile, reinterpret_cast(&prevSessionData), sizeof(prevSessionData)); + fs.FileClose(&prevSessionFile); + NRF_LOG_INFO("[InfiniSleepController] Loaded previous session data"); } \ No newline at end of file diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 5e95f9cc5b..22286d1abb 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -13,6 +13,7 @@ #define PUSHES_TO_STOP_ALARM 5 #define TRACKER_UPDATE_INTERVAL_MINS 5 #define TRACKER_DATA_FILE_NAME "SleepTracker_Data.csv" +#define PREV_SESSION_DATA_FILE_NAME "SleepTracker_PrevSession.csv" #define SLEEP_CYCLE_DURATION 90 // sleep cycle duration in minutes #define DESIRED_CYCLES 5 // desired number of sleep cycles #define PUSHES_TO_STOP_ALARM_TIMEOUT 2 // in seconds @@ -44,10 +45,16 @@ namespace Pinetime { bool isSnoozing = false; uint8_t preSnoozeMinutes = 255; uint8_t preSnnoozeHours = 255; - uint8_t startTimeHours = 0; - uint8_t startTimeMinutes = 0; - uint8_t endTimeHours = 0; - uint8_t endTimeMinutes = 0; + + // Struct for sessions + struct SessionData { + uint8_t startTimeHours = 0; + uint8_t startTimeMinutes = 0; + uint8_t endTimeHours = 0; + uint8_t endTimeMinutes = 0; + }; + + SessionData prevSessionData; void SetPreSnoozeTime() { if (preSnoozeMinutes != 255 || preSnnoozeHours != 255) { @@ -153,12 +160,12 @@ namespace Pinetime { return (totalMinutes * 100 / SLEEP_CYCLE_DURATION); } - uint16_t GetTotalSleep() { - uint8_t endHours = IsEnabled() ? GetCurrentHour() : endTimeHours; - uint8_t endMinutes = IsEnabled() ? GetCurrentMinute() : endTimeMinutes; + uint16_t GetTotalSleep() const { + uint8_t endHours = IsEnabled() ? GetCurrentHour() : prevSessionData.endTimeHours; + uint8_t endMinutes = IsEnabled() ? GetCurrentMinute() : prevSessionData.endTimeMinutes; // Calculate total minutes for start and end times - uint16_t startTotalMinutes = startTimeHours * 60 + startTimeMinutes; + uint16_t startTotalMinutes = prevSessionData.startTimeHours * 60 + prevSessionData.startTimeMinutes; uint16_t endTotalMinutes = endHours * 60 + endMinutes; // If end time is before start time, add 24 hours to end time (handle crossing midnight) @@ -192,13 +199,14 @@ namespace Pinetime { bool ToggleTracker() { if (isEnabled) { - endTimeHours = GetCurrentHour(); - endTimeMinutes = GetCurrentMinute(); + prevSessionData.endTimeHours = GetCurrentHour(); + prevSessionData.endTimeMinutes = GetCurrentMinute(); + SavePrevSessionData(); DisableTracker(); } else { ClearDataCSV(TRACKER_DATA_FILE_NAME); - startTimeHours = GetCurrentHour(); - startTimeMinutes = GetCurrentMinute(); + prevSessionData.startTimeHours = GetCurrentHour(); + prevSessionData.startTimeMinutes = GetCurrentMinute(); EnableTracker(); } return isEnabled; @@ -208,11 +216,11 @@ namespace Pinetime { return isEnabled; } - uint8_t GetCurrentHour() { + uint8_t GetCurrentHour() const { return dateTimeController.Hours(); } - uint8_t GetCurrentMinute() { + uint8_t GetCurrentMinute() const { return dateTimeController.Minutes(); } @@ -251,6 +259,8 @@ namespace Pinetime { void LoadSettingsFromFile(); void SaveSettingsToFile() const; + void LoadPrevSessionData(); + void SavePrevSessionData() const; // For File IO void WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const; diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 679b40e8ce..56d0c088ec 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -205,13 +205,17 @@ void Sleep::DrawInfoScreen() { lv_obj_set_style_local_text_color(lblTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); label_hr = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_fmt(label_hr, "HR: %d", infiniSleepController.rollingBpm); + if (infiniSleepController.rollingBpm == 0) { + lv_label_set_text_static(label_hr, "HR: --"); + } else { + lv_label_set_text_fmt(label_hr, "HR: %d", infiniSleepController.rollingBpm); + } lv_obj_align(label_hr, lblTime, LV_ALIGN_CENTER, 0, 50); lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); if (infiniSleepController.IsEnabled()) { label_start_time = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_fmt(label_start_time, "Began at: %02d:%02d", infiniSleepController.startTimeHours, infiniSleepController.startTimeMinutes); + lv_label_set_text_fmt(label_start_time, "Began at: %02d:%02d", infiniSleepController.prevSessionData.startTimeHours, infiniSleepController.prevSessionData.startTimeMinutes); lv_obj_align(label_start_time, label_hr, LV_ALIGN_CENTER, 0, 20); lv_obj_set_style_local_text_color(label_start_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); } From 99d25d3608483804ed9bfef541ae65c415a5d0f8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 21 Nov 2024 10:35:47 -0600 Subject: [PATCH 056/123] Reset pushes needed to stop alarm when watch sleeps --- src/displayapp/DisplayApp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index c6f04f0bbb..18cb924c80 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -297,6 +297,7 @@ void DisplayApp::Refresh() { if (xQueueReceive(msgQueue, &msg, queueTimeout) == pdTRUE) { switch (msg) { case Messages::GoToSleep: + infiniSleepController.pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; case Messages::GoToAOD: // Checking if SystemTask is sleeping is purely an optimisation. // If it's no longer sleeping since it sent GoToSleep, it has From 85d402c549ea786d93e48da400d7832fb2581381 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 21 Nov 2024 22:03:41 -0600 Subject: [PATCH 057/123] Moved pushes count reset to system task --- src/displayapp/DisplayApp.cpp | 1 - src/systemtask/SystemTask.cpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 18cb924c80..c6f04f0bbb 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -297,7 +297,6 @@ void DisplayApp::Refresh() { if (xQueueReceive(msgQueue, &msg, queueTimeout) == pdTRUE) { switch (msg) { case Messages::GoToSleep: - infiniSleepController.pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; case Messages::GoToAOD: // Checking if SystemTask is sleeping is purely an optimisation. // If it's no longer sleeping since it sent GoToSleep, it has diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 378ed3304b..ac301629cc 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -202,6 +202,7 @@ void SystemTask::Work() { GoToRunning(); break; case Messages::GoToSleep: + infiniSleepController.pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; GoToSleep(); break; case Messages::OnNewTime: From c5998329dda94020488b36f664034fb38e1b4ba8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 22 Nov 2024 11:41:30 -0600 Subject: [PATCH 058/123] Fixed some bugs with snooze time being set weird --- .../infinisleep/InfiniSleepController.cpp | 9 ++++ .../infinisleep/InfiniSleepController.h | 4 +- src/displayapp/DisplayApp.cpp | 4 +- src/displayapp/screens/Sleep.cpp | 49 +++++++++++++------ src/displayapp/screens/Sleep.h | 1 + 5 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index ebc36ff294..1d44ad438c 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -150,6 +150,7 @@ void InfiniSleepController::ScheduleWakeAlarm() { // Calculate the period for the gradualWakeTimer if (infiniSleepSettings.graddualWake && gradualWakeStep != 0) { int64_t gradualWakePeriod = ((secondsToWakeAlarm - gradualWakeSteps[-1+gradualWakeStep--])) * (configTICK_RATE_HZ); + gradualWakeVibration = gradualWakeStep; xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); } @@ -168,6 +169,7 @@ void InfiniSleepController::DisableWakeAlarm() { xTimerStop(wakeAlarmTimer, 0); xTimerStop(gradualWakeTimer, 0); gradualWakeStep = 9; + gradualWakeVibration = 9; isAlerting = false; if (wakeAlarm.isEnabled) { wakeAlarm.isEnabled = false; @@ -175,6 +177,12 @@ void InfiniSleepController::DisableWakeAlarm() { } } +void InfiniSleepController::EnableWakeAlarm() { + wakeAlarm.isEnabled = true; + wakeAlarmChanged = true; + ScheduleWakeAlarm(); +} + void InfiniSleepController::SetOffWakeAlarmNow() { isAlerting = true; systemTask->PushMessage(System::Messages::SetOffWakeAlarm); @@ -186,6 +194,7 @@ void InfiniSleepController::SetOffGradualWakeNow() { // Calculate the period for the gradualWakeTimer if (infiniSleepSettings.graddualWake && gradualWakeStep != 0) { int64_t gradualWakePeriod = ((SecondsToWakeAlarm() - gradualWakeSteps[-1+gradualWakeStep--])) * (configTICK_RATE_HZ); + gradualWakeVibration = gradualWakeStep; xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); } diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 22286d1abb..c6fd926198 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -34,6 +34,7 @@ namespace Pinetime { void SetWakeAlarmTime(uint8_t wakeAlarmHr, uint8_t wakeAlarmMin); void ScheduleWakeAlarm(); void DisableWakeAlarm(); + void EnableWakeAlarm(); void SetOffWakeAlarmNow(); void SetOffGradualWakeNow(); uint32_t SecondsToWakeAlarm() const; @@ -155,6 +156,8 @@ namespace Pinetime { uint8_t gradualWakeVibration = 9; // used to keep track of which vibration duration to use, in position form not idex + uint8_t gradualWakeStep = 9; // used to keep track of which step to use, in position form not idex + uint16_t GetSleepCycles() { uint16_t totalMinutes = GetTotalSleep(); return (totalMinutes * 100 / SLEEP_CYCLE_DURATION); @@ -240,7 +243,6 @@ namespace Pinetime { bool isAlerting = false; bool isGradualWakeAlerting = false; - uint8_t gradualWakeStep = 9; // used to keep track of which step to use, in position form not idex bool wakeAlarmChanged = false; bool isEnabled = false; bool settingsChanged = false; diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index c6f04f0bbb..19048199d8 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -408,8 +408,10 @@ void DisplayApp::Refresh() { } else { LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); } - motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1+infiniSleepController.gradualWakeVibration--]); + motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1+infiniSleepController.gradualWakeVibration]); + NRF_LOG_INFO("Gradual wake triggered"); + break; case Messages::SleepTrackerUpdate: if (currentApp == Apps::Sleep) { diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 56d0c088ec..dbca31c763 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -50,11 +50,11 @@ static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { screen->OnButtonEvent(obj, event); } -static void SnoozeAlarmTaskCallback(lv_task_t* task) { - auto* screen = static_cast(task->user_data); - screen->StopAlerting(); - screen->SnoozeWakeAlarm(); -} +// static void SnoozeAlarmTaskCallback(lv_task_t* task) { +// auto* screen = static_cast(task->user_data); +// screen->StopAlerting(); +// screen->SnoozeWakeAlarm(); +// } static void PressesToStopAlarmTimeoutCallback(lv_task_t* task) { auto* screen = static_cast(task->user_data); @@ -79,6 +79,9 @@ Sleep::~Sleep() { } lv_task_del(taskRefresh); lv_task_del(taskPressesToStopAlarmTimeout); + if (taskSnoozeWakeAlarm != nullptr) { + lv_task_del(taskSnoozeWakeAlarm); + } lv_obj_clean(lv_scr_act()); infiniSleepController.SaveWakeAlarm(); infiniSleepController.SaveInfiniSleepSettings(); @@ -91,6 +94,13 @@ void Sleep::DisableWakeAlarm() { } } +void Sleep::EnableWakeAlarm() { + if (!infiniSleepController.GetWakeAlarm().isEnabled) { + infiniSleepController.EnableWakeAlarm(); + lv_switch_on(enableSwitch, LV_ANIM_ON); + } +} + void Sleep::Refresh() { UpdateDisplay(); } @@ -127,12 +137,12 @@ void Sleep::DrawAlarmScreen() { lv_label_set_align(lblampm, LV_LABEL_ALIGN_CENTER); lv_obj_align(lblampm, lv_scr_act(), LV_ALIGN_CENTER, 0, 30); } - hourCounter.SetValue(infiniSleepController.Hours()); + hourCounter.SetValue(infiniSleepController.GetWakeAlarm().hours); hourCounter.SetValueChangedEventCallback(this, ValueChangedHandler); minuteCounter.Create(); lv_obj_align(minuteCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); - minuteCounter.SetValue(infiniSleepController.Minutes()); + minuteCounter.SetValue(infiniSleepController.GetWakeAlarm().minutes); minuteCounter.SetValueChangedEventCallback(this, ValueChangedHandler); lv_obj_t* colonLabel = lv_label_create(lv_scr_act(), nullptr); @@ -351,6 +361,8 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { uint8_t alarmHour = (infiniSleepController.GetCurrentHour() + suggestedHours) % 24; uint8_t alarmMinute = (infiniSleepController.GetCurrentMinute() + suggestedMinutes) % 60; + infiniSleepController.SetWakeAlarmTime(alarmHour, alarmMinute); + hourCounter.SetValue(alarmHour); minuteCounter.SetValue(alarmMinute); @@ -426,16 +438,23 @@ void Sleep::OnValueChanged() { // Currently snoozes baeed on define statement in InfiniSleepController.h void Sleep::SnoozeWakeAlarm() { - if (minuteCounter.GetValue() >= 55) { - minuteCounter.SetValue(0); - hourCounter.SetValue((infiniSleepController.GetCurrentHour() + 1)); - } else { - minuteCounter.SetValue(infiniSleepController.GetCurrentMinute() + SNOOZE_MINUTES); + if (taskSnoozeWakeAlarm != nullptr) { + lv_task_del(taskSnoozeWakeAlarm); + taskSnoozeWakeAlarm = nullptr; } + + uint16_t totalAlarmMinutes = infiniSleepController.GetCurrentHour() * 60 + infiniSleepController.GetCurrentMinute(); + uint16_t newSnoozeMinutes = totalAlarmMinutes + SNOOZE_MINUTES; + infiniSleepController.SetPreSnoozeTime(); infiniSleepController.isSnoozing = true; - UpdateWakeAlarmTime(); - SetSwitchState(LV_ANIM_OFF); + + infiniSleepController.SetWakeAlarmTime(newSnoozeMinutes / 60, newSnoozeMinutes % 60); + + hourCounter.SetValue(newSnoozeMinutes / 60); + minuteCounter.SetValue(newSnoozeMinutes % 60); + + lv_switch_on(enableSwitch, LV_ANIM_OFF); infiniSleepController.ScheduleWakeAlarm(); } @@ -453,7 +472,7 @@ void Sleep::UpdateWakeAlarmTime() { void Sleep::SetAlerting() { lv_obj_set_hidden(enableSwitch, true); lv_obj_set_hidden(btnStop, false); - taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, pdMS_TO_TICKS(180 * 1000), LV_TASK_PRIO_MID, this); + //taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, pdMS_TO_TICKS(5 * 1000), LV_TASK_PRIO_MID, this); motorController.StartAlarm(); wakeLock.Lock(); } diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index a92810efb9..5e24b79812 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -73,6 +73,7 @@ namespace Pinetime { enum class EnableButtonState { On, Off, Alerting }; void DisableWakeAlarm(); + void EnableWakeAlarm(); void SetRecurButtonState(); void SetSwitchState(lv_anim_enable_t anim); void SetWakeAlarm(); From 954e52d46a3bff855ff7137aaccb4deb936066b3 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 22 Nov 2024 13:24:39 -0600 Subject: [PATCH 059/123] Code optimizations & brought back more memory --- src/FreeRTOSConfig.h | 2 +- .../infinisleep/InfiniSleepController.cpp | 40 +++++------ .../infinisleep/InfiniSleepController.h | 19 +++--- src/displayapp/screens/Sleep.cpp | 66 +++++++++---------- src/displayapp/screens/Sleep.h | 6 +- 5 files changed, 67 insertions(+), 66 deletions(-) diff --git a/src/FreeRTOSConfig.h b/src/FreeRTOSConfig.h index d82b250abd..da05c1b899 100644 --- a/src/FreeRTOSConfig.h +++ b/src/FreeRTOSConfig.h @@ -62,7 +62,7 @@ #define configTICK_RATE_HZ 1024 #define configMAX_PRIORITIES (3) #define configMINIMAL_STACK_SIZE (120) -#define configTOTAL_HEAP_SIZE (1024 * 40) +#define configTOTAL_HEAP_SIZE (1024 * 39) #define configMAX_TASK_NAME_LEN (4) #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 1d44ad438c..03552291b7 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -97,7 +97,7 @@ void InfiniSleepController::SetWakeAlarmTime(uint8_t wakeAlarmHr, uint8_t wakeAl void InfiniSleepController::ScheduleWakeAlarm() { // This line essentially removes the ability to change recurrance type and sets it to daily - SetRecurrence(RecurType::Daily); + //SetRecurrence(RecurType::Daily); // Determine the next time the wake alarm needs to go off and set the timer xTimerStop(wakeAlarmTimer, 0); @@ -126,13 +126,13 @@ void InfiniSleepController::ScheduleWakeAlarm() { tmWakeAlarmTime->tm_sec = 0; // if alarm is in weekday-only mode, make sure it shifts to the next weekday - if (wakeAlarm.recurrence == RecurType::Weekdays) { - if (tmWakeAlarmTime->tm_wday == 0) {// Sunday, shift 1 day - tmWakeAlarmTime->tm_mday += 1; - } else if (tmWakeAlarmTime->tm_wday == 6) { // Saturday, shift 2 days - tmWakeAlarmTime->tm_mday += 2; - } - } + // if (wakeAlarm.recurrence == RecurType::Weekdays) { + // if (tmWakeAlarmTime->tm_wday == 0) {// Sunday, shift 1 day + // tmWakeAlarmTime->tm_mday += 1; + // } else if (tmWakeAlarmTime->tm_wday == 6) { // Saturday, shift 2 days + // tmWakeAlarmTime->tm_mday += 2; + // } + // } tmWakeAlarmTime->tm_isdst = -1; // use system timezone setting to determine DST // now can convert back to a time_point @@ -203,22 +203,22 @@ void InfiniSleepController::SetOffGradualWakeNow() { void InfiniSleepController::StopAlerting() { isAlerting = false; // Disable the alarm unless it is recurring - if (wakeAlarm.recurrence == RecurType::None) { + //if (wakeAlarm.recurrence == RecurType::None) { wakeAlarm.isEnabled = false; wakeAlarmChanged = true; - } else { - // Schedule the alarm for the next day - ScheduleWakeAlarm(); - } + // } else { + // // Schedule the alarm for the next day + // ScheduleWakeAlarm(); + // } } -void InfiniSleepController::SetRecurrence(RecurType recurrence) { - if (wakeAlarm.recurrence == recurrence) { - return; - } - wakeAlarm.recurrence = recurrence; - wakeAlarmChanged = true; -} +// void InfiniSleepController::SetRecurrence(RecurType recurrence) { +// if (wakeAlarm.recurrence == recurrence) { +// return; +// } +// wakeAlarm.recurrence = recurrence; +// wakeAlarmChanged = true; +// } /* Sleep Tracking Section */ diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index c6fd926198..004a5c1ae2 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -6,6 +6,7 @@ #include "components/datetime/DateTimeController.h" #include "components/fs/FS.h" #include "components/heartrate/HeartRateController.h" +#include "components/alarm/AlarmController.h" #include @@ -39,7 +40,7 @@ namespace Pinetime { void SetOffGradualWakeNow(); uint32_t SecondsToWakeAlarm() const; void StopAlerting(); - enum class RecurType { None, Daily, Weekdays }; + //enum class RecurType { None, Daily, Weekdays }; uint8_t pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; @@ -96,11 +97,11 @@ namespace Pinetime { void DisableTracker(); void UpdateTracker(); - RecurType Recurrence() const { - return wakeAlarm.recurrence; - } + // RecurType Recurrence() const { + // return wakeAlarm.recurrence; + // } - void SetRecurrence(RecurType recurrence); + // void SetRecurrence(RecurType recurrence); bool BodyTrackingEnabled() const { return infiniSleepSettings.bodyTracking; @@ -143,16 +144,16 @@ namespace Pinetime { static constexpr uint8_t wakeAlarmFormatVersion = 1; struct WakeAlarmSettings { - uint8_t version = wakeAlarmFormatVersion; + static constexpr uint8_t version = wakeAlarmFormatVersion; uint8_t hours = 7; uint8_t minutes = 0; - RecurType recurrence = RecurType::Daily; + AlarmController::RecurType recurrence = AlarmController::RecurType::Daily; bool isEnabled = false; }; // Dertermine the steps for the gradual wake alarm, the corresponding vibration durations determine the power of the vibration - uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; // In seconds - uint16_t gradualWakeVibrationDurations[9] = {1200, 1200, 1000, 1000, 1000, 700, 700, 700, 500}; // In ms + static constexpr uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; // In seconds + static constexpr uint16_t gradualWakeVibrationDurations[9] = {1200, 1200, 1000, 1000, 1000, 700, 700, 700, 500}; // In ms uint8_t gradualWakeVibration = 9; // used to keep track of which vibration duration to use, in position form not idex diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index dbca31c763..aba30425ee 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -371,10 +371,10 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { infiniSleepController.ScheduleWakeAlarm(); return; } - if (obj == btnRecur) { - DisableWakeAlarm(); - ToggleRecurrence(); - } + // if (obj == btnRecur) { + // DisableWakeAlarm(); + // ToggleRecurrence(); + // } } } @@ -536,33 +536,33 @@ void Sleep::HideAlarmInfo() { btnMessage = nullptr; } -void Sleep::SetRecurButtonState() { - using Pinetime::Controllers::InfiniSleepController; - switch (infiniSleepController.Recurrence()) { - case InfiniSleepController::RecurType::None: - lv_label_set_text_static(txtRecur, "ONCE"); - break; - case InfiniSleepController::RecurType::Daily: - lv_label_set_text_static(txtRecur, "DAILY"); - break; - case InfiniSleepController::RecurType::Weekdays: - lv_label_set_text_static(txtRecur, "MON-FRI"); - break; - } -} +// void Sleep::SetRecurButtonState() { +// using Pinetime::Controllers::InfiniSleepController; +// switch (infiniSleepController.Recurrence()) { +// case InfiniSleepController::RecurType::None: +// lv_label_set_text_static(txtRecur, "ONCE"); +// break; +// case InfiniSleepController::RecurType::Daily: +// lv_label_set_text_static(txtRecur, "DAILY"); +// break; +// case InfiniSleepController::RecurType::Weekdays: +// lv_label_set_text_static(txtRecur, "MON-FRI"); +// break; +// } +// } -void Sleep::ToggleRecurrence() { - using Pinetime::Controllers::InfiniSleepController; - switch (infiniSleepController.Recurrence()) { - case InfiniSleepController::RecurType::None: - infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::Daily); - break; - case InfiniSleepController::RecurType::Daily: - infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::Weekdays); - break; - case InfiniSleepController::RecurType::Weekdays: - infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::None); - break; - } - SetRecurButtonState(); -} \ No newline at end of file +// void Sleep::ToggleRecurrence() { +// using Pinetime::Controllers::InfiniSleepController; +// switch (infiniSleepController.Recurrence()) { +// case InfiniSleepController::RecurType::None: +// infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::Daily); +// break; +// case InfiniSleepController::RecurType::Daily: +// infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::Weekdays); +// break; +// case InfiniSleepController::RecurType::Weekdays: +// infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::None); +// break; +// } +// SetRecurButtonState(); +// } \ No newline at end of file diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 5e24b79812..fb25743089 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -60,7 +60,7 @@ namespace Pinetime { Controllers::MotorController& motorController; Controllers::Settings::ClockType clockType; - lv_obj_t *btnStop, *txtStop, *btnRecur, *txtRecur, *btnInfo, *enableSwitch; + lv_obj_t *btnStop, *txtStop, /**btnRecur, *txtRecur,*/ *btnInfo, *enableSwitch; lv_obj_t *trackerToggleBtn, *trackerToggleLabel; lv_obj_t* lblampm = nullptr; lv_obj_t* txtMessage = nullptr; @@ -74,12 +74,12 @@ namespace Pinetime { enum class EnableButtonState { On, Off, Alerting }; void DisableWakeAlarm(); void EnableWakeAlarm(); - void SetRecurButtonState(); + //void SetRecurButtonState(); void SetSwitchState(lv_anim_enable_t anim); void SetWakeAlarm(); void ShowAlarmInfo(); void HideAlarmInfo(); - void ToggleRecurrence(); + //void ToggleRecurrence(); void UpdateWakeAlarmTime(); Widgets::Counter hourCounter = Widgets::Counter(0, 23, jetbrains_mono_76); Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_76); From e9cb001600c37c95513f5a5ca0f3d2308232af46 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 22 Nov 2024 20:10:40 -0600 Subject: [PATCH 060/123] Added buttons to set desired cycles count and duration per cycle. Removed settings that don't do anything yet. --- .../infinisleep/InfiniSleepController.h | 11 +-- src/displayapp/screens/Sleep.cpp | 72 ++++++++++++++++--- src/displayapp/screens/Sleep.h | 2 +- 3 files changed, 69 insertions(+), 16 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 004a5c1ae2..d624136c52 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -151,6 +151,8 @@ namespace Pinetime { bool isEnabled = false; }; + WakeAlarmSettings wakeAlarm; + // Dertermine the steps for the gradual wake alarm, the corresponding vibration durations determine the power of the vibration static constexpr uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; // In seconds static constexpr uint16_t gradualWakeVibrationDurations[9] = {1200, 1200, 1000, 1000, 1000, 700, 700, 700, 500}; // In ms @@ -183,7 +185,7 @@ namespace Pinetime { } uint16_t GetSuggestedSleepTime() { - return SLEEP_CYCLE_DURATION * DESIRED_CYCLES; + return infiniSleepSettings.desiredCycles * infiniSleepSettings.sleepCycleDuration; } WakeAlarmSettings GetWakeAlarm() const { @@ -195,8 +197,12 @@ namespace Pinetime { bool heartRateTracking = true; bool graddualWake = false; bool smartAlarm = false; + uint8_t sleepCycleDuration = SLEEP_CYCLE_DURATION; + uint8_t desiredCycles = DESIRED_CYCLES; }; + InfiniSleepSettings infiniSleepSettings; + InfiniSleepSettings GetInfiniSleepSettings() const { return infiniSleepSettings; } @@ -248,8 +254,6 @@ namespace Pinetime { bool isEnabled = false; bool settingsChanged = false; - InfiniSleepSettings infiniSleepSettings; - Controllers::DateTime& dateTimeController; Controllers::FS& fs; Controllers::HeartRateController& heartRateController; @@ -257,7 +261,6 @@ namespace Pinetime { TimerHandle_t wakeAlarmTimer; TimerHandle_t gradualWakeTimer; TimerHandle_t trackerUpdateTimer; - WakeAlarmSettings wakeAlarm; std::chrono::time_point wakeAlarmTime; void LoadSettingsFromFile(); diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index aba30425ee..4b07e1137b 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -94,12 +94,12 @@ void Sleep::DisableWakeAlarm() { } } -void Sleep::EnableWakeAlarm() { - if (!infiniSleepController.GetWakeAlarm().isEnabled) { - infiniSleepController.EnableWakeAlarm(); - lv_switch_on(enableSwitch, LV_ANIM_ON); - } -} +// void Sleep::EnableWakeAlarm() { +// if (!infiniSleepController.GetWakeAlarm().isEnabled) { +// infiniSleepController.EnableWakeAlarm(); +// lv_switch_on(enableSwitch, LV_ANIM_ON); +// } +// } void Sleep::Refresh() { UpdateDisplay(); @@ -292,11 +292,11 @@ void Sleep::DrawSettingsScreen() { int offsetAfter = 30; }; - Setting settings[] = { - {"Body Tracking", infiniSleepController.BodyTrackingEnabled()}, + const Setting settings[] = { + //{"Body Tracking", infiniSleepController.BodyTrackingEnabled()}, {"Heart Rate\nTracking", infiniSleepController.HeartRateTrackingEnabled(), 60}, {"Gradual Wake", infiniSleepController.GradualWakeEnabled()}, - {"Smart Alarm\n(alpha)", infiniSleepController.SmartAlarmEnabled()} + //{"Smart Alarm\n(alpha)", infiniSleepController.SmartAlarmEnabled()} }; int y_offset = 50; @@ -321,6 +321,57 @@ void Sleep::DrawSettingsScreen() { y_offset += setting.offsetAfter; // Increase the offset to provide better spacing } + + lv_obj_t* lblCycles = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(lblCycles, "Cycles <----> Mins"); + lv_obj_align(lblCycles, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); + + lv_obj_t* btnCycles = lv_btn_create(lv_scr_act(), nullptr); + lv_obj_set_size(btnCycles, 100, 50); + lv_obj_align(btnCycles, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset + 30); + btnCycles->user_data = this; + lv_obj_set_event_cb(btnCycles, [](lv_obj_t* obj, lv_event_t e) { + if (e == LV_EVENT_CLICKED) { + auto* screen = static_cast(obj->user_data); + int value = screen->infiniSleepController.infiniSleepSettings.desiredCycles; + value = (value % 10) + 1; // Cycle through values 1 to 10 + screen->infiniSleepController.infiniSleepSettings.desiredCycles = value; + screen->infiniSleepController.SetSettingsChanged(); + lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d", value); + } + }); + + lv_obj_t* lblCycleValue = lv_label_create(btnCycles, nullptr); + lv_label_set_text_fmt(lblCycleValue, "%d", infiniSleepController.infiniSleepSettings.desiredCycles); + lv_obj_align(lblCycleValue, nullptr, LV_ALIGN_CENTER, 0, 0); + + lv_obj_t* btnCycleDuration = lv_btn_create(lv_scr_act(), nullptr); + lv_obj_set_size(btnCycleDuration, 100, 50); + lv_obj_align(btnCycleDuration, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 120, y_offset + 30); + btnCycleDuration->user_data = this; + lv_obj_set_event_cb(btnCycleDuration, [](lv_obj_t* obj, lv_event_t e) { + if (e == LV_EVENT_CLICKED) { + auto* screen = static_cast(obj->user_data); + int value = screen->infiniSleepController.infiniSleepSettings.sleepCycleDuration; + switch (value) { + case 80: value = 85; break; + case 85: value = 90; break; + case 90: value = 95; break; + case 95: value = 100; break; + case 100: value = 80; break; + default: value = 80; break; + } + screen->infiniSleepController.infiniSleepSettings.sleepCycleDuration = value; + screen->infiniSleepController.SetSettingsChanged(); + lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d", value); + } + }); + + lv_obj_t* lblCycleDurationValue = lv_label_create(btnCycleDuration, nullptr); + lv_label_set_text_fmt(lblCycleDurationValue, "%d", infiniSleepController.infiniSleepSettings.sleepCycleDuration); + lv_obj_align(lblCycleDurationValue, nullptr, LV_ALIGN_CENTER, 0, 0); + + y_offset += 70; // Adjust the offset for the next UI element } void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { @@ -367,7 +418,6 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { minuteCounter.SetValue(alarmMinute); OnValueChanged(); - lv_switch_on(enableSwitch, LV_ANIM_OFF); infiniSleepController.ScheduleWakeAlarm(); return; } @@ -454,7 +504,6 @@ void Sleep::SnoozeWakeAlarm() { hourCounter.SetValue(newSnoozeMinutes / 60); minuteCounter.SetValue(newSnoozeMinutes % 60); - lv_switch_on(enableSwitch, LV_ANIM_OFF); infiniSleepController.ScheduleWakeAlarm(); } @@ -467,6 +516,7 @@ void Sleep::UpdateWakeAlarmTime() { } } infiniSleepController.SetWakeAlarmTime(hourCounter.GetValue(), minuteCounter.GetValue()); + SetSwitchState(LV_ANIM_OFF); } void Sleep::SetAlerting() { diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index fb25743089..b3f11cddff 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -73,7 +73,7 @@ namespace Pinetime { enum class EnableButtonState { On, Off, Alerting }; void DisableWakeAlarm(); - void EnableWakeAlarm(); + //void EnableWakeAlarm(); //void SetRecurButtonState(); void SetSwitchState(lv_anim_enable_t anim); void SetWakeAlarm(); From fe15f02e41c4f4f308848583ba3290d58d6c2f1e Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 23 Nov 2024 14:51:59 -0600 Subject: [PATCH 061/123] Bug fixes Fixed crash on destructor cal Removed info button on alarm screen --- src/displayapp/screens/Sleep.cpp | 61 ++++++++++++++++---------------- src/displayapp/screens/Sleep.h | 2 +- 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 4b07e1137b..316db79281 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -50,11 +50,12 @@ static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { screen->OnButtonEvent(obj, event); } -// static void SnoozeAlarmTaskCallback(lv_task_t* task) { -// auto* screen = static_cast(task->user_data); -// screen->StopAlerting(); -// screen->SnoozeWakeAlarm(); -// } +static void SnoozeAlarmTaskCallback(lv_task_t* task) { + auto* screen = static_cast(task->user_data); + lv_task_del(task); + screen->StopAlerting(false); + screen->SnoozeWakeAlarm(); +} static void PressesToStopAlarmTimeoutCallback(lv_task_t* task) { auto* screen = static_cast(task->user_data); @@ -179,17 +180,17 @@ void Sleep::DrawAlarmScreen() { // SetRecurButtonState(); // lv_obj_set_style_local_bg_color(btnRecur, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, bgColor); - btnInfo = lv_btn_create(lv_scr_act(), nullptr); - btnInfo->user_data = this; - lv_obj_set_event_cb(btnInfo, btnEventHandler); - lv_obj_set_size(btnInfo, 50, 50); - lv_obj_align(btnInfo, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, -4); - lv_obj_set_style_local_bg_color(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, bgColor); - lv_obj_set_style_local_border_width(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 4); - lv_obj_set_style_local_border_color(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + // btnInfo = lv_btn_create(lv_scr_act(), nullptr); + // btnInfo->user_data = this; + // lv_obj_set_event_cb(btnInfo, btnEventHandler); + // lv_obj_set_size(btnInfo, 50, 50); + // lv_obj_align(btnInfo, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, -4); + // lv_obj_set_style_local_bg_color(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, bgColor); + // lv_obj_set_style_local_border_width(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 4); + // lv_obj_set_style_local_border_color(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); - lv_obj_t* txtInfo = lv_label_create(btnInfo, nullptr); - lv_label_set_text_static(txtInfo, "i"); + // lv_obj_t* txtInfo = lv_label_create(btnInfo, nullptr); + // lv_label_set_text_static(txtInfo, "i"); enableSwitch = lv_switch_create(lv_scr_act(), nullptr); enableSwitch->user_data = this; @@ -242,8 +243,8 @@ void Sleep::DrawInfoScreen() { // Gradual Wake info label_gradual_wake = lv_label_create(lv_scr_act(), nullptr); - if (infiniSleepController.GetInfiniSleepSettings().graddualWake) { - lv_label_set_text_fmt(label_gradual_wake, "Gradual Wake: %d/9", infiniSleepController.gradualWakeVibration); + if (infiniSleepController.GetWakeAlarm().isEnabled && infiniSleepController.GetInfiniSleepSettings().graddualWake && infiniSleepController.gradualWakeStep > 0) { + lv_label_set_text_fmt(label_gradual_wake, "Gradual Wake: %d/9", infiniSleepController.gradualWakeStep); } else { lv_label_set_text_static(label_gradual_wake, "Gradual Wake: OFF"); } @@ -381,10 +382,10 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { SnoozeWakeAlarm(); return; } - if (obj == btnInfo) { - ShowAlarmInfo(); - return; - } + // if (obj == btnInfo) { + // ShowAlarmInfo(); + // return; + // } if (obj == btnMessage) { HideAlarmInfo(); return; @@ -488,10 +489,8 @@ void Sleep::OnValueChanged() { // Currently snoozes baeed on define statement in InfiniSleepController.h void Sleep::SnoozeWakeAlarm() { - if (taskSnoozeWakeAlarm != nullptr) { - lv_task_del(taskSnoozeWakeAlarm); - taskSnoozeWakeAlarm = nullptr; - } + lv_task_del(taskSnoozeWakeAlarm); + taskSnoozeWakeAlarm = nullptr; uint16_t totalAlarmMinutes = infiniSleepController.GetCurrentHour() * 60 + infiniSleepController.GetCurrentMinute(); uint16_t newSnoozeMinutes = totalAlarmMinutes + SNOOZE_MINUTES; @@ -522,19 +521,19 @@ void Sleep::UpdateWakeAlarmTime() { void Sleep::SetAlerting() { lv_obj_set_hidden(enableSwitch, true); lv_obj_set_hidden(btnStop, false); - //taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, pdMS_TO_TICKS(5 * 1000), LV_TASK_PRIO_MID, this); + taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, pdMS_TO_TICKS(5 * 1000), LV_TASK_PRIO_MID, this); motorController.StartAlarm(); wakeLock.Lock(); } -void Sleep::StopAlerting() { +void Sleep::StopAlerting(bool setSwitch) { infiniSleepController.StopAlerting(); motorController.StopAlarm(); - SetSwitchState(LV_ANIM_OFF); - if (taskSnoozeWakeAlarm != nullptr) { - lv_task_del(taskSnoozeWakeAlarm); - taskSnoozeWakeAlarm = nullptr; + if (setSwitch) { + SetSwitchState(LV_ANIM_OFF); } + lv_task_del(taskSnoozeWakeAlarm); + taskSnoozeWakeAlarm = nullptr; wakeLock.Release(); lv_obj_set_hidden(enableSwitch, false); lv_obj_set_hidden(btnStop, true); diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index b3f11cddff..7a9ccb4096 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -29,7 +29,7 @@ namespace Pinetime { bool OnButtonPushed() override; bool OnTouchEvent(TouchEvents event) override; void OnValueChanged(); - void StopAlerting(); + void StopAlerting(bool setSwitch = true); void SnoozeWakeAlarm(); void UpdateDisplay(); enum class SleepDisplayState { Alarm, Info, Settings }; From b03c8335b2a851bba6f1c0e435fad5af1b767072 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 23 Nov 2024 14:53:32 -0600 Subject: [PATCH 062/123] Switched vibration index variable to use the gradualStep and fixed issues with index updates --- .../infinisleep/InfiniSleepController.cpp | 30 ++++++++++++------- .../infinisleep/InfiniSleepController.h | 6 ++-- src/displayapp/DisplayApp.cpp | 2 +- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 03552291b7..bdf9628672 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -106,7 +106,7 @@ void InfiniSleepController::ScheduleWakeAlarm() { pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; gradualWakeStep = 9; - gradualWakeVibration = 9; + //gradualWakeVibration = 9; auto now = dateTimeController.CurrentDateTime(); wakeAlarmTime = now; @@ -142,15 +142,15 @@ void InfiniSleepController::ScheduleWakeAlarm() { xTimerStart(wakeAlarmTimer, 0); // make sure graudal wake steps are possible - while (gradualWakeStep != 0 && secondsToWakeAlarm <= gradualWakeSteps[gradualWakeStep-1]) { + while (gradualWakeStep > 0 && secondsToWakeAlarm <= gradualWakeSteps[gradualWakeStep-1]) { gradualWakeStep--; - gradualWakeVibration = gradualWakeStep; + //gradualWakeVibration = gradualWakeStep; } // Calculate the period for the gradualWakeTimer - if (infiniSleepSettings.graddualWake && gradualWakeStep != 0) { - int64_t gradualWakePeriod = ((secondsToWakeAlarm - gradualWakeSteps[-1+gradualWakeStep--])) * (configTICK_RATE_HZ); - gradualWakeVibration = gradualWakeStep; + if (infiniSleepSettings.graddualWake && gradualWakeStep > 0) { + int64_t gradualWakePeriod = ((secondsToWakeAlarm - gradualWakeSteps[-1+gradualWakeStep])) * (configTICK_RATE_HZ); + //gradualWakeVibration = gradualWakeStep; xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); } @@ -169,7 +169,7 @@ void InfiniSleepController::DisableWakeAlarm() { xTimerStop(wakeAlarmTimer, 0); xTimerStop(gradualWakeTimer, 0); gradualWakeStep = 9; - gradualWakeVibration = 9; + //gradualWakeVibration = 9; isAlerting = false; if (wakeAlarm.isEnabled) { wakeAlarm.isEnabled = false; @@ -190,13 +190,23 @@ void InfiniSleepController::SetOffWakeAlarmNow() { void InfiniSleepController::SetOffGradualWakeNow() { //isGradualWakeAlerting = true; + systemTask->PushMessage(System::Messages::SetOffGradualWake); + + // make sure graudal wake steps are possible + while (gradualWakeStep > 0 && SecondsToWakeAlarm() <= gradualWakeSteps[gradualWakeStep-1]) { + gradualWakeStep--; + //gradualWakeVibration = gradualWakeStep; + } + // Calculate the period for the gradualWakeTimer - if (infiniSleepSettings.graddualWake && gradualWakeStep != 0) { - int64_t gradualWakePeriod = ((SecondsToWakeAlarm() - gradualWakeSteps[-1+gradualWakeStep--])) * (configTICK_RATE_HZ); - gradualWakeVibration = gradualWakeStep; + if (infiniSleepSettings.graddualWake && gradualWakeStep > 0) { + int64_t gradualWakePeriod = ((SecondsToWakeAlarm() - gradualWakeSteps[-1+gradualWakeStep])) * (configTICK_RATE_HZ); + //gradualWakeVibration = gradualWakeStep; xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); + } else { + xTimerStop(gradualWakeTimer, 0); } } diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index d624136c52..686ea7d322 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -155,11 +155,11 @@ namespace Pinetime { // Dertermine the steps for the gradual wake alarm, the corresponding vibration durations determine the power of the vibration static constexpr uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; // In seconds - static constexpr uint16_t gradualWakeVibrationDurations[9] = {1200, 1200, 1000, 1000, 1000, 700, 700, 700, 500}; // In ms + static constexpr uint16_t gradualWakeVibrationDurations[9] = {1000, 1000, 900, 800, 800, 700, 700, 700, 500}; // In ms - uint8_t gradualWakeVibration = 9; // used to keep track of which vibration duration to use, in position form not idex + //uint8_t gradualWakeVibration = 9; // used to keep track of which vibration duration to use, in position form not idex - uint8_t gradualWakeStep = 9; // used to keep track of which step to use, in position form not idex + int8_t gradualWakeStep = 9; // used to keep track of which step to use, in position form not idex uint16_t GetSleepCycles() { uint16_t totalMinutes = GetTotalSleep(); diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 19048199d8..3176ded644 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -408,7 +408,7 @@ void DisplayApp::Refresh() { } else { LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); } - motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1+infiniSleepController.gradualWakeVibration]); + motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1+infiniSleepController.gradualWakeStep]); NRF_LOG_INFO("Gradual wake triggered"); From 95e083f0552e3bfbcd7a7ddac0384d7a8a4f1673 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 11:15:42 -0600 Subject: [PATCH 063/123] Formatted with clang-format --- .../infinisleep/InfiniSleepController.cpp | 194 +++---- .../infinisleep/InfiniSleepController.h | 520 +++++++++--------- src/displayapp/DisplayApp.cpp | 6 +- src/displayapp/screens/Sleep.cpp | 124 +++-- src/displayapp/screens/Sleep.h | 34 +- 5 files changed, 465 insertions(+), 413 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index bdf9628672..46361f65c9 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -1,4 +1,4 @@ -# include "components/infinisleep/InfiniSleepController.h" +#include "components/infinisleep/InfiniSleepController.h" #include "systemtask/SystemTask.h" #include "task.h" #include @@ -7,7 +7,9 @@ using namespace Pinetime::Controllers; using namespace std::chrono_literals; -InfiniSleepController::InfiniSleepController(Controllers::DateTime& dateTimeController, Controllers::FS& fs, Controllers::HeartRateController& heartRateController) +InfiniSleepController::InfiniSleepController(Controllers::DateTime& dateTimeController, + Controllers::FS& fs, + Controllers::HeartRateController& heartRateController) : dateTimeController {dateTimeController}, fs {fs}, heartRateController {heartRateController} { } @@ -32,23 +34,24 @@ namespace { } void InfiniSleepController::Init(System::SystemTask* systemTask) { - this->systemTask = systemTask; - wakeAlarmTimer = xTimerCreate("WakeAlarm", 1, pdFALSE, this, SetOffWakeAlarm); - gradualWakeTimer = xTimerCreate("GradualWake", 1, pdFALSE, this, SetOffGradualWake); - - LoadSettingsFromFile(); - LoadPrevSessionData(); - if (wakeAlarm.isEnabled) { - NRF_LOG_INFO("[InfiniSleepController] Loaded wake alarm was enabled, scheduling"); - ScheduleWakeAlarm(); - } + this->systemTask = systemTask; + wakeAlarmTimer = xTimerCreate("WakeAlarm", 1, pdFALSE, this, SetOffWakeAlarm); + gradualWakeTimer = xTimerCreate("GradualWake", 1, pdFALSE, this, SetOffGradualWake); + + LoadSettingsFromFile(); + LoadPrevSessionData(); + if (wakeAlarm.isEnabled) { + NRF_LOG_INFO("[InfiniSleepController] Loaded wake alarm was enabled, scheduling"); + ScheduleWakeAlarm(); + } } void InfiniSleepController::EnableTracker() { DisableTracker(); NRF_LOG_INFO("[InfiniSleepController] Enabling tracker"); isEnabled = true; - trackerUpdateTimer = xTimerCreate("TrackerUpdate", pdMS_TO_TICKS(TRACKER_UPDATE_INTERVAL_MINS * 60 * 1000), pdFALSE, this, SetOffTrackerUpdate); + trackerUpdateTimer = + xTimerCreate("TrackerUpdate", pdMS_TO_TICKS(TRACKER_UPDATE_INTERVAL_MINS * 60 * 1000), pdFALSE, this, SetOffTrackerUpdate); xTimerStart(trackerUpdateTimer, 0); } @@ -71,105 +74,106 @@ void InfiniSleepController::UpdateTracker() { } void InfiniSleepController::SaveWakeAlarm() { - // verify is save needed - if (wakeAlarmChanged) { - SaveSettingsToFile(); - } - wakeAlarmChanged = false; + // verify is save needed + if (wakeAlarmChanged) { + SaveSettingsToFile(); + } + wakeAlarmChanged = false; } void InfiniSleepController::SaveInfiniSleepSettings() { - // verify is save needed - if (settingsChanged) { - SaveSettingsToFile(); - } - settingsChanged = false; + // verify is save needed + if (settingsChanged) { + SaveSettingsToFile(); + } + settingsChanged = false; } void InfiniSleepController::SetWakeAlarmTime(uint8_t wakeAlarmHr, uint8_t wakeAlarmMin) { - if (wakeAlarm.hours == wakeAlarmHr && wakeAlarm.minutes == wakeAlarmMin) { - return; - } - wakeAlarm.hours = wakeAlarmHr; - wakeAlarm.minutes = wakeAlarmMin; - wakeAlarmChanged = true; + if (wakeAlarm.hours == wakeAlarmHr && wakeAlarm.minutes == wakeAlarmMin) { + return; + } + wakeAlarm.hours = wakeAlarmHr; + wakeAlarm.minutes = wakeAlarmMin; + wakeAlarmChanged = true; } void InfiniSleepController::ScheduleWakeAlarm() { - // This line essentially removes the ability to change recurrance type and sets it to daily - //SetRecurrence(RecurType::Daily); + // This line essentially removes the ability to change recurrance type and sets it to daily + // SetRecurrence(RecurType::Daily); - // Determine the next time the wake alarm needs to go off and set the timer - xTimerStop(wakeAlarmTimer, 0); - xTimerStop(gradualWakeTimer, 0); + // Determine the next time the wake alarm needs to go off and set the timer + xTimerStop(wakeAlarmTimer, 0); + xTimerStop(gradualWakeTimer, 0); - pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; + pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; - gradualWakeStep = 9; - //gradualWakeVibration = 9; + gradualWakeStep = 9; + // gradualWakeVibration = 9; + + auto now = dateTimeController.CurrentDateTime(); + wakeAlarmTime = now; + time_t ttWakeAlarmTime = + std::chrono::system_clock::to_time_t(std::chrono::time_point_cast(wakeAlarmTime)); + tm* tmWakeAlarmTime = std::localtime(&ttWakeAlarmTime); + + // If the time being set has already passed today, the wake alarm should be set for tomorrow + if (wakeAlarm.hours < dateTimeController.Hours() || + (wakeAlarm.hours == dateTimeController.Hours() && wakeAlarm.minutes <= dateTimeController.Minutes())) { + tmWakeAlarmTime->tm_mday += 1; + // tm_wday doesn't update automatically + tmWakeAlarmTime->tm_wday = (tmWakeAlarmTime->tm_wday + 1) % 7; + } - auto now = dateTimeController.CurrentDateTime(); - wakeAlarmTime = now; - time_t ttWakeAlarmTime = std::chrono::system_clock::to_time_t(std::chrono::time_point_cast(wakeAlarmTime)); - tm* tmWakeAlarmTime = std::localtime(&ttWakeAlarmTime); + tmWakeAlarmTime->tm_hour = wakeAlarm.hours; + tmWakeAlarmTime->tm_min = wakeAlarm.minutes; + tmWakeAlarmTime->tm_sec = 0; + + // if alarm is in weekday-only mode, make sure it shifts to the next weekday + // if (wakeAlarm.recurrence == RecurType::Weekdays) { + // if (tmWakeAlarmTime->tm_wday == 0) {// Sunday, shift 1 day + // tmWakeAlarmTime->tm_mday += 1; + // } else if (tmWakeAlarmTime->tm_wday == 6) { // Saturday, shift 2 days + // tmWakeAlarmTime->tm_mday += 2; + // } + // } + tmWakeAlarmTime->tm_isdst = -1; // use system timezone setting to determine DST - // If the time being set has already passed today, the wake alarm should be set for tomorrow - if (wakeAlarm.hours < dateTimeController.Hours() || - (wakeAlarm.hours == dateTimeController.Hours() && wakeAlarm.minutes <= dateTimeController.Minutes())) { - tmWakeAlarmTime->tm_mday += 1; - // tm_wday doesn't update automatically - tmWakeAlarmTime->tm_wday = (tmWakeAlarmTime->tm_wday + 1) % 7; - } + // now can convert back to a time_point + wakeAlarmTime = std::chrono::system_clock::from_time_t(std::mktime(tmWakeAlarmTime)); + int64_t secondsToWakeAlarm = std::chrono::duration_cast(wakeAlarmTime - now).count(); + xTimerChangePeriod(wakeAlarmTimer, secondsToWakeAlarm * configTICK_RATE_HZ, 0); + xTimerStart(wakeAlarmTimer, 0); - tmWakeAlarmTime->tm_hour = wakeAlarm.hours; - tmWakeAlarmTime->tm_min = wakeAlarm.minutes; - tmWakeAlarmTime->tm_sec = 0; - - // if alarm is in weekday-only mode, make sure it shifts to the next weekday - // if (wakeAlarm.recurrence == RecurType::Weekdays) { - // if (tmWakeAlarmTime->tm_wday == 0) {// Sunday, shift 1 day - // tmWakeAlarmTime->tm_mday += 1; - // } else if (tmWakeAlarmTime->tm_wday == 6) { // Saturday, shift 2 days - // tmWakeAlarmTime->tm_mday += 2; - // } - // } - tmWakeAlarmTime->tm_isdst = -1; // use system timezone setting to determine DST - - // now can convert back to a time_point - wakeAlarmTime = std::chrono::system_clock::from_time_t(std::mktime(tmWakeAlarmTime)); - int64_t secondsToWakeAlarm = std::chrono::duration_cast(wakeAlarmTime - now).count(); - xTimerChangePeriod(wakeAlarmTimer, secondsToWakeAlarm * configTICK_RATE_HZ, 0); - xTimerStart(wakeAlarmTimer, 0); - - // make sure graudal wake steps are possible - while (gradualWakeStep > 0 && secondsToWakeAlarm <= gradualWakeSteps[gradualWakeStep-1]) { - gradualWakeStep--; - //gradualWakeVibration = gradualWakeStep; - } + // make sure graudal wake steps are possible + while (gradualWakeStep > 0 && secondsToWakeAlarm <= gradualWakeSteps[gradualWakeStep - 1]) { + gradualWakeStep--; + // gradualWakeVibration = gradualWakeStep; + } - // Calculate the period for the gradualWakeTimer - if (infiniSleepSettings.graddualWake && gradualWakeStep > 0) { - int64_t gradualWakePeriod = ((secondsToWakeAlarm - gradualWakeSteps[-1+gradualWakeStep])) * (configTICK_RATE_HZ); - //gradualWakeVibration = gradualWakeStep; - xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); - xTimerStart(gradualWakeTimer, 0); - } + // Calculate the period for the gradualWakeTimer + if (infiniSleepSettings.graddualWake && gradualWakeStep > 0) { + int64_t gradualWakePeriod = ((secondsToWakeAlarm - gradualWakeSteps[-1 + gradualWakeStep])) * (configTICK_RATE_HZ); + // gradualWakeVibration = gradualWakeStep; + xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); + xTimerStart(gradualWakeTimer, 0); + } - if (!wakeAlarm.isEnabled) { - wakeAlarm.isEnabled = true; - wakeAlarmChanged = true; - } + if (!wakeAlarm.isEnabled) { + wakeAlarm.isEnabled = true; + wakeAlarmChanged = true; + } } uint32_t InfiniSleepController::SecondsToWakeAlarm() const { - return std::chrono::duration_cast(wakeAlarmTime - dateTimeController.CurrentDateTime()).count(); + return std::chrono::duration_cast(wakeAlarmTime - dateTimeController.CurrentDateTime()).count(); } void InfiniSleepController::DisableWakeAlarm() { xTimerStop(wakeAlarmTimer, 0); xTimerStop(gradualWakeTimer, 0); gradualWakeStep = 9; - //gradualWakeVibration = 9; + // gradualWakeVibration = 9; isAlerting = false; if (wakeAlarm.isEnabled) { wakeAlarm.isEnabled = false; @@ -189,20 +193,20 @@ void InfiniSleepController::SetOffWakeAlarmNow() { } void InfiniSleepController::SetOffGradualWakeNow() { - //isGradualWakeAlerting = true; + // isGradualWakeAlerting = true; systemTask->PushMessage(System::Messages::SetOffGradualWake); // make sure graudal wake steps are possible - while (gradualWakeStep > 0 && SecondsToWakeAlarm() <= gradualWakeSteps[gradualWakeStep-1]) { + while (gradualWakeStep > 0 && SecondsToWakeAlarm() <= gradualWakeSteps[gradualWakeStep - 1]) { gradualWakeStep--; - //gradualWakeVibration = gradualWakeStep; + // gradualWakeVibration = gradualWakeStep; } // Calculate the period for the gradualWakeTimer if (infiniSleepSettings.graddualWake && gradualWakeStep > 0) { - int64_t gradualWakePeriod = ((SecondsToWakeAlarm() - gradualWakeSteps[-1+gradualWakeStep])) * (configTICK_RATE_HZ); - //gradualWakeVibration = gradualWakeStep; + int64_t gradualWakePeriod = ((SecondsToWakeAlarm() - gradualWakeSteps[-1 + gradualWakeStep])) * (configTICK_RATE_HZ); + // gradualWakeVibration = gradualWakeStep; xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); } else { @@ -213,9 +217,9 @@ void InfiniSleepController::SetOffGradualWakeNow() { void InfiniSleepController::StopAlerting() { isAlerting = false; // Disable the alarm unless it is recurring - //if (wakeAlarm.recurrence == RecurType::None) { - wakeAlarm.isEnabled = false; - wakeAlarmChanged = true; + // if (wakeAlarm.recurrence == RecurType::None) { + wakeAlarm.isEnabled = false; + wakeAlarmChanged = true; // } else { // // Schedule the alarm for the next day // ScheduleWakeAlarm(); @@ -237,7 +241,7 @@ void InfiniSleepController::UpdateBPM() { prevBpm = bpm; bpm = heartRateController.HeartRate(); - if(prevBpm != 0) + if (prevBpm != 0) rollingBpm = (rollingBpm + bpm) / 2; else rollingBpm = bpm; diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 686ea7d322..21f318679e 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -10,268 +10,268 @@ #include -#define SNOOZE_MINUTES 3 -#define PUSHES_TO_STOP_ALARM 5 +#define SNOOZE_MINUTES 3 +#define PUSHES_TO_STOP_ALARM 5 #define TRACKER_UPDATE_INTERVAL_MINS 5 -#define TRACKER_DATA_FILE_NAME "SleepTracker_Data.csv" -#define PREV_SESSION_DATA_FILE_NAME "SleepTracker_PrevSession.csv" -#define SLEEP_CYCLE_DURATION 90 // sleep cycle duration in minutes -#define DESIRED_CYCLES 5 // desired number of sleep cycles -#define PUSHES_TO_STOP_ALARM_TIMEOUT 2 // in seconds +#define TRACKER_DATA_FILE_NAME "SleepTracker_Data.csv" +#define PREV_SESSION_DATA_FILE_NAME "SleepTracker_PrevSession.csv" +#define SLEEP_CYCLE_DURATION 90 // sleep cycle duration in minutes +#define DESIRED_CYCLES 5 // desired number of sleep cycles +#define PUSHES_TO_STOP_ALARM_TIMEOUT 2 // in seconds namespace Pinetime { - namespace System { - class SystemTask; - } - - namespace Controllers { - class InfiniSleepController { - public: - InfiniSleepController(Controllers::DateTime& dateTimeCOntroller, Controllers::FS& , Controllers::HeartRateController& heartRateController); - - void Init(System::SystemTask* systemTask); - void SaveWakeAlarm(); - void SaveInfiniSleepSettings(); - void SetWakeAlarmTime(uint8_t wakeAlarmHr, uint8_t wakeAlarmMin); - void ScheduleWakeAlarm(); - void DisableWakeAlarm(); - void EnableWakeAlarm(); - void SetOffWakeAlarmNow(); - void SetOffGradualWakeNow(); - uint32_t SecondsToWakeAlarm() const; - void StopAlerting(); - //enum class RecurType { None, Daily, Weekdays }; - - uint8_t pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; - - bool isSnoozing = false; - uint8_t preSnoozeMinutes = 255; - uint8_t preSnnoozeHours = 255; - - // Struct for sessions - struct SessionData { - uint8_t startTimeHours = 0; - uint8_t startTimeMinutes = 0; - uint8_t endTimeHours = 0; - uint8_t endTimeMinutes = 0; - }; - - SessionData prevSessionData; - - void SetPreSnoozeTime() { - if (preSnoozeMinutes != 255 || preSnnoozeHours != 255) { - return; - } - preSnoozeMinutes = wakeAlarm.minutes; - preSnnoozeHours = wakeAlarm.hours; - } - - void RestorePreSnoozeTime() { - if (preSnoozeMinutes == 255 || preSnnoozeHours == 255) { - return; - } - wakeAlarm.minutes = preSnoozeMinutes; - wakeAlarm.hours = preSnnoozeHours; - preSnoozeMinutes = 255; - preSnnoozeHours = 255; - } - - - uint8_t Hours() const { - return wakeAlarm.hours; - } - - uint8_t Minutes() const { - return wakeAlarm.minutes; - } - - bool IsAlerting() const { - return isAlerting; - } - - bool IsEnabled() const { - return isEnabled; - } - - void EnableTracker(); - void DisableTracker(); - void UpdateTracker(); - - // RecurType Recurrence() const { - // return wakeAlarm.recurrence; - // } - - // void SetRecurrence(RecurType recurrence); - - bool BodyTrackingEnabled() const { - return infiniSleepSettings.bodyTracking; - } - - void SetBodyTrackingEnabled(bool enabled) { - infiniSleepSettings.bodyTracking = enabled; - } - - bool HeartRateTrackingEnabled() const { - return infiniSleepSettings.heartRateTracking; - } - - void SetHeartRateTrackingEnabled(bool enabled) { - infiniSleepSettings.heartRateTracking = enabled; - } - - bool GradualWakeEnabled() const { - return infiniSleepSettings.graddualWake; - } - - void SetGradualWakeEnabled(bool enabled) { - infiniSleepSettings.graddualWake = enabled; - } - - bool SmartAlarmEnabled() const { - return infiniSleepSettings.smartAlarm; - } - - void SetSmartAlarmEnabled(bool enabled) { - infiniSleepSettings.smartAlarm = enabled; - } - - void SetSettingsChanged() { - settingsChanged = true; - } - - // Versions 255 is reserved for now, so the version field can be made - // bigger, should it ever be needed. - static constexpr uint8_t wakeAlarmFormatVersion = 1; - - struct WakeAlarmSettings { - static constexpr uint8_t version = wakeAlarmFormatVersion; - uint8_t hours = 7; - uint8_t minutes = 0; - AlarmController::RecurType recurrence = AlarmController::RecurType::Daily; - bool isEnabled = false; - }; - - WakeAlarmSettings wakeAlarm; - - // Dertermine the steps for the gradual wake alarm, the corresponding vibration durations determine the power of the vibration - static constexpr uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; // In seconds - static constexpr uint16_t gradualWakeVibrationDurations[9] = {1000, 1000, 900, 800, 800, 700, 700, 700, 500}; // In ms - - //uint8_t gradualWakeVibration = 9; // used to keep track of which vibration duration to use, in position form not idex - - int8_t gradualWakeStep = 9; // used to keep track of which step to use, in position form not idex - - uint16_t GetSleepCycles() { - uint16_t totalMinutes = GetTotalSleep(); - return (totalMinutes * 100 / SLEEP_CYCLE_DURATION); - } - - uint16_t GetTotalSleep() const { - uint8_t endHours = IsEnabled() ? GetCurrentHour() : prevSessionData.endTimeHours; - uint8_t endMinutes = IsEnabled() ? GetCurrentMinute() : prevSessionData.endTimeMinutes; - - // Calculate total minutes for start and end times - uint16_t startTotalMinutes = prevSessionData.startTimeHours * 60 + prevSessionData.startTimeMinutes; - uint16_t endTotalMinutes = endHours * 60 + endMinutes; - - // If end time is before start time, add 24 hours to end time (handle crossing midnight) - if (endTotalMinutes < startTotalMinutes) { - endTotalMinutes += 24 * 60; - } - - uint16_t sleepMinutes = endTotalMinutes - startTotalMinutes; - - return sleepMinutes; - } - - uint16_t GetSuggestedSleepTime() { - return infiniSleepSettings.desiredCycles * infiniSleepSettings.sleepCycleDuration; - } - - WakeAlarmSettings GetWakeAlarm() const { - return wakeAlarm; - } - - struct InfiniSleepSettings { - bool bodyTracking = false; - bool heartRateTracking = true; - bool graddualWake = false; - bool smartAlarm = false; - uint8_t sleepCycleDuration = SLEEP_CYCLE_DURATION; - uint8_t desiredCycles = DESIRED_CYCLES; - }; - - InfiniSleepSettings infiniSleepSettings; - - InfiniSleepSettings GetInfiniSleepSettings() const { - return infiniSleepSettings; - } - - bool ToggleTracker() { - if (isEnabled) { - prevSessionData.endTimeHours = GetCurrentHour(); - prevSessionData.endTimeMinutes = GetCurrentMinute(); - SavePrevSessionData(); - DisableTracker(); - } else { - ClearDataCSV(TRACKER_DATA_FILE_NAME); - prevSessionData.startTimeHours = GetCurrentHour(); - prevSessionData.startTimeMinutes = GetCurrentMinute(); - EnableTracker(); - } - return isEnabled; - } - - bool IsTrackerEnabled() const { - return isEnabled; - } - - uint8_t GetCurrentHour() const { - return dateTimeController.Hours(); - } - - uint8_t GetCurrentMinute() const { - return dateTimeController.Minutes(); - } - - //int64_t secondsToWakeAlarm = 0; - - int bpm = 0; - int prevBpm = 0; - int rollingBpm = 0; - - void UpdateBPM(); - - uint8_t GetGradualWakeStep() const { - return (9 - gradualWakeStep) + 1; - } - - private: - - bool isAlerting = false; - bool isGradualWakeAlerting = false; - bool wakeAlarmChanged = false; - bool isEnabled = false; - bool settingsChanged = false; - - Controllers::DateTime& dateTimeController; - Controllers::FS& fs; - Controllers::HeartRateController& heartRateController; - System::SystemTask* systemTask = nullptr; - TimerHandle_t wakeAlarmTimer; - TimerHandle_t gradualWakeTimer; - TimerHandle_t trackerUpdateTimer; - std::chrono::time_point wakeAlarmTime; - - void LoadSettingsFromFile(); - void SaveSettingsToFile() const; - void LoadPrevSessionData(); - void SavePrevSessionData() const; - - // For File IO - void WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const; - void ClearDataCSV(const char* fileName) const; - }; - } + namespace System { + class SystemTask; + } + + namespace Controllers { + class InfiniSleepController { + public: + InfiniSleepController(Controllers::DateTime& dateTimeCOntroller, + Controllers::FS&, + Controllers::HeartRateController& heartRateController); + + void Init(System::SystemTask* systemTask); + void SaveWakeAlarm(); + void SaveInfiniSleepSettings(); + void SetWakeAlarmTime(uint8_t wakeAlarmHr, uint8_t wakeAlarmMin); + void ScheduleWakeAlarm(); + void DisableWakeAlarm(); + void EnableWakeAlarm(); + void SetOffWakeAlarmNow(); + void SetOffGradualWakeNow(); + uint32_t SecondsToWakeAlarm() const; + void StopAlerting(); + // enum class RecurType { None, Daily, Weekdays }; + + uint8_t pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; + + bool isSnoozing = false; + uint8_t preSnoozeMinutes = 255; + uint8_t preSnnoozeHours = 255; + + // Struct for sessions + struct SessionData { + uint8_t startTimeHours = 0; + uint8_t startTimeMinutes = 0; + uint8_t endTimeHours = 0; + uint8_t endTimeMinutes = 0; + }; + + SessionData prevSessionData; + + void SetPreSnoozeTime() { + if (preSnoozeMinutes != 255 || preSnnoozeHours != 255) { + return; + } + preSnoozeMinutes = wakeAlarm.minutes; + preSnnoozeHours = wakeAlarm.hours; + } + + void RestorePreSnoozeTime() { + if (preSnoozeMinutes == 255 || preSnnoozeHours == 255) { + return; + } + wakeAlarm.minutes = preSnoozeMinutes; + wakeAlarm.hours = preSnnoozeHours; + preSnoozeMinutes = 255; + preSnnoozeHours = 255; + } + + uint8_t Hours() const { + return wakeAlarm.hours; + } + + uint8_t Minutes() const { + return wakeAlarm.minutes; + } + + bool IsAlerting() const { + return isAlerting; + } + + bool IsEnabled() const { + return isEnabled; + } + + void EnableTracker(); + void DisableTracker(); + void UpdateTracker(); + + // RecurType Recurrence() const { + // return wakeAlarm.recurrence; + // } + + // void SetRecurrence(RecurType recurrence); + + bool BodyTrackingEnabled() const { + return infiniSleepSettings.bodyTracking; + } + + void SetBodyTrackingEnabled(bool enabled) { + infiniSleepSettings.bodyTracking = enabled; + } + + bool HeartRateTrackingEnabled() const { + return infiniSleepSettings.heartRateTracking; + } + + void SetHeartRateTrackingEnabled(bool enabled) { + infiniSleepSettings.heartRateTracking = enabled; + } + + bool GradualWakeEnabled() const { + return infiniSleepSettings.graddualWake; + } + + void SetGradualWakeEnabled(bool enabled) { + infiniSleepSettings.graddualWake = enabled; + } + + bool SmartAlarmEnabled() const { + return infiniSleepSettings.smartAlarm; + } + + void SetSmartAlarmEnabled(bool enabled) { + infiniSleepSettings.smartAlarm = enabled; + } + + void SetSettingsChanged() { + settingsChanged = true; + } + + // Versions 255 is reserved for now, so the version field can be made + // bigger, should it ever be needed. + static constexpr uint8_t wakeAlarmFormatVersion = 1; + + struct WakeAlarmSettings { + static constexpr uint8_t version = wakeAlarmFormatVersion; + uint8_t hours = 7; + uint8_t minutes = 0; + AlarmController::RecurType recurrence = AlarmController::RecurType::Daily; + bool isEnabled = false; + }; + + WakeAlarmSettings wakeAlarm; + + // Dertermine the steps for the gradual wake alarm, the corresponding vibration durations determine the power of the vibration + static constexpr uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; // In seconds + static constexpr uint16_t gradualWakeVibrationDurations[9] = {1000, 1000, 900, 800, 800, 700, 700, 700, 500}; // In ms + + // uint8_t gradualWakeVibration = 9; // used to keep track of which vibration duration to use, in position form not idex + + int8_t gradualWakeStep = 9; // used to keep track of which step to use, in position form not idex + + uint16_t GetSleepCycles() { + uint16_t totalMinutes = GetTotalSleep(); + return (totalMinutes * 100 / SLEEP_CYCLE_DURATION); + } + + uint16_t GetTotalSleep() const { + uint8_t endHours = IsEnabled() ? GetCurrentHour() : prevSessionData.endTimeHours; + uint8_t endMinutes = IsEnabled() ? GetCurrentMinute() : prevSessionData.endTimeMinutes; + + // Calculate total minutes for start and end times + uint16_t startTotalMinutes = prevSessionData.startTimeHours * 60 + prevSessionData.startTimeMinutes; + uint16_t endTotalMinutes = endHours * 60 + endMinutes; + + // If end time is before start time, add 24 hours to end time (handle crossing midnight) + if (endTotalMinutes < startTotalMinutes) { + endTotalMinutes += 24 * 60; + } + + uint16_t sleepMinutes = endTotalMinutes - startTotalMinutes; + + return sleepMinutes; + } + + uint16_t GetSuggestedSleepTime() { + return infiniSleepSettings.desiredCycles * infiniSleepSettings.sleepCycleDuration; + } + + WakeAlarmSettings GetWakeAlarm() const { + return wakeAlarm; + } + + struct InfiniSleepSettings { + bool bodyTracking = false; + bool heartRateTracking = true; + bool graddualWake = false; + bool smartAlarm = false; + uint8_t sleepCycleDuration = SLEEP_CYCLE_DURATION; + uint8_t desiredCycles = DESIRED_CYCLES; + }; + + InfiniSleepSettings infiniSleepSettings; + + InfiniSleepSettings GetInfiniSleepSettings() const { + return infiniSleepSettings; + } + + bool ToggleTracker() { + if (isEnabled) { + prevSessionData.endTimeHours = GetCurrentHour(); + prevSessionData.endTimeMinutes = GetCurrentMinute(); + SavePrevSessionData(); + DisableTracker(); + } else { + ClearDataCSV(TRACKER_DATA_FILE_NAME); + prevSessionData.startTimeHours = GetCurrentHour(); + prevSessionData.startTimeMinutes = GetCurrentMinute(); + EnableTracker(); + } + return isEnabled; + } + + bool IsTrackerEnabled() const { + return isEnabled; + } + + uint8_t GetCurrentHour() const { + return dateTimeController.Hours(); + } + + uint8_t GetCurrentMinute() const { + return dateTimeController.Minutes(); + } + + // int64_t secondsToWakeAlarm = 0; + + int bpm = 0; + int prevBpm = 0; + int rollingBpm = 0; + + void UpdateBPM(); + + uint8_t GetGradualWakeStep() const { + return (9 - gradualWakeStep) + 1; + } + + private: + bool isAlerting = false; + bool isGradualWakeAlerting = false; + bool wakeAlarmChanged = false; + bool isEnabled = false; + bool settingsChanged = false; + + Controllers::DateTime& dateTimeController; + Controllers::FS& fs; + Controllers::HeartRateController& heartRateController; + System::SystemTask* systemTask = nullptr; + TimerHandle_t wakeAlarmTimer; + TimerHandle_t gradualWakeTimer; + TimerHandle_t trackerUpdateTimer; + std::chrono::time_point wakeAlarmTime; + + void LoadSettingsFromFile(); + void SaveSettingsToFile() const; + void LoadPrevSessionData(); + void SavePrevSessionData() const; + + // For File IO + void WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const; + void ClearDataCSV(const char* fileName) const; + }; + } } \ No newline at end of file diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 3176ded644..cc2ffcfdce 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -403,12 +403,12 @@ void DisplayApp::Refresh() { break; case Messages::GradualWakeTriggered: if (currentApp == Apps::Sleep) { - //auto* sleep = static_cast(currentScreen.get()); - //sleep->SetGradualWakeAlerting(); + // auto* sleep = static_cast(currentScreen.get()); + // sleep->SetGradualWakeAlerting(); } else { LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); } - motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1+infiniSleepController.gradualWakeStep]); + motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1 + infiniSleepController.gradualWakeStep]); NRF_LOG_INFO("Gradual wake triggered"); diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 316db79281..638ffb210b 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -23,27 +23,27 @@ namespace { extern InfiniSleepController infiniSleepController; static void settingsToggleEventHandler(lv_obj_t* obj, lv_event_t e) { - if (e != LV_EVENT_VALUE_CHANGED) { - return; - } + if (e != LV_EVENT_VALUE_CHANGED) { + return; + } - const char* setting_name = static_cast(obj->user_data); - bool enabled = lv_checkbox_is_checked(obj); - - if (strcmp(setting_name, "Body Tracking") == 0) { - infiniSleepController.SetBodyTrackingEnabled(enabled); - infiniSleepController.SetSettingsChanged(); - } else if (strcmp(setting_name, "Heart Rate\nTracking") == 0) { - infiniSleepController.SetHeartRateTrackingEnabled(enabled); - infiniSleepController.SetSettingsChanged(); - } else if (strcmp(setting_name, "Gradual Wake") == 0) { - infiniSleepController.SetGradualWakeEnabled(enabled); - infiniSleepController.SetSettingsChanged(); - } else if (strcmp(setting_name, "Smart Alarm\n(alpha)") == 0) { - infiniSleepController.SetSmartAlarmEnabled(enabled); - infiniSleepController.SetSettingsChanged(); - } + const char* setting_name = static_cast(obj->user_data); + bool enabled = lv_checkbox_is_checked(obj); + + if (strcmp(setting_name, "Body Tracking") == 0) { + infiniSleepController.SetBodyTrackingEnabled(enabled); + infiniSleepController.SetSettingsChanged(); + } else if (strcmp(setting_name, "Heart Rate\nTracking") == 0) { + infiniSleepController.SetHeartRateTrackingEnabled(enabled); + infiniSleepController.SetSettingsChanged(); + } else if (strcmp(setting_name, "Gradual Wake") == 0) { + infiniSleepController.SetGradualWakeEnabled(enabled); + infiniSleepController.SetSettingsChanged(); + } else if (strcmp(setting_name, "Smart Alarm\n(alpha)") == 0) { + infiniSleepController.SetSmartAlarmEnabled(enabled); + infiniSleepController.SetSettingsChanged(); } +} static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { auto* screen = static_cast(obj->user_data); @@ -71,7 +71,8 @@ Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, UpdateDisplay(); taskRefresh = lv_task_create(RefreshTaskCallback, 2000, LV_TASK_PRIO_MID, this); - taskPressesToStopAlarmTimeout = lv_task_create(PressesToStopAlarmTimeoutCallback, PUSHES_TO_STOP_ALARM_TIMEOUT * 1000, LV_TASK_PRIO_MID, this); + taskPressesToStopAlarmTimeout = + lv_task_create(PressesToStopAlarmTimeoutCallback, PUSHES_TO_STOP_ALARM_TIMEOUT * 1000, LV_TASK_PRIO_MID, this); } Sleep::~Sleep() { @@ -222,11 +223,17 @@ void Sleep::DrawInfoScreen() { lv_label_set_text_fmt(label_hr, "HR: %d", infiniSleepController.rollingBpm); } lv_obj_align(label_hr, lblTime, LV_ALIGN_CENTER, 0, 50); - lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); - + lv_obj_set_style_local_text_color(label_hr, + LV_LABEL_PART_MAIN, + LV_STATE_DEFAULT, + infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); + if (infiniSleepController.IsEnabled()) { label_start_time = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_fmt(label_start_time, "Began at: %02d:%02d", infiniSleepController.prevSessionData.startTimeHours, infiniSleepController.prevSessionData.startTimeMinutes); + lv_label_set_text_fmt(label_start_time, + "Began at: %02d:%02d", + infiniSleepController.prevSessionData.startTimeHours, + infiniSleepController.prevSessionData.startTimeMinutes); lv_obj_align(label_start_time, label_hr, LV_ALIGN_CENTER, 0, 20); lv_obj_set_style_local_text_color(label_start_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); } @@ -234,28 +241,44 @@ void Sleep::DrawInfoScreen() { // The alarm info label_alarm_time = lv_label_create(lv_scr_act(), nullptr); if (infiniSleepController.GetWakeAlarm().isEnabled) { - lv_label_set_text_fmt(label_alarm_time, "Alarm at: %02d:%02d", infiniSleepController.GetWakeAlarm().hours, infiniSleepController.GetWakeAlarm().minutes); + lv_label_set_text_fmt(label_alarm_time, + "Alarm at: %02d:%02d", + infiniSleepController.GetWakeAlarm().hours, + infiniSleepController.GetWakeAlarm().minutes); } else { lv_label_set_text_static(label_alarm_time, "Alarm is not set."); } lv_obj_align(label_alarm_time, label_hr, LV_ALIGN_CENTER, 0, 40); - lv_obj_set_style_local_text_color(label_alarm_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); + lv_obj_set_style_local_text_color(label_alarm_time, + LV_LABEL_PART_MAIN, + LV_STATE_DEFAULT, + infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); // Gradual Wake info label_gradual_wake = lv_label_create(lv_scr_act(), nullptr); - if (infiniSleepController.GetWakeAlarm().isEnabled && infiniSleepController.GetInfiniSleepSettings().graddualWake && infiniSleepController.gradualWakeStep > 0) { + if (infiniSleepController.GetWakeAlarm().isEnabled && infiniSleepController.GetInfiniSleepSettings().graddualWake && + infiniSleepController.gradualWakeStep > 0) { lv_label_set_text_fmt(label_gradual_wake, "Gradual Wake: %d/9", infiniSleepController.gradualWakeStep); } else { lv_label_set_text_static(label_gradual_wake, "Gradual Wake: OFF"); } lv_obj_align(label_gradual_wake, label_hr, LV_ALIGN_CENTER, 0, 60); - lv_obj_set_style_local_text_color(label_gradual_wake, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); + lv_obj_set_style_local_text_color(label_gradual_wake, + LV_LABEL_PART_MAIN, + LV_STATE_DEFAULT, + infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); // Sleep Cycles Info label_sleep_cycles = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_fmt(label_sleep_cycles, "Sleep Cycles: %d.%02d", infiniSleepController.GetSleepCycles() / 100, infiniSleepController.GetSleepCycles() % 100); + lv_label_set_text_fmt(label_sleep_cycles, + "Sleep Cycles: %d.%02d", + infiniSleepController.GetSleepCycles() / 100, + infiniSleepController.GetSleepCycles() % 100); lv_obj_align(label_sleep_cycles, label_hr, LV_ALIGN_CENTER, 0, 80); - lv_obj_set_style_local_text_color(label_sleep_cycles, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); + lv_obj_set_style_local_text_color(label_sleep_cycles, + LV_LABEL_PART_MAIN, + LV_STATE_DEFAULT, + infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); // Total sleep time label_total_sleep = lv_label_create(lv_scr_act(), nullptr); @@ -264,7 +287,10 @@ void Sleep::DrawInfoScreen() { lv_label_set_text_fmt(label_total_sleep, "Total Sleep: %dh%dm", totalMinutes / 60, totalMinutes % 60); lv_obj_align(label_total_sleep, label_hr, LV_ALIGN_CENTER, 0, 100); - lv_obj_set_style_local_text_color(label_total_sleep, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); + lv_obj_set_style_local_text_color(label_total_sleep, + LV_LABEL_PART_MAIN, + LV_STATE_DEFAULT, + infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); trackerToggleBtn = lv_btn_create(lv_scr_act(), nullptr); trackerToggleBtn->user_data = this; @@ -302,9 +328,9 @@ void Sleep::DrawSettingsScreen() { int y_offset = 50; for (const auto& setting : settings) { - //lv_obj_t* lblSetting = lv_label_create(lv_scr_act(), nullptr); - // lv_label_set_text_static(lblSetting, setting.name); - // lv_obj_align(lblSetting, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); + // lv_obj_t* lblSetting = lv_label_create(lv_scr_act(), nullptr); + // lv_label_set_text_static(lblSetting, setting.name); + // lv_obj_align(lblSetting, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); lv_obj_t* checkbox = lv_checkbox_create(lv_scr_act(), nullptr); checkbox->user_data = const_cast(setting.name); @@ -318,7 +344,7 @@ void Sleep::DrawSettingsScreen() { lv_obj_align(checkbox, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); lv_obj_set_event_cb(checkbox, settingsToggleEventHandler); - //lv_obj_set_event_cb(lblSetting, settingsToggleEventHandler); + // lv_obj_set_event_cb(lblSetting, settingsToggleEventHandler); y_offset += setting.offsetAfter; // Increase the offset to provide better spacing } @@ -355,12 +381,24 @@ void Sleep::DrawSettingsScreen() { auto* screen = static_cast(obj->user_data); int value = screen->infiniSleepController.infiniSleepSettings.sleepCycleDuration; switch (value) { - case 80: value = 85; break; - case 85: value = 90; break; - case 90: value = 95; break; - case 95: value = 100; break; - case 100: value = 80; break; - default: value = 80; break; + case 80: + value = 85; + break; + case 85: + value = 90; + break; + case 90: + value = 95; + break; + case 95: + value = 100; + break; + case 100: + value = 80; + break; + default: + value = 80; + break; } screen->infiniSleepController.infiniSleepSettings.sleepCycleDuration = value; screen->infiniSleepController.SetSettingsChanged(); @@ -453,8 +491,8 @@ bool Sleep::OnButtonPushed() { bool Sleep::OnTouchEvent(Pinetime::Applications::TouchEvents event) { // Swiping should be ignored when in alerting state - if (infiniSleepController.IsAlerting() && - (event != TouchEvents::SwipeDown && event != TouchEvents::SwipeUp && event != TouchEvents::SwipeLeft && event != TouchEvents::SwipeRight)) { + if (infiniSleepController.IsAlerting() && (event != TouchEvents::SwipeDown && event != TouchEvents::SwipeUp && + event != TouchEvents::SwipeLeft && event != TouchEvents::SwipeRight)) { return true; } @@ -502,7 +540,7 @@ void Sleep::SnoozeWakeAlarm() { hourCounter.SetValue(newSnoozeMinutes / 60); minuteCounter.SetValue(newSnoozeMinutes % 60); - + infiniSleepController.ScheduleWakeAlarm(); } diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 7a9ccb4096..7ab7703f81 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -20,8 +20,12 @@ namespace Pinetime { namespace Screens { class Sleep : public Screen { public: - //explicit Sleep(Controllers::HeartRateController& HeartRateController, Controllers::DateTime& DateTimeController, Controllers::FS& fsController, System::SystemTask& systemTask); - explicit Sleep(Controllers::InfiniSleepController& infiniSleepController, Controllers::Settings::ClockType clockType, System::SystemTask& systemTask, Controllers::MotorController& motorController); + // explicit Sleep(Controllers::HeartRateController& HeartRateController, Controllers::DateTime& DateTimeController, Controllers::FS& + // fsController, System::SystemTask& systemTask); + explicit Sleep(Controllers::InfiniSleepController& infiniSleepController, + Controllers::Settings::ClockType clockType, + System::SystemTask& systemTask, + Controllers::MotorController& motorController); ~Sleep() override; void Refresh() override; void SetAlerting(); @@ -44,14 +48,15 @@ namespace Pinetime { // // Data Processing functions // float ConvertToMinutes(int hours, int minutes, int seconds) const; // Get the moving average of BPM Values - //std::vector MovingAverage(const std::vector& bpm, int windowSize) const; + // std::vector MovingAverage(const std::vector& bpm, int windowSize) const; // Detect the sleep regions - //std::vector> DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const; + // std::vector> DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float + // threshold) const; // Get the sleep info - //void GetSleepInfo(const std::vector>& data) const; + // void GetSleepInfo(const std::vector>& data) const; // Read IO - //std::vector> ReadDataCSV(const char* fileName) const; + // std::vector> ReadDataCSV(const char* fileName) const; Controllers::InfiniSleepController& infiniSleepController; @@ -73,13 +78,13 @@ namespace Pinetime { enum class EnableButtonState { On, Off, Alerting }; void DisableWakeAlarm(); - //void EnableWakeAlarm(); - //void SetRecurButtonState(); + // void EnableWakeAlarm(); + // void SetRecurButtonState(); void SetSwitchState(lv_anim_enable_t anim); void SetWakeAlarm(); void ShowAlarmInfo(); void HideAlarmInfo(); - //void ToggleRecurrence(); + // void ToggleRecurrence(); void UpdateWakeAlarmTime(); Widgets::Counter hourCounter = Widgets::Counter(0, 23, jetbrains_mono_76); Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_76); @@ -112,14 +117,19 @@ namespace Pinetime { // lv_task_t* hrRefreshTask; }; } - + template <> struct AppTraits { static constexpr Apps app = Apps::Sleep; static constexpr const char* icon = Screens::Symbols::bed; + static Screens::Screen* Create(AppControllers& controllers) { - //return new Screens::Sleep(controllers.heartRateController, controllers.dateTimeController, controllers.filesystem, *controllers.systemTask); - return new Screens::Sleep(controllers.infiniSleepController, controllers.settingsController.GetClockType(), *controllers.systemTask, controllers.motorController); + // return new Screens::Sleep(controllers.heartRateController, controllers.dateTimeController, controllers.filesystem, + // *controllers.systemTask); + return new Screens::Sleep(controllers.infiniSleepController, + controllers.settingsController.GetClockType(), + *controllers.systemTask, + controllers.motorController); } }; } From 11c9afffbf7516686653f350d011f37e76bb6982 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 11:34:38 -0600 Subject: [PATCH 064/123] Updated DisplayAppRecovery --- src/displayapp/DisplayAppRecovery.cpp | 4 +++- src/displayapp/DisplayAppRecovery.h | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/displayapp/DisplayAppRecovery.cpp b/src/displayapp/DisplayAppRecovery.cpp index bcb8db0e9d..72ce4955ba 100644 --- a/src/displayapp/DisplayAppRecovery.cpp +++ b/src/displayapp/DisplayAppRecovery.cpp @@ -7,6 +7,7 @@ #include "touchhandler/TouchHandler.h" #include "displayapp/icons/infinitime/infinitime-nb.c" #include "components/ble/BleController.h" +#include "displayapp/screens/Sleep.h" using namespace Pinetime::Applications; @@ -25,7 +26,8 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, Pinetime::Controllers::BrightnessController& /*brightnessController*/, Pinetime::Controllers::TouchHandler& /*touchHandler*/, Pinetime::Controllers::FS& /*filesystem*/, - Pinetime::Drivers::SpiNorFlash& /*spiNorFlash*/) + Pinetime::Drivers::SpiNorFlash& /*spiNorFlash*/, + Pinetime::Controllers::InfiniSleepController& infiniSleepController) : lcd {lcd}, bleController {bleController} { } diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h index 162ff2575e..6cb3e7394d 100644 --- a/src/displayapp/DisplayAppRecovery.h +++ b/src/displayapp/DisplayAppRecovery.h @@ -61,7 +61,8 @@ namespace Pinetime { Pinetime::Controllers::BrightnessController& brightnessController, Pinetime::Controllers::TouchHandler& touchHandler, Pinetime::Controllers::FS& filesystem, - Pinetime::Drivers::SpiNorFlash& spiNorFlash); + Pinetime::Drivers::SpiNorFlash& spiNorFlash, + Pinetime::Controllers::InfiniSleepController& infiniSleepController); void Start(); void Start(Pinetime::System::BootErrors) { From 54e3a86cfee38a703b52d0f94db4d680022e275f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 16:05:30 -0600 Subject: [PATCH 065/123] Trying to fix error from Github Build Action --- src/displayapp/DisplayApp.h | 1 + src/displayapp/DisplayAppRecovery.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index 57e1483743..49eb2ec1fc 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -14,6 +14,7 @@ #include "displayapp/screens/Screen.h" #include "components/timer/Timer.h" #include "components/alarm/AlarmController.h" +#include "components/infinisleep/InfiniSleepController.h" #include "touchhandler/TouchHandler.h" #include "displayapp/Messages.h" diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h index 6cb3e7394d..dc5108b66f 100644 --- a/src/displayapp/DisplayAppRecovery.h +++ b/src/displayapp/DisplayAppRecovery.h @@ -37,6 +37,7 @@ namespace Pinetime { class SimpleWeatherService; class MusicService; class NavigationService; + class InfiniSleepController; } namespace System { From 39ff9f9d5fdf7c74d5d9f4ca6f708e27ac19af3b Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 16:32:13 -0600 Subject: [PATCH 066/123] Undid some edits that were for testing --- src/components/infinisleep/InfiniSleepController.cpp | 2 ++ src/components/infinisleep/InfiniSleepController.h | 3 ++- src/displayapp/DisplayApp.cpp | 2 ++ src/displayapp/screens/Sleep.cpp | 2 +- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 46361f65c9..d1b93e3664 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -196,7 +196,9 @@ void InfiniSleepController::SetOffGradualWakeNow() { // isGradualWakeAlerting = true; systemTask->PushMessage(System::Messages::SetOffGradualWake); +} +void InfiniSleepController::UpdateGradualWake() { // make sure graudal wake steps are possible while (gradualWakeStep > 0 && SecondsToWakeAlarm() <= gradualWakeSteps[gradualWakeStep - 1]) { gradualWakeStep--; diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 21f318679e..69aa809004 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -40,6 +40,7 @@ namespace Pinetime { void EnableWakeAlarm(); void SetOffWakeAlarmNow(); void SetOffGradualWakeNow(); + void UpdateGradualWake(); uint32_t SecondsToWakeAlarm() const; void StopAlerting(); // enum class RecurType { None, Daily, Weekdays }; @@ -164,7 +165,7 @@ namespace Pinetime { uint16_t GetSleepCycles() { uint16_t totalMinutes = GetTotalSleep(); - return (totalMinutes * 100 / SLEEP_CYCLE_DURATION); + return (totalMinutes * 100 / infiniSleepSettings.sleepCycleDuration); } uint16_t GetTotalSleep() const { diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index cc2ffcfdce..47ba272a79 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -410,6 +410,8 @@ void DisplayApp::Refresh() { } motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1 + infiniSleepController.gradualWakeStep]); + infiniSleepController.UpdateGradualWake(); + NRF_LOG_INFO("Gradual wake triggered"); break; diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 638ffb210b..d2995cecfb 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -559,7 +559,7 @@ void Sleep::UpdateWakeAlarmTime() { void Sleep::SetAlerting() { lv_obj_set_hidden(enableSwitch, true); lv_obj_set_hidden(btnStop, false); - taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, pdMS_TO_TICKS(5 * 1000), LV_TASK_PRIO_MID, this); + taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, pdMS_TO_TICKS(120 * 1000), LV_TASK_PRIO_MID, this); motorController.StartAlarm(); wakeLock.Lock(); } From a52a1a76b3b9adcb929aa1a64d11cc09928666d0 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 17:28:36 -0600 Subject: [PATCH 067/123] removed commented code --- .../infinisleep/InfiniSleepController.cpp | 32 -------- .../infinisleep/InfiniSleepController.h | 11 --- src/displayapp/screens/Sleep.cpp | 74 +------------------ src/displayapp/screens/Sleep.h | 47 ------------ 4 files changed, 1 insertion(+), 163 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index d1b93e3664..362bbb06d0 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -109,7 +109,6 @@ void InfiniSleepController::ScheduleWakeAlarm() { pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; gradualWakeStep = 9; - // gradualWakeVibration = 9; auto now = dateTimeController.CurrentDateTime(); wakeAlarmTime = now; @@ -129,14 +128,6 @@ void InfiniSleepController::ScheduleWakeAlarm() { tmWakeAlarmTime->tm_min = wakeAlarm.minutes; tmWakeAlarmTime->tm_sec = 0; - // if alarm is in weekday-only mode, make sure it shifts to the next weekday - // if (wakeAlarm.recurrence == RecurType::Weekdays) { - // if (tmWakeAlarmTime->tm_wday == 0) {// Sunday, shift 1 day - // tmWakeAlarmTime->tm_mday += 1; - // } else if (tmWakeAlarmTime->tm_wday == 6) { // Saturday, shift 2 days - // tmWakeAlarmTime->tm_mday += 2; - // } - // } tmWakeAlarmTime->tm_isdst = -1; // use system timezone setting to determine DST // now can convert back to a time_point @@ -154,7 +145,6 @@ void InfiniSleepController::ScheduleWakeAlarm() { // Calculate the period for the gradualWakeTimer if (infiniSleepSettings.graddualWake && gradualWakeStep > 0) { int64_t gradualWakePeriod = ((secondsToWakeAlarm - gradualWakeSteps[-1 + gradualWakeStep])) * (configTICK_RATE_HZ); - // gradualWakeVibration = gradualWakeStep; xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); } @@ -173,7 +163,6 @@ void InfiniSleepController::DisableWakeAlarm() { xTimerStop(wakeAlarmTimer, 0); xTimerStop(gradualWakeTimer, 0); gradualWakeStep = 9; - // gradualWakeVibration = 9; isAlerting = false; if (wakeAlarm.isEnabled) { wakeAlarm.isEnabled = false; @@ -202,13 +191,11 @@ void InfiniSleepController::UpdateGradualWake() { // make sure graudal wake steps are possible while (gradualWakeStep > 0 && SecondsToWakeAlarm() <= gradualWakeSteps[gradualWakeStep - 1]) { gradualWakeStep--; - // gradualWakeVibration = gradualWakeStep; } // Calculate the period for the gradualWakeTimer if (infiniSleepSettings.graddualWake && gradualWakeStep > 0) { int64_t gradualWakePeriod = ((SecondsToWakeAlarm() - gradualWakeSteps[-1 + gradualWakeStep])) * (configTICK_RATE_HZ); - // gradualWakeVibration = gradualWakeStep; xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); } else { @@ -218,24 +205,10 @@ void InfiniSleepController::UpdateGradualWake() { void InfiniSleepController::StopAlerting() { isAlerting = false; - // Disable the alarm unless it is recurring - // if (wakeAlarm.recurrence == RecurType::None) { wakeAlarm.isEnabled = false; wakeAlarmChanged = true; - // } else { - // // Schedule the alarm for the next day - // ScheduleWakeAlarm(); - // } } -// void InfiniSleepController::SetRecurrence(RecurType recurrence) { -// if (wakeAlarm.recurrence == recurrence) { -// return; -// } -// wakeAlarm.recurrence = recurrence; -// wakeAlarmChanged = true; -// } - /* Sleep Tracking Section */ void InfiniSleepController::UpdateBPM() { @@ -342,11 +315,6 @@ void InfiniSleepController::LoadSettingsFromFile() { } void InfiniSleepController::SaveSettingsToFile() const { - // lfs_dir systemDir; - // if (fs.DirOpen("/system/sleep", &systemDir) != LFS_ERR_OK) { - // fs.DirCreate("/system/sleep"); - // } - // fs.DirClose(&systemDir); lfs_file_t alarmFile; WakeAlarmSettings tempWakeAlarm = wakeAlarm; if (isSnoozing) { diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 69aa809004..e777f6e2a2 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -43,7 +43,6 @@ namespace Pinetime { void UpdateGradualWake(); uint32_t SecondsToWakeAlarm() const; void StopAlerting(); - // enum class RecurType { None, Daily, Weekdays }; uint8_t pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; @@ -99,12 +98,6 @@ namespace Pinetime { void DisableTracker(); void UpdateTracker(); - // RecurType Recurrence() const { - // return wakeAlarm.recurrence; - // } - - // void SetRecurrence(RecurType recurrence); - bool BodyTrackingEnabled() const { return infiniSleepSettings.bodyTracking; } @@ -159,8 +152,6 @@ namespace Pinetime { static constexpr uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; // In seconds static constexpr uint16_t gradualWakeVibrationDurations[9] = {1000, 1000, 900, 800, 800, 700, 700, 700, 500}; // In ms - // uint8_t gradualWakeVibration = 9; // used to keep track of which vibration duration to use, in position form not idex - int8_t gradualWakeStep = 9; // used to keep track of which step to use, in position form not idex uint16_t GetSleepCycles() { @@ -236,8 +227,6 @@ namespace Pinetime { return dateTimeController.Minutes(); } - // int64_t secondsToWakeAlarm = 0; - int bpm = 0; int prevBpm = 0; int rollingBpm = 0; diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index d2995cecfb..10b2f63470 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -96,13 +96,6 @@ void Sleep::DisableWakeAlarm() { } } -// void Sleep::EnableWakeAlarm() { -// if (!infiniSleepController.GetWakeAlarm().isEnabled) { -// infiniSleepController.EnableWakeAlarm(); -// lv_switch_on(enableSwitch, LV_ANIM_ON); -// } -// } - void Sleep::Refresh() { UpdateDisplay(); } @@ -172,27 +165,6 @@ void Sleep::DrawAlarmScreen() { txtSuggestedAlarm = lv_label_create(btnSuggestedAlarm, nullptr); lv_label_set_text_static(txtSuggestedAlarm, "Suggested"); - // btnRecur = lv_btn_create(lv_scr_act(), nullptr); - // btnRecur->user_data = this; - // lv_obj_set_event_cb(btnRecur, btnEventHandler); - // lv_obj_set_size(btnRecur, 115, 50); - // lv_obj_align(btnRecur, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); - // txtRecur = lv_label_create(btnRecur, nullptr); - // SetRecurButtonState(); - // lv_obj_set_style_local_bg_color(btnRecur, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, bgColor); - - // btnInfo = lv_btn_create(lv_scr_act(), nullptr); - // btnInfo->user_data = this; - // lv_obj_set_event_cb(btnInfo, btnEventHandler); - // lv_obj_set_size(btnInfo, 50, 50); - // lv_obj_align(btnInfo, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, -4); - // lv_obj_set_style_local_bg_color(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, bgColor); - // lv_obj_set_style_local_border_width(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 4); - // lv_obj_set_style_local_border_color(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); - - // lv_obj_t* txtInfo = lv_label_create(btnInfo, nullptr); - // lv_label_set_text_static(txtInfo, "i"); - enableSwitch = lv_switch_create(lv_scr_act(), nullptr); enableSwitch->user_data = this; lv_obj_set_event_cb(enableSwitch, btnEventHandler); @@ -328,9 +300,6 @@ void Sleep::DrawSettingsScreen() { int y_offset = 50; for (const auto& setting : settings) { - // lv_obj_t* lblSetting = lv_label_create(lv_scr_act(), nullptr); - // lv_label_set_text_static(lblSetting, setting.name); - // lv_obj_align(lblSetting, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); lv_obj_t* checkbox = lv_checkbox_create(lv_scr_act(), nullptr); checkbox->user_data = const_cast(setting.name); @@ -344,8 +313,6 @@ void Sleep::DrawSettingsScreen() { lv_obj_align(checkbox, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); lv_obj_set_event_cb(checkbox, settingsToggleEventHandler); - // lv_obj_set_event_cb(lblSetting, settingsToggleEventHandler); - y_offset += setting.offsetAfter; // Increase the offset to provide better spacing } @@ -420,10 +387,6 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { SnoozeWakeAlarm(); return; } - // if (obj == btnInfo) { - // ShowAlarmInfo(); - // return; - // } if (obj == btnMessage) { HideAlarmInfo(); return; @@ -460,10 +423,6 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { infiniSleepController.ScheduleWakeAlarm(); return; } - // if (obj == btnRecur) { - // DisableWakeAlarm(); - // ToggleRecurrence(); - // } } } @@ -621,35 +580,4 @@ void Sleep::HideAlarmInfo() { lv_obj_del(btnMessage); txtMessage = nullptr; btnMessage = nullptr; -} - -// void Sleep::SetRecurButtonState() { -// using Pinetime::Controllers::InfiniSleepController; -// switch (infiniSleepController.Recurrence()) { -// case InfiniSleepController::RecurType::None: -// lv_label_set_text_static(txtRecur, "ONCE"); -// break; -// case InfiniSleepController::RecurType::Daily: -// lv_label_set_text_static(txtRecur, "DAILY"); -// break; -// case InfiniSleepController::RecurType::Weekdays: -// lv_label_set_text_static(txtRecur, "MON-FRI"); -// break; -// } -// } - -// void Sleep::ToggleRecurrence() { -// using Pinetime::Controllers::InfiniSleepController; -// switch (infiniSleepController.Recurrence()) { -// case InfiniSleepController::RecurType::None: -// infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::Daily); -// break; -// case InfiniSleepController::RecurType::Daily: -// infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::Weekdays); -// break; -// case InfiniSleepController::RecurType::Weekdays: -// infiniSleepController.SetRecurrence(InfiniSleepController::RecurType::None); -// break; -// } -// SetRecurButtonState(); -// } \ No newline at end of file +} \ No newline at end of file diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 7ab7703f81..1a41cb43cf 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -9,19 +9,11 @@ #include "systemtask/WakeLock.h" #include "Symbols.h" -//#define GRADUAL_WAKE_MOTOR_DURATION_MS 1000 - -//#include -//#include // for accumulate -//#include // for abs - namespace Pinetime { namespace Applications { namespace Screens { class Sleep : public Screen { public: - // explicit Sleep(Controllers::HeartRateController& HeartRateController, Controllers::DateTime& DateTimeController, Controllers::FS& - // fsController, System::SystemTask& systemTask); explicit Sleep(Controllers::InfiniSleepController& infiniSleepController, Controllers::Settings::ClockType clockType, System::SystemTask& systemTask, @@ -39,25 +31,6 @@ namespace Pinetime { enum class SleepDisplayState { Alarm, Info, Settings }; SleepDisplayState displayState = SleepDisplayState::Info; - // void Refresh() override; - - // void GetBPM(); - - // void ClearDataCSV(const char* filename) const; - - // // Data Processing functions - // float ConvertToMinutes(int hours, int minutes, int seconds) const; - // Get the moving average of BPM Values - // std::vector MovingAverage(const std::vector& bpm, int windowSize) const; - // Detect the sleep regions - // std::vector> DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float - // threshold) const; - // Get the sleep info - // void GetSleepInfo(const std::vector>& data) const; - - // Read IO - // std::vector> ReadDataCSV(const char* fileName) const; - Controllers::InfiniSleepController& infiniSleepController; private: @@ -78,13 +51,10 @@ namespace Pinetime { enum class EnableButtonState { On, Off, Alerting }; void DisableWakeAlarm(); - // void EnableWakeAlarm(); - // void SetRecurButtonState(); void SetSwitchState(lv_anim_enable_t anim); void SetWakeAlarm(); void ShowAlarmInfo(); void HideAlarmInfo(); - // void ToggleRecurrence(); void UpdateWakeAlarmTime(); Widgets::Counter hourCounter = Widgets::Counter(0, 23, jetbrains_mono_76); Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_76); @@ -93,18 +63,6 @@ namespace Pinetime { void DrawInfoScreen(); void DrawSettingsScreen(); - // Controllers::HeartRateController& heartRateController; - // Controllers::DateTime& dateTimeController; - // Controllers::FS& fsController; - // Pinetime::System::WakeLock wakeLock; - - // // For File IO - // void WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const; - - // int bpm = 0; - // int prevBpm = 0; - // int rollingBpm = 0; - lv_obj_t* label_hr; lv_obj_t* label_start_time; lv_obj_t* label_alarm_time; @@ -112,9 +70,6 @@ namespace Pinetime { lv_obj_t* label_total_sleep; lv_obj_t* label_sleep_cycles; lv_obj_t *btnSuggestedAlarm, *txtSuggestedAlarm; - - // lv_task_t* mainRefreshTask; - // lv_task_t* hrRefreshTask; }; } @@ -124,8 +79,6 @@ namespace Pinetime { static constexpr const char* icon = Screens::Symbols::bed; static Screens::Screen* Create(AppControllers& controllers) { - // return new Screens::Sleep(controllers.heartRateController, controllers.dateTimeController, controllers.filesystem, - // *controllers.systemTask); return new Screens::Sleep(controllers.infiniSleepController, controllers.settingsController.GetClockType(), *controllers.systemTask, From c106914d13ab9133f84db9a11467fe59610617cf Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 18:18:25 -0600 Subject: [PATCH 068/123] Finally fixed errors during "make -j4 all" --- src/displayapp/DisplayAppRecovery.cpp | 2 +- src/displayapp/DisplayAppRecovery.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/displayapp/DisplayAppRecovery.cpp b/src/displayapp/DisplayAppRecovery.cpp index 72ce4955ba..82d8c99c5e 100644 --- a/src/displayapp/DisplayAppRecovery.cpp +++ b/src/displayapp/DisplayAppRecovery.cpp @@ -28,7 +28,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, Pinetime::Controllers::FS& /*filesystem*/, Pinetime::Drivers::SpiNorFlash& /*spiNorFlash*/, Pinetime::Controllers::InfiniSleepController& infiniSleepController) - : lcd {lcd}, bleController {bleController} { + : lcd {lcd}, bleController {bleController}, infiniSleepController {infiniSleepController} { } void DisplayApp::Start() { diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h index dc5108b66f..937265d41b 100644 --- a/src/displayapp/DisplayAppRecovery.h +++ b/src/displayapp/DisplayAppRecovery.h @@ -85,6 +85,7 @@ namespace Pinetime { void Refresh(); Pinetime::Drivers::St7789& lcd; const Controllers::Ble& bleController; + const Controllers::InfiniSleepController& infiniSleepController; static constexpr uint8_t queueSize = 10; static constexpr uint8_t itemSize = 1; From df248778b9e231f5716b16541441e904e97e4500 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 20:23:17 -0600 Subject: [PATCH 069/123] Removed sleep controller from recovery firmware --- src/displayapp/DisplayAppRecovery.cpp | 4 ++-- src/displayapp/DisplayAppRecovery.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/displayapp/DisplayAppRecovery.cpp b/src/displayapp/DisplayAppRecovery.cpp index 82d8c99c5e..2500dcad32 100644 --- a/src/displayapp/DisplayAppRecovery.cpp +++ b/src/displayapp/DisplayAppRecovery.cpp @@ -27,8 +27,8 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, Pinetime::Controllers::TouchHandler& /*touchHandler*/, Pinetime::Controllers::FS& /*filesystem*/, Pinetime::Drivers::SpiNorFlash& /*spiNorFlash*/, - Pinetime::Controllers::InfiniSleepController& infiniSleepController) - : lcd {lcd}, bleController {bleController}, infiniSleepController {infiniSleepController} { + Pinetime::Controllers::InfiniSleepController& /*infiniSleepController*/) + : lcd {lcd}, bleController {bleController} { } void DisplayApp::Start() { diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h index 937265d41b..dc5108b66f 100644 --- a/src/displayapp/DisplayAppRecovery.h +++ b/src/displayapp/DisplayAppRecovery.h @@ -85,7 +85,6 @@ namespace Pinetime { void Refresh(); Pinetime::Drivers::St7789& lcd; const Controllers::Ble& bleController; - const Controllers::InfiniSleepController& infiniSleepController; static constexpr uint8_t queueSize = 10; static constexpr uint8_t itemSize = 1; From 6717b166a0100889fb71317f703500974ace8e1d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 25 Nov 2024 18:44:22 -0600 Subject: [PATCH 070/123] Fixed Alert retriggering due to Display Update. This seems to be the root of most of the previous bugs of the snooze alarm time constantly changing and the motor buzzing weird due to retriggering --- src/displayapp/screens/Sleep.cpp | 36 +++++++++++++++++++++++++------- src/displayapp/screens/Sleep.h | 6 +++++- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 10b2f63470..1876b32091 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -52,7 +52,7 @@ static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { static void SnoozeAlarmTaskCallback(lv_task_t* task) { auto* screen = static_cast(task->user_data); - lv_task_del(task); + lv_task_set_prio(task, LV_TASK_PRIO_OFF); screen->StopAlerting(false); screen->SnoozeWakeAlarm(); } @@ -175,6 +175,12 @@ void Sleep::DrawAlarmScreen() { UpdateWakeAlarmTime(); + if (alreadyAlerting) { + RedrawSetAlerting(); + return; + } + + if (infiniSleepController.IsAlerting()) { SetAlerting(); } else { @@ -437,8 +443,10 @@ bool Sleep::OnButtonPushed() { infiniSleepController.pushesLeftToStopWakeAlarm--; return true; } else { + if (infiniSleepController.isSnoozing) { + infiniSleepController.RestorePreSnoozeTime(); + } infiniSleepController.isSnoozing = false; - infiniSleepController.RestorePreSnoozeTime(); StopAlerting(); UpdateDisplay(); return true; @@ -455,6 +463,9 @@ bool Sleep::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return true; } + lastDisplayState = displayState; + NRF_LOG_INFO("Last Display State: %d", static_cast(lastDisplayState)); + // The cases for swiping to change page on app switch (event) { case TouchEvents::SwipeRight: @@ -486,8 +497,12 @@ void Sleep::OnValueChanged() { // Currently snoozes baeed on define statement in InfiniSleepController.h void Sleep::SnoozeWakeAlarm() { - lv_task_del(taskSnoozeWakeAlarm); - taskSnoozeWakeAlarm = nullptr; + if (taskSnoozeWakeAlarm != nullptr) { + lv_task_del(taskSnoozeWakeAlarm); + taskSnoozeWakeAlarm = nullptr; + } + + NRF_LOG_INFO("Snoozing alarm for %d minutes", SNOOZE_MINUTES); uint16_t totalAlarmMinutes = infiniSleepController.GetCurrentHour() * 60 + infiniSleepController.GetCurrentMinute(); uint16_t newSnoozeMinutes = totalAlarmMinutes + SNOOZE_MINUTES; @@ -518,9 +533,17 @@ void Sleep::UpdateWakeAlarmTime() { void Sleep::SetAlerting() { lv_obj_set_hidden(enableSwitch, true); lv_obj_set_hidden(btnStop, false); - taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, pdMS_TO_TICKS(120 * 1000), LV_TASK_PRIO_MID, this); + NRF_LOG_INFO("Alarm is alerting"); + taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, 120 * 1000, LV_TASK_PRIO_MID, this); motorController.StartAlarm(); wakeLock.Lock(); + alreadyAlerting = true; +} + +void Sleep::RedrawSetAlerting() { + lv_obj_set_hidden(enableSwitch, true); + lv_obj_set_hidden(btnStop, false); + wakeLock.Lock(); } void Sleep::StopAlerting(bool setSwitch) { @@ -529,11 +552,10 @@ void Sleep::StopAlerting(bool setSwitch) { if (setSwitch) { SetSwitchState(LV_ANIM_OFF); } - lv_task_del(taskSnoozeWakeAlarm); - taskSnoozeWakeAlarm = nullptr; wakeLock.Release(); lv_obj_set_hidden(enableSwitch, false); lv_obj_set_hidden(btnStop, true); + alreadyAlerting = false; } void Sleep::SetSwitchState(lv_anim_enable_t anim) { diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 1a41cb43cf..514867917a 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -21,6 +21,7 @@ namespace Pinetime { ~Sleep() override; void Refresh() override; void SetAlerting(); + void RedrawSetAlerting(); void OnButtonEvent(lv_obj_t* obj, lv_event_t event); bool OnButtonPushed() override; bool OnTouchEvent(TouchEvents event) override; @@ -30,6 +31,7 @@ namespace Pinetime { void UpdateDisplay(); enum class SleepDisplayState { Alarm, Info, Settings }; SleepDisplayState displayState = SleepDisplayState::Info; + SleepDisplayState lastDisplayState = SleepDisplayState::Info; Controllers::InfiniSleepController& infiniSleepController; @@ -49,7 +51,7 @@ namespace Pinetime { lv_task_t* taskPressesToStopAlarmTimeout = nullptr; - enum class EnableButtonState { On, Off, Alerting }; + //enum class EnableButtonState { On, Off, Alerting }; void DisableWakeAlarm(); void SetSwitchState(lv_anim_enable_t anim); void SetWakeAlarm(); @@ -63,6 +65,8 @@ namespace Pinetime { void DrawInfoScreen(); void DrawSettingsScreen(); + bool alreadyAlerting = false; + lv_obj_t* label_hr; lv_obj_t* label_start_time; lv_obj_t* label_alarm_time; From 891bae948456bb6b8a08a6d578f14d9a3409b872 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 25 Nov 2024 18:45:26 -0600 Subject: [PATCH 071/123] Formatted Code --- src/displayapp/screens/Sleep.cpp | 1 - src/displayapp/screens/Sleep.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 1876b32091..36fb60bf17 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -180,7 +180,6 @@ void Sleep::DrawAlarmScreen() { return; } - if (infiniSleepController.IsAlerting()) { SetAlerting(); } else { diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 514867917a..4e33cf5e89 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -51,7 +51,7 @@ namespace Pinetime { lv_task_t* taskPressesToStopAlarmTimeout = nullptr; - //enum class EnableButtonState { On, Off, Alerting }; + // enum class EnableButtonState { On, Off, Alerting }; void DisableWakeAlarm(); void SetSwitchState(lv_anim_enable_t anim); void SetWakeAlarm(); From 651c51a32082e76cbd721695b4f558beec47c853 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 27 Nov 2024 12:51:45 -0600 Subject: [PATCH 072/123] Made suggested alarm time label more descriptive --- src/displayapp/screens/Sleep.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 36fb60bf17..1270d9c0f0 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -163,7 +163,7 @@ void Sleep::DrawAlarmScreen() { lv_obj_set_size(btnSuggestedAlarm, 115, 50); lv_obj_align(btnSuggestedAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); txtSuggestedAlarm = lv_label_create(btnSuggestedAlarm, nullptr); - lv_label_set_text_static(txtSuggestedAlarm, "Suggested"); + lv_label_set_text_static(txtSuggestedAlarm, "Use Sugg.\nAlarmTime"); enableSwitch = lv_switch_create(lv_scr_act(), nullptr); enableSwitch->user_data = this; From 16c319a89b4ef16cbf4c32efef8b618c58a595e6 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 00:17:55 -0600 Subject: [PATCH 073/123] Made sure double clicking side button doesn't show notifications when alerting --- src/displayapp/DisplayApp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 47ba272a79..776ca725ef 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -499,7 +499,7 @@ void DisplayApp::Refresh() { LoadNewScreen(Apps::SysInfo, DisplayApp::FullRefreshDirections::Up); break; case Messages::ButtonDoubleClicked: - if (currentApp != Apps::Notifications && currentApp != Apps::NotificationsPreview) { + if (!infiniSleepController.IsAlerting() && currentApp != Apps::Notifications && currentApp != Apps::NotificationsPreview) { LoadNewScreen(Apps::Notifications, DisplayApp::FullRefreshDirections::Down); } break; From 240ee6db6ae7e8cd07e14adc54a9aef8f00fa69f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 00:18:57 -0600 Subject: [PATCH 074/123] Added PWM to motor controller Main reason is to control the intensity of the wakeup vibrations --- src/CMakeLists.txt | 1 + src/components/motor/MotorController.cpp | 74 ++++++++++++++++++++++++ src/components/motor/MotorController.h | 9 +++ src/displayapp/DisplayApp.cpp | 5 +- src/sdk_config.h | 4 +- 5 files changed, 89 insertions(+), 4 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1f1946b2f7..c0c8181586 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -42,6 +42,7 @@ set(SDK_SOURCE_FILES "${NRF5_SDK_PATH}/modules/nrfx/drivers/src/nrfx_gpiote.c" "${NRF5_SDK_PATH}/modules/nrfx/soc/nrfx_atomic.c" "${NRF5_SDK_PATH}/modules/nrfx/drivers/src/nrfx_saadc.c" + "${NRF5_SDK_PATH}/modules/nrfx/drivers/src/nrfx_pwm.c" # FreeRTOS ${NRF5_SDK_PATH}/external/freertos/source/croutine.c diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index 044bc24bd2..cdc41ae6e4 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -2,9 +2,21 @@ #include #include "systemtask/SystemTask.h" #include "drivers/PinMap.h" +#include "nrf_drv_pwm.h" using namespace Pinetime::Controllers; +static nrf_drv_pwm_t m_pwm2 = NRF_DRV_PWM_INSTANCE(2); +static nrf_pwm_values_individual_t seq_values; +static nrf_pwm_sequence_t const seq = { + { + .p_individual = &seq_values + }, + NRF_PWM_VALUES_LENGTH(seq_values), + 0, + 0 +}; + void MotorController::Init() { nrf_gpio_cfg_output(PinMap::Motor); nrf_gpio_pin_set(PinMap::Motor); @@ -12,6 +24,38 @@ void MotorController::Init() { shortVib = xTimerCreate("shortVib", 1, pdFALSE, nullptr, StopMotor); longVib = xTimerCreate("longVib", pdMS_TO_TICKS(1000), pdTRUE, this, Ring); alarmVib = xTimerCreate("alarmVib", pdMS_TO_TICKS(500), pdTRUE, this, AlarmRing); + //gradualWakeBuzzDelay = xTimerCreate("gradualWakeBuzzDelay", pdMS_TO_TICKS(15), pdTRUE, this, GradualWakeBuzzRing); + //gradualWakeBuzzEnd = xTimerCreate("gradualWakeBuzzEnd", pdMS_TO_TICKS(550), pdTRUE, this, StopGradualWakeBuzzCallback); + + InitPWM(); +} + +void MotorController::InitPWM() { + nrf_drv_pwm_config_t const config2 = { + .output_pins = { + PinMap::Motor, // channel 0 + NRF_DRV_PWM_PIN_NOT_USED, // channel 1 + NRF_DRV_PWM_PIN_NOT_USED, // channel 2 + NRF_DRV_PWM_PIN_NOT_USED // channel 3 + }, + .irq_priority = APP_IRQ_PRIORITY_LOWEST, + .base_clock = NRF_PWM_CLK_1MHz, + .count_mode = NRF_PWM_MODE_UP, + .top_value = 100, + .load_mode = NRF_PWM_LOAD_INDIVIDUAL, + .step_mode = NRF_PWM_STEP_AUTO + }; + + nrf_drv_pwm_init(&m_pwm2, &config2, NULL); + seq_values.channel_0 = 0; + nrf_drv_pwm_simple_playback(&m_pwm2, &seq, 1, NRF_DRV_PWM_FLAG_LOOP); + + SetMotorStrength(100); +} + +void MotorController::SetMotorStrength(uint8_t strength) { + if (strength > 100) strength = 100; + seq_values.channel_0 = strength; } void MotorController::Ring(TimerHandle_t xTimer) { @@ -27,10 +71,12 @@ void MotorController::AlarmRing(TimerHandle_t xTimer) { void MotorController::RunForDuration(uint16_t motorDuration) { if (motorDuration > 0 && xTimerChangePeriod(shortVib, pdMS_TO_TICKS(motorDuration), 0) == pdPASS && xTimerStart(shortVib, 0) == pdPASS) { nrf_gpio_pin_clear(PinMap::Motor); + nrf_drv_pwm_simple_playback(&m_pwm2, &seq, 1, NRF_DRV_PWM_FLAG_LOOP); } } void MotorController::StartRinging() { + SetMotorStrength(100); RunForDuration(50); xTimerStart(longVib, 0); } @@ -38,9 +84,11 @@ void MotorController::StartRinging() { void MotorController::StopRinging() { xTimerStop(longVib, 0); nrf_gpio_pin_set(PinMap::Motor); + nrf_drv_pwm_stop(&m_pwm2, true); } void MotorController::StartAlarm() { + SetMotorStrength(100); RunForDuration(300); xTimerStart(alarmVib, 0); } @@ -48,8 +96,34 @@ void MotorController::StartAlarm() { void MotorController::StopAlarm() { xTimerStop(alarmVib, 0); nrf_gpio_pin_set(PinMap::Motor); + nrf_drv_pwm_stop(&m_pwm2, true); } void MotorController::StopMotor(TimerHandle_t /*xTimer*/) { nrf_gpio_pin_set(PinMap::Motor); + nrf_drv_pwm_stop(&m_pwm2, true); +} + +void MotorController::GradualWakeBuzz() { + SetMotorStrength(40); + RunForDuration(540); + //xTimerStart(gradualWakeBuzzDelay, 0); + //xTimerStart(gradualWakeBuzzEnd, 0); +} + +void MotorController::GradualWakeBuzzRing(TimerHandle_t xTimer) { + auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); + motorController->RunForDuration(12); +} + +void MotorController::StopGradualWakeBuzzCallback(TimerHandle_t xTimer) { + auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); + motorController->StopGradualWakeBuzz(); +} + +void MotorController::StopGradualWakeBuzz() { + //xTimerStop(gradualWakeBuzzDelay, 0); + xTimerStop(gradualWakeBuzzEnd, 0); + SetMotorStrength(100); + StopMotor(nullptr); } diff --git a/src/components/motor/MotorController.h b/src/components/motor/MotorController.h index 4acbeda710..455d04c1f0 100644 --- a/src/components/motor/MotorController.h +++ b/src/components/motor/MotorController.h @@ -17,14 +17,23 @@ namespace Pinetime { void StopRinging(); void StartAlarm(); void StopAlarm(); + void GradualWakeBuzz(); + void StopGradualWakeBuzz(); private: static void Ring(TimerHandle_t xTimer); static void AlarmRing(TimerHandle_t xTimer); static void StopMotor(TimerHandle_t xTimer); + static void GradualWakeBuzzRing(TimerHandle_t xTimer); + static void StopGradualWakeBuzzCallback(TimerHandle_t xTimer); + void InitPWM(); + void SetMotorStrength(uint8_t strength); + TimerHandle_t shortVib; TimerHandle_t longVib; TimerHandle_t alarmVib; + TimerHandle_t gradualWakeBuzzDelay; + TimerHandle_t gradualWakeBuzzEnd; }; } } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 776ca725ef..9497396f3e 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -408,8 +408,9 @@ void DisplayApp::Refresh() { } else { LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); } - motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1 + infiniSleepController.gradualWakeStep]); - + //motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1 + infiniSleepController.gradualWakeStep]); + motorController.GradualWakeBuzz(); + infiniSleepController.UpdateGradualWake(); NRF_LOG_INFO("Gradual wake triggered"); diff --git a/src/sdk_config.h b/src/sdk_config.h index b42b39244f..da44682d4b 100644 --- a/src/sdk_config.h +++ b/src/sdk_config.h @@ -5633,7 +5633,7 @@ // PWM_ENABLED - nrf_drv_pwm - PWM peripheral driver - legacy layer //========================================================== #ifndef PWM_ENABLED - #define PWM_ENABLED 0 + #define PWM_ENABLED 1 #endif // PWM_DEFAULT_CONFIG_OUT0_PIN - Out0 pin <0-31> @@ -5739,7 +5739,7 @@ // PWM2_ENABLED - Enable PWM2 instance #ifndef PWM2_ENABLED - #define PWM2_ENABLED 0 + #define PWM2_ENABLED 1 #endif // PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED - Enables nRF52 Anomaly 109 workaround for PWM. From ed82380538606273908fd889592405494395292e Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 00:32:56 -0600 Subject: [PATCH 075/123] Updated Gradual Wake Buzz values to try to match SleepTk --- src/components/motor/MotorController.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index cdc41ae6e4..cf9b3ae84f 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -105,8 +105,8 @@ void MotorController::StopMotor(TimerHandle_t /*xTimer*/) { } void MotorController::GradualWakeBuzz() { - SetMotorStrength(40); - RunForDuration(540); + SetMotorStrength(80); + RunForDuration(100); //xTimerStart(gradualWakeBuzzDelay, 0); //xTimerStart(gradualWakeBuzzEnd, 0); } From 4b94d9eac259e828047d156983c95a3ea021dc5f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 20:13:57 -0600 Subject: [PATCH 076/123] Removed periodic file logging --- src/components/infinisleep/InfiniSleepController.cpp | 6 +++--- src/displayapp/screens/Sleep.cpp | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 362bbb06d0..dffbb0bc6e 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -230,9 +230,9 @@ void InfiniSleepController::UpdateBPM() { NRF_LOG_INFO("BPM: %d at %02d:%02d:%02d", rollingBpm, hours, minutes, seconds); // Write data to CSV - const int motion = 0; // Placeholder for motion data - std::tuple data[1] = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; - WriteDataCSV(TRACKER_DATA_FILE_NAME, data, 1); + //const int motion = 0; // Placeholder for motion data + //std::tuple data[1] = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; + //WriteDataCSV(TRACKER_DATA_FILE_NAME, data, 1); } void InfiniSleepController::WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const { diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 1270d9c0f0..82b692ea6b 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -69,6 +69,8 @@ Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, Controllers::MotorController& motorController) : infiniSleepController {infiniSleepController}, wakeLock(systemTask), motorController {motorController}, clockType {clockType} { + infiniSleepController.SetHeartRateTrackingEnabled(false); + infiniSleepController.SetSettingsChanged(); UpdateDisplay(); taskRefresh = lv_task_create(RefreshTaskCallback, 2000, LV_TASK_PRIO_MID, this); taskPressesToStopAlarmTimeout = @@ -298,7 +300,7 @@ void Sleep::DrawSettingsScreen() { const Setting settings[] = { //{"Body Tracking", infiniSleepController.BodyTrackingEnabled()}, - {"Heart Rate\nTracking", infiniSleepController.HeartRateTrackingEnabled(), 60}, + // {"Heart Rate\nTracking", infiniSleepController.HeartRateTrackingEnabled(), 60}, {"Gradual Wake", infiniSleepController.GradualWakeEnabled()}, //{"Smart Alarm\n(alpha)", infiniSleepController.SmartAlarmEnabled()} }; From 66b31a552d26d9baf419073bd486e03900f4be7e Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 20:15:27 -0600 Subject: [PATCH 077/123] UI Tweaks --- src/displayapp/screens/Sleep.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 82b692ea6b..d13242b2a7 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -154,7 +154,7 @@ void Sleep::DrawAlarmScreen() { lv_obj_align(btnStop, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); lv_obj_set_style_local_bg_color(btnStop, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); txtStop = lv_label_create(btnStop, nullptr); - lv_label_set_text_static(txtStop, Symbols::stop); + lv_label_set_text_static(txtStop, "ZzZz"); lv_obj_set_hidden(btnStop, true); static constexpr lv_color_t bgColor = Colors::bgAlt; @@ -164,8 +164,19 @@ void Sleep::DrawAlarmScreen() { lv_obj_set_event_cb(btnSuggestedAlarm, btnEventHandler); lv_obj_set_size(btnSuggestedAlarm, 115, 50); lv_obj_align(btnSuggestedAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); - txtSuggestedAlarm = lv_label_create(btnSuggestedAlarm, nullptr); - lv_label_set_text_static(txtSuggestedAlarm, "Use Sugg.\nAlarmTime"); + //txtSuggestedAlarm = lv_label_create(btnSuggestedAlarm, nullptr); + //lv_label_set_text_static(txtSuggestedAlarm, "Use Sugg.\nAlarmTime"); + + txtSuggestedAlarm = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(txtSuggestedAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -15, -10); + lv_label_set_text_static(txtSuggestedAlarm, "Auto"); + + + 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_WHITE); + lv_obj_align(icon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -50, -10); + lv_label_set_text_static(icon, Symbols::sun); + enableSwitch = lv_switch_create(lv_scr_act(), nullptr); enableSwitch->user_data = this; @@ -235,8 +246,8 @@ void Sleep::DrawInfoScreen() { // Gradual Wake info label_gradual_wake = lv_label_create(lv_scr_act(), nullptr); - if (infiniSleepController.GetWakeAlarm().isEnabled && infiniSleepController.GetInfiniSleepSettings().graddualWake && - infiniSleepController.gradualWakeStep > 0) { + if (infiniSleepController.GetInfiniSleepSettings().graddualWake && + infiniSleepController.gradualWakeStep >= 0) { lv_label_set_text_fmt(label_gradual_wake, "Gradual Wake: %d/9", infiniSleepController.gradualWakeStep); } else { lv_label_set_text_static(label_gradual_wake, "Gradual Wake: OFF"); From badef472d098b0c25b6e1ca8d97f6ca61f90c1fe Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 22:43:47 -0600 Subject: [PATCH 078/123] Removed extra data write --- src/components/infinisleep/InfiniSleepController.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index e777f6e2a2..be80a270d5 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -207,7 +207,7 @@ namespace Pinetime { SavePrevSessionData(); DisableTracker(); } else { - ClearDataCSV(TRACKER_DATA_FILE_NAME); + //ClearDataCSV(TRACKER_DATA_FILE_NAME); prevSessionData.startTimeHours = GetCurrentHour(); prevSessionData.startTimeMinutes = GetCurrentMinute(); EnableTracker(); From 04b5d6f8e1e8757337d0444b38fe9c040d278417 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 22:47:23 -0600 Subject: [PATCH 079/123] Make app go to info page when alarm is turned off and also turn of tracker. Also removed screen turning on when gradual wake --- src/displayapp/DisplayApp.cpp | 2 +- src/displayapp/screens/Sleep.cpp | 7 +++++++ src/systemtask/SystemTask.cpp | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 9497396f3e..f86d5f459d 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -406,7 +406,7 @@ void DisplayApp::Refresh() { // auto* sleep = static_cast(currentScreen.get()); // sleep->SetGradualWakeAlerting(); } else { - LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); + //LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); } //motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1 + infiniSleepController.gradualWakeStep]); motorController.GradualWakeBuzz(); diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index d13242b2a7..76f2a3aa5c 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -460,6 +460,13 @@ bool Sleep::OnButtonPushed() { } infiniSleepController.isSnoozing = false; StopAlerting(); + if (infiniSleepController.IsTrackerEnabled()) { + displayState = SleepDisplayState::Info; + UpdateDisplay(); + OnButtonEvent(trackerToggleBtn, LV_EVENT_CLICKED); + return true; + } + displayState = SleepDisplayState::Info; UpdateDisplay(); return true; } diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index ac301629cc..d195602150 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -231,7 +231,7 @@ void SystemTask::Work() { displayApp.PushMessage(Pinetime::Applications::Display::Messages::WakeAlarmTriggered); break; case Messages::SetOffGradualWake: - GoToRunning(); + //GoToRunning(); displayApp.PushMessage(Pinetime::Applications::Display::Messages::GradualWakeTriggered); break; case Messages::BleConnected: From 5115fe792c4dc892051243a25582fd2ceed29025 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 22:48:30 -0600 Subject: [PATCH 080/123] Added PWM to Motor Controller --- src/components/motor/MotorController.cpp | 101 +++++++++++------------ src/components/motor/MotorController.h | 3 +- 2 files changed, 49 insertions(+), 55 deletions(-) diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index cf9b3ae84f..9d02d0a8cb 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -2,60 +2,52 @@ #include #include "systemtask/SystemTask.h" #include "drivers/PinMap.h" -#include "nrf_drv_pwm.h" +#include "nrf_pwm.h" using namespace Pinetime::Controllers; -static nrf_drv_pwm_t m_pwm2 = NRF_DRV_PWM_INSTANCE(2); -static nrf_pwm_values_individual_t seq_values; -static nrf_pwm_sequence_t const seq = { - { - .p_individual = &seq_values - }, - NRF_PWM_VALUES_LENGTH(seq_values), - 0, - 0 -}; +static uint16_t pwmValue = 0; // Declare the variable for PWM value void MotorController::Init() { + // Configure the motor pin as an output nrf_gpio_cfg_output(PinMap::Motor); nrf_gpio_pin_set(PinMap::Motor); + // Configure the PWM sequence + static nrf_pwm_sequence_t seq; + seq.values.p_common = &pwmValue; // Use the PWM value array + seq.length = NRF_PWM_VALUES_LENGTH(pwmValue); + seq.repeats = 0; + seq.end_delay = 0; + + // Configure the PWM pins + uint32_t out_pins[] = {PinMap::Motor, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED}; + nrf_pwm_pins_set(NRF_PWM2, out_pins); + + // Enable and configure the PWM peripheral + nrf_pwm_enable(NRF_PWM2); + nrf_pwm_configure(NRF_PWM2, NRF_PWM_CLK_1MHz, NRF_PWM_MODE_UP, 255); // Top value determines the resolution + nrf_pwm_loop_set(NRF_PWM2, 0); // Infinite loop + nrf_pwm_decoder_set(NRF_PWM2, NRF_PWM_LOAD_COMMON, NRF_PWM_STEP_AUTO); + nrf_pwm_sequence_set(NRF_PWM2, 0, &seq); + + // Start the PWM with an initial value of 0 + pwmValue = 0; + nrf_pwm_task_trigger(NRF_PWM2, NRF_PWM_TASK_SEQSTART0); + + // Initialize timers for motor actions shortVib = xTimerCreate("shortVib", 1, pdFALSE, nullptr, StopMotor); longVib = xTimerCreate("longVib", pdMS_TO_TICKS(1000), pdTRUE, this, Ring); alarmVib = xTimerCreate("alarmVib", pdMS_TO_TICKS(500), pdTRUE, this, AlarmRing); - //gradualWakeBuzzDelay = xTimerCreate("gradualWakeBuzzDelay", pdMS_TO_TICKS(15), pdTRUE, this, GradualWakeBuzzRing); - //gradualWakeBuzzEnd = xTimerCreate("gradualWakeBuzzEnd", pdMS_TO_TICKS(550), pdTRUE, this, StopGradualWakeBuzzCallback); - - InitPWM(); -} - -void MotorController::InitPWM() { - nrf_drv_pwm_config_t const config2 = { - .output_pins = { - PinMap::Motor, // channel 0 - NRF_DRV_PWM_PIN_NOT_USED, // channel 1 - NRF_DRV_PWM_PIN_NOT_USED, // channel 2 - NRF_DRV_PWM_PIN_NOT_USED // channel 3 - }, - .irq_priority = APP_IRQ_PRIORITY_LOWEST, - .base_clock = NRF_PWM_CLK_1MHz, - .count_mode = NRF_PWM_MODE_UP, - .top_value = 100, - .load_mode = NRF_PWM_LOAD_INDIVIDUAL, - .step_mode = NRF_PWM_STEP_AUTO - }; - - nrf_drv_pwm_init(&m_pwm2, &config2, NULL); - seq_values.channel_0 = 0; - nrf_drv_pwm_simple_playback(&m_pwm2, &seq, 1, NRF_DRV_PWM_FLAG_LOOP); - - SetMotorStrength(100); } void MotorController::SetMotorStrength(uint8_t strength) { - if (strength > 100) strength = 100; - seq_values.channel_0 = strength; + // Ensure strength is within bounds (0-100) + if (strength > 100) + strength = 100; + + // Map the strength to the PWM value (0-100 -> 0-top_value) + pwmValue = (strength * 255) / 100; } void MotorController::Ring(TimerHandle_t xTimer) { @@ -65,13 +57,14 @@ void MotorController::Ring(TimerHandle_t xTimer) { void MotorController::AlarmRing(TimerHandle_t xTimer) { auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); + motorController->SetMotorStrength(80); motorController->RunForDuration(300); } void MotorController::RunForDuration(uint16_t motorDuration) { if (motorDuration > 0 && xTimerChangePeriod(shortVib, pdMS_TO_TICKS(motorDuration), 0) == pdPASS && xTimerStart(shortVib, 0) == pdPASS) { - nrf_gpio_pin_clear(PinMap::Motor); - nrf_drv_pwm_simple_playback(&m_pwm2, &seq, 1, NRF_DRV_PWM_FLAG_LOOP); + // nrf_gpio_pin_clear(PinMap::Motor); + nrf_pwm_task_trigger(NRF_PWM2, NRF_PWM_TASK_SEQSTART0); // Restart the PWM sequence with the updated value } } @@ -83,32 +76,35 @@ void MotorController::StartRinging() { void MotorController::StopRinging() { xTimerStop(longVib, 0); + nrf_pwm_task_trigger(NRF_PWM2, NRF_PWM_TASK_STOP); // Stop the PWM sequence + pwmValue = 0; // Reset the PWM value nrf_gpio_pin_set(PinMap::Motor); - nrf_drv_pwm_stop(&m_pwm2, true); } void MotorController::StartAlarm() { - SetMotorStrength(100); + SetMotorStrength(80); RunForDuration(300); xTimerStart(alarmVib, 0); } void MotorController::StopAlarm() { xTimerStop(alarmVib, 0); + nrf_pwm_task_trigger(NRF_PWM0, NRF_PWM_TASK_STOP); // Stop the PWM sequence + pwmValue = 0; // Reset the PWM value nrf_gpio_pin_set(PinMap::Motor); - nrf_drv_pwm_stop(&m_pwm2, true); } void MotorController::StopMotor(TimerHandle_t /*xTimer*/) { - nrf_gpio_pin_set(PinMap::Motor); - nrf_drv_pwm_stop(&m_pwm2, true); + nrf_pwm_task_trigger(NRF_PWM2, NRF_PWM_TASK_STOP); // Stop the PWM sequence + pwmValue = 0; // Reset the PWM value + nrf_gpio_pin_set(PinMap::Motor); // Set the motor pin to the off state } void MotorController::GradualWakeBuzz() { - SetMotorStrength(80); + SetMotorStrength(60); RunForDuration(100); - //xTimerStart(gradualWakeBuzzDelay, 0); - //xTimerStart(gradualWakeBuzzEnd, 0); + // xTimerStart(gradualWakeBuzzDelay, 0); + // xTimerStart(gradualWakeBuzzEnd, 0); } void MotorController::GradualWakeBuzzRing(TimerHandle_t xTimer) { @@ -122,8 +118,7 @@ void MotorController::StopGradualWakeBuzzCallback(TimerHandle_t xTimer) { } void MotorController::StopGradualWakeBuzz() { - //xTimerStop(gradualWakeBuzzDelay, 0); + // xTimerStop(gradualWakeBuzzDelay, 0); xTimerStop(gradualWakeBuzzEnd, 0); - SetMotorStrength(100); - StopMotor(nullptr); + // StopMotor(nullptr); } diff --git a/src/components/motor/MotorController.h b/src/components/motor/MotorController.h index 455d04c1f0..087074b850 100644 --- a/src/components/motor/MotorController.h +++ b/src/components/motor/MotorController.h @@ -19,6 +19,7 @@ namespace Pinetime { void StopAlarm(); void GradualWakeBuzz(); void StopGradualWakeBuzz(); + void SetMotorStrength(uint8_t strength); private: static void Ring(TimerHandle_t xTimer); @@ -26,8 +27,6 @@ namespace Pinetime { static void StopMotor(TimerHandle_t xTimer); static void GradualWakeBuzzRing(TimerHandle_t xTimer); static void StopGradualWakeBuzzCallback(TimerHandle_t xTimer); - void InitPWM(); - void SetMotorStrength(uint8_t strength); TimerHandle_t shortVib; TimerHandle_t longVib; From a4ee5889bf281b50522d1648fac074be8541f860 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 29 Nov 2024 21:04:49 -0600 Subject: [PATCH 081/123] Reworked UI Layout Changed to vertical swiping and made the order: Info, Alarm, Settings Reworked Info page text and made tracker toggle button larger. Removed cycle duration setting. --- src/displayapp/screens/Sleep.cpp | 128 +++++++++++-------------------- src/displayapp/screens/Sleep.h | 2 +- 2 files changed, 45 insertions(+), 85 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 76f2a3aa5c..a5330f3e20 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -75,6 +75,8 @@ Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, taskRefresh = lv_task_create(RefreshTaskCallback, 2000, LV_TASK_PRIO_MID, this); taskPressesToStopAlarmTimeout = lv_task_create(PressesToStopAlarmTimeoutCallback, PUSHES_TO_STOP_ALARM_TIMEOUT * 1000, LV_TASK_PRIO_MID, this); + infiniSleepController.infiniSleepSettings.sleepCycleDuration = 90; + infiniSleepController.SetSettingsChanged(); } Sleep::~Sleep() { @@ -206,25 +208,38 @@ void Sleep::DrawInfoScreen() { lv_obj_align(lblTime, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 5); lv_obj_set_style_local_text_color(lblTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); - label_hr = lv_label_create(lv_scr_act(), nullptr); - if (infiniSleepController.rollingBpm == 0) { - lv_label_set_text_static(label_hr, "HR: --"); - } else { - lv_label_set_text_fmt(label_hr, "HR: %d", infiniSleepController.rollingBpm); - } - lv_obj_align(label_hr, lblTime, LV_ALIGN_CENTER, 0, 50); - lv_obj_set_style_local_text_color(label_hr, + // Total sleep time + label_total_sleep = lv_label_create(lv_scr_act(), nullptr); + + uint16_t totalMinutes = infiniSleepController.GetTotalSleep(); + + lv_label_set_text_fmt(label_total_sleep, "Time Asleep: %dh%dm", totalMinutes / 60, totalMinutes % 60); + lv_obj_align(label_total_sleep, lv_scr_act(), LV_ALIGN_CENTER, 0, -60); + lv_obj_set_style_local_text_color(label_total_sleep, + LV_LABEL_PART_MAIN, + LV_STATE_DEFAULT, + infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); + + // Sleep Cycles Info + label_sleep_cycles = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_fmt(label_sleep_cycles, + "Sleep Cycles: %d.%02d", + infiniSleepController.GetSleepCycles() / 100, + infiniSleepController.GetSleepCycles() % 100); + lv_obj_align(label_sleep_cycles, lv_scr_act(), LV_ALIGN_CENTER, 0, -40); + lv_obj_set_style_local_text_color(label_sleep_cycles, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); + // Start time if (infiniSleepController.IsEnabled()) { label_start_time = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_fmt(label_start_time, "Began at: %02d:%02d", infiniSleepController.prevSessionData.startTimeHours, infiniSleepController.prevSessionData.startTimeMinutes); - lv_obj_align(label_start_time, label_hr, LV_ALIGN_CENTER, 0, 20); + lv_obj_align(label_start_time, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); lv_obj_set_style_local_text_color(label_start_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); } @@ -238,7 +253,7 @@ void Sleep::DrawInfoScreen() { } else { lv_label_set_text_static(label_alarm_time, "Alarm is not set."); } - lv_obj_align(label_alarm_time, label_hr, LV_ALIGN_CENTER, 0, 40); + lv_obj_align(label_alarm_time, lv_scr_act(), LV_ALIGN_CENTER, 0, 20); lv_obj_set_style_local_text_color(label_alarm_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, @@ -248,43 +263,21 @@ void Sleep::DrawInfoScreen() { label_gradual_wake = lv_label_create(lv_scr_act(), nullptr); if (infiniSleepController.GetInfiniSleepSettings().graddualWake && infiniSleepController.gradualWakeStep >= 0) { - lv_label_set_text_fmt(label_gradual_wake, "Gradual Wake: %d/9", infiniSleepController.gradualWakeStep); + lv_label_set_text_fmt(label_gradual_wake, "Gradual Wake: ON"); } else { lv_label_set_text_static(label_gradual_wake, "Gradual Wake: OFF"); } - lv_obj_align(label_gradual_wake, label_hr, LV_ALIGN_CENTER, 0, 60); + lv_obj_align(label_gradual_wake, lv_scr_act(), LV_ALIGN_CENTER, 0, 40); lv_obj_set_style_local_text_color(label_gradual_wake, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); - // Sleep Cycles Info - label_sleep_cycles = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_fmt(label_sleep_cycles, - "Sleep Cycles: %d.%02d", - infiniSleepController.GetSleepCycles() / 100, - infiniSleepController.GetSleepCycles() % 100); - lv_obj_align(label_sleep_cycles, label_hr, LV_ALIGN_CENTER, 0, 80); - lv_obj_set_style_local_text_color(label_sleep_cycles, - LV_LABEL_PART_MAIN, - LV_STATE_DEFAULT, - infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); - - // Total sleep time - label_total_sleep = lv_label_create(lv_scr_act(), nullptr); - - uint16_t totalMinutes = infiniSleepController.GetTotalSleep(); - - lv_label_set_text_fmt(label_total_sleep, "Total Sleep: %dh%dm", totalMinutes / 60, totalMinutes % 60); - lv_obj_align(label_total_sleep, label_hr, LV_ALIGN_CENTER, 0, 100); - lv_obj_set_style_local_text_color(label_total_sleep, - LV_LABEL_PART_MAIN, - LV_STATE_DEFAULT, - infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); - + // Start/Stop button trackerToggleBtn = lv_btn_create(lv_scr_act(), nullptr); trackerToggleBtn->user_data = this; - lv_obj_align(trackerToggleBtn, lv_scr_act(), LV_ALIGN_CENTER, 0, 100); + lv_obj_set_height(trackerToggleBtn, 50); + lv_obj_align(trackerToggleBtn, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0); // Tracker toggle button trackerToggleLabel = lv_label_create(trackerToggleBtn, nullptr); @@ -335,12 +328,12 @@ void Sleep::DrawSettingsScreen() { } lv_obj_t* lblCycles = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_static(lblCycles, "Cycles <----> Mins"); + lv_label_set_text_static(lblCycles, "Desired\nCycles"); lv_obj_align(lblCycles, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); lv_obj_t* btnCycles = lv_btn_create(lv_scr_act(), nullptr); lv_obj_set_size(btnCycles, 100, 50); - lv_obj_align(btnCycles, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset + 30); + lv_obj_align(btnCycles, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 130, y_offset); btnCycles->user_data = this; lv_obj_set_event_cb(btnCycles, [](lv_obj_t* obj, lv_event_t e) { if (e == LV_EVENT_CLICKED) { @@ -357,43 +350,8 @@ void Sleep::DrawSettingsScreen() { lv_label_set_text_fmt(lblCycleValue, "%d", infiniSleepController.infiniSleepSettings.desiredCycles); lv_obj_align(lblCycleValue, nullptr, LV_ALIGN_CENTER, 0, 0); - lv_obj_t* btnCycleDuration = lv_btn_create(lv_scr_act(), nullptr); - lv_obj_set_size(btnCycleDuration, 100, 50); - lv_obj_align(btnCycleDuration, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 120, y_offset + 30); - btnCycleDuration->user_data = this; - lv_obj_set_event_cb(btnCycleDuration, [](lv_obj_t* obj, lv_event_t e) { - if (e == LV_EVENT_CLICKED) { - auto* screen = static_cast(obj->user_data); - int value = screen->infiniSleepController.infiniSleepSettings.sleepCycleDuration; - switch (value) { - case 80: - value = 85; - break; - case 85: - value = 90; - break; - case 90: - value = 95; - break; - case 95: - value = 100; - break; - case 100: - value = 80; - break; - default: - value = 80; - break; - } - screen->infiniSleepController.infiniSleepSettings.sleepCycleDuration = value; - screen->infiniSleepController.SetSettingsChanged(); - lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d", value); - } - }); - - lv_obj_t* lblCycleDurationValue = lv_label_create(btnCycleDuration, nullptr); - lv_label_set_text_fmt(lblCycleDurationValue, "%d", infiniSleepController.infiniSleepSettings.sleepCycleDuration); - lv_obj_align(lblCycleDurationValue, nullptr, LV_ALIGN_CENTER, 0, 0); + infiniSleepController.infiniSleepSettings.sleepCycleDuration = 90; + infiniSleepController.SetSettingsChanged(); y_offset += 70; // Adjust the offset for the next UI element } @@ -483,23 +441,25 @@ bool Sleep::OnTouchEvent(Pinetime::Applications::TouchEvents event) { } lastDisplayState = displayState; - NRF_LOG_INFO("Last Display State: %d", static_cast(lastDisplayState)); + NRF_LOG_INFO("Last Display State: %d", static_cast(lastDisplayState)); // The cases for swiping to change page on app switch (event) { - case TouchEvents::SwipeRight: - if (displayState != SleepDisplayState::Alarm) { + case TouchEvents::SwipeDown: + if (static_cast(displayState) != 0) { displayState = static_cast(static_cast(displayState) - 1); UpdateDisplay(); + } else { + return false; } - NRF_LOG_INFO("SwipeLeft: %d", static_cast(displayState)); + NRF_LOG_INFO("SwipeDown: %d", static_cast(displayState)); return true; - case TouchEvents::SwipeLeft: - if (displayState != SleepDisplayState::Settings) { - displayState = static_cast(static_cast(displayState) + 1); + case TouchEvents::SwipeUp: + if (static_cast(displayState) != 2) { + displayState = static_cast(static_cast(displayState) + 1); UpdateDisplay(); } - NRF_LOG_INFO("SwipeRight: %d", static_cast(displayState)); + NRF_LOG_INFO("SwipeUp: %d", static_cast(displayState)); return true; default: break; diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 4e33cf5e89..f482e64018 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -29,7 +29,7 @@ namespace Pinetime { void StopAlerting(bool setSwitch = true); void SnoozeWakeAlarm(); void UpdateDisplay(); - enum class SleepDisplayState { Alarm, Info, Settings }; + enum class SleepDisplayState { Info, Alarm, Settings }; SleepDisplayState displayState = SleepDisplayState::Info; SleepDisplayState lastDisplayState = SleepDisplayState::Info; From c36a0e6bf67278f56d84eab03a96709fc4499063 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 29 Nov 2024 21:40:39 -0600 Subject: [PATCH 082/123] Added stop button to alerting UI, goal is to more it easier to understand what to do to stop the alarm. --- src/displayapp/screens/Sleep.cpp | 68 +++++++++++++++++++++++--------- src/displayapp/screens/Sleep.h | 3 +- 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index a5330f3e20..237afc2967 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -149,14 +149,24 @@ void Sleep::DrawAlarmScreen() { lv_label_set_text_static(colonLabel, ":"); lv_obj_align(colonLabel, lv_scr_act(), LV_ALIGN_CENTER, 0, -29); + btnSnooze = lv_btn_create(lv_scr_act(), nullptr); + btnSnooze->user_data = this; + lv_obj_set_event_cb(btnSnooze, btnEventHandler); + lv_obj_set_size(btnSnooze, 115, 50); + lv_obj_align(btnSnooze, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + lv_obj_set_style_local_bg_color(btnSnooze, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); + txtSnooze = lv_label_create(btnSnooze, nullptr); + lv_label_set_text_static(txtSnooze, "ZzZz"); + lv_obj_set_hidden(btnSnooze, true); + btnStop = lv_btn_create(lv_scr_act(), nullptr); btnStop->user_data = this; lv_obj_set_event_cb(btnStop, btnEventHandler); lv_obj_set_size(btnStop, 115, 50); lv_obj_align(btnStop, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); - lv_obj_set_style_local_bg_color(btnStop, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); + lv_obj_set_style_local_bg_color(btnStop, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); txtStop = lv_label_create(btnStop, nullptr); - lv_label_set_text_static(txtStop, "ZzZz"); + lv_label_set_text_fmt(txtStop, "Stop: %d", infiniSleepController.pushesLeftToStopWakeAlarm); lv_obj_set_hidden(btnStop, true); static constexpr lv_color_t bgColor = Colors::bgAlt; @@ -358,11 +368,15 @@ void Sleep::DrawSettingsScreen() { void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { if (event == LV_EVENT_CLICKED) { - if (obj == btnStop) { + if (obj == btnSnooze) { StopAlerting(); SnoozeWakeAlarm(); return; } + if (obj == btnStop) { + StopAlarmPush(); + return; + } if (obj == btnMessage) { HideAlarmInfo(); return; @@ -408,28 +422,35 @@ bool Sleep::OnButtonPushed() { return true; } if (infiniSleepController.IsAlerting()) { - if (infiniSleepController.pushesLeftToStopWakeAlarm > 1) { - lv_task_reset(taskPressesToStopAlarmTimeout); - infiniSleepController.pushesLeftToStopWakeAlarm--; + if (StopAlarmPush()) { return true; - } else { - if (infiniSleepController.isSnoozing) { - infiniSleepController.RestorePreSnoozeTime(); - } - infiniSleepController.isSnoozing = false; - StopAlerting(); - if (infiniSleepController.IsTrackerEnabled()) { - displayState = SleepDisplayState::Info; - UpdateDisplay(); - OnButtonEvent(trackerToggleBtn, LV_EVENT_CLICKED); - return true; - } + } + } + return false; +} + +bool Sleep::StopAlarmPush() { + if (infiniSleepController.pushesLeftToStopWakeAlarm > 1) { + lv_task_reset(taskPressesToStopAlarmTimeout); + infiniSleepController.pushesLeftToStopWakeAlarm--; + UpdateDisplay(); + return true; + } else { + if (infiniSleepController.isSnoozing) { + infiniSleepController.RestorePreSnoozeTime(); + } + infiniSleepController.isSnoozing = false; + StopAlerting(); + if (infiniSleepController.IsTrackerEnabled()) { displayState = SleepDisplayState::Info; UpdateDisplay(); + OnButtonEvent(trackerToggleBtn, LV_EVENT_CLICKED); return true; } + displayState = SleepDisplayState::Info; + UpdateDisplay(); + return true; } - return false; } bool Sleep::OnTouchEvent(Pinetime::Applications::TouchEvents event) { @@ -511,7 +532,10 @@ void Sleep::UpdateWakeAlarmTime() { void Sleep::SetAlerting() { lv_obj_set_hidden(enableSwitch, true); + lv_obj_set_hidden(btnSnooze, false); lv_obj_set_hidden(btnStop, false); + lv_obj_set_hidden(btnSuggestedAlarm, true); + lv_obj_set_hidden(txtSuggestedAlarm, true); NRF_LOG_INFO("Alarm is alerting"); taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, 120 * 1000, LV_TASK_PRIO_MID, this); motorController.StartAlarm(); @@ -521,7 +545,10 @@ void Sleep::SetAlerting() { void Sleep::RedrawSetAlerting() { lv_obj_set_hidden(enableSwitch, true); + lv_obj_set_hidden(btnSnooze, false); lv_obj_set_hidden(btnStop, false); + lv_obj_set_hidden(btnSuggestedAlarm, true); + lv_obj_set_hidden(txtSuggestedAlarm, true); wakeLock.Lock(); } @@ -533,7 +560,10 @@ void Sleep::StopAlerting(bool setSwitch) { } wakeLock.Release(); lv_obj_set_hidden(enableSwitch, false); + lv_obj_set_hidden(btnSnooze, true); lv_obj_set_hidden(btnStop, true); + lv_obj_set_hidden(btnSuggestedAlarm, false); + lv_obj_set_hidden(txtSuggestedAlarm, false); alreadyAlerting = false; } diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index f482e64018..003bdceb71 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -40,7 +40,7 @@ namespace Pinetime { Controllers::MotorController& motorController; Controllers::Settings::ClockType clockType; - lv_obj_t *btnStop, *txtStop, /**btnRecur, *txtRecur,*/ *btnInfo, *enableSwitch; + lv_obj_t *btnStop, *btnSnooze, *txtStop, *txtSnooze, /**btnRecur, *txtRecur,*/ *btnInfo, *enableSwitch; lv_obj_t *trackerToggleBtn, *trackerToggleLabel; lv_obj_t* lblampm = nullptr; lv_obj_t* txtMessage = nullptr; @@ -64,6 +64,7 @@ namespace Pinetime { void DrawAlarmScreen(); void DrawInfoScreen(); void DrawSettingsScreen(); + bool StopAlarmPush(); bool alreadyAlerting = false; From aa875bbeb537227628d7221b5a625b064cb92df0 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 29 Nov 2024 23:27:35 -0600 Subject: [PATCH 083/123] Forgot to hide the auto icon --- src/displayapp/screens/Sleep.cpp | 11 +++++++---- src/displayapp/screens/Sleep.h | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 237afc2967..946a85f318 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -184,10 +184,10 @@ void Sleep::DrawAlarmScreen() { lv_label_set_text_static(txtSuggestedAlarm, "Auto"); - 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_WHITE); - lv_obj_align(icon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -50, -10); - lv_label_set_text_static(icon, Symbols::sun); + iconSuggestedAlarm = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(iconSuggestedAlarm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_obj_align(iconSuggestedAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -50, -10); + lv_label_set_text_static(iconSuggestedAlarm, Symbols::sun); enableSwitch = lv_switch_create(lv_scr_act(), nullptr); @@ -536,6 +536,7 @@ void Sleep::SetAlerting() { lv_obj_set_hidden(btnStop, false); lv_obj_set_hidden(btnSuggestedAlarm, true); lv_obj_set_hidden(txtSuggestedAlarm, true); + lv_obj_set_hidden(iconSuggestedAlarm, true); NRF_LOG_INFO("Alarm is alerting"); taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, 120 * 1000, LV_TASK_PRIO_MID, this); motorController.StartAlarm(); @@ -549,6 +550,7 @@ void Sleep::RedrawSetAlerting() { lv_obj_set_hidden(btnStop, false); lv_obj_set_hidden(btnSuggestedAlarm, true); lv_obj_set_hidden(txtSuggestedAlarm, true); + lv_obj_set_hidden(iconSuggestedAlarm, true); wakeLock.Lock(); } @@ -564,6 +566,7 @@ void Sleep::StopAlerting(bool setSwitch) { lv_obj_set_hidden(btnStop, true); lv_obj_set_hidden(btnSuggestedAlarm, false); lv_obj_set_hidden(txtSuggestedAlarm, false); + lv_obj_set_hidden(iconSuggestedAlarm, false); alreadyAlerting = false; } diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 003bdceb71..06dd2f5462 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -74,7 +74,7 @@ namespace Pinetime { lv_obj_t* label_gradual_wake; lv_obj_t* label_total_sleep; lv_obj_t* label_sleep_cycles; - lv_obj_t *btnSuggestedAlarm, *txtSuggestedAlarm; + lv_obj_t *btnSuggestedAlarm, *txtSuggestedAlarm, *iconSuggestedAlarm; }; } From 60679a333e82becb8e31d178882dd73aa923f794 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 29 Nov 2024 23:29:42 -0600 Subject: [PATCH 084/123] Added "Ramping Up" of Wake Alarm Buzz Made new function in motor controller for this --- src/components/motor/MotorController.cpp | 32 ++++++++++++++++++++++++ src/components/motor/MotorController.h | 8 ++++++ src/displayapp/screens/Sleep.cpp | 4 +-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index 9d02d0a8cb..8122cab0fe 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -39,6 +39,7 @@ void MotorController::Init() { shortVib = xTimerCreate("shortVib", 1, pdFALSE, nullptr, StopMotor); longVib = xTimerCreate("longVib", pdMS_TO_TICKS(1000), pdTRUE, this, Ring); alarmVib = xTimerCreate("alarmVib", pdMS_TO_TICKS(500), pdTRUE, this, AlarmRing); + wakeAlarmVib = xTimerCreate("wakeAlarmVib", pdMS_TO_TICKS(1000), pdTRUE, this, WakeAlarmRing); } void MotorController::SetMotorStrength(uint8_t strength) { @@ -48,6 +49,7 @@ void MotorController::SetMotorStrength(uint8_t strength) { // Map the strength to the PWM value (0-100 -> 0-top_value) pwmValue = (strength * 255) / 100; + // pwmValue = strength; } void MotorController::Ring(TimerHandle_t xTimer) { @@ -63,6 +65,9 @@ void MotorController::AlarmRing(TimerHandle_t xTimer) { void MotorController::RunForDuration(uint16_t motorDuration) { if (motorDuration > 0 && xTimerChangePeriod(shortVib, pdMS_TO_TICKS(motorDuration), 0) == pdPASS && xTimerStart(shortVib, 0) == pdPASS) { + if (pwmValue == 0) { + SetMotorStrength(100); + } // nrf_gpio_pin_clear(PinMap::Motor); nrf_pwm_task_trigger(NRF_PWM2, NRF_PWM_TASK_SEQSTART0); // Restart the PWM sequence with the updated value } @@ -94,6 +99,33 @@ void MotorController::StopAlarm() { nrf_gpio_pin_set(PinMap::Motor); } +void MotorController::StartWakeAlarm() { + wakeAlarmStrength = 80; + wakeAlarmDuration = 100; + SetMotorStrength(wakeAlarmStrength); + RunForDuration(wakeAlarmDuration); + xTimerStart(wakeAlarmVib, 0); +} + +void MotorController::WakeAlarmRing(TimerHandle_t xTimer) { + auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); + if (motorController->wakeAlarmStrength > 20) { + motorController->wakeAlarmStrength -= 1; + } + if (motorController->wakeAlarmDuration < 500) { + motorController->wakeAlarmDuration += 6; + } + motorController->SetMotorStrength(motorController->wakeAlarmStrength); + motorController->RunForDuration(motorController->wakeAlarmDuration); +} + +void MotorController::StopWakeAlarm() { + xTimerStop(wakeAlarmVib, 0); + nrf_pwm_task_trigger(NRF_PWM0, NRF_PWM_TASK_STOP); // Stop the PWM sequence + pwmValue = 0; // Reset the PWM value + nrf_gpio_pin_set(PinMap::Motor); +} + void MotorController::StopMotor(TimerHandle_t /*xTimer*/) { nrf_pwm_task_trigger(NRF_PWM2, NRF_PWM_TASK_STOP); // Stop the PWM sequence pwmValue = 0; // Reset the PWM value diff --git a/src/components/motor/MotorController.h b/src/components/motor/MotorController.h index 087074b850..8fca89cfe5 100644 --- a/src/components/motor/MotorController.h +++ b/src/components/motor/MotorController.h @@ -17,13 +17,19 @@ namespace Pinetime { void StopRinging(); void StartAlarm(); void StopAlarm(); + void StartWakeAlarm(); + void StopWakeAlarm(); void GradualWakeBuzz(); void StopGradualWakeBuzz(); void SetMotorStrength(uint8_t strength); + uint8_t wakeAlarmStrength = 80; + uint16_t wakeAlarmDuration = 100; + private: static void Ring(TimerHandle_t xTimer); static void AlarmRing(TimerHandle_t xTimer); + static void WakeAlarmRing(TimerHandle_t xTimer); static void StopMotor(TimerHandle_t xTimer); static void GradualWakeBuzzRing(TimerHandle_t xTimer); static void StopGradualWakeBuzzCallback(TimerHandle_t xTimer); @@ -33,6 +39,8 @@ namespace Pinetime { TimerHandle_t alarmVib; TimerHandle_t gradualWakeBuzzDelay; TimerHandle_t gradualWakeBuzzEnd; + + TimerHandle_t wakeAlarmVib; }; } } diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 946a85f318..5d25c8aa55 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -539,7 +539,7 @@ void Sleep::SetAlerting() { lv_obj_set_hidden(iconSuggestedAlarm, true); NRF_LOG_INFO("Alarm is alerting"); taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, 120 * 1000, LV_TASK_PRIO_MID, this); - motorController.StartAlarm(); + motorController.StartWakeAlarm(); wakeLock.Lock(); alreadyAlerting = true; } @@ -556,7 +556,7 @@ void Sleep::RedrawSetAlerting() { void Sleep::StopAlerting(bool setSwitch) { infiniSleepController.StopAlerting(); - motorController.StopAlarm(); + motorController.StopWakeAlarm(); if (setSwitch) { SetSwitchState(LV_ANIM_OFF); } From d3e6fcf68afb4fb85a7e23be06ab0386b934d03d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:17:40 -0600 Subject: [PATCH 085/123] Changed UI of Alerting Alarm screen and added page inditors with scroll animations. the time on the alerting page is not interactable and I also made the snooze button bigger. Also added check to display time in proper formats --- src/displayapp/screens/Sleep.cpp | 104 +++++++++++++++++++++---------- src/displayapp/screens/Sleep.h | 13 +++- 2 files changed, 81 insertions(+), 36 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 5d25c8aa55..5954019caf 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -66,8 +66,9 @@ static void PressesToStopAlarmTimeoutCallback(lv_task_t* task) { Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, Controllers::Settings::ClockType clockType, System::SystemTask& systemTask, - Controllers::MotorController& motorController) - : infiniSleepController {infiniSleepController}, wakeLock(systemTask), motorController {motorController}, clockType {clockType} { + Controllers::MotorController& motorController, + DisplayApp& displayApp) + : infiniSleepController {infiniSleepController}, wakeLock(systemTask), motorController {motorController}, clockType {clockType}, displayApp {displayApp} { infiniSleepController.SetHeartRateTrackingEnabled(false); infiniSleepController.SetSettingsChanged(); @@ -114,45 +115,60 @@ void Sleep::UpdateDisplay() { switch (displayState) { case SleepDisplayState::Alarm: DrawAlarmScreen(); + pageIndicator2.Create(); break; case SleepDisplayState::Info: DrawInfoScreen(); + pageIndicator1.Create(); break; case SleepDisplayState::Settings: DrawSettingsScreen(); + pageIndicator3.Create(); break; } } void Sleep::DrawAlarmScreen() { - hourCounter.Create(); - lv_obj_align(hourCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); - if (clockType == Controllers::Settings::ClockType::H12) { - hourCounter.EnableTwelveHourMode(); - - lblampm = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_font(lblampm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); - lv_label_set_text_static(lblampm, "AM"); - lv_label_set_align(lblampm, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblampm, lv_scr_act(), LV_ALIGN_CENTER, 0, 30); + if (!infiniSleepController.IsAlerting()) { + hourCounter.Create(); + lv_obj_align(hourCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); + if (clockType == Controllers::Settings::ClockType::H12) { + hourCounter.EnableTwelveHourMode(); + + lblampm = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(lblampm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); + lv_label_set_text_static(lblampm, "AM"); + lv_label_set_align(lblampm, LV_LABEL_ALIGN_CENTER); + lv_obj_align(lblampm, lv_scr_act(), LV_ALIGN_CENTER, 0, 30); + } + hourCounter.SetValue(infiniSleepController.GetWakeAlarm().hours); + hourCounter.SetValueChangedEventCallback(this, ValueChangedHandler); + + minuteCounter.Create(); + lv_obj_align(minuteCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); + minuteCounter.SetValue(infiniSleepController.GetWakeAlarm().minutes); + minuteCounter.SetValueChangedEventCallback(this, ValueChangedHandler); + + lv_obj_t* colonLabel = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); + lv_label_set_text_static(colonLabel, ":"); + lv_obj_align(colonLabel, lv_scr_act(), LV_ALIGN_CENTER, 0, -29); + } else { + lv_obj_t* lblTime = lv_label_create(lv_scr_act(), nullptr); + if (clockType == Controllers::Settings::ClockType::H24) { + lv_label_set_text_fmt(lblTime, "%02d:%02d", infiniSleepController.GetCurrentHour(), infiniSleepController.GetCurrentMinute()); + } else { + lv_label_set_text_fmt(lblTime, "%02d:%02d", infiniSleepController.GetCurrentHour() % 12, infiniSleepController.GetCurrentMinute()); + } + lv_obj_align(lblTime, lv_scr_act(), LV_ALIGN_CENTER, -90, -50); + lv_obj_set_style_local_text_color(lblTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_obj_set_style_local_text_font(lblTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_extrabold_compressed); } - hourCounter.SetValue(infiniSleepController.GetWakeAlarm().hours); - hourCounter.SetValueChangedEventCallback(this, ValueChangedHandler); - - minuteCounter.Create(); - lv_obj_align(minuteCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); - minuteCounter.SetValue(infiniSleepController.GetWakeAlarm().minutes); - minuteCounter.SetValueChangedEventCallback(this, ValueChangedHandler); - - lv_obj_t* colonLabel = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_font(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); - lv_label_set_text_static(colonLabel, ":"); - lv_obj_align(colonLabel, lv_scr_act(), LV_ALIGN_CENTER, 0, -29); btnSnooze = lv_btn_create(lv_scr_act(), nullptr); btnSnooze->user_data = this; lv_obj_set_event_cb(btnSnooze, btnEventHandler); - lv_obj_set_size(btnSnooze, 115, 50); + lv_obj_set_size(btnSnooze, 115, 100); lv_obj_align(btnSnooze, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); lv_obj_set_style_local_bg_color(btnSnooze, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); txtSnooze = lv_label_create(btnSnooze, nullptr); @@ -214,7 +230,11 @@ void Sleep::DrawAlarmScreen() { void Sleep::DrawInfoScreen() { lv_obj_t* lblTime = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_fmt(lblTime, "%02d:%02d", infiniSleepController.GetCurrentHour(), infiniSleepController.GetCurrentMinute()); + if (clockType == Controllers::Settings::ClockType::H24) { + lv_label_set_text_fmt(lblTime, "%02d:%02d", infiniSleepController.GetCurrentHour(), infiniSleepController.GetCurrentMinute()); + } else { + lv_label_set_text_fmt(lblTime, "%02d:%02d", infiniSleepController.GetCurrentHour() % 12, infiniSleepController.GetCurrentMinute()); + } lv_obj_align(lblTime, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 5); lv_obj_set_style_local_text_color(lblTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); @@ -245,10 +265,17 @@ void Sleep::DrawInfoScreen() { // Start time if (infiniSleepController.IsEnabled()) { label_start_time = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_fmt(label_start_time, - "Began at: %02d:%02d", - infiniSleepController.prevSessionData.startTimeHours, - infiniSleepController.prevSessionData.startTimeMinutes); + if (clockType == Controllers::Settings::ClockType::H24) { + lv_label_set_text_fmt(label_start_time, + "Began at: %02d:%02d", + infiniSleepController.prevSessionData.startTimeHours, + infiniSleepController.prevSessionData.startTimeMinutes); + } else { + lv_label_set_text_fmt(label_start_time, + "Began at: %02d:%02d", + infiniSleepController.prevSessionData.startTimeHours % 12, + infiniSleepController.prevSessionData.startTimeMinutes); + } lv_obj_align(label_start_time, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); lv_obj_set_style_local_text_color(label_start_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); } @@ -256,10 +283,17 @@ void Sleep::DrawInfoScreen() { // The alarm info label_alarm_time = lv_label_create(lv_scr_act(), nullptr); if (infiniSleepController.GetWakeAlarm().isEnabled) { - lv_label_set_text_fmt(label_alarm_time, - "Alarm at: %02d:%02d", - infiniSleepController.GetWakeAlarm().hours, - infiniSleepController.GetWakeAlarm().minutes); + if (clockType == Controllers::Settings::ClockType::H24) { + lv_label_set_text_fmt(label_alarm_time, + "Alarm at: %02d:%02d", + infiniSleepController.GetWakeAlarm().hours, + infiniSleepController.GetWakeAlarm().minutes); + } else { + lv_label_set_text_fmt(label_alarm_time, + "Alarm at: %02d:%02d", + (infiniSleepController.GetWakeAlarm().hours % 12 == 0) ? 12 : infiniSleepController.GetWakeAlarm().hours % 12, + infiniSleepController.GetWakeAlarm().minutes); + } } else { lv_label_set_text_static(label_alarm_time, "Alarm is not set."); } @@ -468,6 +502,7 @@ bool Sleep::OnTouchEvent(Pinetime::Applications::TouchEvents event) { switch (event) { case TouchEvents::SwipeDown: if (static_cast(displayState) != 0) { + displayApp.SetFullRefresh(Pinetime::Applications::DisplayApp::FullRefreshDirections::Down); displayState = static_cast(static_cast(displayState) - 1); UpdateDisplay(); } else { @@ -477,6 +512,7 @@ bool Sleep::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return true; case TouchEvents::SwipeUp: if (static_cast(displayState) != 2) { + displayApp.SetFullRefresh(Pinetime::Applications::DisplayApp::FullRefreshDirections::Up); displayState = static_cast(static_cast(displayState) + 1); UpdateDisplay(); } diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 06dd2f5462..1b6bb4b56b 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -4,9 +4,11 @@ #include "components/settings/Settings.h" #include "displayapp/screens/Screen.h" #include "displayapp/widgets/Counter.h" +#include "displayapp/widgets/PageIndicator.h" #include "displayapp/Controllers.h" #include "systemtask/SystemTask.h" #include "systemtask/WakeLock.h" +#include "displayapp/DisplayApp.h" #include "Symbols.h" namespace Pinetime { @@ -17,7 +19,8 @@ namespace Pinetime { explicit Sleep(Controllers::InfiniSleepController& infiniSleepController, Controllers::Settings::ClockType clockType, System::SystemTask& systemTask, - Controllers::MotorController& motorController); + Controllers::MotorController& motorController, + DisplayApp& displayApp); ~Sleep() override; void Refresh() override; void SetAlerting(); @@ -39,6 +42,7 @@ namespace Pinetime { System::WakeLock wakeLock; Controllers::MotorController& motorController; Controllers::Settings::ClockType clockType; + DisplayApp& displayApp; lv_obj_t *btnStop, *btnSnooze, *txtStop, *txtSnooze, /**btnRecur, *txtRecur,*/ *btnInfo, *enableSwitch; lv_obj_t *trackerToggleBtn, *trackerToggleLabel; @@ -75,6 +79,10 @@ namespace Pinetime { lv_obj_t* label_total_sleep; lv_obj_t* label_sleep_cycles; lv_obj_t *btnSuggestedAlarm, *txtSuggestedAlarm, *iconSuggestedAlarm; + + Widgets::PageIndicator pageIndicator1 = Widgets::PageIndicator(0,3); + Widgets::PageIndicator pageIndicator2 = Widgets::PageIndicator(1,3); + Widgets::PageIndicator pageIndicator3 = Widgets::PageIndicator(2,3); }; } @@ -87,7 +95,8 @@ namespace Pinetime { return new Screens::Sleep(controllers.infiniSleepController, controllers.settingsController.GetClockType(), *controllers.systemTask, - controllers.motorController); + controllers.motorController, + *controllers.displayApp); } }; } From 8ab64661bf90f083dc1d819160423483e5b4c1db Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:22:16 -0600 Subject: [PATCH 086/123] Changed motor strength to use 0-255 --- src/components/motor/MotorController.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index 8122cab0fe..8ec5cf86d1 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -44,12 +44,12 @@ void MotorController::Init() { void MotorController::SetMotorStrength(uint8_t strength) { // Ensure strength is within bounds (0-100) - if (strength > 100) - strength = 100; + // if (strength > 100) + // strength = 100; // Map the strength to the PWM value (0-100 -> 0-top_value) - pwmValue = (strength * 255) / 100; - // pwmValue = strength; + // pwmValue = (strength * 255) / 100; + pwmValue = strength; } void MotorController::Ring(TimerHandle_t xTimer) { @@ -66,7 +66,7 @@ void MotorController::AlarmRing(TimerHandle_t xTimer) { void MotorController::RunForDuration(uint16_t motorDuration) { if (motorDuration > 0 && xTimerChangePeriod(shortVib, pdMS_TO_TICKS(motorDuration), 0) == pdPASS && xTimerStart(shortVib, 0) == pdPASS) { if (pwmValue == 0) { - SetMotorStrength(100); + SetMotorStrength(255); } // nrf_gpio_pin_clear(PinMap::Motor); nrf_pwm_task_trigger(NRF_PWM2, NRF_PWM_TASK_SEQSTART0); // Restart the PWM sequence with the updated value @@ -109,7 +109,7 @@ void MotorController::StartWakeAlarm() { void MotorController::WakeAlarmRing(TimerHandle_t xTimer) { auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); - if (motorController->wakeAlarmStrength > 20) { + if (motorController->wakeAlarmStrength > 40) { motorController->wakeAlarmStrength -= 1; } if (motorController->wakeAlarmDuration < 500) { From 2f77d78c012b92f9c8798c5923d336dccb019e71 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:24:12 -0600 Subject: [PATCH 087/123] Ran formatter --- .../infinisleep/InfiniSleepController.cpp | 6 +++--- .../infinisleep/InfiniSleepController.h | 2 +- src/displayapp/screens/Sleep.cpp | 21 ++++++++++--------- src/displayapp/screens/Sleep.h | 6 +++--- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index dffbb0bc6e..dea1ae75b2 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -230,9 +230,9 @@ void InfiniSleepController::UpdateBPM() { NRF_LOG_INFO("BPM: %d at %02d:%02d:%02d", rollingBpm, hours, minutes, seconds); // Write data to CSV - //const int motion = 0; // Placeholder for motion data - //std::tuple data[1] = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; - //WriteDataCSV(TRACKER_DATA_FILE_NAME, data, 1); + // const int motion = 0; // Placeholder for motion data + // std::tuple data[1] = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; + // WriteDataCSV(TRACKER_DATA_FILE_NAME, data, 1); } void InfiniSleepController::WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const { diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index be80a270d5..02ab98ebdb 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -207,7 +207,7 @@ namespace Pinetime { SavePrevSessionData(); DisableTracker(); } else { - //ClearDataCSV(TRACKER_DATA_FILE_NAME); + // ClearDataCSV(TRACKER_DATA_FILE_NAME); prevSessionData.startTimeHours = GetCurrentHour(); prevSessionData.startTimeMinutes = GetCurrentMinute(); EnableTracker(); diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 5954019caf..cd29e90b6b 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -68,7 +68,11 @@ Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, System::SystemTask& systemTask, Controllers::MotorController& motorController, DisplayApp& displayApp) - : infiniSleepController {infiniSleepController}, wakeLock(systemTask), motorController {motorController}, clockType {clockType}, displayApp {displayApp} { + : infiniSleepController {infiniSleepController}, + wakeLock(systemTask), + motorController {motorController}, + clockType {clockType}, + displayApp {displayApp} { infiniSleepController.SetHeartRateTrackingEnabled(false); infiniSleepController.SetSettingsChanged(); @@ -192,20 +196,18 @@ void Sleep::DrawAlarmScreen() { lv_obj_set_event_cb(btnSuggestedAlarm, btnEventHandler); lv_obj_set_size(btnSuggestedAlarm, 115, 50); lv_obj_align(btnSuggestedAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); - //txtSuggestedAlarm = lv_label_create(btnSuggestedAlarm, nullptr); - //lv_label_set_text_static(txtSuggestedAlarm, "Use Sugg.\nAlarmTime"); + // txtSuggestedAlarm = lv_label_create(btnSuggestedAlarm, nullptr); + // lv_label_set_text_static(txtSuggestedAlarm, "Use Sugg.\nAlarmTime"); txtSuggestedAlarm = lv_label_create(lv_scr_act(), nullptr); lv_obj_align(txtSuggestedAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -15, -10); lv_label_set_text_static(txtSuggestedAlarm, "Auto"); - iconSuggestedAlarm = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(iconSuggestedAlarm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); lv_obj_align(iconSuggestedAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -50, -10); lv_label_set_text_static(iconSuggestedAlarm, Symbols::sun); - enableSwitch = lv_switch_create(lv_scr_act(), nullptr); enableSwitch->user_data = this; lv_obj_set_event_cb(enableSwitch, btnEventHandler); @@ -290,9 +292,9 @@ void Sleep::DrawInfoScreen() { infiniSleepController.GetWakeAlarm().minutes); } else { lv_label_set_text_fmt(label_alarm_time, - "Alarm at: %02d:%02d", - (infiniSleepController.GetWakeAlarm().hours % 12 == 0) ? 12 : infiniSleepController.GetWakeAlarm().hours % 12, - infiniSleepController.GetWakeAlarm().minutes); + "Alarm at: %02d:%02d", + (infiniSleepController.GetWakeAlarm().hours % 12 == 0) ? 12 : infiniSleepController.GetWakeAlarm().hours % 12, + infiniSleepController.GetWakeAlarm().minutes); } } else { lv_label_set_text_static(label_alarm_time, "Alarm is not set."); @@ -305,8 +307,7 @@ void Sleep::DrawInfoScreen() { // Gradual Wake info label_gradual_wake = lv_label_create(lv_scr_act(), nullptr); - if (infiniSleepController.GetInfiniSleepSettings().graddualWake && - infiniSleepController.gradualWakeStep >= 0) { + if (infiniSleepController.GetInfiniSleepSettings().graddualWake && infiniSleepController.gradualWakeStep >= 0) { lv_label_set_text_fmt(label_gradual_wake, "Gradual Wake: ON"); } else { lv_label_set_text_static(label_gradual_wake, "Gradual Wake: OFF"); diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 1b6bb4b56b..006c8f3573 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -80,9 +80,9 @@ namespace Pinetime { lv_obj_t* label_sleep_cycles; lv_obj_t *btnSuggestedAlarm, *txtSuggestedAlarm, *iconSuggestedAlarm; - Widgets::PageIndicator pageIndicator1 = Widgets::PageIndicator(0,3); - Widgets::PageIndicator pageIndicator2 = Widgets::PageIndicator(1,3); - Widgets::PageIndicator pageIndicator3 = Widgets::PageIndicator(2,3); + Widgets::PageIndicator pageIndicator1 = Widgets::PageIndicator(0, 3); + Widgets::PageIndicator pageIndicator2 = Widgets::PageIndicator(1, 3); + Widgets::PageIndicator pageIndicator3 = Widgets::PageIndicator(2, 3); }; } From 4f1a072653bbea1b8cf2323a23e98eb023c12a59 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:35:44 -0600 Subject: [PATCH 088/123] more formatting --- src/displayapp/DisplayApp.cpp | 6 +++--- src/systemtask/SystemTask.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index f86d5f459d..0dc84b98a3 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -406,11 +406,11 @@ void DisplayApp::Refresh() { // auto* sleep = static_cast(currentScreen.get()); // sleep->SetGradualWakeAlerting(); } else { - //LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); + // LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); } - //motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1 + infiniSleepController.gradualWakeStep]); + // motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1 + infiniSleepController.gradualWakeStep]); motorController.GradualWakeBuzz(); - + infiniSleepController.UpdateGradualWake(); NRF_LOG_INFO("Gradual wake triggered"); diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index d195602150..c7e4685f8c 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -231,7 +231,7 @@ void SystemTask::Work() { displayApp.PushMessage(Pinetime::Applications::Display::Messages::WakeAlarmTriggered); break; case Messages::SetOffGradualWake: - //GoToRunning(); + // GoToRunning(); displayApp.PushMessage(Pinetime::Applications::Display::Messages::GradualWakeTriggered); break; case Messages::BleConnected: From 8393bd6df67c882d0f06f02fb6ab87e8e8f19fe8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:47:12 -0600 Subject: [PATCH 089/123] Fixed bug where snoozing causes crash due to widget not being on screen --- src/displayapp/screens/Sleep.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index cd29e90b6b..4ea1d21f98 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -405,6 +405,7 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { if (event == LV_EVENT_CLICKED) { if (obj == btnSnooze) { StopAlerting(); + UpdateDisplay(); SnoozeWakeAlarm(); return; } From 70b073e7c27371ba7019520abe2b5446ee80f202 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 22:36:31 -0600 Subject: [PATCH 090/123] Fixed PWM controller number typo --- src/components/motor/MotorController.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index 8ec5cf86d1..ad98dca581 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -94,7 +94,7 @@ void MotorController::StartAlarm() { void MotorController::StopAlarm() { xTimerStop(alarmVib, 0); - nrf_pwm_task_trigger(NRF_PWM0, NRF_PWM_TASK_STOP); // Stop the PWM sequence + nrf_pwm_task_trigger(NRF_PWM2, NRF_PWM_TASK_STOP); // Stop the PWM sequence pwmValue = 0; // Reset the PWM value nrf_gpio_pin_set(PinMap::Motor); } @@ -121,7 +121,7 @@ void MotorController::WakeAlarmRing(TimerHandle_t xTimer) { void MotorController::StopWakeAlarm() { xTimerStop(wakeAlarmVib, 0); - nrf_pwm_task_trigger(NRF_PWM0, NRF_PWM_TASK_STOP); // Stop the PWM sequence + nrf_pwm_task_trigger(NRF_PWM2, NRF_PWM_TASK_STOP); // Stop the PWM sequence pwmValue = 0; // Reset the PWM value nrf_gpio_pin_set(PinMap::Motor); } From 9637f761ac1eb02b295f401fd0230d84bba25836 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 22:42:59 -0600 Subject: [PATCH 091/123] Fixed make all error displayapp include wasnt needed --- src/displayapp/screens/Sleep.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 006c8f3573..514fdd57c4 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -8,7 +8,6 @@ #include "displayapp/Controllers.h" #include "systemtask/SystemTask.h" #include "systemtask/WakeLock.h" -#include "displayapp/DisplayApp.h" #include "Symbols.h" namespace Pinetime { From edb1f077f7ed034845a61725fd38895a3ccd7288 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 22:52:54 -0600 Subject: [PATCH 092/123] Fixed autosnooze crash --- src/displayapp/screens/Sleep.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 4ea1d21f98..5a39dd1809 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -54,6 +54,7 @@ static void SnoozeAlarmTaskCallback(lv_task_t* task) { auto* screen = static_cast(task->user_data); lv_task_set_prio(task, LV_TASK_PRIO_OFF); screen->StopAlerting(false); + screen->UpdateDisplay(); screen->SnoozeWakeAlarm(); } From c41070544ec2b1981aec7166b45f82a469487f5a Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 1 Dec 2024 15:31:38 -0600 Subject: [PATCH 093/123] Changed the Alerting UI and removed gradual wake while snooze --- .../infinisleep/InfiniSleepController.cpp | 2 +- src/displayapp/screens/Sleep.cpp | 92 +++++++++++-------- 2 files changed, 56 insertions(+), 38 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index dea1ae75b2..432b09d0f6 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -143,7 +143,7 @@ void InfiniSleepController::ScheduleWakeAlarm() { } // Calculate the period for the gradualWakeTimer - if (infiniSleepSettings.graddualWake && gradualWakeStep > 0) { + if (isSnoozing != true && infiniSleepSettings.graddualWake && gradualWakeStep > 0) { int64_t gradualWakePeriod = ((secondsToWakeAlarm - gradualWakeSteps[-1 + gradualWakeStep])) * (configTICK_RATE_HZ); xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 5a39dd1809..770706204e 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -134,60 +134,72 @@ void Sleep::UpdateDisplay() { } void Sleep::DrawAlarmScreen() { - if (!infiniSleepController.IsAlerting()) { - hourCounter.Create(); - lv_obj_align(hourCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); - if (clockType == Controllers::Settings::ClockType::H12) { - hourCounter.EnableTwelveHourMode(); - - lblampm = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_font(lblampm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); - lv_label_set_text_static(lblampm, "AM"); - lv_label_set_align(lblampm, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblampm, lv_scr_act(), LV_ALIGN_CENTER, 0, 30); - } - hourCounter.SetValue(infiniSleepController.GetWakeAlarm().hours); - hourCounter.SetValueChangedEventCallback(this, ValueChangedHandler); - - minuteCounter.Create(); - lv_obj_align(minuteCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); - minuteCounter.SetValue(infiniSleepController.GetWakeAlarm().minutes); - minuteCounter.SetValueChangedEventCallback(this, ValueChangedHandler); - - lv_obj_t* colonLabel = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_font(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); - lv_label_set_text_static(colonLabel, ":"); - lv_obj_align(colonLabel, lv_scr_act(), LV_ALIGN_CENTER, 0, -29); - } else { + hourCounter.Create(); + lv_obj_align(hourCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); + if (clockType == Controllers::Settings::ClockType::H12) { + hourCounter.EnableTwelveHourMode(); + + lblampm = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(lblampm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); + lv_label_set_text_static(lblampm, "AM"); + lv_label_set_align(lblampm, LV_LABEL_ALIGN_CENTER); + lv_obj_align(lblampm, lv_scr_act(), LV_ALIGN_CENTER, 0, 30); + } + hourCounter.SetValue(infiniSleepController.GetWakeAlarm().hours); + hourCounter.SetValueChangedEventCallback(this, ValueChangedHandler); + + minuteCounter.Create(); + lv_obj_align(minuteCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); + minuteCounter.SetValue(infiniSleepController.GetWakeAlarm().minutes); + minuteCounter.SetValueChangedEventCallback(this, ValueChangedHandler); + + lv_obj_t* colonLabel = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); + lv_label_set_text_static(colonLabel, ":"); + lv_obj_align(colonLabel, lv_scr_act(), LV_ALIGN_CENTER, 0, -29); + + if (infiniSleepController.IsAlerting()) { + lv_obj_set_hidden(hourCounter.GetObject(), true); + lv_obj_set_hidden(minuteCounter.GetObject(), true); + lv_obj_set_hidden(colonLabel, true); + lv_obj_t* lblTime = lv_label_create(lv_scr_act(), nullptr); if (clockType == Controllers::Settings::ClockType::H24) { lv_label_set_text_fmt(lblTime, "%02d:%02d", infiniSleepController.GetCurrentHour(), infiniSleepController.GetCurrentMinute()); } else { - lv_label_set_text_fmt(lblTime, "%02d:%02d", infiniSleepController.GetCurrentHour() % 12, infiniSleepController.GetCurrentMinute()); + lv_label_set_text_fmt(lblTime, "%02d:%02d", (infiniSleepController.GetCurrentHour() % 12 == 0) ? 12 : infiniSleepController.GetCurrentHour() % 12, infiniSleepController.GetCurrentMinute()); } - lv_obj_align(lblTime, lv_scr_act(), LV_ALIGN_CENTER, -90, -50); + lv_obj_align(lblTime, lv_scr_act(), LV_ALIGN_CENTER, -87, -100); lv_obj_set_style_local_text_color(lblTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); - lv_obj_set_style_local_text_font(lblTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_extrabold_compressed); + lv_label_set_align(lblTime, LV_LABEL_ALIGN_CENTER); + lv_obj_set_style_local_text_font(lblTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); + + lv_obj_t* lblWaketxt = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(lblWaketxt, "Wake Up!"); + lv_obj_align(lblWaketxt, lv_scr_act(), LV_ALIGN_CENTER, 0, -22); + lv_label_set_align(lblWaketxt, LV_LABEL_ALIGN_CENTER); + lv_obj_set_style_local_text_font(lblWaketxt, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); + lv_obj_set_style_local_text_color(lblWaketxt, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); } btnSnooze = lv_btn_create(lv_scr_act(), nullptr); btnSnooze->user_data = this; lv_obj_set_event_cb(btnSnooze, btnEventHandler); - lv_obj_set_size(btnSnooze, 115, 100); - lv_obj_align(btnSnooze, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + lv_obj_set_size(btnSnooze, 200, 63); + lv_obj_align(btnSnooze, lv_scr_act(), LV_ALIGN_CENTER, 0, 28); lv_obj_set_style_local_bg_color(btnSnooze, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); txtSnooze = lv_label_create(btnSnooze, nullptr); - lv_label_set_text_static(txtSnooze, "ZzZz"); + lv_label_set_text_static(txtSnooze, "Snooze"); lv_obj_set_hidden(btnSnooze, true); btnStop = lv_btn_create(lv_scr_act(), nullptr); btnStop->user_data = this; lv_obj_set_event_cb(btnStop, btnEventHandler); - lv_obj_set_size(btnStop, 115, 50); - lv_obj_align(btnStop, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); + lv_obj_set_size(btnStop, 130, 50); + lv_obj_align(btnStop, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); lv_obj_set_style_local_bg_color(btnStop, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); txtStop = lv_label_create(btnStop, nullptr); - lv_label_set_text_fmt(txtStop, "Stop: %d", infiniSleepController.pushesLeftToStopWakeAlarm); + lv_label_set_text_fmt(txtStop, "Stop: %d/%d", PUSHES_TO_STOP_ALARM - infiniSleepController.pushesLeftToStopWakeAlarm, PUSHES_TO_STOP_ALARM); lv_obj_set_hidden(btnStop, true); static constexpr lv_color_t bgColor = Colors::bgAlt; @@ -234,9 +246,15 @@ void Sleep::DrawAlarmScreen() { void Sleep::DrawInfoScreen() { lv_obj_t* lblTime = lv_label_create(lv_scr_act(), nullptr); if (clockType == Controllers::Settings::ClockType::H24) { - lv_label_set_text_fmt(lblTime, "%02d:%02d", infiniSleepController.GetCurrentHour(), infiniSleepController.GetCurrentMinute()); + lv_label_set_text_fmt(lblTime, + "%02d:%02d", + infiniSleepController.GetCurrentHour(), + infiniSleepController.GetCurrentMinute()); } else { - lv_label_set_text_fmt(lblTime, "%02d:%02d", infiniSleepController.GetCurrentHour() % 12, infiniSleepController.GetCurrentMinute()); + lv_label_set_text_fmt(lblTime, + "%02d:%02d", + (infiniSleepController.GetCurrentHour() % 12 == 0) ? 12 : infiniSleepController.GetCurrentHour() % 12, + infiniSleepController.GetCurrentMinute()); } lv_obj_align(lblTime, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 5); lv_obj_set_style_local_text_color(lblTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); @@ -276,7 +294,7 @@ void Sleep::DrawInfoScreen() { } else { lv_label_set_text_fmt(label_start_time, "Began at: %02d:%02d", - infiniSleepController.prevSessionData.startTimeHours % 12, + (infiniSleepController.prevSessionData.startTimeHours % 12 == 0) ? 12 : infiniSleepController.prevSessionData.startTimeHours % 12, infiniSleepController.prevSessionData.startTimeMinutes); } lv_obj_align(label_start_time, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); From ec69c03da8bfdeb62284b22db6a8ab484a293a6e Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 1 Dec 2024 15:32:02 -0600 Subject: [PATCH 094/123] Formatting --- src/displayapp/screens/Sleep.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 770706204e..274b8d1a44 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -167,7 +167,10 @@ void Sleep::DrawAlarmScreen() { if (clockType == Controllers::Settings::ClockType::H24) { lv_label_set_text_fmt(lblTime, "%02d:%02d", infiniSleepController.GetCurrentHour(), infiniSleepController.GetCurrentMinute()); } else { - lv_label_set_text_fmt(lblTime, "%02d:%02d", (infiniSleepController.GetCurrentHour() % 12 == 0) ? 12 : infiniSleepController.GetCurrentHour() % 12, infiniSleepController.GetCurrentMinute()); + lv_label_set_text_fmt(lblTime, + "%02d:%02d", + (infiniSleepController.GetCurrentHour() % 12 == 0) ? 12 : infiniSleepController.GetCurrentHour() % 12, + infiniSleepController.GetCurrentMinute()); } lv_obj_align(lblTime, lv_scr_act(), LV_ALIGN_CENTER, -87, -100); lv_obj_set_style_local_text_color(lblTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); @@ -199,7 +202,10 @@ void Sleep::DrawAlarmScreen() { lv_obj_align(btnStop, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); lv_obj_set_style_local_bg_color(btnStop, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); txtStop = lv_label_create(btnStop, nullptr); - lv_label_set_text_fmt(txtStop, "Stop: %d/%d", PUSHES_TO_STOP_ALARM - infiniSleepController.pushesLeftToStopWakeAlarm, PUSHES_TO_STOP_ALARM); + lv_label_set_text_fmt(txtStop, + "Stop: %d/%d", + PUSHES_TO_STOP_ALARM - infiniSleepController.pushesLeftToStopWakeAlarm, + PUSHES_TO_STOP_ALARM); lv_obj_set_hidden(btnStop, true); static constexpr lv_color_t bgColor = Colors::bgAlt; @@ -246,10 +252,7 @@ void Sleep::DrawAlarmScreen() { void Sleep::DrawInfoScreen() { lv_obj_t* lblTime = lv_label_create(lv_scr_act(), nullptr); if (clockType == Controllers::Settings::ClockType::H24) { - lv_label_set_text_fmt(lblTime, - "%02d:%02d", - infiniSleepController.GetCurrentHour(), - infiniSleepController.GetCurrentMinute()); + lv_label_set_text_fmt(lblTime, "%02d:%02d", infiniSleepController.GetCurrentHour(), infiniSleepController.GetCurrentMinute()); } else { lv_label_set_text_fmt(lblTime, "%02d:%02d", @@ -292,10 +295,11 @@ void Sleep::DrawInfoScreen() { infiniSleepController.prevSessionData.startTimeHours, infiniSleepController.prevSessionData.startTimeMinutes); } else { - lv_label_set_text_fmt(label_start_time, - "Began at: %02d:%02d", - (infiniSleepController.prevSessionData.startTimeHours % 12 == 0) ? 12 : infiniSleepController.prevSessionData.startTimeHours % 12, - infiniSleepController.prevSessionData.startTimeMinutes); + lv_label_set_text_fmt( + label_start_time, + "Began at: %02d:%02d", + (infiniSleepController.prevSessionData.startTimeHours % 12 == 0) ? 12 : infiniSleepController.prevSessionData.startTimeHours % 12, + infiniSleepController.prevSessionData.startTimeMinutes); } lv_obj_align(label_start_time, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); lv_obj_set_style_local_text_color(label_start_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); From 22a40a96be145ecc859e70e11d185d6bc9dad69b Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 2 Dec 2024 21:49:03 -0600 Subject: [PATCH 095/123] Added Setting to decide motor strength removed some unsed code in motorcontroller made snoozing take user to info page fixed logic for skipping gradual wake while in snooze --- .../infinisleep/InfiniSleepController.cpp | 2 +- .../infinisleep/InfiniSleepController.h | 1 + src/components/motor/MotorController.cpp | 46 ++------------ src/components/motor/MotorController.h | 9 +-- src/displayapp/DisplayApp.cpp | 8 ++- src/displayapp/screens/Sleep.cpp | 60 ++++++++++++++++++- 6 files changed, 71 insertions(+), 55 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 432b09d0f6..dea1ae75b2 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -143,7 +143,7 @@ void InfiniSleepController::ScheduleWakeAlarm() { } // Calculate the period for the gradualWakeTimer - if (isSnoozing != true && infiniSleepSettings.graddualWake && gradualWakeStep > 0) { + if (infiniSleepSettings.graddualWake && gradualWakeStep > 0) { int64_t gradualWakePeriod = ((secondsToWakeAlarm - gradualWakeSteps[-1 + gradualWakeStep])) * (configTICK_RATE_HZ); xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 02ab98ebdb..e1f739c5c2 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -192,6 +192,7 @@ namespace Pinetime { bool smartAlarm = false; uint8_t sleepCycleDuration = SLEEP_CYCLE_DURATION; uint8_t desiredCycles = DESIRED_CYCLES; + uint8_t motorStrength = 100; }; InfiniSleepSettings infiniSleepSettings; diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index ad98dca581..310f361950 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -38,7 +38,6 @@ void MotorController::Init() { // Initialize timers for motor actions shortVib = xTimerCreate("shortVib", 1, pdFALSE, nullptr, StopMotor); longVib = xTimerCreate("longVib", pdMS_TO_TICKS(1000), pdTRUE, this, Ring); - alarmVib = xTimerCreate("alarmVib", pdMS_TO_TICKS(500), pdTRUE, this, AlarmRing); wakeAlarmVib = xTimerCreate("wakeAlarmVib", pdMS_TO_TICKS(1000), pdTRUE, this, WakeAlarmRing); } @@ -57,12 +56,6 @@ void MotorController::Ring(TimerHandle_t xTimer) { motorController->RunForDuration(50); } -void MotorController::AlarmRing(TimerHandle_t xTimer) { - auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); - motorController->SetMotorStrength(80); - motorController->RunForDuration(300); -} - void MotorController::RunForDuration(uint16_t motorDuration) { if (motorDuration > 0 && xTimerChangePeriod(shortVib, pdMS_TO_TICKS(motorDuration), 0) == pdPASS && xTimerStart(shortVib, 0) == pdPASS) { if (pwmValue == 0) { @@ -86,21 +79,8 @@ void MotorController::StopRinging() { nrf_gpio_pin_set(PinMap::Motor); } -void MotorController::StartAlarm() { - SetMotorStrength(80); - RunForDuration(300); - xTimerStart(alarmVib, 0); -} - -void MotorController::StopAlarm() { - xTimerStop(alarmVib, 0); - nrf_pwm_task_trigger(NRF_PWM2, NRF_PWM_TASK_STOP); // Stop the PWM sequence - pwmValue = 0; // Reset the PWM value - nrf_gpio_pin_set(PinMap::Motor); -} - void MotorController::StartWakeAlarm() { - wakeAlarmStrength = 80; + wakeAlarmStrength = (80 * infiniSleepMotorStrength) / 100; wakeAlarmDuration = 100; SetMotorStrength(wakeAlarmStrength); RunForDuration(wakeAlarmDuration); @@ -109,8 +89,8 @@ void MotorController::StartWakeAlarm() { void MotorController::WakeAlarmRing(TimerHandle_t xTimer) { auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); - if (motorController->wakeAlarmStrength > 40) { - motorController->wakeAlarmStrength -= 1; + if (motorController->wakeAlarmStrength > (40 * motorController->infiniSleepMotorStrength) / 100) { + motorController->wakeAlarmStrength -= (1 * motorController->infiniSleepMotorStrength) / 100; } if (motorController->wakeAlarmDuration < 500) { motorController->wakeAlarmDuration += 6; @@ -133,24 +113,6 @@ void MotorController::StopMotor(TimerHandle_t /*xTimer*/) { } void MotorController::GradualWakeBuzz() { - SetMotorStrength(60); + SetMotorStrength((60 * infiniSleepMotorStrength) / 100); RunForDuration(100); - // xTimerStart(gradualWakeBuzzDelay, 0); - // xTimerStart(gradualWakeBuzzEnd, 0); -} - -void MotorController::GradualWakeBuzzRing(TimerHandle_t xTimer) { - auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); - motorController->RunForDuration(12); -} - -void MotorController::StopGradualWakeBuzzCallback(TimerHandle_t xTimer) { - auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); - motorController->StopGradualWakeBuzz(); -} - -void MotorController::StopGradualWakeBuzz() { - // xTimerStop(gradualWakeBuzzDelay, 0); - xTimerStop(gradualWakeBuzzEnd, 0); - // StopMotor(nullptr); } diff --git a/src/components/motor/MotorController.h b/src/components/motor/MotorController.h index 8fca89cfe5..33d9f08b1f 100644 --- a/src/components/motor/MotorController.h +++ b/src/components/motor/MotorController.h @@ -15,8 +15,6 @@ namespace Pinetime { void RunForDuration(uint16_t motorDuration); void StartRinging(); void StopRinging(); - void StartAlarm(); - void StopAlarm(); void StartWakeAlarm(); void StopWakeAlarm(); void GradualWakeBuzz(); @@ -25,20 +23,15 @@ namespace Pinetime { uint8_t wakeAlarmStrength = 80; uint16_t wakeAlarmDuration = 100; + uint8_t infiniSleepMotorStrength = 100; private: static void Ring(TimerHandle_t xTimer); - static void AlarmRing(TimerHandle_t xTimer); static void WakeAlarmRing(TimerHandle_t xTimer); static void StopMotor(TimerHandle_t xTimer); - static void GradualWakeBuzzRing(TimerHandle_t xTimer); - static void StopGradualWakeBuzzCallback(TimerHandle_t xTimer); TimerHandle_t shortVib; TimerHandle_t longVib; - TimerHandle_t alarmVib; - TimerHandle_t gradualWakeBuzzDelay; - TimerHandle_t gradualWakeBuzzEnd; TimerHandle_t wakeAlarmVib; }; diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 0dc84b98a3..527e30dfa6 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -409,12 +409,14 @@ void DisplayApp::Refresh() { // LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); } // motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1 + infiniSleepController.gradualWakeStep]); - motorController.GradualWakeBuzz(); + + if (infiniSleepController.isSnoozing == false) { + motorController.GradualWakeBuzz(); + NRF_LOG_INFO("Gradual wake triggered"); + } infiniSleepController.UpdateGradualWake(); - NRF_LOG_INFO("Gradual wake triggered"); - break; case Messages::SleepTrackerUpdate: if (currentApp == Apps::Sleep) { diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 274b8d1a44..5834c7f9e8 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -56,6 +56,8 @@ static void SnoozeAlarmTaskCallback(lv_task_t* task) { screen->StopAlerting(false); screen->UpdateDisplay(); screen->SnoozeWakeAlarm(); + screen->displayState = Sleep::SleepDisplayState::Info; + screen->UpdateDisplay(); } static void PressesToStopAlarmTimeoutCallback(lv_task_t* task) { @@ -377,7 +379,7 @@ void Sleep::DrawSettingsScreen() { //{"Smart Alarm\n(alpha)", infiniSleepController.SmartAlarmEnabled()} }; - int y_offset = 50; + int y_offset = 30; for (const auto& setting : settings) { lv_obj_t* checkbox = lv_checkbox_create(lv_scr_act(), nullptr); @@ -421,6 +423,51 @@ void Sleep::DrawSettingsScreen() { infiniSleepController.infiniSleepSettings.sleepCycleDuration = 90; infiniSleepController.SetSettingsChanged(); + y_offset += 60; // Adjust the offset for the next UI element + + lv_obj_t* lblMotorStrength = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(lblMotorStrength, "Vibration\nStrength"); + lv_obj_align(lblMotorStrength, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); + + lv_obj_t* btnMotorStrength = lv_btn_create(lv_scr_act(), nullptr); + lv_obj_set_size(btnMotorStrength, 100, 50); + lv_obj_align(btnMotorStrength, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 130, y_offset); + btnMotorStrength->user_data = this; + lv_obj_set_event_cb(btnMotorStrength, [](lv_obj_t* obj, lv_event_t e) { + if (e == LV_EVENT_CLICKED) { + auto* screen = static_cast(obj->user_data); + uint8_t value = screen->infiniSleepController.infiniSleepSettings.motorStrength; + value += 25; + if (value > 200) value = 100; + screen->infiniSleepController.infiniSleepSettings.motorStrength = value; + screen->infiniSleepController.SetSettingsChanged(); + lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d%", value); + screen->motorController.infiniSleepMotorStrength = value; + } + }); + + lv_obj_t* lblMotorStrengthValue = lv_label_create(btnMotorStrength, nullptr); + lv_label_set_text_fmt(lblMotorStrengthValue, "%d%", infiniSleepController.infiniSleepSettings.motorStrength); + motorController.infiniSleepMotorStrength = infiniSleepController.infiniSleepSettings.motorStrength; + lv_obj_align(lblMotorStrengthValue, nullptr, LV_ALIGN_CENTER, 0, 0); + + y_offset += 60; // Adjust the offset for the next UI element + + lv_obj_t* btnTestMotorGradual = lv_btn_create(lv_scr_act(), nullptr); + lv_obj_set_size(btnTestMotorGradual, 220, 50); + lv_obj_align(btnTestMotorGradual, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); + btnTestMotorGradual->user_data = this; + lv_obj_set_event_cb(btnTestMotorGradual, [](lv_obj_t* obj, lv_event_t e) { + if (e == LV_EVENT_CLICKED) { + auto* screen = static_cast(obj->user_data); + screen->motorController.GradualWakeBuzz(); + } + }); + + lv_obj_t* txtTestMotorGradual = lv_label_create(btnTestMotorGradual, nullptr); + lv_label_set_text_static(txtTestMotorGradual, "Test Motor"); + lv_obj_align(txtTestMotorGradual, nullptr, LV_ALIGN_CENTER, 0, 0); + y_offset += 70; // Adjust the offset for the next UI element } @@ -430,6 +477,8 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { StopAlerting(); UpdateDisplay(); SnoozeWakeAlarm(); + displayState = SleepDisplayState::Info; + UpdateDisplay(); return; } if (obj == btnStop) { @@ -446,6 +495,10 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } else { infiniSleepController.DisableWakeAlarm(); } + if (infiniSleepController.isSnoozing) { + infiniSleepController.RestorePreSnoozeTime(); + } + infiniSleepController.isSnoozing = false; return; } if (obj == trackerToggleBtn) { @@ -485,6 +538,11 @@ bool Sleep::OnButtonPushed() { return true; } } + if (displayState != SleepDisplayState::Info) { + displayState = SleepDisplayState::Info; + UpdateDisplay(); + return true; + } return false; } From 058871026751cb56bce31cfe32ae131ff7fdd8d2 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 5 Dec 2024 19:31:22 -0600 Subject: [PATCH 096/123] Added Setting to select pushes required to stop alarm Also added setting for natural awake, will implement next --- .../infinisleep/InfiniSleepController.cpp | 7 +- .../infinisleep/InfiniSleepController.h | 2 + src/displayapp/screens/Sleep.cpp | 136 +++++++++++------- src/systemtask/SystemTask.cpp | 2 +- 4 files changed, 91 insertions(+), 56 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index dea1ae75b2..645f8a9083 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -40,6 +40,11 @@ void InfiniSleepController::Init(System::SystemTask* systemTask) { LoadSettingsFromFile(); LoadPrevSessionData(); + if (infiniSleepSettings.pushesToStopAlarm == 0) { + infiniSleepSettings.pushesToStopAlarm = PUSHES_TO_STOP_ALARM; + settingsChanged = true; + } + pushesLeftToStopWakeAlarm = infiniSleepSettings.pushesToStopAlarm; if (wakeAlarm.isEnabled) { NRF_LOG_INFO("[InfiniSleepController] Loaded wake alarm was enabled, scheduling"); ScheduleWakeAlarm(); @@ -106,7 +111,7 @@ void InfiniSleepController::ScheduleWakeAlarm() { xTimerStop(wakeAlarmTimer, 0); xTimerStop(gradualWakeTimer, 0); - pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; + pushesLeftToStopWakeAlarm = infiniSleepSettings.pushesToStopAlarm; gradualWakeStep = 9; diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index e1f739c5c2..14355679ce 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -193,6 +193,8 @@ namespace Pinetime { uint8_t sleepCycleDuration = SLEEP_CYCLE_DURATION; uint8_t desiredCycles = DESIRED_CYCLES; uint8_t motorStrength = 100; + bool naturalWake = false; + uint8_t pushesToStopAlarm = PUSHES_TO_STOP_ALARM; }; InfiniSleepSettings infiniSleepSettings; diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 5834c7f9e8..28ec9d50d5 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -62,7 +62,7 @@ static void SnoozeAlarmTaskCallback(lv_task_t* task) { static void PressesToStopAlarmTimeoutCallback(lv_task_t* task) { auto* screen = static_cast(task->user_data); - screen->infiniSleepController.pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; + screen->infiniSleepController.pushesLeftToStopWakeAlarm = screen->infiniSleepController.infiniSleepSettings.pushesToStopAlarm; screen->UpdateDisplay(); } @@ -206,8 +206,8 @@ void Sleep::DrawAlarmScreen() { txtStop = lv_label_create(btnStop, nullptr); lv_label_set_text_fmt(txtStop, "Stop: %d/%d", - PUSHES_TO_STOP_ALARM - infiniSleepController.pushesLeftToStopWakeAlarm, - PUSHES_TO_STOP_ALARM); + infiniSleepController.infiniSleepSettings.pushesToStopAlarm - infiniSleepController.pushesLeftToStopWakeAlarm, + infiniSleepController.infiniSleepSettings.pushesToStopAlarm); lv_obj_set_hidden(btnStop, true); static constexpr lv_color_t bgColor = Colors::bgAlt; @@ -362,40 +362,46 @@ void Sleep::DrawInfoScreen() { } void Sleep::DrawSettingsScreen() { - lv_obj_t* lblSettings = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_static(lblSettings, "Settings"); - lv_obj_align(lblSettings, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 10); - - struct Setting { - const char* name; - bool enabled; - int offsetAfter = 30; - }; - - const Setting settings[] = { - //{"Body Tracking", infiniSleepController.BodyTrackingEnabled()}, - // {"Heart Rate\nTracking", infiniSleepController.HeartRateTrackingEnabled(), 60}, - {"Gradual Wake", infiniSleepController.GradualWakeEnabled()}, - //{"Smart Alarm\n(alpha)", infiniSleepController.SmartAlarmEnabled()} - }; - - int y_offset = 30; - for (const auto& setting : settings) { - - lv_obj_t* checkbox = lv_checkbox_create(lv_scr_act(), nullptr); - checkbox->user_data = const_cast(setting.name); - lv_checkbox_set_text_static(checkbox, const_cast(setting.name)); - - if (setting.enabled) { - lv_checkbox_set_checked(checkbox, true); - } else { - lv_checkbox_set_checked(checkbox, false); + // lv_obj_t* lblSettings = lv_label_create(lv_scr_act(), nullptr); + // lv_label_set_text_static(lblSettings, "Settings"); + // lv_obj_align(lblSettings, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 10); + + int y_offset = 10; + + lv_obj_t* lblWakeMode = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(lblWakeMode, "Wake\nMode"); + lv_obj_align(lblWakeMode, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); + + lv_obj_t* btnWakeMode = lv_btn_create(lv_scr_act(), nullptr); + lv_obj_set_size(btnWakeMode, 100, 50); + lv_obj_align(btnWakeMode, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 130, y_offset); + btnWakeMode->user_data = this; + lv_obj_set_event_cb(btnWakeMode, [](lv_obj_t* obj, lv_event_t e) { + if (e == LV_EVENT_CLICKED) { + auto* screen = static_cast(obj->user_data); + auto& settings = screen->infiniSleepController.infiniSleepSettings; + if (settings.graddualWake) { + settings.graddualWake = false; + settings.naturalWake = true; + } else if (settings.naturalWake) { + settings.naturalWake = false; + settings.graddualWake = false; + } else if (!settings.graddualWake && !settings.naturalWake) { + settings.graddualWake = true; + } + screen->infiniSleepController.SetSettingsChanged(); + const char* mode = settings.graddualWake ? "Grad." : settings.naturalWake ? "Nat." : "Off"; + lv_label_set_text_static(lv_obj_get_child(obj, nullptr), mode); } - lv_obj_align(checkbox, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); + }); + const char* mode = infiniSleepController.infiniSleepSettings.graddualWake ? "Grad." + : infiniSleepController.infiniSleepSettings.naturalWake ? "Nat." + : "Off"; + lv_obj_t* lblWakeModeValue = lv_label_create(btnWakeMode, nullptr); + lv_label_set_text_static(lblWakeModeValue, mode); + lv_obj_align(lblWakeModeValue, nullptr, LV_ALIGN_CENTER, 0, 0); - lv_obj_set_event_cb(checkbox, settingsToggleEventHandler); - y_offset += setting.offsetAfter; // Increase the offset to provide better spacing - } + y_offset += 60; // Adjust the offset for the next UI element lv_obj_t* lblCycles = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(lblCycles, "Desired\nCycles"); @@ -425,9 +431,20 @@ void Sleep::DrawSettingsScreen() { y_offset += 60; // Adjust the offset for the next UI element - lv_obj_t* lblMotorStrength = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_static(lblMotorStrength, "Vibration\nStrength"); - lv_obj_align(lblMotorStrength, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); + lv_obj_t* btnTestMotorGradual = lv_btn_create(lv_scr_act(), nullptr); + lv_obj_set_size(btnTestMotorGradual, 110, 50); + lv_obj_align(btnTestMotorGradual, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); + btnTestMotorGradual->user_data = this; + lv_obj_set_event_cb(btnTestMotorGradual, [](lv_obj_t* obj, lv_event_t e) { + if (e == LV_EVENT_CLICKED) { + auto* screen = static_cast(obj->user_data); + screen->motorController.GradualWakeBuzz(); + } + }); + + lv_obj_t* lblMotorStrength = lv_label_create(btnTestMotorGradual, nullptr); + lv_label_set_text_static(lblMotorStrength, "Motor\nPower"); + lv_obj_align(lblMotorStrength, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, 0); lv_obj_t* btnMotorStrength = lv_btn_create(lv_scr_act(), nullptr); lv_obj_set_size(btnMotorStrength, 100, 50); @@ -438,37 +455,44 @@ void Sleep::DrawSettingsScreen() { auto* screen = static_cast(obj->user_data); uint8_t value = screen->infiniSleepController.infiniSleepSettings.motorStrength; value += 25; - if (value > 200) value = 100; + if (value > 200) + value = 100; screen->infiniSleepController.infiniSleepSettings.motorStrength = value; screen->infiniSleepController.SetSettingsChanged(); - lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d%", value); + lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d", value); screen->motorController.infiniSleepMotorStrength = value; } }); lv_obj_t* lblMotorStrengthValue = lv_label_create(btnMotorStrength, nullptr); - lv_label_set_text_fmt(lblMotorStrengthValue, "%d%", infiniSleepController.infiniSleepSettings.motorStrength); + lv_label_set_text_fmt(lblMotorStrengthValue, "%d", infiniSleepController.infiniSleepSettings.motorStrength); motorController.infiniSleepMotorStrength = infiniSleepController.infiniSleepSettings.motorStrength; lv_obj_align(lblMotorStrengthValue, nullptr, LV_ALIGN_CENTER, 0, 0); y_offset += 60; // Adjust the offset for the next UI element - lv_obj_t* btnTestMotorGradual = lv_btn_create(lv_scr_act(), nullptr); - lv_obj_set_size(btnTestMotorGradual, 220, 50); - lv_obj_align(btnTestMotorGradual, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); - btnTestMotorGradual->user_data = this; - lv_obj_set_event_cb(btnTestMotorGradual, [](lv_obj_t* obj, lv_event_t e) { + lv_obj_t* lblPushesToStop = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(lblPushesToStop, "Pushes\nto Stop"); + lv_obj_align(lblPushesToStop, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); + + lv_obj_t* btnPushesToStop = lv_btn_create(lv_scr_act(), nullptr); + lv_obj_set_size(btnPushesToStop, 100, 50); + lv_obj_align(btnPushesToStop, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 130, y_offset); + btnPushesToStop->user_data = this; + lv_obj_set_event_cb(btnPushesToStop, [](lv_obj_t* obj, lv_event_t e) { if (e == LV_EVENT_CLICKED) { auto* screen = static_cast(obj->user_data); - screen->motorController.GradualWakeBuzz(); + int value = screen->infiniSleepController.infiniSleepSettings.pushesToStopAlarm; + value = (value % 10) + 1; // Cycle through values 1 to 10 + screen->infiniSleepController.infiniSleepSettings.pushesToStopAlarm = value; + screen->infiniSleepController.SetSettingsChanged(); + lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d", value); } }); - lv_obj_t* txtTestMotorGradual = lv_label_create(btnTestMotorGradual, nullptr); - lv_label_set_text_static(txtTestMotorGradual, "Test Motor"); - lv_obj_align(txtTestMotorGradual, nullptr, LV_ALIGN_CENTER, 0, 0); - - y_offset += 70; // Adjust the offset for the next UI element + lv_obj_t* lblPushesToStopValue = lv_label_create(btnPushesToStop, nullptr); + lv_label_set_text_fmt(lblPushesToStopValue, "%d", infiniSleepController.infiniSleepSettings.pushesToStopAlarm); + lv_obj_align(lblPushesToStopValue, nullptr, LV_ALIGN_CENTER, 0, 0); } void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { @@ -658,7 +682,9 @@ void Sleep::SetAlerting() { lv_obj_set_hidden(iconSuggestedAlarm, true); NRF_LOG_INFO("Alarm is alerting"); taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, 120 * 1000, LV_TASK_PRIO_MID, this); - motorController.StartWakeAlarm(); + if (infiniSleepController.infiniSleepSettings.graddualWake) { + motorController.StartWakeAlarm(); + } wakeLock.Lock(); alreadyAlerting = true; } @@ -675,7 +701,9 @@ void Sleep::RedrawSetAlerting() { void Sleep::StopAlerting(bool setSwitch) { infiniSleepController.StopAlerting(); - motorController.StopWakeAlarm(); + if (infiniSleepController.infiniSleepSettings.graddualWake) { + motorController.StopWakeAlarm(); + } if (setSwitch) { SetSwitchState(LV_ANIM_OFF); } diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index c7e4685f8c..f6825566b6 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -202,7 +202,7 @@ void SystemTask::Work() { GoToRunning(); break; case Messages::GoToSleep: - infiniSleepController.pushesLeftToStopWakeAlarm = PUSHES_TO_STOP_ALARM; + infiniSleepController.pushesLeftToStopWakeAlarm = infiniSleepController.infiniSleepSettings.pushesToStopAlarm; GoToSleep(); break; case Messages::OnNewTime: From dea45b3e648ca218d5eba10c875564559dacea01 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 5 Dec 2024 19:41:28 -0600 Subject: [PATCH 097/123] Disabled settings while alarm is active. Dif this to avoid weird behavior that can happen if changed during alarm active state. This also remove the need to handle those in code. --- src/displayapp/screens/Sleep.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 28ec9d50d5..357382ba03 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -366,6 +366,14 @@ void Sleep::DrawSettingsScreen() { // lv_label_set_text_static(lblSettings, "Settings"); // lv_obj_align(lblSettings, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 10); + if (infiniSleepController.wakeAlarm.isEnabled) { + lv_obj_t* lblWarning = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(lblWarning, "Disable alarm to\nchange settings."); + lv_obj_align(lblWarning, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_text_color(lblWarning, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); + return; + } + int y_offset = 10; lv_obj_t* lblWakeMode = lv_label_create(lv_scr_act(), nullptr); From 2c1fbde683b625ddaadee971f5b5f007d47aa2fc Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 5 Dec 2024 20:04:51 -0600 Subject: [PATCH 098/123] Added natural wake alarm to motor controller. removed wakelock when using natural alrm mode as user may not wake up soon and unintended taps may happen. --- src/components/motor/MotorController.cpp | 20 ++++++ src/components/motor/MotorController.h | 4 ++ src/displayapp/screens/Sleep.cpp | 83 +++--------------------- src/displayapp/screens/Sleep.h | 2 - 4 files changed, 34 insertions(+), 75 deletions(-) diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index 310f361950..dd4ed64b29 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -39,6 +39,7 @@ void MotorController::Init() { shortVib = xTimerCreate("shortVib", 1, pdFALSE, nullptr, StopMotor); longVib = xTimerCreate("longVib", pdMS_TO_TICKS(1000), pdTRUE, this, Ring); wakeAlarmVib = xTimerCreate("wakeAlarmVib", pdMS_TO_TICKS(1000), pdTRUE, this, WakeAlarmRing); + naturalWakeAlarmVib = xTimerCreate("natWakeVib", pdMS_TO_TICKS(30 * 1000), pdTRUE, this, NaturalWakeAlarmRing); } void MotorController::SetMotorStrength(uint8_t strength) { @@ -106,6 +107,25 @@ void MotorController::StopWakeAlarm() { nrf_gpio_pin_set(PinMap::Motor); } +void MotorController::StartNaturalWakeAlarm() { + SetMotorStrength((60 * infiniSleepMotorStrength) / 100); + RunForDuration(280); + xTimerStart(naturalWakeAlarmVib, 0); +} + +void MotorController::NaturalWakeAlarmRing(TimerHandle_t xTimer) { + auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); + motorController->SetMotorStrength((60 * motorController->infiniSleepMotorStrength) / 100); + motorController->RunForDuration(280); +} + +void MotorController::StopNaturalWakeAlarm() { + xTimerStop(naturalWakeAlarmVib, 0); + nrf_pwm_task_trigger(NRF_PWM2, NRF_PWM_TASK_STOP); // Stop the PWM sequence + pwmValue = 0; // Reset the PWM value + nrf_gpio_pin_set(PinMap::Motor); +} + void MotorController::StopMotor(TimerHandle_t /*xTimer*/) { nrf_pwm_task_trigger(NRF_PWM2, NRF_PWM_TASK_STOP); // Stop the PWM sequence pwmValue = 0; // Reset the PWM value diff --git a/src/components/motor/MotorController.h b/src/components/motor/MotorController.h index 33d9f08b1f..cfeeb22a25 100644 --- a/src/components/motor/MotorController.h +++ b/src/components/motor/MotorController.h @@ -17,6 +17,8 @@ namespace Pinetime { void StopRinging(); void StartWakeAlarm(); void StopWakeAlarm(); + void StartNaturalWakeAlarm(); + void StopNaturalWakeAlarm(); void GradualWakeBuzz(); void StopGradualWakeBuzz(); void SetMotorStrength(uint8_t strength); @@ -28,12 +30,14 @@ namespace Pinetime { private: static void Ring(TimerHandle_t xTimer); static void WakeAlarmRing(TimerHandle_t xTimer); + static void NaturalWakeAlarmRing(TimerHandle_t xTimer); static void StopMotor(TimerHandle_t xTimer); TimerHandle_t shortVib; TimerHandle_t longVib; TimerHandle_t wakeAlarmVib; + TimerHandle_t naturalWakeAlarmVib; }; } } diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 357382ba03..49fd987428 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -20,31 +20,6 @@ namespace { } } -extern InfiniSleepController infiniSleepController; - -static void settingsToggleEventHandler(lv_obj_t* obj, lv_event_t e) { - if (e != LV_EVENT_VALUE_CHANGED) { - return; - } - - const char* setting_name = static_cast(obj->user_data); - bool enabled = lv_checkbox_is_checked(obj); - - if (strcmp(setting_name, "Body Tracking") == 0) { - infiniSleepController.SetBodyTrackingEnabled(enabled); - infiniSleepController.SetSettingsChanged(); - } else if (strcmp(setting_name, "Heart Rate\nTracking") == 0) { - infiniSleepController.SetHeartRateTrackingEnabled(enabled); - infiniSleepController.SetSettingsChanged(); - } else if (strcmp(setting_name, "Gradual Wake") == 0) { - infiniSleepController.SetGradualWakeEnabled(enabled); - infiniSleepController.SetSettingsChanged(); - } else if (strcmp(setting_name, "Smart Alarm\n(alpha)") == 0) { - infiniSleepController.SetSmartAlarmEnabled(enabled); - infiniSleepController.SetSettingsChanged(); - } -} - static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { auto* screen = static_cast(obj->user_data); screen->OnButtonEvent(obj, event); @@ -517,10 +492,6 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { StopAlarmPush(); return; } - if (obj == btnMessage) { - HideAlarmInfo(); - return; - } if (obj == enableSwitch) { if (lv_switch_get_state(enableSwitch)) { infiniSleepController.ScheduleWakeAlarm(); @@ -561,10 +532,6 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } bool Sleep::OnButtonPushed() { - if (txtMessage != nullptr && btnMessage != nullptr) { - HideAlarmInfo(); - return true; - } if (infiniSleepController.IsAlerting()) { if (StopAlarmPush()) { return true; @@ -692,8 +659,12 @@ void Sleep::SetAlerting() { taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, 120 * 1000, LV_TASK_PRIO_MID, this); if (infiniSleepController.infiniSleepSettings.graddualWake) { motorController.StartWakeAlarm(); + } else if (infiniSleepController.infiniSleepSettings.naturalWake) { + motorController.StartNaturalWakeAlarm(); + } + if (infiniSleepController.infiniSleepSettings.naturalWake != true) { + wakeLock.Lock(); } - wakeLock.Lock(); alreadyAlerting = true; } @@ -704,13 +675,17 @@ void Sleep::RedrawSetAlerting() { lv_obj_set_hidden(btnSuggestedAlarm, true); lv_obj_set_hidden(txtSuggestedAlarm, true); lv_obj_set_hidden(iconSuggestedAlarm, true); - wakeLock.Lock(); + if (infiniSleepController.infiniSleepSettings.naturalWake != true) { + wakeLock.Lock(); + } } void Sleep::StopAlerting(bool setSwitch) { infiniSleepController.StopAlerting(); if (infiniSleepController.infiniSleepSettings.graddualWake) { motorController.StopWakeAlarm(); + } else if (infiniSleepController.infiniSleepSettings.naturalWake) { + motorController.StopNaturalWakeAlarm(); } if (setSwitch) { SetSwitchState(LV_ANIM_OFF); @@ -731,42 +706,4 @@ void Sleep::SetSwitchState(lv_anim_enable_t anim) { } else { lv_switch_off(enableSwitch, anim); } -} - -void Sleep::ShowAlarmInfo() { - if (btnMessage != nullptr) { - return; - } - btnMessage = lv_btn_create(lv_scr_act(), nullptr); - btnMessage->user_data = this; - lv_obj_set_event_cb(btnMessage, btnEventHandler); - lv_obj_set_height(btnMessage, 200); - lv_obj_set_width(btnMessage, 150); - lv_obj_align(btnMessage, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); - txtMessage = lv_label_create(btnMessage, nullptr); - lv_obj_set_style_local_bg_color(btnMessage, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_NAVY); - - if (infiniSleepController.GetWakeAlarm().isEnabled) { - auto timeToAlarm = infiniSleepController.SecondsToWakeAlarm(); - - auto daysToAlarm = timeToAlarm / 86400; - auto hrsToAlarm = (timeToAlarm % 86400) / 3600; - auto minToAlarm = (timeToAlarm % 3600) / 60; - auto secToAlarm = timeToAlarm % 60; - - lv_label_set_text_fmt(txtMessage, - "Time to\nalarm:\n%2lu Days\n%2lu Hours\n%2lu Minutes\n%2lu Seconds", - daysToAlarm, - hrsToAlarm, - minToAlarm, - secToAlarm); - } else { - lv_label_set_text_static(txtMessage, "Alarm\nis not\nset."); - } -} - -void Sleep::HideAlarmInfo() { - lv_obj_del(btnMessage); - txtMessage = nullptr; - btnMessage = nullptr; } \ No newline at end of file diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 514fdd57c4..7e5ce3738b 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -58,8 +58,6 @@ namespace Pinetime { void DisableWakeAlarm(); void SetSwitchState(lv_anim_enable_t anim); void SetWakeAlarm(); - void ShowAlarmInfo(); - void HideAlarmInfo(); void UpdateWakeAlarmTime(); Widgets::Counter hourCounter = Widgets::Counter(0, 23, jetbrains_mono_76); Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_76); From b6e9dc0e666935ba9118583a80a6d3372a5d4cf2 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 7 Dec 2024 12:16:40 -0600 Subject: [PATCH 099/123] Made sure to wait for sleep app to load before doing things on wake I think this fixed some things --- src/displayapp/DisplayApp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 527e30dfa6..66c5e17bfd 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -359,6 +359,9 @@ void DisplayApp::Refresh() { if (infiniSleepController.IsEnabled()) { if (currentApp != Apps::Sleep) { LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::Up); + // Wait for the sleep app to load before moving on. + while (!lv_task_handler()) { + }; } } } From d576dd9bc7d890eca2a068fb9c1c29efdf61b092 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 7 Dec 2024 12:18:45 -0600 Subject: [PATCH 100/123] Updated info page to show current wake mode instead of just gradual wake --- src/displayapp/screens/Sleep.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 49fd987428..e91ac4abc5 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -307,10 +307,12 @@ void Sleep::DrawInfoScreen() { // Gradual Wake info label_gradual_wake = lv_label_create(lv_scr_act(), nullptr); - if (infiniSleepController.GetInfiniSleepSettings().graddualWake && infiniSleepController.gradualWakeStep >= 0) { - lv_label_set_text_fmt(label_gradual_wake, "Gradual Wake: ON"); + if (infiniSleepController.infiniSleepSettings.graddualWake) { + lv_label_set_text_static(label_gradual_wake, "Wake Mode: Gradual"); + } else if (infiniSleepController.infiniSleepSettings.naturalWake) { + lv_label_set_text_static(label_gradual_wake, "Wake Mode: Natural"); } else { - lv_label_set_text_static(label_gradual_wake, "Gradual Wake: OFF"); + lv_label_set_text_static(label_gradual_wake, "Wake Mode: Off"); } lv_obj_align(label_gradual_wake, lv_scr_act(), LV_ALIGN_CENTER, 0, 40); lv_obj_set_style_local_text_color(label_gradual_wake, From d8935f3886c3131c6c45b550176410bec7a6bdfa Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 7 Dec 2024 12:20:32 -0600 Subject: [PATCH 101/123] Removed suto display refresh on alarm screen, allows for holding down on widget without 2 second stutter. Formatted DisplayApp.cpp --- src/displayapp/DisplayApp.cpp | 2 +- src/displayapp/screens/Sleep.cpp | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 66c5e17bfd..2415e138d0 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -412,7 +412,7 @@ void DisplayApp::Refresh() { // LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::None); } // motorController.RunForDuration(infiniSleepController.gradualWakeVibrationDurations[-1 + infiniSleepController.gradualWakeStep]); - + if (infiniSleepController.isSnoozing == false) { motorController.GradualWakeBuzz(); NRF_LOG_INFO("Gradual wake triggered"); diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index e91ac4abc5..b3a99b4ea2 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -88,6 +88,10 @@ void Sleep::Refresh() { } void Sleep::UpdateDisplay() { + if (lastDisplayState == displayState && displayState == SleepDisplayState::Alarm) { + return; + } + // Clear the screen lv_obj_clean(lv_scr_act()); if (infiniSleepController.IsAlerting()) { @@ -528,6 +532,7 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { OnValueChanged(); infiniSleepController.ScheduleWakeAlarm(); + SetSwitchState(LV_ANIM_OFF); return; } } From d117ed9181dfab21691d5f5e8ae7e4bfb17474d9 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 9 Dec 2024 00:11:41 -0600 Subject: [PATCH 102/123] Fixed display not upadting on alerting screen. removed auto snooze for natural wake removed side button to stop alarm --- src/displayapp/screens/Sleep.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index b3a99b4ea2..1011b097f1 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -88,7 +88,7 @@ void Sleep::Refresh() { } void Sleep::UpdateDisplay() { - if (lastDisplayState == displayState && displayState == SleepDisplayState::Alarm) { + if (infiniSleepController.IsAlerting() != true && lastDisplayState == displayState && displayState == SleepDisplayState::Alarm) { return; } @@ -540,11 +540,8 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { bool Sleep::OnButtonPushed() { if (infiniSleepController.IsAlerting()) { - if (StopAlarmPush()) { - return true; - } - } - if (displayState != SleepDisplayState::Info) { + return true; + } else if (displayState != SleepDisplayState::Info) { displayState = SleepDisplayState::Info; UpdateDisplay(); return true; @@ -579,8 +576,8 @@ bool Sleep::StopAlarmPush() { bool Sleep::OnTouchEvent(Pinetime::Applications::TouchEvents event) { // Swiping should be ignored when in alerting state - if (infiniSleepController.IsAlerting() && (event != TouchEvents::SwipeDown && event != TouchEvents::SwipeUp && - event != TouchEvents::SwipeLeft && event != TouchEvents::SwipeRight)) { + if (infiniSleepController.IsAlerting() && (event == TouchEvents::SwipeDown || event == TouchEvents::SwipeUp || + event == TouchEvents::SwipeLeft || event == TouchEvents::SwipeRight)) { return true; } @@ -663,7 +660,9 @@ void Sleep::SetAlerting() { lv_obj_set_hidden(txtSuggestedAlarm, true); lv_obj_set_hidden(iconSuggestedAlarm, true); NRF_LOG_INFO("Alarm is alerting"); - taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, 120 * 1000, LV_TASK_PRIO_MID, this); + if (infiniSleepController.infiniSleepSettings.naturalWake != true) { + taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, 120 * 1000, LV_TASK_PRIO_MID, this); + } if (infiniSleepController.infiniSleepSettings.graddualWake) { motorController.StartWakeAlarm(); } else if (infiniSleepController.infiniSleepSettings.naturalWake) { From 5385ee1dd40744a2a84f36392d7a0c7383cbcc23 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 9 Dec 2024 01:11:03 -0600 Subject: [PATCH 103/123] Moved Code event code for settings page into btnHandler, better convention. --- src/displayapp/screens/Sleep.cpp | 209 +++++++++++++++---------------- src/displayapp/screens/Sleep.h | 3 + 2 files changed, 106 insertions(+), 106 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 1011b097f1..c47b7b9840 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -11,36 +11,36 @@ #include using namespace Pinetime::Applications::Screens; -using Pinetime::Controllers::InfiniSleepController; namespace { void ValueChangedHandler(void* userData) { auto* screen = static_cast(userData); screen->OnValueChanged(); } -} -static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { - auto* screen = static_cast(obj->user_data); - screen->OnButtonEvent(obj, event); -} + void btnEventHandler(lv_obj_t* obj, lv_event_t event) { + auto* screen = static_cast(obj->user_data); + screen->OnButtonEvent(obj, event); + } -static void SnoozeAlarmTaskCallback(lv_task_t* task) { - auto* screen = static_cast(task->user_data); - lv_task_set_prio(task, LV_TASK_PRIO_OFF); - screen->StopAlerting(false); - screen->UpdateDisplay(); - screen->SnoozeWakeAlarm(); - screen->displayState = Sleep::SleepDisplayState::Info; - screen->UpdateDisplay(); -} + void SnoozeAlarmTaskCallback(lv_task_t* task) { + auto* screen = static_cast(task->user_data); + lv_task_set_prio(task, LV_TASK_PRIO_OFF); + screen->StopAlerting(false); + screen->UpdateDisplay(); + screen->SnoozeWakeAlarm(); + screen->displayState = Sleep::SleepDisplayState::Info; + screen->UpdateDisplay(); + } -static void PressesToStopAlarmTimeoutCallback(lv_task_t* task) { - auto* screen = static_cast(task->user_data); - screen->infiniSleepController.pushesLeftToStopWakeAlarm = screen->infiniSleepController.infiniSleepSettings.pushesToStopAlarm; - screen->UpdateDisplay(); + void PressesToStopAlarmTimeoutCallback(lv_task_t* task) { + auto* screen = static_cast(task->user_data); + screen->infiniSleepController.pushesLeftToStopWakeAlarm = screen->infiniSleepController.infiniSleepSettings.pushesToStopAlarm; + screen->UpdateDisplay(); + } } + Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, Controllers::Settings::ClockType clockType, System::SystemTask& systemTask, @@ -355,63 +355,37 @@ void Sleep::DrawSettingsScreen() { return; } - int y_offset = 10; + uint8_t y_offset = 10; - lv_obj_t* lblWakeMode = lv_label_create(lv_scr_act(), nullptr); + lblWakeMode = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(lblWakeMode, "Wake\nMode"); lv_obj_align(lblWakeMode, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); - lv_obj_t* btnWakeMode = lv_btn_create(lv_scr_act(), nullptr); + btnWakeMode = lv_btn_create(lv_scr_act(), nullptr); lv_obj_set_size(btnWakeMode, 100, 50); lv_obj_align(btnWakeMode, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 130, y_offset); btnWakeMode->user_data = this; - lv_obj_set_event_cb(btnWakeMode, [](lv_obj_t* obj, lv_event_t e) { - if (e == LV_EVENT_CLICKED) { - auto* screen = static_cast(obj->user_data); - auto& settings = screen->infiniSleepController.infiniSleepSettings; - if (settings.graddualWake) { - settings.graddualWake = false; - settings.naturalWake = true; - } else if (settings.naturalWake) { - settings.naturalWake = false; - settings.graddualWake = false; - } else if (!settings.graddualWake && !settings.naturalWake) { - settings.graddualWake = true; - } - screen->infiniSleepController.SetSettingsChanged(); - const char* mode = settings.graddualWake ? "Grad." : settings.naturalWake ? "Nat." : "Off"; - lv_label_set_text_static(lv_obj_get_child(obj, nullptr), mode); - } - }); + lv_obj_set_event_cb(btnWakeMode, btnEventHandler); const char* mode = infiniSleepController.infiniSleepSettings.graddualWake ? "Grad." : infiniSleepController.infiniSleepSettings.naturalWake ? "Nat." : "Off"; - lv_obj_t* lblWakeModeValue = lv_label_create(btnWakeMode, nullptr); + lblWakeModeValue = lv_label_create(btnWakeMode, nullptr); lv_label_set_text_static(lblWakeModeValue, mode); lv_obj_align(lblWakeModeValue, nullptr, LV_ALIGN_CENTER, 0, 0); y_offset += 60; // Adjust the offset for the next UI element - lv_obj_t* lblCycles = lv_label_create(lv_scr_act(), nullptr); + lblCycles = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(lblCycles, "Desired\nCycles"); lv_obj_align(lblCycles, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); - lv_obj_t* btnCycles = lv_btn_create(lv_scr_act(), nullptr); + btnCycles = lv_btn_create(lv_scr_act(), nullptr); lv_obj_set_size(btnCycles, 100, 50); lv_obj_align(btnCycles, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 130, y_offset); btnCycles->user_data = this; - lv_obj_set_event_cb(btnCycles, [](lv_obj_t* obj, lv_event_t e) { - if (e == LV_EVENT_CLICKED) { - auto* screen = static_cast(obj->user_data); - int value = screen->infiniSleepController.infiniSleepSettings.desiredCycles; - value = (value % 10) + 1; // Cycle through values 1 to 10 - screen->infiniSleepController.infiniSleepSettings.desiredCycles = value; - screen->infiniSleepController.SetSettingsChanged(); - lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d", value); - } - }); + lv_obj_set_event_cb(btnCycles, btnEventHandler); - lv_obj_t* lblCycleValue = lv_label_create(btnCycles, nullptr); + lblCycleValue = lv_label_create(btnCycles, nullptr); lv_label_set_text_fmt(lblCycleValue, "%d", infiniSleepController.infiniSleepSettings.desiredCycles); lv_obj_align(lblCycleValue, nullptr, LV_ALIGN_CENTER, 0, 0); @@ -420,66 +394,40 @@ void Sleep::DrawSettingsScreen() { y_offset += 60; // Adjust the offset for the next UI element - lv_obj_t* btnTestMotorGradual = lv_btn_create(lv_scr_act(), nullptr); + btnTestMotorGradual = lv_btn_create(lv_scr_act(), nullptr); lv_obj_set_size(btnTestMotorGradual, 110, 50); lv_obj_align(btnTestMotorGradual, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); btnTestMotorGradual->user_data = this; - lv_obj_set_event_cb(btnTestMotorGradual, [](lv_obj_t* obj, lv_event_t e) { - if (e == LV_EVENT_CLICKED) { - auto* screen = static_cast(obj->user_data); - screen->motorController.GradualWakeBuzz(); - } - }); + lv_obj_set_event_cb(btnTestMotorGradual, btnEventHandler); - lv_obj_t* lblMotorStrength = lv_label_create(btnTestMotorGradual, nullptr); + lblMotorStrength = lv_label_create(btnTestMotorGradual, nullptr); lv_label_set_text_static(lblMotorStrength, "Motor\nPower"); lv_obj_align(lblMotorStrength, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, 0); - lv_obj_t* btnMotorStrength = lv_btn_create(lv_scr_act(), nullptr); + btnMotorStrength = lv_btn_create(lv_scr_act(), nullptr); lv_obj_set_size(btnMotorStrength, 100, 50); lv_obj_align(btnMotorStrength, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 130, y_offset); btnMotorStrength->user_data = this; - lv_obj_set_event_cb(btnMotorStrength, [](lv_obj_t* obj, lv_event_t e) { - if (e == LV_EVENT_CLICKED) { - auto* screen = static_cast(obj->user_data); - uint8_t value = screen->infiniSleepController.infiniSleepSettings.motorStrength; - value += 25; - if (value > 200) - value = 100; - screen->infiniSleepController.infiniSleepSettings.motorStrength = value; - screen->infiniSleepController.SetSettingsChanged(); - lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d", value); - screen->motorController.infiniSleepMotorStrength = value; - } - }); + lv_obj_set_event_cb(btnMotorStrength, btnEventHandler); - lv_obj_t* lblMotorStrengthValue = lv_label_create(btnMotorStrength, nullptr); + lblMotorStrengthValue = lv_label_create(btnMotorStrength, nullptr); lv_label_set_text_fmt(lblMotorStrengthValue, "%d", infiniSleepController.infiniSleepSettings.motorStrength); motorController.infiniSleepMotorStrength = infiniSleepController.infiniSleepSettings.motorStrength; lv_obj_align(lblMotorStrengthValue, nullptr, LV_ALIGN_CENTER, 0, 0); y_offset += 60; // Adjust the offset for the next UI element - lv_obj_t* lblPushesToStop = lv_label_create(lv_scr_act(), nullptr); + lblPushesToStop = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(lblPushesToStop, "Pushes\nto Stop"); lv_obj_align(lblPushesToStop, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 10, y_offset); - lv_obj_t* btnPushesToStop = lv_btn_create(lv_scr_act(), nullptr); + btnPushesToStop = lv_btn_create(lv_scr_act(), nullptr); lv_obj_set_size(btnPushesToStop, 100, 50); lv_obj_align(btnPushesToStop, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 130, y_offset); btnPushesToStop->user_data = this; - lv_obj_set_event_cb(btnPushesToStop, [](lv_obj_t* obj, lv_event_t e) { - if (e == LV_EVENT_CLICKED) { - auto* screen = static_cast(obj->user_data); - int value = screen->infiniSleepController.infiniSleepSettings.pushesToStopAlarm; - value = (value % 10) + 1; // Cycle through values 1 to 10 - screen->infiniSleepController.infiniSleepSettings.pushesToStopAlarm = value; - screen->infiniSleepController.SetSettingsChanged(); - lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d", value); - } - }); + lv_obj_set_event_cb(btnPushesToStop, btnEventHandler); - lv_obj_t* lblPushesToStopValue = lv_label_create(btnPushesToStop, nullptr); + lblPushesToStopValue = lv_label_create(btnPushesToStop, nullptr); lv_label_set_text_fmt(lblPushesToStopValue, "%d", infiniSleepController.infiniSleepSettings.pushesToStopAlarm); lv_obj_align(lblPushesToStopValue, nullptr, LV_ALIGN_CENTER, 0, 0); } @@ -535,13 +483,61 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { SetSwitchState(LV_ANIM_OFF); return; } + if (obj == btnWakeMode) { + if (infiniSleepController.infiniSleepSettings.graddualWake) { + infiniSleepController.infiniSleepSettings.graddualWake = false; + infiniSleepController.infiniSleepSettings.naturalWake = true; + } else if (infiniSleepController.infiniSleepSettings.naturalWake) { + infiniSleepController.infiniSleepSettings.naturalWake = false; + infiniSleepController.infiniSleepSettings.graddualWake = false; + } else if (!infiniSleepController.infiniSleepSettings.graddualWake && !infiniSleepController.infiniSleepSettings.naturalWake) { + infiniSleepController.infiniSleepSettings.graddualWake = true; + } + infiniSleepController.SetSettingsChanged(); + const char* mode = infiniSleepController.infiniSleepSettings.graddualWake ? "Grad." : infiniSleepController.infiniSleepSettings.naturalWake ? "Nat." : "Off"; + lv_label_set_text_static(lv_obj_get_child(obj, nullptr), mode); + return; + } + if (obj == btnCycles) { + uint8_t value = infiniSleepController.infiniSleepSettings.desiredCycles; + value = (value % 10) + 1; // Cycle through values 1 to 10 + infiniSleepController.infiniSleepSettings.desiredCycles = value; + infiniSleepController.SetSettingsChanged(); + lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d", value); + return; + } + if (obj == btnTestMotorGradual) { + motorController.GradualWakeBuzz(); + return; + } + if (obj == btnMotorStrength) { + uint8_t value = infiniSleepController.infiniSleepSettings.motorStrength; + value += 25; + if (value > 200) { + value = 100; + } + infiniSleepController.infiniSleepSettings.motorStrength = value; + infiniSleepController.SetSettingsChanged(); + lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d", value); + motorController.infiniSleepMotorStrength = value; + return; + } + if (obj == btnPushesToStop) { + uint8_t value = infiniSleepController.infiniSleepSettings.pushesToStopAlarm; + value = (value % 10) + 1; // Cycle through values 1 to 10 + infiniSleepController.infiniSleepSettings.pushesToStopAlarm = value; + infiniSleepController.SetSettingsChanged(); + lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d", value); + return; + } } } bool Sleep::OnButtonPushed() { if (infiniSleepController.IsAlerting()) { return true; - } else if (displayState != SleepDisplayState::Info) { + } + if (displayState != SleepDisplayState::Info) { displayState = SleepDisplayState::Info; UpdateDisplay(); return true; @@ -555,22 +551,23 @@ bool Sleep::StopAlarmPush() { infiniSleepController.pushesLeftToStopWakeAlarm--; UpdateDisplay(); return true; - } else { - if (infiniSleepController.isSnoozing) { - infiniSleepController.RestorePreSnoozeTime(); - } - infiniSleepController.isSnoozing = false; - StopAlerting(); - if (infiniSleepController.IsTrackerEnabled()) { - displayState = SleepDisplayState::Info; - UpdateDisplay(); - OnButtonEvent(trackerToggleBtn, LV_EVENT_CLICKED); - return true; - } + } + + if (infiniSleepController.isSnoozing) { + infiniSleepController.RestorePreSnoozeTime(); + } + infiniSleepController.isSnoozing = false; + StopAlerting(); + if (infiniSleepController.IsTrackerEnabled()) { displayState = SleepDisplayState::Info; UpdateDisplay(); + infiniSleepController.ToggleTracker(); + UpdateDisplay(); return true; } + displayState = SleepDisplayState::Info; + UpdateDisplay(); + return true; } bool Sleep::OnTouchEvent(Pinetime::Applications::TouchEvents event) { @@ -660,7 +657,7 @@ void Sleep::SetAlerting() { lv_obj_set_hidden(txtSuggestedAlarm, true); lv_obj_set_hidden(iconSuggestedAlarm, true); NRF_LOG_INFO("Alarm is alerting"); - if (infiniSleepController.infiniSleepSettings.naturalWake != true) { + if (!infiniSleepController.infiniSleepSettings.naturalWake) { taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, 120 * 1000, LV_TASK_PRIO_MID, this); } if (infiniSleepController.infiniSleepSettings.graddualWake) { @@ -668,7 +665,7 @@ void Sleep::SetAlerting() { } else if (infiniSleepController.infiniSleepSettings.naturalWake) { motorController.StartNaturalWakeAlarm(); } - if (infiniSleepController.infiniSleepSettings.naturalWake != true) { + if (!infiniSleepController.infiniSleepSettings.naturalWake) { wakeLock.Lock(); } alreadyAlerting = true; @@ -681,7 +678,7 @@ void Sleep::RedrawSetAlerting() { lv_obj_set_hidden(btnSuggestedAlarm, true); lv_obj_set_hidden(txtSuggestedAlarm, true); lv_obj_set_hidden(iconSuggestedAlarm, true); - if (infiniSleepController.infiniSleepSettings.naturalWake != true) { + if (!infiniSleepController.infiniSleepSettings.naturalWake) { wakeLock.Lock(); } } diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 7e5ce3738b..ed3d49e1a5 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -77,6 +77,9 @@ namespace Pinetime { lv_obj_t* label_sleep_cycles; lv_obj_t *btnSuggestedAlarm, *txtSuggestedAlarm, *iconSuggestedAlarm; + lv_obj_t *lblWakeMode, *btnWakeMode, *lblWakeModeValue, *lblCycles, *btnCycles, *lblCycleValue, *btnTestMotorGradual, + *lblMotorStrength, *btnMotorStrength, *lblMotorStrengthValue, *lblPushesToStop, *btnPushesToStop, *lblPushesToStopValue; + Widgets::PageIndicator pageIndicator1 = Widgets::PageIndicator(0, 3); Widgets::PageIndicator pageIndicator2 = Widgets::PageIndicator(1, 3); Widgets::PageIndicator pageIndicator3 = Widgets::PageIndicator(2, 3); From ff193befc60f408feae7df794b0b096647542af9 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 9 Dec 2024 11:09:45 -0600 Subject: [PATCH 104/123] Code Clean up removed some unused code. Didn't reduce RAM usage. --- .../infinisleep/InfiniSleepController.cpp | 128 +++++++++--------- .../infinisleep/InfiniSleepController.h | 56 ++------ src/displayapp/DisplayApp.cpp | 3 - src/displayapp/screens/Sleep.cpp | 7 +- 4 files changed, 79 insertions(+), 115 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 645f8a9083..b020fc1cea 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -70,7 +70,7 @@ void InfiniSleepController::UpdateTracker() { NRF_LOG_INFO("[InfiniSleepController] Updating tracker"); if (infiniSleepSettings.heartRateTracking) { - UpdateBPM(); + // UpdateBPM(); } systemTask->PushMessage(System::Messages::SleepTrackerUpdate); @@ -200,7 +200,7 @@ void InfiniSleepController::UpdateGradualWake() { // Calculate the period for the gradualWakeTimer if (infiniSleepSettings.graddualWake && gradualWakeStep > 0) { - int64_t gradualWakePeriod = ((SecondsToWakeAlarm() - gradualWakeSteps[-1 + gradualWakeStep])) * (configTICK_RATE_HZ); + uint64_t gradualWakePeriod = ((SecondsToWakeAlarm() - gradualWakeSteps[-1 + gradualWakeStep])) * (configTICK_RATE_HZ); xTimerChangePeriod(gradualWakeTimer, gradualWakePeriod, 0); xTimerStart(gradualWakeTimer, 0); } else { @@ -216,70 +216,70 @@ void InfiniSleepController::StopAlerting() { /* Sleep Tracking Section */ -void InfiniSleepController::UpdateBPM() { - // Get the heart rate from the controller - prevBpm = bpm; - bpm = heartRateController.HeartRate(); - - if (prevBpm != 0) - rollingBpm = (rollingBpm + bpm) / 2; - else - rollingBpm = bpm; - - // Get the current time from DateTimeController - int hours = dateTimeController.Hours(); - int minutes = dateTimeController.Minutes(); - int seconds = dateTimeController.Seconds(); - - // Log the BPM and current time - NRF_LOG_INFO("BPM: %d at %02d:%02d:%02d", rollingBpm, hours, minutes, seconds); - - // Write data to CSV - // const int motion = 0; // Placeholder for motion data - // std::tuple data[1] = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; - // WriteDataCSV(TRACKER_DATA_FILE_NAME, data, 1); -} - -void InfiniSleepController::WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const { - lfs_file_t file; - int err = fs.FileOpen(&file, fileName, LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND); - if (err < 0) { - // Handle error - NRF_LOG_INFO("Error opening file: %d", err); - return; - } - - for (int i = 0; i < dataSize; ++i) { - int hours, minutes, seconds, bpm, motion; - std::tie(hours, minutes, seconds, bpm, motion) = data[i]; - char buffer[64]; - int len = snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d,%d,%d\n", hours, minutes, seconds, bpm, motion); - err = fs.FileWrite(&file, reinterpret_cast(buffer), len); - if (err < 0) { - // Handle error - NRF_LOG_INFO("Error writing to file: %d", err); - fs.FileClose(&file); - - return; - } - } - - fs.FileClose(&file); -} +// void InfiniSleepController::UpdateBPM() { +// // Get the heart rate from the controller +// prevBpm = bpm; +// bpm = heartRateController.HeartRate(); + +// if (prevBpm != 0) +// rollingBpm = (rollingBpm + bpm) / 2; +// else +// rollingBpm = bpm; + +// // Get the current time from DateTimeController +// int hours = dateTimeController.Hours(); +// int minutes = dateTimeController.Minutes(); +// int seconds = dateTimeController.Seconds(); + +// // Log the BPM and current time +// NRF_LOG_INFO("BPM: %d at %02d:%02d:%02d", rollingBpm, hours, minutes, seconds); + +// // Write data to CSV +// // const int motion = 0; // Placeholder for motion data +// // std::tuple data[1] = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; +// // WriteDataCSV(TRACKER_DATA_FILE_NAME, data, 1); +// } + +// void InfiniSleepController::WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const { +// lfs_file_t file; +// int err = fs.FileOpen(&file, fileName, LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND); +// if (err < 0) { +// // Handle error +// NRF_LOG_INFO("Error opening file: %d", err); +// return; +// } + +// for (int i = 0; i < dataSize; ++i) { +// int hours, minutes, seconds, bpm, motion; +// std::tie(hours, minutes, seconds, bpm, motion) = data[i]; +// char buffer[64]; +// int len = snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d,%d,%d\n", hours, minutes, seconds, bpm, motion); +// err = fs.FileWrite(&file, reinterpret_cast(buffer), len); +// if (err < 0) { +// // Handle error +// NRF_LOG_INFO("Error writing to file: %d", err); +// fs.FileClose(&file); + +// return; +// } +// } + +// fs.FileClose(&file); +// } // Clear data in CSV -void InfiniSleepController::ClearDataCSV(const char* filename) const { - lfs_file_t file; - int err = fs.FileOpen(&file, filename, LFS_O_WRONLY | LFS_O_TRUNC); - if (err < 0) { - // Handle error - NRF_LOG_INFO("Error opening file: %d", err); - return; - } - - fs.FileClose(&file); - NRF_LOG_INFO("CSV data cleared"); -} +// void InfiniSleepController::ClearDataCSV(const char* filename) const { +// lfs_file_t file; +// int err = fs.FileOpen(&file, filename, LFS_O_WRONLY | LFS_O_TRUNC); +// if (err < 0) { +// // Handle error +// NRF_LOG_INFO("Error opening file: %d", err); +// return; +// } + +// fs.FileClose(&file); +// NRF_LOG_INFO("CSV data cleared"); +// } /* Sleep Tracking Section End */ diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 14355679ce..183147d302 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -98,38 +98,6 @@ namespace Pinetime { void DisableTracker(); void UpdateTracker(); - bool BodyTrackingEnabled() const { - return infiniSleepSettings.bodyTracking; - } - - void SetBodyTrackingEnabled(bool enabled) { - infiniSleepSettings.bodyTracking = enabled; - } - - bool HeartRateTrackingEnabled() const { - return infiniSleepSettings.heartRateTracking; - } - - void SetHeartRateTrackingEnabled(bool enabled) { - infiniSleepSettings.heartRateTracking = enabled; - } - - bool GradualWakeEnabled() const { - return infiniSleepSettings.graddualWake; - } - - void SetGradualWakeEnabled(bool enabled) { - infiniSleepSettings.graddualWake = enabled; - } - - bool SmartAlarmEnabled() const { - return infiniSleepSettings.smartAlarm; - } - - void SetSmartAlarmEnabled(bool enabled) { - infiniSleepSettings.smartAlarm = enabled; - } - void SetSettingsChanged() { settingsChanged = true; } @@ -149,14 +117,12 @@ namespace Pinetime { WakeAlarmSettings wakeAlarm; // Dertermine the steps for the gradual wake alarm, the corresponding vibration durations determine the power of the vibration - static constexpr uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; // In seconds - static constexpr uint16_t gradualWakeVibrationDurations[9] = {1000, 1000, 900, 800, 800, 700, 700, 700, 500}; // In ms + static constexpr uint16_t gradualWakeSteps[9] = {30, 60, 90, 120, 180, 240, 300, 350, 600}; // In seconds - int8_t gradualWakeStep = 9; // used to keep track of which step to use, in position form not idex + uint8_t gradualWakeStep = 9; // used to keep track of which step to use, in position form not idex - uint16_t GetSleepCycles() { - uint16_t totalMinutes = GetTotalSleep(); - return (totalMinutes * 100 / infiniSleepSettings.sleepCycleDuration); + uint16_t GetSleepCycles() const { + return (GetTotalSleep() * 100 / infiniSleepSettings.sleepCycleDuration); } uint16_t GetTotalSleep() const { @@ -177,7 +143,7 @@ namespace Pinetime { return sleepMinutes; } - uint16_t GetSuggestedSleepTime() { + uint16_t GetSuggestedSleepTime() const { return infiniSleepSettings.desiredCycles * infiniSleepSettings.sleepCycleDuration; } @@ -230,10 +196,6 @@ namespace Pinetime { return dateTimeController.Minutes(); } - int bpm = 0; - int prevBpm = 0; - int rollingBpm = 0; - void UpdateBPM(); uint8_t GetGradualWakeStep() const { @@ -247,6 +209,10 @@ namespace Pinetime { bool isEnabled = false; bool settingsChanged = false; + // uint8_t bpm = 0; + // uint8_t prevBpm = 0; + // uint8_t rollingBpm = 0; + Controllers::DateTime& dateTimeController; Controllers::FS& fs; Controllers::HeartRateController& heartRateController; @@ -262,8 +228,8 @@ namespace Pinetime { void SavePrevSessionData() const; // For File IO - void WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const; - void ClearDataCSV(const char* fileName) const; + // void WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const; + // void ClearDataCSV(const char* fileName) const; }; } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 2415e138d0..b9075fd798 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -359,9 +359,6 @@ void DisplayApp::Refresh() { if (infiniSleepController.IsEnabled()) { if (currentApp != Apps::Sleep) { LoadNewScreen(Apps::Sleep, DisplayApp::FullRefreshDirections::Up); - // Wait for the sleep app to load before moving on. - while (!lv_task_handler()) { - }; } } } diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index c47b7b9840..c4d4629a60 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -40,7 +40,6 @@ namespace { } } - Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, Controllers::Settings::ClockType clockType, System::SystemTask& systemTask, @@ -52,7 +51,7 @@ Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, clockType {clockType}, displayApp {displayApp} { - infiniSleepController.SetHeartRateTrackingEnabled(false); + infiniSleepController.infiniSleepSettings.heartRateTracking = false; infiniSleepController.SetSettingsChanged(); UpdateDisplay(); taskRefresh = lv_task_create(RefreshTaskCallback, 2000, LV_TASK_PRIO_MID, this); @@ -494,7 +493,9 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { infiniSleepController.infiniSleepSettings.graddualWake = true; } infiniSleepController.SetSettingsChanged(); - const char* mode = infiniSleepController.infiniSleepSettings.graddualWake ? "Grad." : infiniSleepController.infiniSleepSettings.naturalWake ? "Nat." : "Off"; + const char* mode = infiniSleepController.infiniSleepSettings.graddualWake ? "Grad." + : infiniSleepController.infiniSleepSettings.naturalWake ? "Nat." + : "Off"; lv_label_set_text_static(lv_obj_get_child(obj, nullptr), mode); return; } From edd89cf58f9922378eece8c6d14874a10d5a3235 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 9 Dec 2024 19:52:13 -0600 Subject: [PATCH 105/123] Added a both option for wake mode that allows for natural wake with pre vibrations added the similar ramping up effect to the natural wake alarm but with larger interval --- src/components/motor/MotorController.cpp | 16 ++++-- src/displayapp/screens/Sleep.cpp | 66 ++++++++++++++---------- 2 files changed, 51 insertions(+), 31 deletions(-) diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index dd4ed64b29..8a12971725 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -108,15 +108,23 @@ void MotorController::StopWakeAlarm() { } void MotorController::StartNaturalWakeAlarm() { - SetMotorStrength((60 * infiniSleepMotorStrength) / 100); - RunForDuration(280); + wakeAlarmStrength = (80 * infiniSleepMotorStrength) / 100; + wakeAlarmDuration = 100; + SetMotorStrength(wakeAlarmStrength); + RunForDuration(wakeAlarmDuration); xTimerStart(naturalWakeAlarmVib, 0); } void MotorController::NaturalWakeAlarmRing(TimerHandle_t xTimer) { auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); - motorController->SetMotorStrength((60 * motorController->infiniSleepMotorStrength) / 100); - motorController->RunForDuration(280); + if (motorController->wakeAlarmStrength > (40 * motorController->infiniSleepMotorStrength) / 100) { + motorController->wakeAlarmStrength -= (30 * motorController->infiniSleepMotorStrength) / 100; + } + if (motorController->wakeAlarmDuration < 500) { + motorController->wakeAlarmDuration += 180; + } + motorController->SetMotorStrength(motorController->wakeAlarmStrength); + motorController->RunForDuration(motorController->wakeAlarmDuration); } void MotorController::StopNaturalWakeAlarm() { diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index c4d4629a60..a2df141aa1 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -91,6 +91,8 @@ void Sleep::UpdateDisplay() { return; } + lv_task_reset(taskRefresh); + // Clear the screen lv_obj_clean(lv_scr_act()); if (infiniSleepController.IsAlerting()) { @@ -199,12 +201,12 @@ void Sleep::DrawAlarmScreen() { // lv_label_set_text_static(txtSuggestedAlarm, "Use Sugg.\nAlarmTime"); txtSuggestedAlarm = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(txtSuggestedAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -15, -10); + lv_obj_align(txtSuggestedAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -15, -13); lv_label_set_text_static(txtSuggestedAlarm, "Auto"); iconSuggestedAlarm = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(iconSuggestedAlarm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); - lv_obj_align(iconSuggestedAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -50, -10); + lv_obj_align(iconSuggestedAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -50, -13); lv_label_set_text_static(iconSuggestedAlarm, Symbols::sun); enableSwitch = lv_switch_create(lv_scr_act(), nullptr); @@ -245,7 +247,7 @@ void Sleep::DrawInfoScreen() { // Total sleep time label_total_sleep = lv_label_create(lv_scr_act(), nullptr); - uint16_t totalMinutes = infiniSleepController.GetTotalSleep(); + const uint16_t totalMinutes = infiniSleepController.GetTotalSleep(); lv_label_set_text_fmt(label_total_sleep, "Time Asleep: %dh%dm", totalMinutes / 60, totalMinutes % 60); lv_obj_align(label_total_sleep, lv_scr_act(), LV_ALIGN_CENTER, 0, -60); @@ -310,8 +312,10 @@ void Sleep::DrawInfoScreen() { // Gradual Wake info label_gradual_wake = lv_label_create(lv_scr_act(), nullptr); - if (infiniSleepController.infiniSleepSettings.graddualWake) { - lv_label_set_text_static(label_gradual_wake, "Wake Mode: Gradual"); + if (infiniSleepController.infiniSleepSettings.graddualWake && infiniSleepController.infiniSleepSettings.naturalWake) { + lv_label_set_text_static(label_gradual_wake, "Wake Mode: Both"); + } else if (infiniSleepController.infiniSleepSettings.graddualWake) { + lv_label_set_text_static(label_gradual_wake, "Wake Mode: PreWake"); } else if (infiniSleepController.infiniSleepSettings.naturalWake) { lv_label_set_text_static(label_gradual_wake, "Wake Mode: Natural"); } else { @@ -365,9 +369,11 @@ void Sleep::DrawSettingsScreen() { lv_obj_align(btnWakeMode, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 130, y_offset); btnWakeMode->user_data = this; lv_obj_set_event_cb(btnWakeMode, btnEventHandler); - const char* mode = infiniSleepController.infiniSleepSettings.graddualWake ? "Grad." - : infiniSleepController.infiniSleepSettings.naturalWake ? "Nat." - : "Off"; + const char* mode = (infiniSleepController.infiniSleepSettings.graddualWake && infiniSleepController.infiniSleepSettings.naturalWake) + ? "Both" + : infiniSleepController.infiniSleepSettings.graddualWake ? "Pre." + : infiniSleepController.infiniSleepSettings.naturalWake ? "Nat." + : "Off"; lblWakeModeValue = lv_label_create(btnWakeMode, nullptr); lv_label_set_text_static(lblWakeModeValue, mode); lv_obj_align(lblWakeModeValue, nullptr, LV_ALIGN_CENTER, 0, 0); @@ -464,13 +470,13 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } if (obj == btnSuggestedAlarm) { // Set the suggested time - uint16_t totalSuggestedMinutes = infiniSleepController.GetSuggestedSleepTime(); - uint8_t suggestedHours = totalSuggestedMinutes / 60; - uint8_t suggestedMinutes = totalSuggestedMinutes % 60; + const uint16_t totalSuggestedMinutes = infiniSleepController.GetSuggestedSleepTime(); + const uint8_t suggestedHours = totalSuggestedMinutes / 60; + const uint8_t suggestedMinutes = totalSuggestedMinutes % 60; // Time for alarm, current time + suggested sleep time - uint8_t alarmHour = (infiniSleepController.GetCurrentHour() + suggestedHours) % 24; - uint8_t alarmMinute = (infiniSleepController.GetCurrentMinute() + suggestedMinutes) % 60; + const uint8_t alarmHour = (infiniSleepController.GetCurrentHour() + suggestedHours) % 24; + const uint8_t alarmMinute = (infiniSleepController.GetCurrentMinute() + suggestedMinutes) % 60; infiniSleepController.SetWakeAlarmTime(alarmHour, alarmMinute); @@ -483,19 +489,25 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { return; } if (obj == btnWakeMode) { - if (infiniSleepController.infiniSleepSettings.graddualWake) { + if (infiniSleepController.infiniSleepSettings.graddualWake && infiniSleepController.infiniSleepSettings.naturalWake) { infiniSleepController.infiniSleepSettings.graddualWake = false; - infiniSleepController.infiniSleepSettings.naturalWake = true; - } else if (infiniSleepController.infiniSleepSettings.naturalWake) { infiniSleepController.infiniSleepSettings.naturalWake = false; + } else if (infiniSleepController.infiniSleepSettings.graddualWake) { infiniSleepController.infiniSleepSettings.graddualWake = false; + infiniSleepController.infiniSleepSettings.naturalWake = true; + } else if (infiniSleepController.infiniSleepSettings.naturalWake) { + infiniSleepController.infiniSleepSettings.naturalWake = true; + infiniSleepController.infiniSleepSettings.graddualWake = true; } else if (!infiniSleepController.infiniSleepSettings.graddualWake && !infiniSleepController.infiniSleepSettings.naturalWake) { infiniSleepController.infiniSleepSettings.graddualWake = true; + infiniSleepController.infiniSleepSettings.naturalWake = false; } infiniSleepController.SetSettingsChanged(); - const char* mode = infiniSleepController.infiniSleepSettings.graddualWake ? "Grad." - : infiniSleepController.infiniSleepSettings.naturalWake ? "Nat." - : "Off"; + const char* mode = (infiniSleepController.infiniSleepSettings.graddualWake && infiniSleepController.infiniSleepSettings.naturalWake) + ? "Both" + : infiniSleepController.infiniSleepSettings.graddualWake ? "Pre." + : infiniSleepController.infiniSleepSettings.naturalWake ? "Nat." + : "Off"; lv_label_set_text_static(lv_obj_get_child(obj, nullptr), mode); return; } @@ -624,8 +636,8 @@ void Sleep::SnoozeWakeAlarm() { NRF_LOG_INFO("Snoozing alarm for %d minutes", SNOOZE_MINUTES); - uint16_t totalAlarmMinutes = infiniSleepController.GetCurrentHour() * 60 + infiniSleepController.GetCurrentMinute(); - uint16_t newSnoozeMinutes = totalAlarmMinutes + SNOOZE_MINUTES; + const uint16_t totalAlarmMinutes = infiniSleepController.GetCurrentHour() * 60 + infiniSleepController.GetCurrentMinute(); + const uint16_t newSnoozeMinutes = totalAlarmMinutes + SNOOZE_MINUTES; infiniSleepController.SetPreSnoozeTime(); infiniSleepController.isSnoozing = true; @@ -661,10 +673,10 @@ void Sleep::SetAlerting() { if (!infiniSleepController.infiniSleepSettings.naturalWake) { taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, 120 * 1000, LV_TASK_PRIO_MID, this); } - if (infiniSleepController.infiniSleepSettings.graddualWake) { - motorController.StartWakeAlarm(); - } else if (infiniSleepController.infiniSleepSettings.naturalWake) { + if (infiniSleepController.infiniSleepSettings.naturalWake) { motorController.StartNaturalWakeAlarm(); + } else { + motorController.StartWakeAlarm(); } if (!infiniSleepController.infiniSleepSettings.naturalWake) { wakeLock.Lock(); @@ -686,10 +698,10 @@ void Sleep::RedrawSetAlerting() { void Sleep::StopAlerting(bool setSwitch) { infiniSleepController.StopAlerting(); - if (infiniSleepController.infiniSleepSettings.graddualWake) { - motorController.StopWakeAlarm(); - } else if (infiniSleepController.infiniSleepSettings.naturalWake) { + if (infiniSleepController.infiniSleepSettings.naturalWake) { motorController.StopNaturalWakeAlarm(); + } else { + motorController.StopWakeAlarm(); } if (setSwitch) { SetSwitchState(LV_ANIM_OFF); From e6bb3b156ae29ab01e682aeb1fec0594cd70e7b2 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 12 Dec 2024 18:49:02 -0600 Subject: [PATCH 106/123] Enabling tracker sets brightness to low and resets to previous brightness when stopped Also tweaked the Natural Wake Vibration a little. --- src/components/infinisleep/InfiniSleepController.cpp | 12 +++++++++--- src/components/infinisleep/InfiniSleepController.h | 6 +++++- src/components/motor/MotorController.cpp | 8 ++++++-- src/main.cpp | 4 +++- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index b020fc1cea..1e1a78cb2c 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -9,8 +9,9 @@ using namespace std::chrono_literals; InfiniSleepController::InfiniSleepController(Controllers::DateTime& dateTimeController, Controllers::FS& fs, - Controllers::HeartRateController& heartRateController) - : dateTimeController {dateTimeController}, fs {fs}, heartRateController {heartRateController} { + Controllers::HeartRateController& heartRateController, + Controllers::BrightnessController& brightnessController) + : dateTimeController {dateTimeController}, fs {fs}, heartRateController {heartRateController}, brightnessController {brightnessController} { } namespace { @@ -49,10 +50,14 @@ void InfiniSleepController::Init(System::SystemTask* systemTask) { NRF_LOG_INFO("[InfiniSleepController] Loaded wake alarm was enabled, scheduling"); ScheduleWakeAlarm(); } + + prevBrightnessLevel = brightnessController.Level(); } void InfiniSleepController::EnableTracker() { - DisableTracker(); + prevBrightnessLevel = brightnessController.Level(); + brightnessController.Set(BrightnessController::Levels::Low); + // DisableTracker(); NRF_LOG_INFO("[InfiniSleepController] Enabling tracker"); isEnabled = true; trackerUpdateTimer = @@ -61,6 +66,7 @@ void InfiniSleepController::EnableTracker() { } void InfiniSleepController::DisableTracker() { + brightnessController.Set(prevBrightnessLevel); NRF_LOG_INFO("[InfiniSleepController] Disabling tracker"); xTimerStop(trackerUpdateTimer, 0); isEnabled = false; diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 183147d302..53cf0b0ac2 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -29,7 +29,8 @@ namespace Pinetime { public: InfiniSleepController(Controllers::DateTime& dateTimeCOntroller, Controllers::FS&, - Controllers::HeartRateController& heartRateController); + Controllers::HeartRateController& heartRateController, + Controllers::BrightnessController& brightnessController); void Init(System::SystemTask* systemTask); void SaveWakeAlarm(); @@ -169,6 +170,8 @@ namespace Pinetime { return infiniSleepSettings; } + BrightnessController::Levels prevBrightnessLevel; + bool ToggleTracker() { if (isEnabled) { prevSessionData.endTimeHours = GetCurrentHour(); @@ -216,6 +219,7 @@ namespace Pinetime { Controllers::DateTime& dateTimeController; Controllers::FS& fs; Controllers::HeartRateController& heartRateController; + Controllers::BrightnessController& brightnessController; System::SystemTask* systemTask = nullptr; TimerHandle_t wakeAlarmTimer; TimerHandle_t gradualWakeTimer; diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index 8a12971725..d6c64bfd80 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -118,10 +118,14 @@ void MotorController::StartNaturalWakeAlarm() { void MotorController::NaturalWakeAlarmRing(TimerHandle_t xTimer) { auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); if (motorController->wakeAlarmStrength > (40 * motorController->infiniSleepMotorStrength) / 100) { - motorController->wakeAlarmStrength -= (30 * motorController->infiniSleepMotorStrength) / 100; + motorController->wakeAlarmStrength -= (15 * motorController->infiniSleepMotorStrength) / 100; + } else { + motorController->wakeAlarmStrength += (30 * motorController->infiniSleepMotorStrength) / 100; } if (motorController->wakeAlarmDuration < 500) { - motorController->wakeAlarmDuration += 180; + motorController->wakeAlarmDuration += 90; + } else { + motorController->wakeAlarmDuration -= 90; } motorController->SetMotorStrength(motorController->wakeAlarmStrength); motorController->RunForDuration(motorController->wakeAlarmDuration); diff --git a/src/main.cpp b/src/main.cpp index 3efc6bb59d..f60f592c63 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -105,12 +105,14 @@ Pinetime::Drivers::Watchdog watchdog; Pinetime::Controllers::NotificationManager notificationManager; Pinetime::Controllers::MotionController motionController; Pinetime::Controllers::AlarmController alarmController {dateTimeController, fs}; -Pinetime::Controllers::InfiniSleepController infiniSleepController {dateTimeController, fs, heartRateController}; Pinetime::Controllers::TouchHandler touchHandler; Pinetime::Controllers::ButtonHandler buttonHandler; Pinetime::Controllers::BrightnessController brightnessController {}; +Pinetime::Controllers::InfiniSleepController infiniSleepController {dateTimeController, fs, heartRateController, brightnessController}; + + Pinetime::Applications::DisplayApp displayApp(lcd, touchPanel, batteryController, From 604bdd3cfa50b725ec8b1a3be3956dee1af73911 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 12 Dec 2024 20:56:39 -0600 Subject: [PATCH 107/123] Opening app now sets lower brightness and restores when closing only if tracker disabled. --- src/components/infinisleep/InfiniSleepController.cpp | 3 --- src/components/infinisleep/InfiniSleepController.h | 4 ++++ src/displayapp/screens/Sleep.cpp | 8 ++++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 1e1a78cb2c..acfd189d61 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -55,8 +55,6 @@ void InfiniSleepController::Init(System::SystemTask* systemTask) { } void InfiniSleepController::EnableTracker() { - prevBrightnessLevel = brightnessController.Level(); - brightnessController.Set(BrightnessController::Levels::Low); // DisableTracker(); NRF_LOG_INFO("[InfiniSleepController] Enabling tracker"); isEnabled = true; @@ -66,7 +64,6 @@ void InfiniSleepController::EnableTracker() { } void InfiniSleepController::DisableTracker() { - brightnessController.Set(prevBrightnessLevel); NRF_LOG_INFO("[InfiniSleepController] Disabling tracker"); xTimerStop(trackerUpdateTimer, 0); isEnabled = false; diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 53cf0b0ac2..c913abcb96 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -205,6 +205,10 @@ namespace Pinetime { return (9 - gradualWakeStep) + 1; } + BrightnessController& GetBrightnessController() { + return brightnessController; + } + private: bool isAlerting = false; bool isGradualWakeAlerting = false; diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index a2df141aa1..b1e54550a0 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -59,6 +59,11 @@ Sleep::Sleep(Controllers::InfiniSleepController& infiniSleepController, lv_task_create(PressesToStopAlarmTimeoutCallback, PUSHES_TO_STOP_ALARM_TIMEOUT * 1000, LV_TASK_PRIO_MID, this); infiniSleepController.infiniSleepSettings.sleepCycleDuration = 90; infiniSleepController.SetSettingsChanged(); + + if (!infiniSleepController.IsEnabled()) { + infiniSleepController.prevBrightnessLevel = infiniSleepController.GetBrightnessController().Level(); + } + infiniSleepController.GetBrightnessController().Set(Controllers::BrightnessController::Levels::Low); } Sleep::~Sleep() { @@ -73,6 +78,9 @@ Sleep::~Sleep() { lv_obj_clean(lv_scr_act()); infiniSleepController.SaveWakeAlarm(); infiniSleepController.SaveInfiniSleepSettings(); + if (!infiniSleepController.IsEnabled()) { + infiniSleepController.GetBrightnessController().Set(infiniSleepController.prevBrightnessLevel); + } } void Sleep::DisableWakeAlarm() { From 73fb325e60795b6619d43fbf714a58a593c94ae4 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 13 Dec 2024 13:06:30 -0600 Subject: [PATCH 108/123] Fixed bug where brightness isn't low when watch turning on from sleep. --- src/displayapp/DisplayApp.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index b9075fd798..457e363ba8 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -759,6 +759,10 @@ void DisplayApp::Register(Pinetime::Controllers::NavigationService* NavigationSe } void DisplayApp::ApplyBrightness() { + if (infiniSleepController.IsEnabled() || currentApp == Apps::Sleep) { + brightnessController.Set(Controllers::BrightnessController::Levels::Low); + return; + } auto brightness = settingsController.GetBrightness(); if (brightness != Controllers::BrightnessController::Levels::Low && brightness != Controllers::BrightnessController::Levels::Medium && brightness != Controllers::BrightnessController::Levels::High) { From db4192d54b32e3583ec5b9b2e5359b5afc0e7828 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 16 Dec 2024 13:33:51 -0600 Subject: [PATCH 109/123] Updated SessionData struct and removed wakelock --- .../infinisleep/InfiniSleepController.h | 29 +++++++++++++------ src/displayapp/screens/Sleep.cpp | 12 ++++---- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index c913abcb96..7f48ff60ed 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -25,6 +25,20 @@ namespace Pinetime { } namespace Controllers { + namespace InfiniSleepControllerTypes { + // Struct for sessions + struct SessionData { + uint8_t day = 0; + uint8_t month = 0; + uint16_t year = 0; + + uint8_t startTimeHours = 0; + uint8_t startTimeMinutes = 0; + uint8_t endTimeHours = 0; + uint8_t endTimeMinutes = 0; + }; + } + class InfiniSleepController { public: InfiniSleepController(Controllers::DateTime& dateTimeCOntroller, @@ -51,15 +65,7 @@ namespace Pinetime { uint8_t preSnoozeMinutes = 255; uint8_t preSnnoozeHours = 255; - // Struct for sessions - struct SessionData { - uint8_t startTimeHours = 0; - uint8_t startTimeMinutes = 0; - uint8_t endTimeHours = 0; - uint8_t endTimeMinutes = 0; - }; - - SessionData prevSessionData; + InfiniSleepControllerTypes::SessionData prevSessionData; void SetPreSnoozeTime() { if (preSnoozeMinutes != 255 || preSnnoozeHours != 255) { @@ -180,8 +186,13 @@ namespace Pinetime { DisableTracker(); } else { // ClearDataCSV(TRACKER_DATA_FILE_NAME); + prevSessionData.endTimeHours = 255; + prevSessionData.endTimeMinutes = 255; prevSessionData.startTimeHours = GetCurrentHour(); prevSessionData.startTimeMinutes = GetCurrentMinute(); + prevSessionData.day = dateTimeController.Day(); + prevSessionData.month = static_cast(dateTimeController.Month()); + prevSessionData.year = dateTimeController.Year(); EnableTracker(); } return isEnabled; diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index b1e54550a0..9f2bcf9b7e 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -686,9 +686,9 @@ void Sleep::SetAlerting() { } else { motorController.StartWakeAlarm(); } - if (!infiniSleepController.infiniSleepSettings.naturalWake) { - wakeLock.Lock(); - } + // if (!infiniSleepController.infiniSleepSettings.naturalWake) { + // wakeLock.Lock(); + // } alreadyAlerting = true; } @@ -699,9 +699,9 @@ void Sleep::RedrawSetAlerting() { lv_obj_set_hidden(btnSuggestedAlarm, true); lv_obj_set_hidden(txtSuggestedAlarm, true); lv_obj_set_hidden(iconSuggestedAlarm, true); - if (!infiniSleepController.infiniSleepSettings.naturalWake) { - wakeLock.Lock(); - } + // if (!infiniSleepController.infiniSleepSettings.naturalWake) { + // wakeLock.Lock(); + // } } void Sleep::StopAlerting(bool setSwitch) { From ee480d1b86c391cfaf5b10789bbfc65bf871ff59 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 16 Dec 2024 21:24:37 -0600 Subject: [PATCH 110/123] Added total sleep minutes to SessionData --- .../infinisleep/InfiniSleepController.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 7f48ff60ed..3018a125c8 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -36,6 +36,8 @@ namespace Pinetime { uint8_t startTimeMinutes = 0; uint8_t endTimeHours = 0; uint8_t endTimeMinutes = 0; + + uint16_t totalSleepMinutes = 0; }; } @@ -182,10 +184,23 @@ namespace Pinetime { if (isEnabled) { prevSessionData.endTimeHours = GetCurrentHour(); prevSessionData.endTimeMinutes = GetCurrentMinute(); + + // Calculate total sleep time + uint16_t startTotalMinutes = prevSessionData.startTimeHours * 60 + prevSessionData.startTimeMinutes; + uint16_t endTotalMinutes = GetCurrentHour() * 60 + GetCurrentMinute(); + + // If end time is before start time, add 24 hours to end time (handle crossing midnight) + if (endTotalMinutes < startTotalMinutes) { + endTotalMinutes += 24 * 60; + } + + prevSessionData.totalSleepMinutes = endTotalMinutes - startTotalMinutes; + SavePrevSessionData(); DisableTracker(); } else { // ClearDataCSV(TRACKER_DATA_FILE_NAME); + prevSessionData.totalSleepMinutes = 0; prevSessionData.endTimeHours = 255; prevSessionData.endTimeMinutes = 255; prevSessionData.startTimeHours = GetCurrentHour(); From 895c276177368a7fcfd154db5190a203187ab152 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 17 Dec 2024 09:23:20 -0600 Subject: [PATCH 111/123] Added a variable to ignore button press during certion actions. I think pressing the side button as the auto snooze function is running causes a crash. --- src/displayapp/screens/Sleep.cpp | 6 ++++-- src/displayapp/screens/Sleep.h | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 9f2bcf9b7e..21b5cb1aba 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -24,13 +24,15 @@ namespace { } void SnoozeAlarmTaskCallback(lv_task_t* task) { - auto* screen = static_cast(task->user_data); lv_task_set_prio(task, LV_TASK_PRIO_OFF); + auto* screen = static_cast(task->user_data); + screen->ignoreButtonPush = true; screen->StopAlerting(false); screen->UpdateDisplay(); screen->SnoozeWakeAlarm(); screen->displayState = Sleep::SleepDisplayState::Info; screen->UpdateDisplay(); + screen->ignoreButtonPush = false; } void PressesToStopAlarmTimeoutCallback(lv_task_t* task) { @@ -555,7 +557,7 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } bool Sleep::OnButtonPushed() { - if (infiniSleepController.IsAlerting()) { + if (infiniSleepController.IsAlerting() || ignoreButtonPush) { return true; } if (displayState != SleepDisplayState::Info) { diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index ed3d49e1a5..a38194775a 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -37,6 +37,8 @@ namespace Pinetime { Controllers::InfiniSleepController& infiniSleepController; + bool ignoreButtonPush = false; + private: System::WakeLock wakeLock; Controllers::MotorController& motorController; From f3b6318e5e80f95797b1e727d8a48174d5b7cc5f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 19 Dec 2024 11:41:30 -0600 Subject: [PATCH 112/123] Moved alerting logic, shouldn't change anything. --- src/displayapp/screens/Sleep.cpp | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 21b5cb1aba..b0789e4925 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -123,6 +123,17 @@ void Sleep::UpdateDisplay() { pageIndicator3.Create(); break; } + + if (alreadyAlerting) { + RedrawSetAlerting(); + return; + } + + if (infiniSleepController.IsAlerting()) { + SetAlerting(); + } else { + SetSwitchState(LV_ANIM_OFF); + } } void Sleep::DrawAlarmScreen() { @@ -228,17 +239,6 @@ void Sleep::DrawAlarmScreen() { lv_obj_set_style_local_bg_color(enableSwitch, LV_SWITCH_PART_BG, LV_STATE_DEFAULT, bgColor); UpdateWakeAlarmTime(); - - if (alreadyAlerting) { - RedrawSetAlerting(); - return; - } - - if (infiniSleepController.IsAlerting()) { - SetAlerting(); - } else { - SetSwitchState(LV_ANIM_OFF); - } } void Sleep::DrawInfoScreen() { @@ -688,9 +688,7 @@ void Sleep::SetAlerting() { } else { motorController.StartWakeAlarm(); } - // if (!infiniSleepController.infiniSleepSettings.naturalWake) { - // wakeLock.Lock(); - // } + wakeLock.Lock(); alreadyAlerting = true; } @@ -701,9 +699,7 @@ void Sleep::RedrawSetAlerting() { lv_obj_set_hidden(btnSuggestedAlarm, true); lv_obj_set_hidden(txtSuggestedAlarm, true); lv_obj_set_hidden(iconSuggestedAlarm, true); - // if (!infiniSleepController.infiniSleepSettings.naturalWake) { - // wakeLock.Lock(); - // } + wakeLock.Lock(); } void Sleep::StopAlerting(bool setSwitch) { From ed5f8d1e998f1632fbcebfc147d4105c1876fbcf Mon Sep 17 00:00:00 2001 From: liamcharger Date: Thu, 19 Dec 2024 11:06:39 -0500 Subject: [PATCH 113/123] settings: vibrate on change of motor strength --- src/displayapp/screens/Sleep.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index b0789e4925..95e086f74b 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -543,6 +543,7 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { infiniSleepController.SetSettingsChanged(); lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d", value); motorController.infiniSleepMotorStrength = value; + motorController.GradualWakeBuzz(); return; } if (obj == btnPushesToStop) { From f09ec24522d37b9de531631f42e44a14d24cf761 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 19 Dec 2024 17:51:49 -0600 Subject: [PATCH 114/123] Bug fix and Changed Off to Normal. Bug was that the SetSwitchState was missing a check to make sure enableSwitch is available. --- src/components/infinisleep/InfiniSleepController.cpp | 12 +++++++++++- src/components/infinisleep/InfiniSleepController.h | 3 +++ src/displayapp/screens/Sleep.cpp | 12 ++++++------ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index acfd189d61..106c3b5ca4 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -368,7 +368,17 @@ void InfiniSleepController::LoadPrevSessionData() { return; } - fs.FileRead(&prevSessionFile, reinterpret_cast(&prevSessionData), sizeof(prevSessionData)); + InfiniSleepControllerTypes::SessionData tmpSessionData; + + fs.FileRead(&prevSessionFile, reinterpret_cast(&tmpSessionData), sizeof(tmpSessionData)); fs.FileClose(&prevSessionFile); + + if (tmpSessionData.version != SESSION_DATA_VERSION) { + NRF_LOG_WARNING("[InfiniSleepController] Loaded previous session data has version %u instead of %u, discarding", + tmpSessionData.version, + SESSION_DATA_VERSION); + return; + } + prevSessionData = tmpSessionData; NRF_LOG_INFO("[InfiniSleepController] Loaded previous session data"); } \ No newline at end of file diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index 3018a125c8..c9dfacddeb 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -18,6 +18,7 @@ #define SLEEP_CYCLE_DURATION 90 // sleep cycle duration in minutes #define DESIRED_CYCLES 5 // desired number of sleep cycles #define PUSHES_TO_STOP_ALARM_TIMEOUT 2 // in seconds +#define SESSION_DATA_VERSION 1 // Version of the session data struct namespace Pinetime { namespace System { @@ -38,6 +39,8 @@ namespace Pinetime { uint8_t endTimeMinutes = 0; uint16_t totalSleepMinutes = 0; + + uint8_t version = SESSION_DATA_VERSION; }; } diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 95e086f74b..d1b435b75a 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -3,7 +3,7 @@ #include "displayapp/screens/Symbols.h" #include "displayapp/InfiniTimeTheme.h" #include "components/settings/Settings.h" -#include "components/alarm/AlarmController.h" +#include "components/infinisleep/InfiniSleepController.h" #include "components/motor/MotorController.h" #include "systemtask/SystemTask.h" @@ -131,7 +131,7 @@ void Sleep::UpdateDisplay() { if (infiniSleepController.IsAlerting()) { SetAlerting(); - } else { + } else if (displayState == SleepDisplayState::Alarm) { SetSwitchState(LV_ANIM_OFF); } } @@ -329,7 +329,7 @@ void Sleep::DrawInfoScreen() { } else if (infiniSleepController.infiniSleepSettings.naturalWake) { lv_label_set_text_static(label_gradual_wake, "Wake Mode: Natural"); } else { - lv_label_set_text_static(label_gradual_wake, "Wake Mode: Off"); + lv_label_set_text_static(label_gradual_wake, "Wake Mode: Normal"); } lv_obj_align(label_gradual_wake, lv_scr_act(), LV_ALIGN_CENTER, 0, 40); lv_obj_set_style_local_text_color(label_gradual_wake, @@ -383,7 +383,7 @@ void Sleep::DrawSettingsScreen() { ? "Both" : infiniSleepController.infiniSleepSettings.graddualWake ? "Pre." : infiniSleepController.infiniSleepSettings.naturalWake ? "Nat." - : "Off"; + : "Norm."; lblWakeModeValue = lv_label_create(btnWakeMode, nullptr); lv_label_set_text_static(lblWakeModeValue, mode); lv_obj_align(lblWakeModeValue, nullptr, LV_ALIGN_CENTER, 0, 0); @@ -517,7 +517,7 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { ? "Both" : infiniSleepController.infiniSleepSettings.graddualWake ? "Pre." : infiniSleepController.infiniSleepSettings.naturalWake ? "Nat." - : "Off"; + : "Norm."; lv_label_set_text_static(lv_obj_get_child(obj, nullptr), mode); return; } @@ -724,7 +724,7 @@ void Sleep::StopAlerting(bool setSwitch) { } void Sleep::SetSwitchState(lv_anim_enable_t anim) { - if (infiniSleepController.GetWakeAlarm().isEnabled) { + if (displayState == SleepDisplayState::Alarm && infiniSleepController.GetWakeAlarm().isEnabled) { lv_switch_on(enableSwitch, anim); } else { lv_switch_off(enableSwitch, anim); From bc09fa04ad5eeb8bcf8c4a23e20f3ac4741500c3 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 20 Dec 2024 13:11:55 -0600 Subject: [PATCH 115/123] Pressing side button while alarm alerting snoozes. --- src/displayapp/screens/Sleep.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index d1b435b75a..e11138ab82 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -558,7 +558,12 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } bool Sleep::OnButtonPushed() { - if (infiniSleepController.IsAlerting() || ignoreButtonPush) { + if (ignoreButtonPush) { + return true; + } + // Side button to snooze + if (infiniSleepController.IsAlerting() && displayState == SleepDisplayState::Alarm) { + OnButtonEvent(btnSnooze, LV_EVENT_CLICKED); return true; } if (displayState != SleepDisplayState::Info) { From 08a7bb56e418bbd8cfd82d0285515387c25be06f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 20 Dec 2024 13:19:24 -0600 Subject: [PATCH 116/123] Made changes to the SnoozeAlarmTaskCallback, it uses the existing code in the OnButtonEvent function. Also made sure to delete the task in some places. --- src/displayapp/screens/Sleep.cpp | 10 +++++----- src/displayapp/screens/Sleep.h | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index e11138ab82..f47b4c99e2 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -27,11 +27,7 @@ namespace { lv_task_set_prio(task, LV_TASK_PRIO_OFF); auto* screen = static_cast(task->user_data); screen->ignoreButtonPush = true; - screen->StopAlerting(false); - screen->UpdateDisplay(); - screen->SnoozeWakeAlarm(); - screen->displayState = Sleep::SleepDisplayState::Info; - screen->UpdateDisplay(); + screen->OnButtonEvent(screen->btnSnooze, LV_EVENT_CLICKED); screen->ignoreButtonPush = false; } @@ -709,6 +705,10 @@ void Sleep::RedrawSetAlerting() { } void Sleep::StopAlerting(bool setSwitch) { + if (taskSnoozeWakeAlarm != nullptr) { + lv_task_del(taskSnoozeWakeAlarm); + taskSnoozeWakeAlarm = nullptr; + } infiniSleepController.StopAlerting(); if (infiniSleepController.infiniSleepSettings.naturalWake) { motorController.StopNaturalWakeAlarm(); diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index a38194775a..6376ca982e 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -39,13 +39,15 @@ namespace Pinetime { bool ignoreButtonPush = false; + lv_obj_t *btnSnooze; + private: System::WakeLock wakeLock; Controllers::MotorController& motorController; Controllers::Settings::ClockType clockType; DisplayApp& displayApp; - lv_obj_t *btnStop, *btnSnooze, *txtStop, *txtSnooze, /**btnRecur, *txtRecur,*/ *btnInfo, *enableSwitch; + lv_obj_t *btnStop, *txtStop, *txtSnooze, /**btnRecur, *txtRecur,*/ *btnInfo, *enableSwitch; lv_obj_t *trackerToggleBtn, *trackerToggleLabel; lv_obj_t* lblampm = nullptr; lv_obj_t* txtMessage = nullptr; From 9e2b541b93576fe081b166ac8ca61c862e2318cc Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 20 Dec 2024 13:39:09 -0600 Subject: [PATCH 117/123] Added startTimeStamp to SessionData --- src/components/infinisleep/InfiniSleepController.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/infinisleep/InfiniSleepController.h b/src/components/infinisleep/InfiniSleepController.h index c9dfacddeb..9e2ff3fb8f 100644 --- a/src/components/infinisleep/InfiniSleepController.h +++ b/src/components/infinisleep/InfiniSleepController.h @@ -18,7 +18,7 @@ #define SLEEP_CYCLE_DURATION 90 // sleep cycle duration in minutes #define DESIRED_CYCLES 5 // desired number of sleep cycles #define PUSHES_TO_STOP_ALARM_TIMEOUT 2 // in seconds -#define SESSION_DATA_VERSION 1 // Version of the session data struct +#define SESSION_DATA_VERSION 2 // Version of the session data struct namespace Pinetime { namespace System { @@ -40,6 +40,8 @@ namespace Pinetime { uint16_t totalSleepMinutes = 0; + uint32_t startTimeStamp = 0; + uint8_t version = SESSION_DATA_VERSION; }; } @@ -211,6 +213,7 @@ namespace Pinetime { prevSessionData.day = dateTimeController.Day(); prevSessionData.month = static_cast(dateTimeController.Month()); prevSessionData.year = dateTimeController.Year(); + prevSessionData.startTimeStamp = dateTimeController.CurrentDateTime().time_since_epoch().count(); EnableTracker(); } return isEnabled; From cec1bcf46f26976f35931854fc4ffc20289ffe17 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 21 Dec 2024 22:22:29 -0600 Subject: [PATCH 118/123] Added more checks in code --- src/displayapp/screens/Sleep.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index f47b4c99e2..22f96f194b 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -651,7 +651,9 @@ void Sleep::SnoozeWakeAlarm() { const uint16_t totalAlarmMinutes = infiniSleepController.GetCurrentHour() * 60 + infiniSleepController.GetCurrentMinute(); const uint16_t newSnoozeMinutes = totalAlarmMinutes + SNOOZE_MINUTES; - infiniSleepController.SetPreSnoozeTime(); + if (infiniSleepController.isSnoozing != true) { + infiniSleepController.SetPreSnoozeTime(); + } infiniSleepController.isSnoozing = true; infiniSleepController.SetWakeAlarmTime(newSnoozeMinutes / 60, newSnoozeMinutes % 60); @@ -683,6 +685,10 @@ void Sleep::SetAlerting() { lv_obj_set_hidden(iconSuggestedAlarm, true); NRF_LOG_INFO("Alarm is alerting"); if (!infiniSleepController.infiniSleepSettings.naturalWake) { + if (taskSnoozeWakeAlarm != nullptr) { + lv_task_del(taskSnoozeWakeAlarm); + taskSnoozeWakeAlarm = nullptr; + } taskSnoozeWakeAlarm = lv_task_create(SnoozeAlarmTaskCallback, 120 * 1000, LV_TASK_PRIO_MID, this); } if (infiniSleepController.infiniSleepSettings.naturalWake) { From 830f1365292e17911ffa46c75d1e3fccde3956be Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 22 Dec 2024 12:05:21 -0600 Subject: [PATCH 119/123] Showing wake mode on info screen only when alarm is active. Also applied code formatting. --- src/displayapp/screens/Sleep.cpp | 32 +++++++++++++++++--------------- src/displayapp/screens/Sleep.h | 2 +- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 22f96f194b..ccd1ea635a 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -316,22 +316,24 @@ void Sleep::DrawInfoScreen() { LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); - // Gradual Wake info - label_gradual_wake = lv_label_create(lv_scr_act(), nullptr); - if (infiniSleepController.infiniSleepSettings.graddualWake && infiniSleepController.infiniSleepSettings.naturalWake) { - lv_label_set_text_static(label_gradual_wake, "Wake Mode: Both"); - } else if (infiniSleepController.infiniSleepSettings.graddualWake) { - lv_label_set_text_static(label_gradual_wake, "Wake Mode: PreWake"); - } else if (infiniSleepController.infiniSleepSettings.naturalWake) { - lv_label_set_text_static(label_gradual_wake, "Wake Mode: Natural"); - } else { - lv_label_set_text_static(label_gradual_wake, "Wake Mode: Normal"); + // Wake Mode info + if (infiniSleepController.GetWakeAlarm().isEnabled) { + label_gradual_wake = lv_label_create(lv_scr_act(), nullptr); + if (infiniSleepController.infiniSleepSettings.graddualWake && infiniSleepController.infiniSleepSettings.naturalWake) { + lv_label_set_text_static(label_gradual_wake, "Wake Mode: Both"); + } else if (infiniSleepController.infiniSleepSettings.graddualWake) { + lv_label_set_text_static(label_gradual_wake, "Wake Mode: PreWake"); + } else if (infiniSleepController.infiniSleepSettings.naturalWake) { + lv_label_set_text_static(label_gradual_wake, "Wake Mode: Natural"); + } else { + lv_label_set_text_static(label_gradual_wake, "Wake Mode: Normal"); + } + lv_obj_align(label_gradual_wake, lv_scr_act(), LV_ALIGN_CENTER, 0, 40); + lv_obj_set_style_local_text_color(label_gradual_wake, + LV_LABEL_PART_MAIN, + LV_STATE_DEFAULT, + infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); } - lv_obj_align(label_gradual_wake, lv_scr_act(), LV_ALIGN_CENTER, 0, 40); - lv_obj_set_style_local_text_color(label_gradual_wake, - LV_LABEL_PART_MAIN, - LV_STATE_DEFAULT, - infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); // Start/Stop button trackerToggleBtn = lv_btn_create(lv_scr_act(), nullptr); diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 6376ca982e..13f8816798 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -39,7 +39,7 @@ namespace Pinetime { bool ignoreButtonPush = false; - lv_obj_t *btnSnooze; + lv_obj_t* btnSnooze; private: System::WakeLock wakeLock; From 2cacaf01a1246ed13acbe49fdbda858aa5664e9f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 12 Jul 2025 18:33:35 -0500 Subject: [PATCH 120/123] removed unhandled charging message --- src/displayapp/Messages.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index ce25df5a7b..580cc8f776 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -26,7 +26,6 @@ namespace Pinetime { GradualWakeTriggered, Chime, BleRadioEnableToggle, - OnChargingEvent, SleepTrackerUpdate, }; } From db8049e9573891b0d87422f4564c2b8fcd48d0f4 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 12 Jul 2025 21:59:18 -0500 Subject: [PATCH 121/123] Added IsAvailable to app header --- src/displayapp/screens/Sleep.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 13f8816798..1a92d4b301 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -102,6 +102,10 @@ namespace Pinetime { controllers.motorController, *controllers.displayApp); } + + static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) { + return true; + }; }; } } \ No newline at end of file From c3f7c485acda1cb35d67ffb4da24c6f1b44c2825 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 13 Jul 2025 17:11:51 -0500 Subject: [PATCH 122/123] Updated auto alarm time calculation --- src/displayapp/screens/Sleep.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index ccd1ea635a..49634d86cf 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -483,8 +483,15 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { const uint8_t suggestedMinutes = totalSuggestedMinutes % 60; // Time for alarm, current time + suggested sleep time - const uint8_t alarmHour = (infiniSleepController.GetCurrentHour() + suggestedHours) % 24; - const uint8_t alarmMinute = (infiniSleepController.GetCurrentMinute() + suggestedMinutes) % 60; + // Convert current time to total minutes since midnight + const uint16_t currentTotalMinutes = infiniSleepController.GetCurrentHour() * 60 + infiniSleepController.GetCurrentMinute(); + + // Add suggested sleep time + const uint16_t alarmTotalMinutes = (currentTotalMinutes + totalSuggestedMinutes) % (24 * 60); + + // Convert back to hours and minutes + const uint8_t alarmHour = alarmTotalMinutes / 60; + const uint8_t alarmMinute = alarmTotalMinutes % 60; infiniSleepController.SetWakeAlarmTime(alarmHour, alarmMinute); From afa8bff40b6dee40cad8d7768e1d008f0350b93a Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 13 Jul 2025 17:16:20 -0500 Subject: [PATCH 123/123] removed unused variables --- src/displayapp/screens/Sleep.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 49634d86cf..2f73f6ad37 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -479,8 +479,6 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { if (obj == btnSuggestedAlarm) { // Set the suggested time const uint16_t totalSuggestedMinutes = infiniSleepController.GetSuggestedSleepTime(); - const uint8_t suggestedHours = totalSuggestedMinutes / 60; - const uint8_t suggestedMinutes = totalSuggestedMinutes % 60; // Time for alarm, current time + suggested sleep time // Convert current time to total minutes since midnight