From: joeycastillo Date: Mon, 30 Sep 2024 04:24:23 +0000 (-0400) Subject: bring in battery voltage face, add new method and demo for displaying floats X-Git-Url: https://git.earman.xyz/?a=commitdiff_plain;h=996571967ff4ae3bda73db7f741983bd69e82cb4;p=sensor-watch.git bring in battery voltage face, add new method and demo for displaying floats --- diff --git a/Makefile b/Makefile index 6a76e69..ab894ce 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/watch_faces/demo/voltage_face.c b/movement/watch_faces/demo/voltage_face.c deleted file mode 100644 index 2d209d2..0000000 --- a/movement/watch_faces/demo/voltage_face.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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 "voltage_face.h" -#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); -} - -void voltage_face_setup(uint8_t watch_face_index, void ** context_ptr) { - (void) watch_face_index; - (void) context_ptr; -} - -void voltage_face_activate(void *context) { - (void) context; -} - -bool voltage_face_loop(movement_event_t event, void *context) { - (void) context; - watch_date_time date_time; - switch (event.event_type) { - case EVENT_ACTIVATE: - _voltage_face_update_display(); - break; - case EVENT_TICK: - date_time = watch_rtc_get_date_time(); - if (date_time.unit.second % 5 == 4) { - watch_set_indicator(WATCH_INDICATOR_SIGNAL); - } else if (date_time.unit.second % 5 == 0) { - _voltage_face_update_display(); - watch_clear_indicator(WATCH_INDICATOR_SIGNAL); - } - break; - case EVENT_LOW_ENERGY_UPDATE: - // clear seconds area and start tick animation if necessary - if (!watch_sleep_animation_is_running()) { - watch_display_string(" ", 8); - 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); - } - break; - default: - movement_default_loop_handler(event); - break; - } - - return true; -} - -void voltage_face_resign(void *context) { - (void) context; -} diff --git a/movement/watch_faces/demo/voltage_face.h b/movement/watch_faces/demo/voltage_face.h deleted file mode 100644 index 9257671..0000000 --- a/movement/watch_faces/demo/voltage_face.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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. - */ - -#ifndef VOLTAGE_FACE_H_ -#define VOLTAGE_FACE_H_ - -/* - * VOLTAGE face - * - * This watch face is very simple and has no controls to speak of. It displays - * the battery voltage as measured by the SAM L22’s ADC. - * - * Note that the Simple Clock watch face includes a low battery warning, so you - * don’t technically need to this watch face unless you want to track the - * battery level. - */ - -#include "movement.h" - -void voltage_face_setup(uint8_t watch_face_index, void ** context_ptr); -void voltage_face_activate(void *context); -bool voltage_face_loop(movement_event_t event, void *context); -void voltage_face_resign(void *context); - -#define voltage_face ((const watch_face_t){ \ - voltage_face_setup, \ - voltage_face_activate, \ - voltage_face_loop, \ - voltage_face_resign, \ - NULL, \ -}) - -#endif // VOLTAGE_FACE_H_ diff --git a/movement_config.h b/movement_config.h index c54149e..94564d9 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 09d682f..1d3215d 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 417e30d..0e38e1c 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 0000000..fa650d2 --- /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 0000000..96ea8ad --- /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/watch-faces/sensor/voltage_face.c b/watch-faces/sensor/voltage_face.c new file mode 100644 index 0000000..b532c9d --- /dev/null +++ b/watch-faces/sensor/voltage_face.c @@ -0,0 +1,87 @@ +/* + * 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 "voltage_face.h" +#include "watch.h" + +static void _voltage_face_update_display(void) { + watch_enable_adc(); + float voltage = (float)watch_get_vcc_voltage() / 1000.0; + watch_disable_adc(); + + 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) { + (void) watch_face_index; + (void) context_ptr; +} + +void voltage_face_activate(void *context) { + (void) context; +} + +bool voltage_face_loop(movement_event_t event, void *context) { + (void) context; + watch_date_time date_time; + switch (event.event_type) { + case EVENT_ACTIVATE: + _voltage_face_update_display(); + break; + case EVENT_TICK: + date_time = watch_rtc_get_date_time(); + if (date_time.unit.second % 5 == 4) { + watch_set_indicator(WATCH_INDICATOR_SIGNAL); + } else if (date_time.unit.second % 5 == 0) { + _voltage_face_update_display(); + watch_clear_indicator(WATCH_INDICATOR_SIGNAL); + } + break; + case EVENT_LOW_ENERGY_UPDATE: + // clear seconds area (on classic LCD) and start tick animation if necessary + if (!watch_sleep_animation_is_running()) { + 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_text_with_fallback(WATCH_POSITION_SECONDS, " V", " "); + } + break; + default: + movement_default_loop_handler(event); + break; + } + + return true; +} + +void voltage_face_resign(void *context) { + (void) context; +} diff --git a/watch-faces/sensor/voltage_face.h b/watch-faces/sensor/voltage_face.h new file mode 100644 index 0000000..9257671 --- /dev/null +++ b/watch-faces/sensor/voltage_face.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef VOLTAGE_FACE_H_ +#define VOLTAGE_FACE_H_ + +/* + * VOLTAGE face + * + * This watch face is very simple and has no controls to speak of. It displays + * the battery voltage as measured by the SAM L22’s ADC. + * + * Note that the Simple Clock watch face includes a low battery warning, so you + * don’t technically need to this watch face unless you want to track the + * battery level. + */ + +#include "movement.h" + +void voltage_face_setup(uint8_t watch_face_index, void ** context_ptr); +void voltage_face_activate(void *context); +bool voltage_face_loop(movement_event_t event, void *context); +void voltage_face_resign(void *context); + +#define voltage_face ((const watch_face_t){ \ + voltage_face_setup, \ + voltage_face_activate, \ + voltage_face_loop, \ + voltage_face_resign, \ + NULL, \ +}) + +#endif // VOLTAGE_FACE_H_ diff --git a/watch-library/shared/watch/watch_common_display.c b/watch-library/shared/watch/watch_common_display.c index 4e7184f..baf0fde 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 c3a23ba..b369b3b 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);