From d756e911716a9e75478296c152f5decc0755db10 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 2 Oct 2024 15:27:11 -0500 Subject: [PATCH 001/121] 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 91ff007959..1d48c0e913 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -31,6 +31,7 @@ #include "displayapp/screens/PassKey.h" #include "displayapp/screens/Error.h" #include "displayapp/screens/Calculator.h" +#include "displayapp/screens/SleepTracker.h" #include "drivers/Cst816s.h" #include "drivers/St7789.h" diff --git a/src/displayapp/apps/Apps.h.in b/src/displayapp/apps/Apps.h.in index e697096a65..cce85e85ed 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 33e5432385..2ba8347466 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -17,6 +17,7 @@ else () set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Weather") #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Motion") set(USERAPP_TYPES "${DEFAULT_USER_APP_TYPES}" CACHE STRING "List of user apps to build into the firmware") + set(USERAPP_TYPES "${USERAPP_TYPES}, Apps::SleepTracker") endif () if(DEFINED ENABLE_WATCHFACES) diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index fea3160572..204ca977d1 100644 --- a/src/displayapp/fonts/fonts.json +++ b/src/displayapp/fonts/fonts.json @@ -7,7 +7,7 @@ }, { "file": "FontAwesome5-Solid+Brands+Regular.woff", - "range": "0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf06e, 0xf015, 0xf00c, 0xf0f3, 0xf522, 0xf743, 0xf1ec, 0xf55a" + "range": "0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf06e, 0xf015, 0xf00c, 0xf0f3, 0xf522, 0xf743, 0xf236, 0xf1ec, 0xf55a" } ], "bpp": 1, diff --git a/src/displayapp/screens/SleepTracker.cpp b/src/displayapp/screens/SleepTracker.cpp new file mode 100644 index 0000000000..b4803be9e4 --- /dev/null +++ b/src/displayapp/screens/SleepTracker.cpp @@ -0,0 +1,21 @@ +#include "displayapp/screens/SleepTracker.h" + +using namespace Pinetime::Applications::Screens; + +SleepTracker::SleepTracker() { + lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(title, "My test application"); + lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); + lv_obj_align(title, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + + // Create the HR Data Task + +} + +SleepTracker::~SleepTracker() { + lv_obj_clean(lv_scr_act()); +} + +void SleepTracker::GetBPM() { + +} \ No newline at end of file diff --git a/src/displayapp/screens/SleepTracker.h b/src/displayapp/screens/SleepTracker.h new file mode 100644 index 0000000000..748d2cdec5 --- /dev/null +++ b/src/displayapp/screens/SleepTracker.h @@ -0,0 +1,30 @@ +#pragma once + +#include "displayapp/apps/Apps.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/Controllers.h" +#include "Symbols.h" + +namespace Pinetime { + namespace Applications { + namespace Screens { + class SleepTracker : public Screen { + public: + SleepTracker(); + ~SleepTracker() override; + + private: + void GetBPM(); + }; + } + + template <> + struct AppTraits { + static constexpr Apps app = Apps::SleepTracker; + static constexpr const char* icon = Screens::Symbols::bed; + static Screens::Screen* Create(AppControllers& controllers) { + return new Screens::SleepTracker(); + } + }; + } +} \ No newline at end of file diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index 40699b3d65..01e2c40e6c 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"; static constexpr const char* calculator = "\xEF\x87\xAC"; static constexpr const char* backspace = "\xEF\x95\x9A"; From a94bb99dc23917c6c88096080be17f591ae090dc Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 3 Oct 2024 18:29:54 -0500 Subject: [PATCH 002/121] 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 c856642126ac991d6763844308a5b1ab91246f4c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 3 Oct 2024 19:45:57 -0500 Subject: [PATCH 003/121] 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 9b80270493d7254d68c2815c14e2e241b6cf8b7a Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 4 Oct 2024 13:43:39 -0500 Subject: [PATCH 004/121] 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 44dd6eaf5669a2871b6fd9aa1e2596f84cd228d1 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 4 Oct 2024 23:56:53 -0500 Subject: [PATCH 005/121] 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 98923646a70344c0b8d4c5597c58f9efb22e99d4 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 5 Oct 2024 13:30:53 -0500 Subject: [PATCH 006/121] More changes tyo get the app on the watch --- src/CMakeLists.txt | 2 ++ src/FreeRTOSConfig.h | 1 + src/displayapp/apps/CMakeLists.txt | 12 ++++++------ src/displayapp/screens/SleepTracker.cpp | 4 ++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8651059018..2a066e7eae 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -396,6 +396,7 @@ list(APPEND SOURCE_FILES displayapp/screens/PassKey.cpp displayapp/screens/Error.cpp displayapp/screens/Alarm.cpp + displayapp/screens/SleepTracker.cpp displayapp/screens/Styles.cpp displayapp/screens/WeatherSymbols.cpp displayapp/Colors.cpp @@ -614,6 +615,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 d877705a70..930ec7644b 100644 --- a/src/FreeRTOSConfig.h +++ b/src/FreeRTOSConfig.h @@ -62,6 +62,7 @@ #define configTICK_RATE_HZ 1024 #define configMAX_PRIORITIES (3) #define configMINIMAL_STACK_SIZE (120) +#define configTOTAL_HEAP_SIZE (1024 * 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 2ba8347466..4d907c1d00 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -6,18 +6,18 @@ else () set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Timer") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Steps") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::HeartRate") - set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Music") - set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paint") - set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paddle") + #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Music") + #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paint") + #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paddle") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Twos") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Dice") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Metronome") - set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Navigation") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Calculator") - 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 51f2a2cfb75df96572b5824fa9e0a6c8c1c9b141 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 6 Oct 2024 09:19:40 -0500 Subject: [PATCH 007/121] 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 2a066e7eae..9b08aed8b3 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 @@ -457,7 +457,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 @@ -531,7 +531,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 @@ -596,7 +596,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 1d48c0e913..2a113480e2 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 cce85e85ed..08d9f4d8fc 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 4d907c1d00..3d4cfbc470 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -24,7 +24,7 @@ if(DEFINED ENABLE_WATCHFACES) set(WATCHFACE_TYPES ${ENABLE_WATCHFACES} CACHE STRING "List of watch faces to build into the firmware") else() set(DEFAULT_WATCHFACE_TYPES "WatchFace::Digital") - set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Analog") + #set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Analog") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::PineTimeStyle") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Terminal") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Infineat") diff --git a/src/displayapp/screens/SleepTracker.cpp b/src/displayapp/screens/SleepTracker.cpp index dbbff8f5dc..412db8275f 100644 --- a/src/displayapp/screens/SleepTracker.cpp +++ b/src/displayapp/screens/SleepTracker.cpp @@ -7,6 +7,7 @@ #include #include +#include using namespace Pinetime::Applications::Screens; @@ -19,7 +20,6 @@ namespace { void ClearDataCallback(lv_obj_t* btn, lv_event_t event) { if (event == LV_EVENT_CLICKED) { - // Clear data auto* screen = static_cast(lv_obj_get_user_data(btn)); screen->ClearDataCSV("SleepTracker_Data.csv"); } @@ -27,7 +27,6 @@ namespace { void GetSleepInfoCallback(lv_obj_t* btn, lv_event_t event) { if (event == LV_EVENT_CLICKED) { - // Get sleep info auto* screen = static_cast(lv_obj_get_user_data(btn)); screen->GetSleepInfo(screen->ReadDataCSV("SleepTracker_Data.csv")); } @@ -40,8 +39,8 @@ SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController wakeLock.Lock(); - static constexpr uint8_t btnWidth = 115; - static constexpr uint8_t btnHeight = 80; + constexpr uint8_t btnWidth = 115; + constexpr uint8_t btnHeight = 80; lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(title, "Sleep Tracker"); @@ -73,9 +72,7 @@ SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController lv_obj_t* txtInfo = lv_label_create(btnInfo, nullptr); lv_label_set_text(txtInfo, "?"); - - - std::vector> data = ReadDataCSV("SleepTracker_Data.csv"); + const auto data = ReadDataCSV("SleepTracker_Data.csv"); for (const auto& entry : data) { int hours, minutes, seconds, bpm, motion; std::tie(hours, minutes, seconds, bpm, motion) = entry; @@ -98,86 +95,85 @@ void SleepTracker::Refresh() { } // Convert time to minutes -double SleepTracker::ConvertToMinutes(int hours, int minutes, int seconds) { - return hours * 60 + minutes + seconds / 60.0; +float SleepTracker::ConvertToMinutes(int hours, int minutes, int seconds) const { + return hours * 60 + minutes + seconds / 60.0f; } // Get the moving average of BPM Values -std::vector SleepTracker::MovingAverage(const std::vector& bpmData, int windowSize) { - std::vector smoothedBpm; - - int n = bpmData.size(); +std::vector SleepTracker::MovingAverage(const std::vector& bpmData, int windowSize) const { + std::vector smoothedBpm; + const int n = bpmData.size(); - for (int i = 0; i < n - windowSize + 1; ++i) { - double sum = 0; - for (int j = 0; j < windowSize; ++j) { - sum += bpmData[i + j]; - } - smoothedBpm.push_back(sum / windowSize); + for (int i = 0; i < n - windowSize + 1; ++i) { + float sum = 0; + for (int j = 0; j < windowSize; ++j) { + sum += bpmData[i + j]; } + smoothedBpm.push_back(sum / windowSize); + } - return smoothedBpm; + return smoothedBpm; } // Detect the sleep regions -std::vector> SleepTracker::DetectSleepRegions(const std::vector& bpmData, const std::vector& time, double threshold) { - std::vector> sleep_regions; - double start_time = -1; - bool in_sleep = false; +std::vector> SleepTracker::DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const { + std::vector> sleep_regions; + float start_time = -1; + bool in_sleep = false; - for (unsigned int i = 0; i < bpmData.size(); ++i) { - if (bpmData[i] < threshold) { - if (!in_sleep) { - start_time = time[i]; // Mark the start of sleep - in_sleep = true; - } - } else { - if (in_sleep) { - double end_time = time[i]; // Mark the end of sleep - sleep_regions.push_back({start_time, end_time}); - in_sleep = false; - } - } + for (size_t i = 0; i < bpmData.size(); ++i) { + if (bpmData[i] < threshold) { + if (!in_sleep) { + start_time = time[i]; // Mark the start of sleep + in_sleep = true; + } + } else { + if (in_sleep) { + float end_time = time[i]; // Mark the end of sleep + sleep_regions.emplace_back(start_time, end_time); + in_sleep = false; + } } + } - // In case the last region extends to the end of the data - if (in_sleep) { - sleep_regions.push_back({start_time, time.back()}); - } + // In case the last region extends to the end of the data + if (in_sleep) { + sleep_regions.emplace_back(start_time, time.back()); + } - return sleep_regions; + return sleep_regions; } // Get Sleep Info -void SleepTracker::GetSleepInfo(std::vector> data) { - std::vector time; +void SleepTracker::GetSleepInfo(const std::vector>& data) const { + std::vector time; std::vector bpm; // Extract the time (in minutes) and bpm from the data for (const auto& entry : data) { - int hours, minutes, seconds, bpm_value, motion; - std::tie(hours, minutes, seconds, bpm_value, motion) = entry; - time.push_back(ConvertToMinutes(hours, minutes, seconds)); - bpm.push_back(bpm_value); + int hours, minutes, seconds, bpm_value, motion; + std::tie(hours, minutes, seconds, bpm_value, motion) = entry; + time.push_back(ConvertToMinutes(hours, minutes, seconds)); + bpm.push_back(bpm_value); } // Compute the moving average with a window size of 5 (15 minutes smoothing, since each data point is 3 minutes) - std::vector smoothed_bpm = MovingAverage(bpm, 5); + const auto smoothed_bpm = MovingAverage(bpm, 5); // Calculate a threshold as 80% of the average BPM - double average_bpm = std::accumulate(bpm.begin(), bpm.end(), 0.0) / bpm.size(); - double threshold = average_bpm * 0.8; + const float average_bpm = std::accumulate(bpm.begin(), bpm.end(), 0.0f) / bpm.size(); + const float threshold = average_bpm * 0.8f; // Detect multiple sleep regions - std::vector> sleep_regions = DetectSleepRegions(smoothed_bpm, time, threshold); + const auto sleep_regions = DetectSleepRegions(smoothed_bpm, time, threshold); // Output sleep regions if (!sleep_regions.empty()) { - for (const auto& region : sleep_regions) { - NRF_LOG_INFO("Sleep detected from %.2f minutes to %.2f minutes.", region.first, region.second); - } + for (const auto& region : sleep_regions) { + NRF_LOG_INFO("Sleep detected from %.2f minutes to %.2f minutes.", region.first, region.second); + } } else { - NRF_LOG_INFO("No significant sleep regions detected."); + NRF_LOG_INFO("No significant sleep regions detected."); } // Open the output file @@ -229,7 +225,6 @@ void SleepTracker::GetBPM() { rollingBpm = bpm; // Get the current time from DateTimeController - //auto now = dateTimeController.CurrentDateTime(); int hours = dateTimeController.Hours(); int minutes = dateTimeController.Minutes(); int seconds = dateTimeController.Seconds(); @@ -238,15 +233,9 @@ void SleepTracker::GetBPM() { NRF_LOG_INFO("BPM: %d at %02d:%02d:%02d", rollingBpm, hours, minutes, seconds); // Write data to CSV - int motion = 0; // Placeholder for motion data - std::vector> data = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; + const int motion = 0; // Placeholder for motion data + const std::vector> data = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; WriteDataCSV("SleepTracker_Data.csv", data); - - // if (bpm == 0) { - // lv_label_set_text_static(label_hr, "---"); - // } else { - // lv_label_set_text_fmt(label_hr, "%03d", bpm); - // } } // File IO Stuff @@ -255,7 +244,7 @@ void SleepTracker::GetBPM() { * Write data to a CSV file * Format: Time,BPM,Motion */ -void SleepTracker::WriteDataCSV(const char* fileName, const std::vector>& data) { +void SleepTracker::WriteDataCSV(const char* fileName, const std::vector>& data) const { lfs_file_t file; int err = fsController.FileOpen(&file, fileName, LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND); if (err < 0) { @@ -264,30 +253,17 @@ void SleepTracker::WriteDataCSV(const char* fileName, const std::vector(header), strlen(header)); - // if (err < 0) { - // // Handle error - // NRF_LOG_INFO("Error writing to file: %d", err); - // fsController.FileClose(&file); - // return; - // } - // } - // Write data for (const auto& entry : data) { int hours, minutes, seconds, bpm, motion; std::tie(hours, minutes, seconds, bpm, motion) = entry; char buffer[64]; int len = snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d,%d,%d\n", hours, minutes, seconds, bpm, motion); - int err = fsController.FileWrite(&file, reinterpret_cast(buffer), len); + err = fsController.FileWrite(&file, reinterpret_cast(buffer), len); if (err < 0) { // Handle error NRF_LOG_INFO("Error writing to file: %d", err); + fsController.FileClose(&file); return; } } @@ -296,7 +272,7 @@ void SleepTracker::WriteDataCSV(const char* fileName, const std::vector> SleepTracker::ReadDataCSV(const char* filename) { +std::vector> SleepTracker::ReadDataCSV(const char* filename) const { lfs_file_t file; int err = fsController.FileOpen(&file, filename, LFS_O_RDONLY); if (err < 0) { @@ -309,12 +285,6 @@ std::vector> SleepTracker::ReadDataCSV(const char buffer[128]; int bytesRead; - // Skip header - // bytesRead = fsController.FileRead(&file, reinterpret_cast(buffer), sizeof(buffer)); - // std::istringstream headerStream(buffer); - // std::string headerLine; - // std::getline(headerStream, headerLine); - // Read data while ((bytesRead = fsController.FileRead(&file, reinterpret_cast(buffer), sizeof(buffer))) > 0) { std::istringstream dataStream(buffer); @@ -340,7 +310,7 @@ std::vector> SleepTracker::ReadDataCSV(const } // Clear data in CSV -void SleepTracker::ClearDataCSV(const char* filename) { +void SleepTracker::ClearDataCSV(const char* filename) const { lfs_file_t file; int err = fsController.FileOpen(&file, filename, LFS_O_WRONLY | LFS_O_TRUNC); if (err < 0) { diff --git a/src/displayapp/screens/SleepTracker.h b/src/displayapp/screens/SleepTracker.h index 76861833c8..c120fa1932 100644 --- a/src/displayapp/screens/SleepTracker.h +++ b/src/displayapp/screens/SleepTracker.h @@ -23,19 +23,19 @@ namespace Pinetime { void GetBPM(); - void ClearDataCSV(const char* filename); + void ClearDataCSV(const char* filename) const; // Data Processing functions - double ConvertToMinutes(int hours, int minutes, int seconds); + float ConvertToMinutes(int hours, int minutes, int seconds) const; // Get the moving average of BPM Values - std::vector MovingAverage(const std::vector& bpm, int windowSize); + std::vector MovingAverage(const std::vector& bpm, int windowSize) const; // Detect the sleep regions - std::vector> DetectSleepRegions(const std::vector& bpmData, const std::vector& time, double threshold); + std::vector> DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const; // Get the sleep info - void GetSleepInfo(std::vector> data); + void GetSleepInfo(const std::vector>& data) const; // Read IO - std::vector> ReadDataCSV(const char* fileName); + std::vector> ReadDataCSV(const char* fileName) const; private: Controllers::HeartRateController& heartRateController; @@ -44,7 +44,7 @@ namespace Pinetime { Pinetime::System::WakeLock wakeLock; // For File IO - void WriteDataCSV(const char* fileName, const std::vector>& data); + void WriteDataCSV(const char* fileName, const std::vector>& data) const; int bpm = 0; int prevBpm = 0; From dab5b9d4a4ec7a6f2ad3a8f8c6ff3a5c2e84bf66 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 9 Oct 2024 12:36:05 -0500 Subject: [PATCH 008/121] 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 3d4cfbc470..4d907c1d00 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -24,7 +24,7 @@ if(DEFINED ENABLE_WATCHFACES) set(WATCHFACE_TYPES ${ENABLE_WATCHFACES} CACHE STRING "List of watch faces to build into the firmware") else() set(DEFAULT_WATCHFACE_TYPES "WatchFace::Digital") - #set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Analog") + set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Analog") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::PineTimeStyle") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Terminal") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Infineat") diff --git a/src/displayapp/screens/SleepTracker.cpp b/src/displayapp/screens/SleepTracker.cpp index 412db8275f..925381dd18 100644 --- a/src/displayapp/screens/SleepTracker.cpp +++ b/src/displayapp/screens/SleepTracker.cpp @@ -25,12 +25,12 @@ namespace { } } - void GetSleepInfoCallback(lv_obj_t* btn, lv_event_t event) { - if (event == LV_EVENT_CLICKED) { - auto* screen = static_cast(lv_obj_get_user_data(btn)); - screen->GetSleepInfo(screen->ReadDataCSV("SleepTracker_Data.csv")); - } - } + // void GetSleepInfoCallback(lv_obj_t* btn, lv_event_t event) { + // if (event == LV_EVENT_CLICKED) { + // auto* screen = static_cast(lv_obj_get_user_data(btn)); + // screen->GetSleepInfo(screen->ReadDataCSV("SleepTracker_Data.csv")); + // } + // } } @@ -64,21 +64,21 @@ SleepTracker::SleepTracker(Controllers::HeartRateController& heartRateController lv_label_set_text(txtClear, "X"); // Create the get info button - lv_obj_t* btnInfo = lv_btn_create(lv_scr_act(), nullptr); - btnInfo->user_data = this; - lv_obj_set_event_cb(btnInfo, GetSleepInfoCallback); - lv_obj_set_size(btnInfo, btnWidth, btnHeight); - lv_obj_align(btnInfo, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); - lv_obj_t* txtInfo = lv_label_create(btnInfo, nullptr); - lv_label_set_text(txtInfo, "?"); - - const auto data = ReadDataCSV("SleepTracker_Data.csv"); - for (const auto& entry : data) { - int hours, minutes, seconds, bpm, motion; - std::tie(hours, minutes, seconds, bpm, motion) = entry; - NRF_LOG_INFO("Read data: %02d:%02d:%02d, %d, %d", hours, minutes, seconds, bpm, motion); - } - NRF_LOG_INFO("-------------------------------"); + // lv_obj_t* btnInfo = lv_btn_create(lv_scr_act(), nullptr); + // btnInfo->user_data = this; + // lv_obj_set_event_cb(btnInfo, GetSleepInfoCallback); + // lv_obj_set_size(btnInfo, btnWidth, btnHeight); + // lv_obj_align(btnInfo, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + // lv_obj_t* txtInfo = lv_label_create(btnInfo, nullptr); + // lv_label_set_text(txtInfo, "?"); + + // const auto data = ReadDataCSV("SleepTracker_Data.csv"); + // for (const auto& entry : data) { + // int hours, minutes, seconds, bpm, motion; + // std::tie(hours, minutes, seconds, bpm, motion) = entry; + // NRF_LOG_INFO("Read data: %02d:%02d:%02d, %d, %d", hours, minutes, seconds, bpm, motion); + // } + // NRF_LOG_INFO("-------------------------------"); } SleepTracker::~SleepTracker() { @@ -100,119 +100,119 @@ float SleepTracker::ConvertToMinutes(int hours, int minutes, int seconds) const } // Get the moving average of BPM Values -std::vector SleepTracker::MovingAverage(const std::vector& bpmData, int windowSize) const { - std::vector smoothedBpm; - const int n = bpmData.size(); +// std::vector SleepTracker::MovingAverage(const std::vector& bpmData, int windowSize) const { +// std::vector smoothedBpm; +// const int n = bpmData.size(); - for (int i = 0; i < n - windowSize + 1; ++i) { - float sum = 0; - for (int j = 0; j < windowSize; ++j) { - sum += bpmData[i + j]; - } - smoothedBpm.push_back(sum / windowSize); - } +// for (int i = 0; i < n - windowSize + 1; ++i) { +// float sum = 0; +// for (int j = 0; j < windowSize; ++j) { +// sum += bpmData[i + j]; +// } +// smoothedBpm.push_back(sum / windowSize); +// } - return smoothedBpm; -} +// return smoothedBpm; +// } // Detect the sleep regions -std::vector> SleepTracker::DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const { - std::vector> sleep_regions; - float start_time = -1; - bool in_sleep = false; +// std::vector> SleepTracker::DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const { +// std::vector> sleep_regions; +// float start_time = -1; +// bool in_sleep = false; - for (size_t i = 0; i < bpmData.size(); ++i) { - if (bpmData[i] < threshold) { - if (!in_sleep) { - start_time = time[i]; // Mark the start of sleep - in_sleep = true; - } - } else { - if (in_sleep) { - float end_time = time[i]; // Mark the end of sleep - sleep_regions.emplace_back(start_time, end_time); - in_sleep = false; - } - } - } +// for (size_t i = 0; i < bpmData.size(); ++i) { +// if (bpmData[i] < threshold) { +// if (!in_sleep) { +// start_time = time[i]; // Mark the start of sleep +// in_sleep = true; +// } +// } else { +// if (in_sleep) { +// float end_time = time[i]; // Mark the end of sleep +// sleep_regions.emplace_back(start_time, end_time); +// in_sleep = false; +// } +// } +// } - // In case the last region extends to the end of the data - if (in_sleep) { - sleep_regions.emplace_back(start_time, time.back()); - } +// // In case the last region extends to the end of the data +// if (in_sleep) { +// sleep_regions.emplace_back(start_time, time.back()); +// } - return sleep_regions; -} +// return sleep_regions; +// } -// Get Sleep Info -void SleepTracker::GetSleepInfo(const std::vector>& data) const { - std::vector time; - std::vector bpm; +// // Get Sleep Info +// void SleepTracker::GetSleepInfo(const std::vector>& data) const { +// std::vector time; +// std::vector bpm; - // Extract the time (in minutes) and bpm from the data - for (const auto& entry : data) { - int hours, minutes, seconds, bpm_value, motion; - std::tie(hours, minutes, seconds, bpm_value, motion) = entry; - time.push_back(ConvertToMinutes(hours, minutes, seconds)); - bpm.push_back(bpm_value); - } +// // Extract the time (in minutes) and bpm from the data +// for (const auto& entry : data) { +// int hours, minutes, seconds, bpm_value, motion; +// std::tie(hours, minutes, seconds, bpm_value, motion) = entry; +// time.push_back(ConvertToMinutes(hours, minutes, seconds)); +// bpm.push_back(bpm_value); +// } - // Compute the moving average with a window size of 5 (15 minutes smoothing, since each data point is 3 minutes) - const auto smoothed_bpm = MovingAverage(bpm, 5); +// // Compute the moving average with a window size of 5 (15 minutes smoothing, since each data point is 3 minutes) +// const auto smoothed_bpm = MovingAverage(bpm, 5); - // Calculate a threshold as 80% of the average BPM - const float average_bpm = std::accumulate(bpm.begin(), bpm.end(), 0.0f) / bpm.size(); - const float threshold = average_bpm * 0.8f; +// // Calculate a threshold as 80% of the average BPM +// const float average_bpm = std::accumulate(bpm.begin(), bpm.end(), 0.0f) / bpm.size(); +// const float threshold = average_bpm * 0.8f; - // Detect multiple sleep regions - const auto sleep_regions = DetectSleepRegions(smoothed_bpm, time, threshold); +// // Detect multiple sleep regions +// const auto sleep_regions = DetectSleepRegions(smoothed_bpm, time, threshold); - // Output sleep regions - if (!sleep_regions.empty()) { - for (const auto& region : sleep_regions) { - NRF_LOG_INFO("Sleep detected from %.2f minutes to %.2f minutes.", region.first, region.second); - } - } else { - NRF_LOG_INFO("No significant sleep regions detected."); - } - - // Open the output file - lfs_file_t file; - int err = fsController.FileOpen(&file, "SleepTracker_SleepInfo.csv", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC); - if (err < 0) { - // Handle error - NRF_LOG_INFO("Error opening file: %d", err); - return; - } - - // Write sleep regions to the file - if (!sleep_regions.empty()) { - for (const auto& region : sleep_regions) { - char buffer[64]; - int len = snprintf(buffer, sizeof(buffer), "Sleep detected from %.2f minutes to %.2f minutes.\n", region.first, region.second); - err = fsController.FileWrite(&file, reinterpret_cast(buffer), len); - if (err < 0) { - // Handle error - NRF_LOG_INFO("Error writing to file: %d", err); - fsController.FileClose(&file); - return; - } - } - } else { - const char* noSleepMsg = "No significant sleep regions detected.\n"; - err = fsController.FileWrite(&file, reinterpret_cast(noSleepMsg), strlen(noSleepMsg)); - if (err < 0) { - // Handle error - NRF_LOG_INFO("Error writing to file: %d", err); - fsController.FileClose(&file); - return; - } - } - - // Close the file - fsController.FileClose(&file); - NRF_LOG_INFO("Sleep info written to SleepTracker_SleepInfo.csv"); -} +// // Output sleep regions +// if (!sleep_regions.empty()) { +// for (const auto& region : sleep_regions) { +// NRF_LOG_INFO("Sleep detected from %.2f minutes to %.2f minutes.", region.first, region.second); +// } +// } else { +// NRF_LOG_INFO("No significant sleep regions detected."); +// } + +// // Open the output file +// lfs_file_t file; +// int err = fsController.FileOpen(&file, "SleepTracker_SleepInfo.csv", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC); +// if (err < 0) { +// // Handle error +// NRF_LOG_INFO("Error opening file: %d", err); +// return; +// } + +// // Write sleep regions to the file +// if (!sleep_regions.empty()) { +// for (const auto& region : sleep_regions) { +// char buffer[64]; +// int len = snprintf(buffer, sizeof(buffer), "Sleep detected from %.2f minutes to %.2f minutes.\n", region.first, region.second); +// err = fsController.FileWrite(&file, reinterpret_cast(buffer), len); +// if (err < 0) { +// // Handle error +// NRF_LOG_INFO("Error writing to file: %d", err); +// fsController.FileClose(&file); +// return; +// } +// } +// } else { +// const char* noSleepMsg = "No significant sleep regions detected.\n"; +// err = fsController.FileWrite(&file, reinterpret_cast(noSleepMsg), strlen(noSleepMsg)); +// if (err < 0) { +// // Handle error +// NRF_LOG_INFO("Error writing to file: %d", err); +// fsController.FileClose(&file); +// return; +// } +// } + +// // Close the file +// fsController.FileClose(&file); +// NRF_LOG_INFO("Sleep info written to SleepTracker_SleepInfo.csv"); +// } void SleepTracker::GetBPM() { // Get the heart rate from the controller @@ -234,8 +234,8 @@ void SleepTracker::GetBPM() { // Write data to CSV const int motion = 0; // Placeholder for motion data - const std::vector> data = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; - WriteDataCSV("SleepTracker_Data.csv", data); + std::tuple data[1] = {std::make_tuple(hours, minutes, seconds, bpm, motion)}; + WriteDataCSV("SleepTracker_Data.csv", data, 1); } // File IO Stuff @@ -244,7 +244,7 @@ void SleepTracker::GetBPM() { * Write data to a CSV file * Format: Time,BPM,Motion */ -void SleepTracker::WriteDataCSV(const char* fileName, const std::vector>& data) const { +void SleepTracker::WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const { lfs_file_t file; int err = fsController.FileOpen(&file, fileName, LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND); if (err < 0) { @@ -253,10 +253,9 @@ void SleepTracker::WriteDataCSV(const char* fileName, const std::vector(buffer), len); @@ -272,42 +271,42 @@ void SleepTracker::WriteDataCSV(const char* fileName, const std::vector> SleepTracker::ReadDataCSV(const char* filename) const { - lfs_file_t file; - int err = fsController.FileOpen(&file, filename, LFS_O_RDONLY); - if (err < 0) { - // Handle error - NRF_LOG_INFO("Error opening file: %d", err); - return {}; - } - - std::vector> data; - char buffer[128]; - int bytesRead; - - // Read data - while ((bytesRead = fsController.FileRead(&file, reinterpret_cast(buffer), sizeof(buffer))) > 0) { - std::istringstream dataStream(buffer); - std::string line; - while (std::getline(dataStream, line)) { - int hours, minutes, seconds, bpm, motion; - char colon1, colon2, comma1, comma2; - std::istringstream lineStream(line); - if (lineStream >> hours >> colon1 >> minutes >> colon2 >> seconds >> comma1 >> bpm >> comma2 >> motion) { - if (colon1 == ':' && colon2 == ':' && comma1 == ',' && comma2 == ',') { - data.emplace_back(hours, minutes, seconds, bpm, motion); - } else { - NRF_LOG_INFO("Parsing error: incorrect format in line: %s", line.c_str()); - } - } else { - NRF_LOG_INFO("Parsing error: failed to parse line: %s", line.c_str()); - } - } - } - - fsController.FileClose(&file); - return data; -} +// std::vector> SleepTracker::ReadDataCSV(const char* filename) const { +// lfs_file_t file; +// int err = fsController.FileOpen(&file, filename, LFS_O_RDONLY); +// if (err < 0) { +// // Handle error +// NRF_LOG_INFO("Error opening file: %d", err); +// return {}; +// } + +// std::vector> data; +// char buffer[128]; +// int bytesRead; + +// // Read data +// while ((bytesRead = fsController.FileRead(&file, reinterpret_cast(buffer), sizeof(buffer))) > 0) { +// std::istringstream dataStream(buffer); +// std::string line; +// while (std::getline(dataStream, line)) { +// int hours, minutes, seconds, bpm, motion; +// char colon1, colon2, comma1, comma2; +// std::istringstream lineStream(line); +// if (lineStream >> hours >> colon1 >> minutes >> colon2 >> seconds >> comma1 >> bpm >> comma2 >> motion) { +// if (colon1 == ':' && colon2 == ':' && comma1 == ',' && comma2 == ',') { +// data.emplace_back(hours, minutes, seconds, bpm, motion); +// } else { +// NRF_LOG_INFO("Parsing error: incorrect format in line: %s", line.c_str()); +// } +// } else { +// NRF_LOG_INFO("Parsing error: failed to parse line: %s", line.c_str()); +// } +// } +// } + +// fsController.FileClose(&file); +// return data; +// } // Clear data in CSV void SleepTracker::ClearDataCSV(const char* filename) const { diff --git a/src/displayapp/screens/SleepTracker.h b/src/displayapp/screens/SleepTracker.h index c120fa1932..11196fb3a4 100644 --- a/src/displayapp/screens/SleepTracker.h +++ b/src/displayapp/screens/SleepTracker.h @@ -7,9 +7,9 @@ #include "systemtask/WakeLock.h" #include "Symbols.h" -#include -#include // for accumulate -#include // for abs +//#include +//#include // for accumulate +//#include // for abs namespace Pinetime { namespace Applications { @@ -28,14 +28,14 @@ namespace Pinetime { // Data Processing functions float ConvertToMinutes(int hours, int minutes, int seconds) const; // Get the moving average of BPM Values - std::vector MovingAverage(const std::vector& bpm, int windowSize) const; + //std::vector MovingAverage(const std::vector& bpm, int windowSize) const; // Detect the sleep regions - std::vector> DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const; + //std::vector> DetectSleepRegions(const std::vector& bpmData, const std::vector& time, float threshold) const; // Get the sleep info - void GetSleepInfo(const std::vector>& data) const; + //void GetSleepInfo(const std::vector>& data) const; // Read IO - std::vector> ReadDataCSV(const char* fileName) const; + //std::vector> ReadDataCSV(const char* fileName) const; private: Controllers::HeartRateController& heartRateController; @@ -44,7 +44,7 @@ namespace Pinetime { Pinetime::System::WakeLock wakeLock; // For File IO - void WriteDataCSV(const char* fileName, const std::vector>& data) const; + void WriteDataCSV(const char* fileName, const std::tuple* data, int dataSize) const; int bpm = 0; int prevBpm = 0; diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 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 26d10c3a142f931b86f91ae19ff07e7f764eba53 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 9 Oct 2024 13:46:07 -0500 Subject: [PATCH 009/121] 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 9b08aed8b3..8f74b90ebd 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 @@ -457,7 +457,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 @@ -596,7 +596,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 2a113480e2..1d48c0e913 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 08d9f4d8fc..cce85e85ed 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 4d907c1d00..25f2cff87d 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -13,7 +13,7 @@ else () 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::Calculator") - #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/121] 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 8f74b90ebd..2a066e7eae 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -531,7 +531,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 25f2cff87d..3b992b0381 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -6,15 +6,15 @@ else () set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Timer") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Steps") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::HeartRate") - #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Music") - #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paint") - #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paddle") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Music") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paint") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paddle") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Twos") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Dice") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Metronome") set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Calculator") 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 b74f4c8ef8a8077b683455b84b58063f6e2c522f Mon Sep 17 00:00:00 2001 From: Liam Willey Date: Fri, 11 Oct 2024 00:18:07 -0400 Subject: [PATCH 011/121] 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 2a066e7eae..3bc6a21228 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -396,7 +396,7 @@ list(APPEND SOURCE_FILES displayapp/screens/PassKey.cpp displayapp/screens/Error.cpp displayapp/screens/Alarm.cpp - displayapp/screens/SleepTracker.cpp + displayapp/screens/Sleep.cpp displayapp/screens/Styles.cpp displayapp/screens/WeatherSymbols.cpp displayapp/Colors.cpp @@ -615,7 +615,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 1d48c0e913..aaa958ec02 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -31,7 +31,7 @@ #include "displayapp/screens/PassKey.h" #include "displayapp/screens/Error.h" #include "displayapp/screens/Calculator.h" -#include "displayapp/screens/SleepTracker.h" +#include "displayapp/screens/Sleep.h" #include "drivers/Cst816s.h" #include "drivers/St7789.h" diff --git a/src/displayapp/apps/Apps.h.in b/src/displayapp/apps/Apps.h.in index cce85e85ed..0598bf7974 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 3b992b0381..799da36f71 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -15,7 +15,7 @@ else () set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Calculator") 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 5000fe47f85258cd10c538f97488ebb3411e13c0 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 28 Oct 2024 01:58:22 -0500 Subject: [PATCH 012/121] 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 3bc6a21228..d1a3c1f461 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -469,6 +469,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 @@ -538,6 +539,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 @@ -658,6 +660,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 0341e53e6f3edfbf691ce854a69c5b4035dbd6c2 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 01:03:40 -0500 Subject: [PATCH 013/121] 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 aaa958ec02..7492714080 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -84,7 +84,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}, @@ -101,6 +102,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, touchHandler {touchHandler}, filesystem {filesystem}, spiNorFlash {spiNorFlash}, + infiniSleepController {infiniSleepController}, lvgl {lcd, filesystem}, timer(this, TimerCallback), controllers {batteryController, @@ -112,6 +114,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, motorController, motionController, alarmController, + infiniSleepController, brightnessController, nullptr, filesystem, @@ -388,6 +391,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 ed48ba56d20bc36107d8490ff1056ae0d1f38fcc Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 13:55:24 -0500 Subject: [PATCH 014/121] 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 a3f22021fe5f0b71c06bf38742a9f04529d78ff1 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 14:29:24 -0500 Subject: [PATCH 015/121] 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 6611f5d47a24a234bcbd94b21694f2d13d910ac7 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 14:47:01 -0500 Subject: [PATCH 016/121] 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 8dd662814629df0619906e762a8a88e49b9ed0f6 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 29 Oct 2024 15:18:49 -0500 Subject: [PATCH 017/121] 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 c419741b0933ab3570285250327f10f2e5be43bd Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 30 Oct 2024 13:25:43 -0500 Subject: [PATCH 018/121] 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 2697598d82987f4425ff8f513e6a188cebd61f07 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 30 Oct 2024 13:40:39 -0500 Subject: [PATCH 019/121] 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 7096ed92d77da0b93a221927329da80d0f7f5f76 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 30 Oct 2024 21:10:33 -0500 Subject: [PATCH 020/121] 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 34edbe30d637685832337c65561ba50fff8e20db Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 31 Oct 2024 00:40:29 -0500 Subject: [PATCH 021/121] 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 7492714080..2e05e43068 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -399,6 +399,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 598f9bfe36c0319344661e0bf38dd853ff51bc8c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 31 Oct 2024 10:27:30 -0500 Subject: [PATCH 022/121] 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 17306bab0adaf748b7bba6ef96875d1f64ab2c82 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 31 Oct 2024 11:44:46 -0500 Subject: [PATCH 023/121] 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 6083660f3044d42902981b46b7229d0e2546c02c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 1 Nov 2024 23:57:15 -0500 Subject: [PATCH 024/121] 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 1b00dfa4a54560e61429a9f09e9da12d89bcd073 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 1 Nov 2024 23:58:07 -0500 Subject: [PATCH 025/121] 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 2e05e43068..021badc3c6 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(static_cast(3000)); + motorController.RunForDuration(GRADUAL_WAKE_MOTOR_DURATION_MS); NRF_LOG_INFO("Gradual wake triggered"); break; case Messages::ShowPairingKey: From b4e5eda083eab44cd9ee167b528be48bafca2119 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 2 Nov 2024 11:59:27 -0500 Subject: [PATCH 026/121] 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 76087231955924a40b0f6e3475cbbf2e39bd0b8c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 2 Nov 2024 12:01:21 -0500 Subject: [PATCH 027/121] 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 7adc02e934b69aa0f0c10db3288cc29fa5579685 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 2 Nov 2024 18:24:42 -0500 Subject: [PATCH 028/121] 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 604cd66c30d3c32399950921dbb11041ecbdc1f6 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 2 Nov 2024 19:07:41 -0500 Subject: [PATCH 029/121] 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 74b969bb97d3ed5dfac4f87866e08ab676e3b392 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 00:18:54 -0600 Subject: [PATCH 030/121] 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 0a399317f8f7a13743da82a178f5f27753f363e1 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 00:37:07 -0600 Subject: [PATCH 031/121] 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 ddde24662f85104fbdbdffd18aa83e36f2abfab8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 00:43:10 -0600 Subject: [PATCH 032/121] 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 5a414adcf877ede93c79f85c50f6d62bbe1c6baf Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 01:16:02 -0600 Subject: [PATCH 033/121] 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 3f0f8436c8e4a215a112a1d0152da4cddd1792cd Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 01:45:05 -0600 Subject: [PATCH 034/121] 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 c6fcabd9b2191ab0ebc9a825fe84573986d45e30 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 10:06:58 -0600 Subject: [PATCH 035/121] 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 38fa50dce3450ceb76b1a8c7fabce777a8e7f8c4 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 13:22:31 -0600 Subject: [PATCH 036/121] 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 52eb558a87140efa67d0e1f9f625a51f0c350b80 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 21:44:43 -0600 Subject: [PATCH 037/121] 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 bbaa0b5cc735ae84933a6fed0a3129909fca825a Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 4 Nov 2024 22:01:43 -0600 Subject: [PATCH 038/121] 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 b373b36d867d0c79c9c7675cff77bd99f0770982 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 6 Nov 2024 23:48:16 -0600 Subject: [PATCH 039/121] 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 0fe62f64ce157757789f6ad260ecbd4e1534b7ba Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 7 Nov 2024 00:09:03 -0600 Subject: [PATCH 040/121] 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 aaeeeaa71e3e8e64182a32d9c03a243bb81adda5 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 8 Nov 2024 15:06:44 -0600 Subject: [PATCH 041/121] 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 aa09ce6ef35bc16af3df2d110475e06c8a17ddf2 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 8 Nov 2024 16:43:50 -0600 Subject: [PATCH 042/121] 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 941f7a65fb4d5e3131954cd73bd7843fccc1275f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 8 Nov 2024 16:50:50 -0600 Subject: [PATCH 043/121] 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 4aedcb6b9057842f48cf629617d8c12cf866fdf1 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 8 Nov 2024 16:52:03 -0600 Subject: [PATCH 044/121] 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 021badc3c6..3860c0db03 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -409,6 +409,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 d3c7ef72dab75f8c2c73eb67bf71143c61aff93d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 10 Nov 2024 02:57:35 -0600 Subject: [PATCH 045/121] 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 712cc971d6f815f05f4c5c45b8c2bf37255b2744 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 18 Nov 2024 13:04:50 -0600 Subject: [PATCH 046/121] 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 3860c0db03..e2aeca4b02 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(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 d463f7296b6bc66bf2a3df4c2da1ff5fd22b75cf Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 18 Nov 2024 20:52:48 -0600 Subject: [PATCH 047/121] 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 1ed2d53dd387459c39afeadc52c1e9cb90f9e1c9 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 19 Nov 2024 09:53:26 -0600 Subject: [PATCH 048/121] 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 36f7cc627c309c52fa57c481a85e52041be42018 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 19 Nov 2024 10:26:36 -0600 Subject: [PATCH 049/121] 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 e2dbaa5fcdaf8b6d1cd59266ed9f84accdf9c912 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 19 Nov 2024 14:17:48 -0600 Subject: [PATCH 050/121] 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 22eb68d3fda3bcc64c3f317fc12782dc7530e8d6 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 19 Nov 2024 20:06:27 -0600 Subject: [PATCH 051/121] 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 63f4868df028200e6aeefb206c8cedf96a7b8adc Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 20 Nov 2024 12:39:40 -0600 Subject: [PATCH 052/121] 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 83698fbbc35e2111210640142caae55ce6a74809 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 20 Nov 2024 13:23:48 -0600 Subject: [PATCH 053/121] 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 e2aeca4b02..57bb413abc 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -355,6 +355,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 db9e140b07f50f5fe9937a942be889c6f5e0d180 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 21 Nov 2024 09:41:50 -0600 Subject: [PATCH 054/121] 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 33c2b692cb795e3222fe36f3e1eb2e2a546e49d1 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 21 Nov 2024 10:31:30 -0600 Subject: [PATCH 055/121] 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 d193cba69c672392f617ee9cc6bc81b9cc2be439 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 21 Nov 2024 10:35:47 -0600 Subject: [PATCH 056/121] 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 57bb413abc..2fe973177c 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -296,6 +296,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 5b7010e2429b19e9a73b1d22f2852fe7a7540636 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 21 Nov 2024 22:03:41 -0600 Subject: [PATCH 057/121] 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 2fe973177c..57bb413abc 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -296,7 +296,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 130c126d8e6eed59387c666e25e4c530a26a315d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 22 Nov 2024 11:41:30 -0600 Subject: [PATCH 058/121] 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 57bb413abc..17d6e37fe6 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -411,8 +411,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 c7dbd42783fa32df8780e9d253e0d6c7ad15aa56 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 22 Nov 2024 13:24:39 -0600 Subject: [PATCH 059/121] 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 9efc8c77ebae7c983e036dfc437431210299b97f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 22 Nov 2024 20:10:40 -0600 Subject: [PATCH 060/121] 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 e94c5ac367349f8ef3bfb4e2436589de38a20050 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 23 Nov 2024 14:51:59 -0600 Subject: [PATCH 061/121] 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 3872d91a8314c7eae8711ddceed52c0ae27a7533 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 23 Nov 2024 14:53:32 -0600 Subject: [PATCH 062/121] 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 17d6e37fe6..7fc99609e3 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -411,7 +411,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 22bad14a9d43738a16b0b093276cb9d4e58aeff8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 11:15:42 -0600 Subject: [PATCH 063/121] 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 7fc99609e3..05982bdc55 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -406,12 +406,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 d0b79390b163dde3efe679ddec81bf8fe739ed40 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 11:34:38 -0600 Subject: [PATCH 064/121] 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 fb1c98cdac932e38e1576ee2c59ac88e4238f58a Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 16:05:30 -0600 Subject: [PATCH 065/121] 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 6c98e7c76fe96e60630d805bbd578b11dd8a8625 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 16:32:13 -0600 Subject: [PATCH 066/121] 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 05982bdc55..881271ff97 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -413,6 +413,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 217a3f236664950d938d25a22b17688e017c2999 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 17:28:36 -0600 Subject: [PATCH 067/121] 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 e26bc2f860e155d6d3b0ff33da37d5d1f8039095 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 18:18:25 -0600 Subject: [PATCH 068/121] 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 1d940c4c7aa2fb9d2691cf4c482abccfc864e58d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 24 Nov 2024 20:23:17 -0600 Subject: [PATCH 069/121] 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 cbfc620377e6f4c3e8693d05b9c85be13d735289 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 25 Nov 2024 18:44:22 -0600 Subject: [PATCH 070/121] 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 bc6111bfe7b7a6dde59c87d9d19723ebfb4f885c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 25 Nov 2024 18:45:26 -0600 Subject: [PATCH 071/121] 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 d558ba6e0269226c4643a215853e3e01e16fa2d8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 27 Nov 2024 12:51:45 -0600 Subject: [PATCH 072/121] 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 ebe0789b70aafd8004be03019424b7876aef3e9f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 00:17:55 -0600 Subject: [PATCH 073/121] 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 881271ff97..0757b76f1b 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -502,7 +502,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 67b9626bce09c1ee449ad7cdccde6abb9b6148aa Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 00:18:57 -0600 Subject: [PATCH 074/121] 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 d1a3c1f461..7e03d66386 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 0757b76f1b..e26000b474 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -411,8 +411,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 bdff6b21b60708de747212369464e0901bdb2c2f Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 00:32:56 -0600 Subject: [PATCH 075/121] 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 0056765724309cf06bd557609c4aad105ea48f85 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 20:13:57 -0600 Subject: [PATCH 076/121] 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 443e51546a5178fe27ad184560023a8753704f05 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 20:15:27 -0600 Subject: [PATCH 077/121] 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 fe64c51765af88b0a00bcfa2127c45ea88f2cd1d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 22:43:47 -0600 Subject: [PATCH 078/121] 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 592b6a97aab031751fb5b3e603dc0dd2d13e2c07 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 22:47:23 -0600 Subject: [PATCH 079/121] 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 e26000b474..3fb39e189a 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -409,7 +409,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 c363068f74c876da6101f663d987ff8d5c3b8641 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 28 Nov 2024 22:48:30 -0600 Subject: [PATCH 080/121] 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 721cbce73f85710b082ddb45e3591b08e35cc7bb Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 29 Nov 2024 21:04:49 -0600 Subject: [PATCH 081/121] 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 92b9d420c295fd8be74f9f7b4d8859a36e194672 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 29 Nov 2024 21:40:39 -0600 Subject: [PATCH 082/121] 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 b1551490163e957497c42ae328a655fe7fe3e3ec Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 29 Nov 2024 23:27:35 -0600 Subject: [PATCH 083/121] 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 00fdf38384d6a3dc0c6438f54daba7dd76d201f0 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 29 Nov 2024 23:29:42 -0600 Subject: [PATCH 084/121] 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 147828a1a6eeffebc77363996366b9f1a6916a7e Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:17:40 -0600 Subject: [PATCH 085/121] 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 f1f7f962cbb5074b99a256605e9e104c4a57d11c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:22:16 -0600 Subject: [PATCH 086/121] 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 f064fcf17085548e1b2d6fa1c80db34f29f1f45b Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:24:12 -0600 Subject: [PATCH 087/121] 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 363653b35336d29e608875028d1a87ecaa1f299a Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:35:44 -0600 Subject: [PATCH 088/121] 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 3fb39e189a..b44fdfab4a 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -409,11 +409,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 209409f77b4907266f2aaa00d9677e43897b0bf5 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 16:47:12 -0600 Subject: [PATCH 089/121] 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 d7910326afe9a9e8b6ab4f45e061a8cc0cc913b9 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 22:36:31 -0600 Subject: [PATCH 090/121] 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 c31711c52981c8cc025498a807be25d6b66b546d Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 22:42:59 -0600 Subject: [PATCH 091/121] 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 ba01b635c570ffa9a4022226391876c5ea2fcff7 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 30 Nov 2024 22:52:54 -0600 Subject: [PATCH 092/121] 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 032b348edf1842b664ef98b53c7927d0e6254210 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 1 Dec 2024 15:31:38 -0600 Subject: [PATCH 093/121] 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 8a6ede814b07220afa27a20a7129d6af2590b275 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 1 Dec 2024 15:32:02 -0600 Subject: [PATCH 094/121] 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 72971e106d7428d0b9a5395d207a27916a552176 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 2 Dec 2024 21:49:03 -0600 Subject: [PATCH 095/121] 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 b44fdfab4a..7a65a81f29 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -412,12 +412,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 fdf2c36758c29ea7ce3ef14a498b4d5cb8fda160 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 5 Dec 2024 19:31:22 -0600 Subject: [PATCH 096/121] 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 eb23cee8a2abce1bab4b64dc5806c90bc2ec0337 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 5 Dec 2024 19:41:28 -0600 Subject: [PATCH 097/121] 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 15667533a92493e924bba320016f0518e9c17837 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 5 Dec 2024 20:04:51 -0600 Subject: [PATCH 098/121] 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 4e47d5c4dcea3279772c9ee4bf5ccd98d34818d0 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 7 Dec 2024 12:16:40 -0600 Subject: [PATCH 099/121] 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 7a65a81f29..57e52cd709 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -358,6 +358,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 4947c3ceb2ffe892c4e2a3545846d1b64178f6e4 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 7 Dec 2024 12:18:45 -0600 Subject: [PATCH 100/121] 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 e844df402eccfc3138c11858d8e51da0fdd43633 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 7 Dec 2024 12:20:32 -0600 Subject: [PATCH 101/121] 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 57e52cd709..eee0912379 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -415,7 +415,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 859d6553849d9e04f28c967d20081f46b4c3b5be Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 9 Dec 2024 00:11:41 -0600 Subject: [PATCH 102/121] 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 bc04168ddec4f10c06bce32ee994b67f9485ae04 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 9 Dec 2024 01:11:03 -0600 Subject: [PATCH 103/121] 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 15c032406781bbe311d1d2f0edf927315f85b5e0 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 9 Dec 2024 11:09:45 -0600 Subject: [PATCH 104/121] 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 eee0912379..65e5b32396 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -358,9 +358,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 9a11466bd8c28431afe5c3554b0c35126e5b129a Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 9 Dec 2024 19:52:13 -0600 Subject: [PATCH 105/121] 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 7717341d750ed2c25c1ca138dcb1490e85788eb3 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 12 Dec 2024 18:49:02 -0600 Subject: [PATCH 106/121] 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 614a16d575ce9146ad78006ae489b24f051970ac Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 12 Dec 2024 20:56:39 -0600 Subject: [PATCH 107/121] 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 36741efe2aea978e56086eb78d793472ac2e15df Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 13 Dec 2024 13:06:30 -0600 Subject: [PATCH 108/121] 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 65e5b32396..a4fee2f50a 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -767,6 +767,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 8bb5a56beafa7bb3ff210327ab484ae915840c75 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 16 Dec 2024 13:33:51 -0600 Subject: [PATCH 109/121] 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 ad269dfc9c30a5bfcacc36f129de115429a545fe Mon Sep 17 00:00:00 2001 From: cyberneel Date: Mon, 16 Dec 2024 21:24:37 -0600 Subject: [PATCH 110/121] 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 d44bf2cbbeba369b88b8ec8ab4b14c1b67ea991e Mon Sep 17 00:00:00 2001 From: cyberneel Date: Tue, 17 Dec 2024 09:23:20 -0600 Subject: [PATCH 111/121] 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 f649dade7012028d9d186b1e0e2886734d829443 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 19 Dec 2024 11:41:30 -0600 Subject: [PATCH 112/121] 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 ac5a84c4497e178a967d5b2167baeb8bcc618ee2 Mon Sep 17 00:00:00 2001 From: liamcharger Date: Thu, 19 Dec 2024 11:06:39 -0500 Subject: [PATCH 113/121] settings: vibrate on change of motor strength --- src/displayapp/screens/Sleep.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index b0789e4925..95e086f74b 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -543,6 +543,7 @@ void Sleep::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { infiniSleepController.SetSettingsChanged(); lv_label_set_text_fmt(lv_obj_get_child(obj, nullptr), "%d", value); motorController.infiniSleepMotorStrength = value; + motorController.GradualWakeBuzz(); return; } if (obj == btnPushesToStop) { From 760204d441ae260e02d0bf14d64df38ead289fc8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Thu, 19 Dec 2024 17:51:49 -0600 Subject: [PATCH 114/121] 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 ab2c5f38c7280279ba28f4416ca752b61811cb15 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 20 Dec 2024 13:11:55 -0600 Subject: [PATCH 115/121] 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 87b06d1ec861d8b3dba8004f5edb17f383866770 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 20 Dec 2024 13:19:24 -0600 Subject: [PATCH 116/121] 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 9e0a62369592c55701a9858e455f1916d946bf9c Mon Sep 17 00:00:00 2001 From: cyberneel Date: Fri, 20 Dec 2024 13:39:09 -0600 Subject: [PATCH 117/121] 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 eac2b890a32e6a2f0198bc195695549ef9aa3cd8 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sat, 21 Dec 2024 22:22:29 -0600 Subject: [PATCH 118/121] 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 28d74b02f6a28b113a1ff97ec7cbd1959593d277 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Sun, 22 Dec 2024 12:05:21 -0600 Subject: [PATCH 119/121] Showing wake mode on info screen only when alarm is active. Also applied code formatting. --- src/displayapp/screens/Sleep.cpp | 32 +++++++++++++++++--------------- src/displayapp/screens/Sleep.h | 2 +- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/displayapp/screens/Sleep.cpp b/src/displayapp/screens/Sleep.cpp index 22f96f194b..ccd1ea635a 100644 --- a/src/displayapp/screens/Sleep.cpp +++ b/src/displayapp/screens/Sleep.cpp @@ -316,22 +316,24 @@ void Sleep::DrawInfoScreen() { LV_STATE_DEFAULT, infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); - // Gradual Wake info - label_gradual_wake = lv_label_create(lv_scr_act(), nullptr); - if (infiniSleepController.infiniSleepSettings.graddualWake && infiniSleepController.infiniSleepSettings.naturalWake) { - lv_label_set_text_static(label_gradual_wake, "Wake Mode: Both"); - } else if (infiniSleepController.infiniSleepSettings.graddualWake) { - lv_label_set_text_static(label_gradual_wake, "Wake Mode: PreWake"); - } else if (infiniSleepController.infiniSleepSettings.naturalWake) { - lv_label_set_text_static(label_gradual_wake, "Wake Mode: Natural"); - } else { - lv_label_set_text_static(label_gradual_wake, "Wake Mode: Normal"); + // Wake Mode info + if (infiniSleepController.GetWakeAlarm().isEnabled) { + label_gradual_wake = lv_label_create(lv_scr_act(), nullptr); + if (infiniSleepController.infiniSleepSettings.graddualWake && infiniSleepController.infiniSleepSettings.naturalWake) { + lv_label_set_text_static(label_gradual_wake, "Wake Mode: Both"); + } else if (infiniSleepController.infiniSleepSettings.graddualWake) { + lv_label_set_text_static(label_gradual_wake, "Wake Mode: PreWake"); + } else if (infiniSleepController.infiniSleepSettings.naturalWake) { + lv_label_set_text_static(label_gradual_wake, "Wake Mode: Natural"); + } else { + lv_label_set_text_static(label_gradual_wake, "Wake Mode: Normal"); + } + lv_obj_align(label_gradual_wake, lv_scr_act(), LV_ALIGN_CENTER, 0, 40); + lv_obj_set_style_local_text_color(label_gradual_wake, + LV_LABEL_PART_MAIN, + LV_STATE_DEFAULT, + infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); } - lv_obj_align(label_gradual_wake, lv_scr_act(), LV_ALIGN_CENTER, 0, 40); - lv_obj_set_style_local_text_color(label_gradual_wake, - LV_LABEL_PART_MAIN, - LV_STATE_DEFAULT, - infiniSleepController.IsEnabled() ? LV_COLOR_RED : LV_COLOR_WHITE); // Start/Stop button trackerToggleBtn = lv_btn_create(lv_scr_act(), nullptr); diff --git a/src/displayapp/screens/Sleep.h b/src/displayapp/screens/Sleep.h index 6376ca982e..13f8816798 100644 --- a/src/displayapp/screens/Sleep.h +++ b/src/displayapp/screens/Sleep.h @@ -39,7 +39,7 @@ namespace Pinetime { bool ignoreButtonPush = false; - lv_obj_t *btnSnooze; + lv_obj_t* btnSnooze; private: System::WakeLock wakeLock; From 83712f584078ad773699368003602161fec77070 Mon Sep 17 00:00:00 2001 From: Darius Arnold Date: Mon, 3 Mar 2025 20:15:10 +0000 Subject: [PATCH 120/121] Increase version to 1.16 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e0fbe3d4a..78bd7b7b92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10) set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release") -project(pinetime VERSION 1.15.0 LANGUAGES C CXX ASM) +project(pinetime VERSION 1.16.0 LANGUAGES C CXX ASM) set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 20) From 6f183aaac93b88bf3787d3a95199c3a6ae86fb54 Mon Sep 17 00:00:00 2001 From: Darius Arnold Date: Mon, 3 Mar 2025 20:43:01 +0000 Subject: [PATCH 121/121] Format code --- src/components/infinisleep/InfiniSleepController.cpp | 5 ++++- src/displayapp/screens/SystemInfo.cpp | 1 + src/main.cpp | 1 - 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/infinisleep/InfiniSleepController.cpp b/src/components/infinisleep/InfiniSleepController.cpp index 106c3b5ca4..7e388c3a22 100644 --- a/src/components/infinisleep/InfiniSleepController.cpp +++ b/src/components/infinisleep/InfiniSleepController.cpp @@ -11,7 +11,10 @@ InfiniSleepController::InfiniSleepController(Controllers::DateTime& dateTimeCont Controllers::FS& fs, Controllers::HeartRateController& heartRateController, Controllers::BrightnessController& brightnessController) - : dateTimeController {dateTimeController}, fs {fs}, heartRateController {heartRateController}, brightnessController {brightnessController} { + : dateTimeController {dateTimeController}, + fs {fs}, + heartRateController {heartRateController}, + brightnessController {brightnessController} { } namespace { diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index 886dacb6c6..f208a4fd86 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -180,6 +180,7 @@ std::unique_ptr SystemInfo::CreateScreen2() { extern int mallocFailedCount; extern int stackOverflowCount; + std::unique_ptr SystemInfo::CreateScreen3() { lv_mem_monitor_t mon; lv_mem_monitor(&mon); diff --git a/src/main.cpp b/src/main.cpp index f60f592c63..2fe699b63c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -112,7 +112,6 @@ Pinetime::Controllers::BrightnessController brightnessController {}; Pinetime::Controllers::InfiniSleepController infiniSleepController {dateTimeController, fs, heartRateController, brightnessController}; - Pinetime::Applications::DisplayApp displayApp(lcd, touchPanel, batteryController,