From 07d2599005a126ee592a57f07e6ed11feff14b34 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 2 Oct 2024 15:27:11 -0500 Subject: [PATCH 001/119] 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 b1594f197c..94737bb71c 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -30,6 +30,7 @@ #include "displayapp/screens/Weather.h" #include "displayapp/screens/PassKey.h" #include "displayapp/screens/Error.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 2104a267c0..96b9564f35 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 d78587609e..33ead23165 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -16,6 +16,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 41c383c0d4..85e3269088 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" + "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" } ], "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 bd958b285f..6bd5f0efe7 100644 --- a/src/displayapp/screens/Symbols.h +++ b/src/displayapp/screens/Symbols.h @@ -39,6 +39,7 @@ namespace Pinetime { static constexpr const char* eye = "\xEF\x81\xAE"; static constexpr const char* home = "\xEF\x80\x95"; static constexpr const char* sleep = "\xEE\xBD\x84"; + static constexpr const char* bed = "\xEF\x88\xB6"; // fontawesome_weathericons.c // static constexpr const char* sun = "\xEF\x86\x85"; From be0dca5c039e6c4d0bf481e5a78704b74263e341 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 3 Oct 2024 18:29:54 -0500 Subject: [PATCH 002/119] 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 6297c7e7ea5879ea14367cc01acca8e63e084038 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 3 Oct 2024 19:45:57 -0500 Subject: [PATCH 003/119] 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 0eadfe3b93612ffa5b1e83a56b92b5f999701eea Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 4 Oct 2024 13:43:39 -0500 Subject: [PATCH 004/119] 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 f1921eeff571bcf21ceb4443b01211fc7cba2116 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 4 Oct 2024 23:56:53 -0500 Subject: [PATCH 005/119] 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 bbfb05a939567428c122909dbbc8d078f7b59145 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 5 Oct 2024 13:30:53 -0500 Subject: [PATCH 006/119] More changes tyo get the app on the watch --- src/CMakeLists.txt | 2 ++ src/FreeRTOSConfig.h | 2 +- src/displayapp/apps/CMakeLists.txt | 12 ++++++------ src/displayapp/screens/SleepTracker.cpp | 4 ++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0a97a0158b..6701bd90fe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -395,6 +395,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 @@ -613,6 +614,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/FreeRTOSConfig.h b/src/FreeRTOSConfig.h index 67c33a34cc..930ec7644b 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 * 35) #define configMAX_TASK_NAME_LEN (4) #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 diff --git a/src/displayapp/apps/CMakeLists.txt b/src/displayapp/apps/CMakeLists.txt index 33ead23165..9eb3cc8829 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -6,17 +6,17 @@ 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::Weather") + #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Navigation") + #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 3289107ef69d2dd8ef8eda776374776379074ed6 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 6 Oct 2024 09:19:40 -0500 Subject: [PATCH 007/119] trying to decrease flash and ram size --- src/CMakeLists.txt | 10 +- src/FreeRTOSConfig.h | 2 +- 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(+), 107 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6701bd90fe..e8f4d0792a 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 @@ -456,7 +456,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 @@ -530,7 +530,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 @@ -595,7 +595,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 930ec7644b..c21629c199 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 * 35) +#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 94737bb71c..3003c45b14 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 96b9564f35..b642aad846 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 9eb3cc8829..11bb0bb34f 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -23,7 +23,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 298d92ea0d6a4c133a52207ae15aaf0c21b1cec8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 9 Oct 2024 12:36:05 -0500 Subject: [PATCH 008/119] 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 c21629c199..67c33a34cc 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 11bb0bb34f..9eb3cc8829 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -23,7 +23,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 eb013d6d1a..fee1fbf1f6 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 144e47673d630876eaf29a167a9cd151ad07e078 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 9 Oct 2024 13:46:07 -0500 Subject: [PATCH 009/119] 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/apps/CMakeLists.txt | 2 +- src/displayapp/screens/SleepTracker.cpp | 3 ++- src/systemtask/SystemTask.cpp | 2 +- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e8f4d0792a..6254b8953b 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 @@ -456,7 +456,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 @@ -595,7 +595,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 3003c45b14..94737bb71c 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 b642aad846..96b9564f35 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 9eb3cc8829..79f3431e4d 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -12,7 +12,7 @@ else () 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::Weather") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::SleepTracker") #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::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/119] 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 6254b8953b..6701bd90fe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -530,7 +530,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 79f3431e4d..17314db033 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -6,14 +6,14 @@ 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::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 636f1f256112cf0aba90590e41613f5e1e35948c Mon Sep 17 00:00:00 2001 From: Liam Willey Date: Fri, 11 Oct 2024 00:18:07 -0400 Subject: [PATCH 011/119] 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 6701bd90fe..2480518988 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -395,7 +395,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 @@ -614,7 +614,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 94737bb71c..5f507ce76a 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -30,7 +30,7 @@ #include "displayapp/screens/Weather.h" #include "displayapp/screens/PassKey.h" #include "displayapp/screens/Error.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 96b9564f35..499f43accb 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 17314db033..7d8879a4e8 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -14,7 +14,7 @@ else () 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::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 d8f024643b1b91c9f03d97f265c522ccdc5b2747 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 28 Oct 2024 01:58:22 -0500 Subject: [PATCH 012/119] 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 2480518988..0e6f3ee54b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -468,6 +468,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 @@ -537,6 +538,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 @@ -657,6 +659,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 eb013d6d1a..4ad20e5c30 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 a84fa93580aed134b3b63c1864cfe5398d069565 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 01:03:40 -0500 Subject: [PATCH 013/119] 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 5f507ce76a..33cf838972 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -83,7 +83,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}, @@ -100,6 +101,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, touchHandler {touchHandler}, filesystem {filesystem}, spiNorFlash {spiNorFlash}, + infiniSleepController {infiniSleepController}, lvgl {lcd, filesystem}, timer(this, TimerCallback), controllers {batteryController, @@ -111,6 +113,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, motorController, motionController, alarmController, + infiniSleepController, brightnessController, nullptr, filesystem, @@ -383,6 +386,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 2f276eaf9e..9009d5daee 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 d2abc8e58d..fd112e7cb2 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -22,6 +22,7 @@ namespace Pinetime { NotifyDeviceActivity, ShowPairingKey, AlarmTriggered, + WakeAlarmTriggered, Chime, BleRadioEnableToggle, OnChargingEvent, 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 4ad20e5c30..6ceb17d6ec 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 a14ced04302678a0e5670bbde87b38e64f8ca740 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 13:55:24 -0500 Subject: [PATCH 014/119] 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 b5dfc6c4cc4d5c28e66995356bc547d070fbe791 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 14:29:24 -0500 Subject: [PATCH 015/119] 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 69611aec1473a2ee5d1d1d3c2f2964dbc024bf6e Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 14:47:01 -0500 Subject: [PATCH 016/119] 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 65750b5c29c5cc377a0366e03818dbd41f4fb861 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 15:18:49 -0500 Subject: [PATCH 017/119] 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 8325fdca59581f3dd0247152dae429be3bd07c22 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 30 Oct 2024 13:25:43 -0500 Subject: [PATCH 018/119] 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 703a6a5da480b48a48071d510d0c33be7b4f6b99 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 30 Oct 2024 13:40:39 -0500 Subject: [PATCH 019/119] 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 6981d777168e2ea7c50d7245982b9e8ca4645642 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 30 Oct 2024 21:10:33 -0500 Subject: [PATCH 020/119] 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 d4a1661177d7596827b77822e8f7ac848e3baa25 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 31 Oct 2024 00:40:29 -0500 Subject: [PATCH 021/119] 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 33cf838972..8b5ee02861 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -394,6 +394,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 fd112e7cb2..042fa15ec9 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -23,6 +23,7 @@ namespace Pinetime { ShowPairingKey, AlarmTriggered, WakeAlarmTriggered, + GradualWakeTriggered, Chime, BleRadioEnableToggle, OnChargingEvent, 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 6ceb17d6ec..1e4921d891 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 4dd520e045c951f5896008339d679b83f6e5c4d8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 31 Oct 2024 10:27:30 -0500 Subject: [PATCH 022/119] 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 eb7775be488517e8d76bc7c031c3afb2281ad669 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 31 Oct 2024 11:44:46 -0500 Subject: [PATCH 023/119] 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 33706aacf2c90f26c170cd436a041cdee887e796 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 1 Nov 2024 23:57:15 -0500 Subject: [PATCH 024/119] 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 fa52821b2b641909a990ca1e9d638fb987da609d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 1 Nov 2024 23:58:07 -0500 Subject: [PATCH 025/119] 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 8b5ee02861..e286dafb03 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -401,7 +401,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 97e788a6fc6575536390968416e8d74d112b87a1 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 2 Nov 2024 11:59:27 -0500 Subject: [PATCH 026/119] 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 a90791d1ed2340e047a5043933e06096a88f380e Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 2 Nov 2024 12:01:21 -0500 Subject: [PATCH 027/119] 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 c5c5727a3655614b103a458bd5fb3f3efccd017c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 2 Nov 2024 18:24:42 -0500 Subject: [PATCH 028/119] 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 b705a093df90dacdc012a8b5f17637bd9b639847 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 2 Nov 2024 19:07:41 -0500 Subject: [PATCH 029/119] 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 41032a0cd3a254ef1bc089b545bfd145a619b546 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 00:18:54 -0600 Subject: [PATCH 030/119] 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 1e4921d891..15ca4b5ccb 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 835f5cf47fae536dbdf244faef85d0b3ba805796 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 00:37:07 -0600 Subject: [PATCH 031/119] 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 c6bff435429d8e959cf7dd064fbd13467d83d638 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 00:43:10 -0600 Subject: [PATCH 032/119] 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 0902e3e3a1c043547bdcc7bb50d24c5da470c185 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 01:16:02 -0600 Subject: [PATCH 033/119] 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 41b3e92901cea4bdc5a3c164c84f7c1033d927c1 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 01:45:05 -0600 Subject: [PATCH 034/119] 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 62292e85b44d869e0ff88d4f2042b749f1b4d6f8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 10:06:58 -0600 Subject: [PATCH 035/119] 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 388aa9982f294f33fe715f40a54081676fc26d3d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 13:22:31 -0600 Subject: [PATCH 036/119] 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 f177a81226c6fb3c1ff079cb65f4fb5eaa07a53b Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 21:44:43 -0600 Subject: [PATCH 037/119] 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 9eabb40d2077f139554872a48f2e9f02501de0fe Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 22:01:43 -0600 Subject: [PATCH 038/119] 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 ff443859050cc2a2eb93e47de4e5ca4ad09e52c0 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 6 Nov 2024 23:48:16 -0600 Subject: [PATCH 039/119] 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 | 1 + 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, 107 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 042fa15ec9..ce25df5a7b 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -27,6 +27,7 @@ namespace Pinetime { 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 15ca4b5ccb..bc92f1d83e 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -373,6 +373,9 @@ void SystemTask::Work() { nimbleController.DisableRadio(); } break; + case Messages::SleepTrackerUpdate: + displayApp.PushMessage(Pinetime::Applications::Display::Messages::SleepTrackerUpdate); + break; default: break; } From 629d95846e7d1ab8532118be3b65e077b4c7265c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 7 Nov 2024 00:09:03 -0600 Subject: [PATCH 040/119] 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 6ca4cdcb20fa36756e62a68a391560c45a036585 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 8 Nov 2024 15:06:44 -0600 Subject: [PATCH 041/119] 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 1cbb9cbedb8197fc13fc7fc35ceb0e0db36bd2a5 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 8 Nov 2024 16:43:50 -0600 Subject: [PATCH 042/119] 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 ced2ee2d3f35d84d7b2f1d6e0986bb31a9435b74 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 8 Nov 2024 16:50:50 -0600 Subject: [PATCH 043/119] 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 7d8c8d9f7e17b7b5656a53f60aacab6b69825084 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 8 Nov 2024 16:52:03 -0600 Subject: [PATCH 044/119] 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 e286dafb03..4729bdc163 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -404,6 +404,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 593bdd54c2c1300f9ba3b066900690003a3ff8e1 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 10 Nov 2024 02:57:35 -0600 Subject: [PATCH 045/119] 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 8147ffa197e98ed8c116d875b21ab2294c3773f9 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 18 Nov 2024 13:04:50 -0600 Subject: [PATCH 046/119] 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 4729bdc163..fdeba6dd09 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -401,7 +401,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 d76144ebab42b3ea06d1bae2c8d7e6cd2621187e Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 18 Nov 2024 20:52:48 -0600 Subject: [PATCH 047/119] 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 1c183903c96a79d436a37549f19dbd58fb2a1587 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 19 Nov 2024 09:53:26 -0600 Subject: [PATCH 048/119] 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 2ad5dd9d2a1ca92b99ab5322a9932f0403da4a4c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 19 Nov 2024 10:26:36 -0600 Subject: [PATCH 049/119] 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 18a4d4ef2e853426474e432f65b63b0cd1c5a1db Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 19 Nov 2024 14:17:48 -0600 Subject: [PATCH 050/119] 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 1354a197973ff11a76953ca262b1933473a0cf12 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 19 Nov 2024 20:06:27 -0600 Subject: [PATCH 051/119] 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 e896e6a17ca55e4a3576e99cbeeeb3f4cd21db39 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 20 Nov 2024 12:39:40 -0600 Subject: [PATCH 052/119] 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 c2b77d3dfa55976c9972d3b1851af0819215f3d8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 20 Nov 2024 13:23:48 -0600 Subject: [PATCH 053/119] 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 fdeba6dd09..5ecac9a14e 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -354,6 +354,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 8e56830a89123142863028c57d5ac332dfa515dd Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 21 Nov 2024 09:41:50 -0600 Subject: [PATCH 054/119] 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 797dc584a122cf6e54147dfa53e49bdae0dc8443 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 21 Nov 2024 10:31:30 -0600 Subject: [PATCH 055/119] 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 19b51e8d24cd7bb08c70499688a57f95f538beb5 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 21 Nov 2024 10:35:47 -0600 Subject: [PATCH 056/119] 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 5ecac9a14e..8a4c15076a 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -295,6 +295,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 344f5b0a6e9438dc2bac41d51bf9955947de92e4 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 21 Nov 2024 22:03:41 -0600 Subject: [PATCH 057/119] 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 8a4c15076a..5ecac9a14e 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -295,7 +295,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 bc92f1d83e..1425b308cf 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 95e868bef171920571236878b52f1b396125a87e Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 22 Nov 2024 11:41:30 -0600 Subject: [PATCH 058/119] 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 5ecac9a14e..c39e5fd045 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -406,8 +406,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 99c43fbb27fef3395cfd97f590b1138cb9c2db4e Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 22 Nov 2024 13:24:39 -0600 Subject: [PATCH 059/119] 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 67c33a34cc..4696e386f0 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 38666de7070e19098afc9d5dca6a9873c3d06e56 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 22 Nov 2024 20:10:40 -0600 Subject: [PATCH 060/119] 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 44a0ee29e3ee8668fbd4b92c436fe7be9424d248 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 23 Nov 2024 14:51:59 -0600 Subject: [PATCH 061/119] 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 3f06850639a852e1ddcfc7ab099558f3a673daab Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 23 Nov 2024 14:53:32 -0600 Subject: [PATCH 062/119] 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 c39e5fd045..2719616676 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -406,7 +406,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 3a35bd9f3ff29a8c09f08cb676a392121c4960b0 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 11:15:42 -0600 Subject: [PATCH 063/119] 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 2719616676..af2675ccf2 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -401,12 +401,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 4426c22a3cfef9f4f79b53e42cc3d58194546e5d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 11:34:38 -0600 Subject: [PATCH 064/119] 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 245ebed8abaa4485e5970e8b1eb4f3775e4c96cc Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 16:05:30 -0600 Subject: [PATCH 065/119] 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 9009d5daee..0be91e848a 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 2773f2898856e858ee9d74c543bb7f44a4659eb9 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 16:32:13 -0600 Subject: [PATCH 066/119] 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 af2675ccf2..08a524bf00 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -408,6 +408,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 25830599340777e4d35ac15236780eb7fa46d71d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 17:28:36 -0600 Subject: [PATCH 067/119] 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 47732745a8d58a92916674741b47a95e85ae1188 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 18:18:25 -0600 Subject: [PATCH 068/119] 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 466bdbed54d8f00ad732819021961180f6f11a88 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 20:23:17 -0600 Subject: [PATCH 069/119] 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 fca1c482116f437027e0c7c04d8f2d638d6ed033 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 25 Nov 2024 18:44:22 -0600 Subject: [PATCH 070/119] 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 50a9bf4970579642cdced365ad5127d06c675c73 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 25 Nov 2024 18:45:26 -0600 Subject: [PATCH 071/119] 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 8ffc94ff764cddb108a22205c45e64aa65eb3359 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 27 Nov 2024 12:51:45 -0600 Subject: [PATCH 072/119] 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 7f0a7c22b5b176d3c59ef1a9f3107a69e3e173a5 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 00:17:55 -0600 Subject: [PATCH 073/119] 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 08a524bf00..fdd3ee567f 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -497,7 +497,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 673873e6bb8aa9d78044975514b9de0e7495c069 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 00:18:57 -0600 Subject: [PATCH 074/119] 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 0e6f3ee54b..a9c3b6d8e6 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 fdd3ee567f..388be56657 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -406,8 +406,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 8b96598813ace80ff002bf74e387dbde1d498f50 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 00:32:56 -0600 Subject: [PATCH 075/119] 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 be88829ea2a038715bd9c17f82c54ae45b3ed57f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 20:13:57 -0600 Subject: [PATCH 076/119] 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 522315a491f7b318b5dac372213f09660f10e4dd Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 20:15:27 -0600 Subject: [PATCH 077/119] 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 c2f356f425d3968ff6cb4b7f87441abb48b04596 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 22:43:47 -0600 Subject: [PATCH 078/119] 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 2b3bf3865ccffa683c8529376ef740b474b85d6c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 22:47:23 -0600 Subject: [PATCH 079/119] 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 388be56657..784b6473cc 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -404,7 +404,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 1425b308cf..c574e8fd30 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 015808bff2720b696c64370e85105385545ecd5d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 22:48:30 -0600 Subject: [PATCH 080/119] 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 44fad6a50fc2bc04ddf22edca142f2f8bcd284ba Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 29 Nov 2024 21:04:49 -0600 Subject: [PATCH 081/119] 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 db2febce61fcb410ea8db2a8006df4f81fcb3d8b Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 29 Nov 2024 21:40:39 -0600 Subject: [PATCH 082/119] 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 d736f0311fda4c6a78c77f37e2042030fb77a415 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 29 Nov 2024 23:27:35 -0600 Subject: [PATCH 083/119] 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 a2de43463cd2d664fec9778b5359b55e74876ec1 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 29 Nov 2024 23:29:42 -0600 Subject: [PATCH 084/119] 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 701d08bf5fe54c4bbe3037782dc9767c10c32c29 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:17:40 -0600 Subject: [PATCH 085/119] 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 560b1185f05be29f90396e9f4677e30d154a82f0 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:22:16 -0600 Subject: [PATCH 086/119] 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 d51c3190f5524de43cd939091f213e67db840b29 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:24:12 -0600 Subject: [PATCH 087/119] 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 dc9bc3245af69fb8fa41b6408472697f746ce8ae Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:35:44 -0600 Subject: [PATCH 088/119] 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 784b6473cc..ef0218d392 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -404,11 +404,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 c574e8fd30..8136e5630a 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 59db2493a834cd756bc44ad3988fdcac2bb959dc Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:47:12 -0600 Subject: [PATCH 089/119] 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 0e719b5c190776ec794438fa24bbefdc04f2ef49 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 22:36:31 -0600 Subject: [PATCH 090/119] 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 49b5955d13b7d9aec6e94563c3bd2e194a85250a Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 22:42:59 -0600 Subject: [PATCH 091/119] 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 b0f8998fbd40e219c22f306051840fce3a7b51c0 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 22:52:54 -0600 Subject: [PATCH 092/119] 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 27b5634cf01d742ebb8e40bf7cb4ee1d6a08a348 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 1 Dec 2024 15:31:38 -0600 Subject: [PATCH 093/119] 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 0608e0f53311fcf421bdb2fa51b6a1076f5dd10e Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 1 Dec 2024 15:32:02 -0600 Subject: [PATCH 094/119] 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 2fc156b63c5aa46c6a91bfa39a39237d8bf7d3e0 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 2 Dec 2024 21:49:03 -0600 Subject: [PATCH 095/119] 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 ef0218d392..e9f19ed508 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -407,12 +407,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 b8d27b918c77e10609e6edea5658c94b6a5c1d52 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 5 Dec 2024 19:31:22 -0600 Subject: [PATCH 096/119] 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 8136e5630a..df69091bef 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 8d2e5f55b394fce04b2d87dc232b67c1bbed72e3 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 5 Dec 2024 19:41:28 -0600 Subject: [PATCH 097/119] 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 073599eb033cf97f31eeb582ff30dbc7e7a0a4ed Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 5 Dec 2024 20:04:51 -0600 Subject: [PATCH 098/119] 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 fe9f176329f8aab108dcca17e98af0f9a16a62f5 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 7 Dec 2024 12:16:40 -0600 Subject: [PATCH 099/119] 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 e9f19ed508..4f6381789b 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -357,6 +357,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 01b32557061bb1293eda66ae4422b90709044bca Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 7 Dec 2024 12:18:45 -0600 Subject: [PATCH 100/119] 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 aff5c7e01c7421d7f1f252f826b4b558dfa900d5 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 7 Dec 2024 12:20:32 -0600 Subject: [PATCH 101/119] 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 4f6381789b..f69cd63268 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -410,7 +410,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 101c0c962c5492e62ef05d5c56f3d3dcb2bb40c6 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 9 Dec 2024 00:11:41 -0600 Subject: [PATCH 102/119] 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 8cfabeae537ebad8fab32343637df332e79bb78d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 9 Dec 2024 01:11:03 -0600 Subject: [PATCH 103/119] 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 860fcb63152b5338ca330ee466835640781bd99a Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 9 Dec 2024 11:09:45 -0600 Subject: [PATCH 104/119] 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 f69cd63268..cc69664109 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -357,9 +357,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 37f81ba609a80cb16d6bb75ba4a596bcf34f3897 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 9 Dec 2024 19:52:13 -0600 Subject: [PATCH 105/119] 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 66aaaae8037e108766ba5621f107b2cf62112fc8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 12 Dec 2024 18:49:02 -0600 Subject: [PATCH 106/119] 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 14d173fa46b59406ffc3a1626601593606daff7d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 12 Dec 2024 20:56:39 -0600 Subject: [PATCH 107/119] 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 152f0281b4fb4b3342674c165245539dfb707914 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 13 Dec 2024 13:06:30 -0600 Subject: [PATCH 108/119] 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 cc69664109..1463bd2685 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -760,6 +760,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 7d1cfaef821a5e2ca890240a203c46f32cacc719 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 16 Dec 2024 13:33:51 -0600 Subject: [PATCH 109/119] 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 1892a90511ca4eea02491d61938a9b4cafcdb2eb Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 16 Dec 2024 21:24:37 -0600 Subject: [PATCH 110/119] 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 1bfd33fbd12d997db50fe5fc6d72af990e89fa33 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 17 Dec 2024 09:23:20 -0600 Subject: [PATCH 111/119] 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 cadd0f8777ac82c0b50373fc3a2b27d97dbea07e Mon Sep 17 00:00:00 2001 From: liamcharger Date: Thu, 19 Dec 2024 11:06:39 -0500 Subject: [PATCH 112/119] 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 21b5cb1aba..aafa5c2976 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 f09b548090a7198ca37bd40ebf70f7a53091878f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 19 Dec 2024 11:41:30 -0600 Subject: [PATCH 113/119] 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 a3af01732b539afdfe4e815a88d0c3d4ce1fd833 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 19 Dec 2024 17:51:49 -0600 Subject: [PATCH 114/119] 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 ee73c340a60cfe0d41c731c392bf26480382c010 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 20 Dec 2024 13:11:55 -0600 Subject: [PATCH 115/119] 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 0e0e1f564d65d612c9e5d9221cf584742970c46d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 20 Dec 2024 13:19:24 -0600 Subject: [PATCH 116/119] 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 7b8339ca967deb28c2bb1c309bf46ee04c3d68ad Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 20 Dec 2024 13:39:09 -0600 Subject: [PATCH 117/119] 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 37351cfac591235b3c1e06f9c6f2998d4a8e9437 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 21 Dec 2024 22:22:29 -0600 Subject: [PATCH 118/119] 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 578f06e45dcdf7f07a94b79b950b9eded130a3b5 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 22 Dec 2024 12:05:21 -0600 Subject: [PATCH 119/119] 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;