From 1770866d5ec5911f022d0f0238a6bf447885d823 Mon Sep 17 00:00:00 2001 From: minacode Date: Sat, 3 Dec 2022 23:09:24 +0100 Subject: [PATCH 001/194] add int calculator --- src/CMakeLists.txt | 1 + src/displayapp/DisplayApp.cpp | 1 + src/displayapp/screens/Calculator.cpp | 160 ++++++++++++++++++++++++++ src/displayapp/screens/Calculator.h | 31 +++++ 4 files changed, 193 insertions(+) create mode 100644 src/displayapp/screens/Calculator.cpp create mode 100644 src/displayapp/screens/Calculator.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fd8ece62a6..29fdb94637 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -380,6 +380,7 @@ list(APPEND SOURCE_FILES displayapp/screens/Metronome.cpp displayapp/screens/Motion.cpp displayapp/screens/Weather.cpp + displayapp/screens/Calculator.cpp displayapp/screens/FirmwareValidation.cpp displayapp/screens/ApplicationList.cpp displayapp/screens/Notifications.cpp diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 3fd34b3a8c..ad63d36aef 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -30,6 +30,7 @@ #include "displayapp/screens/Weather.h" #include "displayapp/screens/PassKey.h" #include "displayapp/screens/Error.h" +#include "displayapp/screens/Calculator.h" #include "drivers/Cst816s.h" #include "drivers/St7789.h" diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp new file mode 100644 index 0000000000..8a9def68dd --- /dev/null +++ b/src/displayapp/screens/Calculator.cpp @@ -0,0 +1,160 @@ +#include "Calculator.h" +#include + + +using namespace Pinetime::Applications::Screens; + + +static void eventHandler(lv_obj_t* obj, lv_event_t event) { + auto app = static_cast(obj->user_data); + app->OnButtonEvent(obj, event); +} + +Calculator::~Calculator() { + lv_obj_clean(lv_scr_act()); +} + +static const char* buttonMap[] = { + "7", "8", "9", "<", "\n", + "4", "5", "6", "+-", "\n", + "1", "2", "3", "*/", "\n", + ".", "0", "=", "^", "" +}; + +Calculator::Calculator(DisplayApp* app) : Screen(app) { + resultLabel = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_long_mode(resultLabel, LV_LABEL_LONG_CROP); + lv_label_set_align(resultLabel, LV_LABEL_ALIGN_RIGHT); + lv_label_set_text(resultLabel, "0"); + lv_obj_set_size(resultLabel, 190, 20); + lv_obj_set_pos(resultLabel, 10, 10); + + valueLabel = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_long_mode(valueLabel, LV_LABEL_LONG_CROP); + lv_label_set_align(valueLabel, LV_LABEL_ALIGN_RIGHT); + lv_label_set_text(valueLabel, "0"); + lv_obj_set_size(valueLabel, 190, 20); + lv_obj_set_pos(valueLabel, 10, 40); + + operationLabel = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(operationLabel, ""); + lv_obj_set_size(operationLabel, 20, 20); + lv_obj_set_pos(operationLabel, 210, 40); + + buttonMatrix = lv_btnmatrix_create(lv_scr_act(), nullptr); + buttonMatrix->user_data = this; + lv_obj_set_event_cb(buttonMatrix, eventHandler); + lv_btnmatrix_set_map(buttonMatrix, buttonMap); + lv_obj_set_size(buttonMatrix, 240, 180); + lv_obj_align(buttonMatrix, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0); +} + +void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { + if (event == LV_EVENT_CLICKED) { + if (obj == buttonMatrix) { + const char* buttonText = lv_btnmatrix_get_active_btn_text(obj); + + // we only compare the first char because it is enough + switch (*buttonText) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + // *buttonText is the first char in buttonText + // "- '0'" results in the int value of the char + // *10 shifts the value one digit to the left so we can add the new digit + value = (value * 10) + (*buttonText - '0'); + break; + + case '.': + break; + + // for every operator we: + // - eval the current operator if value > 0 + // - then set the new operator + // - + and - as well as * and / cycle on the same button + case '+': + if (value != 0) { + Eval(); + } + if (operation == '+') { + operation = '-'; + } else { + operation = '+'; + } + break; + case '*': + if (value != 0) { + Eval(); + } + if (operation == '*') { + operation = '/'; + } else { + operation = '*'; + } + break; + case '^': + if (value != 0) { + Eval(); + } + operation = '^'; + break; + + case '<': + if (value > 0) { + value = 0; + } else { + result = 0; + } + operation = ' '; + break; + case '=': + Eval(); + operation = ' '; + break; + } + lv_label_set_text_fmt(valueLabel, "%d", value); + lv_label_set_text_fmt(resultLabel, "%d", result); + lv_label_set_text(operationLabel, &operation); + } + } +} + +void Calculator::Eval() { + switch (operation) { + case ' ': + case '=': + result = value; + value = 0; + break; + case '+': + result += value; + value = 0; + break; + case '-': + result -= value; + value = 0; + break; + case '*': + result *= value; + value = 0; + break; + case '/': + if (value != 0) { + result /= value; + value = 0; + } + break; + case '^': + result = pow(result, value); + value = 0; + break; + } + operation = ' '; +} diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h new file mode 100644 index 0000000000..c90b1b387a --- /dev/null +++ b/src/displayapp/screens/Calculator.h @@ -0,0 +1,31 @@ +#pragma once + +#include "Screen.h" + + +namespace Pinetime { + namespace Applications { + namespace Screens { + class Calculator : public Screen { + public: + ~Calculator() override; + + Calculator(DisplayApp* app); + + void OnButtonEvent(lv_obj_t* obj, lv_event_t event); + + private: + lv_obj_t* buttonMatrix; + lv_obj_t* valueLabel; + lv_obj_t* resultLabel; + lv_obj_t* operationLabel; + + void Eval(); + + int value = 0; + int result = 0; + char operation = ' '; + }; + } + } +} From e0cd8f60deb26a699f22ed3ab743363f7b508c7c Mon Sep 17 00:00:00 2001 From: Max Friedrich Date: Sun, 4 Dec 2022 01:38:21 +0100 Subject: [PATCH 002/194] Fix comparison --- src/displayapp/screens/Calculator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 8a9def68dd..152a5748a3 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -107,7 +107,7 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { break; case '<': - if (value > 0) { + if (value != 0) { value = 0; } else { result = 0; From ba9d4772ffb4b21d2a67a6e76e68faebfb425287 Mon Sep 17 00:00:00 2001 From: minacode Date: Sun, 4 Dec 2022 13:10:01 +0100 Subject: [PATCH 003/194] add offset --- src/displayapp/screens/Calculator.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index c90b1b387a..2d12e68fff 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -22,8 +22,10 @@ namespace Pinetime { void Eval(); - int value = 0; - int result = 0; + static constexpr FIXED_POINT_OFFSET = 1000; + + long int value = 0; + long int result = 0; char operation = ' '; }; } From 1aec3afdfadfa90170dd27e4ebe3ab07232681db Mon Sep 17 00:00:00 2001 From: minacode Date: Sun, 4 Dec 2022 14:12:18 +0100 Subject: [PATCH 004/194] added fixed point numbers, pow is still broken --- src/displayapp/screens/Calculator.cpp | 56 ++++++++++++++++++++++----- src/displayapp/screens/Calculator.h | 3 +- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 152a5748a3..bd4908a47f 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -1,5 +1,6 @@ #include "Calculator.h" #include +#include using namespace Pinetime::Applications::Screens; @@ -25,19 +26,19 @@ Calculator::Calculator(DisplayApp* app) : Screen(app) { resultLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(resultLabel, LV_LABEL_LONG_CROP); lv_label_set_align(resultLabel, LV_LABEL_ALIGN_RIGHT); - lv_label_set_text(resultLabel, "0"); + lv_label_set_text_fmt(resultLabel, "%d", result); lv_obj_set_size(resultLabel, 190, 20); lv_obj_set_pos(resultLabel, 10, 10); valueLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(valueLabel, LV_LABEL_LONG_CROP); lv_label_set_align(valueLabel, LV_LABEL_ALIGN_RIGHT); - lv_label_set_text(valueLabel, "0"); + lv_label_set_text_fmt(valueLabel, "%d", value); lv_obj_set_size(valueLabel, 190, 20); lv_obj_set_pos(valueLabel, 10, 40); operationLabel = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_static(operationLabel, ""); + lv_label_set_text_static(operationLabel, &operation); lv_obj_set_size(operationLabel, 20, 20); lv_obj_set_pos(operationLabel, 210, 40); @@ -66,17 +67,32 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { case '7': case '8': case '9': + // if this is true, we already pressed the . button + if (offset < FIXED_POINT_OFFSET) { + value += offset * (*buttonText - '0'); + offset /= 10; + } else { + value *= 10; + value += offset * (*buttonText - '0'); + } // *buttonText is the first char in buttonText // "- '0'" results in the int value of the char - // *10 shifts the value one digit to the left so we can add the new digit - value = (value * 10) + (*buttonText - '0'); + NRF_LOG_INFO(". offset: %d", offset); + NRF_LOG_INFO(". value: %d", value); + NRF_LOG_INFO(". result: %d", result); break; case '.': + if (offset == FIXED_POINT_OFFSET) { + offset /= 10; + } + NRF_LOG_INFO(". offset: %d", offset); + NRF_LOG_INFO(". value: %d", value); + NRF_LOG_INFO(". result: %d", result); break; // for every operator we: - // - eval the current operator if value > 0 + // - eval the current operator if value > FIXED_POINT_OFFSET // - then set the new operator // - + and - as well as * and / cycle on the same button case '+': @@ -119,9 +135,23 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { operation = ' '; break; } - lv_label_set_text_fmt(valueLabel, "%d", value); - lv_label_set_text_fmt(resultLabel, "%d", result); - lv_label_set_text(operationLabel, &operation); + + // show values, spare . if no remainder + int valueRemainder = value % FIXED_POINT_OFFSET; + if (valueRemainder || offset < FIXED_POINT_OFFSET) { + lv_label_set_text_fmt(valueLabel, "%d.%d", value / FIXED_POINT_OFFSET, valueRemainder); + } else { + lv_label_set_text_fmt(valueLabel, "%d", value / FIXED_POINT_OFFSET); + } + int resultRemainder = result % FIXED_POINT_OFFSET; + if (resultRemainder) { + lv_label_set_text_fmt(resultLabel, "%d.%d", result / FIXED_POINT_OFFSET, resultRemainder); + } else { + lv_label_set_text_fmt(resultLabel, "%d", result / FIXED_POINT_OFFSET); + } + + // show operation + lv_label_set_text_static(operationLabel, &operation); } } } @@ -143,18 +173,24 @@ void Calculator::Eval() { break; case '*': result *= value; + // fixed point offset was multiplied too + result /= FIXED_POINT_OFFSET; value = 0; break; case '/': - if (value != 0) { + if (value != FIXED_POINT_OFFSET) { + // fixed point offset will be divided too + result *= FIXED_POINT_OFFSET; result /= value; value = 0; } break; + // TODO pow is totally broken with fixed point numbers case '^': result = pow(result, value); value = 0; break; } operation = ' '; + offset = FIXED_POINT_OFFSET; } diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 2d12e68fff..b74ff7bd1a 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -22,7 +22,8 @@ namespace Pinetime { void Eval(); - static constexpr FIXED_POINT_OFFSET = 1000; + static constexpr int FIXED_POINT_OFFSET = 1000; + int offset = FIXED_POINT_OFFSET; long int value = 0; long int result = 0; From 9d4ad4e619c329d585d978e846914b784fc194af Mon Sep 17 00:00:00 2001 From: minacode Date: Sun, 4 Dec 2022 15:51:56 +0100 Subject: [PATCH 005/194] added pow with floats --- src/displayapp/screens/Calculator.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index bd4908a47f..40ad565446 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -185,9 +185,18 @@ void Calculator::Eval() { value = 0; } break; - // TODO pow is totally broken with fixed point numbers + + // we use floats here because pow with fixed point numbers is weird case '^': - result = pow(result, value); + float tmp_value = (float)value; + tmp_value /= FIXED_POINT_OFFSET; + + float tmp_result = (float)result; + tmp_result /= FIXED_POINT_OFFSET; + + tmp_result = pow(tmp_result, tmp_value); + result = (long) (tmp_result * FIXED_POINT_OFFSET); + value = 0; break; } From f2e6e835a4b8a75f0c19abe430dd9367403d30c3 Mon Sep 17 00:00:00 2001 From: minacode Date: Mon, 5 Dec 2022 17:34:49 +0100 Subject: [PATCH 006/194] added calculator symbol --- src/displayapp/fonts/fonts.json | 2 +- src/displayapp/screens/Symbols.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index 41c383c0d4..61546450a6 100644 --- a/src/displayapp/fonts/fonts.json +++ b/src/displayapp/fonts/fonts.json @@ -7,7 +7,7 @@ }, { "file": "FontAwesome5-Solid+Brands+Regular.woff", - "range": "0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf06e, 0xf015, 0xf00c, 0xf0f3, 0xf522, 0xf743" + "range": "0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf201, 0xf06e, 0xf015, 0xf00c, 0xf1ec, 0xf743" } ], "bpp": 1, diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index bd958b285f..f3b098fc6a 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* calculator = "\xEF\x87\xAC"; // fontawesome_weathericons.c // static constexpr const char* sun = "\xEF\x86\x85"; From 7e7aa6c04ec42f56ff7b4b8fd0cf335b83304c20 Mon Sep 17 00:00:00 2001 From: minacode Date: Mon, 5 Dec 2022 17:35:26 +0100 Subject: [PATCH 007/194] fixes and cleanup --- src/displayapp/screens/Calculator.cpp | 77 ++++++++++++++++++--------- src/displayapp/screens/Calculator.h | 8 ++- 2 files changed, 59 insertions(+), 26 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 40ad565446..fc05136037 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -27,26 +27,27 @@ Calculator::Calculator(DisplayApp* app) : Screen(app) { lv_label_set_long_mode(resultLabel, LV_LABEL_LONG_CROP); lv_label_set_align(resultLabel, LV_LABEL_ALIGN_RIGHT); lv_label_set_text_fmt(resultLabel, "%d", result); - lv_obj_set_size(resultLabel, 190, 20); + lv_obj_set_size(resultLabel, 142, 20); lv_obj_set_pos(resultLabel, 10, 10); valueLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(valueLabel, LV_LABEL_LONG_CROP); lv_label_set_align(valueLabel, LV_LABEL_ALIGN_RIGHT); lv_label_set_text_fmt(valueLabel, "%d", value); - lv_obj_set_size(valueLabel, 190, 20); + lv_obj_set_size(valueLabel, 142, 20); lv_obj_set_pos(valueLabel, 10, 40); operationLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(operationLabel, &operation); lv_obj_set_size(operationLabel, 20, 20); - lv_obj_set_pos(operationLabel, 210, 40); + lv_obj_set_pos(operationLabel, 195, 40); buttonMatrix = lv_btnmatrix_create(lv_scr_act(), nullptr); buttonMatrix->user_data = this; lv_obj_set_event_cb(buttonMatrix, eventHandler); lv_btnmatrix_set_map(buttonMatrix, buttonMap); - lv_obj_set_size(buttonMatrix, 240, 180); + lv_obj_set_size(buttonMatrix, 238, 180); + lv_obj_set_style_local_pad_inner(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); lv_obj_align(buttonMatrix, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0); } @@ -69,14 +70,16 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { case '9': // if this is true, we already pressed the . button if (offset < FIXED_POINT_OFFSET) { + // *buttonText is the first char in buttonText + // "- '0'" results in the int value of the char value += offset * (*buttonText - '0'); offset /= 10; } else { value *= 10; value += offset * (*buttonText - '0'); } - // *buttonText is the first char in buttonText - // "- '0'" results in the int value of the char + UpdateLabel(valueLabel, value); + NRF_LOG_INFO(". offset: %d", offset); NRF_LOG_INFO(". value: %d", value); NRF_LOG_INFO(". result: %d", result); @@ -86,6 +89,8 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { if (offset == FIXED_POINT_OFFSET) { offset /= 10; } + UpdateLabel(valueLabel, value); + NRF_LOG_INFO(". offset: %d", offset); NRF_LOG_INFO(". value: %d", value); NRF_LOG_INFO(". result: %d", result); @@ -104,6 +109,7 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } else { operation = '+'; } + lv_label_refr_text(operationLabel); break; case '*': if (value != 0) { @@ -114,45 +120,65 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } else { operation = '*'; } + lv_label_refr_text(operationLabel); break; case '^': if (value != 0) { Eval(); } operation = '^'; + lv_label_refr_text(operationLabel); break; case '<': + offset = FIXED_POINT_OFFSET; if (value != 0) { value = 0; } else { result = 0; + UpdateLabel(resultLabel, result); } + UpdateLabel(valueLabel, value); + operation = ' '; + lv_label_refr_text(operationLabel); break; case '=': Eval(); operation = ' '; + lv_label_refr_text(operationLabel); break; } - - // show values, spare . if no remainder - int valueRemainder = value % FIXED_POINT_OFFSET; - if (valueRemainder || offset < FIXED_POINT_OFFSET) { - lv_label_set_text_fmt(valueLabel, "%d.%d", value / FIXED_POINT_OFFSET, valueRemainder); - } else { - lv_label_set_text_fmt(valueLabel, "%d", value / FIXED_POINT_OFFSET); - } - int resultRemainder = result % FIXED_POINT_OFFSET; - if (resultRemainder) { - lv_label_set_text_fmt(resultLabel, "%d.%d", result / FIXED_POINT_OFFSET, resultRemainder); - } else { - lv_label_set_text_fmt(resultLabel, "%d", result / FIXED_POINT_OFFSET); } + } +} + +void Calculator::UpdateLabel(lv_obj_t* label, long int number) { + long int remainder = number % FIXED_POINT_OFFSET; + // remove sign from remainder + if (remainder < 0) { + remainder *= -1; + } - // show operation - lv_label_set_text_static(operationLabel, &operation); + // remove trailing zeros because its more beautiful + long int printRemainder = remainder; + while (printRemainder > 0 && printRemainder % 10 == 0) { + printRemainder /= 10; + } + + // we have to print a . and leading zeros in some cases + if (remainder || (offset < FIXED_POINT_OFFSET)) { + if (remainder == 0) { + lv_label_set_text_fmt(label, "%d.", number / FIXED_POINT_OFFSET); + } else if (remainder < 10) { + lv_label_set_text_fmt(label, "%d.00%d", number / FIXED_POINT_OFFSET, printRemainder); + } else if (remainder < 100) { + lv_label_set_text_fmt(label, "%d.0%d", number / FIXED_POINT_OFFSET, printRemainder); + } else { + lv_label_set_text_fmt(label, "%d.%d", number / FIXED_POINT_OFFSET, printRemainder); } + } else { + lv_label_set_text_fmt(label, "%d", number / FIXED_POINT_OFFSET); } } @@ -188,18 +214,21 @@ void Calculator::Eval() { // we use floats here because pow with fixed point numbers is weird case '^': - float tmp_value = (float)value; + float tmp_value = (float) value; tmp_value /= FIXED_POINT_OFFSET; - float tmp_result = (float)result; + float tmp_result = (float) result; tmp_result /= FIXED_POINT_OFFSET; tmp_result = pow(tmp_result, tmp_value); - result = (long) (tmp_result * FIXED_POINT_OFFSET); + result = (long int) (tmp_result * FIXED_POINT_OFFSET); value = 0; break; } operation = ' '; offset = FIXED_POINT_OFFSET; + + UpdateLabel(valueLabel, value); + UpdateLabel(resultLabel, result); } diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index b74ff7bd1a..db1603b6f0 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -21,9 +21,13 @@ namespace Pinetime { lv_obj_t* operationLabel; void Eval(); + void UpdateLabel(lv_obj_t* label, long int number); - static constexpr int FIXED_POINT_OFFSET = 1000; - int offset = FIXED_POINT_OFFSET; + // offset is the current offset for new digits + // standard is FIXED_POINT_OFFSET for 3 decimal places + // after typing a . this gets divided by 10 with each input + static constexpr long int FIXED_POINT_OFFSET = 1000; + long int offset = FIXED_POINT_OFFSET; long int value = 0; long int result = 0; From fed59f18fa8127978b8b268b45104052764b7a6f Mon Sep 17 00:00:00 2001 From: minacode Date: Wed, 7 Dec 2022 15:06:40 +0100 Subject: [PATCH 008/194] make buttons bigger --- src/displayapp/screens/Calculator.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index fc05136037..a392672cfe 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -27,20 +27,20 @@ Calculator::Calculator(DisplayApp* app) : Screen(app) { lv_label_set_long_mode(resultLabel, LV_LABEL_LONG_CROP); lv_label_set_align(resultLabel, LV_LABEL_ALIGN_RIGHT); lv_label_set_text_fmt(resultLabel, "%d", result); - lv_obj_set_size(resultLabel, 142, 20); - lv_obj_set_pos(resultLabel, 10, 10); + lv_obj_set_size(resultLabel, 145, 20); + lv_obj_set_pos(resultLabel, 10, 5); valueLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(valueLabel, LV_LABEL_LONG_CROP); lv_label_set_align(valueLabel, LV_LABEL_ALIGN_RIGHT); lv_label_set_text_fmt(valueLabel, "%d", value); - lv_obj_set_size(valueLabel, 142, 20); - lv_obj_set_pos(valueLabel, 10, 40); + lv_obj_set_size(valueLabel, 145, 20); + lv_obj_set_pos(valueLabel, 10, 35); operationLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(operationLabel, &operation); lv_obj_set_size(operationLabel, 20, 20); - lv_obj_set_pos(operationLabel, 195, 40); + lv_obj_set_pos(operationLabel, 203, 35); buttonMatrix = lv_btnmatrix_create(lv_scr_act(), nullptr); buttonMatrix->user_data = this; @@ -48,6 +48,10 @@ Calculator::Calculator(DisplayApp* app) : Screen(app) { lv_btnmatrix_set_map(buttonMatrix, buttonMap); lv_obj_set_size(buttonMatrix, 238, 180); lv_obj_set_style_local_pad_inner(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); + lv_obj_set_style_local_pad_top(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); + lv_obj_set_style_local_pad_bottom(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); + lv_obj_set_style_local_pad_left(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); + lv_obj_set_style_local_pad_right(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); lv_obj_align(buttonMatrix, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0); } From 5af0a3410d3dda0a5454aeee921ac05cde5ff143 Mon Sep 17 00:00:00 2001 From: minacode Date: Wed, 7 Dec 2022 17:36:40 +0100 Subject: [PATCH 009/194] fixed number displays --- src/displayapp/screens/Calculator.cpp | 119 ++++++++++++++++++-------- src/displayapp/screens/Calculator.h | 5 +- 2 files changed, 86 insertions(+), 38 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index a392672cfe..29f7437c3d 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -38,7 +38,7 @@ Calculator::Calculator(DisplayApp* app) : Screen(app) { lv_obj_set_pos(valueLabel, 10, 35); operationLabel = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_static(operationLabel, &operation); + lv_label_set_text_static(operationLabel, operation); lv_obj_set_size(operationLabel, 20, 20); lv_obj_set_pos(operationLabel, 203, 35); @@ -60,6 +60,10 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { if (obj == buttonMatrix) { const char* buttonText = lv_btnmatrix_get_active_btn_text(obj); + if (buttonText == nullptr) { + return; + } + // we only compare the first char because it is enough switch (*buttonText) { case '0': @@ -82,7 +86,7 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { value *= 10; value += offset * (*buttonText - '0'); } - UpdateLabel(valueLabel, value); + UpdateValueLabel(); NRF_LOG_INFO(". offset: %d", offset); NRF_LOG_INFO(". value: %d", value); @@ -93,7 +97,7 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { if (offset == FIXED_POINT_OFFSET) { offset /= 10; } - UpdateLabel(valueLabel, value); + UpdateValueLabel(); NRF_LOG_INFO(". offset: %d", offset); NRF_LOG_INFO(". value: %d", value); @@ -108,10 +112,10 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { if (value != 0) { Eval(); } - if (operation == '+') { - operation = '-'; + if (*operation == '+') { + *operation = '-'; } else { - operation = '+'; + *operation = '+'; } lv_label_refr_text(operationLabel); break; @@ -119,10 +123,10 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { if (value != 0) { Eval(); } - if (operation == '*') { - operation = '/'; + if (*operation == '*') { + *operation = '/'; } else { - operation = '*'; + *operation = '*'; } lv_label_refr_text(operationLabel); break; @@ -130,7 +134,7 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { if (value != 0) { Eval(); } - operation = '^'; + *operation = '^'; lv_label_refr_text(operationLabel); break; @@ -140,16 +144,16 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { value = 0; } else { result = 0; - UpdateLabel(resultLabel, result); + UpdateResultLabel(); } - UpdateLabel(valueLabel, value); + UpdateValueLabel(); - operation = ' '; + *operation = ' '; lv_label_refr_text(operationLabel); break; case '=': Eval(); - operation = ' '; + *operation = ' '; lv_label_refr_text(operationLabel); break; } @@ -157,37 +161,80 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } } -void Calculator::UpdateLabel(lv_obj_t* label, long int number) { - long int remainder = number % FIXED_POINT_OFFSET; - // remove sign from remainder - if (remainder < 0) { - remainder *= -1; +void Calculator::UpdateResultLabel() { + NRF_LOG_INFO("update result label"); + + long int integer = result / FIXED_POINT_OFFSET; + long int remainder = result % FIXED_POINT_OFFSET; + + // todo zero padding + if (remainder == 0) { + lv_label_set_text_fmt(resultLabel, "%ld", integer); + return; } - // remove trailing zeros because its more beautiful long int printRemainder = remainder; - while (printRemainder > 0 && printRemainder % 10 == 0) { + while ((printRemainder > 0) && (printRemainder % 10 == 0)) { + NRF_LOG_INFO("pr: %ld", printRemainder); printRemainder /= 10; } - // we have to print a . and leading zeros in some cases - if (remainder || (offset < FIXED_POINT_OFFSET)) { - if (remainder == 0) { - lv_label_set_text_fmt(label, "%d.", number / FIXED_POINT_OFFSET); - } else if (remainder < 10) { - lv_label_set_text_fmt(label, "%d.00%d", number / FIXED_POINT_OFFSET, printRemainder); - } else if (remainder < 100) { - lv_label_set_text_fmt(label, "%d.0%d", number / FIXED_POINT_OFFSET, printRemainder); - } else { - lv_label_set_text_fmt(label, "%d.%d", number / FIXED_POINT_OFFSET, printRemainder); + int padding = 0; + long int tmp = FIXED_POINT_OFFSET; + while (tmp > remainder) { + tmp /= 10; + padding++; + } + + lv_label_set_text_fmt( + resultLabel, + "%ld.%0*u", + integer, + padding, + printRemainder + ); +} + +void Calculator::UpdateValueLabel() { + long int integer = value / FIXED_POINT_OFFSET; + long int remainder = value % FIXED_POINT_OFFSET; + + long int printRemainder; + int padding; + + if (offset == 0) { + printRemainder = remainder; + padding = 3; + } else { + printRemainder = remainder / (10*offset); + padding = 0; + + // calculate the padding length as the length difference + // between FIXED_POINT_OFFSET and offset + long int tmp = FIXED_POINT_OFFSET / (10*offset); + while (tmp > 1) { + padding ++; + tmp /= 10; } + } + + if (offset == FIXED_POINT_OFFSET) { + lv_label_set_text_fmt(valueLabel, "%ld", integer); + } else if ((offset == FIXED_POINT_OFFSET / 10) && (remainder == 0)) { + lv_label_set_text_fmt(valueLabel, "%ld.", integer); } else { - lv_label_set_text_fmt(label, "%d", number / FIXED_POINT_OFFSET); + lv_label_set_text_fmt( + valueLabel, + "%ld.%0*u", + integer, + padding, + printRemainder + ); } } void Calculator::Eval() { - switch (operation) { + switch (*operation) { case ' ': case '=': result = value; @@ -230,9 +277,9 @@ void Calculator::Eval() { value = 0; break; } - operation = ' '; + *operation = ' '; offset = FIXED_POINT_OFFSET; - UpdateLabel(valueLabel, value); - UpdateLabel(resultLabel, result); + UpdateValueLabel(); + UpdateResultLabel(); } diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index db1603b6f0..5bcec86a47 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -21,7 +21,8 @@ namespace Pinetime { lv_obj_t* operationLabel; void Eval(); - void UpdateLabel(lv_obj_t* label, long int number); + void UpdateValueLabel(); + void UpdateResultLabel(); // offset is the current offset for new digits // standard is FIXED_POINT_OFFSET for 3 decimal places @@ -31,7 +32,7 @@ namespace Pinetime { long int value = 0; long int result = 0; - char operation = ' '; + char operation[2] {" "}; }; } } From cacf107c116c2047e44086b3fee7b4bcf5f32927 Mon Sep 17 00:00:00 2001 From: minacode Date: Thu, 8 Dec 2022 20:43:47 +0100 Subject: [PATCH 010/194] format --- src/displayapp/screens/Calculator.cpp | 33 +++++---------------- src/displayapp/screens/Calculator.h | 41 +++++++++++++-------------- 2 files changed, 27 insertions(+), 47 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 29f7437c3d..5153afa573 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -2,10 +2,8 @@ #include #include - using namespace Pinetime::Applications::Screens; - static void eventHandler(lv_obj_t* obj, lv_event_t event) { auto app = static_cast(obj->user_data); app->OnButtonEvent(obj, event); @@ -15,12 +13,7 @@ Calculator::~Calculator() { lv_obj_clean(lv_scr_act()); } -static const char* buttonMap[] = { - "7", "8", "9", "<", "\n", - "4", "5", "6", "+-", "\n", - "1", "2", "3", "*/", "\n", - ".", "0", "=", "^", "" -}; +static const char* buttonMap[] = {"7", "8", "9", "<", "\n", "4", "5", "6", "+-", "\n", "1", "2", "3", "*/", "\n", ".", "0", "=", "^", ""}; Calculator::Calculator(DisplayApp* app) : Screen(app) { resultLabel = lv_label_create(lv_scr_act(), nullptr); @@ -186,13 +179,7 @@ void Calculator::UpdateResultLabel() { padding++; } - lv_label_set_text_fmt( - resultLabel, - "%ld.%0*u", - integer, - padding, - printRemainder - ); + lv_label_set_text_fmt(resultLabel, "%ld.%0*u", integer, padding, printRemainder); } void Calculator::UpdateValueLabel() { @@ -201,19 +188,19 @@ void Calculator::UpdateValueLabel() { long int printRemainder; int padding; - + if (offset == 0) { printRemainder = remainder; padding = 3; } else { - printRemainder = remainder / (10*offset); + printRemainder = remainder / (10 * offset); padding = 0; // calculate the padding length as the length difference // between FIXED_POINT_OFFSET and offset - long int tmp = FIXED_POINT_OFFSET / (10*offset); + long int tmp = FIXED_POINT_OFFSET / (10 * offset); while (tmp > 1) { - padding ++; + padding++; tmp /= 10; } } @@ -223,13 +210,7 @@ void Calculator::UpdateValueLabel() { } else if ((offset == FIXED_POINT_OFFSET / 10) && (remainder == 0)) { lv_label_set_text_fmt(valueLabel, "%ld.", integer); } else { - lv_label_set_text_fmt( - valueLabel, - "%ld.%0*u", - integer, - padding, - printRemainder - ); + lv_label_set_text_fmt(valueLabel, "%ld.%0*u", integer, padding, printRemainder); } } diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 5bcec86a47..52ff6d4ba7 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -2,37 +2,36 @@ #include "Screen.h" - namespace Pinetime { namespace Applications { namespace Screens { class Calculator : public Screen { - public: - ~Calculator() override; + public: + ~Calculator() override; - Calculator(DisplayApp* app); + Calculator(DisplayApp* app); - void OnButtonEvent(lv_obj_t* obj, lv_event_t event); + void OnButtonEvent(lv_obj_t* obj, lv_event_t event); - private: - lv_obj_t* buttonMatrix; - lv_obj_t* valueLabel; - lv_obj_t* resultLabel; - lv_obj_t* operationLabel; + private: + lv_obj_t* buttonMatrix; + lv_obj_t* valueLabel; + lv_obj_t* resultLabel; + lv_obj_t* operationLabel; - void Eval(); - void UpdateValueLabel(); - void UpdateResultLabel(); + void Eval(); + void UpdateValueLabel(); + void UpdateResultLabel(); - // offset is the current offset for new digits - // standard is FIXED_POINT_OFFSET for 3 decimal places - // after typing a . this gets divided by 10 with each input - static constexpr long int FIXED_POINT_OFFSET = 1000; - long int offset = FIXED_POINT_OFFSET; + // offset is the current offset for new digits + // standard is FIXED_POINT_OFFSET for 3 decimal places + // after typing a . this gets divided by 10 with each input + static constexpr long int FIXED_POINT_OFFSET = 1000; + long int offset = FIXED_POINT_OFFSET; - long int value = 0; - long int result = 0; - char operation[2] {" "}; + long int value = 0; + long int result = 0; + char operation[2] {" "}; }; } } From 21e2427c62f9fe61698214c66bb75b97fc424a74 Mon Sep 17 00:00:00 2001 From: minacode Date: Fri, 9 Dec 2022 17:57:35 +0100 Subject: [PATCH 011/194] changed long int to int64_t --- src/displayapp/screens/Calculator.cpp | 47 ++++++++++++++------------- src/displayapp/screens/Calculator.h | 4 +-- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 5153afa573..228dbadbc1 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -1,5 +1,6 @@ #include "Calculator.h" #include +#include #include using namespace Pinetime::Applications::Screens; @@ -19,14 +20,14 @@ Calculator::Calculator(DisplayApp* app) : Screen(app) { resultLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(resultLabel, LV_LABEL_LONG_CROP); lv_label_set_align(resultLabel, LV_LABEL_ALIGN_RIGHT); - lv_label_set_text_fmt(resultLabel, "%d", result); + lv_label_set_text_fmt(resultLabel, "%" PRId64, result); lv_obj_set_size(resultLabel, 145, 20); lv_obj_set_pos(resultLabel, 10, 5); valueLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(valueLabel, LV_LABEL_LONG_CROP); lv_label_set_align(valueLabel, LV_LABEL_ALIGN_RIGHT); - lv_label_set_text_fmt(valueLabel, "%d", value); + lv_label_set_text_fmt(valueLabel, "%" PRId64, value); lv_obj_set_size(valueLabel, 145, 20); lv_obj_set_pos(valueLabel, 10, 35); @@ -81,9 +82,9 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } UpdateValueLabel(); - NRF_LOG_INFO(". offset: %d", offset); - NRF_LOG_INFO(". value: %d", value); - NRF_LOG_INFO(". result: %d", result); + NRF_LOG_INFO(". offset: %" PRId64, offset); + NRF_LOG_INFO(". value: %" PRId64, value); + NRF_LOG_INFO(". result: %" PRId64, result); break; case '.': @@ -92,9 +93,9 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } UpdateValueLabel(); - NRF_LOG_INFO(". offset: %d", offset); - NRF_LOG_INFO(". value: %d", value); - NRF_LOG_INFO(". result: %d", result); + NRF_LOG_INFO(". offset: %" PRId64, offset); + NRF_LOG_INFO(". value: %" PRId64, value); + NRF_LOG_INFO(". result: %" PRId64, result); break; // for every operator we: @@ -157,36 +158,36 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { void Calculator::UpdateResultLabel() { NRF_LOG_INFO("update result label"); - long int integer = result / FIXED_POINT_OFFSET; - long int remainder = result % FIXED_POINT_OFFSET; + int64_t integer = result / FIXED_POINT_OFFSET; + int64_t remainder = result % FIXED_POINT_OFFSET; // todo zero padding if (remainder == 0) { - lv_label_set_text_fmt(resultLabel, "%ld", integer); + lv_label_set_text_fmt(resultLabel, "%" PRId64, integer); return; } - long int printRemainder = remainder; + int64_t printRemainder = remainder; while ((printRemainder > 0) && (printRemainder % 10 == 0)) { - NRF_LOG_INFO("pr: %ld", printRemainder); + NRF_LOG_INFO("pr: %" PRId64, printRemainder); printRemainder /= 10; } int padding = 0; - long int tmp = FIXED_POINT_OFFSET; + int64_t tmp = FIXED_POINT_OFFSET; while (tmp > remainder) { tmp /= 10; padding++; } - lv_label_set_text_fmt(resultLabel, "%ld.%0*u", integer, padding, printRemainder); + lv_label_set_text_fmt(resultLabel, "%" PRId64 ".%0*u", integer, padding, printRemainder); } void Calculator::UpdateValueLabel() { - long int integer = value / FIXED_POINT_OFFSET; - long int remainder = value % FIXED_POINT_OFFSET; + int64_t integer = value / FIXED_POINT_OFFSET; + int64_t remainder = value % FIXED_POINT_OFFSET; - long int printRemainder; + int64_t printRemainder; int padding; if (offset == 0) { @@ -198,7 +199,7 @@ void Calculator::UpdateValueLabel() { // calculate the padding length as the length difference // between FIXED_POINT_OFFSET and offset - long int tmp = FIXED_POINT_OFFSET / (10 * offset); + int64_t tmp = FIXED_POINT_OFFSET / (10 * offset); while (tmp > 1) { padding++; tmp /= 10; @@ -206,11 +207,11 @@ void Calculator::UpdateValueLabel() { } if (offset == FIXED_POINT_OFFSET) { - lv_label_set_text_fmt(valueLabel, "%ld", integer); + lv_label_set_text_fmt(valueLabel, "%" PRId64, integer); } else if ((offset == FIXED_POINT_OFFSET / 10) && (remainder == 0)) { - lv_label_set_text_fmt(valueLabel, "%ld.", integer); + lv_label_set_text_fmt(valueLabel, "%" PRId64 ".", integer); } else { - lv_label_set_text_fmt(valueLabel, "%ld.%0*u", integer, padding, printRemainder); + lv_label_set_text_fmt(valueLabel, "%" PRId64 ".%0*u", integer, padding, printRemainder); } } @@ -253,7 +254,7 @@ void Calculator::Eval() { tmp_result /= FIXED_POINT_OFFSET; tmp_result = pow(tmp_result, tmp_value); - result = (long int) (tmp_result * FIXED_POINT_OFFSET); + result = (int64_t) (tmp_result * FIXED_POINT_OFFSET); value = 0; break; diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 52ff6d4ba7..cd97744c19 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -29,8 +29,8 @@ namespace Pinetime { static constexpr long int FIXED_POINT_OFFSET = 1000; long int offset = FIXED_POINT_OFFSET; - long int value = 0; - long int result = 0; + int64_t value = 0; + int64_t result = 0; char operation[2] {" "}; }; } From 37b0842f926c1ca6dc60ee655e73bbb4552d312b Mon Sep 17 00:00:00 2001 From: minacode Date: Fri, 9 Dec 2022 18:14:24 +0100 Subject: [PATCH 012/194] change float to double --- src/displayapp/screens/Calculator.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 228dbadbc1..c3b119f32e 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -247,14 +247,15 @@ void Calculator::Eval() { // we use floats here because pow with fixed point numbers is weird case '^': - float tmp_value = (float) value; + double tmp_value = (double) value; tmp_value /= FIXED_POINT_OFFSET; - float tmp_result = (float) result; + double tmp_result = (double) result; tmp_result /= FIXED_POINT_OFFSET; tmp_result = pow(tmp_result, tmp_value); - result = (int64_t) (tmp_result * FIXED_POINT_OFFSET); + tmp_result *= FIXED_POINT_OFFSET; + result = (int64_t) tmp_result; value = 0; break; From 0957bdcb43cbca73365e18f86836d292d6e5b3bd Mon Sep 17 00:00:00 2001 From: minacode Date: Mon, 19 Dec 2022 17:42:45 +0100 Subject: [PATCH 013/194] fixed crashes --- src/displayapp/screens/Calculator.cpp | 17 ++++++++--------- src/displayapp/screens/Calculator.h | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index c3b119f32e..025d078287 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -167,13 +167,13 @@ void Calculator::UpdateResultLabel() { return; } - int64_t printRemainder = remainder; + int64_t printRemainder = remainder < 0 ? -remainder : remainder; while ((printRemainder > 0) && (printRemainder % 10 == 0)) { NRF_LOG_INFO("pr: %" PRId64, printRemainder); printRemainder /= 10; } - int padding = 0; + uint8_t padding = 0; int64_t tmp = FIXED_POINT_OFFSET; while (tmp > remainder) { tmp /= 10; @@ -187,14 +187,13 @@ void Calculator::UpdateValueLabel() { int64_t integer = value / FIXED_POINT_OFFSET; int64_t remainder = value % FIXED_POINT_OFFSET; - int64_t printRemainder; - int padding; + int64_t printRemainder = remainder < 0 ? -remainder : remainder; + uint8_t padding; if (offset == 0) { - printRemainder = remainder; padding = 3; } else { - printRemainder = remainder / (10 * offset); + printRemainder /= (10 * offset); padding = 0; // calculate the padding length as the length difference @@ -247,15 +246,15 @@ void Calculator::Eval() { // we use floats here because pow with fixed point numbers is weird case '^': - double tmp_value = (double) value; + double tmp_value = static_cast(value); tmp_value /= FIXED_POINT_OFFSET; - double tmp_result = (double) result; + double tmp_result = static_cast(result); tmp_result /= FIXED_POINT_OFFSET; tmp_result = pow(tmp_result, tmp_value); tmp_result *= FIXED_POINT_OFFSET; - result = (int64_t) tmp_result; + result = static_cast(tmp_result); value = 0; break; diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index cd97744c19..3a6f9ae4e8 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -26,8 +26,8 @@ namespace Pinetime { // offset is the current offset for new digits // standard is FIXED_POINT_OFFSET for 3 decimal places // after typing a . this gets divided by 10 with each input - static constexpr long int FIXED_POINT_OFFSET = 1000; - long int offset = FIXED_POINT_OFFSET; + static constexpr int64_t FIXED_POINT_OFFSET = 1000; + int64_t offset = FIXED_POINT_OFFSET; int64_t value = 0; int64_t result = 0; From 64fb4f92cc941dd5ee6e6f02df22d5951f15fbdf Mon Sep 17 00:00:00 2001 From: minacode Date: Mon, 19 Dec 2022 23:06:47 +0100 Subject: [PATCH 014/194] WIP: refactored the prints --- src/displayapp/screens/Calculator.cpp | 62 +++++++++++++-------------- src/displayapp/screens/Calculator.h | 24 +++++++++-- 2 files changed, 50 insertions(+), 36 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 025d078287..7ebcc829a2 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -156,31 +156,27 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } void Calculator::UpdateResultLabel() { - NRF_LOG_INFO("update result label"); - int64_t integer = result / FIXED_POINT_OFFSET; int64_t remainder = result % FIXED_POINT_OFFSET; - // todo zero padding if (remainder == 0) { lv_label_set_text_fmt(resultLabel, "%" PRId64, integer); return; } - int64_t printRemainder = remainder < 0 ? -remainder : remainder; - while ((printRemainder > 0) && (printRemainder % 10 == 0)) { - NRF_LOG_INFO("pr: %" PRId64, printRemainder); - printRemainder /= 10; + if (remainder < 0) { + remainder = -remainder; } - uint8_t padding = 0; - int64_t tmp = FIXED_POINT_OFFSET; - while (tmp > remainder) { - tmp /= 10; - padding++; + uint8_t min_width = N_DECIMALS; + + // cut "0"-digits on the right + while ((remainder > 0) && (remainder % 10 == 0)) { + remainder /= 10; + min_width--; } - lv_label_set_text_fmt(resultLabel, "%" PRId64 ".%0*u", integer, padding, printRemainder); + lv_label_set_text_fmt(resultLabel, "%" PRId64 ".%0*" PRId64, integer, min_width, remainder); } void Calculator::UpdateValueLabel() { @@ -188,29 +184,31 @@ void Calculator::UpdateValueLabel() { int64_t remainder = value % FIXED_POINT_OFFSET; int64_t printRemainder = remainder < 0 ? -remainder : remainder; - uint8_t padding; - if (offset == 0) { - padding = 3; - } else { - printRemainder /= (10 * offset); - padding = 0; - - // calculate the padding length as the length difference - // between FIXED_POINT_OFFSET and offset - int64_t tmp = FIXED_POINT_OFFSET / (10 * offset); - while (tmp > 1) { - padding++; - tmp /= 10; - } + uint8_t min_width = 0; + int64_t tmp_offset = offset; + + // TODO there has to be a simpler way to do this + if (tmp_offset == 0) { + tmp_offset = 1; + min_width = 1; + } + while (tmp_offset < FIXED_POINT_OFFSET) { + tmp_offset *= 10; + min_width++; + } + min_width--; + + for (uint8_t i = min_width; i < N_DECIMALS; i++) { + printRemainder /= 10; } if (offset == FIXED_POINT_OFFSET) { lv_label_set_text_fmt(valueLabel, "%" PRId64, integer); - } else if ((offset == FIXED_POINT_OFFSET / 10) && (remainder == 0)) { + } else if ((offset == (FIXED_POINT_OFFSET / 10)) && (remainder == 0)) { lv_label_set_text_fmt(valueLabel, "%" PRId64 ".", integer); } else { - lv_label_set_text_fmt(valueLabel, "%" PRId64 ".%0*u", integer, padding, printRemainder); + lv_label_set_text_fmt(valueLabel, "%" PRId64 ".%0*" PRId64, integer, min_width, printRemainder); } } @@ -247,13 +245,13 @@ void Calculator::Eval() { // we use floats here because pow with fixed point numbers is weird case '^': double tmp_value = static_cast(value); - tmp_value /= FIXED_POINT_OFFSET; + tmp_value /= static_cast(FIXED_POINT_OFFSET); double tmp_result = static_cast(result); - tmp_result /= FIXED_POINT_OFFSET; + tmp_result /= static_cast(FIXED_POINT_OFFSET); tmp_result = pow(tmp_result, tmp_value); - tmp_result *= FIXED_POINT_OFFSET; + tmp_result *= static_cast(FIXED_POINT_OFFSET); result = static_cast(tmp_result); value = 0; diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 3a6f9ae4e8..dac520cf89 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -2,6 +2,17 @@ #include "Screen.h" +namespace { + int64_t constexpr powi(int64_t base, uint8_t exponent) { + int64_t value = 1; + while (exponent) { + value *= base; + exponent--; + } + return value; + } +} + namespace Pinetime { namespace Applications { namespace Screens { @@ -23,14 +34,19 @@ namespace Pinetime { void UpdateValueLabel(); void UpdateResultLabel(); - // offset is the current offset for new digits - // standard is FIXED_POINT_OFFSET for 3 decimal places - // after typing a . this gets divided by 10 with each input - static constexpr int64_t FIXED_POINT_OFFSET = 1000; + // change this if you want to change the number of decimals + static constexpr uint8_t N_DECIMALS = 4; + // this is the constant default offset + static constexpr int64_t FIXED_POINT_OFFSET = powi(10, N_DECIMALS); + // this is the current offset, may wary after pressing '.' int64_t offset = FIXED_POINT_OFFSET; int64_t value = 0; int64_t result = 0; + // this has length 2 because it must be a string + // because we also use it as the buffer for the operationLabel + // the second char is always \0 + // we only care about the first char char operation[2] {" "}; }; } From 8c10adc890e52ee3811e09d64cfeb703e6c33c50 Mon Sep 17 00:00:00 2001 From: minacode Date: Tue, 20 Dec 2022 19:30:07 +0100 Subject: [PATCH 015/194] set value bounds and checks --- src/displayapp/screens/Calculator.cpp | 24 ++++++++++++++++++++++-- src/displayapp/screens/Calculator.h | 6 ++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 7ebcc829a2..b99abf0672 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -76,7 +76,7 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { // "- '0'" results in the int value of the char value += offset * (*buttonText - '0'); offset /= 10; - } else { + } else if (value <= MAX_VALUE / 10) { value *= 10; value += offset * (*buttonText - '0'); } @@ -220,21 +220,41 @@ void Calculator::Eval() { value = 0; break; case '+': + // check for overflow + if (((result > 0) && (value > (MAX_VALUE - result))) || + ((result < 0) && (value < (MIN_VALUE - result)))) { + break; + } + result += value; value = 0; break; case '-': + // check for overflow + if (((result < 0) && (value > (MAX_VALUE + result))) || + ((result > 0) && (value < (MIN_VALUE + result)))) { + break; + } + result -= value; value = 0; break; case '*': + // check for overflow + // while dividing we eliminate the fixed point offset + // therefore we have to multiply it again for the comparison with value + if (((result != 0) && (value > (FIXED_POINT_OFFSET * (MAX_VALUE / result)))) || + ((result != 0) && (value < (FIXED_POINT_OFFSET * (MIN_VALUE / result))))) { + break; + } + result *= value; // fixed point offset was multiplied too result /= FIXED_POINT_OFFSET; value = 0; break; case '/': - if (value != FIXED_POINT_OFFSET) { + if (value != 0) { // fixed point offset will be divided too result *= FIXED_POINT_OFFSET; result /= value; diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index dac520cf89..593cbc216a 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -41,6 +41,12 @@ namespace Pinetime { // this is the current offset, may wary after pressing '.' int64_t offset = FIXED_POINT_OFFSET; + // the screen can show 12 chars + // but two are needed for '.' and '-' + static constexpr uint8_t MAX_DIGITS = 10; + static constexpr int64_t MAX_VALUE = powi(10, MAX_DIGITS) - 1; + static constexpr int64_t MIN_VALUE = -MAX_VALUE; + int64_t value = 0; int64_t result = 0; // this has length 2 because it must be a string From e46a1ca712247120cf9fbfb75753ff28f11ebc8e Mon Sep 17 00:00:00 2001 From: minacode Date: Tue, 20 Dec 2022 20:03:49 +0100 Subject: [PATCH 016/194] add backspace button --- src/displayapp/fonts/fonts.json | 2 +- src/displayapp/screens/Calculator.cpp | 36 ++++++++++++++++++++++----- src/displayapp/screens/Symbols.h | 1 + 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index 61546450a6..8f2a65d95a 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, 0xf201, 0xf06e, 0xf015, 0xf00c, 0xf1ec, 0xf743" + "range": "0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf201, 0xf06e, 0xf015, 0xf00c, 0xf1ec, 0xf743, 0xf55a" } ], "bpp": 1, diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index b99abf0672..43922f64e6 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -1,7 +1,8 @@ -#include "Calculator.h" #include #include #include +#include "Calculator.h" +#include "Symbols.h" using namespace Pinetime::Applications::Screens; @@ -14,7 +15,7 @@ Calculator::~Calculator() { lv_obj_clean(lv_scr_act()); } -static const char* buttonMap[] = {"7", "8", "9", "<", "\n", "4", "5", "6", "+-", "\n", "1", "2", "3", "*/", "\n", ".", "0", "=", "^", ""}; +static const char* buttonMap[] = {"7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+-", "\n", "1", "2", "3", "*/", "\n", ".", "0", "=", "^", ""}; Calculator::Calculator(DisplayApp* app) : Screen(app) { resultLabel = lv_label_create(lv_scr_act(), nullptr); @@ -132,15 +133,38 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { lv_label_refr_text(operationLabel); break; - case '<': - offset = FIXED_POINT_OFFSET; + // this is a little hacky because it matches only the first char + case Symbols::backspace[0]: if (value != 0) { - value = 0; + // delete one value digit + + if (offset < FIXED_POINT_OFFSET) { + if (offset == 0) { + offset = 1; + } else { + offset *= 10; + } + } else { + value /= 10; + } + + if (offset < FIXED_POINT_OFFSET) { + value -= value % (10 * offset); + } else { + value -= value % offset; + } + + UpdateValueLabel(); } else { + // reset the result + result = 0; UpdateResultLabel(); } - UpdateValueLabel(); + + NRF_LOG_INFO(". offset: %" PRId64, offset); + NRF_LOG_INFO(". value: %" PRId64, value); + NRF_LOG_INFO(". result: %" PRId64, result); *operation = ' '; lv_label_refr_text(operationLabel); diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index f3b098fc6a..40699b3d65 100644 --- a/src/displayapp/screens/Symbols.h +++ b/src/displayapp/screens/Symbols.h @@ -40,6 +40,7 @@ namespace Pinetime { static constexpr const char* home = "\xEF\x80\x95"; static constexpr const char* sleep = "\xEE\xBD\x84"; static constexpr const char* calculator = "\xEF\x87\xAC"; + static constexpr const char* backspace = "\xEF\x95\x9A"; // fontawesome_weathericons.c // static constexpr const char* sun = "\xEF\x86\x85"; From 7a7ffca49ccaeca23ccd6b1ffab53f6ceee82f7d Mon Sep 17 00:00:00 2001 From: minacode Date: Tue, 20 Dec 2022 20:27:51 +0100 Subject: [PATCH 017/194] WIP: = repeats calculation --- src/displayapp/screens/Calculator.cpp | 53 +++++++++++++++++++-------- src/displayapp/screens/Calculator.h | 1 + 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 43922f64e6..3a08fa84d7 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -106,36 +106,57 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { case '+': if (value != 0) { Eval(); + ResetInput(); + + UpdateValueLabel(); + UpdateResultLabel(); } + if (*operation == '+') { *operation = '-'; } else { *operation = '+'; } + lv_label_refr_text(operationLabel); break; + case '*': if (value != 0) { Eval(); + ResetInput(); + + UpdateValueLabel(); + UpdateResultLabel(); } + if (*operation == '*') { *operation = '/'; } else { *operation = '*'; } + lv_label_refr_text(operationLabel); break; + case '^': if (value != 0) { Eval(); + ResetInput(); + + UpdateValueLabel(); + UpdateResultLabel(); } *operation = '^'; + lv_label_refr_text(operationLabel); break; // this is a little hacky because it matches only the first char case Symbols::backspace[0]: - if (value != 0) { + if (*operation != ' ') { + *operation = ' '; + } else if (value != 0) { // delete one value digit if (offset < FIXED_POINT_OFFSET) { @@ -171,14 +192,21 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { break; case '=': Eval(); - *operation = ' '; - lv_label_refr_text(operationLabel); + + UpdateValueLabel(); + UpdateResultLabel(); break; } } } } +void Calculator::ResetInput() { + value = 0; + offset = FIXED_POINT_OFFSET; + *operation = ' '; +} + void Calculator::UpdateResultLabel() { int64_t integer = result / FIXED_POINT_OFFSET; int64_t remainder = result % FIXED_POINT_OFFSET; @@ -236,13 +264,13 @@ void Calculator::UpdateValueLabel() { } } +// update the result based on value and operation void Calculator::Eval() { switch (*operation) { case ' ': - case '=': result = value; - value = 0; break; + case '+': // check for overflow if (((result > 0) && (value > (MAX_VALUE - result))) || @@ -251,7 +279,6 @@ void Calculator::Eval() { } result += value; - value = 0; break; case '-': // check for overflow @@ -261,7 +288,6 @@ void Calculator::Eval() { } result -= value; - value = 0; break; case '*': // check for overflow @@ -275,19 +301,17 @@ void Calculator::Eval() { result *= value; // fixed point offset was multiplied too result /= FIXED_POINT_OFFSET; - value = 0; break; case '/': if (value != 0) { // fixed point offset will be divided too result *= FIXED_POINT_OFFSET; result /= value; - value = 0; } break; // we use floats here because pow with fixed point numbers is weird - case '^': + case '^': { double tmp_value = static_cast(value); tmp_value /= static_cast(FIXED_POINT_OFFSET); @@ -297,13 +321,10 @@ void Calculator::Eval() { tmp_result = pow(tmp_result, tmp_value); tmp_result *= static_cast(FIXED_POINT_OFFSET); result = static_cast(tmp_result); + break; + } - value = 0; + default: break; } - *operation = ' '; - offset = FIXED_POINT_OFFSET; - - UpdateValueLabel(); - UpdateResultLabel(); } diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 593cbc216a..90e2b4a2e1 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -31,6 +31,7 @@ namespace Pinetime { lv_obj_t* operationLabel; void Eval(); + void ResetInput(); void UpdateValueLabel(); void UpdateResultLabel(); From 3fce445420593707656ed3799961197709bc0318 Mon Sep 17 00:00:00 2001 From: minacode Date: Tue, 20 Dec 2022 20:44:50 +0100 Subject: [PATCH 018/194] format --- src/displayapp/screens/Calculator.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 3a08fa84d7..61e41452d6 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -15,7 +15,8 @@ Calculator::~Calculator() { lv_obj_clean(lv_scr_act()); } -static const char* buttonMap[] = {"7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+-", "\n", "1", "2", "3", "*/", "\n", ".", "0", "=", "^", ""}; +static const char* buttonMap[] = {"7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+-", "\n", "1", "2", "3", "*/", "\n", ".", "0", + "=", "^", ""}; Calculator::Calculator(DisplayApp* app) : Screen(app) { resultLabel = lv_label_create(lv_scr_act(), nullptr); @@ -273,8 +274,7 @@ void Calculator::Eval() { case '+': // check for overflow - if (((result > 0) && (value > (MAX_VALUE - result))) || - ((result < 0) && (value < (MIN_VALUE - result)))) { + if (((result > 0) && (value > (MAX_VALUE - result))) || ((result < 0) && (value < (MIN_VALUE - result)))) { break; } @@ -282,8 +282,7 @@ void Calculator::Eval() { break; case '-': // check for overflow - if (((result < 0) && (value > (MAX_VALUE + result))) || - ((result > 0) && (value < (MIN_VALUE + result)))) { + if (((result < 0) && (value > (MAX_VALUE + result))) || ((result > 0) && (value < (MIN_VALUE + result)))) { break; } From 4096da4952d130cbb21fd37ddf67f2506abfc36d Mon Sep 17 00:00:00 2001 From: minacode Date: Tue, 20 Dec 2022 22:50:23 +0100 Subject: [PATCH 019/194] fix offset bug from backspace --- src/displayapp/screens/Calculator.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 61e41452d6..6f8596ca86 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -176,6 +176,10 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { value -= value % offset; } + if ((value == 0) && (offset < FIXED_POINT_OFFSET)) { + offset = FIXED_POINT_OFFSET; + } + UpdateValueLabel(); } else { // reset the result @@ -191,6 +195,7 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { *operation = ' '; lv_label_refr_text(operationLabel); break; + case '=': Eval(); From 0048a8b2b599ccf16e077bce7e6d6602221118e0 Mon Sep 17 00:00:00 2001 From: minacode Date: Wed, 21 Dec 2022 00:57:23 +0100 Subject: [PATCH 020/194] fix backspace for zeros --- src/displayapp/screens/Calculator.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 6f8596ca86..eaffbf7d57 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -176,10 +176,9 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { value -= value % offset; } - if ((value == 0) && (offset < FIXED_POINT_OFFSET)) { - offset = FIXED_POINT_OFFSET; - } - + UpdateValueLabel(); + } else if (offset < FIXED_POINT_OFFSET) { + offset *= 10; UpdateValueLabel(); } else { // reset the result From b64787ac6dbfc990e241d151a48fbfc378e6e1c5 Mon Sep 17 00:00:00 2001 From: minacode Date: Wed, 21 Dec 2022 16:00:04 +0100 Subject: [PATCH 021/194] colored current button --- src/displayapp/screens/Calculator.cpp | 275 +++++++++++++------------- src/displayapp/screens/Calculator.h | 1 + 2 files changed, 144 insertions(+), 132 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index eaffbf7d57..e39fe4e6c4 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -48,161 +48,172 @@ Calculator::Calculator(DisplayApp* app) : Screen(app) { lv_obj_set_style_local_pad_bottom(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); lv_obj_set_style_local_pad_left(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); lv_obj_set_style_local_pad_right(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_FOCUSED, LV_COLOR_BLUE); lv_obj_align(buttonMatrix, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0); } void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { - if (event == LV_EVENT_CLICKED) { - if (obj == buttonMatrix) { - const char* buttonText = lv_btnmatrix_get_active_btn_text(obj); + if (obj == buttonMatrix) { + if ((event == LV_EVENT_PRESSED) || (event == LV_EVENT_PRESSING)) { + uint16_t activeButton = lv_btnmatrix_get_active_btn(buttonMatrix); + lv_btnmatrix_set_focused_btn(buttonMatrix, activeButton); + } + if (event == LV_EVENT_RELEASED) { + HandleInput(); + lv_btnmatrix_set_focused_btn(buttonMatrix, LV_BTNMATRIX_BTN_NONE); + } + } +} + + +void Calculator::HandleInput() { + const char* buttonText = lv_btnmatrix_get_active_btn_text(buttonMatrix); - if (buttonText == nullptr) { - return; + if (buttonText == nullptr) { + return; + } + + // we only compare the first char because it is enough + switch (*buttonText) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + // if this is true, we already pressed the . button + if (offset < FIXED_POINT_OFFSET) { + // *buttonText is the first char in buttonText + // "- '0'" results in the int value of the char + value += offset * (*buttonText - '0'); + offset /= 10; + } else if (value <= MAX_VALUE / 10) { + value *= 10; + value += offset * (*buttonText - '0'); } + UpdateValueLabel(); - // we only compare the first char because it is enough - switch (*buttonText) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - // if this is true, we already pressed the . button - if (offset < FIXED_POINT_OFFSET) { - // *buttonText is the first char in buttonText - // "- '0'" results in the int value of the char - value += offset * (*buttonText - '0'); - offset /= 10; - } else if (value <= MAX_VALUE / 10) { - value *= 10; - value += offset * (*buttonText - '0'); - } - UpdateValueLabel(); + NRF_LOG_INFO(". offset: %" PRId64, offset); + NRF_LOG_INFO(". value: %" PRId64, value); + NRF_LOG_INFO(". result: %" PRId64, result); + break; - NRF_LOG_INFO(". offset: %" PRId64, offset); - NRF_LOG_INFO(". value: %" PRId64, value); - NRF_LOG_INFO(". result: %" PRId64, result); - break; + case '.': + if (offset == FIXED_POINT_OFFSET) { + offset /= 10; + } + UpdateValueLabel(); - case '.': - if (offset == FIXED_POINT_OFFSET) { - offset /= 10; - } - UpdateValueLabel(); - - NRF_LOG_INFO(". offset: %" PRId64, offset); - NRF_LOG_INFO(". value: %" PRId64, value); - NRF_LOG_INFO(". result: %" PRId64, result); - break; - - // for every operator we: - // - eval the current operator if value > FIXED_POINT_OFFSET - // - then set the new operator - // - + and - as well as * and / cycle on the same button - case '+': - if (value != 0) { - Eval(); - ResetInput(); - - UpdateValueLabel(); - UpdateResultLabel(); - } + NRF_LOG_INFO(". offset: %" PRId64, offset); + NRF_LOG_INFO(". value: %" PRId64, value); + NRF_LOG_INFO(". result: %" PRId64, result); + break; - if (*operation == '+') { - *operation = '-'; - } else { - *operation = '+'; - } + // for every operator we: + // - eval the current operator if value > FIXED_POINT_OFFSET + // - then set the new operator + // - + and - as well as * and / cycle on the same button + case '+': + if (value != 0) { + Eval(); + ResetInput(); - lv_label_refr_text(operationLabel); - break; + UpdateValueLabel(); + UpdateResultLabel(); + } - case '*': - if (value != 0) { - Eval(); - ResetInput(); + if (*operation == '+') { + *operation = '-'; + } else { + *operation = '+'; + } - UpdateValueLabel(); - UpdateResultLabel(); - } + lv_label_refr_text(operationLabel); + break; - if (*operation == '*') { - *operation = '/'; - } else { - *operation = '*'; - } + case '*': + if (value != 0) { + Eval(); + ResetInput(); - lv_label_refr_text(operationLabel); - break; + UpdateValueLabel(); + UpdateResultLabel(); + } - case '^': - if (value != 0) { - Eval(); - ResetInput(); + if (*operation == '*') { + *operation = '/'; + } else { + *operation = '*'; + } - UpdateValueLabel(); - UpdateResultLabel(); - } - *operation = '^'; - - lv_label_refr_text(operationLabel); - break; - - // this is a little hacky because it matches only the first char - case Symbols::backspace[0]: - if (*operation != ' ') { - *operation = ' '; - } else if (value != 0) { - // delete one value digit - - if (offset < FIXED_POINT_OFFSET) { - if (offset == 0) { - offset = 1; - } else { - offset *= 10; - } - } else { - value /= 10; - } - - if (offset < FIXED_POINT_OFFSET) { - value -= value % (10 * offset); - } else { - value -= value % offset; - } - - UpdateValueLabel(); - } else if (offset < FIXED_POINT_OFFSET) { - offset *= 10; - UpdateValueLabel(); - } else { - // reset the result + lv_label_refr_text(operationLabel); + break; - result = 0; - UpdateResultLabel(); - } + case '^': + if (value != 0) { + Eval(); + ResetInput(); - NRF_LOG_INFO(". offset: %" PRId64, offset); - NRF_LOG_INFO(". value: %" PRId64, value); - NRF_LOG_INFO(". result: %" PRId64, result); + UpdateValueLabel(); + UpdateResultLabel(); + } + *operation = '^'; - *operation = ' '; - lv_label_refr_text(operationLabel); - break; + lv_label_refr_text(operationLabel); + break; - case '=': - Eval(); + // this is a little hacky because it matches only the first char + case Symbols::backspace[0]: + if (*operation != ' ') { + *operation = ' '; + } else if (value != 0) { + // delete one value digit - UpdateValueLabel(); - UpdateResultLabel(); - break; + if (offset < FIXED_POINT_OFFSET) { + if (offset == 0) { + offset = 1; + } else { + offset *= 10; + } + } else { + value /= 10; + } + + if (offset < FIXED_POINT_OFFSET) { + value -= value % (10 * offset); + } else { + value -= value % offset; + } + + UpdateValueLabel(); + } else if (offset < FIXED_POINT_OFFSET) { + offset *= 10; + UpdateValueLabel(); + } else { + // reset the result + + result = 0; + UpdateResultLabel(); } - } + + NRF_LOG_INFO(". offset: %" PRId64, offset); + NRF_LOG_INFO(". value: %" PRId64, value); + NRF_LOG_INFO(". result: %" PRId64, result); + + *operation = ' '; + lv_label_refr_text(operationLabel); + break; + + case '=': + Eval(); + + UpdateValueLabel(); + UpdateResultLabel(); + break; } } diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 90e2b4a2e1..0f68199e2d 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -32,6 +32,7 @@ namespace Pinetime { void Eval(); void ResetInput(); + void HandleInput(); void UpdateValueLabel(); void UpdateResultLabel(); From 5433363f011812099b6b3193005ee54ac618cdac Mon Sep 17 00:00:00 2001 From: minacode Date: Wed, 21 Dec 2022 16:04:34 +0100 Subject: [PATCH 022/194] format --- src/displayapp/screens/Calculator.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index e39fe4e6c4..5acd6a6dac 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -65,7 +65,6 @@ void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } } - void Calculator::HandleInput() { const char* buttonText = lv_btnmatrix_get_active_btn_text(buttonMatrix); From 852c1de62209b9c4a0715bb8b5ddcdc665f3a30c Mon Sep 17 00:00:00 2001 From: minacode Date: Sat, 31 Dec 2022 12:54:03 +0100 Subject: [PATCH 023/194] save changes --- src/displayapp/screens/Calculator.cpp | 77 ++++++++++++++++----------- src/displayapp/screens/Calculator.h | 1 + 2 files changed, 46 insertions(+), 32 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 5acd6a6dac..3fac476a0b 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -84,6 +84,10 @@ void Calculator::HandleInput() { case '7': case '8': case '9': + if (equalSignPressed) { + ResetInput(); + } + // if this is true, we already pressed the . button if (offset < FIXED_POINT_OFFSET) { // *buttonText is the first char in buttonText @@ -94,7 +98,6 @@ void Calculator::HandleInput() { value *= 10; value += offset * (*buttonText - '0'); } - UpdateValueLabel(); NRF_LOG_INFO(". offset: %" PRId64, offset); NRF_LOG_INFO(". value: %" PRId64, value); @@ -102,10 +105,13 @@ void Calculator::HandleInput() { break; case '.': + if (equalSignPressed) { + ResetInput(); + } + if (offset == FIXED_POINT_OFFSET) { offset /= 10; } - UpdateValueLabel(); NRF_LOG_INFO(". offset: %" PRId64, offset); NRF_LOG_INFO(". value: %" PRId64, value); @@ -117,12 +123,13 @@ void Calculator::HandleInput() { // - then set the new operator // - + and - as well as * and / cycle on the same button case '+': + if (equalSignPressed) { + ResetInput(); + } + if (value != 0) { Eval(); ResetInput(); - - UpdateValueLabel(); - UpdateResultLabel(); } if (*operation == '+') { @@ -130,17 +137,16 @@ void Calculator::HandleInput() { } else { *operation = '+'; } - - lv_label_refr_text(operationLabel); break; case '*': + if (equalSignPressed) { + ResetInput(); + } + if (value != 0) { Eval(); ResetInput(); - - UpdateValueLabel(); - UpdateResultLabel(); } if (*operation == '*') { @@ -148,30 +154,30 @@ void Calculator::HandleInput() { } else { *operation = '*'; } - - lv_label_refr_text(operationLabel); break; case '^': + if (equalSignPressed) { + ResetInput(); + } + if (value != 0) { Eval(); ResetInput(); - - UpdateValueLabel(); - UpdateResultLabel(); } *operation = '^'; - - lv_label_refr_text(operationLabel); break; // this is a little hacky because it matches only the first char case Symbols::backspace[0]: + if (equalSignPressed) { + ResetInput(); + } + if (*operation != ' ') { *operation = ' '; } else if (value != 0) { // delete one value digit - if (offset < FIXED_POINT_OFFSET) { if (offset == 0) { offset = 1; @@ -181,22 +187,16 @@ void Calculator::HandleInput() { } else { value /= 10; } - if (offset < FIXED_POINT_OFFSET) { value -= value % (10 * offset); } else { value -= value % offset; } - - UpdateValueLabel(); } else if (offset < FIXED_POINT_OFFSET) { offset *= 10; - UpdateValueLabel(); } else { // reset the result - result = 0; - UpdateResultLabel(); } NRF_LOG_INFO(". offset: %" PRId64, offset); @@ -204,22 +204,24 @@ void Calculator::HandleInput() { NRF_LOG_INFO(". result: %" PRId64, result); *operation = ' '; - lv_label_refr_text(operationLabel); break; case '=': + equalSignPressed = true; Eval(); - - UpdateValueLabel(); - UpdateResultLabel(); break; } + + UpdateValueLabel(); + UpdateResultLabel(); + lv_label_refr_text(operationLabel); } void Calculator::ResetInput() { value = 0; offset = FIXED_POINT_OFFSET; *operation = ' '; + equalSignPressed = false; } void Calculator::UpdateResultLabel() { @@ -316,11 +318,14 @@ void Calculator::Eval() { result /= FIXED_POINT_OFFSET; break; case '/': - if (value != 0) { - // fixed point offset will be divided too - result *= FIXED_POINT_OFFSET; - result /= value; + // check for zero division + if (value == 0) { + break; } + + // fixed point offset will be divided too + result *= FIXED_POINT_OFFSET; + result /= value; break; // we use floats here because pow with fixed point numbers is weird @@ -331,6 +336,14 @@ void Calculator::Eval() { double tmp_result = static_cast(result); tmp_result /= static_cast(FIXED_POINT_OFFSET); + // check for overflow + // result^value > MAX_VALUE iff + // log2(result^value) > log2(MAX_VALUE) iff + // value * log2(result) > log2(MAX_VALUE) + if ((value * log2(result)) > log2(MAX_VALUE)) { + break; + } + tmp_result = pow(tmp_result, tmp_value); tmp_result *= static_cast(FIXED_POINT_OFFSET); result = static_cast(tmp_result); diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 0f68199e2d..a2223bd216 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -56,6 +56,7 @@ namespace Pinetime { // the second char is always \0 // we only care about the first char char operation[2] {" "}; + bool equalSignPressed = false; }; } } From 477ad1e8400996668fa7631e750a91bb1894649a Mon Sep 17 00:00:00 2001 From: minacode Date: Sat, 31 Dec 2022 14:13:26 +0100 Subject: [PATCH 024/194] fixed various issues --- src/displayapp/screens/Calculator.cpp | 197 ++++++++++++++++---------- src/displayapp/screens/Calculator.h | 18 ++- 2 files changed, 133 insertions(+), 82 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 3fac476a0b..36bfba6bb8 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -15,7 +15,7 @@ Calculator::~Calculator() { lv_obj_clean(lv_scr_act()); } -static const char* buttonMap[] = {"7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+-", "\n", "1", "2", "3", "*/", "\n", ".", "0", +static const char* buttonMap[] = {"7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", ".", "0", "=", "^", ""}; Calculator::Calculator(DisplayApp* app) : Screen(app) { @@ -23,21 +23,16 @@ Calculator::Calculator(DisplayApp* app) : Screen(app) { lv_label_set_long_mode(resultLabel, LV_LABEL_LONG_CROP); lv_label_set_align(resultLabel, LV_LABEL_ALIGN_RIGHT); lv_label_set_text_fmt(resultLabel, "%" PRId64, result); - lv_obj_set_size(resultLabel, 145, 20); + lv_obj_set_size(resultLabel, 200, 20); lv_obj_set_pos(resultLabel, 10, 5); valueLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(valueLabel, LV_LABEL_LONG_CROP); lv_label_set_align(valueLabel, LV_LABEL_ALIGN_RIGHT); lv_label_set_text_fmt(valueLabel, "%" PRId64, value); - lv_obj_set_size(valueLabel, 145, 20); + lv_obj_set_size(valueLabel, 200, 20); lv_obj_set_pos(valueLabel, 10, 35); - operationLabel = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_static(operationLabel, operation); - lv_obj_set_size(operationLabel, 20, 20); - lv_obj_set_pos(operationLabel, 203, 35); - buttonMatrix = lv_btnmatrix_create(lv_scr_act(), nullptr); buttonMatrix->user_data = this; lv_obj_set_event_cb(buttonMatrix, eventHandler); @@ -50,6 +45,10 @@ Calculator::Calculator(DisplayApp* app) : Screen(app) { lv_obj_set_style_local_pad_right(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_FOCUSED, LV_COLOR_BLUE); lv_obj_align(buttonMatrix, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0); + + lv_obj_set_style_local_bg_opa(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_OPA_COVER); + lv_obj_set_style_local_bg_grad_stop(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, 128); + lv_obj_set_style_local_bg_main_stop(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, 128); } void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { @@ -72,6 +71,11 @@ void Calculator::HandleInput() { return; } + if ((equalSignPressed && (*buttonText != '=')) || (error != Error::None)) { + ResetInput(); + UpdateOperation(); + } + // we only compare the first char because it is enough switch (*buttonText) { case '0': @@ -84,10 +88,6 @@ void Calculator::HandleInput() { case '7': case '8': case '9': - if (equalSignPressed) { - ResetInput(); - } - // if this is true, we already pressed the . button if (offset < FIXED_POINT_OFFSET) { // *buttonText is the first char in buttonText @@ -105,10 +105,6 @@ void Calculator::HandleInput() { break; case '.': - if (equalSignPressed) { - ResetInput(); - } - if (offset == FIXED_POINT_OFFSET) { offset /= 10; } @@ -123,60 +119,57 @@ void Calculator::HandleInput() { // - then set the new operator // - + and - as well as * and / cycle on the same button case '+': - if (equalSignPressed) { - ResetInput(); - } - if (value != 0) { Eval(); ResetInput(); } - if (*operation == '+') { - *operation = '-'; - } else { - *operation = '+'; + switch (operation) { + case '+': + operation = '-'; + break; + case '-': + operation = ' '; + break; + default: + operation = '+'; + break; } + UpdateOperation(); break; case '*': - if (equalSignPressed) { - ResetInput(); - } - if (value != 0) { Eval(); ResetInput(); } - if (*operation == '*') { - *operation = '/'; - } else { - *operation = '*'; + switch (operation) { + case '*': + operation = '/'; + break; + case '/': + operation = ' '; + break; + default: + operation = '*'; + break; } + UpdateOperation(); break; case '^': - if (equalSignPressed) { - ResetInput(); - } - if (value != 0) { Eval(); ResetInput(); } - *operation = '^'; + operation = '^'; + UpdateOperation(); break; // this is a little hacky because it matches only the first char case Symbols::backspace[0]: - if (equalSignPressed) { - ResetInput(); - } - - if (*operation != ' ') { - *operation = ' '; - } else if (value != 0) { + if (value != 0) { // delete one value digit if (offset < FIXED_POINT_OFFSET) { if (offset == 0) { @@ -193,7 +186,11 @@ void Calculator::HandleInput() { value -= value % offset; } } else if (offset < FIXED_POINT_OFFSET) { - offset *= 10; + if (offset == 0) { + offset = 1; + } else { + offset *= 10; + } } else { // reset the result result = 0; @@ -203,7 +200,7 @@ void Calculator::HandleInput() { NRF_LOG_INFO(". value: %" PRId64, value); NRF_LOG_INFO(". result: %" PRId64, result); - *operation = ' '; + operation = ' '; break; case '=': @@ -211,17 +208,50 @@ void Calculator::HandleInput() { Eval(); break; } - + UpdateValueLabel(); UpdateResultLabel(); - lv_label_refr_text(operationLabel); +} + +void Calculator::UpdateOperation() { + lv_btnmatrix_clear_btn_ctrl(buttonMatrix, 7, LV_BTNMATRIX_CTRL_CHECK_STATE); + lv_btnmatrix_clear_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); + lv_btnmatrix_clear_btn_ctrl(buttonMatrix, 15, LV_BTNMATRIX_CTRL_CHECK_STATE); + + if (operation == '+') { + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 7, LV_BTNMATRIX_CTRL_CHECK_STATE); + } else if (operation == '-') { + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 7, LV_BTNMATRIX_CTRL_CHECK_STATE); + } + if (operation == '*') { + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); + } else if (operation == '/') { + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); + } else if (operation == '^') { + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_NONE); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 15, LV_BTNMATRIX_CTRL_CHECK_STATE); + } } void Calculator::ResetInput() { value = 0; offset = FIXED_POINT_OFFSET; - *operation = ' '; + operation = ' '; equalSignPressed = false; + error = Error::None; } void Calculator::UpdateResultLabel() { @@ -249,41 +279,53 @@ void Calculator::UpdateResultLabel() { } void Calculator::UpdateValueLabel() { - int64_t integer = value / FIXED_POINT_OFFSET; - int64_t remainder = value % FIXED_POINT_OFFSET; + switch (error) { + case Error::TooLarge: + lv_label_set_text_static(valueLabel, "too large"); + break; + case Error::ZeroDivision: + lv_label_set_text_static(valueLabel, "zero division"); + break; + case Error::None: + default: { + int64_t integer = value / FIXED_POINT_OFFSET; + int64_t remainder = value % FIXED_POINT_OFFSET; - int64_t printRemainder = remainder < 0 ? -remainder : remainder; + int64_t printRemainder = remainder < 0 ? -remainder : remainder; - uint8_t min_width = 0; - int64_t tmp_offset = offset; + uint8_t min_width = 0; + int64_t tmp_offset = offset; - // TODO there has to be a simpler way to do this - if (tmp_offset == 0) { - tmp_offset = 1; - min_width = 1; - } - while (tmp_offset < FIXED_POINT_OFFSET) { - tmp_offset *= 10; - min_width++; - } - min_width--; + // TODO there has to be a simpler way to do this + if (tmp_offset == 0) { + tmp_offset = 1; + min_width = 1; + } + while (tmp_offset < FIXED_POINT_OFFSET) { + tmp_offset *= 10; + min_width++; + } + min_width--; - for (uint8_t i = min_width; i < N_DECIMALS; i++) { - printRemainder /= 10; - } + for (uint8_t i = min_width; i < N_DECIMALS; i++) { + printRemainder /= 10; + } - if (offset == FIXED_POINT_OFFSET) { - lv_label_set_text_fmt(valueLabel, "%" PRId64, integer); - } else if ((offset == (FIXED_POINT_OFFSET / 10)) && (remainder == 0)) { - lv_label_set_text_fmt(valueLabel, "%" PRId64 ".", integer); - } else { - lv_label_set_text_fmt(valueLabel, "%" PRId64 ".%0*" PRId64, integer, min_width, printRemainder); + if (offset == FIXED_POINT_OFFSET) { + lv_label_set_text_fmt(valueLabel, "%" PRId64, integer); + } else if ((offset == (FIXED_POINT_OFFSET / 10)) && (remainder == 0)) { + lv_label_set_text_fmt(valueLabel, "%" PRId64 ".", integer); + } else { + lv_label_set_text_fmt(valueLabel, "%" PRId64 ".%0*" PRId64, integer, min_width, printRemainder); + } + } + break; } } // update the result based on value and operation void Calculator::Eval() { - switch (*operation) { + switch (operation) { case ' ': result = value; break; @@ -291,6 +333,7 @@ void Calculator::Eval() { case '+': // check for overflow if (((result > 0) && (value > (MAX_VALUE - result))) || ((result < 0) && (value < (MIN_VALUE - result)))) { + error = Error::TooLarge; break; } @@ -299,6 +342,7 @@ void Calculator::Eval() { case '-': // check for overflow if (((result < 0) && (value > (MAX_VALUE + result))) || ((result > 0) && (value < (MIN_VALUE + result)))) { + error = Error::TooLarge; break; } @@ -310,6 +354,7 @@ void Calculator::Eval() { // therefore we have to multiply it again for the comparison with value if (((result != 0) && (value > (FIXED_POINT_OFFSET * (MAX_VALUE / result)))) || ((result != 0) && (value < (FIXED_POINT_OFFSET * (MIN_VALUE / result))))) { + error = Error::TooLarge; break; } @@ -320,6 +365,7 @@ void Calculator::Eval() { case '/': // check for zero division if (value == 0) { + error = Error::ZeroDivision; break; } @@ -340,7 +386,8 @@ void Calculator::Eval() { // result^value > MAX_VALUE iff // log2(result^value) > log2(MAX_VALUE) iff // value * log2(result) > log2(MAX_VALUE) - if ((value * log2(result)) > log2(MAX_VALUE)) { + if ((tmp_value * log2(std::abs(tmp_result))) > log2(static_cast(MAX_VALUE))) { + error = Error::TooLarge; break; } diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index a2223bd216..00cefdb3e4 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -28,13 +28,13 @@ namespace Pinetime { lv_obj_t* buttonMatrix; lv_obj_t* valueLabel; lv_obj_t* resultLabel; - lv_obj_t* operationLabel; void Eval(); void ResetInput(); void HandleInput(); void UpdateValueLabel(); void UpdateResultLabel(); + void UpdateOperation(); // change this if you want to change the number of decimals static constexpr uint8_t N_DECIMALS = 4; @@ -45,18 +45,22 @@ namespace Pinetime { // the screen can show 12 chars // but two are needed for '.' and '-' - static constexpr uint8_t MAX_DIGITS = 10; + static constexpr uint8_t MAX_DIGITS = 15; static constexpr int64_t MAX_VALUE = powi(10, MAX_DIGITS) - 1; static constexpr int64_t MIN_VALUE = -MAX_VALUE; int64_t value = 0; int64_t result = 0; - // this has length 2 because it must be a string - // because we also use it as the buffer for the operationLabel - // the second char is always \0 - // we only care about the first char - char operation[2] {" "}; + char operation = ' '; bool equalSignPressed = false; + + enum Error { + TooLarge, + ZeroDivision, + None, + }; + + Error error = Error::None; }; } } From b9ede114bfdf5468a63ef005e9e1fc2e8bdf7de5 Mon Sep 17 00:00:00 2001 From: minacode Date: Sat, 31 Dec 2022 14:29:13 +0100 Subject: [PATCH 025/194] reset value after copy to result --- src/displayapp/screens/Calculator.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 36bfba6bb8..6b7a6349a7 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -206,6 +206,12 @@ void Calculator::HandleInput() { case '=': equalSignPressed = true; Eval(); + // If the operation is ' ' then we move the value to the result. + // We reset the input after this. + // This seems more convenient. + if (operation == ' ') { + ResetInput(); + } break; } From c36ad92eb8294c3863f5cf0eb2696d975eda1a84 Mon Sep 17 00:00:00 2001 From: minacode Date: Sat, 31 Dec 2022 14:29:51 +0100 Subject: [PATCH 026/194] format --- src/displayapp/screens/Calculator.cpp | 9 ++++----- src/displayapp/screens/Calculator.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 6b7a6349a7..2fc7d1fe34 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -45,7 +45,7 @@ Calculator::Calculator(DisplayApp* app) : Screen(app) { lv_obj_set_style_local_pad_right(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_FOCUSED, LV_COLOR_BLUE); lv_obj_align(buttonMatrix, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0); - + lv_obj_set_style_local_bg_opa(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_OPA_COVER); lv_obj_set_style_local_bg_grad_stop(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, 128); lv_obj_set_style_local_bg_main_stop(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, 128); @@ -214,7 +214,7 @@ void Calculator::HandleInput() { } break; } - + UpdateValueLabel(); UpdateResultLabel(); } @@ -324,8 +324,7 @@ void Calculator::UpdateValueLabel() { } else { lv_label_set_text_fmt(valueLabel, "%" PRId64 ".%0*" PRId64, integer, min_width, printRemainder); } - } - break; + } break; } } @@ -389,7 +388,7 @@ void Calculator::Eval() { tmp_result /= static_cast(FIXED_POINT_OFFSET); // check for overflow - // result^value > MAX_VALUE iff + // result^value > MAX_VALUE iff // log2(result^value) > log2(MAX_VALUE) iff // value * log2(result) > log2(MAX_VALUE) if ((tmp_value * log2(std::abs(tmp_result))) > log2(static_cast(MAX_VALUE))) { diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 00cefdb3e4..d9554429b0 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -59,7 +59,7 @@ namespace Pinetime { ZeroDivision, None, }; - + Error error = Error::None; }; } From d4ea28c1282be1ba7f263340e401bfa2385b493d Mon Sep 17 00:00:00 2001 From: minacode Date: Sat, 31 Dec 2022 14:40:49 +0100 Subject: [PATCH 027/194] format and tidy --- src/displayapp/screens/Calculator.cpp | 8 ++++---- src/displayapp/screens/Calculator.h | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 2fc7d1fe34..4ef66c7bc1 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -219,7 +219,7 @@ void Calculator::HandleInput() { UpdateResultLabel(); } -void Calculator::UpdateOperation() { +void Calculator::UpdateOperation() const { lv_btnmatrix_clear_btn_ctrl(buttonMatrix, 7, LV_BTNMATRIX_CTRL_CHECK_STATE); lv_btnmatrix_clear_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); lv_btnmatrix_clear_btn_ctrl(buttonMatrix, 15, LV_BTNMATRIX_CTRL_CHECK_STATE); @@ -260,7 +260,7 @@ void Calculator::ResetInput() { error = Error::None; } -void Calculator::UpdateResultLabel() { +void Calculator::UpdateResultLabel() const { int64_t integer = result / FIXED_POINT_OFFSET; int64_t remainder = result % FIXED_POINT_OFFSET; @@ -381,10 +381,10 @@ void Calculator::Eval() { // we use floats here because pow with fixed point numbers is weird case '^': { - double tmp_value = static_cast(value); + auto tmp_value = static_cast(value); tmp_value /= static_cast(FIXED_POINT_OFFSET); - double tmp_result = static_cast(result); + auto tmp_result = static_cast(result); tmp_result /= static_cast(FIXED_POINT_OFFSET); // check for overflow diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index d9554429b0..4a6969c3de 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -25,16 +25,16 @@ namespace Pinetime { void OnButtonEvent(lv_obj_t* obj, lv_event_t event); private: - lv_obj_t* buttonMatrix; - lv_obj_t* valueLabel; - lv_obj_t* resultLabel; + lv_obj_t* buttonMatrix {}; + lv_obj_t* valueLabel {}; + lv_obj_t* resultLabel {}; void Eval(); void ResetInput(); void HandleInput(); void UpdateValueLabel(); - void UpdateResultLabel(); - void UpdateOperation(); + void UpdateResultLabel() const; + void UpdateOperation() const; // change this if you want to change the number of decimals static constexpr uint8_t N_DECIMALS = 4; From 25cd03ebf70b8997be2cf58a7ddbe4f3c432902a Mon Sep 17 00:00:00 2001 From: minacode Date: Sun, 1 Jan 2023 02:04:32 +0100 Subject: [PATCH 028/194] add power operation toggle --- src/displayapp/screens/Calculator.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 4ef66c7bc1..7340e483d3 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -163,7 +163,12 @@ void Calculator::HandleInput() { Eval(); ResetInput(); } - operation = '^'; + + if (operation == '^') { + operation = ' '; + } else { + operation = '^'; + } UpdateOperation(); break; From e98cd4995886e6c870b54d3a8f1bc4e3a1133759 Mon Sep 17 00:00:00 2001 From: minacode Date: Thu, 5 Jan 2023 21:44:05 +0100 Subject: [PATCH 029/194] checked buttons cleanup --- src/displayapp/screens/Calculator.cpp | 63 +++++++++++++++------------ 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 7340e483d3..e486fa4cb1 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -37,6 +37,7 @@ Calculator::Calculator(DisplayApp* app) : Screen(app) { buttonMatrix->user_data = this; lv_obj_set_event_cb(buttonMatrix, eventHandler); lv_btnmatrix_set_map(buttonMatrix, buttonMap); + lv_btnmatrix_set_one_check(buttonMatrix, true); lv_obj_set_size(buttonMatrix, 238, 180); lv_obj_set_style_local_pad_inner(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); lv_obj_set_style_local_pad_top(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); @@ -225,35 +226,39 @@ void Calculator::HandleInput() { } void Calculator::UpdateOperation() const { - lv_btnmatrix_clear_btn_ctrl(buttonMatrix, 7, LV_BTNMATRIX_CTRL_CHECK_STATE); - lv_btnmatrix_clear_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); - lv_btnmatrix_clear_btn_ctrl(buttonMatrix, 15, LV_BTNMATRIX_CTRL_CHECK_STATE); - - if (operation == '+') { - lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); - lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); - lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); - lv_btnmatrix_set_btn_ctrl(buttonMatrix, 7, LV_BTNMATRIX_CTRL_CHECK_STATE); - } else if (operation == '-') { - lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); - lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); - lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); - lv_btnmatrix_set_btn_ctrl(buttonMatrix, 7, LV_BTNMATRIX_CTRL_CHECK_STATE); - } - if (operation == '*') { - lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); - lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); - lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); - lv_btnmatrix_set_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); - } else if (operation == '/') { - lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); - lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); - lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); - lv_btnmatrix_set_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); - } else if (operation == '^') { - lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_NONE); - lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); - lv_btnmatrix_set_btn_ctrl(buttonMatrix, 15, LV_BTNMATRIX_CTRL_CHECK_STATE); + switch (operation) { + case '+': + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 7, LV_BTNMATRIX_CTRL_CHECK_STATE); + break; + case '-': + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 7, LV_BTNMATRIX_CTRL_CHECK_STATE); + break; + case '*': + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); + break; + case '/': + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); + break; + case '^': + lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_NONE); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); + lv_btnmatrix_set_btn_ctrl(buttonMatrix, 15, LV_BTNMATRIX_CTRL_CHECK_STATE); + break; + default: + lv_btnmatrix_clear_btn_ctrl_all(buttonMatrix, LV_BTNMATRIX_CTRL_CHECK_STATE); + break; } } From 4cd0ec79dfde343944cf6d2e0526cbcc01134fd0 Mon Sep 17 00:00:00 2001 From: minacode Date: Thu, 5 Jan 2023 21:47:18 +0100 Subject: [PATCH 030/194] removed swiping --- src/displayapp/screens/Calculator.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index e486fa4cb1..6193c74da0 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -44,7 +44,6 @@ Calculator::Calculator(DisplayApp* app) : Screen(app) { lv_obj_set_style_local_pad_bottom(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); lv_obj_set_style_local_pad_left(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); lv_obj_set_style_local_pad_right(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); - lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_FOCUSED, LV_COLOR_BLUE); lv_obj_align(buttonMatrix, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0); lv_obj_set_style_local_bg_opa(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_OPA_COVER); @@ -53,15 +52,8 @@ Calculator::Calculator(DisplayApp* app) : Screen(app) { } void Calculator::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { - if (obj == buttonMatrix) { - if ((event == LV_EVENT_PRESSED) || (event == LV_EVENT_PRESSING)) { - uint16_t activeButton = lv_btnmatrix_get_active_btn(buttonMatrix); - lv_btnmatrix_set_focused_btn(buttonMatrix, activeButton); - } - if (event == LV_EVENT_RELEASED) { - HandleInput(); - lv_btnmatrix_set_focused_btn(buttonMatrix, LV_BTNMATRIX_BTN_NONE); - } + if ((obj == buttonMatrix) && (event == LV_EVENT_PRESSED)) { + HandleInput(); } } From 89c6c2f6849473651bfc586c13598cbf590b47e6 Mon Sep 17 00:00:00 2001 From: minacode Date: Thu, 5 Jan 2023 22:03:54 +0100 Subject: [PATCH 031/194] add better colors --- src/displayapp/InfiniTimeTheme.h | 1 + src/displayapp/screens/Calculator.cpp | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/displayapp/InfiniTimeTheme.h b/src/displayapp/InfiniTimeTheme.h index 0690b09912..9ceb08771e 100644 --- a/src/displayapp/InfiniTimeTheme.h +++ b/src/displayapp/InfiniTimeTheme.h @@ -8,6 +8,7 @@ namespace Colors { static constexpr lv_color_t green = LV_COLOR_MAKE(0x0, 0xb0, 0x0); static constexpr lv_color_t blue = LV_COLOR_MAKE(0x0, 0x50, 0xff); static constexpr lv_color_t lightGray = LV_COLOR_MAKE(0xb0, 0xb0, 0xb0); + static constexpr lv_color_t deepOrange = LV_COLOR_MAKE(0xff, 0x40, 0x0); static constexpr lv_color_t bg = LV_COLOR_MAKE(0x5d, 0x69, 0x7e); static constexpr lv_color_t bgAlt = LV_COLOR_MAKE(0x38, 0x38, 0x38); diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 6193c74da0..8efc0ee5e9 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -2,6 +2,7 @@ #include #include #include "Calculator.h" +#include "displayapp/InfiniTimeTheme.h" #include "Symbols.h" using namespace Pinetime::Applications::Screens; @@ -39,6 +40,7 @@ Calculator::Calculator(DisplayApp* app) : Screen(app) { lv_btnmatrix_set_map(buttonMatrix, buttonMap); lv_btnmatrix_set_one_check(buttonMatrix, true); lv_obj_set_size(buttonMatrix, 238, 180); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_DEFAULT, Colors::bgAlt); lv_obj_set_style_local_pad_inner(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); lv_obj_set_style_local_pad_top(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); lv_obj_set_style_local_pad_bottom(buttonMatrix, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 1); @@ -221,31 +223,31 @@ void Calculator::UpdateOperation() const { switch (operation) { case '+': lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); - lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); - lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::bgAlt); lv_btnmatrix_set_btn_ctrl(buttonMatrix, 7, LV_BTNMATRIX_CTRL_CHECK_STATE); break; case '-': lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); - lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); - lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::bgAlt); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); lv_btnmatrix_set_btn_ctrl(buttonMatrix, 7, LV_BTNMATRIX_CTRL_CHECK_STATE); break; case '*': lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); - lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); - lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::bgAlt); lv_btnmatrix_set_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); break; case '/': lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_HOR); - lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_GRAY); - lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::bgAlt); + lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); lv_btnmatrix_set_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); break; case '^': lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_NONE); - lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_COLOR_RED); + lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); lv_btnmatrix_set_btn_ctrl(buttonMatrix, 15, LV_BTNMATRIX_CTRL_CHECK_STATE); break; default: From edf99905f4d4f92c11ed91d99eda3ec1847d541c Mon Sep 17 00:00:00 2001 From: Finlay Davidson Date: Mon, 9 Jan 2023 00:57:42 +0100 Subject: [PATCH 032/194] Remove power operation in calculator app Also shuffles bottom row around a bit, and adds a unary minus button. Also fixes issue where the colours on the operator buttons aren't wiped when the backspace button is pressed. --- src/displayapp/screens/Calculator.cpp | 52 +++++---------------------- 1 file changed, 8 insertions(+), 44 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 8efc0ee5e9..1e03d4fa1d 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -16,8 +16,8 @@ Calculator::~Calculator() { lv_obj_clean(lv_scr_act()); } -static const char* buttonMap[] = {"7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", ".", "0", - "=", "^", ""}; +static const char* buttonMap[] = {"7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ".", + "(-)", "=", ""}; Calculator::Calculator(DisplayApp* app) : Screen(app) { resultLabel = lv_label_create(lv_scr_act(), nullptr); @@ -99,6 +99,11 @@ void Calculator::HandleInput() { NRF_LOG_INFO(". result: %" PRId64, result); break; + // unary minus + case '(': + value = -value; + break; + case '.': if (offset == FIXED_POINT_OFFSET) { offset /= 10; @@ -153,20 +158,6 @@ void Calculator::HandleInput() { UpdateOperation(); break; - case '^': - if (value != 0) { - Eval(); - ResetInput(); - } - - if (operation == '^') { - operation = ' '; - } else { - operation = '^'; - } - UpdateOperation(); - break; - // this is a little hacky because it matches only the first char case Symbols::backspace[0]: if (value != 0) { @@ -201,6 +192,7 @@ void Calculator::HandleInput() { NRF_LOG_INFO(". result: %" PRId64, result); operation = ' '; + UpdateOperation(); break; case '=': @@ -245,11 +237,6 @@ void Calculator::UpdateOperation() const { lv_obj_set_style_local_bg_grad_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); lv_btnmatrix_set_btn_ctrl(buttonMatrix, 11, LV_BTNMATRIX_CTRL_CHECK_STATE); break; - case '^': - lv_obj_set_style_local_bg_grad_dir(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, LV_GRAD_DIR_NONE); - lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_CHECKED, Colors::deepOrange); - lv_btnmatrix_set_btn_ctrl(buttonMatrix, 15, LV_BTNMATRIX_CTRL_CHECK_STATE); - break; default: lv_btnmatrix_clear_btn_ctrl_all(buttonMatrix, LV_BTNMATRIX_CTRL_CHECK_STATE); break; @@ -383,29 +370,6 @@ void Calculator::Eval() { result /= value; break; - // we use floats here because pow with fixed point numbers is weird - case '^': { - auto tmp_value = static_cast(value); - tmp_value /= static_cast(FIXED_POINT_OFFSET); - - auto tmp_result = static_cast(result); - tmp_result /= static_cast(FIXED_POINT_OFFSET); - - // check for overflow - // result^value > MAX_VALUE iff - // log2(result^value) > log2(MAX_VALUE) iff - // value * log2(result) > log2(MAX_VALUE) - if ((tmp_value * log2(std::abs(tmp_result))) > log2(static_cast(MAX_VALUE))) { - error = Error::TooLarge; - break; - } - - tmp_result = pow(tmp_result, tmp_value); - tmp_result *= static_cast(FIXED_POINT_OFFSET); - result = static_cast(tmp_result); - break; - } - default: break; } From 4a74e49f4397d6f39d27b692edf6a67018707fa0 Mon Sep 17 00:00:00 2001 From: minacode Date: Mon, 9 Jan 2023 09:19:46 +0100 Subject: [PATCH 033/194] format --- src/displayapp/screens/Calculator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 1e03d4fa1d..9bb735be82 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -16,8 +16,8 @@ Calculator::~Calculator() { lv_obj_clean(lv_scr_act()); } -static const char* buttonMap[] = {"7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ".", - "(-)", "=", ""}; +static const char* buttonMap[] = { + "7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ".", "(-)", "=", ""}; Calculator::Calculator(DisplayApp* app) : Screen(app) { resultLabel = lv_label_create(lv_scr_act(), nullptr); From 041369b88e2d0825c2a93255b2e99ed4e3878a57 Mon Sep 17 00:00:00 2001 From: minacode Date: Sun, 29 Jan 2023 23:34:59 +0100 Subject: [PATCH 034/194] fixed negative number input Instead of always adding the new digit it now gets multipled with a sign, based on whether value is negative or not. Thus, the addition becomes a subtraction for negative numbers. --- src/displayapp/screens/Calculator.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 9bb735be82..b4cc003f51 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -82,22 +82,25 @@ void Calculator::HandleInput() { case '6': case '7': case '8': - case '9': + case '9': { + // *buttonText is the first char in buttonText + // "- '0'" results in the int value of the char + auto digit = (*buttonText) - '0'; + auto sign = (value < 0) ? -1 : 1; + // if this is true, we already pressed the . button if (offset < FIXED_POINT_OFFSET) { - // *buttonText is the first char in buttonText - // "- '0'" results in the int value of the char - value += offset * (*buttonText - '0'); + value += sign * offset * digit; offset /= 10; } else if (value <= MAX_VALUE / 10) { value *= 10; - value += offset * (*buttonText - '0'); + value += sign * offset * digit; } NRF_LOG_INFO(". offset: %" PRId64, offset); NRF_LOG_INFO(". value: %" PRId64, value); NRF_LOG_INFO(". result: %" PRId64, result); - break; + } break; // unary minus case '(': From f116a3e2bddaf5ab6311978669519785f725fd25 Mon Sep 17 00:00:00 2001 From: minacode Date: Sat, 4 Mar 2023 15:23:34 +0100 Subject: [PATCH 035/194] changes --- src/displayapp/screens/Calculator.cpp | 6 +++--- src/displayapp/screens/Calculator.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index b4cc003f51..44d0875282 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -347,12 +347,12 @@ void Calculator::Eval() { result -= value; break; - case '*': + case '*': // check for overflow // while dividing we eliminate the fixed point offset // therefore we have to multiply it again for the comparison with value - if (((result != 0) && (value > (FIXED_POINT_OFFSET * (MAX_VALUE / result)))) || - ((result != 0) && (value < (FIXED_POINT_OFFSET * (MIN_VALUE / result))))) { + // we also assume here that MAX_VALUE == -MIN_VALUE + if ((result != 0) && (std::abs(value) > (FIXED_POINT_OFFSET * (MAX_VALUE / std::abs(result))))) { error = Error::TooLarge; break; } diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 4a6969c3de..f657613067 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -47,6 +47,7 @@ namespace Pinetime { // but two are needed for '.' and '-' static constexpr uint8_t MAX_DIGITS = 15; static constexpr int64_t MAX_VALUE = powi(10, MAX_DIGITS) - 1; + // this is assumed in the multiplication overflow! static constexpr int64_t MIN_VALUE = -MAX_VALUE; int64_t value = 0; From 19eb8a95cb93c904286b5687c73ede401d4de7f1 Mon Sep 17 00:00:00 2001 From: minacode Date: Sat, 4 Mar 2023 17:01:03 +0100 Subject: [PATCH 036/194] fix after rebase --- src/displayapp/InfiniTimeTheme.h | 1 - src/displayapp/screens/Calculator.cpp | 2 +- src/displayapp/screens/Calculator.h | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/displayapp/InfiniTimeTheme.h b/src/displayapp/InfiniTimeTheme.h index 9ceb08771e..0690b09912 100644 --- a/src/displayapp/InfiniTimeTheme.h +++ b/src/displayapp/InfiniTimeTheme.h @@ -8,7 +8,6 @@ namespace Colors { static constexpr lv_color_t green = LV_COLOR_MAKE(0x0, 0xb0, 0x0); static constexpr lv_color_t blue = LV_COLOR_MAKE(0x0, 0x50, 0xff); static constexpr lv_color_t lightGray = LV_COLOR_MAKE(0xb0, 0xb0, 0xb0); - static constexpr lv_color_t deepOrange = LV_COLOR_MAKE(0xff, 0x40, 0x0); static constexpr lv_color_t bg = LV_COLOR_MAKE(0x5d, 0x69, 0x7e); static constexpr lv_color_t bgAlt = LV_COLOR_MAKE(0x38, 0x38, 0x38); diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 44d0875282..8b1b5a7dbd 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -19,7 +19,7 @@ Calculator::~Calculator() { static const char* buttonMap[] = { "7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ".", "(-)", "=", ""}; -Calculator::Calculator(DisplayApp* app) : Screen(app) { +Calculator::Calculator() { resultLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(resultLabel, LV_LABEL_LONG_CROP); lv_label_set_align(resultLabel, LV_LABEL_ALIGN_RIGHT); diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index f657613067..1751386108 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -20,7 +20,7 @@ namespace Pinetime { public: ~Calculator() override; - Calculator(DisplayApp* app); + Calculator(); void OnButtonEvent(lv_obj_t* obj, lv_event_t event); From 44d1d7d4b6df06b6aed491be5af6369611f58f92 Mon Sep 17 00:00:00 2001 From: minacode Date: Sat, 4 Mar 2023 17:05:12 +0100 Subject: [PATCH 037/194] format --- src/displayapp/screens/Calculator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 8b1b5a7dbd..fddb0db216 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -347,7 +347,7 @@ void Calculator::Eval() { result -= value; break; - case '*': + case '*': // check for overflow // while dividing we eliminate the fixed point offset // therefore we have to multiply it again for the comparison with value From a3a557fb99bba741b7e49d9cd0b888c3e9810894 Mon Sep 17 00:00:00 2001 From: minacode Date: Sat, 4 Mar 2023 17:22:59 +0100 Subject: [PATCH 038/194] fixed display of negative numbers smaller than 0 --- src/displayapp/screens/Calculator.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index fddb0db216..e5d3881082 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -105,6 +105,11 @@ void Calculator::HandleInput() { // unary minus case '(': value = -value; + + NRF_LOG_INFO(". offset: %" PRId64, offset); + NRF_LOG_INFO(". value: %" PRId64, value); + NRF_LOG_INFO(". result: %" PRId64, result); + break; case '.': @@ -207,6 +212,11 @@ void Calculator::HandleInput() { if (operation == ' ') { ResetInput(); } + + NRF_LOG_INFO(". offset: %" PRId64, offset); + NRF_LOG_INFO(". value: %" PRId64, value); + NRF_LOG_INFO(". result: %" PRId64, result); + break; } @@ -257,6 +267,7 @@ void Calculator::ResetInput() { void Calculator::UpdateResultLabel() const { int64_t integer = result / FIXED_POINT_OFFSET; int64_t remainder = result % FIXED_POINT_OFFSET; + bool negative = (remainder < 0); if (remainder == 0) { lv_label_set_text_fmt(resultLabel, "%" PRId64, integer); @@ -275,7 +286,11 @@ void Calculator::UpdateResultLabel() const { min_width--; } - lv_label_set_text_fmt(resultLabel, "%" PRId64 ".%0*" PRId64, integer, min_width, remainder); + if ((integer == 0) && negative) { + lv_label_set_text_fmt(resultLabel, "-0.%0*" PRId64, min_width, remainder); + } else { + lv_label_set_text_fmt(resultLabel, "%" PRId64 ".%0*" PRId64, integer, min_width, remainder); + } } void Calculator::UpdateValueLabel() { @@ -290,6 +305,7 @@ void Calculator::UpdateValueLabel() { default: { int64_t integer = value / FIXED_POINT_OFFSET; int64_t remainder = value % FIXED_POINT_OFFSET; + bool negative = (remainder < 0); int64_t printRemainder = remainder < 0 ? -remainder : remainder; @@ -311,7 +327,9 @@ void Calculator::UpdateValueLabel() { printRemainder /= 10; } - if (offset == FIXED_POINT_OFFSET) { + if ((integer == 0) && negative) { + lv_label_set_text_fmt(valueLabel, "-0.%0*" PRId64, min_width, printRemainder); + } else if (offset == FIXED_POINT_OFFSET) { lv_label_set_text_fmt(valueLabel, "%" PRId64, integer); } else if ((offset == (FIXED_POINT_OFFSET / 10)) && (remainder == 0)) { lv_label_set_text_fmt(valueLabel, "%" PRId64 ".", integer); From 25022004a0ce7c0ccd2f0c9aed575bf47332605c Mon Sep 17 00:00:00 2001 From: Max Friedrich Date: Sun, 12 Nov 2023 20:04:13 +0100 Subject: [PATCH 039/194] only remove the operator if the value is zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: SuIông N. --- src/displayapp/screens/Calculator.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index e5d3881082..a311ee0fb4 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -199,8 +199,10 @@ void Calculator::HandleInput() { NRF_LOG_INFO(". value: %" PRId64, value); NRF_LOG_INFO(". result: %" PRId64, result); - operation = ' '; - UpdateOperation(); + if (value == 0) { + operation = ' '; + UpdateOperation(); + } break; case '=': From d356c400e9cd6ebaad51e3dfd1a7f35abd283544 Mon Sep 17 00:00:00 2001 From: minacode Date: Sun, 12 Nov 2023 19:58:52 +0100 Subject: [PATCH 040/194] lower maximum number size and number of digits This is necessary to ensure correct calculations. Themaximum int64 has 19 digits. Therefore, 18 digits are safe to use. But in order to calculate exact multiplication we need twice the number of digits after the comma, so I decided to go with 12 digits before the comman and 3 after it. --- src/displayapp/screens/Calculator.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 1751386108..2111c29828 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -37,7 +37,7 @@ namespace Pinetime { void UpdateOperation() const; // change this if you want to change the number of decimals - static constexpr uint8_t N_DECIMALS = 4; + static constexpr uint8_t N_DECIMALS = 3; // this is the constant default offset static constexpr int64_t FIXED_POINT_OFFSET = powi(10, N_DECIMALS); // this is the current offset, may wary after pressing '.' @@ -45,7 +45,7 @@ namespace Pinetime { // the screen can show 12 chars // but two are needed for '.' and '-' - static constexpr uint8_t MAX_DIGITS = 15; + static constexpr uint8_t MAX_DIGITS = 12; static constexpr int64_t MAX_VALUE = powi(10, MAX_DIGITS) - 1; // this is assumed in the multiplication overflow! static constexpr int64_t MIN_VALUE = -MAX_VALUE; From e6099835fb09bd2b7a3f18a8c16dd37a8ff60f50 Mon Sep 17 00:00:00 2001 From: minacode Date: Sun, 10 Dec 2023 18:24:20 +0100 Subject: [PATCH 041/194] update to optional apps This commit updates the codebase to use the new interface for compile-time optional apps. --- src/displayapp/screens/Calculator.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 2111c29828..dcfc65feba 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -1,6 +1,9 @@ #pragma once -#include "Screen.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/Apps.h" +#include "displayapp/Controllers.h" +#include "Symbols.h" namespace { int64_t constexpr powi(int64_t base, uint8_t exponent) { @@ -64,5 +67,14 @@ namespace Pinetime { Error error = Error::None; }; } + + template <> + struct AppTraits { + static constexpr Apps app = Apps::Calculator; + static constexpr const char* icon = Screens::Symbols::calculator; + static Screens::Screen* Create(AppControllers& controllers) { + return new Screens::Calculator(); + }; + }; } } From 10346ef4d61dfbbebae058ae1a96e60aaa110d0a Mon Sep 17 00:00:00 2001 From: minacode Date: Sun, 10 Dec 2023 18:36:00 +0100 Subject: [PATCH 042/194] fix build and format warnings --- src/displayapp/screens/Calculator.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index dcfc65feba..3b23a8a674 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -72,7 +72,8 @@ namespace Pinetime { struct AppTraits { static constexpr Apps app = Apps::Calculator; static constexpr const char* icon = Screens::Symbols::calculator; - static Screens::Screen* Create(AppControllers& controllers) { + + static Screens::Screen* Create(AppControllers& /* controllers */) { return new Screens::Calculator(); }; }; From b734baf47bb4371170990d269c7964cf65bcb6cc Mon Sep 17 00:00:00 2001 From: minacode Date: Sat, 13 Jan 2024 21:39:11 +0100 Subject: [PATCH 043/194] reduce heap size --- src/FreeRTOSConfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FreeRTOSConfig.h b/src/FreeRTOSConfig.h index 67c33a34cc..930ec7644b 100644 --- a/src/FreeRTOSConfig.h +++ b/src/FreeRTOSConfig.h @@ -62,7 +62,7 @@ #define configTICK_RATE_HZ 1024 #define configMAX_PRIORITIES (3) #define configMINIMAL_STACK_SIZE (120) -#define configTOTAL_HEAP_SIZE (1024 * 40) +#define configTOTAL_HEAP_SIZE (1024 * 35) #define configMAX_TASK_NAME_LEN (4) #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 From ab7ceb9cfb7bb7b952456b5a60e74a415ee4a818 Mon Sep 17 00:00:00 2001 From: minacode Date: Sat, 13 Jan 2024 21:39:48 +0100 Subject: [PATCH 044/194] implement new CMake interface --- src/displayapp/apps/Apps.h.in | 1 + src/displayapp/apps/CMakeLists.txt | 1 + src/displayapp/screens/Calculator.h | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/displayapp/apps/Apps.h.in b/src/displayapp/apps/Apps.h.in index 2104a267c0..e697096a65 100644 --- a/src/displayapp/apps/Apps.h.in +++ b/src/displayapp/apps/Apps.h.in @@ -26,6 +26,7 @@ namespace Pinetime { StopWatch, Metronome, Motion, + Calculator, Steps, Dice, Weather, diff --git a/src/displayapp/apps/CMakeLists.txt b/src/displayapp/apps/CMakeLists.txt index d78587609e..33e5432385 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -13,6 +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::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::Motion") set(USERAPP_TYPES "${DEFAULT_USER_APP_TYPES}" CACHE STRING "List of user apps to build into the firmware") diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 3b23a8a674..99d86e7531 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -1,7 +1,7 @@ #pragma once #include "displayapp/screens/Screen.h" -#include "displayapp/Apps.h" +#include "displayapp/apps/Apps.h" #include "displayapp/Controllers.h" #include "Symbols.h" From 0f65f4827ee18298cb9471a2476e41265978a951 Mon Sep 17 00:00:00 2001 From: minacode Date: Tue, 16 Jul 2024 15:39:34 +0200 Subject: [PATCH 045/194] set heap size to 39 --- src/FreeRTOSConfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FreeRTOSConfig.h b/src/FreeRTOSConfig.h index 930ec7644b..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 * 35) +#define configTOTAL_HEAP_SIZE (1024 * 39) #define configMAX_TASK_NAME_LEN (4) #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 From d2c178eddf5ce7a171a14dc8b9898a79d9d29410 Mon Sep 17 00:00:00 2001 From: minacode Date: Tue, 16 Jul 2024 15:39:54 +0200 Subject: [PATCH 046/194] add missing icon --- src/displayapp/fonts/fonts.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index 8f2a65d95a..152a42e90f 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, 0xf201, 0xf06e, 0xf015, 0xf00c, 0xf1ec, 0xf743, 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, 0xf201, 0xf06e, 0xf015, 0xf00c, 0xf1ec, 0xf743, 0xf55a, 0xf0f3" } ], "bpp": 1, From accd6665173f4a51496fe18cbef90b6b846fa5fc Mon Sep 17 00:00:00 2001 From: minacode Date: Tue, 16 Jul 2024 15:40:08 +0200 Subject: [PATCH 047/194] remove TODO --- src/displayapp/screens/Calculator.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index a311ee0fb4..81bf2f623c 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -314,7 +314,6 @@ void Calculator::UpdateValueLabel() { uint8_t min_width = 0; int64_t tmp_offset = offset; - // TODO there has to be a simpler way to do this if (tmp_offset == 0) { tmp_offset = 1; min_width = 1; From 0d54f1e776d23c6b9cdbc79f20faae96291206ca Mon Sep 17 00:00:00 2001 From: minacode Date: Sat, 31 Aug 2024 18:14:13 +0200 Subject: [PATCH 048/194] add const I dont 100% understand, how it works, but this seems to reduce the amount of needed memory, such that we do not have to reduce the size in the FreeRTOS config. --- src/FreeRTOSConfig.h | 2 +- src/displayapp/screens/Calculator.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/FreeRTOSConfig.h b/src/FreeRTOSConfig.h index 4696e386f0..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 * 39) +#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/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 81bf2f623c..15651df70f 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -16,7 +16,7 @@ Calculator::~Calculator() { lv_obj_clean(lv_scr_act()); } -static const char* buttonMap[] = { +static const char* const buttonMap[] = { "7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ".", "(-)", "=", ""}; Calculator::Calculator() { @@ -37,7 +37,7 @@ Calculator::Calculator() { buttonMatrix = lv_btnmatrix_create(lv_scr_act(), nullptr); buttonMatrix->user_data = this; lv_obj_set_event_cb(buttonMatrix, eventHandler); - lv_btnmatrix_set_map(buttonMatrix, buttonMap); + lv_btnmatrix_set_map(buttonMatrix, const_cast(buttonMap)); lv_btnmatrix_set_one_check(buttonMatrix, true); lv_obj_set_size(buttonMatrix, 238, 180); lv_obj_set_style_local_bg_color(buttonMatrix, LV_BTNMATRIX_PART_BTN, LV_STATE_DEFAULT, Colors::bgAlt); From dcacb9ca5ce667be627d7cf9c3912f4536048a59 Mon Sep 17 00:00:00 2001 From: minacode Date: Sun, 1 Sep 2024 22:00:10 +0200 Subject: [PATCH 049/194] add constexpr --- src/displayapp/screens/Calculator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 15651df70f..9143ccf565 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -16,7 +16,7 @@ Calculator::~Calculator() { lv_obj_clean(lv_scr_act()); } -static const char* const buttonMap[] = { +constexpr const char* const buttonMap[] = { "7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ".", "(-)", "=", ""}; Calculator::Calculator() { From eb160eecb35db8225c3fd794a2f0e61e9c4a4455 Mon Sep 17 00:00:00 2001 From: Max Friedrich Date: Tue, 3 Sep 2024 03:03:32 +0200 Subject: [PATCH 050/194] Remove const Because it is redundant --- src/displayapp/screens/Calculator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 9143ccf565..5f51b88dbd 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -16,7 +16,7 @@ Calculator::~Calculator() { lv_obj_clean(lv_scr_act()); } -constexpr const char* const buttonMap[] = { +constexpr char* const buttonMap[] = { "7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ".", "(-)", "=", ""}; Calculator::Calculator() { From 8c30a35eafad11062374503654580b49a065e58d Mon Sep 17 00:00:00 2001 From: minacode Date: Sun, 24 Nov 2024 13:57:49 +0100 Subject: [PATCH 051/194] fix compile error by making the button labels even more const --- src/displayapp/screens/Calculator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 5f51b88dbd..9143ccf565 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -16,7 +16,7 @@ Calculator::~Calculator() { lv_obj_clean(lv_scr_act()); } -constexpr char* const buttonMap[] = { +constexpr const char* const buttonMap[] = { "7", "8", "9", Symbols::backspace, "\n", "4", "5", "6", "+ -", "\n", "1", "2", "3", "* /", "\n", "0", ".", "(-)", "=", ""}; Calculator::Calculator() { From 76c4bda211382ae767489a5064c9e000cb071ee3 Mon Sep 17 00:00:00 2001 From: Max Friedrich Date: Sun, 24 Nov 2024 16:39:44 +0100 Subject: [PATCH 052/194] fix typo Co-authored-by: mark9064 <30447455+mark9064@users.noreply.github.com> --- src/displayapp/screens/Calculator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 99d86e7531..6888fba265 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -43,7 +43,7 @@ namespace Pinetime { static constexpr uint8_t N_DECIMALS = 3; // this is the constant default offset static constexpr int64_t FIXED_POINT_OFFSET = powi(10, N_DECIMALS); - // this is the current offset, may wary after pressing '.' + // this is the current offset, may vary after pressing '.' int64_t offset = FIXED_POINT_OFFSET; // the screen can show 12 chars From 9a97e6c37bac9ac473e71c7e2cbc3332adbb4360 Mon Sep 17 00:00:00 2001 From: minacode Date: Sun, 24 Nov 2024 18:35:18 +0100 Subject: [PATCH 053/194] rearrange font symbols --- src/displayapp/fonts/fonts.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index 152a42e90f..059e283ecf 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, 0xf201, 0xf06e, 0xf015, 0xf00c, 0xf1ec, 0xf743, 0xf55a, 0xf0f3" + "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, 0xf743, 0xf1ec, 0xf55a" } ], "bpp": 1, From 7be0251664ddd66a9c59d760a9c89de408a2f14b Mon Sep 17 00:00:00 2001 From: minacode Date: Sun, 24 Nov 2024 18:38:16 +0100 Subject: [PATCH 054/194] explain number of digits --- src/displayapp/screens/Calculator.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index 6888fba265..d7d66054f9 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -40,6 +40,8 @@ namespace Pinetime { void UpdateOperation() const; // change this if you want to change the number of decimals + // keep in mind, that we only have 12 digits in total (see MAX_DIGITS) + // due to the fixed point implementation static constexpr uint8_t N_DECIMALS = 3; // this is the constant default offset static constexpr int64_t FIXED_POINT_OFFSET = powi(10, N_DECIMALS); From 0e1893fe762d20bb63a37d3b18033772bc2a49e8 Mon Sep 17 00:00:00 2001 From: minacode Date: Sun, 24 Nov 2024 18:40:11 +0100 Subject: [PATCH 055/194] remove logging --- src/displayapp/screens/Calculator.cpp | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 9143ccf565..fd312a725a 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -1,6 +1,5 @@ #include #include -#include #include "Calculator.h" #include "displayapp/InfiniTimeTheme.h" #include "Symbols.h" @@ -96,30 +95,17 @@ void Calculator::HandleInput() { value *= 10; value += sign * offset * digit; } - - NRF_LOG_INFO(". offset: %" PRId64, offset); - NRF_LOG_INFO(". value: %" PRId64, value); - NRF_LOG_INFO(". result: %" PRId64, result); } break; // unary minus case '(': value = -value; - - NRF_LOG_INFO(". offset: %" PRId64, offset); - NRF_LOG_INFO(". value: %" PRId64, value); - NRF_LOG_INFO(". result: %" PRId64, result); - break; case '.': if (offset == FIXED_POINT_OFFSET) { offset /= 10; } - - NRF_LOG_INFO(". offset: %" PRId64, offset); - NRF_LOG_INFO(". value: %" PRId64, value); - NRF_LOG_INFO(". result: %" PRId64, result); break; // for every operator we: @@ -195,10 +181,6 @@ void Calculator::HandleInput() { result = 0; } - NRF_LOG_INFO(". offset: %" PRId64, offset); - NRF_LOG_INFO(". value: %" PRId64, value); - NRF_LOG_INFO(". result: %" PRId64, result); - if (value == 0) { operation = ' '; UpdateOperation(); @@ -214,11 +196,6 @@ void Calculator::HandleInput() { if (operation == ' ') { ResetInput(); } - - NRF_LOG_INFO(". offset: %" PRId64, offset); - NRF_LOG_INFO(". value: %" PRId64, value); - NRF_LOG_INFO(". result: %" PRId64, result); - break; } From 9e3c6651a275ae094694d75f6bfd4d7b62b6b51c Mon Sep 17 00:00:00 2001 From: Max Friedrich Date: Sun, 24 Nov 2024 21:07:34 +0100 Subject: [PATCH 056/194] do not remove dice icon --- src/displayapp/fonts/fonts.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index 059e283ecf..fea3160572 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, 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, 0xf1ec, 0xf55a" } ], "bpp": 1, From acf38e973eaf83e810428d9dd40c16ac0ba475bb Mon Sep 17 00:00:00 2001 From: Max Friedrich Date: Sat, 7 Dec 2024 17:52:58 +0100 Subject: [PATCH 057/194] Specify auto types --- src/displayapp/screens/Calculator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index fd312a725a..36474d4eeb 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -84,8 +84,8 @@ void Calculator::HandleInput() { case '9': { // *buttonText is the first char in buttonText // "- '0'" results in the int value of the char - auto digit = (*buttonText) - '0'; - auto sign = (value < 0) ? -1 : 1; + uint8_t digit = (*buttonText) - '0'; + int8_t sign = (value < 0) ? -1 : 1; // if this is true, we already pressed the . button if (offset < FIXED_POINT_OFFSET) { From 9cb3b65dac2ea7046c908438cf9ff5d999ce95e3 Mon Sep 17 00:00:00 2001 From: Max Friedrich Date: Sat, 7 Dec 2024 17:58:28 +0100 Subject: [PATCH 058/194] Change variables to camel case --- src/displayapp/screens/Calculator.cpp | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 36474d4eeb..7c759584d3 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -257,18 +257,18 @@ void Calculator::UpdateResultLabel() const { remainder = -remainder; } - uint8_t min_width = N_DECIMALS; + uint8_t minWidth = N_DECIMALS; // cut "0"-digits on the right while ((remainder > 0) && (remainder % 10 == 0)) { remainder /= 10; - min_width--; + minWidth--; } if ((integer == 0) && negative) { - lv_label_set_text_fmt(resultLabel, "-0.%0*" PRId64, min_width, remainder); + lv_label_set_text_fmt(resultLabel, "-0.%0*" PRId64, minWidth, remainder); } else { - lv_label_set_text_fmt(resultLabel, "%" PRId64 ".%0*" PRId64, integer, min_width, remainder); + lv_label_set_text_fmt(resultLabel, "%" PRId64 ".%0*" PRId64, integer, minWidth, remainder); } } @@ -288,31 +288,31 @@ void Calculator::UpdateValueLabel() { int64_t printRemainder = remainder < 0 ? -remainder : remainder; - uint8_t min_width = 0; - int64_t tmp_offset = offset; + uint8_t minWidth = 0; + int64_t tmpOffset = offset; - if (tmp_offset == 0) { - tmp_offset = 1; - min_width = 1; + if (tmpOffset == 0) { + tmpOffset = 1; + minWidth = 1; } - while (tmp_offset < FIXED_POINT_OFFSET) { - tmp_offset *= 10; - min_width++; + while (tmpOffset < FIXED_POINT_OFFSET) { + tmpOffset *= 10; + minWidth++; } - min_width--; + minWidth--; - for (uint8_t i = min_width; i < N_DECIMALS; i++) { + for (uint8_t i = minWidth; i < N_DECIMALS; i++) { printRemainder /= 10; } if ((integer == 0) && negative) { - lv_label_set_text_fmt(valueLabel, "-0.%0*" PRId64, min_width, printRemainder); + lv_label_set_text_fmt(valueLabel, "-0.%0*" PRId64, minWidth, printRemainder); } else if (offset == FIXED_POINT_OFFSET) { lv_label_set_text_fmt(valueLabel, "%" PRId64, integer); } else if ((offset == (FIXED_POINT_OFFSET / 10)) && (remainder == 0)) { lv_label_set_text_fmt(valueLabel, "%" PRId64 ".", integer); } else { - lv_label_set_text_fmt(valueLabel, "%" PRId64 ".%0*" PRId64, integer, min_width, printRemainder); + lv_label_set_text_fmt(valueLabel, "%" PRId64 ".%0*" PRId64, integer, minWidth, printRemainder); } } break; } From 3705dc96e786b24830d73972b3b7e115a23f4505 Mon Sep 17 00:00:00 2001 From: Max Friedrich Date: Sat, 7 Dec 2024 18:00:32 +0100 Subject: [PATCH 059/194] Rename equalSignPressed to equalSignPressedBefore --- src/displayapp/screens/Calculator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 7c759584d3..a1f093830c 100644 --- a/src/displayapp/screens/Calculator.cpp +++ b/src/displayapp/screens/Calculator.cpp @@ -65,7 +65,7 @@ void Calculator::HandleInput() { return; } - if ((equalSignPressed && (*buttonText != '=')) || (error != Error::None)) { + if ((equalSignPressedBefore && (*buttonText != '=')) || (error != Error::None)) { ResetInput(); UpdateOperation(); } @@ -188,7 +188,7 @@ void Calculator::HandleInput() { break; case '=': - equalSignPressed = true; + equalSignPressedBefore = true; Eval(); // If the operation is ' ' then we move the value to the result. // We reset the input after this. @@ -239,7 +239,7 @@ void Calculator::ResetInput() { value = 0; offset = FIXED_POINT_OFFSET; operation = ' '; - equalSignPressed = false; + equalSignPressedBefore = false; error = Error::None; } From 1cb1a8bbdcc425b688dc018fd8f125c8a29ba689 Mon Sep 17 00:00:00 2001 From: Max Friedrich Date: Sat, 7 Dec 2024 18:01:25 +0100 Subject: [PATCH 060/194] Update header --- src/displayapp/screens/Calculator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index d7d66054f9..d71b7a83b2 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -58,7 +58,7 @@ namespace Pinetime { int64_t value = 0; int64_t result = 0; char operation = ' '; - bool equalSignPressed = false; + bool equalSignPressedBefore = false; enum Error { TooLarge, From a3320b1bcd0344d6ffc8dbda9c9210b2d29886e7 Mon Sep 17 00:00:00 2001 From: Max Friedrich Date: Mon, 9 Dec 2024 20:07:59 +0100 Subject: [PATCH 061/194] fix constexpr position Co-authored-by: mark9064 <30447455+mark9064@users.noreply.github.com> --- src/displayapp/screens/Calculator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/Calculator.h b/src/displayapp/screens/Calculator.h index d71b7a83b2..9971f275a4 100644 --- a/src/displayapp/screens/Calculator.h +++ b/src/displayapp/screens/Calculator.h @@ -6,7 +6,7 @@ #include "Symbols.h" namespace { - int64_t constexpr powi(int64_t base, uint8_t exponent) { + constexpr int64_t powi(int64_t base, uint8_t exponent) { int64_t value = 1; while (exponent) { value *= base; From 9d13f7a859b2c04eac98116f76d5ad22cc27d283 Mon Sep 17 00:00:00 2001 From: JustScott Date: Mon, 3 Feb 2025 12:06:58 -0600 Subject: [PATCH 062/194] Add time since last weather update to weather app --- src/displayapp/screens/Weather.cpp | 23 +++++++++++++++++++++-- src/displayapp/screens/Weather.h | 9 +++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp index 25464c70cf..ceb0892c39 100644 --- a/src/displayapp/screens/Weather.cpp +++ b/src/displayapp/screens/Weather.cpp @@ -35,8 +35,10 @@ namespace { } } -Weather::Weather(Controllers::Settings& settingsController, Controllers::SimpleWeatherService& weatherService) - : settingsController {settingsController}, weatherService {weatherService} { +Weather::Weather(Controllers::Settings& settingsController, + Controllers::SimpleWeatherService& weatherService, + Controllers::DateTime& dateTimeController) + : settingsController {settingsController}, weatherService {weatherService}, dateTimeController {dateTimeController} { temperature = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); @@ -45,6 +47,11 @@ Weather::Weather(Controllers::Settings& settingsController, Controllers::SimpleW lv_obj_align(temperature, nullptr, LV_ALIGN_CENTER, 0, -30); lv_obj_set_auto_realign(temperature, true); + lastUpdated = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(lastUpdated, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::bg); + lv_label_set_text_fmt(lastUpdated, ""); + lv_obj_align(lastUpdated, nullptr, LV_ALIGN_CENTER, -40, 0); + minTemperature = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(minTemperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::bg); lv_label_set_text(minTemperature, ""); @@ -137,6 +144,18 @@ void Weather::Refresh() { lv_label_set_text_fmt(temperature, "%d°%c", temp, tempUnit); lv_label_set_text_fmt(minTemperature, "%d°", minTemp); lv_label_set_text_fmt(maxTemperature, "%d°", maxTemp); + + int64_t secondsSinceEpoch = dateTimeController.CurrentDateTime().time_since_epoch().count() / 1000000000; + int64_t secondsSinceWeatherUpdate = secondsSinceEpoch - optCurrentWeather->timestamp; + if (secondsSinceWeatherUpdate < 0) { + lv_label_set_text_fmt(lastUpdated, "0s old", secondsSinceWeatherUpdate); + } else if (secondsSinceWeatherUpdate < 60) { + lv_label_set_text_fmt(lastUpdated, "%ds old", secondsSinceWeatherUpdate); + } else if (secondsSinceWeatherUpdate > 59 && secondsSinceWeatherUpdate < 3600) { + lv_label_set_text_fmt(lastUpdated, "%dm old", secondsSinceWeatherUpdate / 60); + } else if (secondsSinceWeatherUpdate > 3599) { + lv_label_set_text_fmt(lastUpdated, "%dh old", secondsSinceWeatherUpdate / 3600); + } } else { lv_label_set_text(icon, ""); lv_label_set_text(condition, ""); diff --git a/src/displayapp/screens/Weather.h b/src/displayapp/screens/Weather.h index 6975311e06..2d41555bbc 100644 --- a/src/displayapp/screens/Weather.h +++ b/src/displayapp/screens/Weather.h @@ -4,6 +4,7 @@ #include #include "displayapp/screens/Screen.h" #include "components/ble/SimpleWeatherService.h" +#include "components/datetime/DateTimeController.h" #include "displayapp/apps/Apps.h" #include "displayapp/Controllers.h" #include "Symbols.h" @@ -20,7 +21,9 @@ namespace Pinetime { class Weather : public Screen { public: - Weather(Controllers::Settings& settingsController, Controllers::SimpleWeatherService& weatherService); + Weather(Controllers::Settings& settingsController, + Controllers::SimpleWeatherService& weatherService, + Controllers::DateTime& dateTimeController); ~Weather() override; void Refresh() override; @@ -28,6 +31,7 @@ namespace Pinetime { private: Controllers::Settings& settingsController; Controllers::SimpleWeatherService& weatherService; + Controllers::DateTime& dateTimeController; Utility::DirtyValue> currentWeather {}; Utility::DirtyValue> currentForecast {}; @@ -35,6 +39,7 @@ namespace Pinetime { lv_obj_t* icon; lv_obj_t* condition; lv_obj_t* temperature; + lv_obj_t* lastUpdated; lv_obj_t* minTemperature; lv_obj_t* maxTemperature; lv_obj_t* forecast; @@ -49,7 +54,7 @@ namespace Pinetime { static constexpr const char* icon = Screens::Symbols::cloudSunRain; static Screens::Screen* Create(AppControllers& controllers) { - return new Screens::Weather(controllers.settingsController, *controllers.weatherController); + return new Screens::Weather(controllers.settingsController, *controllers.weatherController, controllers.dateTimeController); }; }; } From b542e26c269355d74ded5a5d151e91281e97d714 Mon Sep 17 00:00:00 2001 From: JustScott Date: Tue, 4 Feb 2025 22:48:27 -0600 Subject: [PATCH 063/194] Replace 'old' with 'ago' and adjust positioning --- src/displayapp/screens/Weather.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp index ceb0892c39..055b3b07f7 100644 --- a/src/displayapp/screens/Weather.cpp +++ b/src/displayapp/screens/Weather.cpp @@ -44,13 +44,13 @@ Weather::Weather(Controllers::Settings& settingsController, lv_obj_set_style_local_text_color(temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); lv_obj_set_style_local_text_font(temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text(temperature, "---"); - lv_obj_align(temperature, nullptr, LV_ALIGN_CENTER, 0, -30); + lv_obj_align(temperature, nullptr, LV_ALIGN_CENTER, 0, -32); lv_obj_set_auto_realign(temperature, true); lastUpdated = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(lastUpdated, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::bg); lv_label_set_text_fmt(lastUpdated, ""); - lv_obj_align(lastUpdated, nullptr, LV_ALIGN_CENTER, -40, 0); + lv_obj_align(lastUpdated, nullptr, LV_ALIGN_CENTER, -40, -1); minTemperature = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(minTemperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::bg); @@ -148,13 +148,13 @@ void Weather::Refresh() { int64_t secondsSinceEpoch = dateTimeController.CurrentDateTime().time_since_epoch().count() / 1000000000; int64_t secondsSinceWeatherUpdate = secondsSinceEpoch - optCurrentWeather->timestamp; if (secondsSinceWeatherUpdate < 0) { - lv_label_set_text_fmt(lastUpdated, "0s old", secondsSinceWeatherUpdate); + lv_label_set_text_fmt(lastUpdated, "0s ago", secondsSinceWeatherUpdate); } else if (secondsSinceWeatherUpdate < 60) { - lv_label_set_text_fmt(lastUpdated, "%ds old", secondsSinceWeatherUpdate); + lv_label_set_text_fmt(lastUpdated, "%ds ago", secondsSinceWeatherUpdate); } else if (secondsSinceWeatherUpdate > 59 && secondsSinceWeatherUpdate < 3600) { - lv_label_set_text_fmt(lastUpdated, "%dm old", secondsSinceWeatherUpdate / 60); + lv_label_set_text_fmt(lastUpdated, "%dm ago", secondsSinceWeatherUpdate / 60); } else if (secondsSinceWeatherUpdate > 3599) { - lv_label_set_text_fmt(lastUpdated, "%dh old", secondsSinceWeatherUpdate / 3600); + lv_label_set_text_fmt(lastUpdated, "%dh ago", secondsSinceWeatherUpdate / 3600); } } else { lv_label_set_text(icon, ""); From 6cd398826b407136b4a79bd99fc8bd93c66f009d Mon Sep 17 00:00:00 2001 From: JustScott Date: Fri, 7 Feb 2025 04:38:50 -0600 Subject: [PATCH 064/194] Updated labels, improved/simplified logic, and improved positioning Use "Now" for the label until 31 seconds, then display the live time. --- src/displayapp/screens/Weather.cpp | 31 ++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp index 055b3b07f7..29ce2f28dc 100644 --- a/src/displayapp/screens/Weather.cpp +++ b/src/displayapp/screens/Weather.cpp @@ -50,7 +50,6 @@ Weather::Weather(Controllers::Settings& settingsController, lastUpdated = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(lastUpdated, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::bg); lv_label_set_text_fmt(lastUpdated, ""); - lv_obj_align(lastUpdated, nullptr, LV_ALIGN_CENTER, -40, -1); minTemperature = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(minTemperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::bg); @@ -145,21 +144,33 @@ void Weather::Refresh() { lv_label_set_text_fmt(minTemperature, "%d°", minTemp); lv_label_set_text_fmt(maxTemperature, "%d°", maxTemp); - int64_t secondsSinceEpoch = dateTimeController.CurrentDateTime().time_since_epoch().count() / 1000000000; - int64_t secondsSinceWeatherUpdate = secondsSinceEpoch - optCurrentWeather->timestamp; - if (secondsSinceWeatherUpdate < 0) { - lv_label_set_text_fmt(lastUpdated, "0s ago", secondsSinceWeatherUpdate); - } else if (secondsSinceWeatherUpdate < 60) { + std::chrono::seconds secondsSinceEpoch = + std::chrono::duration_cast(dateTimeController.CurrentDateTime().time_since_epoch()); + int32_t secondsSinceWeatherUpdate = secondsSinceEpoch.count() - optCurrentWeather->timestamp; + int8_t minutesSinceWeatherUpdate = secondsSinceWeatherUpdate / 60; + int8_t hoursSinceWeatherUpdate = secondsSinceWeatherUpdate / 3600; + + lv_obj_align(lastUpdated, nullptr, LV_ALIGN_CENTER, -31, -1); + if ((secondsSinceWeatherUpdate > 9 && secondsSinceWeatherUpdate < 60) || + (minutesSinceWeatherUpdate > 9 && minutesSinceWeatherUpdate < 60) || hoursSinceWeatherUpdate > 9) { + lv_obj_align(lastUpdated, nullptr, LV_ALIGN_CENTER, -41, -1); + } + + if (hoursSinceWeatherUpdate > 0) { + lv_label_set_text_fmt(lastUpdated, "%dh ago", hoursSinceWeatherUpdate); + } else if (minutesSinceWeatherUpdate > 0) { + lv_label_set_text_fmt(lastUpdated, "%dm ago", minutesSinceWeatherUpdate); + } else if (secondsSinceWeatherUpdate > 30) { lv_label_set_text_fmt(lastUpdated, "%ds ago", secondsSinceWeatherUpdate); - } else if (secondsSinceWeatherUpdate > 59 && secondsSinceWeatherUpdate < 3600) { - lv_label_set_text_fmt(lastUpdated, "%dm ago", secondsSinceWeatherUpdate / 60); - } else if (secondsSinceWeatherUpdate > 3599) { - lv_label_set_text_fmt(lastUpdated, "%dh ago", secondsSinceWeatherUpdate / 3600); + } else if (secondsSinceWeatherUpdate < 31) { + lv_obj_align(lastUpdated, nullptr, LV_ALIGN_CENTER, -18, -1); + lv_label_set_text_fmt(lastUpdated, "Now", secondsSinceWeatherUpdate); } } else { lv_label_set_text(icon, ""); lv_label_set_text(condition, ""); lv_label_set_text(temperature, "---"); + lv_label_set_text(lastUpdated, ""); lv_obj_set_style_local_text_color(temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); lv_label_set_text(minTemperature, ""); lv_label_set_text(maxTemperature, ""); From cb4e7d655b5fd867074755f82bc7f481acfffad4 Mon Sep 17 00:00:00 2001 From: JustScott Date: Sat, 8 Feb 2025 12:13:59 -0600 Subject: [PATCH 065/194] Fixed positioning Move from `lv_obj_align` to `lv_obj_set_pos` to avoid weird positioning errors when changing the position more than once. --- src/displayapp/screens/Weather.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp index 29ce2f28dc..c8debd81f0 100644 --- a/src/displayapp/screens/Weather.cpp +++ b/src/displayapp/screens/Weather.cpp @@ -49,7 +49,7 @@ Weather::Weather(Controllers::Settings& settingsController, lastUpdated = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(lastUpdated, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::bg); - lv_label_set_text_fmt(lastUpdated, ""); + lv_label_set_text(lastUpdated, ""); minTemperature = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(minTemperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::bg); @@ -150,20 +150,30 @@ void Weather::Refresh() { int8_t minutesSinceWeatherUpdate = secondsSinceWeatherUpdate / 60; int8_t hoursSinceWeatherUpdate = secondsSinceWeatherUpdate / 3600; - lv_obj_align(lastUpdated, nullptr, LV_ALIGN_CENTER, -31, -1); - if ((secondsSinceWeatherUpdate > 9 && secondsSinceWeatherUpdate < 60) || - (minutesSinceWeatherUpdate > 9 && minutesSinceWeatherUpdate < 60) || hoursSinceWeatherUpdate > 9) { - lv_obj_align(lastUpdated, nullptr, LV_ALIGN_CENTER, -41, -1); - } + constexpr uint8_t Y_POSITION = 108; + constexpr uint8_t X_SINGLE_DIGIT_POSITION = 90; + constexpr uint8_t X_TWO_DIGIT_POSITION = 78; + constexpr uint8_t X_NOW_POSITION = 102; + + lv_obj_set_pos(lastUpdated, X_SINGLE_DIGIT_POSITION, Y_POSITION); if (hoursSinceWeatherUpdate > 0) { + if (hoursSinceWeatherUpdate > 9) { + lv_obj_set_pos(lastUpdated, X_TWO_DIGIT_POSITION, Y_POSITION); + } lv_label_set_text_fmt(lastUpdated, "%dh ago", hoursSinceWeatherUpdate); } else if (minutesSinceWeatherUpdate > 0) { + if (minutesSinceWeatherUpdate > 9 && minutesSinceWeatherUpdate < 60) { + lv_obj_set_pos(lastUpdated, X_TWO_DIGIT_POSITION, Y_POSITION); + } lv_label_set_text_fmt(lastUpdated, "%dm ago", minutesSinceWeatherUpdate); } else if (secondsSinceWeatherUpdate > 30) { + if (secondsSinceWeatherUpdate > 9 && secondsSinceWeatherUpdate < 60) { + lv_obj_set_pos(lastUpdated, X_TWO_DIGIT_POSITION, Y_POSITION); + } lv_label_set_text_fmt(lastUpdated, "%ds ago", secondsSinceWeatherUpdate); } else if (secondsSinceWeatherUpdate < 31) { - lv_obj_align(lastUpdated, nullptr, LV_ALIGN_CENTER, -18, -1); + lv_obj_set_pos(lastUpdated, X_NOW_POSITION, Y_POSITION); lv_label_set_text_fmt(lastUpdated, "Now", secondsSinceWeatherUpdate); } } else { From ecba7b8de4aa7d44a106abf188717bdb0031f8d3 Mon Sep 17 00:00:00 2001 From: Darius Arnold Date: Sun, 23 Feb 2025 15:39:27 +0000 Subject: [PATCH 066/194] Set build context directory in devcontainer.json Otherwise the default build context is the top level directory when building the dev container in JetBrain IDEs. VsCode seems to use the Dockerfile location as build context instead, meaning the container build works by default here. --- .devcontainer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.devcontainer.json b/.devcontainer.json index 95a27dac74..813f92cc3a 100644 --- a/.devcontainer.json +++ b/.devcontainer.json @@ -2,7 +2,8 @@ // https://github.com/microsoft/vscode-dev-containers/tree/v0.154.2/containers/cpp { "build": { - "dockerfile": "docker/Dockerfile" + "dockerfile": "docker/Dockerfile", + "context": "docker", }, "customizations": { "vscode": { From 228e7f2086bd9d9c52dedded31264580a2b1ce8d Mon Sep 17 00:00:00 2001 From: Darius Arnold Date: Wed, 26 Feb 2025 20:29:43 +0000 Subject: [PATCH 067/194] Install sudo and ninja in the dev container Dockerfile --- docker/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/Dockerfile b/docker/Dockerfile index e6d92aae96..cc63c343f5 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -15,11 +15,13 @@ RUN apt-get update -qq \ cmake \ git \ make \ + ninja-build \ nodejs \ python3 \ python3-pip \ python3-pil \ python-is-python3 \ + sudo \ tar \ unzip \ wget \ From 4a0f2cbef86b2d2eef353a7a140d609d596ed6a8 Mon Sep 17 00:00:00 2001 From: Darius Arnold Date: Sat, 1 Mar 2025 16:43:07 +0000 Subject: [PATCH 068/194] Add basic CMakePresets.json file Everything is set to work in the dev container by default. --- CMakePresets.json | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 CMakePresets.json diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000000..0cb47a4448 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,68 @@ +{ + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 22, + "patch": 0 + }, + "configurePresets": [ + { + "name": "base", + "description": "Default build using devcontainer tools", + "generator": "Ninja", + "hidden": true, + "cacheVariables": { + "ARM_NONE_EABI_TOOLCHAIN_PATH": { + "type": "PATH", + "value": "/opt/gcc-arm-none-eabi-10.3-2021.10" + }, + "NRF5_SDK_PATH": { + "type": "PATH", + "value": "/opt/nRF5_SDK_15.3.0_59ac345" + }, + "BUILD_DFU": { + "type": "BOOL", + "value": "ON" + }, + "BUILD_RESOURCES": { + "type": "BOOL", + "value": "ON" + }, + "TARGET_DEVICE": { + "type": "STRING", + "value": "PINETIME" + } + } + }, + { + "name": "pinetime-debug", + "inherits": "base", + "displayName": "Pinetime Debug", + "description": "Debug build using Ninja", + "binaryDir": "build/debug", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "pinetime-release", + "inherits": "base", + "displayName": "Pinetime Release", + "description": "Release build using Ninja", + "binaryDir": "build/release", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + } + ], + "buildPresets": [ + { + "name": "pinetime-release", + "configurePreset": "pinetime-release" + }, + { + "name": "pinetime-debug", + "configurePreset": "pinetime-debug" + } + ] +} From ba78fff1909a50489e71633e2292a21fc05d24bd Mon Sep 17 00:00:00 2001 From: Darius Arnold Date: Sat, 1 Mar 2025 16:43:19 +0000 Subject: [PATCH 069/194] Add build script --- build.sh | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100755 build.sh diff --git a/build.sh b/build.sh new file mode 100755 index 0000000000..78dc9178b0 --- /dev/null +++ b/build.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set euo -pipefail + +cmake --preset pinetime-release +cmake --build --preset pinetime-release From 7aa6ca7ffed2b6460dee550cde5ab3f3a21662bc Mon Sep 17 00:00:00 2001 From: Darius Arnold Date: Sat, 1 Mar 2025 19:50:04 +0000 Subject: [PATCH 070/194] Make vibration after timer ends more noticable Replace the single short vibration after timer ends with three ones with longer duration. The single short pulse was very easy to miss. --- src/displayapp/DisplayApp.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 6671ac9e51..4768f63400 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -372,7 +372,11 @@ void DisplayApp::Refresh() { } else { LoadNewScreen(Apps::Timer, DisplayApp::FullRefreshDirections::Up); } - motorController.RunForDuration(35); + motorController.RunForDuration(100); + vTaskDelay(pdMS_TO_TICKS(500)); + motorController.RunForDuration(100); + vTaskDelay(pdMS_TO_TICKS(500)); + motorController.RunForDuration(100); break; case Messages::AlarmTriggered: if (currentApp == Apps::Alarm) { From 375740bec3dcc4b3c4586a226e53f294979e4bbd Mon Sep 17 00:00:00 2001 From: Darius Arnold Date: Sat, 1 Mar 2025 20:51:13 +0000 Subject: [PATCH 071/194] Set sudo password for developer user in dev container This makes it possible to do live changes in a running container and debug issues there before adding to Dockerfile. --- docker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index cc63c343f5..9f3f26374c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -64,8 +64,8 @@ RUN bash -c "source /opt/build.sh; GetNrfSdk;" # McuBoot RUN bash -c "source /opt/build.sh; GetMcuBoot;" -# Add the infinitime user for connecting devcontainer -RUN adduser infinitime +# Add the infinitime user with sudo password "it" for developing in devcontainer +RUN adduser infinitime && echo "infinitime:it" | chpasswd && usermod -aG sudo infinitime # Configure Git to accept the /sources directory as safe RUN git config --global --add safe.directory /sources From e4aaad6c31e3d6c08dcc4e0ee3cef442b49fe186 Mon Sep 17 00:00:00 2001 From: Darius Arnold Date: Sat, 1 Mar 2025 20:56:23 +0000 Subject: [PATCH 072/194] Add option to enable ccache to build - Add ENABLE_CCACHE flag to cmake - Install ccache in dev container - Always enable caching in CMakePresets.json --- CMakeLists.txt | 4 ++++ CMakePresets.json | 4 ++++ cmake/ccache.cmake | 14 ++++++++++++++ docker/Dockerfile | 1 + 4 files changed, 23 insertions(+) create mode 100644 cmake/ccache.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 3250982d6a..6e0fbe3d4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,10 @@ if(BUILD_RESOURCES) set(BUILD_RESOURCES true) endif() +if(ENABLE_CCACHE) + include(cmake/ccache.cmake) +endif() + set(TARGET_DEVICE "PINETIME" CACHE STRING "Target device") set_property(CACHE TARGET_DEVICE PROPERTY STRINGS PINETIME MOY_TFK5 MOY_TIN5 MOY_TON5 MOY_UNK) diff --git a/CMakePresets.json b/CMakePresets.json index 0cb47a4448..3d94774fd6 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -31,6 +31,10 @@ "TARGET_DEVICE": { "type": "STRING", "value": "PINETIME" + }, + "ENABLE_CCACHE": { + "type": "BOOL", + "value": true } } }, diff --git a/cmake/ccache.cmake b/cmake/ccache.cmake new file mode 100644 index 0000000000..e9dccaa9ed --- /dev/null +++ b/cmake/ccache.cmake @@ -0,0 +1,14 @@ +find_program(CCACHE_EXECUTABLE ccache) + +if (CCACHE_EXECUTABLE) + message(STATUS "Activating ccache compiler cache.") + set(ccacheEnv + CCACHE_SLOPPINESS=pch_defines + ) + foreach (lang IN ITEMS C CXX) + set(CMAKE_${lang}_COMPILER_LAUNCHER + ${CMAKE_COMMAND} -E env ${ccacheEnv} ${CCACHE_EXECUTABLE} + ) + endforeach () + message(WARNING "Ccache could not be activated because ccache executable was not found.") +endif () diff --git a/docker/Dockerfile b/docker/Dockerfile index 9f3f26374c..95df5a64b8 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -12,6 +12,7 @@ RUN apt-get update -qq \ # x86_64 / generic packages bash \ build-essential \ + ccache \ cmake \ git \ make \ From 0ca74511ae40aadb76d1455a35f7a83216745bbb Mon Sep 17 00:00:00 2001 From: Darius Arnold Date: Sun, 2 Mar 2025 19:43:08 +0000 Subject: [PATCH 073/194] Increase size of the alarm info button This button shows the duration of the alarm but is hard to hit with the default size. --- src/displayapp/screens/Alarm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/Alarm.cpp b/src/displayapp/screens/Alarm.cpp index 4cf4392157..372c13c82c 100644 --- a/src/displayapp/screens/Alarm.cpp +++ b/src/displayapp/screens/Alarm.cpp @@ -98,7 +98,7 @@ Alarm::Alarm(Controllers::AlarmController& alarmController, 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_set_size(btnInfo, 62, 62); 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); From d756e911716a9e75478296c152f5decc0755db10 Mon Sep 17 00:00:00 2001 From: cyberneel Date: Wed, 2 Oct 2024 15:27:11 -0500 Subject: [PATCH 074/194] 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 075/194] 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 076/194] 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 077/194] 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 078/194] 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 079/194] 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 080/194] 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 081/194] 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 082/194] 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 083/194] 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 084/194] 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 085/194] 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 086/194] 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 087/194] 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 088/194] 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 089/194] 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 090/194] 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 091/194] 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 092/194] 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 093/194] 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 094/194] 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 095/194] 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 096/194] 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 097/194] 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 098/194] 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 099/194] 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 100/194] 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 101/194] 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 102/194] 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 103/194] 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 104/194] 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 105/194] 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 106/194] 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 107/194] 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 108/194] 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 109/194] 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 110/194] 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 111/194] 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 112/194] 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 113/194] 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 114/194] 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 115/194] 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 116/194] 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 117/194] 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 118/194] 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 119/194] 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 120/194] 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 121/194] 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 122/194] 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 123/194] 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 124/194] 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 125/194] 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 126/194] 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 127/194] 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 128/194] 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 129/194] 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 130/194] 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 131/194] 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 132/194] 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 133/194] 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 134/194] 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 135/194] 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 136/194] 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 137/194] 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 138/194] 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 139/194] 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 140/194] 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 141/194] 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 142/194] 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 143/194] 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 144/194] 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 145/194] 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 146/194] 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 147/194] 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 148/194] 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 149/194] 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 150/194] 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 151/194] 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 152/194] 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 153/194] 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 154/194] 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 155/194] 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 156/194] 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 157/194] 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 158/194] 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 159/194] 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 160/194] 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 161/194] 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 162/194] 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 163/194] 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 164/194] 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 165/194] 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 166/194] 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 167/194] 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 168/194] 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 169/194] 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 170/194] 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 171/194] 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 172/194] 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 173/194] 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 174/194] 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 175/194] 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 176/194] 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 177/194] 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 178/194] 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 179/194] 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 180/194] 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 181/194] 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 182/194] 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 183/194] 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 184/194] 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 185/194] 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 186/194] 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 187/194] 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 188/194] 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 189/194] 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 190/194] 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 191/194] 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 192/194] 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 193/194] 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 194/194] 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,