add Baby kicks face (#70)
This commit is contained in:
132
watch-faces/complication/baby_kicks_face.h
Normal file
132
watch-faces/complication/baby_kicks_face.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2025 Gábor Nyéki
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Baby kicks face
|
||||
*
|
||||
* Count the movements of your in-utero baby.
|
||||
*
|
||||
* Background:
|
||||
*
|
||||
* This practice is recommended particularly in the third trimester
|
||||
* (from week 28 onwards). The exact recommendations vary as to how to
|
||||
* count the baby's movements. Some recommend drawing a chart with the
|
||||
* number of "kicks" within a 12-hour period:
|
||||
*
|
||||
* - https://en.wikipedia.org/wiki/Kick_chart
|
||||
*
|
||||
* Others recommend measuring the time that it takes for the baby to
|
||||
* "kick" 10 times:
|
||||
*
|
||||
* - https://my.clevelandclinic.org/health/articles/23497-kick-counts
|
||||
* - https://healthy.kaiserpermanente.org/health-wellness/health-encyclopedia/he.pregnancy-kick-counts.aa107042
|
||||
*
|
||||
* (Of course, not every movement that the baby makes is a kick, and we
|
||||
* are interested in all movements, not only kicks.)
|
||||
*
|
||||
* This watch face follows the latter set of recommendations. When you
|
||||
* start the counter, it measures the number of elapsed minutes, and it
|
||||
* tracks the number of movements as you increment the counter. Since
|
||||
* some consecutive movements made by the baby are actually part of a
|
||||
* longer maneuver, the watch face also displays the number of
|
||||
* one-minute stretches in which the baby moved at least once.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* - ALARM button, short press:
|
||||
* * start the counter if it isn't running
|
||||
* * increment the count otherwise
|
||||
* - ALARM button, long press: undo the last count
|
||||
* - MODE button, long press: reset the count to zero
|
||||
*
|
||||
* The watch face displays two numbers in the "clock digits" positions:
|
||||
*
|
||||
* 1. Count of movements (in the "second" and "minute" positions).
|
||||
* 2. Count of one-minute stretches in which at least one movement
|
||||
* occurred (in the "hour" position).
|
||||
*
|
||||
* The number of elapsed minutes, up to and including 29, is shown in
|
||||
* the "day digits" position. Due to the limitations of the classic LCD
|
||||
* display, completed 30-minute intervals are shown in the "weekday
|
||||
* digits" position. The total number of elapsed minutes is the sum of
|
||||
* these two numbers.
|
||||
*
|
||||
* The watch face times out after 99 minutes, since it cannot display
|
||||
* more than 99 one-minute stretches in the "hour" position. When this
|
||||
* happens, the "weekday digits" position shows "TO".
|
||||
*/
|
||||
|
||||
#include "movement.h"
|
||||
|
||||
typedef enum {
|
||||
BABY_KICKS_MODE_SPLASH = 0,
|
||||
BABY_KICKS_MODE_ACTIVE,
|
||||
BABY_KICKS_MODE_TIMED_OUT,
|
||||
BABY_KICKS_MODE_LE_MODE,
|
||||
} baby_kicks_mode_t;
|
||||
|
||||
/* Stop counting after 99 minutes. The classic LCD cannot display any
|
||||
* larger number in the "weekday digits" position. */
|
||||
#define BABY_KICKS_TIMEOUT 99
|
||||
|
||||
/* Ring buffer to store and allow undoing up to 10 movements. */
|
||||
typedef struct {
|
||||
/* For each movement in the undo buffer, this array stores the value
|
||||
* of `state->stretch_count` right before the movement was
|
||||
* recorded. This is used for decrementing `state->stretch_count`
|
||||
* as part of the undo operation if necessary. */
|
||||
uint8_t stretches[10];
|
||||
|
||||
/* Index of the next available slot in `.stretches`. */
|
||||
uint8_t head;
|
||||
} baby_kicks_undo_buffer_t;
|
||||
|
||||
typedef struct {
|
||||
bool currently_displayed;
|
||||
baby_kicks_mode_t mode;
|
||||
watch_date_time_t now;
|
||||
uint32_t start;
|
||||
uint32_t latest_stretch_start;
|
||||
uint8_t stretch_count; /* Between 0 and `BABY_KICKS_TIMEOUT`. */
|
||||
uint16_t movement_count; /* Between 0 and 9999. */
|
||||
baby_kicks_undo_buffer_t undo_buffer;
|
||||
} baby_kicks_state_t;
|
||||
|
||||
void baby_kicks_face_setup(uint8_t watch_face_index, void **context_ptr);
|
||||
void baby_kicks_face_activate(void *context);
|
||||
bool baby_kicks_face_loop(movement_event_t event, void *context);
|
||||
void baby_kicks_face_resign(void *context);
|
||||
movement_watch_face_advisory_t baby_kicks_face_advise(void *context);
|
||||
|
||||
#define baby_kicks_face ((const watch_face_t) { \
|
||||
baby_kicks_face_setup, \
|
||||
baby_kicks_face_activate, \
|
||||
baby_kicks_face_loop, \
|
||||
baby_kicks_face_resign, \
|
||||
baby_kicks_face_advise, \
|
||||
})
|
||||
Reference in New Issue
Block a user