Fix missing documentation for many clock faces:
* Move from .c to .h as needed for consistency. * When missing from both, copy from pull request or wiki. * When missing entirely, infer functionality from source code.
This commit is contained in:
		
							parent
							
								
									3487d742f1
								
							
						
					
					
						commit
						7802994854
					
				@ -1,3 +1,27 @@
 | 
			
		||||
/*
 | 
			
		||||
 * MIT License
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2023 Wesley Ellis <https://github.com/tahnok>
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "beats_face.h"
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,41 @@
 | 
			
		||||
/*
 | 
			
		||||
 * MIT License
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2023 Wesley Ellis <https://github.com/tahnok>
 | 
			
		||||
 *
 | 
			
		||||
 * 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 BEATS_FACE_H_
 | 
			
		||||
#define BEATS_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * BEATS TIME face
 | 
			
		||||
 *
 | 
			
		||||
 * The Beat Time face displays the current Swatch Internet Time, or .beat time.
 | 
			
		||||
 * This is a decimal time system that divides the day into 1000 beats.
 | 
			
		||||
 *
 | 
			
		||||
 * The three large digits in the bottom row indicate the current beat, and the
 | 
			
		||||
 * two smaller digits (normally the seconds in Simple Clock) indicate the
 | 
			
		||||
 * fractional beat; so for example you can read “67214” as “beat 672.14”.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -25,10 +25,8 @@
 | 
			
		||||
#ifndef DECIMAL_TIME_FACE_H_
 | 
			
		||||
#define DECIMAL_TIME_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DECIMAL TIME FACE
 | 
			
		||||
 * DECIMAL TIME face
 | 
			
		||||
 * 
 | 
			
		||||
 * This face presents the current time as hours and hundredths of an hour. Every hundreth of an hour, or "centihour", 
 | 
			
		||||
 * occurs every 36 seconds. Because they range from 0 to 99, centihours, in the seventies range, will be displayed with a lowercase 7.
 | 
			
		||||
@ -46,9 +44,10 @@
 | 
			
		||||
 * https://hr.colostate.edu/minute-to-decimal-conversion-chart/
 | 
			
		||||
 * 
 | 
			
		||||
 * Many thanks go to Joey Castillo for making this project happen.
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    bool chime_enabled;            // did the user enable hourly chime for this face? 
 | 
			
		||||
    uint8_t features_to_show : 2 ; // what features are to be displayed?
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,32 @@
 | 
			
		||||
#ifndef MARS_TIME_FACE_H_
 | 
			
		||||
#define MARS_TIME_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MARS TIME face
 | 
			
		||||
 *
 | 
			
		||||
 * This watch face is dedicated to Martian timekeeping.
 | 
			
		||||
 * It has several modes, and can display either a time or a date.
 | 
			
		||||
 *
 | 
			
		||||
 * Pressing the ALARM button cycles through different time zones on Mars:
 | 
			
		||||
 *   MC - Mars Coordinated Time, the time at Airy-0 Crater on the Martian prime meridian
 | 
			
		||||
 *   ZH - Local mean solar time for the Zhurong rover
 | 
			
		||||
 *   PE - LMST for the Perseverance rover
 | 
			
		||||
 *   IN - LMST for the Insight lander
 | 
			
		||||
 *   CU - LMST for the Curiosity rover
 | 
			
		||||
 *
 | 
			
		||||
 * Press the LIGHT button to toggle between displaying time and date:
 | 
			
		||||
 *   MC S - the Mars Sol Date, Martian days since December 29, 1873
 | 
			
		||||
 *   ZH Sol - Mission sol for the Zhurong rover
 | 
			
		||||
 *   PE Sol - Mission sol for the Perseverance rover
 | 
			
		||||
 *   IN S - Mission sol for the InSight lander
 | 
			
		||||
 *   CU S - Mission sol for the Curiosity rover
 | 
			
		||||
 *
 | 
			
		||||
 * Note that where the mission sol is below 1000, this watch face displays
 | 
			
		||||
 * the word “Sol” on the bottom line. When the mission sol is over 1000, the
 | 
			
		||||
 * word “Sol” will not fit and so it displays a stylized letter S at the top
 | 
			
		||||
 * right.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
 | 
			
		||||
@ -25,9 +25,9 @@
 | 
			
		||||
#ifndef REPETITION_MINUTE_FACE_H_
 | 
			
		||||
#define REPETITION_MINUTE_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * REPETITION MINUTE face
 | 
			
		||||
 *
 | 
			
		||||
 * A hopefully useful complication for friendly neighbors in the dark
 | 
			
		||||
 *
 | 
			
		||||
 * Originating from 1676 from reverend and mechanician Edward Barlow, and
 | 
			
		||||
@ -40,7 +40,6 @@
 | 
			
		||||
 * before widespread artificial illumination, to allow the time to be determined
 | 
			
		||||
 * in the dark, and were also used by the visually impaired. 
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * How to use it :
 | 
			
		||||
 * 
 | 
			
		||||
 * Long press the light button to get an auditive reading of the time like so :
 | 
			
		||||
@ -51,9 +50,10 @@
 | 
			
		||||
 * Prerequisite : a watch with a working buzzer
 | 
			
		||||
 * 
 | 
			
		||||
 * ~ Only in the darkness can you see the stars. - Martin Luther King ~
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint32_t previous_date_time;
 | 
			
		||||
    uint8_t last_battery_check;
 | 
			
		||||
 | 
			
		||||
@ -25,9 +25,9 @@
 | 
			
		||||
#ifndef SIIMPLE_CLOCK_BIN_LED_FACE_H_
 | 
			
		||||
#define SIIMPLE_CLOCK_BIN_LED_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * BINARY LED CLOCK FACE
 | 
			
		||||
 *
 | 
			
		||||
 * A "fork" of the simple clock face, which provides the functionality of showing 
 | 
			
		||||
 * the current time by flashing the LED using binary representation.
 | 
			
		||||
 *
 | 
			
		||||
@ -49,6 +49,8 @@
 | 
			
		||||
 *   represents 1.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint32_t previous_date_time;
 | 
			
		||||
    uint8_t last_battery_check;
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,15 @@
 | 
			
		||||
#ifndef SIMPLE_CLOCK_FACE_H_
 | 
			
		||||
#define SIMPLE_CLOCK_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * SIMPLE CLOCK FACE
 | 
			
		||||
 *
 | 
			
		||||
 * Displays the current time, matching the original operation of the watch.
 | 
			
		||||
 * This is the default display mode in most watch configurations.
 | 
			
		||||
 *
 | 
			
		||||
 * Long-press ALARM to toggle the hourly chime.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,14 @@
 | 
			
		||||
#ifndef WEEKNUMBER_CLOCK_FACE_H_
 | 
			
		||||
#define WEEKNUMBER_CLOCK_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * WEEK-NUMBER WATCH FACE
 | 
			
		||||
 *
 | 
			
		||||
 * Same as simple clock, but has iso 8601 week number instead of seconds counter.
 | 
			
		||||
 *
 | 
			
		||||
 * Long-press ALARM to toggle the hourly chime.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -23,79 +23,6 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * World Clock 2
 | 
			
		||||
 * =============
 | 
			
		||||
 *
 | 
			
		||||
 * This is an alternative world clock face that allows the user to cycle
 | 
			
		||||
 * through a list of selected time zones. It extends the original
 | 
			
		||||
 * implementation by Joey Castillo. The face has two modes *display mode*
 | 
			
		||||
 * and *settings mode*.
 | 
			
		||||
 *
 | 
			
		||||
 * ### Settings mode
 | 
			
		||||
 *
 | 
			
		||||
 * When the clock face is activated for the first time, it enters
 | 
			
		||||
 * *settings mode*. Here, the user can select the time zones they want to
 | 
			
		||||
 * display. The face shows a summary of the current time zone:
 | 
			
		||||
 *
 | 
			
		||||
 * - The top of the face displays the first two letters of the time zone
 | 
			
		||||
 *   abbreviation, such as "PS" for Pacific Standard Time or CE for
 | 
			
		||||
 * "Central European Time".
 | 
			
		||||
 *
 | 
			
		||||
 * - The upper-right corner shows the index number of the time zone. This
 | 
			
		||||
 *   helps avoid confusion when multiple time zones have the same
 | 
			
		||||
 *   two-letter abbreviation.
 | 
			
		||||
 *
 | 
			
		||||
 * - The main display shows the offset from UTC, with a "+" indicating a
 | 
			
		||||
 *   positive offset and a "-" indicating a negative offset. For example,
 | 
			
		||||
 *   the offset for Japanese Standard Time is displayed as "+9:00".
 | 
			
		||||
 *
 | 
			
		||||
 * The user can navigate through the time zones and select them using the
 | 
			
		||||
 * following buttons:
 | 
			
		||||
 *
 | 
			
		||||
 * - The *alarm button* moves forward to the next time zone, while the
 | 
			
		||||
 *   *light button* moves backward to the previous zone. This way, the
 | 
			
		||||
 *   user can cycle through all 41 supported time zones.
 | 
			
		||||
 *
 | 
			
		||||
 * - A *long press* on the *light button* selects the current time zone,
 | 
			
		||||
 *   and the signal indicator appears at the top left. Another *long
 | 
			
		||||
 *   press* of the *light button* deselects the time zone.
 | 
			
		||||
 *
 | 
			
		||||
 * - A *long press* on the *alarm button* exits settings mode and returns
 | 
			
		||||
 *   to display mode.
 | 
			
		||||
 *
 | 
			
		||||
 * ### Display mode
 | 
			
		||||
 *
 | 
			
		||||
 * In the display mode, the face shows the time of the currently selected
 | 
			
		||||
 * time zone. The face includes the following components:
 | 
			
		||||
 *
 | 
			
		||||
 * - The top of the face displays the first two letters of the time zone
 | 
			
		||||
 *   abbreviation, such as "PS" for Pacific Standard Time or "CE" for
 | 
			
		||||
 *   Central European Time.
 | 
			
		||||
 *
 | 
			
		||||
 * - The upper-right corner shows the current day of the month, which
 | 
			
		||||
 *   helps indicate time zones that cross the international date line
 | 
			
		||||
 *   with respect to the local time.
 | 
			
		||||
 *
 | 
			
		||||
 * - The main display shows the time in the selected time zone in either
 | 
			
		||||
 *   12-hour or 24-hour form. There is no timeout, allowing users to keep
 | 
			
		||||
 *   the chosen time zone displayed for as long as they wish.
 | 
			
		||||
 *
 | 
			
		||||
 * The user can navigate through the selected time zones using the
 | 
			
		||||
 * following buttons:
 | 
			
		||||
 *
 | 
			
		||||
 * - The *alarm button* moves to the next selected time zone, while the
 | 
			
		||||
 *   light button moves to the *previous zone*. If no time zone is
 | 
			
		||||
 *   selected, the face simply shows UTC.
 | 
			
		||||
 *
 | 
			
		||||
 * - A *long press* on the *alarm button* enters settings mode and
 | 
			
		||||
 *   enables the user to re-configure the selected time zones.
 | 
			
		||||
 *
 | 
			
		||||
 * - A *long press* on the *light button* activates the LED illumination
 | 
			
		||||
 *   of the watch.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "world_clock2_face.h"
 | 
			
		||||
 | 
			
		||||
@ -26,6 +26,65 @@
 | 
			
		||||
#ifndef WORLD_CLOCK2_FACE_H_
 | 
			
		||||
#define WORLD_CLOCK2_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * WORLD CLOCK 2
 | 
			
		||||
 *
 | 
			
		||||
 * This is an alternative world clock face that allows the user to cycle
 | 
			
		||||
 * through a list of selected time zones. It extends the original
 | 
			
		||||
 * implementation by Joey Castillo. The face has two modes: display mode
 | 
			
		||||
 * and settings mode.
 | 
			
		||||
 *
 | 
			
		||||
 * Settings mode
 | 
			
		||||
 *
 | 
			
		||||
 * When the clock face is activated for the first time, it enters settings
 | 
			
		||||
 * mode. Here, the user can select the time zones they want to display. The
 | 
			
		||||
 * face shows a summary of the current time zone:
 | 
			
		||||
 *  * The top of the face displays the first two letters of the time zone
 | 
			
		||||
 *    abbreviation, such as "PS" for Pacific Standard Time or CE for
 | 
			
		||||
 *    "Central European Time".
 | 
			
		||||
 *  * The upper-right corner shows the index number of the time zone. This
 | 
			
		||||
 *    helps avoid confusion when multiple time zones have the same two-letter
 | 
			
		||||
 *    abbreviation.
 | 
			
		||||
 *  * The main display shows the offset from UTC, with a "+" indicating a
 | 
			
		||||
 *    positive offset and a "-" indicating a negative offset. For example,
 | 
			
		||||
 *    the offset for Japanese Standard Time is displayed as "+9:00".
 | 
			
		||||
 *
 | 
			
		||||
 * The user can navigate through the time zones and select them using the
 | 
			
		||||
 * following buttons:
 | 
			
		||||
 *  * The ALARM button moves forward to the next time zone, while the LIGHT
 | 
			
		||||
 *    button moves backward to the previous zone. This way, the user can
 | 
			
		||||
 *    cycle through all 41 supported time zones.
 | 
			
		||||
 *  * A long press on the LIGHT button selects the current time zone, and
 | 
			
		||||
 *    the signal indicator appears at the top left. Another long press of
 | 
			
		||||
 *    the LIGHT button deselects the time zone.
 | 
			
		||||
 *  * A long press on the ALARM button exits settings mode and returns to
 | 
			
		||||
 *    display mode.
 | 
			
		||||
 *
 | 
			
		||||
 * Display mode
 | 
			
		||||
 *
 | 
			
		||||
 * In the display mode, the face shows the time of the currently selected
 | 
			
		||||
 * time zone. The face includes the following components:
 | 
			
		||||
 *  * The top of the face displays the first two letters of the time zone
 | 
			
		||||
 *    abbreviation, such as "PS" for Pacific Standard Time or "CE" for
 | 
			
		||||
 *    Central European Time.
 | 
			
		||||
 *  * The upper-right corner shows the current day of the month, which helps
 | 
			
		||||
 *    indicate time zones that cross the international date line with respect
 | 
			
		||||
 *    to the local time.
 | 
			
		||||
 *  * The main display shows the time in the selected time zone in either
 | 
			
		||||
 *    12-hour or 24-hour form. There is no timeout, allowing users to keep
 | 
			
		||||
 *    the chosen time zone displayed for as long as they wish.
 | 
			
		||||
 *
 | 
			
		||||
 * The user can navigate through the selected time zones using the following
 | 
			
		||||
 * buttons:
 | 
			
		||||
 *  * The ALARM button moves to the next selected time zone, while the LIGHT
 | 
			
		||||
 *    button moves to the previous zone. If no time zone is selected, the
 | 
			
		||||
 *    face simply shows UTC.
 | 
			
		||||
 *  * A long press on the ALARM button enters settings mode and enables the
 | 
			
		||||
 *    user to re-configure the selected time zones.
 | 
			
		||||
 *  * A long press on the LIGHT button activates the LED illumination of the
 | 
			
		||||
 *    watch.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Number of zones. See movement_timezone_offsets. */
 | 
			
		||||
#define NUM_TIME_ZONES  41
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,29 @@
 | 
			
		||||
#ifndef WORLD_CLOCK_FACE_H_
 | 
			
		||||
#define WORLD_CLOCK_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * WORLD CLOCK FACE
 | 
			
		||||
 *
 | 
			
		||||
 * The World Clock watch face looks similar to the Simple Clock watch face,
 | 
			
		||||
 * but you’ll notice that at first launch the day of week indicators are blank.
 | 
			
		||||
 * That’s because this watch face does not display the day of the week.
 | 
			
		||||
 * Instead, you may customize these letters to display the name of a time zone
 | 
			
		||||
 * of your choosing.
 | 
			
		||||
 *
 | 
			
		||||
 * To customize this watch face, press and hold the ALARM button. The first
 | 
			
		||||
 * letter in the top row will begin flashing. Press the ALARM button repeatedly
 | 
			
		||||
 * to advance through the available letters in the first slot, then press the
 | 
			
		||||
 * LIGHT button to move to the second letter. Finally, press LIGHT again to move
 | 
			
		||||
 * to the time zone setting, and press ALARM to cycle through the available time
 | 
			
		||||
 * zones. Press LIGHT one last time to return to the world clock display.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that the second slot cannot display all letters or numbers. Also note
 | 
			
		||||
 * that at this time, time zones do not automatically update for daylight saving
 | 
			
		||||
 * time; you will need to manually adjust this field each spring and fall.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef union {
 | 
			
		||||
    struct {
 | 
			
		||||
        uint8_t char_0;
 | 
			
		||||
 | 
			
		||||
@ -25,15 +25,32 @@
 | 
			
		||||
#ifndef WYOSCAN_FACE_H_
 | 
			
		||||
#define WYOSCAN_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * A DESCRIPTION OF YOUR WATCH FACE
 | 
			
		||||
 * WYOSCAN .5 hz watchface
 | 
			
		||||
 *
 | 
			
		||||
 * and a description of how use it
 | 
			
		||||
 * This is a recreation of the Wyoscan watch, which was a $175 watch in 2014.
 | 
			
		||||
 * It was an f-91w pcb replacement.
 | 
			
		||||
 * 
 | 
			
		||||
 * Video: https://user-images.githubusercontent.com/1795778/252550124-e07f0ed1-e328-4337-a654-fa1ee65d883f.mp4
 | 
			
		||||
 * Background information: https://artmetropole.com/shop/11460
 | 
			
		||||
 * Demo of what it looks like: https://www.o-r-g.com/apps/wyoscan
 | 
			
		||||
 *
 | 
			
		||||
 * 8 frames per number * 6 numbers + the trailing 16 frames = 64 frames
 | 
			
		||||
 * at 32 frames per second, this is a 2-second cycle time or 0.5 Hz.
 | 
			
		||||
 *
 | 
			
		||||
 * It is giving me a stack overflow after about 2.5 cycles of the time display
 | 
			
		||||
 * in the emulator, but it works fine on the watch.
 | 
			
		||||
 *
 | 
			
		||||
 * I'd like to make something for the low energy mode, but I haven't thought
 | 
			
		||||
 * about how that might work, right now it just freezes in low energy mode
 | 
			
		||||
 * until you press the 12-24HR button.
 | 
			
		||||
 *
 | 
			
		||||
 * There are no controls; it simply animates as long as the page is active.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
#define MAX_ILLUMINATED_SEGMENTS 16
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -25,10 +25,8 @@
 | 
			
		||||
#ifndef ACTIVITY_FACE_H_
 | 
			
		||||
#define ACTIVITY_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ACTIVITY WATCH FACE
 | 
			
		||||
 * ACTIVITY watch face
 | 
			
		||||
 *
 | 
			
		||||
 * The Activity face lets you record activities like you would do with a fitness watch.
 | 
			
		||||
 * It supports different activities like running, biking, rowing etc., and for each recorded activity
 | 
			
		||||
@ -69,9 +67,10 @@
 | 
			
		||||
 * 
 | 
			
		||||
 * See the top of activity_face.c for some customization options. What you most likely want to do
 | 
			
		||||
 * is reduce the list of activities shown on the first screen to the ones you are regularly doing.
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
void activity_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
 | 
			
		||||
void activity_face_activate(movement_settings_t *settings, void *context);
 | 
			
		||||
bool activity_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
 | 
			
		||||
 | 
			
		||||
@ -22,8 +22,6 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
@ -32,31 +30,6 @@
 | 
			
		||||
#include "watch_utility.h"
 | 
			
		||||
#include "watch_private_display.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    Implements 16 alarm slots on the sensor watch
 | 
			
		||||
 | 
			
		||||
    Usage:
 | 
			
		||||
    - In normal mode, the alarm button cycles through all 16 alarms. 
 | 
			
		||||
    - Pressing the alarm button long in normal mode toggles the corresponding alarm on or off.
 | 
			
		||||
      (Whereas pressing the alarm button extra long brings you back to alarm no. 1.)
 | 
			
		||||
    - Pressing the light button enters setting mode and cycles through the settings of each alarm.
 | 
			
		||||
      (Long pressing the light button enters setting mode without illuminating the led.)
 | 
			
		||||
    - In setting mode an alarm slot is selected by pressing the alarm button when the slot number 
 | 
			
		||||
      in the upper right corner is blinking.
 | 
			
		||||
    - For each alarm slot, you can select the day. These are the day modes:
 | 
			
		||||
        - ED = the alarm rings every day
 | 
			
		||||
        - 1t = the alarm fires only one time and is erased afterwards
 | 
			
		||||
        - MF = the alarm fires Mondays to Fridays
 | 
			
		||||
        - WN = the alarm fires on weekends (Sa/Su)
 | 
			
		||||
        - MO to SU = the alarm fires only on the given day of week
 | 
			
		||||
    - You can fast cycle through hour or minute setting via long press of the alarm button.
 | 
			
		||||
    - You can select the tone in which the alarm is played. (Three pitch levels available.)
 | 
			
		||||
    - You can select how many "beep rounds" are played for each alarm. 1 to 9 rounds, plus extra 
 | 
			
		||||
      long ('L') and extra short ('o') alarms.
 | 
			
		||||
    - The simple watch face indicates if any alarm is set within the next 24h by showing the signal
 | 
			
		||||
      indicator.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    alarm_setting_idx_alarm,
 | 
			
		||||
    alarm_setting_idx_day,
 | 
			
		||||
 | 
			
		||||
@ -27,12 +27,35 @@
 | 
			
		||||
#ifndef ALARM_FACE_H_
 | 
			
		||||
#define ALARM_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
A face for setting various alarms
 | 
			
		||||
 * ALARM face
 | 
			
		||||
 *
 | 
			
		||||
 * Implements up to 16 alarm slots on the sensor watch
 | 
			
		||||
 *
 | 
			
		||||
 * Usage:
 | 
			
		||||
 *    - In normal mode, the alarm button cycles through all 16 alarms. 
 | 
			
		||||
 *    - Pressing the alarm button long in normal mode toggles the corresponding alarm on or off.
 | 
			
		||||
 *      (Whereas pressing the alarm button extra long brings you back to alarm no. 1.)
 | 
			
		||||
 *    - Pressing the light button enters setting mode and cycles through the settings of each alarm.
 | 
			
		||||
 *      (Long pressing the light button enters setting mode without illuminating the led.)
 | 
			
		||||
 *    - In setting mode an alarm slot is selected by pressing the alarm button when the slot number 
 | 
			
		||||
 *      in the upper right corner is blinking.
 | 
			
		||||
 *    - For each alarm slot, you can select the day. These are the day modes:
 | 
			
		||||
 *        - ED = the alarm rings every day
 | 
			
		||||
 *        - 1t = the alarm fires only one time and is erased afterwards
 | 
			
		||||
 *        - MF = the alarm fires Mondays to Fridays
 | 
			
		||||
 *        - WN = the alarm fires on weekends (Sa/Su)
 | 
			
		||||
 *        - MO to SU = the alarm fires only on the given day of week
 | 
			
		||||
 *    - You can fast cycle through hour or minute setting via long press of the alarm button.
 | 
			
		||||
 *    - You can select the tone in which the alarm is played. (Three pitch levels available.)
 | 
			
		||||
 *    - You can select how many "beep rounds" are played for each alarm. 1 to 9 rounds, plus extra 
 | 
			
		||||
 *      long ('L') and extra short ('o') alarms.
 | 
			
		||||
 *    - The simple watch face indicates if any alarm is set within the next 24h by showing the signal
 | 
			
		||||
 *      indicator.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
#define ALARM_ALARMS 16     // no of available alarm slots (be aware: only 4 bits reserved for this value in struct below)
 | 
			
		||||
#define ALARM_DAY_STATES 11 // no of different day settings
 | 
			
		||||
#define ALARM_DAY_EACH_DAY 7
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,47 @@
 | 
			
		||||
#ifndef ASTRONOMY_FACE_H_
 | 
			
		||||
#define ASTRONOMY_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ASTRONOMY face
 | 
			
		||||
 *
 | 
			
		||||
 * The Astronomy watch face is among the most complex watch faces in the
 | 
			
		||||
 * Movement collection. It allows you to calculate the locations of celestial
 | 
			
		||||
 * bodies in the sky, as well as distance in astronomical units (or, in the
 | 
			
		||||
 * case of the Moon, distance in kilometers).
 | 
			
		||||
 * 
 | 
			
		||||
 * When you arrive at the Astronomy watch face, you’ll see its name (“Astro”)
 | 
			
		||||
 * and an animation of two objects orbiting each other. You will also see “SO”
 | 
			
		||||
 * (for Sol) flashing in the top left. The flashing letters indicate the
 | 
			
		||||
 * currently selected celestial body. Short press Alarm to advance through
 | 
			
		||||
 * the available celestial bodies:
 | 
			
		||||
 * 
 | 
			
		||||
 *     SO - Sol, the sun
 | 
			
		||||
 *     ME - Mercury
 | 
			
		||||
 *     VE - Venus
 | 
			
		||||
 *     LU - Luna, the Earth’s moon
 | 
			
		||||
 *     MA - Mars
 | 
			
		||||
 *     JU - Jupiter
 | 
			
		||||
 *     SA - Saturn
 | 
			
		||||
 *     UR - Uranus
 | 
			
		||||
 *     NE - Neptune
 | 
			
		||||
 * 
 | 
			
		||||
 * Once you’ve selected the celestial body whose parameters you wish to
 | 
			
		||||
 * calculate, long press the Alarm button and release it. The letter “C” will
 | 
			
		||||
 * flash while the calculation is performed.
 | 
			
		||||
 * 
 | 
			
		||||
 * When the calculation is complete, the screen will display the altitude
 | 
			
		||||
 * (“aL”) of the celestial body. You can cycle through the available parameters
 | 
			
		||||
 * with repeated short presses on the Alarm button:
 | 
			
		||||
 * 
 | 
			
		||||
 *     aL - Altitude (in degrees), the elevation over the horizon. If negative, it is below the horizon.
 | 
			
		||||
 *     aZ - Azimuth (in degrees), the cardinal direction relative to true north.
 | 
			
		||||
 *     rA - Right Ascension (in hours/minutes/seconds)
 | 
			
		||||
 *     dE - Declination (in degrees/minutes/seconds)
 | 
			
		||||
 *     di - Distance (the digits in the top right will display either aU for astronomical units, or K for kilometers)
 | 
			
		||||
 * 
 | 
			
		||||
 * Long press on the Alarm button to select another celestial body.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
#include "astrolib.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,32 @@
 | 
			
		||||
#ifndef BLINKY_FACE_H_
 | 
			
		||||
#define BLINKY_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * BLINKY LIGHT face
 | 
			
		||||
 *
 | 
			
		||||
 * The blinky light watch face was designed as a tutorial for making a watch
 | 
			
		||||
 * face in Movement, but it actually might be useful to have a blinking light
 | 
			
		||||
 * in a pinch.
 | 
			
		||||
 *
 | 
			
		||||
 * The screen displays the name of the watch face (”BL”), as well as an S at
 | 
			
		||||
 * the top right for slow blink or an F for fast blink. The bottom line selects
 | 
			
		||||
 * the color: green, red or yellow. You can change the speed of the blinking
 | 
			
		||||
 * light by pressing the Alarm button, and change the color with the Light
 | 
			
		||||
 * button. A long press on the Alarm button starts the blinking light, and
 | 
			
		||||
 * another long press stops it.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that this will chew through your battery! The green LED uses about
 | 
			
		||||
 * 450µA at full brightness, which is 45 times the normal power consumption of
 | 
			
		||||
 * the watch. The red LED is an order of magnitude less efficient (4500 µA),
 | 
			
		||||
 * and the yellow setting lights both LEDs, which chews through nearly
 | 
			
		||||
 * 5 milliamperes. This means that one hour of yellow blinking is likely to
 | 
			
		||||
 * eat up between 2 and 3 percent of the battery’s usable life!
 | 
			
		||||
 *
 | 
			
		||||
 * Still, if you need to signal your location to someone in a dark forest,
 | 
			
		||||
 * this watch face could come in handy. Just try to use the green LED as much
 | 
			
		||||
 * as you can.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,17 @@
 | 
			
		||||
#ifndef BREATHING_FACE_H_
 | 
			
		||||
#define BREATHING_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * BOXED BREATHING face
 | 
			
		||||
 *
 | 
			
		||||
 * Breathing is a complication for guiding boxed breathing sessions.
 | 
			
		||||
 * Boxed breathing is a technique to help you stay calm and improve
 | 
			
		||||
 * concentration in stressful situations.
 | 
			
		||||
 *
 | 
			
		||||
 * Usage: Timed messages will cycle as long as this face is active.
 | 
			
		||||
 * Press ALARM to toggle sound.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
void breathing_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
 | 
			
		||||
 | 
			
		||||
@ -23,27 +23,12 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "countdown_face.h"
 | 
			
		||||
#include "watch.h"
 | 
			
		||||
#include "watch_utility.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    Slight extension of the original countdown face by Wesley Ellis.
 | 
			
		||||
 | 
			
		||||
    - Press the light button to enter setting mode and adjust the
 | 
			
		||||
      countdown timer.
 | 
			
		||||
 | 
			
		||||
    - Start and pause the countdown using the alarm button, similar to the
 | 
			
		||||
      stopwatch face.
 | 
			
		||||
 | 
			
		||||
    - When paused or terminated, press the light button to restore the
 | 
			
		||||
      last entered countdown.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#define CD_SELECTIONS 3
 | 
			
		||||
#define DEFAULT_MINUTES 3
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -22,22 +22,27 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef COUNTDOWN_FACE_H_
 | 
			
		||||
#define COUNTDOWN_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
A countdown/timer face
 | 
			
		||||
 | 
			
		||||
Max countdown is 23 hours, 59 minutes and 59 seconds.
 | 
			
		||||
 | 
			
		||||
Note: we have to prevent the watch from going to deep sleep using
 | 
			
		||||
movement_schedule_background_task() while the timer is running.
 | 
			
		||||
 * COUNTDOWN TIMER face
 | 
			
		||||
 *
 | 
			
		||||
 * Slight extension of the original countdown face by Wesley Ellis.
 | 
			
		||||
 *   - Press the light button to enter setting mode and adjust the
 | 
			
		||||
 *     countdown timer.
 | 
			
		||||
 *   - Start and pause the countdown using the alarm button, similar
 | 
			
		||||
 *     to the stopwatch face.
 | 
			
		||||
 *   - When paused or terminated, press the light button to restore the
 | 
			
		||||
 *     last entered countdown.
 | 
			
		||||
 *
 | 
			
		||||
 * Max countdown is 23 hours, 59 minutes and 59 seconds.
 | 
			
		||||
 *
 | 
			
		||||
 * Note: we have to prevent the watch from going to deep sleep using
 | 
			
		||||
 * movement_schedule_background_task() while the timer is running.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    cd_paused,
 | 
			
		||||
 | 
			
		||||
@ -25,9 +25,19 @@
 | 
			
		||||
#ifndef COUNTER_FACE_H_
 | 
			
		||||
#define COUNTER_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * COUNTER face
 | 
			
		||||
 *
 | 
			
		||||
 * Counter face is designed to count the number of running laps during exercises.
 | 
			
		||||
 *
 | 
			
		||||
 * Usage:
 | 
			
		||||
 * Short-press ALARM to increment the counter (loops at 99)
 | 
			
		||||
 * Long-press ALARM to reset the counter.
 | 
			
		||||
 * Long-press LIGHT to toggle sound.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
// Counter face is designed to count the number of running laps during excercises.
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t counter_idx;
 | 
			
		||||
    bool beep_on;
 | 
			
		||||
 | 
			
		||||
@ -20,8 +20,6 @@
 | 
			
		||||
 * 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.
 | 
			
		||||
 *
 | 
			
		||||
 * Displays some pre-defined data that you might want to remember. Math constants, birthdays, phone numbers...
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
@ -96,12 +94,8 @@ bool databank_face_loop(movement_event_t event, movement_settings_t *settings, v
 | 
			
		||||
        case EVENT_ACTIVATE:
 | 
			
		||||
             display();
 | 
			
		||||
        case EVENT_TICK:
 | 
			
		||||
            // on activate and tick, if we are animating,
 | 
			
		||||
            break;
 | 
			
		||||
        case EVENT_LIGHT_BUTTON_UP:
 | 
			
		||||
            // when the user presses 'light', we illuminate the LED. We could override this if
 | 
			
		||||
            // our UI needed an additional button for input, consuming the light button press
 | 
			
		||||
            // but not illuminating the LED.
 | 
			
		||||
            databank_state.current_word = (databank_state.current_word + max_words - 1) % max_words;
 | 
			
		||||
            display();
 | 
			
		||||
            break;
 | 
			
		||||
@ -116,8 +110,6 @@ bool databank_face_loop(movement_event_t event, movement_settings_t *settings, v
 | 
			
		||||
            display();
 | 
			
		||||
            break;
 | 
			
		||||
        case EVENT_ALARM_BUTTON_UP:
 | 
			
		||||
            // when the user presses 'alarm', we toggle the state of the animation. If animating,
 | 
			
		||||
            // we stop; if stopped, we resume.
 | 
			
		||||
            databank_state.current_word = (databank_state.current_word + 1) % max_words;
 | 
			
		||||
            display();
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,23 @@
 | 
			
		||||
#ifndef DATABANK_FACE_H_
 | 
			
		||||
#define DATABANK_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DATABANK face
 | 
			
		||||
 *
 | 
			
		||||
 * Displays some pre-defined data that you might want to remember
 | 
			
		||||
 * Math constants, birthdays, phone numbers...
 | 
			
		||||
 *
 | 
			
		||||
 * Usage: Edit the global variable `pi_data` in "databank_face.c"
 | 
			
		||||
 * to the define the data that will be displayed. Each "item" contains
 | 
			
		||||
 * a two-letter label (using the day-of-week display), then a longer
 | 
			
		||||
 * string that will be displayed one "word" (six characters) at a time.
 | 
			
		||||
 *
 | 
			
		||||
 * Short-press ALARM to display the next word.
 | 
			
		||||
 * Short-press LIGHT to display the previous word.
 | 
			
		||||
 * Long-press ALARM to display the next item.
 | 
			
		||||
 * Long-press LIGHT to display the previous item.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
void databank_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
 | 
			
		||||
 | 
			
		||||
@ -25,10 +25,29 @@
 | 
			
		||||
#ifndef DAY_ONE_FACE_H_
 | 
			
		||||
#define DAY_ONE_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
/*
 | 
			
		||||
 * DAY ONE face
 | 
			
		||||
 *
 | 
			
		||||
 * This watch face displays the number of days since a given date.
 | 
			
		||||
 * It was originally designed to display the number of days you’ve been alive,
 | 
			
		||||
 * but technically it can count up from any date in the 20th century or the
 | 
			
		||||
 * 21st century, so far.
 | 
			
		||||
 *
 | 
			
		||||
 * Long press on the Alarm button to enter customization mode. The text “YR”
 | 
			
		||||
 * will appear, and will allow you to set the year starting from 1959. Press
 | 
			
		||||
 * Alarm repeatedly to advance the year. If your birthday is before 1959,
 | 
			
		||||
 * advance beyond the current year and it will wrap around to 1900.
 | 
			
		||||
 *
 | 
			
		||||
 * Once you have set the year, press Light to set the month (“MO”) and
 | 
			
		||||
 * day (“DA”), advancing the value by pressing Alarm repeatedly.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that at this time, the Day One face does not display the sleep
 | 
			
		||||
 * indicator in sleep mode, which may make the watch appear to be
 | 
			
		||||
 * unresponsive in sleep mode. You can still press the Alarm button to
 | 
			
		||||
 * wake the watch. This UI quirk will be addressed in a future update.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// The Day One face is designed to count upwards from the wearer's date of birth. It also functions as an
 | 
			
		||||
// interface for setting the birth date register, which other watch faces can use for various purposes.
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t current_page;
 | 
			
		||||
 | 
			
		||||
@ -22,9 +22,12 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
#ifndef DISCGOLF_FACE_H_
 | 
			
		||||
#define DISCGOLF_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DISC GOLF face
 | 
			
		||||
 *
 | 
			
		||||
 * Keep track of scores in discgolf or golf!
 | 
			
		||||
 * The watch face operates in three different modes:
 | 
			
		||||
 *
 | 
			
		||||
@ -58,10 +61,6 @@
 | 
			
		||||
 *  lowest score for that course, and saved if it is better.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef DISCGOLF_FACE_H_
 | 
			
		||||
#define DISCGOLF_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
#define courses 11
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -26,16 +26,6 @@
 | 
			
		||||
#ifndef DUAL_TIMER_FACE_H_
 | 
			
		||||
#define DUAL_TIMER_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * IMPORTANT: This watch face uses the same TC2 callback counter as the Stock Stopwatch
 | 
			
		||||
 * watch-face. It works through calling a global handler function. The two watch-faces
 | 
			
		||||
 * therefore can't coexist within the same firmware. If you want to compile this watch-face
 | 
			
		||||
 * then you need to remove the line <../watch_faces/complication/stock_stopwatch_face.c \>
 | 
			
		||||
 * from the Makefile.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DUAL TIMER
 | 
			
		||||
 * ==========
 | 
			
		||||
@ -70,8 +60,15 @@
 | 
			
		||||
 * the timers. In this case LONG PRESSING MODE will move to the next face instead of moving
 | 
			
		||||
 * back to the default watch face.
 | 
			
		||||
 *
 | 
			
		||||
 * IMPORTANT: This watch face uses the same TC2 callback counter as the Stock Stopwatch
 | 
			
		||||
 * watch-face. It works through calling a global handler function. The two watch-faces
 | 
			
		||||
 * therefore can't coexist within the same firmware. If you want to compile this watch-face
 | 
			
		||||
 * then you need to remove the line <../watch_faces/complication/stock_stopwatch_face.c \>
 | 
			
		||||
 * from the Makefile.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t centiseconds : 7;  // 0-59
 | 
			
		||||
    uint8_t seconds : 6;  // 0-59
 | 
			
		||||
 | 
			
		||||
@ -25,9 +25,9 @@
 | 
			
		||||
#ifndef FLASHLIGHT_FACE_H_
 | 
			
		||||
#define FLASHLIGHT_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * FLASHLIGHT face
 | 
			
		||||
 *
 | 
			
		||||
 * A flashlight for use with the Flashlight sensor board.
 | 
			
		||||
 *
 | 
			
		||||
 * When the watch face appears, the display will show "FL" in the top two positions.
 | 
			
		||||
@ -35,6 +35,8 @@
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    // Anything you need to keep track of, put it here!
 | 
			
		||||
    uint8_t unused;
 | 
			
		||||
 | 
			
		||||
@ -25,10 +25,8 @@
 | 
			
		||||
#ifndef GEOMANCY_FACE_H_
 | 
			
		||||
#define GEOMANCY_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * GEOMANCY WATCH FACE
 | 
			
		||||
 * GEOMANCY watch face
 | 
			
		||||
 *
 | 
			
		||||
 * A simple and straightforward watch face for the ancient Eastern geomantic divination system
 | 
			
		||||
 * of I Ching and the western system of "Geomancy". It is an optional addition to the Toss Up
 | 
			
		||||
@ -65,6 +63,8 @@
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t bits : 4;
 | 
			
		||||
} nibble_t;
 | 
			
		||||
 | 
			
		||||
@ -25,8 +25,6 @@
 | 
			
		||||
#ifndef HABIT_FACE_H_
 | 
			
		||||
#define HABIT_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Habit tracking face
 | 
			
		||||
 *
 | 
			
		||||
@ -36,6 +34,8 @@
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
void habit_face_setup(movement_settings_t *settings, uint8_t watch_face_index,
 | 
			
		||||
                      void **context_ptr);
 | 
			
		||||
void habit_face_activate(movement_settings_t *settings, void *context);
 | 
			
		||||
 | 
			
		||||
@ -22,8 +22,6 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
@ -33,57 +31,6 @@
 | 
			
		||||
#include "watch_private_display.h"
 | 
			
		||||
#include "watch_buzzer.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    This face brings 9 customizable interval timers to the sensor watch,
 | 
			
		||||
    to be used as hiit training device and/or for time management techniques.
 | 
			
		||||
 | 
			
		||||
    - There are 9 interval timer slots, you can cycle through these with the
 | 
			
		||||
      alarm button (short press). For each timer slot, a short "slideshow"
 | 
			
		||||
      displaying the relevant details (like length of each phase - see below)
 | 
			
		||||
      is shown.
 | 
			
		||||
 | 
			
		||||
    - To start an interval timer, press and hold the alarm button.
 | 
			
		||||
 | 
			
		||||
    - To pause a running timer, press the alarm button (short press).
 | 
			
		||||
 | 
			
		||||
    - To completely abort a running timer, press and hold the alarm button.
 | 
			
		||||
 | 
			
		||||
    - Press and hold the light button to enter settings mode for each interval
 | 
			
		||||
      timer slot.
 | 
			
		||||
 | 
			
		||||
    - Each interval timer has 1 to 4 phases of customizable length like so:
 | 
			
		||||
      (1) prepare/warum up --> (2) work --> (3) break --> (4) cool down.
 | 
			
		||||
      When setting up or running a timer, each of these phases is displayed by
 | 
			
		||||
      the letters "PR" (prepare), "WO" (work), "BR" (break), "CD" (cool down).
 | 
			
		||||
 | 
			
		||||
    - Each of these phases is optional, you can set the corresponding
 | 
			
		||||
      minutes and seconds to zero. But at least one phase needs to be set, if
 | 
			
		||||
      you want to use the timer.
 | 
			
		||||
 | 
			
		||||
    - You can define the number of rounds either only for the work
 | 
			
		||||
      phase and/or for the combination of work + break phase. Let's say you
 | 
			
		||||
      want an interval timer that counts 3 rounds of 30 seconds work, 
 | 
			
		||||
      followed by 20 seconds rest:
 | 
			
		||||
            work 30s --> work 30s --> work 30s --> break 20s
 | 
			
		||||
      You can do this by setting 30s for the "WO"rk phase and setting a 3
 | 
			
		||||
      in the lower right hand corner of the work page. The "LAP" indicator
 | 
			
		||||
      lights up at this position, to explain that we are setting laps here.
 | 
			
		||||
      After that, set the "BR"eak phase to 20s and leave the rest as it is.
 | 
			
		||||
 | 
			
		||||
    - If you want to set up a certain number of "full rounds", consisting
 | 
			
		||||
      of work phase(s) plus breaks, you can do so at the "BR"eak page. The
 | 
			
		||||
      number in the lower right hand corner determines the number of full
 | 
			
		||||
      rounds to be counted. A "-" means, that there is no limit and the 
 | 
			
		||||
      timer keeps alternating between work and break phases.
 | 
			
		||||
 | 
			
		||||
    - This watch face comes with several pre-defined interval timers,
 | 
			
		||||
      suitable for hiit training (timer slots 1 to 4) as well as doing
 | 
			
		||||
      work according to the pomodoro principle (timer slots 5 to 6).
 | 
			
		||||
      Feel free to adjust the timer slots to your own needs (or completely 
 | 
			
		||||
      wipe them ;-)
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    interval_setting_0_timer_idx,
 | 
			
		||||
    interval_setting_1_clear_yn,
 | 
			
		||||
 | 
			
		||||
@ -22,17 +22,63 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef INTERVAL_FACE_H_
 | 
			
		||||
#define INTERVAL_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
A face for customizable interval timers
 | 
			
		||||
 * INTERVAL TIMER face
 | 
			
		||||
 *
 | 
			
		||||
 * This face brings 9 customizable interval timers to the sensor watch,
 | 
			
		||||
 * to be used as hiit training device and/or for time management techniques.
 | 
			
		||||
 *
 | 
			
		||||
 * - There are 9 interval timer slots, you can cycle through these with the
 | 
			
		||||
 *   alarm button (short press). For each timer slot, a short "slideshow"
 | 
			
		||||
 *   displaying the relevant details (like length of each phase - see below)
 | 
			
		||||
 *   is shown.
 | 
			
		||||
 *
 | 
			
		||||
 * - To start an interval timer, press and hold the alarm button.
 | 
			
		||||
 *
 | 
			
		||||
 * - To pause a running timer, press the alarm button (short press).
 | 
			
		||||
 *
 | 
			
		||||
 * - To completely abort a running timer, press and hold the alarm button.
 | 
			
		||||
 *
 | 
			
		||||
 * - Press and hold the light button to enter settings mode for each interval
 | 
			
		||||
 *   timer slot.
 | 
			
		||||
 *
 | 
			
		||||
 * - Each interval timer has 1 to 4 phases of customizable length like so:
 | 
			
		||||
 *   (1) prepare/warum up --> (2) work --> (3) break --> (4) cool down.
 | 
			
		||||
 *   When setting up or running a timer, each of these phases is displayed by
 | 
			
		||||
 *   the letters "PR" (prepare), "WO" (work), "BR" (break), "CD" (cool down).
 | 
			
		||||
 *
 | 
			
		||||
 * - Each of these phases is optional, you can set the corresponding
 | 
			
		||||
 *   minutes and seconds to zero. But at least one phase needs to be set, if
 | 
			
		||||
 *   you want to use the timer.
 | 
			
		||||
 *
 | 
			
		||||
 * - You can define the number of rounds either only for the work
 | 
			
		||||
 *   phase and/or for the combination of work + break phase. Let's say you
 | 
			
		||||
 *   want an interval timer that counts 3 rounds of 30 seconds work, 
 | 
			
		||||
 *   followed by 20 seconds rest:
 | 
			
		||||
 *         work 30s --> work 30s --> work 30s --> break 20s
 | 
			
		||||
 *   You can do this by setting 30s for the "WO"rk phase and setting a 3
 | 
			
		||||
 *   in the lower right hand corner of the work page. The "LAP" indicator
 | 
			
		||||
 *   lights up at this position, to explain that we are setting laps here.
 | 
			
		||||
 *   After that, set the "BR"eak phase to 20s and leave the rest as it is.
 | 
			
		||||
 *
 | 
			
		||||
 * - If you want to set up a certain number of "full rounds", consisting
 | 
			
		||||
 *   of work phase(s) plus breaks, you can do so at the "BR"eak page. The
 | 
			
		||||
 *   number in the lower right hand corner determines the number of full
 | 
			
		||||
 *   rounds to be counted. A "-" means, that there is no limit and the 
 | 
			
		||||
 *   timer keeps alternating between work and break phases.
 | 
			
		||||
 *
 | 
			
		||||
 * - This watch face comes with several pre-defined interval timers,
 | 
			
		||||
 *   suitable for hiit training (timer slots 1 to 4) as well as doing
 | 
			
		||||
 *   work according to the pomodoro principle (timer slots 5 to 6).
 | 
			
		||||
 *   Feel free to adjust the timer slots to your own needs (or completely 
 | 
			
		||||
 *   wipe them ;-)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
#define INTERVAL_TIMERS 9     // no of available customizable timers (be aware: only 4 bits reserved for this value in struct below)
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -25,8 +25,6 @@
 | 
			
		||||
#ifndef INVADERS_FACE_H_
 | 
			
		||||
#define INVADERS_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Remake of the "famous" Casio Number Invaders Game
 | 
			
		||||
 *
 | 
			
		||||
@ -60,6 +58,8 @@
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint16_t highscore;
 | 
			
		||||
    bool sound_on;
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,30 @@
 | 
			
		||||
#ifndef MOON_PHASE_FACE_H_
 | 
			
		||||
#define MOON_PHASE_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MOON PHASE face
 | 
			
		||||
 *
 | 
			
		||||
 * The Moon Phase face is similar to the Sunrise/Sunset face: it displays the
 | 
			
		||||
 * current phase of the moon, along with the day of the month and a graphical
 | 
			
		||||
 * representation of the moon on the top row.
 | 
			
		||||
 * 
 | 
			
		||||
 * This graphical representation is a bit abstract. The segments that turn on
 | 
			
		||||
 * represent the shape of the moon, waxing from the bottom right and waning at
 | 
			
		||||
 * the top left. A small crescent at the bottom right will grow into a larger
 | 
			
		||||
 * crescent, then add lines in the center for a quarter and half moon. All
 | 
			
		||||
 * segments are on during a full moon. Then gradually the segments at the
 | 
			
		||||
 * bottom right will turn off, until all that remains is a small waning
 | 
			
		||||
 * crescent at the top left.
 | 
			
		||||
 * 
 | 
			
		||||
 * All segments turn off during a new moon.
 | 
			
		||||
 * 
 | 
			
		||||
 * On this screen you may press the Alarm button repeatedly to move forward
 | 
			
		||||
 * in time: the day of the month at the top right will advance by one day for
 | 
			
		||||
 * each button press, and both the text and the graphical representation will
 | 
			
		||||
 * display the moon phase for that day. Try pressing the Alarm button 27 times
 | 
			
		||||
 * now, just to visualize what the moon will look like over the next month.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -22,89 +22,6 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
## Morse-code-based RPN calculator 
 | 
			
		||||
 | 
			
		||||
The calculator is operated by first composing a **token** in Morse code, then submitting it to the calculator. A token specifies either a calculator operation or a float value.
 | 
			
		||||
These two parts of the codebase are totally independent:
 | 
			
		||||
 | 
			
		||||
 1. The Morse-code reader (`mc.h`, `mc.c`) 
 | 
			
		||||
 2. The RPN calculator (`calc.h`, `calc.c`, `calc_fn.h`, `calc_fn.c`, `small_strtod.c`)
 | 
			
		||||
 | 
			
		||||
The user interface (`morsecalc_face.h`, `morsecalc_face.c`) lets you talk to the RPN calculator through Morse code.
 | 
			
		||||
 | 
			
		||||
## Controls
 | 
			
		||||
 | 
			
		||||
 - `light` is dash
 | 
			
		||||
 - `alarm` is dot
 | 
			
		||||
 - `mode` is "finish character"
 | 
			
		||||
 - long-press `mode` or submit a blank token to switch faces
 | 
			
		||||
 - long-press `alarm` to show stack
 | 
			
		||||
 - long-press `light` to toggle the light
 | 
			
		||||
   
 | 
			
		||||
## Morse code token entry
 | 
			
		||||
As you enter `.`s and `-`s, the morse code char you've entered will appear in the top center digit.
 | 
			
		||||
At the top right is the # of morse code `.`/`-` you've input so far. The character resets at the 6th `.`/`-`.
 | 
			
		||||
Once you have the character you want to enter, push `mode` to enter it. 
 | 
			
		||||
The character will be appended to the current token, whose 6 trailing chars are shown on the main display.
 | 
			
		||||
Once you've typed in the token you want, enter a blank Morse code character and then push `mode`.
 | 
			
		||||
This submits it to the calculator.
 | 
			
		||||
   
 | 
			
		||||
Special characters:
 | 
			
		||||
 | 
			
		||||
 - Backspace is `(` (`-.--.`). 
 | 
			
		||||
 - Clear token input without submitting to calculator is `Start transmission` (`-.-.-`).
 | 
			
		||||
    
 | 
			
		||||
## Writing commands
 | 
			
		||||
First the calculator will try to interpret the token as a command/stack operation. 
 | 
			
		||||
Commands are defined in `calc_dict[]` in `movement/lib/morsecalc/calc_fns.h`.
 | 
			
		||||
If the command doesn't appear in the dictionary, the calculator tries to interpret the token as a number.
 | 
			
		||||
 
 | 
			
		||||
## Writing numbers
 | 
			
		||||
Numbers are written like floating point strings. 
 | 
			
		||||
Entering a number pushes it to the top of the stack if there's room.
 | 
			
		||||
This can get long, so for convenience numerals can also be written in binary with .- = 01.
 | 
			
		||||
 | 
			
		||||
    0   1    2    3    4    5    6    7    8    9
 | 
			
		||||
    .   -    -.   --   -..  -.-  --.  ---  -... -..-
 | 
			
		||||
    e   t    n    m    d    k    g    o    b    x
 | 
			
		||||
 | 
			
		||||
 - Exponent signs must be entered as "p".
 | 
			
		||||
 - Decimal place "." can be entered as "h" (code ....)
 | 
			
		||||
 - Sign "-" can be entered as "Ch digraph" (code ----)
 | 
			
		||||
 
 | 
			
		||||
For example: "4.2e-3" can be entered directly, or as "4h2pC3"
 | 
			
		||||
  similarly, "0.0042" can also be entered as "eheedn"
 | 
			
		||||
Once you submit a number to the watch face, it pushes it to the top of the stack if there's room.
 | 
			
		||||
        
 | 
			
		||||
## Number display
 | 
			
		||||
After a command runs, the top of the stack is displayed in this format:
 | 
			
		||||
   
 | 
			
		||||
  - Main 4 digits = leading 4 digits
 | 
			
		||||
  - Last 2 digits = exponent
 | 
			
		||||
  - Top middle = [Stack location, Sign of number]
 | 
			
		||||
  - Top right = [Stack exponent, Sign of exponent]
 | 
			
		||||
  
 | 
			
		||||
Blank sign digit means positive.
 | 
			
		||||
So for example, the watch face might look like this:
 | 
			
		||||
 | 
			
		||||
    [   0 -5]
 | 
			
		||||
    [4200 03]
 | 
			
		||||
 | 
			
		||||
... representing `+4.200e-3` is in stack location 0 (the top) and it's one of five items in the stack.
 | 
			
		||||
 | 
			
		||||
## Looking at the stack
 | 
			
		||||
To show the top of the stack, push and hold `light`/`alarm` or submit a blank token by pushing `mode` a bunch of times.
 | 
			
		||||
To show the N-th stack item (0 through 9):
 | 
			
		||||
 | 
			
		||||
 - Put in the Morse code for N without pushing the mode button.
 | 
			
		||||
 - Push and hold `alarm`.
 | 
			
		||||
    
 | 
			
		||||
To show the memory register, use `m` instead of a number. 
 | 
			
		||||
   
 | 
			
		||||
To see all the calculator operations and their token aliases, see the `calc_dict[]` struct in `calc_fns.h` 
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,96 @@
 | 
			
		||||
#ifndef MORSECALC_FACE_H_
 | 
			
		||||
#define MORSECALC_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MORSECALC face
 | 
			
		||||
 * Morse-code-based RPN calculator
 | 
			
		||||
 *
 | 
			
		||||
 * The calculator is operated by first composing a **token** in Morse code,
 | 
			
		||||
 * then submitting it to the calculator. A token specifies either a calculator
 | 
			
		||||
 * operation or a float value.
 | 
			
		||||
 *
 | 
			
		||||
 * These two parts of the codebase are totally independent:
 | 
			
		||||
 *  1. The Morse-code reader (`mc.h`, `mc.c`)
 | 
			
		||||
 *  2. The RPN calculator (`calc.h`, `calc.c`, `calc_fn.h`, `calc_fn.c`, `small_strtod.c`)
 | 
			
		||||
 *
 | 
			
		||||
 * The user interface (`morsecalc_face.h`, `morsecalc_face.c`) lets you talk
 | 
			
		||||
 * to the RPN calculator through Morse code.
 | 
			
		||||
 *
 | 
			
		||||
 * ## Controls
 | 
			
		||||
 *  - `light` is dash
 | 
			
		||||
 *  - `alarm` is dot
 | 
			
		||||
 *  - `mode` is "finish character"
 | 
			
		||||
 *  - long-press `mode` or submit a blank token to switch faces
 | 
			
		||||
 *  - long-press `alarm` to show stack
 | 
			
		||||
 *  - long-press `light` to toggle the light
 | 
			
		||||
 *
 | 
			
		||||
 * ## Morse code token entry
 | 
			
		||||
 * As you enter `.`s and `-`s, the morse code char you've entered will
 | 
			
		||||
 * appear in the top center digit. At the top right is the # of morse code
 | 
			
		||||
 * `.`/`-` you've input so far. The character resets at the 6th `.`/`-`.
 | 
			
		||||
 *
 | 
			
		||||
 * Once you have the character you want to enter, push `mode` to enter it.
 | 
			
		||||
 *
 | 
			
		||||
 * The character will be appended to the current token, whose 6 trailing
 | 
			
		||||
 * chars are shown on the main display. Once you've typed in the token you
 | 
			
		||||
 * want, enter a blank Morse code character and then push `mode`.
 | 
			
		||||
 * This submits it to the calculator.
 | 
			
		||||
 *
 | 
			
		||||
 * Special characters:
 | 
			
		||||
 *  - Backspace is `(` (`-.--.`).
 | 
			
		||||
 *  - Clear token input without submitting to calculator is `Start
 | 
			
		||||
 *    transmission` (`-.-.-`).
 | 
			
		||||
 *
 | 
			
		||||
 * ## Writing commands
 | 
			
		||||
 * First the calculator will try to interpret the token as a command/stack operation.
 | 
			
		||||
 * Commands are defined in `calc_dict[]` in `movement/lib/morsecalc/calc_fns.h`.
 | 
			
		||||
 * If the command doesn't appear in the dictionary, the calculator tries to interpret the token as a number.
 | 
			
		||||
 *
 | 
			
		||||
 * ## Writing numbers
 | 
			
		||||
 * Numbers are written like floating point strings.
 | 
			
		||||
 * Entering a number pushes it to the top of the stack if there's room.
 | 
			
		||||
 * This can get long, so for convenience numerals can also be written in binary with .- = 01.
 | 
			
		||||
 *
 | 
			
		||||
 *     0   1    2    3    4    5    6    7    8    9
 | 
			
		||||
 *     .   -    -.   --   -..  -.-  --.  ---  -... -..-
 | 
			
		||||
 *     e   t    n    m    d    k    g    o    b    x
 | 
			
		||||
 *
 | 
			
		||||
 *  - Exponent signs must be entered as "p".
 | 
			
		||||
 *  - Decimal place "." can be entered as "h" (code ....)
 | 
			
		||||
 *  - Sign "-" can be entered as "Ch digraph" (code ----)
 | 
			
		||||
 *
 | 
			
		||||
 * For example: "4.2e-3" can be entered directly, or as "4h2pC3"
 | 
			
		||||
 *   similarly, "0.0042" can also be entered as "eheedn"
 | 
			
		||||
 * Once you submit a number to the watch face, it pushes it to the top of the stack if there's room.
 | 
			
		||||
 *
 | 
			
		||||
 * ## Number display
 | 
			
		||||
 * After a command runs, the top of the stack is displayed in this format:
 | 
			
		||||
 *
 | 
			
		||||
 *   - Main 4 digits = leading 4 digits
 | 
			
		||||
 *   - Last 2 digits = exponent
 | 
			
		||||
 *   - Top middle = [Stack location, Sign of number]
 | 
			
		||||
 *   - Top right = [Stack exponent, Sign of exponent]
 | 
			
		||||
 *
 | 
			
		||||
 * Blank sign digit means positive.
 | 
			
		||||
 * So for example, the watch face might look like this:
 | 
			
		||||
 *
 | 
			
		||||
 *     [   0 -5]
 | 
			
		||||
 *     [4200 03]
 | 
			
		||||
 *
 | 
			
		||||
 * ... representing `+4.200e-3` is in stack location 0 (the top) and it's one of five items in the stack.
 | 
			
		||||
 *
 | 
			
		||||
 * ## Looking at the stack
 | 
			
		||||
 * To show the top of the stack, push and hold `light`/`alarm` or submit a blank token by pushing `mode` a bunch of times.
 | 
			
		||||
 * To show the N-th stack item (0 through 9):
 | 
			
		||||
 *
 | 
			
		||||
 *  - Put in the Morse code for N without pushing the mode button.
 | 
			
		||||
 *  - Push and hold `alarm`.
 | 
			
		||||
 *
 | 
			
		||||
 * To show the memory register, use `m` instead of a number.
 | 
			
		||||
 *
 | 
			
		||||
 * To see all the calculator operations and their token aliases, see the `calc_dict[]` struct in `calc_fns.h`
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define MORSECALC_TOKEN_LEN 32
 | 
			
		||||
#define MORSECODE_LEN 5
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -20,7 +20,6 @@
 | 
			
		||||
 * 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 <stdlib.h>
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,48 @@
 | 
			
		||||
#ifndef ORRERY_FACE_H_
 | 
			
		||||
#define ORRERY_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ORRERY face
 | 
			
		||||
 *
 | 
			
		||||
 * The Orrery watch face is similar to the Astronomy watch face in that it
 | 
			
		||||
 * calculates properties of the planets, but instead of calculating their
 | 
			
		||||
 * positions in the sky, this watch face calculates their absolute locations
 | 
			
		||||
 * in the solar system. This is only useful if you want to plot the planets
 | 
			
		||||
 * on graph paper, but hey, you never know!
 | 
			
		||||
 * 
 | 
			
		||||
 * The controls are identical to the Astronomy watch face: while the title
 | 
			
		||||
 * screen (“Orrery”) is displayed, you can advance through the available
 | 
			
		||||
 * planets with repeated short presses on the Alarm button. The available
 | 
			
		||||
 * planets:
 | 
			
		||||
 * 
 | 
			
		||||
 *     ME - Mercury
 | 
			
		||||
 *     VE - Venus
 | 
			
		||||
 *     EA - Earth
 | 
			
		||||
 *     LU - Luna, the Earth’s moon
 | 
			
		||||
 *     MA - Mars
 | 
			
		||||
 *     JU - Jupiter
 | 
			
		||||
 *     SA - Saturn
 | 
			
		||||
 *     UR - Uranus
 | 
			
		||||
 *     NE - Neptune
 | 
			
		||||
 * 
 | 
			
		||||
 * Note that the sun is not available in this menu, as the sun is always at
 | 
			
		||||
 * (0,0,0) in this calculation.
 | 
			
		||||
 * 
 | 
			
		||||
 * Long press on the Alarm button to calculate the planet’s location, and
 | 
			
		||||
 * after a flashing “C” (for Calculating), you will be presented with the
 | 
			
		||||
 * planet’s X coordinate in astronomical units. Short press Alarm to cycle
 | 
			
		||||
 * through the X, Y and Z coordinates, and then long press Alarm to return
 | 
			
		||||
 * to planet selection.
 | 
			
		||||
 * 
 | 
			
		||||
 * The large numbers represent the whole number part, and the two smaller
 | 
			
		||||
 * numbers (in the seconds place) represent the decimal portion. So if you
 | 
			
		||||
 * see “SA X 736” and “SA Y -662”, you can read that as an X coordinate of
 | 
			
		||||
 * 7.36 AU and a Y coordinate of -6.62 AU. You can literally draw a dot at
 | 
			
		||||
 * (0, 0) to represent the sun, and a dot at (7.36, -6.62) to represent
 | 
			
		||||
 * Saturn. (The Z coordinates tend to be pretty close to zero, as the
 | 
			
		||||
 * planets largely orbit on a single plane, the ecliptic.)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
 | 
			
		||||
@ -26,12 +26,11 @@
 | 
			
		||||
#ifndef planetary_hours_face_H_
 | 
			
		||||
#define planetary_hours_face_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
#include "sunrise_sunset_face.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * BACKGROUND
 | 
			
		||||
 | 
			
		||||
 * PLANETARY HOURS face
 | 
			
		||||
 * 
 | 
			
		||||
 * Background
 | 
			
		||||
 *
 | 
			
		||||
 * Both the 24 hour day and the order of our weekdays have quite esoteric roots.
 | 
			
		||||
 * The ancient Egyptians divided the day up into 12 hours of sunlight and 12 hours
 | 
			
		||||
 * of night time. Obviously the length of these hours varied throughout the year.
 | 
			
		||||
@ -74,6 +73,9 @@
 | 
			
		||||
 * watch face to work properly!)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
#include "sunrise_sunset_face.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    // Anything you need to keep track of, put it here!
 | 
			
		||||
    uint32_t planetary_hours[24];
 | 
			
		||||
 | 
			
		||||
@ -26,12 +26,11 @@
 | 
			
		||||
#ifndef planetary_time_face_H_
 | 
			
		||||
#define planetary_time_face_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
#include "sunrise_sunset_face.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * PLANETARY TIME face
 | 
			
		||||
 *
 | 
			
		||||
 * BACKGROUND
 | 
			
		||||
 | 
			
		||||
 *
 | 
			
		||||
 * Both the 24 hour day and the order of our weekdays have quite esoteric roots.
 | 
			
		||||
 * The ancient Egyptians divided the day up into 12 hours of sunlight and 12 hours
 | 
			
		||||
 * of night time. Obviously the length of these hours varied throughout the year.
 | 
			
		||||
@ -77,6 +76,9 @@
 | 
			
		||||
 * watch face to work properly!)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
#include "sunrise_sunset_face.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    // Anything you need to keep track of, put it here!
 | 
			
		||||
    uint32_t phase_start;
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,18 @@
 | 
			
		||||
#ifndef PROBABILITY_FACE_H_
 | 
			
		||||
#define PROBABILITY_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * PROBABILITY face
 | 
			
		||||
 *
 | 
			
		||||
 * This face is a dice-rolling random number generator.
 | 
			
		||||
 * Supports dice with 2, 4, 6, 8, 10, 12, 20, or 100 sides.
 | 
			
		||||
 *
 | 
			
		||||
 * Press LIGHT to cycle through die type.
 | 
			
		||||
 * The current die size is indicated on the left ("C" for 100)
 | 
			
		||||
 *
 | 
			
		||||
 * Press ALARM to roll the selected die.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,33 @@
 | 
			
		||||
#ifndef PULSOMETER_FACE_H_
 | 
			
		||||
#define PULSOMETER_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * PULSOMETER face
 | 
			
		||||
 *
 | 
			
		||||
 * The Pulsometer is an implementation of a sort of a classic mechanical
 | 
			
		||||
 * watch complication. A classic pulsometer complication involves a
 | 
			
		||||
 * chronograph with a scale calibrated for counting a certain number of
 | 
			
		||||
 * heartbeats (often 30). You start it and begin counting heartbeats, and
 | 
			
		||||
 * stop it after counting the specified number of beats. Once stopped,
 | 
			
		||||
 * the needle will point to your heart rate.
 | 
			
		||||
 * 
 | 
			
		||||
 * The pulsometer on Sensor Watch flashes its instructions at launch:
 | 
			
		||||
 * “Hold Alarm + count 30 beats.” Using the hand on the side where you wear
 | 
			
		||||
 * your watch, touch your carotid artery (in your neck) and feel for your
 | 
			
		||||
 * pulse. Once you find it, use your other hand to press and hold the Alarm
 | 
			
		||||
 * button, and count your heartbeats. When you reach 30 beats, release the
 | 
			
		||||
 * Alarm button. The display will show a number such as “60 bpm”; this is
 | 
			
		||||
 * your heart rate in beats per minute.
 | 
			
		||||
 * 
 | 
			
		||||
 * Two notes:
 | 
			
		||||
 *  o For the first few seconds of a measurement, the display will read “Hi”.
 | 
			
		||||
 *    This indicates that it’s too early for the measured value to be a valid
 | 
			
		||||
 *    heart rate. Once the measurement is below 240 bpm, the display will update.
 | 
			
		||||
 *  o If you hold the button down for more than 45 seconds, the display will
 | 
			
		||||
 *    read “Lo”. If it took this long for you to count 30 heartbeats, this
 | 
			
		||||
 *    indicates that your heart rate is below 40 beats per minute.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -25,11 +25,8 @@
 | 
			
		||||
#ifndef RANDONAUT_FACE_H_
 | 
			
		||||
#define RANDONAUT_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
#include "place_face.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * RANDONAUT FACE
 | 
			
		||||
 * RANDONAUT face
 | 
			
		||||
 * ==============
 | 
			
		||||
 *
 | 
			
		||||
 * Randonauting is a way to turn the world around you into an adventure and get the user outside 
 | 
			
		||||
@ -71,6 +68,9 @@
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
#include "place_face.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t mode :3;
 | 
			
		||||
    uint8_t location_format :3;
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,16 @@
 | 
			
		||||
#ifndef RATEMETER_FACE_H_
 | 
			
		||||
#define RATEMETER_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * RATE METER face
 | 
			
		||||
 *
 | 
			
		||||
 * The rate meter shows the rate per minute at which the ALARM button is
 | 
			
		||||
 * being pressed. This is particularly useful in sports where cadence
 | 
			
		||||
 * tracking is useful. For instance, rowing coaches often use a dedicated
 | 
			
		||||
 * rate meter - clicking the rate button each time the crew puts their oars
 | 
			
		||||
 * in the water to see the rate (strokes per minute) on the rate meter.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -22,39 +22,6 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* RPN Calculator alternate face.
 | 
			
		||||
 *
 | 
			
		||||
 * Operations appear in the 'day' section; ALARM changes between operations when operation is flashing.
 | 
			
		||||
 * LIGHT executes current operation.
 | 
			
		||||
 *
 | 
			
		||||
 * This is the alternate face because it has a non-traditional number entry system which
 | 
			
		||||
 * I call 'guess a number'. In number entry mode, the watch tries to guess which number you
 | 
			
		||||
 * want, and you respond with 'smaller' (left - MODE) or larger (right - ALARM). This means
 | 
			
		||||
 * that when you _are_ entering a number, MODE will no longer move between faces!
 | 
			
		||||
 *
 | 
			
		||||
 * Example of entering the number 27
 | 
			
		||||
 *  - select the NO operation (probably unnecessary, as this is the default),
 | 
			
		||||
 *    and execute it by hitting LIGHT.
 | 
			
		||||
 *  - you are now in number entry mode; you know this because nothing is flashing.
 | 
			
		||||
 *  - Watch displays 10; you hit ALARM to say you want a larger number.
 | 
			
		||||
 *  - Watch displays 100; you hit MODE to say you want a smaller number.
 | 
			
		||||
 *  - Continuing: 50 -> MODE -> 30 -> MODE -> 20 -> ALARM -> 27
 | 
			
		||||
 *  - Hit LIGHT to add the number to the stack (and now 'NO' is flashing
 | 
			
		||||
 *    again, indicating you're back in operation selection mode).
 | 
			
		||||
 *
 | 
			
		||||
 * One other thing to watch out for is how quickly it will switch into scientific notation
 | 
			
		||||
 * due to the limitations of the display when you have large numbers or non-integer values.
 | 
			
		||||
 * In this mode, the 'colon' serves at the decimal point, and the numbers in the top right
 | 
			
		||||
 * are the exponent.
 | 
			
		||||
 *
 | 
			
		||||
 * As with the main movement firmware, this has the concept of 'secondary' functions which
 | 
			
		||||
 * you can jump to by a long hold of ALARM on NO. These are functions to do with stack
 | 
			
		||||
 * manipulation (pop, swap, dupe, clear, size (le)). If you're _not_ on NO, a long
 | 
			
		||||
 * hold will take you back to it.
 | 
			
		||||
 *
 | 
			
		||||
 * See 'functions' below for names of all operations.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,40 @@
 | 
			
		||||
#ifndef CALCULATOR_FACE_H_
 | 
			
		||||
#define CALCULATOR_FACE_H_
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 * RPN Calculator alternate face.
 | 
			
		||||
 *
 | 
			
		||||
 * Operations appear in the 'day' section; ALARM changes between operations when
 | 
			
		||||
 * operation is flashing. LIGHT executes current operation.
 | 
			
		||||
 *
 | 
			
		||||
 * This is the alternate face because it has a non-traditional number entry system which
 | 
			
		||||
 * I call 'guess a number'. In number entry mode, the watch tries to guess which number you
 | 
			
		||||
 * want, and you respond with 'smaller' (left - MODE) or larger (right - ALARM). This means
 | 
			
		||||
 * that when you _are_ entering a number, MODE will no longer move between faces!
 | 
			
		||||
 *
 | 
			
		||||
 * Example of entering the number 27
 | 
			
		||||
 *  - select the NO operation (probably unnecessary, as this is the default),
 | 
			
		||||
 *    and execute it by hitting LIGHT.
 | 
			
		||||
 *  - you are now in number entry mode; you know this because nothing is flashing.
 | 
			
		||||
 *  - Watch displays 10; you hit ALARM to say you want a larger number.
 | 
			
		||||
 *  - Watch displays 100; you hit MODE to say you want a smaller number.
 | 
			
		||||
 *  - Continuing: 50 -> MODE -> 30 -> MODE -> 20 -> ALARM -> 27
 | 
			
		||||
 *  - Hit LIGHT to add the number to the stack (and now 'NO' is flashing
 | 
			
		||||
 *    again, indicating you're back in operation selection mode).
 | 
			
		||||
 *
 | 
			
		||||
 * One other thing to watch out for is how quickly it will switch into scientific notation
 | 
			
		||||
 * due to the limitations of the display when you have large numbers or non-integer values.
 | 
			
		||||
 * In this mode, the 'colon' serves at the decimal point, and the numbers in the top right
 | 
			
		||||
 * are the exponent.
 | 
			
		||||
 *
 | 
			
		||||
 * As with the main movement firmware, this has the concept of 'secondary' functions which
 | 
			
		||||
 * you can jump to by a long hold of ALARM on NO. These are functions to do with stack
 | 
			
		||||
 * manipulation (pop, swap, dupe, clear, size (le)). If you're _not_ on NO, a long
 | 
			
		||||
 * hold will take you back to it.
 | 
			
		||||
 *
 | 
			
		||||
 * See 'functions' in "rpn_calculator_alt_face.c" for names of all operations.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
#define CALC_MAX_STACK_SIZE 20
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,15 @@
 | 
			
		||||
#ifndef RPN_CALCULATOR_FACE_H_
 | 
			
		||||
#define RPN_CALCULATOR_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * RPN CALCULATOR face
 | 
			
		||||
 *
 | 
			
		||||
 * A calculator face using reverse polish notation (RPN).
 | 
			
		||||
 *
 | 
			
		||||
 * For usage instructions, please refer to the wiki:
 | 
			
		||||
 * https://www.sensorwatch.net/docs/watchfaces/complication/#rpn-calculator
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
#define RPN_CALCULATOR_STACK_SIZE 4
 | 
			
		||||
 | 
			
		||||
@ -24,45 +24,12 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "sailing_face.h"
 | 
			
		||||
#include "watch.h"
 | 
			
		||||
#include "watch_utility.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
Implements a sailing timer.
 | 
			
		||||
 | 
			
		||||
Usage:
 | 
			
		||||
 | 
			
		||||
Waiting mode: Light button enters settings, alarm button starts the timer (sailing mode).
 | 
			
		||||
 | 
			
		||||
Sailing mode:
 | 
			
		||||
Alarm button switches to next programmed start signal, long press on light button
 | 
			
		||||
resets timer and enters waiting mode. Countdown to zero, then switch to counting mode.
 | 
			
		||||
 | 
			
		||||
Counting mode:
 | 
			
		||||
After the start signal (0s), the duration of the race is counted (like a stopwatch timer).
 | 
			
		||||
Alarm button increases the lap counter, alarm long press resets lap counter.
 | 
			
		||||
Long press on light button resets timer and enters waiting mode.
 | 
			
		||||
 | 
			
		||||
Setting mode:
 | 
			
		||||
Alarm button increases active (blinking) signal. Goes to 0 if upper boundary
 | 
			
		||||
(11 or whatever the signal left to the active one is set to) is met.
 | 
			
		||||
10 is printed vertically (letter o plus top segment).
 | 
			
		||||
Alarm button long press resets to default minutes (5-4-1-0).
 | 
			
		||||
Light button cycles through the signals.
 | 
			
		||||
Long press on light button cycles through sound modes:
 | 
			
		||||
- Bell indicator: Sound at start (0s) only.
 | 
			
		||||
- Signal indicator: Sound at each programmed signal and at start.
 | 
			
		||||
- Bell+Signal: Sound at each minute, at 30s and at 10s countdown.
 | 
			
		||||
- No indicator: No sound.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#define sl_SELECTIONS 6
 | 
			
		||||
#define DEFAULT_MINUTES { 5,4,1,0,0,0 }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -24,17 +24,43 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef SAILING_FACE_H_
 | 
			
		||||
#define SAILING_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
A sailing sailing/timer face
 | 
			
		||||
 * SAILING face
 | 
			
		||||
 * Implements a sailing timer.
 | 
			
		||||
 *
 | 
			
		||||
 * Usage:
 | 
			
		||||
 *
 | 
			
		||||
 * Waiting mode:
 | 
			
		||||
 * LIGHT button enters settings
 | 
			
		||||
 * ALARM button starts the timer (sailing mode).
 | 
			
		||||
 *
 | 
			
		||||
 * Sailing mode:
 | 
			
		||||
 * ALARM button switches to next programmed start signal.
 | 
			
		||||
 * Long press on LIGHT button resets timer and enters waiting mode.
 | 
			
		||||
 * Countdown to zero, then switch to counting mode.
 | 
			
		||||
 *
 | 
			
		||||
 * Counting mode:
 | 
			
		||||
 * After the start signal (0s), the duration of the race is counted (like a stopwatch timer).
 | 
			
		||||
 * ALARM button increases the lap counter, ALARM long press resets lap counter.
 | 
			
		||||
 * Long press on LIGHT button resets timer and enters waiting mode.
 | 
			
		||||
 *
 | 
			
		||||
 * Setting mode:
 | 
			
		||||
 * ALARM button increases active (blinking) signal. Goes to 0 if upper boundary
 | 
			
		||||
 * (11 or whatever the signal left to the active one is set to) is met.
 | 
			
		||||
 * 10 is printed vertically (letter o plus top segment).
 | 
			
		||||
 * ALARM button long press resets to default minutes (5-4-1-0).
 | 
			
		||||
 * LIGHT button cycles through the signals.
 | 
			
		||||
 * Long press on LIGHT button cycles through sound modes:
 | 
			
		||||
 * - Bell indicator: Sound at start (0s) only.
 | 
			
		||||
 * - Signal indicator: Sound at each programmed signal and at start.
 | 
			
		||||
 * - Bell+Signal: Sound at each minute, at 30s and at 10s countdown.
 | 
			
		||||
 * - No indicator: No sound.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    sl_waiting,
 | 
			
		||||
 | 
			
		||||
@ -25,9 +25,8 @@
 | 
			
		||||
#ifndef SHIPS_BELL_FACE_H_
 | 
			
		||||
#define SHIPS_BELL_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * SHIP'S BELL face
 | 
			
		||||
 * A ship's bell complication.
 | 
			
		||||
 *
 | 
			
		||||
 * See: https://en.wikipedia.org/wiki/Ship%27s_bell#Simpler_system
 | 
			
		||||
@ -45,6 +44,8 @@
 | 
			
		||||
 *   - long press Alarm button: Cycle through the watches (All/1/2/3)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    bool bell_enabled;
 | 
			
		||||
    uint8_t on_watch;
 | 
			
		||||
 | 
			
		||||
@ -25,12 +25,34 @@
 | 
			
		||||
#ifndef STOCK_STOPWATCH_FACE_H_
 | 
			
		||||
#define STOCK_STOPWATCH_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
/*
 | 
			
		||||
 * STOCK STOPWATCH face
 | 
			
		||||
 *
 | 
			
		||||
 * The Stock Stopwatch face implements the original F-91W stopwatch
 | 
			
		||||
 * functionality, including counting hundredths of seconds and lap timing.
 | 
			
		||||
 *
 | 
			
		||||
 * Use the ALARM button to start and stop the stopwatch.
 | 
			
		||||
 * Press the LIGHT button while the stopwatch is running to view the lap time.
 | 
			
		||||
 *  (The stopwatch continues running in the background, indicated by a blinking colon.)
 | 
			
		||||
 * Press the LIGHT button again to switch back to the running stopwatch.
 | 
			
		||||
 * Press the LIGHT button when the timekeeping is stopped to reset the stopwatch.
 | 
			
		||||
 *
 | 
			
		||||
 * There are two improvements compared to the original F-91W:
 | 
			
		||||
 *  o When the stopwatch reaches 59:59, the counter does not simply jump back
 | 
			
		||||
 *    to zero but keeps track of hours in the upper right-hand corner
 | 
			
		||||
 *    (up to 24 hours).
 | 
			
		||||
 *  o Long-press the light button to toggle the LED behavior.
 | 
			
		||||
 *    It either turns on with each button press or remains off.
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE:
 | 
			
		||||
 * This watch face relies heavily on static vars in stock_stopwatch.c.
 | 
			
		||||
 * The disadvantage is that you cannot use more than one instance of this
 | 
			
		||||
 * watch face on your custom firmware - but then again, who would want that?
 | 
			
		||||
 * The advantage is that accessing vars is more direct and faster, and we
 | 
			
		||||
 * can save some precious cpu cycles.  :-)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// This watch face relies heavily on static vars in stock_stopwatch.c.
 | 
			
		||||
// The disadvantage is that you cannot use more than one instance of this watch face on
 | 
			
		||||
// your custom firmware - but then again, who would want that? The advantage is that accessing
 | 
			
		||||
// vars is more direct and faster, and we can save some precious cpu cycles  :-) 
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    bool light_on_button;   // determines whether the light button actually triggers the led
 | 
			
		||||
 | 
			
		||||
@ -26,6 +26,17 @@
 | 
			
		||||
#ifndef STOPWATCH_FACE_H_
 | 
			
		||||
#define STOPWATCH_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * STOPWATCH FACE
 | 
			
		||||
 *
 | 
			
		||||
 * The Stopwatch face provides basic stopwatch functionality: you can start
 | 
			
		||||
 * and stop the stopwatch with the alarm button. Pressing the light button
 | 
			
		||||
 * when the timer is stopped resets it.
 | 
			
		||||
 *
 | 
			
		||||
 * This face does not count sub-seconds.
 | 
			
		||||
 * See also: "stock_stopwatch_face.h"
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -25,10 +25,18 @@
 | 
			
		||||
#ifndef SUNRISE_SUNSET_FACE_H_
 | 
			
		||||
#define SUNRISE_SUNSET_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
/*
 | 
			
		||||
 * SUNRISE & SUNSET FACE
 | 
			
		||||
 *
 | 
			
		||||
 * The Sunrise/Sunset face is designed to display the next sunrise or sunset
 | 
			
		||||
 * for a given location. It also functions as an interface for setting the
 | 
			
		||||
 * location register, which other watch faces can use for various purposes.
 | 
			
		||||
 *
 | 
			
		||||
 * Refer to the wiki for usage instructions:
 | 
			
		||||
 *  https://www.sensorwatch.net/docs/watchfaces/complication/#sunrisesunset
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// The Sunrise/Sunset face is designed to display the next sunrise or sunset for a given location.
 | 
			
		||||
// TODO: It also functions as an interface for setting the location register, which other watch faces can use for various purposes.
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t sign: 1;    // 0-1
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,49 @@
 | 
			
		||||
#ifndef TACHYMETER_FACE_H_
 | 
			
		||||
#define TACHYMETER_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * TACHYMETER face
 | 
			
		||||
 *
 | 
			
		||||
 * The Tachymeter complication emulates the tachymeter function often
 | 
			
		||||
 * present in watches, that computes the average speed in [units per hour]
 | 
			
		||||
 * for a given distance given in [units].
 | 
			
		||||
 *
 | 
			
		||||
 * Use case:
 | 
			
		||||
 *     User sets the distance
 | 
			
		||||
 *     User starts the tachymeter when the trip begins
 | 
			
		||||
 *     User stops the tachymeter when the trip ends
 | 
			
		||||
 *     The watch presents the average speed and trip duration in seconds
 | 
			
		||||
 * 
 | 
			
		||||
 * Usage:
 | 
			
		||||
 *     Go to tachymeter face, TC is shown in the Weekday Digits
 | 
			
		||||
 *     A steady d in the Day Digits indicates the distance to be used.
 | 
			
		||||
 *         To edit the distance:
 | 
			
		||||
 *         Long-press the Alarm button, the distance edition page (d will blink)
 | 
			
		||||
 *         Use the Light button to change the editing (blinking) digit, and press Alarm to increase its value
 | 
			
		||||
 *         Once done, long-press the Alarm button to exit the distance edition page
 | 
			
		||||
 *     Press the Alarm button to start the tachymeter.
 | 
			
		||||
 *         A running animation will appear in the Day Digits
 | 
			
		||||
 *     Press the Alarm button to stop the tachymeter
 | 
			
		||||
 *     The average speed and total time information will alternate.
 | 
			
		||||
 *         The average speed will be shown alongside /h in the Day Digits;
 | 
			
		||||
 *         and the total time will be shown alongside t in the Day Digits.
 | 
			
		||||
 *     Long press the Light button to return to the distance d page,
 | 
			
		||||
 *         and restart the tachymeter from there.
 | 
			
		||||
 *     Long-press the light button in the steady distance page to reset
 | 
			
		||||
 *         the distance to 1.00
 | 
			
		||||
 * 
 | 
			
		||||
 * Pending design points
 | 
			
		||||
 * o movement_request_tick_frequency(4) is used to obtain a 4Hz ticking, thus
 | 
			
		||||
 *   having a time resolution of 250 ms. Not sure if using event.subsecond`
 | 
			
		||||
 *   is the proper way to get the fractions of second for the start and
 | 
			
		||||
 *   final times.
 | 
			
		||||
 * o For distance and average speed, the Second Digits (position 8 and 9)
 | 
			
		||||
 *   can be seen as decimals, thus possible to show distances as short as
 | 
			
		||||
 *   0.01 km (or miles) and speeds as low as 0.01 km/h (or mph). However,
 | 
			
		||||
 *   if the same idea is used for the total time (showing hundredths),
 | 
			
		||||
 *   this limits the display to 9999.99 seconds (~2h:45m).
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -25,11 +25,17 @@
 | 
			
		||||
#ifndef TALLY_FACE_H_
 | 
			
		||||
#define TALLY_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
/*
 | 
			
		||||
 * TALLY face
 | 
			
		||||
 *
 | 
			
		||||
 * Tally face is designed to act as a tally counter.
 | 
			
		||||
 * Based on the counter_face watch face by Shogo Okamoto.
 | 
			
		||||
 *
 | 
			
		||||
 * To advance the counter, press the ALARM button.
 | 
			
		||||
 * To reset, long press the ALARM button.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// Tally face is designed to act as a tally counter.
 | 
			
		||||
// Based on the counter_face watch face by Shogo Okamoto.
 | 
			
		||||
// To advance the counter, press the Alarm button. To reset, long press the Alarm button.
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint32_t tally_idx;
 | 
			
		||||
 | 
			
		||||
@ -25,10 +25,8 @@
 | 
			
		||||
#ifndef TAROT_FACE_H_
 | 
			
		||||
#define TAROT_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Tarot card watch face
 | 
			
		||||
 * TAROT CARD watch face
 | 
			
		||||
 *
 | 
			
		||||
 * Draw from a deck of tarot cards. Can choose between major arcana only or
 | 
			
		||||
 * entire deck.
 | 
			
		||||
@ -62,6 +60,8 @@
 | 
			
		||||
 * - Light button (long press): go back to Draw screen, for choosing different draw parameters.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
#define MAX_CARDS_TO_DRAW 10
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -20,11 +20,6 @@
 | 
			
		||||
 * 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.
 | 
			
		||||
 *
 | 
			
		||||
 * Gathers temperature statistics in a chart form. Statistics bins are per hour / per 0.5°C.
 | 
			
		||||
 * Saved to file every day at 00:00. Can help improve watch precision in the future. 
 | 
			
		||||
 * If you can gather statistics over few months, and then send tempchart.ini to 3@14.by - it 
 | 
			
		||||
 * will help future generations of precision quartz watches. 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,19 @@
 | 
			
		||||
#ifndef TEMPCHART_FACE_H_
 | 
			
		||||
#define TEMPCHART_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * TEMPERATURE CHART face
 | 
			
		||||
 *
 | 
			
		||||
 * Gathers temperature statistics in a chart form.
 | 
			
		||||
 * Statistics bins are per hour / per 0.5°C.
 | 
			
		||||
 *
 | 
			
		||||
 * Saved to file every day at 00:00.
 | 
			
		||||
 * Can help improve watch precision in the future. 
 | 
			
		||||
 *
 | 
			
		||||
 * If you can gather statistics over few months, and then send "tempchart.ini"
 | 
			
		||||
 * to "3@14.by", it will help future generations of precision quartz watches.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
void tempchart_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
 | 
			
		||||
 | 
			
		||||
@ -25,9 +25,9 @@
 | 
			
		||||
#ifndef TIME_LEFT_FACE_H_
 | 
			
		||||
#define TIME_LEFT_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * TIME LEFT face
 | 
			
		||||
 *
 | 
			
		||||
 * The Time Left Face helps you to visualize how far you have proceeded in a certain
 | 
			
		||||
 * time span. Much like the Day One Face, you can set your beginning date. In addition
 | 
			
		||||
 * to that, you also set your target or destination date. You can then use the face
 | 
			
		||||
@ -65,6 +65,8 @@
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t current_page;
 | 
			
		||||
    uint16_t current_year;
 | 
			
		||||
 | 
			
		||||
@ -22,8 +22,6 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "timer_face.h"
 | 
			
		||||
 | 
			
		||||
@ -22,14 +22,11 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef TIMER_FACE_H_
 | 
			
		||||
#define TIMER_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * TIMER face
 | 
			
		||||
 * Advanced timer/countdown face with pre-set timer lengths
 | 
			
		||||
 * 
 | 
			
		||||
 * This watch face provides the functionality of starting a countdown by choosing 
 | 
			
		||||
@ -53,6 +50,8 @@
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
#define TIMER_SLOTS 9           // offer 9 timer slots
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,26 @@
 | 
			
		||||
#ifndef TOMATO_FACE_H_
 | 
			
		||||
#define TOMATO_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * TOMATO TIMER face
 | 
			
		||||
 *
 | 
			
		||||
 * Add a "tomato" timer watch face that alternates between 25 and 5 minute
 | 
			
		||||
 * timers as in the Pomodoro Technique.
 | 
			
		||||
 *  https://en.wikipedia.org/wiki/Pomodoro_Technique
 | 
			
		||||
 *
 | 
			
		||||
 * The top right letter shows mode (f for focus or b for break).
 | 
			
		||||
 * The bottom right shows how many focus sessions you've completed.
 | 
			
		||||
 * (You can reset the count with a long press of alarm)
 | 
			
		||||
 *
 | 
			
		||||
 * When you show up and it says 25 minutes, you can start it (alarm),
 | 
			
		||||
 *  switch to 5 minute (light) mode or leave (mode).
 | 
			
		||||
 *
 | 
			
		||||
 * When it's running you can reset (alarm), or leave (mode).
 | 
			
		||||
 *
 | 
			
		||||
 * When it's done, we beep and go back to step 1, changing switching
 | 
			
		||||
 *  mode from focus to break (or break to focus)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
 | 
			
		||||
@ -25,10 +25,8 @@
 | 
			
		||||
#ifndef TOSS_UP_FACE_H_
 | 
			
		||||
#define TOSS_UP_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * TOSS UP FACE
 | 
			
		||||
 * TOSS UP face
 | 
			
		||||
 * ============
 | 
			
		||||
 *
 | 
			
		||||
 * Playful watch face for games of chance or divination using coins or dice.
 | 
			
		||||
@ -75,6 +73,8 @@
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    // Anything you need to keep track of, put it here!
 | 
			
		||||
    uint32_t entropy;
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,27 @@
 | 
			
		||||
/*
 | 
			
		||||
 * MIT License
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2022 Wesley Ellis (https://github.com/tahnok)
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "totp_face.h"
 | 
			
		||||
@ -5,15 +29,6 @@
 | 
			
		||||
#include "watch_utility.h"
 | 
			
		||||
#include "TOTP.h"
 | 
			
		||||
 | 
			
		||||
// Use https://cryptii.com/pipes/base32-to-hex to convert base32 to hex
 | 
			
		||||
// Use https://github.com/susam/mintotp to generate test codes for verification
 | 
			
		||||
// Available algorothms:
 | 
			
		||||
// SHA1 (most TOTP codes use this)
 | 
			
		||||
// SHA224
 | 
			
		||||
// SHA256
 | 
			
		||||
// SHA384
 | 
			
		||||
// SHA512
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Enter your TOTP key data below
 | 
			
		||||
static const uint8_t num_keys = 2;
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,58 @@
 | 
			
		||||
/*
 | 
			
		||||
 * MIT License
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2022 Wesley Ellis (https://github.com/tahnok)
 | 
			
		||||
 *
 | 
			
		||||
 * 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 TOTP_FACE_H_
 | 
			
		||||
#define TOTP_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * TOTP face
 | 
			
		||||
 * Time-based one-time password (TOTP) generator
 | 
			
		||||
 *
 | 
			
		||||
 * Generate one-time passwords often used for two-factor authentication.
 | 
			
		||||
 * The secret key must be set by hand, by editing "totp_face.c".
 | 
			
		||||
 *
 | 
			
		||||
 * Available algorithms:
 | 
			
		||||
 *  o SHA1 (most TOTP codes use this)
 | 
			
		||||
 *  o SHA224
 | 
			
		||||
 *  o SHA256
 | 
			
		||||
 *  o SHA384
 | 
			
		||||
 *  o SHA512
 | 
			
		||||
 *
 | 
			
		||||
 * Instructions:
 | 
			
		||||
 *  o Find your secret key(s) and convert them to the required format.
 | 
			
		||||
 *      o Use https://cryptii.com/pipes/base32-to-hex to convert base32 to hex
 | 
			
		||||
 *      o Use https://github.com/susam/mintotp to generate test codes for verification
 | 
			
		||||
 *  o Edit global variables in "totp_face.c" to configure your stored keys:
 | 
			
		||||
 *      o "keys", "key_sizes", "timesteps", and "algorithms" set the
 | 
			
		||||
 *        cryptographic parameters for each secret key.
 | 
			
		||||
 *      o "labels" sets the two-letter label for each key
 | 
			
		||||
 *        (This replaces the day-of-week indicator)
 | 
			
		||||
 *      o Once finished, remove the two provided examples.
 | 
			
		||||
 *
 | 
			
		||||
 * If you have more than one secret key, press ALARM to cycle through them.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,27 @@
 | 
			
		||||
/*
 | 
			
		||||
 * MIT License
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2022 Wesley Ellis (https://github.com/tahnok)
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
@ -11,24 +35,6 @@
 | 
			
		||||
 | 
			
		||||
#include "totp_face_lfs.h"
 | 
			
		||||
 | 
			
		||||
/* Reads from a file totp_uris.txt where each line is what's in a QR code:
 | 
			
		||||
 * e.g.
 | 
			
		||||
 *   otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example
 | 
			
		||||
 *   otpauth://totp/ACME%20Co:john.doe@email.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30
 | 
			
		||||
 * This is also the same as what Aegis exports in plain-text format.
 | 
			
		||||
 *
 | 
			
		||||
 * Minimal sanitisation of input, however.
 | 
			
		||||
 *
 | 
			
		||||
 * At the moment, to get the records onto the filesystem, start a serial connection and do:
 | 
			
		||||
 *   echo otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example > totp_uris.txt
 | 
			
		||||
 *   echo otpauth://totp/ACME%20Co:john.doe@email.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30 >> totp_uris.txt
 | 
			
		||||
 * (note the double >> in the second one)
 | 
			
		||||
 *
 | 
			
		||||
 * You may want to customise the characters that appear to identify the 2FA code. These are just the first two characters of the issuer,
 | 
			
		||||
 * and it's fine to modify the URI.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define MAX_TOTP_RECORDS 20
 | 
			
		||||
#define MAX_TOTP_SECRET_SIZE 48
 | 
			
		||||
#define TOTP_FILE "totp_uris.txt"
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,54 @@
 | 
			
		||||
/*
 | 
			
		||||
 * MIT License
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2022 Wesley Ellis (https://github.com/tahnok)
 | 
			
		||||
 *
 | 
			
		||||
 * 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 TOTP_FACE_LFS_H_
 | 
			
		||||
#define TOTP_FACE_LFS_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * TOTP-LFS face
 | 
			
		||||
 * Time-based one-time password (TOTP) generator using LFS
 | 
			
		||||
 *
 | 
			
		||||
 * Reads from a file "totp_uris.txt", containing a single secret key in a
 | 
			
		||||
 * series of URLs. Each line is what's in a QR code, e.g.:
 | 
			
		||||
 *   otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example
 | 
			
		||||
 *   otpauth://totp/ACME%20Co:john.doe@email.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30
 | 
			
		||||
 *
 | 
			
		||||
 * This is also the same as what Aegis exports in plain-text format.
 | 
			
		||||
 * This face performs minimal sanitisation of input, however.
 | 
			
		||||
 *
 | 
			
		||||
 * At the moment, to get the records onto the filesystem, start a serial connection and do:
 | 
			
		||||
 *   echo otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example > totp_uris.txt
 | 
			
		||||
 *   echo otpauth://totp/ACME%20Co:john.doe@email.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30 >> totp_uris.txt
 | 
			
		||||
 * (note the double >> in the second one)
 | 
			
		||||
 *
 | 
			
		||||
 * You may want to customise the characters that appear to identify the 2FA
 | 
			
		||||
 * code. These are just the first two characters of the issuer, and it's fine
 | 
			
		||||
 * to modify the URI.
 | 
			
		||||
 *
 | 
			
		||||
 * If you have more than one secret key, press ALARM to cycle through them.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -22,24 +22,12 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
// #include <threads.h>
 | 
			
		||||
 | 
			
		||||
#include "wake_face.h"
 | 
			
		||||
#include "watch.h"
 | 
			
		||||
#include "watch_utility.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    UI Notes
 | 
			
		||||
    º Light advances hour by 1
 | 
			
		||||
    º Light long press advances hour by 6
 | 
			
		||||
    º Alarm advances minute by 10
 | 
			
		||||
    º Alarm long press cycles through signal modes (just one at the moment)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Private
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
@ -22,11 +22,24 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef WAKE_FACE_H_
 | 
			
		||||
#define WAKE_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * WAKE daily alarm face
 | 
			
		||||
 *
 | 
			
		||||
 * Basic daily alarm clock face. Seems useful if nothing else in the interest
 | 
			
		||||
 * of feature parity with the F-91W’s OEM module, 593.
 | 
			
		||||
 *
 | 
			
		||||
 * Also experiments with caret-free UI: One button cycles hours, the other
 | 
			
		||||
 * minutes, so there’s no toggling between display and adjust modes and no
 | 
			
		||||
 * cycling the caret through the UI.
 | 
			
		||||
 *   º LIGHT advances hour by 1
 | 
			
		||||
 *   º LIGHT long press advances hour by 6
 | 
			
		||||
 *   º ALARM advances minute by 10
 | 
			
		||||
 *   º ALARM long press cycles through signal modes (just one at the moment)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,17 @@
 | 
			
		||||
#ifndef CHARACTER_SET_FACE_H_
 | 
			
		||||
#define CHARACTER_SET_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * CHARACTER SET FACE
 | 
			
		||||
 *
 | 
			
		||||
 * This watch face displays all of the characters in the Sensor Watch character
 | 
			
		||||
 * set. You can advance from one character to the next with a short press of the
 | 
			
		||||
 * ALARM button.
 | 
			
		||||
 *
 | 
			
		||||
 * This watch face may be useful to watch face developers, in that it can help
 | 
			
		||||
 * them to understand which characters will work in different positions.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
void character_set_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
 | 
			
		||||
 | 
			
		||||
@ -25,8 +25,6 @@
 | 
			
		||||
#ifndef CHIRPY_DEMO_FACE_H_
 | 
			
		||||
#define CHIRPY_DEMO_FACE_H_
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * CHIRPY DEMO FACE
 | 
			
		||||
 * 
 | 
			
		||||
@ -50,9 +48,10 @@
 | 
			
		||||
 * 
 | 
			
		||||
 * To record and decode a chirpy transmission on your computer, you can use the web app here:
 | 
			
		||||
 * https://jealousmarkup.xyz/off/chirpy/rx/
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
void chirpy_demo_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
 | 
			
		||||
void chirpy_demo_face_activate(movement_settings_t *settings, void *context);
 | 
			
		||||
bool chirpy_demo_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,17 @@
 | 
			
		||||
#ifndef DEMO_FACE_H_
 | 
			
		||||
#define DEMO_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DEMO FACE
 | 
			
		||||
 *
 | 
			
		||||
 * This watch was designed for the Crowd Supply marketing team, so they could
 | 
			
		||||
 * photograph the various functions of Sensor Watch. The Alarm button advances
 | 
			
		||||
 * through static screens that simulate different watch faces.
 | 
			
		||||
 *
 | 
			
		||||
 * This watch face may only be useful to you if you need to photograph Sensor
 | 
			
		||||
 * Watch, i.e. for a blog post.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
void demo_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,18 @@
 | 
			
		||||
#ifndef FREQUENCY_CORRECTION_FACE_H_
 | 
			
		||||
#define FREQUENCY_CORRECTION_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * FREQUENCY CORRECTION FACE
 | 
			
		||||
 *
 | 
			
		||||
 * While active, this face generates a square-wave on pin A1 of the 9-pin
 | 
			
		||||
 * connector. The output frequency is adjustable from 64 Hz to 0.5 Hz.
 | 
			
		||||
 * Long-press ALARM to cycle through available frequencies.
 | 
			
		||||
 *
 | 
			
		||||
 * This face also displays the value of the watch's frequency-correction
 | 
			
		||||
 * register. This setting varies from -127 to +127. Press LIGHT to increment
 | 
			
		||||
 * or ALARM to decrement the setting.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,13 @@
 | 
			
		||||
#ifndef HELLO_THERE_FACE_H_
 | 
			
		||||
#define HELLO_THERE_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * HELLO THERE FACE
 | 
			
		||||
 *
 | 
			
		||||
 * A simple demo that displays the word "Hello" and then the word "there",
 | 
			
		||||
 * on an endless loop. Press ALARM to pause or resume the animation.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,14 @@
 | 
			
		||||
#ifndef LIS2DW_LOGGING_FACE_H_
 | 
			
		||||
#define LIS2DW_LOGGING_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * LIS2DW Accelerometer Data Logger
 | 
			
		||||
 *
 | 
			
		||||
 * This is an experimental watch face for logging data on the “Sensor Watch
 | 
			
		||||
 * Motion Express” board. I will add more documentation for this watch face
 | 
			
		||||
 * once this sensor board is more widely available.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
#include "watch.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,17 @@
 | 
			
		||||
#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(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,12 @@
 | 
			
		||||
#ifndef ACCELEROMETER_DATA_ACQUISITION_FACE_H_
 | 
			
		||||
#define ACCELEROMETER_DATA_ACQUISITION_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ACCELEROMETER DATA ACQUISITION
 | 
			
		||||
 *
 | 
			
		||||
 * TODO: Add description here, including controls.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
#define ACCELEROMETER_DATA_ACQUISITION_INVALID ((uint64_t)(0b11))   // all bits are 1 when the flash is erased
 | 
			
		||||
 | 
			
		||||
@ -22,37 +22,6 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Aperture-priority Light Meter Face
 | 
			
		||||
 *
 | 
			
		||||
 * Tested with the "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001" flexboard.
 | 
			
		||||
 * This flexboard could use a revision: 
 | 
			
		||||
 *
 | 
			
		||||
 *  - The thermistor components should be moved west a mm or flipped to the backside
 | 
			
		||||
 *    to avoid stressing the flexboard against the processor so much.
 | 
			
		||||
 *  - The 'no connect' pad falls off easily.
 | 
			
		||||
 *
 | 
			
		||||
 * Controls:
 | 
			
		||||
 *
 | 
			
		||||
 *  - Trigger a measurement by long-pressing Alarm.
 | 
			
		||||
 *    Sensor integration is happening when the Signal indicator is on.
 | 
			
		||||
 *
 | 
			
		||||
 *  - ISO setting can be cycled by long-pressing Light.
 | 
			
		||||
 *    During integration the current ISO setting will be displayed. 
 | 
			
		||||
 *
 | 
			
		||||
 *  - EV measurement in the top right: "LAP" indicates "half stop". 
 | 
			
		||||
 *    So "LAP -1" means EV = -1.5. Likewise "LAP 13" means EV = +13.5  
 | 
			
		||||
 *
 | 
			
		||||
 *  - Aperture in the bottom right: the last 3 main digits are the f-stop. 
 | 
			
		||||
 *    Adjust this number in half-stop increments using Alarm = +1/2 and Light = -1/2. 
 | 
			
		||||
 *
 | 
			
		||||
 *  - Best shutter speed in the bottom left: the first 3 digits are the shutter speed. 
 | 
			
		||||
 *    Some special chars are needed here: "-" = seconds, "h" = extra half second, "K" = thousands.
 | 
			
		||||
 *    "HI" or "LO" if there's no shutter in the dictionary within 0.5 stops of correct exposure.
 | 
			
		||||
 *
 | 
			
		||||
 *  - Mode long-press changes the main digits to show raw sensor lux measurements.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,37 @@
 | 
			
		||||
#ifndef LIGHTMETER_FACE_H_
 | 
			
		||||
#define LIGHTMETER_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Aperture-priority Light Meter Face
 | 
			
		||||
 *
 | 
			
		||||
 * Tested with the "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001" flexboard.
 | 
			
		||||
 * This flexboard could use a revision: 
 | 
			
		||||
 *
 | 
			
		||||
 *  - The thermistor components should be moved west a mm or flipped to the backside
 | 
			
		||||
 *    to avoid stressing the flexboard against the processor so much.
 | 
			
		||||
 *  - The 'no connect' pad falls off easily.
 | 
			
		||||
 *
 | 
			
		||||
 * Controls:
 | 
			
		||||
 *
 | 
			
		||||
 *  - Trigger a measurement by long-pressing Alarm.
 | 
			
		||||
 *    Sensor integration is happening when the Signal indicator is on.
 | 
			
		||||
 *
 | 
			
		||||
 *  - ISO setting can be cycled by long-pressing Light.
 | 
			
		||||
 *    During integration the current ISO setting will be displayed. 
 | 
			
		||||
 *
 | 
			
		||||
 *  - EV measurement in the top right: "LAP" indicates "half stop". 
 | 
			
		||||
 *    So "LAP -1" means EV = -1.5. Likewise "LAP 13" means EV = +13.5  
 | 
			
		||||
 *
 | 
			
		||||
 *  - Aperture in the bottom right: the last 3 main digits are the f-stop. 
 | 
			
		||||
 *    Adjust this number in half-stop increments using Alarm = +1/2 and Light = -1/2. 
 | 
			
		||||
 *
 | 
			
		||||
 *  - Best shutter speed in the bottom left: the first 3 digits are the shutter speed. 
 | 
			
		||||
 *    Some special chars are needed here: "-" = seconds, "h" = extra half second, "K" = thousands.
 | 
			
		||||
 *    "HI" or "LO" if there's no shutter in the dictionary within 0.5 stops of correct exposure.
 | 
			
		||||
 *
 | 
			
		||||
 *  - Mode long-press changes the main digits to show raw sensor lux measurements.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
#include "opt3001.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,34 @@
 | 
			
		||||
#ifndef THERMISTOR_LOGGING_FACE_H_
 | 
			
		||||
#define THERMISTOR_LOGGING_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * THERMISTOR LOGGING (aka Temperature Log)
 | 
			
		||||
 *
 | 
			
		||||
 * This watch face automatically logs the temperature once an hour, and
 | 
			
		||||
 * maintains a 36-hour log of readings. This watch face is admittedly rather
 | 
			
		||||
 * complex, and bears some explanation.
 | 
			
		||||
 *
 | 
			
		||||
 * The main display shows the letters “TL” in the top left, indicating the
 | 
			
		||||
 * name of the watch face. At the top right, it displays the index of the
 | 
			
		||||
 * reading; 0 represents the most recent reading taken, 1 represents one
 | 
			
		||||
 * hour earlier, etc. The bottom line in this mode displays the logged
 | 
			
		||||
 * temperature.
 | 
			
		||||
 *
 | 
			
		||||
 * A short press of the “Alarm” button advances to the next oldest reading;
 | 
			
		||||
 * you will see the number at the top right advance from 0 to 1 to 2, all
 | 
			
		||||
 * the way to 35, the oldest reading available.
 | 
			
		||||
 *
 | 
			
		||||
 * A short press of the “Light” button will briefly display the timestamp
 | 
			
		||||
 * of the reading. The letters at the top left will display the word “At”,
 | 
			
		||||
 * and the main line will display the timestamp of the currently displayed
 | 
			
		||||
 * data point. The number in the top right will display the day of the month
 | 
			
		||||
 * for the given data point; for example, you can read “At 22 3:00 PM” as
 | 
			
		||||
 * ”At 3:00 PM on the 22nd”.
 | 
			
		||||
 *
 | 
			
		||||
 * If you need to illuminate the LED to read the data point, long press the
 | 
			
		||||
 * Light button and release it.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
#include "watch.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,29 @@
 | 
			
		||||
#ifndef THERMISTOR_READOUT_FACE_H_
 | 
			
		||||
#define THERMISTOR_READOUT_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * THERMISTOR READOUT (aka Temperature Display)
 | 
			
		||||
 *
 | 
			
		||||
 * This watch face is designed to work with either the Temperature + GPIO
 | 
			
		||||
 * sensor board or the Temperature + Light sensor board. It reads the current
 | 
			
		||||
 * temperature from the thermistor voltage divider on the sensor board, and
 | 
			
		||||
 * displays the current temperature in degrees Celsius.
 | 
			
		||||
 *
 | 
			
		||||
 * When the watch is on your wrist, your body heat interferes with an ambient
 | 
			
		||||
 * temperature reading, but if you set it on a bedside table, strap it to your
 | 
			
		||||
 * bike handlebars or place it outside of your tent while camping, this watch
 | 
			
		||||
 * face can act as a digital thermometer for displaying ambient conditions.
 | 
			
		||||
 *
 | 
			
		||||
 * The temperature sensor watch face automatically samples the temperature
 | 
			
		||||
 * once every five seconds, and it illuminates the Signal indicator just
 | 
			
		||||
 * before taking a reading.
 | 
			
		||||
 *
 | 
			
		||||
 * Pressing the ALARM button toggles the unit display from Celsius to
 | 
			
		||||
 * Fahrenheit. Technically this sets the global “Metric / Imperial” flag, so
 | 
			
		||||
 * any other watch face that displays localizable units will display them in
 | 
			
		||||
 * the system selected here.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
void thermistor_readout_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
 | 
			
		||||
 | 
			
		||||
@ -28,11 +28,6 @@
 | 
			
		||||
#include "thermistor_driver.h"
 | 
			
		||||
#include "watch.h"
 | 
			
		||||
 | 
			
		||||
// This watch face is designed for testing temperature sensor boards.
 | 
			
		||||
// It displays temperature readings at a relatively fast rate of 8 Hz,
 | 
			
		||||
// and disables low energy mode so my testing device doesn't sleep.
 | 
			
		||||
// You more than likely want to use thermistor_readout_face instead.
 | 
			
		||||
 | 
			
		||||
static void _thermistor_testing_face_update_display(bool in_fahrenheit) {
 | 
			
		||||
    thermistor_driver_enable();
 | 
			
		||||
    float temperature_c = thermistor_driver_get_temperature();
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,17 @@
 | 
			
		||||
#ifndef THERMISTOR_TESTING_FACE_H_
 | 
			
		||||
#define THERMISTOR_TESTING_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * THERMISTOR TESTING FACE
 | 
			
		||||
 *
 | 
			
		||||
 * This watch face is designed for testing temperature sensor boards.
 | 
			
		||||
 * It displays temperature readings at a relatively fast rate of 8 Hz,
 | 
			
		||||
 * and disables low energy mode so my testing device doesn't sleep.
 | 
			
		||||
 * You more than likely want to use thermistor_readout_face instead.
 | 
			
		||||
 *
 | 
			
		||||
 * Press ALARM to toggle display of metric vs. imperial units.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
void thermistor_testing_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
 | 
			
		||||
 | 
			
		||||
@ -20,21 +20,6 @@
 | 
			
		||||
 * 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.
 | 
			
		||||
 *
 | 
			
		||||
 * FineTune face allows to align watch with sub-second precision in 25/250ms accuracy.
 | 
			
		||||
 * Counts time since previous finetune, and allows to calculate & apply ppm correction for nanosec.
 | 
			
		||||
 *
 | 
			
		||||
 * Main screen - adjust delay (light/alarm)
 | 
			
		||||
 * Long mode press - show hours since previous finetune
 | 
			
		||||
 * Long mode press - show calculated ppm correction. You can apply it with long light, or just reset finetune timer with long alarm.
 | 
			
		||||
 *
 | 
			
		||||
 * Finetune will apply crystal aging correction on every finetune save (as aging is calculated since "last finetune" timestamp) - but you should worry
 | 
			
		||||
 * about aging only on second/third years of watch calibration (if you are really looking at less than 10 seconds per year of error).
 | 
			
		||||
 *
 | 
			
		||||
 * Warning, do not use at the first second of a month, as you might stay at the same month and it will surprise you.
 | 
			
		||||
 * Just wait 1 second...We are not fully replicating RTC timer behavior when RTC is off.
 | 
			
		||||
 * Simulating months and years is... too much complexity.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,34 @@
 | 
			
		||||
#ifndef FINETUNE_FACE_H_
 | 
			
		||||
#define FINETUNE_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * FINETUNE face
 | 
			
		||||
 *
 | 
			
		||||
 * FineTune face allows to align watch with sub-second precision in 25/250ms
 | 
			
		||||
 * accuracy. Counts time since previous finetune, and allows to calculate &
 | 
			
		||||
 * apply ppm correction for nanosec.
 | 
			
		||||
 *
 | 
			
		||||
 * Best used in conjunction with the NANOSEC face.
 | 
			
		||||
 *
 | 
			
		||||
 * Main screen - adjust delay (light/alarm)
 | 
			
		||||
 * Long MODE press - show hours since previous finetune
 | 
			
		||||
 * Long MODE press - show calculated ppm correction.
 | 
			
		||||
 *  You can apply it with long LIGHT, or just reset finetune timer with long ALARM.
 | 
			
		||||
 *
 | 
			
		||||
 * Finetune will apply crystal aging correction on every finetune save
 | 
			
		||||
 * (as aging is calculated since "last finetune" timestamp); but you should
 | 
			
		||||
 * worry about aging only on second/third years of watch calibration (if you
 | 
			
		||||
 * are really looking at less than 10 seconds per year of error).
 | 
			
		||||
 *
 | 
			
		||||
 * Warning, do not use at the first second of a month, as you might stay at
 | 
			
		||||
 * the same month and it will surprise you. Just wait 1 second...We are not
 | 
			
		||||
 * fully replicating RTC timer behavior when RTC is off.
 | 
			
		||||
 * Simulating months and years is... too much complexity.
 | 
			
		||||
 *
 | 
			
		||||
 * For full usage instructions, please refer to the wiki:
 | 
			
		||||
 *  https://www.sensorwatch.net/docs/watchfaces/nanosec/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 | 
			
		||||
@ -22,33 +22,6 @@
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The goal of nanosec face is dramatic improvement of SensorWatch accuracy.
 | 
			
		||||
 * Minimum goal is <60 seconds of error per year. Full success is if we can reach <15 seconds per year (<0.47ppm error).
 | 
			
		||||
 *
 | 
			
		||||
 * It implements temperature correction using tempco from datasheet (and allows to adjust these)
 | 
			
		||||
 * and allows to introduce offset fix. Therefore requires temperature sensor board.
 | 
			
		||||
 *
 | 
			
		||||
 * Most users will need to apply profile 3 ("default") or 2("conservative datasheet"), and tune first parameter -
 | 
			
		||||
 * static offset (as it's different for every crystal sample).
 | 
			
		||||
 *
 | 
			
		||||
 * Frequency correction is dithered over 31 correction intervals (31x10 minutes or ~5 hours), to allow <0.1ppm correction resolution.
 | 
			
		||||
 * 1ppm is 0.0864 sec per day.
 | 
			
		||||
 * 0.1ppm is 0.00864 sec per day.
 | 
			
		||||
 *
 | 
			
		||||
 * To stay under 1ppm error you would need calibration of your specific instance of quartz crystal after some "burn-in" (ideally 1 year).
 | 
			
		||||
 *
 | 
			
		||||
 * Should improve TOTP experience.
 | 
			
		||||
 *
 | 
			
		||||
 * Default funing fork tempco: -0.034 ppm/°C², centered around 25°C
 | 
			
		||||
 * We add optional cubic coefficient, which was measured in practice on my sample.
 | 
			
		||||
 *
 | 
			
		||||
 * Cadence (CD) - how many minutes between corrections. Default 10 minutes.
 | 
			
		||||
 * Every minute might be too much. Every hour - slightly less power consumption but also less precision.
 | 
			
		||||
 *
 | 
			
		||||
 * Can compensate crystal aging (ppm/year) - but you really should be worrying about it on second/third years of watch calibration. *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,47 @@
 | 
			
		||||
#ifndef NANOSEC_FACE_H_
 | 
			
		||||
#define NANOSEC_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * NANOSEC face
 | 
			
		||||
 *
 | 
			
		||||
 * The goal of nanosec face is dramatic improvement of SensorWatch accuracy.
 | 
			
		||||
 * Minimum goal is <60 seconds of error per year. Full success is if we can
 | 
			
		||||
 * reach <15 seconds per year (<0.47ppm error).
 | 
			
		||||
 *
 | 
			
		||||
 * Best used in conjunction with the FINETUNE face.
 | 
			
		||||
 *
 | 
			
		||||
 * It implements temperature correction using tempco from datasheet (and
 | 
			
		||||
 * allows to adjust these) and allows to introduce offset fix. Therefore
 | 
			
		||||
 * requires temperature sensor board.
 | 
			
		||||
 *
 | 
			
		||||
 * Most users will need to apply profile 3 ("default") or 2 ("conservative
 | 
			
		||||
 * datasheet"), and tune first parameter "static offset" (as it's different
 | 
			
		||||
 * for every crystal sample).
 | 
			
		||||
 *
 | 
			
		||||
 * Frequency correction is dithered over 31 correction intervals (31x10
 | 
			
		||||
 * minutes or ~5 hours), to allow <0.1ppm correction resolution.
 | 
			
		||||
 *  * 1ppm is 0.0864 sec per day.
 | 
			
		||||
 *  * 0.1ppm is 0.00864 sec per day.
 | 
			
		||||
 *
 | 
			
		||||
 * To stay under 1ppm error you would need calibration of your specific
 | 
			
		||||
 * instance of quartz crystal after some "burn-in" (ideally 1 year).
 | 
			
		||||
 *
 | 
			
		||||
 * Should improve TOTP experience.
 | 
			
		||||
 *
 | 
			
		||||
 * Default funing fork tempco: -0.034 ppm/°C², centered around 25°C
 | 
			
		||||
 * We add optional cubic coefficient, which was measured in practice on my sample.
 | 
			
		||||
 *
 | 
			
		||||
 * Cadence (CD) - how many minutes between corrections. Default 10 minutes.
 | 
			
		||||
 * Every minute might be too much. Every hour - slightly less power
 | 
			
		||||
 * consumption but also less precision.
 | 
			
		||||
 *
 | 
			
		||||
 * Can compensate crystal aging (ppm/year) - but you really should be worrying
 | 
			
		||||
 * about it on second/third years of watch calibration.
 | 
			
		||||
 *
 | 
			
		||||
 * For full usage instructions, please refer to the wiki:
 | 
			
		||||
 *  https://www.sensorwatch.net/docs/watchfaces/nanosec/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
#define nanosec_profile_count 5
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,57 @@
 | 
			
		||||
#ifndef PREFERENCES_FACE_H_
 | 
			
		||||
#define PREFERENCES_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * PREFERENCES face
 | 
			
		||||
 *
 | 
			
		||||
 * The Preferences watch face allows you to configure various options on your
 | 
			
		||||
 * Sensor Watch. Like all other screens, you advance the field you’re setting
 | 
			
		||||
 * with the Light button, and advance its value with the Alarm button. The
 | 
			
		||||
 * Preferences watch face labels each setting with a two-letter code on the
 | 
			
		||||
 * top row; the following list describes each setting and their options:
 | 
			
		||||
 *
 | 
			
		||||
 *  CL - Clock mode.
 | 
			
		||||
 *      This setting allows you to select a 12-or 24-hour clock display. All
 | 
			
		||||
 *      watch faces that support displaying the time will respect this setting;
 | 
			
		||||
 *      for example, both Simple Clock, World Clock and Sunrise/Sunset will
 | 
			
		||||
 *      display the time in 24 hour format if the 24 hour clock is selected here.
 | 
			
		||||
 *
 | 
			
		||||
 *  BT - Button tone.
 | 
			
		||||
 *      This setting is only relevant if you installed the buzzer connector,
 | 
			
		||||
 *      and it toggles the beep when changing modes. If Y, the buzzer will
 | 
			
		||||
 *      sound a tone when Mode is pressed. Change to N to make the Mode
 | 
			
		||||
 *      button silent.
 | 
			
		||||
 *
 | 
			
		||||
 *  TO - Timeout.
 | 
			
		||||
 *      Sets the time until screens that time out (like Settings and Time Set)
 | 
			
		||||
 *      snap back to the first screen. 60 seconds is a good default for the
 | 
			
		||||
 *      stock firmware, but if you choose a custom firmware with faces that
 | 
			
		||||
 *      you’d like to keep on screen for longer, you can set that here.
 | 
			
		||||
 *
 | 
			
		||||
 *  LE - Low Energy mode.
 | 
			
		||||
 *      Sets the time until the watch enters its low energy sleep mode.
 | 
			
		||||
 *      Options range from 1 hour to 7 days, or Never. The more often Sensor
 | 
			
		||||
 *      Watch goes to sleep, the longer its battery will last — but you will
 | 
			
		||||
 *      lose the seconds indicator while it is asleep. This setting allows
 | 
			
		||||
 *      you to make a tradeoff between the device’s responsiveness and its
 | 
			
		||||
 *      longevity.
 | 
			
		||||
 *
 | 
			
		||||
 *  LT - Light.
 | 
			
		||||
 *      This setting has three screens.
 | 
			
		||||
 *      The first lets you choose how long the LED should stay lit when the
 | 
			
		||||
 *       LIGHT button is pressed. Options are 1 second, 3 seconds and 5
 | 
			
		||||
 *       seconds, or “No LED” to disable the LED entirely.
 | 
			
		||||
 *      The second screen, titled “blu” or “grn”, sets the intensity of the
 | 
			
		||||
 *       blue or green LED depending on the target Sensor Board hardware.
 | 
			
		||||
 *       Values range from 0 (off) to 15 (full intensity).
 | 
			
		||||
 *      The third screen, “red”, sets the intensity of the red LED, again
 | 
			
		||||
 *       from 0 to 15.
 | 
			
		||||
 *      On the last two screens, the LED remains on so that you can see the
 | 
			
		||||
 *      effect of mixing the two LED colors. On the Special Edition boards,
 | 
			
		||||
 *      you’ll have red, blue and a variety of shades of pink and purple to
 | 
			
		||||
 *      experiment with!
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
void preferences_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,23 @@
 | 
			
		||||
#ifndef SET_TIME_FACE_H_
 | 
			
		||||
#define SET_TIME_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * SET TIME face
 | 
			
		||||
 *
 | 
			
		||||
 * The default method for adjusting Sensor Watch time.
 | 
			
		||||
 *
 | 
			
		||||
 * The Time Set watch face allows you to set the time on Sensor Watch. Use
 | 
			
		||||
 * the LIGHT button to advance through the field you are setting, and the
 | 
			
		||||
 * ALARM button to change the value in that field. The fields are, in order:
 | 
			
		||||
 * Hour, Minute, Second, Year, Month, Day and Time Zone.
 | 
			
		||||
 *
 | 
			
		||||
 * For features like World Clock and Sunrise/Sunset to work correctly, you
 | 
			
		||||
 * must set the time to your local time, and the time zone to your local time
 | 
			
		||||
 * zone. This allows Sensor Watch to correctly offset the time. This also
 | 
			
		||||
 * means that when daylight savings time starts or ends, you must update
 | 
			
		||||
 * both the time and the time zone on this screen.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
void set_time_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
 | 
			
		||||
 | 
			
		||||
@ -21,21 +21,6 @@
 | 
			
		||||
 * 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.
 | 
			
		||||
 * 
 | 
			
		||||
 * 
 | 
			
		||||
 * 
 | 
			
		||||
 * This is an extended version of set_time face which allow setting seconds precisely.
 | 
			
		||||
 * To achieve that - press and hold alarm button few seconds before 00 and release exaclty as reference clock turns 00.
 | 
			
		||||
 * All settings can go up, or down (long alarm press).
 | 
			
		||||
 * 
 | 
			
		||||
 * The challenge is that SensorWatch display is delayed 0.5 seconds vs hardware RTC clock. It is caused by interrupts being generated by raising
 | 
			
		||||
 * edge of counter. It means there is no way to precisely trigger at 0.5s, as events at different frequencies slightly mismatch. 
 | 
			
		||||
 * This watch face achieves this approximately by triggering at 15th out of 32Hz events.
 | 
			
		||||
 * 
 | 
			
		||||
 * If you are <30 seconds when setting seconds - you will stay in the same minute. Otherwise - you will go to next minute. 
 | 
			
		||||
 * 
 | 
			
		||||
 * Note that changing anything will slightly delay subseconds counter. This is why this face sets seconds last 
 | 
			
		||||
 * to achiveve best precision. Still, best possible precision is achieved with finetune face. 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,29 @@
 | 
			
		||||
#ifndef SET_TIME_HACKWATCH_FACE_H_
 | 
			
		||||
#define SET_TIME_HACKWATCH_FACE_H_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * SET TIME HACKWATCH
 | 
			
		||||
 *
 | 
			
		||||
 * This is an extended version of set_time face which allow setting seconds
 | 
			
		||||
 * precisely. To achieve that - press and hold alarm button few seconds before
 | 
			
		||||
 * 00 and release exaclty as reference clock turns 00.
 | 
			
		||||
 *
 | 
			
		||||
 * All settings can go up, or down (long alarm press).
 | 
			
		||||
 * 
 | 
			
		||||
 * The challenge is that SensorWatch display is delayed 0.5 seconds vs hardware
 | 
			
		||||
 * RTC clock. It is caused by interrupts being generated by raising edge of
 | 
			
		||||
 * counter. It means there is no way to precisely trigger at 0.5s, as events
 | 
			
		||||
 * at different frequencies slightly mismatch. This watch face achieves this
 | 
			
		||||
 * approximately by triggering at 15th out of 32Hz events.
 | 
			
		||||
 * 
 | 
			
		||||
 * If you are <30 seconds when setting seconds - you will stay in the same
 | 
			
		||||
 * minute. Otherwise - you will go to next minute. 
 | 
			
		||||
 * 
 | 
			
		||||
 * Note that changing anything will slightly delay subseconds counter. This
 | 
			
		||||
 * is why this face sets seconds last to achiveve best precision. Still,
 | 
			
		||||
 * best possible precision is achieved with finetune face. 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "movement.h"
 | 
			
		||||
 | 
			
		||||
void set_time_hackwatch_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user