Merge remote-tracking branch 'origin/main' into manual_dst_toggle
* origin/main: (119 commits) add an openocd.cfg for openocd 0.12.0 Fix compile errors and warnings in movement.c and shell.c faces/totp: avoid displaying when key is invalid faces/totp: fix error message not displayed bug faces/totp: remove dynamic memory allocation faces/totp: improve memory usage faces: restore simple_clock_face uf2conv: argument to `re.split` should be a rawstring movement: fix unintended timeout short circuiting movement: convert can_sleep an automatic variable faces/pulsometer: remember pulsometer measurement faces/pulsometer: remember pulsometer calibration faces/totp: update copyrights faces/totp: allow moving backwards through codes faces/clock: add 24h only feature faces/clock: update copyrights and credits faces/totp: delete leading underscores faces/totp: rename initializer macro to credential faces/totp: improve TOTP initializer labeling faces/totp: decode secrets when setting up ...
This commit is contained in:
@@ -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>
|
||||
@@ -272,7 +245,6 @@ static void value_increase(int16_t delta) {
|
||||
nanosec_state.correction_cadence = (delta > 0) ? 1 : 20;
|
||||
break;
|
||||
}
|
||||
nanosec_state.correction_profile = (nanosec_state.correction_profile + delta) % nanosec_profile_count;
|
||||
break;
|
||||
case 6: // Aging
|
||||
nanosec_state.aging_ppm_pa += delta;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -136,22 +136,22 @@ bool preferences_face_loop(movement_event_t event, movement_settings_t *settings
|
||||
watch_display_string(" Never", 4);
|
||||
break;
|
||||
case 1:
|
||||
watch_display_string("1 hour", 4);
|
||||
watch_display_string("10n&in", 4);
|
||||
break;
|
||||
case 2:
|
||||
watch_display_string("2 hour", 4);
|
||||
watch_display_string("1 hour", 4);
|
||||
break;
|
||||
case 3:
|
||||
watch_display_string("6 hour", 4);
|
||||
watch_display_string("2 hour", 4);
|
||||
break;
|
||||
case 4:
|
||||
watch_display_string("12 hr", 4);
|
||||
watch_display_string("6 hour", 4);
|
||||
break;
|
||||
case 5:
|
||||
watch_display_string(" 1 day", 4);
|
||||
watch_display_string("12 hr", 4);
|
||||
break;
|
||||
case 6:
|
||||
watch_display_string(" 2 day", 4);
|
||||
watch_display_string(" 1 day", 4);
|
||||
break;
|
||||
case 7:
|
||||
watch_display_string(" 7 day", 4);
|
||||
|
||||
@@ -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);
|
||||
|
||||
152
movement/watch_faces/settings/save_load_face.c
Normal file
152
movement/watch_faces/settings/save_load_face.c
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Wesley Aptekar-Cassels
|
||||
*
|
||||
* 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 "save_load_face.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
static void save(save_load_state_t *state) {
|
||||
savefile_t savefile = {
|
||||
1,
|
||||
watch_get_backup_data(0),
|
||||
watch_get_backup_data(1),
|
||||
watch_get_backup_data(2),
|
||||
watch_get_backup_data(3),
|
||||
watch_get_backup_data(4),
|
||||
watch_get_backup_data(5),
|
||||
watch_get_backup_data(6),
|
||||
watch_get_backup_data(7),
|
||||
watch_rtc_get_date_time(),
|
||||
};
|
||||
state->slot[state->index] = savefile;
|
||||
char filename[23];
|
||||
sprintf(filename, "save_load_face_%d.bin", state->index);
|
||||
filesystem_write_file(filename, (char*)&savefile, sizeof(savefile_t));
|
||||
}
|
||||
|
||||
static void load(save_load_state_t *state, movement_settings_t *settings) {
|
||||
watch_store_backup_data(state->slot[state->index].b0, 0);
|
||||
settings->reg = state->slot[state->index].b0;
|
||||
watch_store_backup_data(state->slot[state->index].b1, 1);
|
||||
watch_store_backup_data(state->slot[state->index].b2, 2);
|
||||
watch_store_backup_data(state->slot[state->index].b3, 3);
|
||||
watch_store_backup_data(state->slot[state->index].b4, 4);
|
||||
watch_store_backup_data(state->slot[state->index].b5, 5);
|
||||
watch_store_backup_data(state->slot[state->index].b6, 6);
|
||||
watch_store_backup_data(state->slot[state->index].b7, 7);
|
||||
}
|
||||
|
||||
static void load_saves_to_state(save_load_state_t *state) {
|
||||
for (uint8_t i = 0; i < SAVE_LOAD_SLOTS; i++) {
|
||||
char filename[23];
|
||||
sprintf(filename, "save_load_face_%d.bin", i);
|
||||
if (filesystem_get_file_size(filename) != sizeof(savefile_t)) {
|
||||
state->slot[i].version = 0;
|
||||
continue;
|
||||
}
|
||||
filesystem_read_file(filename, (char*)&state->slot[i], sizeof(savefile_t));
|
||||
if (state->slot[i].version != 1) {
|
||||
state->slot[i].version = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void save_load_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||
(void) settings;
|
||||
(void) watch_face_index;
|
||||
if (*context_ptr == NULL) {
|
||||
*context_ptr = malloc(sizeof(save_load_state_t));
|
||||
memset(*context_ptr, 0, sizeof(save_load_state_t));
|
||||
}
|
||||
}
|
||||
|
||||
void save_load_face_activate(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
save_load_state_t *state = (save_load_state_t *)context;
|
||||
state->index = 0;
|
||||
state->update_timeout = 0;
|
||||
load_saves_to_state(state);
|
||||
}
|
||||
|
||||
static void update_display(save_load_state_t *state) {
|
||||
char buf[11];
|
||||
sprintf(buf, "SL %1d", state->index);
|
||||
watch_display_string(buf, 0);
|
||||
|
||||
if (state->slot[state->index].version) {
|
||||
sprintf(buf, "%02d%02d%02d", state->slot[state->index].rtc.unit.year + 20, state->slot[state->index].rtc.unit.month, state->slot[state->index].rtc.unit.day);
|
||||
watch_display_string(buf, 4);
|
||||
} else {
|
||||
watch_display_string("no dat", 4);
|
||||
}
|
||||
}
|
||||
|
||||
bool save_load_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
||||
save_load_state_t *state = (save_load_state_t *)context;
|
||||
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
update_display(state);
|
||||
break;
|
||||
case EVENT_TICK:
|
||||
if (state->update_timeout) {
|
||||
if (!--state->update_timeout) {
|
||||
update_display(state);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EVENT_ALARM_BUTTON_UP:
|
||||
state->index = (state->index + 1) % SAVE_LOAD_SLOTS;
|
||||
update_display(state);
|
||||
break;
|
||||
case EVENT_LIGHT_LONG_PRESS:
|
||||
save(state);
|
||||
watch_display_string("Saved ", 4);
|
||||
state->update_timeout = 3;
|
||||
break;
|
||||
case EVENT_ALARM_LONG_PRESS:
|
||||
if (state->slot[state->index].version) {
|
||||
load(state, settings);
|
||||
watch_display_string("Loaded", 4);
|
||||
state->update_timeout = 3;
|
||||
}
|
||||
break;
|
||||
case EVENT_TIMEOUT:
|
||||
movement_move_to_face(0);
|
||||
break;
|
||||
default:
|
||||
return movement_default_loop_handler(event, settings);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void save_load_face_resign(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
(void) context;
|
||||
|
||||
// handle any cleanup before your watch face goes off-screen.
|
||||
}
|
||||
|
||||
82
movement/watch_faces/settings/save_load_face.h
Normal file
82
movement/watch_faces/settings/save_load_face.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Wesley Aptekar-Cassels
|
||||
*
|
||||
* 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 SAVE_LOAD_FACE_H_
|
||||
#define SAVE_LOAD_FACE_H_
|
||||
|
||||
#include "movement.h"
|
||||
#include "watch_rtc.h"
|
||||
|
||||
/*
|
||||
* Save/Load face
|
||||
*
|
||||
* This allows you to save your settings (including location, birthday, etc) to
|
||||
* LFS, which is not wiped when firmware is updated, and then load them again.
|
||||
* It provides multiple save slots (four by default).
|
||||
*
|
||||
* Press ALARM to cycle through save slots. Long press LIGHT to save to the
|
||||
* current slot. Long press ALARM to load from the current slot. The date that
|
||||
* a save was taken is shown in YYMMDD format , or "no dat" if the slot is
|
||||
* empty. The index of the current slot is displayed in the upper right corner.
|
||||
*
|
||||
* While the time that a save was taken is recorded, it is not currently
|
||||
* restored.
|
||||
*/
|
||||
|
||||
typedef struct savefile {
|
||||
uint8_t version;
|
||||
uint32_t b0;
|
||||
uint32_t b1;
|
||||
uint32_t b2;
|
||||
uint32_t b3;
|
||||
uint32_t b4;
|
||||
uint32_t b5;
|
||||
uint32_t b6;
|
||||
uint32_t b7;
|
||||
watch_date_time rtc;
|
||||
} savefile_t;
|
||||
|
||||
#define SAVE_LOAD_SLOTS 4
|
||||
|
||||
typedef struct {
|
||||
uint8_t index;
|
||||
uint8_t update_timeout;
|
||||
savefile_t slot[SAVE_LOAD_SLOTS];
|
||||
} save_load_state_t;
|
||||
|
||||
void save_load_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||
void save_load_face_activate(movement_settings_t *settings, void *context);
|
||||
bool save_load_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||
void save_load_face_resign(movement_settings_t *settings, void *context);
|
||||
|
||||
#define save_load_face ((const watch_face_t){ \
|
||||
save_load_face_setup, \
|
||||
save_load_face_activate, \
|
||||
save_load_face_loop, \
|
||||
save_load_face_resign, \
|
||||
NULL, \
|
||||
})
|
||||
|
||||
#endif // SAVE_LOAD_FACE_H_
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user