From b8d149518bf9f0c00d3e21ba13c0e9d5170120ab Mon Sep 17 00:00:00 2001 From: redraw Date: Mon, 15 Sep 2025 22:24:46 -0300 Subject: [PATCH 1/5] add RPN calculator alt face --- .../complication/rpn_calculator_alt_face.c | 21 ++++++++++++++++++- .../complication/rpn_calculator_alt_face.h | 0 2 files changed, 20 insertions(+), 1 deletion(-) rename {legacy/watch_faces => watch-faces}/complication/rpn_calculator_alt_face.c (96%) rename {legacy/watch_faces => watch-faces}/complication/rpn_calculator_alt_face.h (100%) diff --git a/legacy/watch_faces/complication/rpn_calculator_alt_face.c b/watch-faces/complication/rpn_calculator_alt_face.c similarity index 96% rename from legacy/watch_faces/complication/rpn_calculator_alt_face.c rename to watch-faces/complication/rpn_calculator_alt_face.c index 03a75ec89..3edced9e0 100644 --- a/legacy/watch_faces/complication/rpn_calculator_alt_face.c +++ b/watch-faces/complication/rpn_calculator_alt_face.c @@ -28,6 +28,14 @@ #include "rpn_calculator_alt_face.h" +#ifndef M_PI +#define M_PI 3.14159 +#endif + +#ifndef M_E +#define M_E 2.71828 +#endif + static void show_fn(calculator_state_t *state, uint8_t subsecond); void rpn_calculator_alt_face_setup(uint8_t watch_face_index, void ** context_ptr) { @@ -41,6 +49,12 @@ void rpn_calculator_alt_face_setup(uint8_t watch_face_index, void ** context_ptr // Do any pin or peripheral setup here; this will be called whenever the watch wakes from deep sleep. } +static void show_stack_size(calculator_state_t *state) { + char buf[2]; + sprintf(buf, " %d", state->stack_size); + watch_display_text(WATCH_POSITION_TOP_RIGHT, buf); +} + static void show_number(double num) { char buf[9] = {0}; bool negative = num < 0; @@ -302,7 +316,7 @@ struct { }; #define FUNCTIONS_LEN (sizeof(functions) / sizeof(functions[0])) -#define SECONDARY_FN_INDEX (FUNCTIONS_LEN - 4) +#define SECONDARY_FN_INDEX (FUNCTIONS_LEN - 5) // Show the function name (using day display) static void show_fn(calculator_state_t *s, uint8_t subsecond) { @@ -355,6 +369,11 @@ bool rpn_calculator_alt_face_loop(movement_event_t event, void *context) { case EVENT_TICK: if (s->mode == CALC_OPERATION) { show_fn(s, event.subsecond); + if (s->fn_index == 0) { + show_stack_top(s); + } else if (s->fn_index >= SECONDARY_FN_INDEX) { + show_stack_size(s); + } } break; case EVENT_MODE_BUTTON_UP: diff --git a/legacy/watch_faces/complication/rpn_calculator_alt_face.h b/watch-faces/complication/rpn_calculator_alt_face.h similarity index 100% rename from legacy/watch_faces/complication/rpn_calculator_alt_face.h rename to watch-faces/complication/rpn_calculator_alt_face.h From 725c84f740ecf246e16019da8f08a315d883cba3 Mon Sep 17 00:00:00 2001 From: redraw Date: Tue, 16 Sep 2025 15:39:22 -0300 Subject: [PATCH 2/5] rpn calculator alt: add OVER fn --- watch-faces/complication/rpn_calculator_alt_face.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/watch-faces/complication/rpn_calculator_alt_face.c b/watch-faces/complication/rpn_calculator_alt_face.c index 3edced9e0..28d68036b 100644 --- a/watch-faces/complication/rpn_calculator_alt_face.c +++ b/watch-faces/complication/rpn_calculator_alt_face.c @@ -272,6 +272,11 @@ static void fn_swap(calculator_state_t *s) { PUSH(b); } +static void fn_over(calculator_state_t *s) { + double a = s->stack[s->stack_size - 2]; + PUSH(a); +} + static void fn_duplicate(calculator_state_t *s) { double a = POP(); PUSH(a); @@ -310,13 +315,14 @@ struct { // Stack operations. Accessible via secondary_fn_index (i.e. alarm long press). {{'P', 'O'}, 1, 0, fn_pop}, // This ends up displaying the same as 'POW'. But at least it's in a different place. {{'S', 'W'}, 2, 2, fn_swap}, + {{'O', 'v'}, 2, 1, fn_over}, {{'d', 'u'}, 1, 1, fn_duplicate}, // Uppercase 'D' is a bit too 'O' for me. {{'C', 'L'}, 1, 0, fn_clear}, // Operation lie - takes _everything_ off the stack, but a check of 1 is sufficient. {{'L', 'E'}, 1, 0, fn_size}, }; #define FUNCTIONS_LEN (sizeof(functions) / sizeof(functions[0])) -#define SECONDARY_FN_INDEX (FUNCTIONS_LEN - 5) +#define SECONDARY_FN_INDEX (FUNCTIONS_LEN - 6) // Show the function name (using day display) static void show_fn(calculator_state_t *s, uint8_t subsecond) { From 8d1f2a1030c4392be0bf12fe44910ed5b4525dfc Mon Sep 17 00:00:00 2001 From: redraw Date: Wed, 17 Sep 2025 20:54:24 -0300 Subject: [PATCH 3/5] rpn calculator alt: add peek mode --- .../complication/rpn_calculator_alt_face.c | 60 ++++++++++++++++++- .../complication/rpn_calculator_alt_face.h | 3 +- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/watch-faces/complication/rpn_calculator_alt_face.c b/watch-faces/complication/rpn_calculator_alt_face.c index 28d68036b..dcf3f2702 100644 --- a/watch-faces/complication/rpn_calculator_alt_face.c +++ b/watch-faces/complication/rpn_calculator_alt_face.c @@ -49,12 +49,16 @@ void rpn_calculator_alt_face_setup(uint8_t watch_face_index, void ** context_ptr // Do any pin or peripheral setup here; this will be called whenever the watch wakes from deep sleep. } -static void show_stack_size(calculator_state_t *state) { +static void show_stack_index(uint8_t index) { char buf[2]; - sprintf(buf, " %d", state->stack_size); + sprintf(buf, "%2d", index); watch_display_text(WATCH_POSITION_TOP_RIGHT, buf); } +static void show_stack_size(calculator_state_t *state) { + show_stack_index(state->stack_size); +} + static void show_number(double num) { char buf[9] = {0}; bool negative = num < 0; @@ -146,6 +150,9 @@ void rpn_calculator_alt_face_activate(void *context) { static void change_mode(calculator_state_t *s, enum calculator_mode mode) { s->mode = mode; s->fn_index = 0; + if (mode == CALC_PEEK) { + s->peek_index = s->stack_size > 0 ? s->stack_size - 1 : 0; + } show_fn(s, 0); // Faster tick in operation mode so we can blink. movement_request_tick_frequency(mode == CALC_OPERATION ? 4 : 1); @@ -362,6 +369,20 @@ static void show_stack_top(calculator_state_t *s) { } } +// Show peek mode indicator and stack position +static void show_peek_mode(calculator_state_t *s) { + watch_display_string("ST", 0); + show_peek_value(s); +} + +// Show the stack value at peek_index +static void show_peek_value(calculator_state_t *s) { + if (s->stack_size > 0 && s->peek_index < s->stack_size) { + show_number(s->stack[s->peek_index]); + show_stack_index(s->peek_index + 1); + } +} + bool rpn_calculator_alt_face_loop(movement_event_t event, void *context) { calculator_state_t *s = (calculator_state_t *)context; @@ -380,18 +401,37 @@ bool rpn_calculator_alt_face_loop(movement_event_t event, void *context) { } else if (s->fn_index >= SECONDARY_FN_INDEX) { show_stack_size(s); } + } else if (s->mode == CALC_PEEK) { + show_peek_mode(s); + show_peek_value(s); } break; case EVENT_MODE_BUTTON_UP: if (s->mode == CALC_NUMBER) { adjust_number(s, -1); show_stack_top(s); + } else if (s->mode == CALC_PEEK) { + // Navigate down the stack (towards index 0) + if (s->peek_index > 0) { + s->peek_index--; + show_peek_mode(s); + show_peek_value(s); + } } else { movement_move_to_next_face(); return false; } break; case EVENT_LIGHT_BUTTON_DOWN: + break; + case EVENT_LIGHT_BUTTON_UP: + if (s->mode == CALC_PEEK) { + // Exit peek mode and return to operation mode + change_mode(s, CALC_OPERATION); + show_stack_top(s); + break; + } + proposed_stack_size = s->stack_size - functions[s->fn_index].input; if (s->mode == CALC_NUMBER) { @@ -411,11 +451,26 @@ bool rpn_calculator_alt_face_loop(movement_event_t event, void *context) { if (s->mode == CALC_NUMBER) { adjust_number(s, 1); show_stack_top(s); + } else if (s->mode == CALC_PEEK) { + // Navigate up the stack (towards stack top) + if (s->peek_index < s->stack_size - 1) { + s->peek_index++; + show_peek_mode(s); + show_peek_value(s); + } } else { s->fn_index = (s->fn_index + 1) % FUNCTIONS_LEN; show_fn(s, 0); } break; + case EVENT_LIGHT_LONG_PRESS: + if (s->stack_size > 0) { + // Enter peek mode to view the stack + change_mode(s, CALC_PEEK); + show_peek_mode(s); + show_peek_value(s); + } + break; case EVENT_ALARM_LONG_PRESS: if (s->mode == CALC_OPERATION) { if (s->fn_index == 0) { @@ -446,4 +501,3 @@ void rpn_calculator_alt_face_resign(void *context) { // handle any cleanup before your watch face goes off-screen. } - diff --git a/watch-faces/complication/rpn_calculator_alt_face.h b/watch-faces/complication/rpn_calculator_alt_face.h index 4e74115a9..fa563a621 100644 --- a/watch-faces/complication/rpn_calculator_alt_face.h +++ b/watch-faces/complication/rpn_calculator_alt_face.h @@ -66,6 +66,7 @@ enum calculator_mode { CALC_OPERATION = 0, CALC_NUMBER, + CALC_PEEK, }; typedef struct { @@ -77,6 +78,7 @@ typedef struct { double max; enum calculator_mode mode; + uint8_t peek_index; // index for stack viewing in peek mode } calculator_state_t; void rpn_calculator_alt_face_setup(uint8_t watch_face_index, void ** context_ptr); @@ -93,4 +95,3 @@ void rpn_calculator_alt_face_resign(void *context); }) #endif // CALCULATOR_FACE_H_ - From 3ff6358612a73bf389379621d317e5dc6e37b58b Mon Sep 17 00:00:00 2001 From: redraw Date: Wed, 17 Sep 2025 20:56:45 -0300 Subject: [PATCH 4/5] rpn calculator alt: refactor loop into mode handlers --- .../complication/rpn_calculator_alt_face.c | 175 ++++++++++-------- 1 file changed, 96 insertions(+), 79 deletions(-) diff --git a/watch-faces/complication/rpn_calculator_alt_face.c b/watch-faces/complication/rpn_calculator_alt_face.c index dcf3f2702..79df8313a 100644 --- a/watch-faces/complication/rpn_calculator_alt_face.c +++ b/watch-faces/complication/rpn_calculator_alt_face.c @@ -369,12 +369,6 @@ static void show_stack_top(calculator_state_t *s) { } } -// Show peek mode indicator and stack position -static void show_peek_mode(calculator_state_t *s) { - watch_display_string("ST", 0); - show_peek_value(s); -} - // Show the stack value at peek_index static void show_peek_value(calculator_state_t *s) { if (s->stack_size > 0 && s->peek_index < s->stack_size) { @@ -383,60 +377,31 @@ static void show_peek_value(calculator_state_t *s) { } } -bool rpn_calculator_alt_face_loop(movement_event_t event, void *context) { - calculator_state_t *s = (calculator_state_t *)context; +// Show peek mode indicator and stack position +static void show_peek_mode(calculator_state_t *s) { + watch_display_string("ST", 0); + show_peek_value(s); +} +// Handle events in operation mode +static bool handle_operation_mode(movement_event_t event, calculator_state_t *s) { int proposed_stack_size; switch (event.event_type) { - case EVENT_ACTIVATE: - change_mode(s, CALC_OPERATION); - show_stack_top(s); - break; case EVENT_TICK: - if (s->mode == CALC_OPERATION) { - show_fn(s, event.subsecond); - if (s->fn_index == 0) { - show_stack_top(s); - } else if (s->fn_index >= SECONDARY_FN_INDEX) { - show_stack_size(s); - } - } else if (s->mode == CALC_PEEK) { - show_peek_mode(s); - show_peek_value(s); - } - break; - case EVENT_MODE_BUTTON_UP: - if (s->mode == CALC_NUMBER) { - adjust_number(s, -1); + show_fn(s, event.subsecond); + if (s->fn_index == 0) { show_stack_top(s); - } else if (s->mode == CALC_PEEK) { - // Navigate down the stack (towards index 0) - if (s->peek_index > 0) { - s->peek_index--; - show_peek_mode(s); - show_peek_value(s); - } - } else { - movement_move_to_next_face(); - return false; + } else if (s->fn_index >= SECONDARY_FN_INDEX) { + show_stack_size(s); } break; - case EVENT_LIGHT_BUTTON_DOWN: - break; + case EVENT_MODE_BUTTON_UP: + movement_move_to_next_face(); + return false; case EVENT_LIGHT_BUTTON_UP: - if (s->mode == CALC_PEEK) { - // Exit peek mode and return to operation mode - change_mode(s, CALC_OPERATION); - show_stack_top(s); - break; - } - proposed_stack_size = s->stack_size - functions[s->fn_index].input; - - if (s->mode == CALC_NUMBER) { - change_mode(s, CALC_OPERATION); - } else if (proposed_stack_size < 0 || proposed_stack_size + functions[s->fn_index].output > CALC_MAX_STACK_SIZE) { + if (proposed_stack_size < 0 || proposed_stack_size + functions[s->fn_index].output > CALC_MAX_STACK_SIZE) { movement_play_signal(); break; } else { @@ -445,55 +410,107 @@ bool rpn_calculator_alt_face_loop(movement_event_t event, void *context) { s->fn_index = 0; show_fn(s, 0); } - break; case EVENT_ALARM_BUTTON_UP: - if (s->mode == CALC_NUMBER) { - adjust_number(s, 1); - show_stack_top(s); - } else if (s->mode == CALC_PEEK) { - // Navigate up the stack (towards stack top) - if (s->peek_index < s->stack_size - 1) { - s->peek_index++; - show_peek_mode(s); - show_peek_value(s); - } - } else { - s->fn_index = (s->fn_index + 1) % FUNCTIONS_LEN; - show_fn(s, 0); - } + s->fn_index = (s->fn_index + 1) % FUNCTIONS_LEN; + show_fn(s, 0); break; case EVENT_LIGHT_LONG_PRESS: if (s->stack_size > 0) { - // Enter peek mode to view the stack change_mode(s, CALC_PEEK); show_peek_mode(s); show_peek_value(s); } break; case EVENT_ALARM_LONG_PRESS: - if (s->mode == CALC_OPERATION) { - if (s->fn_index == 0) { - s->fn_index = SECONDARY_FN_INDEX; - } else { - s->fn_index = 0; - } - show_fn(s, 0); + if (s->fn_index == 0) { + s->fn_index = SECONDARY_FN_INDEX; + } else { + s->fn_index = 0; } + show_fn(s, 0); + break; + } + return true; +} + +// Handle events in number entry mode +static bool handle_number_mode(movement_event_t event, calculator_state_t *s) { + switch (event.event_type) { + case EVENT_MODE_BUTTON_UP: + adjust_number(s, -1); + show_stack_top(s); break; + case EVENT_LIGHT_BUTTON_UP: + change_mode(s, CALC_OPERATION); + break; + case EVENT_ALARM_BUTTON_UP: + adjust_number(s, 1); + show_stack_top(s); + break; + } + return true; +} + +// Handle events in peek mode +static bool handle_peek_mode(movement_event_t event, calculator_state_t *s) { + switch (event.event_type) { + case EVENT_TICK: + show_peek_mode(s); + show_peek_value(s); + break; + case EVENT_MODE_BUTTON_UP: + if (s->peek_index > 0) { + s->peek_index--; + show_peek_mode(s); + show_peek_value(s); + } + break; + case EVENT_LIGHT_BUTTON_UP: + change_mode(s, CALC_OPERATION); + show_stack_top(s); + break; + case EVENT_ALARM_BUTTON_UP: + if (s->peek_index < s->stack_size - 1) { + s->peek_index++; + show_peek_mode(s); + show_peek_value(s); + } + break; + } + return true; +} + +bool rpn_calculator_alt_face_loop(movement_event_t event, void *context) { + calculator_state_t *s = (calculator_state_t *)context; + + // Handle common events first + switch (event.event_type) { + case EVENT_ACTIVATE: + change_mode(s, CALC_OPERATION); + show_stack_top(s); + return true; case EVENT_TIMEOUT: movement_move_to_face(0); - break; + return true; case EVENT_LOW_ENERGY_UPDATE: - break; + return true; default: - movement_default_loop_handler(event); break; } - // return true if the watch can enter standby mode. If you are PWM'ing an LED or buzzing the buzzer here, - // you should return false since the PWM driver does not operate in standby mode. - return true; + // Delegate to mode-specific handlers + switch (s->mode) { + case CALC_OPERATION: + return handle_operation_mode(event, s); + case CALC_NUMBER: + return handle_number_mode(event, s); + case CALC_PEEK: + return handle_peek_mode(event, s); + default: + movement_default_loop_handler(event); + return true; + } } void rpn_calculator_alt_face_resign(void *context) { From dbcb7ffd28da3ad1da2260a0d6596a0a8b86595b Mon Sep 17 00:00:00 2001 From: redraw Date: Wed, 17 Sep 2025 21:00:40 -0300 Subject: [PATCH 5/5] rpn calculator alt: clear stack with light long press in peek mode --- watch-faces/complication/rpn_calculator_alt_face.c | 6 ++++++ watch-faces/complication/rpn_calculator_alt_face.h | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/watch-faces/complication/rpn_calculator_alt_face.c b/watch-faces/complication/rpn_calculator_alt_face.c index 79df8313a..1e4b3dd03 100644 --- a/watch-faces/complication/rpn_calculator_alt_face.c +++ b/watch-faces/complication/rpn_calculator_alt_face.c @@ -470,6 +470,12 @@ static bool handle_peek_mode(movement_event_t event, calculator_state_t *s) { change_mode(s, CALC_OPERATION); show_stack_top(s); break; + case EVENT_LIGHT_LONG_PRESS: + // Clear the stack + s->stack_size = 0; + change_mode(s, CALC_OPERATION); + show_stack_top(s); + break; case EVENT_ALARM_BUTTON_UP: if (s->peek_index < s->stack_size - 1) { s->peek_index++; diff --git a/watch-faces/complication/rpn_calculator_alt_face.h b/watch-faces/complication/rpn_calculator_alt_face.h index fa563a621..0ff0cc208 100644 --- a/watch-faces/complication/rpn_calculator_alt_face.h +++ b/watch-faces/complication/rpn_calculator_alt_face.h @@ -56,6 +56,16 @@ * manipulation (pop, swap, dupe, clear, size (le)). If you're _not_ on NO, a long * hold will take you back to it. * + * PEEK MODE: + * A new peek mode allows you to browse through the entire calculator stack: + * - Long press LIGHT in operation mode (when stack has items) to enter peek mode + * - In peek mode, "ST" appears in the day section and the stack position (1-based) + * appears in the top right + * - MODE button navigates down the stack (towards index 0, older items) + * - ALARM button navigates up the stack (towards stack top, newer items) + * - LIGHT button exits peek mode and returns to operation mode + * - Long press LIGHT in peek mode clears the entire stack and returns to operation mode + * * See 'functions' in "rpn_calculator_alt_face.c" for names of all operations. */