Merge branch 'main' of https://github.com/joeycastillo/Sensor-Watch into main
This commit is contained in:
commit
c5ecf1dabd
27
.github/workflows/build.yml
vendored
Normal file
27
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches-ignore:
|
||||||
|
- gh-pages
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
container:
|
||||||
|
image: ghcr.io/armmbed/mbed-os-env:latest
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Compile starter-project app
|
||||||
|
run: make
|
||||||
|
working-directory: 'apps/starter-project'
|
||||||
|
- name: Compile accelerometer-test app
|
||||||
|
run: make
|
||||||
|
working-directory: 'apps/accelerometer-test'
|
||||||
|
- name: Upload UF2
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: watch.uf2
|
||||||
|
path: apps/**/build/watch.uf2
|
21
.github/workflows/gh-pages.yml
vendored
Normal file
21
.github/workflows/gh-pages.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
name: GitHub Pages
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
gh-pages:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Doxygen Action
|
||||||
|
uses: mattnotmitt/doxygen-action@v1
|
||||||
|
- name: Deploy
|
||||||
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
publish_branch: gh-pages
|
||||||
|
publish_dir: docs/
|
16
.gitignore
vendored
16
.gitignore
vendored
@ -1,17 +1,19 @@
|
|||||||
.DS_Store
|
**/build/
|
||||||
*.s#*
|
|
||||||
*.b#*
|
*.b#*
|
||||||
*.pro
|
|
||||||
*.job
|
|
||||||
|
|
||||||
*.bin
|
*.bin
|
||||||
|
*.d
|
||||||
*.elf
|
*.elf
|
||||||
*.hex
|
*.hex
|
||||||
|
*.job
|
||||||
*.lss
|
*.lss
|
||||||
*.map
|
*.map
|
||||||
|
*.o
|
||||||
|
*.pro
|
||||||
|
*.s#*
|
||||||
*.uf2
|
*.uf2
|
||||||
*srec
|
*srec
|
||||||
*.o
|
.DS_Store
|
||||||
*.d
|
.idea/
|
||||||
.vs
|
.vs
|
||||||
.vscode
|
.vscode
|
||||||
|
docs/
|
2
Doxyfile
2
Doxyfile
@ -8,7 +8,7 @@ PROJECT_NAME = "Sensor Watch"
|
|||||||
PROJECT_NUMBER = "0.0.0"
|
PROJECT_NUMBER = "0.0.0"
|
||||||
PROJECT_BRIEF = "A board replacement for the classic Casio F-91W wristwatch, powered by a Microchip SAM L22 microcontroller."
|
PROJECT_BRIEF = "A board replacement for the classic Casio F-91W wristwatch, powered by a Microchip SAM L22 microcontroller."
|
||||||
PROJECT_LOGO =
|
PROJECT_LOGO =
|
||||||
OUTPUT_DIRECTORY = "../Sensor-Watch-Documentation"
|
OUTPUT_DIRECTORY = "."
|
||||||
CREATE_SUBDIRS = NO
|
CREATE_SUBDIRS = NO
|
||||||
ALLOW_UNICODE_NAMES = NO
|
ALLOW_UNICODE_NAMES = NO
|
||||||
OUTPUT_LANGUAGE = English
|
OUTPUT_LANGUAGE = English
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
TOP = ../../..
|
TOP = ../..
|
||||||
include $(TOP)/make.mk
|
include $(TOP)/make.mk
|
||||||
|
|
||||||
INCLUDES += \
|
INCLUDES += \
|
||||||
-I../
|
-I./
|
||||||
|
|
||||||
SRCS += \
|
SRCS += \
|
||||||
../app.c
|
./app.c
|
||||||
|
|
||||||
include $(TOP)/rules.mk
|
include $(TOP)/rules.mk
|
1
apps/accelerometer-test/make/.gitignore
vendored
1
apps/accelerometer-test/make/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
build/
|
|
1
apps/beats-time/make/.gitignore
vendored
1
apps/beats-time/make/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
build/
|
|
1
apps/buzzer-test/make/.gitignore
vendored
1
apps/buzzer-test/make/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
build/
|
|
1
apps/spi-test/make/.gitignore
vendored
1
apps/spi-test/make/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
build/
|
|
@ -1,26 +1,26 @@
|
|||||||
# Leave these lines at the top of the file.
|
# Leave these lines at the top of the file.
|
||||||
# TOP should get us to the root of the project...
|
# TOP should get us to the root of the project...
|
||||||
TOP = ../../..
|
TOP = ../..
|
||||||
# ...and make.mk has all the watch library sources and includes.
|
# ...and make.mk has all the watch library sources and includes.
|
||||||
include $(TOP)/make.mk
|
include $(TOP)/make.mk
|
||||||
|
|
||||||
# If you add any other subdirectories with header files you wish to include, add them after ../
|
# If you add any other subdirectories with header files you wish to include, add them after ./
|
||||||
# Note that you will need to add a backslash at the end of any line you wish to continue, i.e.
|
# Note that you will need to add a backslash at the end of any line you wish to continue, i.e.
|
||||||
# INCLUDES += \
|
# INCLUDES += \
|
||||||
# -I../ \
|
# -I./ \
|
||||||
# -I../drivers/ \
|
# -I drivers/ \
|
||||||
# -I../utils/
|
# -I utils/
|
||||||
INCLUDES += \
|
INCLUDES += \
|
||||||
-I../ \
|
-I./ \
|
||||||
|
|
||||||
# If you add any other source files you wish to compile, add them after ../app.c
|
# If you add any other source files you wish to compile, add them after app.c
|
||||||
# Note that you will need to add a backslash at the end of any line you wish to continue, i.e.
|
# Note that you will need to add a backslash at the end of any line you wish to continue, i.e.
|
||||||
# SRCS += \
|
# SRCS += \
|
||||||
# ../app.c \
|
# ./app.c \
|
||||||
# ../drivers/bmp280.c \
|
# ./drivers/bmp280.c \
|
||||||
# ../utils/temperature.c
|
# ./utils/temperature.c
|
||||||
SRCS += \
|
SRCS += \
|
||||||
../app.c \
|
./app.c \
|
||||||
|
|
||||||
# Leave this line at the bottom of the file; rules.mk has all the targets for making your project.
|
# Leave this line at the bottom of the file; rules.mk has all the targets for making your project.
|
||||||
include $(TOP)/rules.mk
|
include $(TOP)/rules.mk
|
1
apps/starter-project/make/.gitignore
vendored
1
apps/starter-project/make/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
build/
|
|
3
make.mk
3
make.mk
@ -20,7 +20,8 @@ else
|
|||||||
MKDIR = mkdir
|
MKDIR = mkdir
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS += -W -Wall --std=gnu99 -Os
|
CFLAGS += -W -Wall -Wextra -Wmissing-prototypes -Wmissing-declarations
|
||||||
|
CFLAGS += --std=gnu99 -Os
|
||||||
CFLAGS += -fno-diagnostics-show-caret
|
CFLAGS += -fno-diagnostics-show-caret
|
||||||
CFLAGS += -fdata-sections -ffunction-sections
|
CFLAGS += -fdata-sections -ffunction-sections
|
||||||
CFLAGS += -funsigned-char -funsigned-bitfields
|
CFLAGS += -funsigned-char -funsigned-bitfields
|
||||||
|
@ -91,7 +91,7 @@ typedef struct {
|
|||||||
Finally, we define the four required functions, and define the watch face struct that users will use to add the face to their watch:
|
Finally, we define the four required functions, and define the watch face struct that users will use to add the face to their watch:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void pulsometer_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void pulsometer_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void pulsometer_face_activate(movement_settings_t *settings, void *context);
|
void pulsometer_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool pulsometer_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool pulsometer_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void pulsometer_face_resign(movement_settings_t *settings, void *context);
|
void pulsometer_face_resign(movement_settings_t *settings, void *context);
|
||||||
@ -119,7 +119,7 @@ These define the tick frequency: when the pulsometer widget is updating the scre
|
|||||||
#### Watch Face Setup
|
#### Watch Face Setup
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void pulsometer_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void pulsometer_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(pulsometer_state_t));
|
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(pulsometer_state_t));
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ SRCS += \
|
|||||||
../watch_faces/demos/voltage_face.c \
|
../watch_faces/demos/voltage_face.c \
|
||||||
../watch_faces/demos/lis2dh_logging_face.c \
|
../watch_faces/demos/lis2dh_logging_face.c \
|
||||||
../watch_faces/demos/demo_face.c \
|
../watch_faces/demos/demo_face.c \
|
||||||
|
../watch_faces/demos/hello_there_face.c \
|
||||||
../watch_faces/complications/beats_face.c \
|
../watch_faces/complications/beats_face.c \
|
||||||
../watch_faces/complications/day_one_face.c \
|
../watch_faces/complications/day_one_face.c \
|
||||||
../watch_faces/complications/stopwatch_face.c \
|
../watch_faces/complications/stopwatch_face.c \
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
movement_state_t movement_state;
|
movement_state_t movement_state;
|
||||||
void * watch_face_contexts[MOVEMENT_NUM_FACES];
|
void * watch_face_contexts[MOVEMENT_NUM_FACES];
|
||||||
|
watch_date_time scheduled_tasks[MOVEMENT_NUM_FACES];
|
||||||
const int32_t movement_le_inactivity_deadlines[8] = {INT_MAX, 3600, 7200, 21600, 43200, 86400, 172800, 604800};
|
const int32_t movement_le_inactivity_deadlines[8] = {INT_MAX, 3600, 7200, 21600, 43200, 86400, 172800, 604800};
|
||||||
const int16_t movement_timeout_inactivity_deadlines[4] = {60, 120, 300, 1800};
|
const int16_t movement_timeout_inactivity_deadlines[4] = {60, 120, 300, 1800};
|
||||||
movement_event_t event;
|
movement_event_t event;
|
||||||
@ -99,6 +100,29 @@ static void _movement_handle_background_tasks(void) {
|
|||||||
movement_state.needs_background_tasks_handled = false;
|
movement_state.needs_background_tasks_handled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _movement_handle_scheduled_tasks(void) {
|
||||||
|
watch_date_time date_time = watch_rtc_get_date_time();
|
||||||
|
uint8_t num_active_tasks = 0;
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) {
|
||||||
|
if (scheduled_tasks[i].reg) {
|
||||||
|
if (scheduled_tasks[i].reg == date_time.reg) {
|
||||||
|
scheduled_tasks[i].reg = 0;
|
||||||
|
movement_event_t background_event = { EVENT_BACKGROUND_TASK, 0 };
|
||||||
|
watch_faces[i].loop(background_event, &movement_state.settings, watch_face_contexts[i]);
|
||||||
|
} else {
|
||||||
|
num_active_tasks++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_active_tasks == 0) {
|
||||||
|
movement_state.has_scheduled_background_task = false;
|
||||||
|
} else {
|
||||||
|
_movement_reset_inactivity_countdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void movement_request_tick_frequency(uint8_t freq) {
|
void movement_request_tick_frequency(uint8_t freq) {
|
||||||
if (freq == 128) return; // Movement uses the 128 Hz tick internally
|
if (freq == 128) return; // Movement uses the 128 Hz tick internally
|
||||||
RTC->MODE2.INTENCLR.reg = 0xFE; // disable all callbacks except the 128 Hz one
|
RTC->MODE2.INTENCLR.reg = 0xFE; // disable all callbacks except the 128 Hz one
|
||||||
@ -125,6 +149,14 @@ void movement_move_to_next_face(void) {
|
|||||||
movement_move_to_face((movement_state.current_watch_face + 1) % MOVEMENT_NUM_FACES);
|
movement_move_to_face((movement_state.current_watch_face + 1) % MOVEMENT_NUM_FACES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void movement_schedule_background_task(watch_date_time date_time) {
|
||||||
|
watch_date_time now = watch_rtc_get_date_time();
|
||||||
|
if (date_time.reg > now.reg) {
|
||||||
|
movement_state.has_scheduled_background_task = true;
|
||||||
|
scheduled_tasks[movement_state.current_watch_face].reg = date_time.reg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void movement_play_signal(void) {
|
void movement_play_signal(void) {
|
||||||
watch_buzzer_play_note(BUZZER_NOTE_C8, 75);
|
watch_buzzer_play_note(BUZZER_NOTE_C8, 75);
|
||||||
watch_buzzer_play_note(BUZZER_NOTE_REST, 100);
|
watch_buzzer_play_note(BUZZER_NOTE_REST, 100);
|
||||||
@ -161,6 +193,7 @@ void app_setup(void) {
|
|||||||
if (is_first_launch) {
|
if (is_first_launch) {
|
||||||
for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) {
|
for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) {
|
||||||
watch_face_contexts[i] = NULL;
|
watch_face_contexts[i] = NULL;
|
||||||
|
scheduled_tasks[i].reg = 0;
|
||||||
is_first_launch = false;
|
is_first_launch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +218,7 @@ void app_setup(void) {
|
|||||||
movement_request_tick_frequency(1);
|
movement_request_tick_frequency(1);
|
||||||
|
|
||||||
for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) {
|
for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) {
|
||||||
watch_faces[i].setup(&movement_state.settings, &watch_face_contexts[i]);
|
watch_faces[i].setup(&movement_state.settings, i, &watch_face_contexts[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
watch_faces[movement_state.current_watch_face].activate(&movement_state.settings, watch_face_contexts[movement_state.current_watch_face]);
|
watch_faces[movement_state.current_watch_face].activate(&movement_state.settings, watch_face_contexts[movement_state.current_watch_face]);
|
||||||
@ -230,6 +263,9 @@ bool app_loop(void) {
|
|||||||
// handle background tasks, if the alarm handler told us we need to
|
// handle background tasks, if the alarm handler told us we need to
|
||||||
if (movement_state.needs_background_tasks_handled) _movement_handle_background_tasks();
|
if (movement_state.needs_background_tasks_handled) _movement_handle_background_tasks();
|
||||||
|
|
||||||
|
// if we have a scheduled background task, handle that here:
|
||||||
|
if (event.event_type == EVENT_TICK && movement_state.has_scheduled_background_task) _movement_handle_scheduled_tasks();
|
||||||
|
|
||||||
// if we have timed out of our low energy mode countdown, enter low energy mode.
|
// if we have timed out of our low energy mode countdown, enter low energy mode.
|
||||||
if (movement_state.le_mode_ticks == 0) {
|
if (movement_state.le_mode_ticks == 0) {
|
||||||
movement_state.le_mode_ticks = -1;
|
movement_state.le_mode_ticks = -1;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define MOVEMENT_H_
|
#define MOVEMENT_H_
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "watch.h"
|
||||||
|
|
||||||
// Movement Preferences
|
// Movement Preferences
|
||||||
// These four 32-bit structs store information about the wearer and their preferences. Tentatively, the plan is
|
// These four 32-bit structs store information about the wearer and their preferences. Tentatively, the plan is
|
||||||
@ -113,13 +114,16 @@ extern const char movement_valid_position_1_chars[];
|
|||||||
* @param settings A pointer to the global Movement settings. You can use this to inform how you present your
|
* @param settings A pointer to the global Movement settings. You can use this to inform how you present your
|
||||||
* display to the user (i.e. taking into account whether they have silenced the buttons, or if
|
* display to the user (i.e. taking into account whether they have silenced the buttons, or if
|
||||||
* they prefer 12 or 24-hour mode). You can also change these settings if you like.
|
* they prefer 12 or 24-hour mode). You can also change these settings if you like.
|
||||||
|
* @param watch_face_index The index of this watch face in the global array of watch faces; 0 is the first face,
|
||||||
|
* 1 is the second, etc. You may stash this value in your context if you wish to reference
|
||||||
|
* it later; your watch face's index is set at launch and will not change.
|
||||||
* @param context_ptr A pointer to a pointer; at first invocation, this value will be NULL, and you can set it
|
* @param context_ptr A pointer to a pointer; at first invocation, this value will be NULL, and you can set it
|
||||||
* to any value you like. Subsequent invocations will pass in whatever value you previously
|
* to any value you like. Subsequent invocations will pass in whatever value you previously
|
||||||
* set. You may want to check if this is NULL and if so, allocate some space to store any
|
* set. You may want to check if this is NULL and if so, allocate some space to store any
|
||||||
* data required for your watch face.
|
* data required for your watch face.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef void (*watch_face_setup)(movement_settings_t *settings, void ** context_ptr);
|
typedef void (*watch_face_setup)(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
|
|
||||||
/** @brief Prepare to go on-screen.
|
/** @brief Prepare to go on-screen.
|
||||||
* @details This function is called just before your watch enters the foreground. If your watch face has any
|
* @details This function is called just before your watch enters the foreground. If your watch face has any
|
||||||
@ -228,6 +232,7 @@ typedef struct {
|
|||||||
|
|
||||||
// background task handling
|
// background task handling
|
||||||
bool needs_background_tasks_handled;
|
bool needs_background_tasks_handled;
|
||||||
|
bool has_scheduled_background_task;
|
||||||
|
|
||||||
// low energy mode countdown
|
// low energy mode countdown
|
||||||
int32_t le_mode_ticks;
|
int32_t le_mode_ticks;
|
||||||
@ -244,8 +249,15 @@ typedef struct {
|
|||||||
void movement_move_to_face(uint8_t watch_face_index);
|
void movement_move_to_face(uint8_t watch_face_index);
|
||||||
void movement_move_to_next_face(void);
|
void movement_move_to_next_face(void);
|
||||||
void movement_illuminate_led(void);
|
void movement_illuminate_led(void);
|
||||||
|
|
||||||
|
// note: requesting a tick frequency of 0 will break any scheduled background tasks.
|
||||||
|
// this will be fixed in a future refactor of the tick mechanism.
|
||||||
void movement_request_tick_frequency(uint8_t freq);
|
void movement_request_tick_frequency(uint8_t freq);
|
||||||
|
|
||||||
|
// note: watch faces can only schedule a background task when in the foreground, since
|
||||||
|
// movement will associate the scheduled task with the currently active face.
|
||||||
|
void movement_schedule_background_task(watch_date_time date_time);
|
||||||
|
|
||||||
void movement_play_signal(void);
|
void movement_play_signal(void);
|
||||||
void movement_play_alarm(void);
|
void movement_play_alarm(void);
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "totp_face.h"
|
#include "totp_face.h"
|
||||||
#include "lis2dh_logging_face.h"
|
#include "lis2dh_logging_face.h"
|
||||||
#include "demo_face.h"
|
#include "demo_face.h"
|
||||||
|
#include "hello_there_face.h"
|
||||||
|
|
||||||
const watch_face_t watch_faces[] = {
|
const watch_face_t watch_faces[] = {
|
||||||
simple_clock_face,
|
simple_clock_face,
|
||||||
|
@ -3,23 +3,34 @@
|
|||||||
#include "watch.h"
|
#include "watch.h"
|
||||||
#include "watch_utility.h"
|
#include "watch_utility.h"
|
||||||
|
|
||||||
void simple_clock_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void simple_clock_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
// the only context we need is the timestamp of the previous tick.
|
(void) watch_face_index;
|
||||||
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(uint32_t));
|
|
||||||
|
if (*context_ptr == NULL) {
|
||||||
|
*context_ptr = malloc(sizeof(simple_clock_state_t));
|
||||||
|
simple_clock_state_t *state = (simple_clock_state_t *)*context_ptr;
|
||||||
|
state->signal_enabled = false;
|
||||||
|
state->watch_face_index = watch_face_index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void simple_clock_face_activate(movement_settings_t *settings, void *context) {
|
void simple_clock_face_activate(movement_settings_t *settings, void *context) {
|
||||||
|
simple_clock_state_t *state = (simple_clock_state_t *)context;
|
||||||
|
|
||||||
if (watch_tick_animation_is_running()) watch_stop_tick_animation();
|
if (watch_tick_animation_is_running()) watch_stop_tick_animation();
|
||||||
|
|
||||||
if (settings->bit.clock_mode_24h) watch_set_indicator(WATCH_INDICATOR_24H);
|
if (settings->bit.clock_mode_24h) watch_set_indicator(WATCH_INDICATOR_24H);
|
||||||
|
if (state->signal_enabled) watch_set_indicator(WATCH_INDICATOR_SIGNAL);
|
||||||
|
|
||||||
watch_set_colon();
|
watch_set_colon();
|
||||||
|
|
||||||
// this ensures that none of the timestamp fields will match, so we can re-render them all.
|
// this ensures that none of the timestamp fields will match, so we can re-render them all.
|
||||||
*((uint32_t *)context) = 0xFFFFFFFF;
|
state->previous_date_time = 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool simple_clock_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
bool simple_clock_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
||||||
|
simple_clock_state_t *state = (simple_clock_state_t *)context;
|
||||||
char buf[11];
|
char buf[11];
|
||||||
uint8_t pos;
|
uint8_t pos;
|
||||||
|
|
||||||
@ -30,8 +41,8 @@ bool simple_clock_face_loop(movement_event_t event, movement_settings_t *setting
|
|||||||
case EVENT_TICK:
|
case EVENT_TICK:
|
||||||
case EVENT_LOW_ENERGY_UPDATE:
|
case EVENT_LOW_ENERGY_UPDATE:
|
||||||
date_time = watch_rtc_get_date_time();
|
date_time = watch_rtc_get_date_time();
|
||||||
previous_date_time = *((uint32_t *)context);
|
previous_date_time = state->previous_date_time;
|
||||||
*((uint32_t *)context) = date_time.reg;
|
state->previous_date_time = date_time.reg;
|
||||||
|
|
||||||
if (date_time.reg >> 6 == previous_date_time >> 6 && event.event_type != EVENT_LOW_ENERGY_UPDATE) {
|
if (date_time.reg >> 6 == previous_date_time >> 6 && event.event_type != EVENT_LOW_ENERGY_UPDATE) {
|
||||||
// everything before seconds is the same, don't waste cycles setting those segments.
|
// everything before seconds is the same, don't waste cycles setting those segments.
|
||||||
@ -69,7 +80,25 @@ bool simple_clock_face_loop(movement_event_t event, movement_settings_t *setting
|
|||||||
case EVENT_LIGHT_BUTTON_DOWN:
|
case EVENT_LIGHT_BUTTON_DOWN:
|
||||||
movement_illuminate_led();
|
movement_illuminate_led();
|
||||||
break;
|
break;
|
||||||
case EVENT_ALARM_BUTTON_UP:
|
case EVENT_ALARM_LONG_PRESS:
|
||||||
|
state->signal_enabled = !state->signal_enabled;
|
||||||
|
if (state->signal_enabled) watch_set_indicator(WATCH_INDICATOR_SIGNAL);
|
||||||
|
else watch_clear_indicator(WATCH_INDICATOR_SIGNAL);
|
||||||
|
break;
|
||||||
|
case EVENT_BACKGROUND_TASK:
|
||||||
|
// uncomment this line to snap back to the clock face when the hour signal sounds:
|
||||||
|
// movement_move_to_face(state->watch_face_index);
|
||||||
|
if (watch_is_buzzer_or_led_enabled()) {
|
||||||
|
// if we are in the foreground, we can just beep.
|
||||||
|
movement_play_signal();
|
||||||
|
} else {
|
||||||
|
// if we were in the background, we need to enable the buzzer peripheral first,
|
||||||
|
watch_enable_buzzer();
|
||||||
|
// beep quickly (this call blocks for 275 ms),
|
||||||
|
movement_play_signal();
|
||||||
|
// and then turn the buzzer peripheral off again.
|
||||||
|
watch_disable_buzzer();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -82,3 +111,13 @@ void simple_clock_face_resign(movement_settings_t *settings, void *context) {
|
|||||||
(void) settings;
|
(void) settings;
|
||||||
(void) context;
|
(void) context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool simple_clock_face_wants_background_task(movement_settings_t *settings, void *context) {
|
||||||
|
(void) settings;
|
||||||
|
simple_clock_state_t *state = (simple_clock_state_t *)context;
|
||||||
|
if (!state->signal_enabled) return false;
|
||||||
|
|
||||||
|
watch_date_time date_time = watch_rtc_get_date_time();
|
||||||
|
|
||||||
|
return date_time.unit.minute == 59;
|
||||||
|
}
|
||||||
|
@ -3,19 +3,24 @@
|
|||||||
|
|
||||||
#include "movement.h"
|
#include "movement.h"
|
||||||
|
|
||||||
void simple_clock_face_setup(movement_settings_t *settings, void ** context_ptr);
|
typedef struct {
|
||||||
|
uint32_t previous_date_time;
|
||||||
|
uint8_t watch_face_index;
|
||||||
|
bool signal_enabled;
|
||||||
|
} simple_clock_state_t;
|
||||||
|
|
||||||
|
void simple_clock_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void simple_clock_face_activate(movement_settings_t *settings, void *context);
|
void simple_clock_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool simple_clock_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool simple_clock_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void simple_clock_face_resign(movement_settings_t *settings, void *context);
|
void simple_clock_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
bool simple_clock_face_wants_background_task(movement_settings_t *settings, void *context);
|
||||||
uint8_t simple_clock_face_get_weekday(uint16_t day, uint16_t month, uint16_t year);
|
|
||||||
|
|
||||||
static const watch_face_t simple_clock_face = {
|
static const watch_face_t simple_clock_face = {
|
||||||
simple_clock_face_setup,
|
simple_clock_face_setup,
|
||||||
simple_clock_face_activate,
|
simple_clock_face_activate,
|
||||||
simple_clock_face_loop,
|
simple_clock_face_loop,
|
||||||
simple_clock_face_resign,
|
simple_clock_face_resign,
|
||||||
NULL
|
simple_clock_face_wants_background_task
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SIMPLE_CLOCK_FACE_H_
|
#endif // SIMPLE_CLOCK_FACE_H_
|
||||||
|
@ -4,8 +4,9 @@
|
|||||||
#include "watch.h"
|
#include "watch.h"
|
||||||
#include "watch_utility.h"
|
#include "watch_utility.h"
|
||||||
|
|
||||||
void world_clock_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void world_clock_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
if (*context_ptr == NULL) {
|
if (*context_ptr == NULL) {
|
||||||
*context_ptr = malloc(sizeof(world_clock_state_t));
|
*context_ptr = malloc(sizeof(world_clock_state_t));
|
||||||
world_clock_state_t *state = (world_clock_state_t *)*context_ptr;
|
world_clock_state_t *state = (world_clock_state_t *)*context_ptr;
|
||||||
|
@ -15,7 +15,7 @@ typedef struct {
|
|||||||
uint32_t previous_date_time;
|
uint32_t previous_date_time;
|
||||||
} world_clock_state_t;
|
} world_clock_state_t;
|
||||||
|
|
||||||
void world_clock_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void world_clock_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void world_clock_face_activate(movement_settings_t *settings, void *context);
|
void world_clock_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool world_clock_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool world_clock_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void world_clock_face_resign(movement_settings_t *settings, void *context);
|
void world_clock_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
@ -5,8 +5,9 @@
|
|||||||
|
|
||||||
const uint8_t BEAT_REFRESH_FREQUENCY = 8;
|
const uint8_t BEAT_REFRESH_FREQUENCY = 8;
|
||||||
|
|
||||||
void beats_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void beats_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
(void) context_ptr;
|
(void) context_ptr;
|
||||||
if (*context_ptr == NULL) {
|
if (*context_ptr == NULL) {
|
||||||
*context_ptr = malloc(sizeof(beats_face_state_t));
|
*context_ptr = malloc(sizeof(beats_face_state_t));
|
||||||
|
@ -9,7 +9,7 @@ typedef struct {
|
|||||||
} beats_face_state_t;
|
} beats_face_state_t;
|
||||||
|
|
||||||
uint32_t clock2beats(uint32_t hours, uint32_t minutes, uint32_t seconds, uint32_t subseconds, int16_t utc_offset);
|
uint32_t clock2beats(uint32_t hours, uint32_t minutes, uint32_t seconds, uint32_t subseconds, int16_t utc_offset);
|
||||||
void beats_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void beats_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void beats_face_activate(movement_settings_t *settings, void *context);
|
void beats_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool beats_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool beats_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void beats_face_resign(movement_settings_t *settings, void *context);
|
void beats_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
@ -17,8 +17,9 @@ static void _day_one_face_update(day_one_state_t state) {
|
|||||||
watch_display_string(buf, 0);
|
watch_display_string(buf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void day_one_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void day_one_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
if (*context_ptr == NULL) {
|
if (*context_ptr == NULL) {
|
||||||
*context_ptr = malloc(sizeof(day_one_state_t));
|
*context_ptr = malloc(sizeof(day_one_state_t));
|
||||||
memset(*context_ptr, 0, sizeof(day_one_state_t));
|
memset(*context_ptr, 0, sizeof(day_one_state_t));
|
||||||
|
@ -15,7 +15,7 @@ typedef struct {
|
|||||||
bool birthday_changed;
|
bool birthday_changed;
|
||||||
} day_one_state_t;
|
} day_one_state_t;
|
||||||
|
|
||||||
void day_one_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void day_one_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void day_one_face_activate(movement_settings_t *settings, void *context);
|
void day_one_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool day_one_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool day_one_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void day_one_face_resign(movement_settings_t *settings, void *context);
|
void day_one_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
#define PULSOMETER_FACE_FREQUENCY_FACTOR (4ul) // refresh rate will be 2 to this power Hz (0 for 1 Hz, 2 for 4 Hz, etc.)
|
#define PULSOMETER_FACE_FREQUENCY_FACTOR (4ul) // refresh rate will be 2 to this power Hz (0 for 1 Hz, 2 for 4 Hz, etc.)
|
||||||
#define PULSOMETER_FACE_FREQUENCY (1 << PULSOMETER_FACE_FREQUENCY_FACTOR)
|
#define PULSOMETER_FACE_FREQUENCY (1 << PULSOMETER_FACE_FREQUENCY_FACTOR)
|
||||||
|
|
||||||
void pulsometer_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void pulsometer_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(pulsometer_state_t));
|
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(pulsometer_state_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ typedef struct {
|
|||||||
int16_t ticks;
|
int16_t ticks;
|
||||||
} pulsometer_state_t;
|
} pulsometer_state_t;
|
||||||
|
|
||||||
void pulsometer_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void pulsometer_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void pulsometer_face_activate(movement_settings_t *settings, void *context);
|
void pulsometer_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool pulsometer_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool pulsometer_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void pulsometer_face_resign(movement_settings_t *settings, void *context);
|
void pulsometer_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
@ -3,8 +3,9 @@
|
|||||||
#include "stopwatch_face.h"
|
#include "stopwatch_face.h"
|
||||||
#include "watch.h"
|
#include "watch.h"
|
||||||
|
|
||||||
void stopwatch_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void stopwatch_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(stopwatch_state_t));
|
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(stopwatch_state_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ typedef struct {
|
|||||||
uint8_t hours;
|
uint8_t hours;
|
||||||
} stopwatch_state_t;
|
} stopwatch_state_t;
|
||||||
|
|
||||||
void stopwatch_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void stopwatch_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void stopwatch_face_activate(movement_settings_t *settings, void *context);
|
void stopwatch_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool stopwatch_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool stopwatch_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void stopwatch_face_resign(movement_settings_t *settings, void *context);
|
void stopwatch_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
@ -17,8 +17,9 @@ static uint8_t hmacKey[] = {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21, 0xde, 0xad, 0xbe
|
|||||||
|
|
||||||
static const uint32_t TIMESTEP = 30;
|
static const uint32_t TIMESTEP = 30;
|
||||||
|
|
||||||
void totp_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void totp_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(totp_state_t));
|
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(totp_state_t));
|
||||||
TOTP(hmacKey, sizeof(hmacKey), TIMESTEP);
|
TOTP(hmacKey, sizeof(hmacKey), TIMESTEP);
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ typedef struct {
|
|||||||
|
|
||||||
} totp_state_t;
|
} totp_state_t;
|
||||||
|
|
||||||
void totp_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void totp_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void totp_face_activate(movement_settings_t *settings, void *context);
|
void totp_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool totp_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool totp_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void totp_face_resign(movement_settings_t *settings, void *context);
|
void totp_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
@ -3,8 +3,9 @@
|
|||||||
#include "character_set_face.h"
|
#include "character_set_face.h"
|
||||||
#include "watch.h"
|
#include "watch.h"
|
||||||
|
|
||||||
void character_set_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void character_set_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(char));
|
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(char));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "movement.h"
|
#include "movement.h"
|
||||||
|
|
||||||
void character_set_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void character_set_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void character_set_face_activate(movement_settings_t *settings, void *context);
|
void character_set_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool character_set_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool character_set_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void character_set_face_resign(movement_settings_t *settings, void *context);
|
void character_set_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
@ -14,8 +14,9 @@ typedef enum {
|
|||||||
DEMO_FACE_NUM_FACES
|
DEMO_FACE_NUM_FACES
|
||||||
} demo_face_index_t;
|
} demo_face_index_t;
|
||||||
|
|
||||||
void demo_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void demo_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
if (*context_ptr == NULL) {
|
if (*context_ptr == NULL) {
|
||||||
*context_ptr = malloc(sizeof(demo_face_index_t));
|
*context_ptr = malloc(sizeof(demo_face_index_t));
|
||||||
memset(*context_ptr, 0, sizeof(demo_face_index_t));
|
memset(*context_ptr, 0, sizeof(demo_face_index_t));
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "movement.h"
|
#include "movement.h"
|
||||||
|
|
||||||
void demo_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void demo_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void demo_face_activate(movement_settings_t *settings, void *context);
|
void demo_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool demo_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool demo_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void demo_face_resign(movement_settings_t *settings, void *context);
|
void demo_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
88
movement/watch_faces/demos/hello_there_face.c
Normal file
88
movement/watch_faces/demos/hello_there_face.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "hello_there_face.h"
|
||||||
|
#include "watch.h"
|
||||||
|
|
||||||
|
void hello_there_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
|
// These next two lines just silence the compiler warnings associated with unused parameters.
|
||||||
|
// We have no use for the settings or the watch_face_index, so we make that explicit here.
|
||||||
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
|
// At boot, context_ptr will be NULL indicating that we don't have anyplace to store our context.
|
||||||
|
if (*context_ptr == NULL) {
|
||||||
|
// in this case, we allocate an area of memory sufficient to store the stuff we need to track.
|
||||||
|
*context_ptr = malloc(sizeof(hello_there_state_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hello_there_face_activate(movement_settings_t *settings, void *context) {
|
||||||
|
// same as above: silence the warning, we don't need to check the settings.
|
||||||
|
(void) settings;
|
||||||
|
// we do however need to set some things in our context. Here we cast it to the correct type...
|
||||||
|
hello_there_state_t *state = (hello_there_state_t *)context;
|
||||||
|
// ...and set the initial state of our watch face. We start out displaying the word 'Hello',
|
||||||
|
state->current_word = 0;
|
||||||
|
// and animate by default.
|
||||||
|
state->animating = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hello_there_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
||||||
|
(void) settings;
|
||||||
|
hello_there_state_t *state = (hello_there_state_t *)context;
|
||||||
|
|
||||||
|
switch (event.event_type) {
|
||||||
|
case EVENT_ACTIVATE:
|
||||||
|
case EVENT_TICK:
|
||||||
|
// on activate and tick, if we are animating,
|
||||||
|
if (state->animating) {
|
||||||
|
// we display the current word,
|
||||||
|
if (state->current_word == 0) watch_display_string("Hello ", 4);
|
||||||
|
else watch_display_string(" there", 4);
|
||||||
|
// and increment it so that it will update on the next tick.
|
||||||
|
state->current_word = (state->current_word + 1) % 2;
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
movement_illuminate_led();
|
||||||
|
break;
|
||||||
|
case EVENT_MODE_BUTTON_UP:
|
||||||
|
// when the user presses 'mode', we tell movement to move to the next watch face.
|
||||||
|
// movement will call our resign function, clear the screen, and transfer control
|
||||||
|
// to the next watch face in the list.
|
||||||
|
movement_move_to_next_face();
|
||||||
|
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.
|
||||||
|
state->animating = !state->animating;
|
||||||
|
break;
|
||||||
|
case EVENT_LOW_ENERGY_UPDATE:
|
||||||
|
// This low energy mode update occurs once a minute, if the watch face is in the
|
||||||
|
// foreground when Movement enters low energy mode. We have the option of supporting
|
||||||
|
// this mode, but since our watch face animates once a second, the "Hello there" face
|
||||||
|
// isn't very useful in this mode. So we choose not to support it. (continued below)
|
||||||
|
break;
|
||||||
|
case EVENT_TIMEOUT:
|
||||||
|
// ... Instead, we respond to the timeout event. This event happens after a configurable
|
||||||
|
// interval on screen (1-30 minutes). The watch will give us this event as a chance to
|
||||||
|
// resign control if we want to, and in this case, we do.
|
||||||
|
// This function will return the watch to the first screen (usually a simple clock),
|
||||||
|
// and it will do it long before the watch enters low energy mode. This ensures we
|
||||||
|
// won't be on screen, and thus opts us out of getting the EVENT_LOW_ENERGY_UPDATE above.
|
||||||
|
movement_move_to_face(0);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hello_there_face_resign(movement_settings_t *settings, void *context) {
|
||||||
|
// our watch face, like most watch faces, has nothing special to do when resigning.
|
||||||
|
// watch faces that enable a peripheral or interact with a sensor may want to turn it off here.
|
||||||
|
(void) settings;
|
||||||
|
(void) context;
|
||||||
|
}
|
24
movement/watch_faces/demos/hello_there_face.h
Normal file
24
movement/watch_faces/demos/hello_there_face.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef HELLO_THERE_FACE_H_
|
||||||
|
#define HELLO_THERE_FACE_H_
|
||||||
|
|
||||||
|
#include "movement.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t current_word;
|
||||||
|
bool animating;
|
||||||
|
} hello_there_state_t;
|
||||||
|
|
||||||
|
void hello_there_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
|
void hello_there_face_activate(movement_settings_t *settings, void *context);
|
||||||
|
bool hello_there_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
|
void hello_there_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
|
||||||
|
static const watch_face_t hello_there_face = {
|
||||||
|
hello_there_face_setup,
|
||||||
|
hello_there_face_activate,
|
||||||
|
hello_there_face_loop,
|
||||||
|
hello_there_face_resign,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HELLO_THERE_FACE_H_
|
@ -86,8 +86,9 @@ static void _lis2dh_logging_face_log_data(lis2dh_logger_state_t *logger_state) {
|
|||||||
logger_state->z_interrupts_this_hour = 0;
|
logger_state->z_interrupts_this_hour = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lis2dh_logging_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void lis2dh_logging_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
if (*context_ptr == NULL) {
|
if (*context_ptr == NULL) {
|
||||||
*context_ptr = malloc(sizeof(lis2dh_logger_state_t));
|
*context_ptr = malloc(sizeof(lis2dh_logger_state_t));
|
||||||
memset(*context_ptr, 0, sizeof(lis2dh_logger_state_t));
|
memset(*context_ptr, 0, sizeof(lis2dh_logger_state_t));
|
||||||
|
@ -25,7 +25,7 @@ typedef struct {
|
|||||||
lis2dh_logger_data_point_t data[LIS2DH_LOGGING_NUM_DATA_POINTS];
|
lis2dh_logger_data_point_t data[LIS2DH_LOGGING_NUM_DATA_POINTS];
|
||||||
} lis2dh_logger_state_t;
|
} lis2dh_logger_state_t;
|
||||||
|
|
||||||
void lis2dh_logging_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void lis2dh_logging_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void lis2dh_logging_face_activate(movement_settings_t *settings, void *context);
|
void lis2dh_logging_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool lis2dh_logging_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool lis2dh_logging_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void lis2dh_logging_face_resign(movement_settings_t *settings, void *context);
|
void lis2dh_logging_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
@ -11,8 +11,9 @@ static void _voltage_face_update_display(void) {
|
|||||||
watch_display_string(buf, 0);
|
watch_display_string(buf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void voltage_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void voltage_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
(void) context_ptr;
|
(void) context_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "movement.h"
|
#include "movement.h"
|
||||||
|
|
||||||
void voltage_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void voltage_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void voltage_face_activate(movement_settings_t *settings, void *context);
|
void voltage_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool voltage_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool voltage_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void voltage_face_resign(movement_settings_t *settings, void *context);
|
void voltage_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
@ -17,8 +17,9 @@ const char preferences_face_titles[PREFERENCES_FACE_NUM_PREFEFENCES][11] = {
|
|||||||
"LT red ", // Light: red component
|
"LT red ", // Light: red component
|
||||||
};
|
};
|
||||||
|
|
||||||
void preferences_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void preferences_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(uint8_t));
|
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(uint8_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "movement.h"
|
#include "movement.h"
|
||||||
|
|
||||||
void preferences_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void preferences_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void preferences_face_activate(movement_settings_t *settings, void *context);
|
void preferences_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool preferences_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool preferences_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void preferences_face_resign(movement_settings_t *settings, void *context);
|
void preferences_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
@ -5,8 +5,9 @@
|
|||||||
#define SET_TIME_FACE_NUM_SETTINGS (7)
|
#define SET_TIME_FACE_NUM_SETTINGS (7)
|
||||||
const char set_time_face_titles[SET_TIME_FACE_NUM_SETTINGS][3] = {"HR", "M1", "SE", "YR", "MO", "DA", "ZO"};
|
const char set_time_face_titles[SET_TIME_FACE_NUM_SETTINGS][3] = {"HR", "M1", "SE", "YR", "MO", "DA", "ZO"};
|
||||||
|
|
||||||
void set_time_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void set_time_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(uint8_t));
|
if (*context_ptr == NULL) *context_ptr = malloc(sizeof(uint8_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "movement.h"
|
#include "movement.h"
|
||||||
|
|
||||||
void set_time_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void set_time_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void set_time_face_activate(movement_settings_t *settings, void *context);
|
void set_time_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool set_time_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool set_time_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void set_time_face_resign(movement_settings_t *settings, void *context);
|
void set_time_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
@ -48,8 +48,9 @@ static void _thermistor_logging_face_update_display(thermistor_logger_state_t *l
|
|||||||
watch_display_string(buf, 0);
|
watch_display_string(buf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void thermistor_logging_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void thermistor_logging_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
if (*context_ptr == NULL) {
|
if (*context_ptr == NULL) {
|
||||||
*context_ptr = malloc(sizeof(thermistor_logger_state_t));
|
*context_ptr = malloc(sizeof(thermistor_logger_state_t));
|
||||||
memset(*context_ptr, 0, sizeof(thermistor_logger_state_t));
|
memset(*context_ptr, 0, sizeof(thermistor_logger_state_t));
|
||||||
|
@ -18,7 +18,7 @@ typedef struct {
|
|||||||
thermistor_logger_data_point_t data[THERMISTOR_LOGGING_NUM_DATA_POINTS];
|
thermistor_logger_data_point_t data[THERMISTOR_LOGGING_NUM_DATA_POINTS];
|
||||||
} thermistor_logger_state_t;
|
} thermistor_logger_state_t;
|
||||||
|
|
||||||
void thermistor_logging_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void thermistor_logging_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void thermistor_logging_face_activate(movement_settings_t *settings, void *context);
|
void thermistor_logging_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool thermistor_logging_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool thermistor_logging_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void thermistor_logging_face_resign(movement_settings_t *settings, void *context);
|
void thermistor_logging_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
@ -17,8 +17,9 @@ static void _thermistor_readout_face_update_display(bool in_fahrenheit) {
|
|||||||
thermistor_driver_disable();
|
thermistor_driver_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void thermistor_readout_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
void thermistor_readout_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
|
(void) watch_face_index;
|
||||||
(void) context_ptr;
|
(void) context_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "movement.h"
|
#include "movement.h"
|
||||||
|
|
||||||
void thermistor_readout_face_setup(movement_settings_t *settings, void ** context_ptr);
|
void thermistor_readout_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||||
void thermistor_readout_face_activate(movement_settings_t *settings, void *context);
|
void thermistor_readout_face_activate(movement_settings_t *settings, void *context);
|
||||||
bool thermistor_readout_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
bool thermistor_readout_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
void thermistor_readout_face_resign(movement_settings_t *settings, void *context);
|
void thermistor_readout_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
@ -38,3 +38,7 @@ void SYSTEM_Handler(void) {
|
|||||||
bool watch_is_battery_low(void) {
|
bool watch_is_battery_low(void) {
|
||||||
return battery_is_low;
|
return battery_is_low;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool watch_is_buzzer_or_led_enabled(void){
|
||||||
|
return hri_mclk_get_APBCMASK_TCC0_bit(MCLK);
|
||||||
|
}
|
||||||
|
@ -73,4 +73,11 @@
|
|||||||
*/
|
*/
|
||||||
bool watch_is_battery_low(void);
|
bool watch_is_battery_low(void);
|
||||||
|
|
||||||
|
/** @brief Returns true if either the buzzer or the LED driver is enabled.
|
||||||
|
* @details Both the buzzer and the LED use the TCC peripheral to drive their behavior. This function returns true if that
|
||||||
|
* peripheral is enabled. You can use this function to determine whether you need to call the watch_disable_leds or
|
||||||
|
* or watch_enable_buzzer functions before using these peripherals.
|
||||||
|
*/
|
||||||
|
bool watch_is_buzzer_or_led_enabled(void);
|
||||||
|
|
||||||
#endif /* WATCH_H_ */
|
#endif /* WATCH_H_ */
|
Loading…
x
Reference in New Issue
Block a user