From 1770866d5ec5911f022d0f0238a6bf447885d823 Mon Sep 17 00:00:00 2001 From: minacode Date: Sat, 3 Dec 2022 23:09:24 +0100 Subject: [PATCH 01/47] 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 fd8ece62..29fdb946 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 3fd34b3a..ad63d36a 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 00000000..8a9def68 --- /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 00000000..c90b1b38 --- /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 02/47] 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 8a9def68..152a5748 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 03/47] 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 c90b1b38..2d12e68f 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 04/47] 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 152a5748..bd4908a4 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 2d12e68f..b74ff7bd 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 05/47] 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 bd4908a4..40ad5654 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 06/47] 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 41c383c0..61546450 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 bd958b28..f3b098fc 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 07/47] 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 40ad5654..fc051360 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); } + } +} - // show operation - lv_label_set_text_static(operationLabel, &operation); +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; + } + + // 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 b74ff7bd..db1603b6 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 08/47] 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 fc051360..a392672c 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 09/47] fixed number displays --- src/displayapp/screens/Calculator.cpp | 121 ++++++++++++++++++-------- src/displayapp/screens/Calculator.h | 5 +- 2 files changed, 87 insertions(+), 39 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index a392672c..29f7437c 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 { - lv_label_set_text_fmt(label, "%d", number / FIXED_POINT_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); + 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( + 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 db1603b6..5bcec86a 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 10/47] 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 29f7437c..5153afa5 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 5bcec86a..52ff6d4b 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 11/47] 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 5153afa5..228dbadb 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 52ff6d4b..cd97744c 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 12/47] 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 228dbadb..c3b119f3 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 13/47] 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 c3b119f3..025d0782 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 cd97744c..3a6f9ae4 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 14/47] WIP: refactored the prints --- src/displayapp/screens/Calculator.cpp | 60 +++++++++++++-------------- src/displayapp/screens/Calculator.h | 24 +++++++++-- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index 025d0782..7ebcc829 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; + uint8_t min_width = 0; + int64_t tmp_offset = offset; - // 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; - } + // 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 3a6f9ae4..dac520cf 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 15/47] 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 7ebcc829..b99abf06 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 dac520cf..593cbc21 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 16/47] 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 61546450..8f2a65d9 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 b99abf06..43922f64 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 f3b098fc..40699b3d 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 17/47] 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 43922f64..3a08fa84 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 593cbc21..90e2b4a2 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 18/47] 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 3a08fa84..61e41452 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 19/47] 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 61e41452..6f8596ca 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 20/47] 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 6f8596ca..eaffbf7d 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 21/47] colored current button --- src/displayapp/screens/Calculator.cpp | 311 +++++++++++++------------- src/displayapp/screens/Calculator.h | 1 + 2 files changed, 162 insertions(+), 150 deletions(-) diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp index eaffbf7d..e39fe4e6 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 (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(); - - 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(); - - 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(); - } - - 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 (*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 - - 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; - } + 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; + } + + // 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; + + 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(); + } + + 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 (*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 + + 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 90e2b4a2..0f68199e 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 22/47] 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 e39fe4e6..5acd6a6d 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 23/47] 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 5acd6a6d..3fac476a 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 0f68199e..a2223bd2 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 24/47] 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 3fac476a..36bfba6b 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 a2223bd2..00cefdb3 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 25/47] 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 36bfba6b..6b7a6349 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 26/47] 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 6b7a6349..2fc7d1fe 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 00cefdb3..d9554429 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 27/47] 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 2fc7d1fe..4ef66c7b 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 d9554429..4a6969c3 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 28/47] 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 4ef66c7b..7340e483 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 29/47] 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 7340e483..e486fa4c 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 30/47] 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 e486fa4c..6193c74d 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 31/47] 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 0690b099..9ceb0877 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 6193c74d..8efc0ee5 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 32/47] 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 8efc0ee5..1e03d4fa 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 33/47] 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 1e03d4fa..9bb735be 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 34/47] 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 9bb735be..b4cc003f 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 35/47] 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 b4cc003f..44d08752 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 4a6969c3..f6576130 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 36/47] 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 9ceb0877..0690b099 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 44d08752..8b1b5a7d 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 f6576130..17513861 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 37/47] 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 8b1b5a7d..fddb0db2 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 38/47] 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 fddb0db2..e5d38810 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 39/47] 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 e5d38810..a311ee0f 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 40/47] 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 17513861..2111c298 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 41/47] 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 2111c298..dcfc65fe 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 42/47] 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 dcfc65fe..3b23a8a6 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 43/47] 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 67c33a34..930ec764 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 44/47] 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 2104a267..e697096a 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 d7858760..33e54323 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 3b23a8a6..99d86e75 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 45/47] 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 930ec764..4696e386 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 46/47] 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 8f2a65d9..152a42e9 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 47/47] 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 a311ee0f..81bf2f62 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;