From 996571967ff4ae3bda73db7f741983bd69e82cb4 Mon Sep 17 00:00:00 2001 From: joeycastillo Date: Mon, 30 Sep 2024 00:24:23 -0400 Subject: [PATCH] bring in battery voltage face, add new method and demo for displaying floats --- Makefile | 2 + movement_config.h | 1 + movement_faces.h | 2 + watch-faces.mk | 2 + watch-faces/demo/float_demo_face.c | 61 +++++++++++++++++++ watch-faces/demo/float_demo_face.h | 49 +++++++++++++++ .../sensor}/voltage_face.c | 13 ++-- .../sensor}/voltage_face.h | 0 .../shared/watch/watch_common_display.c | 32 ++++++++++ watch-library/shared/watch/watch_slcd.h | 13 ++++ 10 files changed, 167 insertions(+), 8 deletions(-) create mode 100644 watch-faces/demo/float_demo_face.c create mode 100644 watch-faces/demo/float_demo_face.h rename {movement/watch_faces/demo => watch-faces/sensor}/voltage_face.c (87%) rename {movement/watch_faces/demo => watch-faces/sensor}/voltage_face.h (100%) diff --git a/Makefile b/Makefile index 6a76e69b..ab894cec 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,8 @@ INCLUDES += \ -I./watch-library/hardware/watch \ -I./watch-faces/clock \ -I./watch-faces/complication \ + -I./watch-faces/demo \ + -I./watch-faces/sensor \ -I./watch-faces/settings \ # Add your source files here. diff --git a/movement_config.h b/movement_config.h index c54149ec..94564d95 100644 --- a/movement_config.h +++ b/movement_config.h @@ -34,6 +34,7 @@ const watch_face_t watch_faces[] = { advanced_alarm_face, countdown_face, fast_stopwatch_face, + voltage_face, preferences_face, set_time_face, }; diff --git a/movement_faces.h b/movement_faces.h index 09d682f3..1d3215d1 100644 --- a/movement_faces.h +++ b/movement_faces.h @@ -31,6 +31,8 @@ #include "countdown_face.h" #include "fast_stopwatch_face.h" #include "sunrise_sunset_face.h" +#include "float_demo_face.h" +#include "voltage_face.h" #include "set_time_face.h" #include "preferences_face.h" // New includes go above this line. diff --git a/watch-faces.mk b/watch-faces.mk index 417e30d6..0e38e1cd 100644 --- a/watch-faces.mk +++ b/watch-faces.mk @@ -6,5 +6,7 @@ SRCS += \ ./watch-faces/complication/countdown_face.c \ ./watch-faces/complication/fast_stopwatch_face.c \ ./watch-faces/complication/sunrise_sunset_face.c \ + ./watch-faces/demo/float_demo_face.c \ + ./watch-faces/sensor/voltage_face.c \ ./watch-faces/settings/set_time_face.c \ ./watch-faces/settings/preferences_face.c \ diff --git a/watch-faces/demo/float_demo_face.c b/watch-faces/demo/float_demo_face.c new file mode 100644 index 00000000..fa650d28 --- /dev/null +++ b/watch-faces/demo/float_demo_face.c @@ -0,0 +1,61 @@ +/* + * MIT License + * + * Copyright (c) 2022 Joey Castillo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include "float_demo_face.h" +#include "watch.h" + +void float_demo_face_setup(uint8_t watch_face_index, void ** context_ptr) { + (void) watch_face_index; + if (*context_ptr == NULL) *context_ptr = malloc(sizeof(float)); +} + +void float_demo_face_activate(void *context) { + float *c = (float *)context; + *c = 0; + watch_display_text_with_fallback(WATCH_POSITION_TOP, "FLOAT", "FL"); + movement_request_tick_frequency(32); +} + +bool float_demo_face_loop(movement_event_t event, void *context) { + float *c = (float *)context; + switch (event.event_type) { + case EVENT_TICK: + *c = (*c) + 0.11; + // fall through + case EVENT_ACTIVATE: + watch_display_float_with_best_effort(*c, "#F"); + break; + default: + movement_default_loop_handler(event); + break; + } + + return true; +} + +void float_demo_face_resign(void *context) { + (void) context; +} diff --git a/watch-faces/demo/float_demo_face.h b/watch-faces/demo/float_demo_face.h new file mode 100644 index 00000000..96ea8ad8 --- /dev/null +++ b/watch-faces/demo/float_demo_face.h @@ -0,0 +1,49 @@ +/* + * MIT License + * + * Copyright (c) 2024 Joey Castillo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef FLOAT_DEMO_FACE_H_ +#define FLOAT_DEMO_FACE_H_ + +/* + * FLOAT DEMO + * + * To be deleted, tests float display functionality. + */ + +#include "movement.h" + +void float_demo_face_setup(uint8_t watch_face_index, void ** context_ptr); +void float_demo_face_activate(void *context); +bool float_demo_face_loop(movement_event_t event, void *context); +void float_demo_face_resign(void *context); + +#define float_demo_face ((const watch_face_t){ \ + float_demo_face_setup, \ + float_demo_face_activate, \ + float_demo_face_loop, \ + float_demo_face_resign, \ + NULL, \ +}) + +#endif // FLOAT_DEMO_FACE_H_ diff --git a/movement/watch_faces/demo/voltage_face.c b/watch-faces/sensor/voltage_face.c similarity index 87% rename from movement/watch_faces/demo/voltage_face.c rename to watch-faces/sensor/voltage_face.c index 2d209d2d..b532c9d0 100644 --- a/movement/watch_faces/demo/voltage_face.c +++ b/watch-faces/sensor/voltage_face.c @@ -28,15 +28,12 @@ #include "watch.h" static void _voltage_face_update_display(void) { - char buf[14]; - watch_enable_adc(); float voltage = (float)watch_get_vcc_voltage() / 1000.0; watch_disable_adc(); - sprintf(buf, "BA %4.2f V", voltage); - // printf("%s\n", buf); - watch_display_string(buf, 0); + watch_display_text_with_fallback(WATCH_POSITION_TOP_LEFT, "BAT", "BA"); + watch_display_float_with_best_effort(voltage, " V"); } void voltage_face_setup(uint8_t watch_face_index, void ** context_ptr) { @@ -65,16 +62,16 @@ bool voltage_face_loop(movement_event_t event, void *context) { } break; case EVENT_LOW_ENERGY_UPDATE: - // clear seconds area and start tick animation if necessary + // clear seconds area (on classic LCD) and start tick animation if necessary if (!watch_sleep_animation_is_running()) { - watch_display_string(" ", 8); + watch_display_text_with_fallback(WATCH_POSITION_SECONDS, " V", " "); watch_start_sleep_animation(1000); } // update once an hour if (date_time.unit.minute == 0) { watch_clear_indicator(WATCH_INDICATOR_SIGNAL); _voltage_face_update_display(); - watch_display_string(" ", 8); + watch_display_text_with_fallback(WATCH_POSITION_SECONDS, " V", " "); } break; default: diff --git a/movement/watch_faces/demo/voltage_face.h b/watch-faces/sensor/voltage_face.h similarity index 100% rename from movement/watch_faces/demo/voltage_face.h rename to watch-faces/sensor/voltage_face.h diff --git a/watch-library/shared/watch/watch_common_display.c b/watch-library/shared/watch/watch_common_display.c index 4e7184f2..baf0fde8 100644 --- a/watch-library/shared/watch/watch_common_display.c +++ b/watch-library/shared/watch/watch_common_display.c @@ -25,6 +25,7 @@ #include "watch_slcd.h" #include "watch_common_display.h" #include +#include #ifdef USE_CUSTOM_LCD static const uint32_t IndicatorSegments[] = { @@ -267,6 +268,37 @@ void watch_display_text_with_fallback(watch_position_t location, const char *str #endif } +void watch_display_float_with_best_effort(float value, const char *units) { + char buf[8]; + char buf_fallback[8]; + const char *blank_units = " "; + + if (value < 0.0) { + watch_clear_decimal_if_available(); + watch_display_text_with_fallback(WATCH_POSITION_BOTTOM, "Undflo", " Unflo"); + return; + } else if (value > 199.99) { + watch_clear_decimal_if_available(); + watch_display_text(WATCH_POSITION_BOTTOM, "Ovrflo"); + return; + } + + uint16_t value_times_100 = (uint16_t)(value * 100.0); + if (value_times_100 > 9999) { + snprintf(buf, sizeof(buf), "%5u%s", value_times_100, units ? units : blank_units); + snprintf(buf_fallback, sizeof(buf_fallback), "%4.1f%s", value, units ? units : blank_units); + } else if (value_times_100 > 999) { + snprintf(buf, sizeof(buf), "%4u%s", value_times_100, units ? units : blank_units); + snprintf(buf_fallback, sizeof(buf_fallback), "%4.1f%s", value, units ? units : blank_units); + } else { + snprintf(buf, sizeof(buf), " %03u%s", value_times_100 % 1000u, units ? units : blank_units); + snprintf(buf_fallback, sizeof(buf_fallback), "%4.2f%s", value, units ? units : blank_units); + } + + watch_display_text_with_fallback(WATCH_POSITION_BOTTOM, buf, buf_fallback); + watch_set_decimal_if_available(); +} + void watch_set_colon(void) { #ifdef USE_CUSTOM_LCD watch_set_pixel(0, 0); diff --git a/watch-library/shared/watch/watch_slcd.h b/watch-library/shared/watch/watch_slcd.h index c3a23ba0..b369b3b5 100644 --- a/watch-library/shared/watch/watch_slcd.h +++ b/watch-library/shared/watch/watch_slcd.h @@ -160,6 +160,19 @@ void watch_display_text(watch_position_t location, const char *string); */ void watch_display_text_with_fallback(watch_position_t location, const char *string, const char *fallback); +/** + * @brief Displays a floating point number as best we can on whatever LCD is available. + * @details The custom LCD can energize a decimal point in the same position as the colon. With the leading 1, + * we can display numbers from 0.00 to 199.99 with two digits of precision. The original F-91W LCD has + * no decimal point, so we use a hyphen to indicate the decimal point. For floats from 0.00 to 9.99, + * we can display the number with two digits after the "decimal point" (hyphen). For floats from 10.0 + * to 99.9, you'll only get one digit after the hyphen. For floats from 100 to 199.9, we'll still give + * you one digit after the hyphen, but you'll lose the second character of your units. + * @param value A floating point number from 0.00 to 199.99 to display on the main clock digits. + * @param units A 1-2 character string to display in the seconds position. Second character may be truncated. + */ +void watch_display_float_with_best_effort(float value, const char *units); + /** @brief Turns the colon segment on. */ void watch_set_colon(void);