'movement' -> 'legacy' to signal things we still need to bring in

This commit is contained in:
Joey Castillo
2024-11-27 10:56:50 -05:00
parent bc08c5a05e
commit 9719567047
221 changed files with 6 additions and 6 deletions

View File

@@ -0,0 +1,246 @@
/*
* MIT License
*
* Copyright (c) 2024 Wesley
*
* 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 "beeps_face.h"
void beeps_face_setup(uint8_t watch_face_index, void ** context_ptr) {
(void) watch_face_index;
if (*context_ptr == NULL) {
*context_ptr = malloc(sizeof(beeps_state_t));
memset(*context_ptr, 0, sizeof(beeps_state_t));
// Do any one-time tasks in here; the inside of this conditional happens only at boot.
}
}
void beeps_face_activate(void *context) {
(void) context;
}
static void _beep_face_update_lcd(beeps_state_t *state) {
char buf[11];
const char buzzernote[][7] = {" 5500", " 5827", " 6174"," 6541"," 6930"," 7342"," 7778"," 8241"," 8731"," 9250"," 9800"," 10383"," 11000"," 11654"," 12347"," 13081"," 13859"," 14683"," 15556"," 16481"," 17461"," 18500"," 19600"," 20765"," 22000"," 23308"," 24694"," 26163"," 27718"," 29366"," 31113"," 32963"," 34923"," 36999"," 39200"," 41530"," 44000"," 46616"," 49388"," 52325"," 55437"," 58733"," 62225"," 65925"," 69846"," 73999"," 78399"," 83061"," 88000"," 93233"," 98777"," 104650"," 110873"," 117466"," 124451"," 131851"," 139691"," 147998"," 156798"," 166122"," 176000"," 186466"," 197553"," 209300"," 221746"," 234932"," 248902"," 263702"," 279383"," 295996"," 313596"," 332244"," 352000"," 372931"," 395107"," 418601"," 443492"," 469863"," 497803"," 527404"," 558765"," 591991"," 627193"," 664488"," 704000"," 745862"," 790213"};
sprintf(buf, "HZ %s", buzzernote[state->frequency]);
watch_display_string(buf, 0);
}
bool beeps_face_loop(movement_event_t event, void *context) {
beeps_state_t *state = (beeps_state_t *)context;
switch (event.event_type) {
case EVENT_ACTIVATE:
_beep_face_update_lcd(state);
break;
case EVENT_LIGHT_BUTTON_DOWN:
state->frequency = (state->frequency + 1) % 87;
_beep_face_update_lcd(state);
break;
case EVENT_ALARM_BUTTON_DOWN:
if (state->frequency == 0) {
watch_buzzer_play_note(BUZZER_NOTE_A1, 500);
} else if (state->frequency == 1) {
watch_buzzer_play_note(BUZZER_NOTE_A1SHARP_B1FLAT, 500);
} else if (state->frequency == 2) {
watch_buzzer_play_note(BUZZER_NOTE_B1, 500);
} else if (state->frequency == 3) {
watch_buzzer_play_note(BUZZER_NOTE_C2, 500);
} else if (state->frequency == 4) {
watch_buzzer_play_note(BUZZER_NOTE_C2SHARP_D2FLAT, 500);
} else if (state->frequency == 5) {
watch_buzzer_play_note(BUZZER_NOTE_D2, 500);
} else if (state->frequency == 6) {
watch_buzzer_play_note(BUZZER_NOTE_D2SHARP_E2FLAT, 500);
} else if (state->frequency == 7) {
watch_buzzer_play_note(BUZZER_NOTE_E2, 500);
} else if (state->frequency == 8) {
watch_buzzer_play_note(BUZZER_NOTE_F2, 500);
} else if (state->frequency == 9) {
watch_buzzer_play_note(BUZZER_NOTE_F2SHARP_G2FLAT, 500);
} else if (state->frequency == 10) {
watch_buzzer_play_note(BUZZER_NOTE_G2, 500);
} else if (state->frequency == 11) {
watch_buzzer_play_note(BUZZER_NOTE_G2SHARP_A2FLAT, 500);
} else if (state->frequency == 12) {
watch_buzzer_play_note(BUZZER_NOTE_A2, 500);
} else if (state->frequency == 13) {
watch_buzzer_play_note(BUZZER_NOTE_A2SHARP_B2FLAT, 500);
} else if (state->frequency == 14) {
watch_buzzer_play_note(BUZZER_NOTE_B2, 500);
} else if (state->frequency == 15) {
watch_buzzer_play_note(BUZZER_NOTE_C3, 500);
} else if (state->frequency == 16) {
watch_buzzer_play_note(BUZZER_NOTE_C3SHARP_D3FLAT, 500);
} else if (state->frequency == 17) {
watch_buzzer_play_note(BUZZER_NOTE_D3, 500);
} else if (state->frequency == 18) {
watch_buzzer_play_note(BUZZER_NOTE_D3SHARP_E3FLAT, 500);
} else if (state->frequency == 19) {
watch_buzzer_play_note(BUZZER_NOTE_E3, 500);
} else if (state->frequency == 20) {
watch_buzzer_play_note(BUZZER_NOTE_F3, 500);
} else if (state->frequency == 21) {
watch_buzzer_play_note(BUZZER_NOTE_F3SHARP_G3FLAT, 500);
} else if (state->frequency == 22) {
watch_buzzer_play_note(BUZZER_NOTE_G3, 500);
} else if (state->frequency == 23) {
watch_buzzer_play_note(BUZZER_NOTE_G3SHARP_A3FLAT, 500);
} else if (state->frequency == 24) {
watch_buzzer_play_note(BUZZER_NOTE_A3, 500);
} else if (state->frequency == 25) {
watch_buzzer_play_note(BUZZER_NOTE_A3SHARP_B3FLAT, 500);
} else if (state->frequency == 26) {
watch_buzzer_play_note(BUZZER_NOTE_B3, 500);
} else if (state->frequency == 27) {
watch_buzzer_play_note(BUZZER_NOTE_C4, 500);
} else if (state->frequency == 28) {
watch_buzzer_play_note(BUZZER_NOTE_C4SHARP_D4FLAT, 500);
} else if (state->frequency == 29) {
watch_buzzer_play_note(BUZZER_NOTE_D4, 500);
} else if (state->frequency == 30) {
watch_buzzer_play_note(BUZZER_NOTE_D4SHARP_E4FLAT, 500);
} else if (state->frequency == 31) {
watch_buzzer_play_note(BUZZER_NOTE_E4, 500);
} else if (state->frequency == 32) {
watch_buzzer_play_note(BUZZER_NOTE_F4, 500);
} else if (state->frequency == 33) {
watch_buzzer_play_note(BUZZER_NOTE_F4SHARP_G4FLAT, 500);
} else if (state->frequency == 34) {
watch_buzzer_play_note(BUZZER_NOTE_G4, 500);
} else if (state->frequency == 35) {
watch_buzzer_play_note(BUZZER_NOTE_G4SHARP_A4FLAT, 500);
} else if (state->frequency == 36) {
watch_buzzer_play_note(BUZZER_NOTE_A4, 500);
} else if (state->frequency == 37) {
watch_buzzer_play_note(BUZZER_NOTE_A4SHARP_B4FLAT, 500);
} else if (state->frequency == 38) {
watch_buzzer_play_note(BUZZER_NOTE_B4, 500);
} else if (state->frequency == 39) {
watch_buzzer_play_note(BUZZER_NOTE_C5, 500);
} else if (state->frequency == 40) {
watch_buzzer_play_note(BUZZER_NOTE_C5SHARP_D5FLAT, 500);
} else if (state->frequency == 41) {
watch_buzzer_play_note(BUZZER_NOTE_D5, 500);
} else if (state->frequency == 42) {
watch_buzzer_play_note(BUZZER_NOTE_D5SHARP_E5FLAT, 500);
} else if (state->frequency == 43) {
watch_buzzer_play_note(BUZZER_NOTE_E5, 500);
} else if (state->frequency == 44) {
watch_buzzer_play_note(BUZZER_NOTE_F5, 500);
} else if (state->frequency == 45) {
watch_buzzer_play_note(BUZZER_NOTE_F5SHARP_G5FLAT, 500);
} else if (state->frequency == 46) {
watch_buzzer_play_note(BUZZER_NOTE_G5, 500);
} else if (state->frequency == 47) {
watch_buzzer_play_note(BUZZER_NOTE_G5SHARP_A5FLAT, 500);
} else if (state->frequency == 48) {
watch_buzzer_play_note(BUZZER_NOTE_A5, 500);
} else if (state->frequency == 49) {
watch_buzzer_play_note(BUZZER_NOTE_A5SHARP_B5FLAT, 500);
} else if (state->frequency == 50) {
watch_buzzer_play_note(BUZZER_NOTE_B5, 500);
} else if (state->frequency == 51) {
watch_buzzer_play_note(BUZZER_NOTE_C6, 500);
} else if (state->frequency == 52) {
watch_buzzer_play_note(BUZZER_NOTE_C6SHARP_D6FLAT, 500);
} else if (state->frequency == 53) {
watch_buzzer_play_note(BUZZER_NOTE_D6, 500);
} else if (state->frequency == 54) {
watch_buzzer_play_note(BUZZER_NOTE_D6SHARP_E6FLAT, 500);
} else if (state->frequency == 55) {
watch_buzzer_play_note(BUZZER_NOTE_E6, 500);
} else if (state->frequency == 56) {
watch_buzzer_play_note(BUZZER_NOTE_F6, 500);
} else if (state->frequency == 57) {
watch_buzzer_play_note(BUZZER_NOTE_F6SHARP_G6FLAT, 500);
} else if (state->frequency == 58) {
watch_buzzer_play_note(BUZZER_NOTE_G6, 500);
} else if (state->frequency == 59) {
watch_buzzer_play_note(BUZZER_NOTE_G6SHARP_A6FLAT, 500);
} else if (state->frequency == 60) {
watch_buzzer_play_note(BUZZER_NOTE_A6, 500);
} else if (state->frequency == 61) {
watch_buzzer_play_note(BUZZER_NOTE_A6SHARP_B6FLAT, 500);
} else if (state->frequency == 62) {
watch_buzzer_play_note(BUZZER_NOTE_B6, 500);
} else if (state->frequency == 63) {
watch_buzzer_play_note(BUZZER_NOTE_C7, 500);
} else if (state->frequency == 64) {
watch_buzzer_play_note(BUZZER_NOTE_C7SHARP_D7FLAT, 500);
} else if (state->frequency == 65) {
watch_buzzer_play_note(BUZZER_NOTE_D7, 500);
} else if (state->frequency == 66) {
watch_buzzer_play_note(BUZZER_NOTE_D7SHARP_E7FLAT, 500);
} else if (state->frequency == 67) {
watch_buzzer_play_note(BUZZER_NOTE_E7, 500);
} else if (state->frequency == 68) {
watch_buzzer_play_note(BUZZER_NOTE_F7, 500);
} else if (state->frequency == 69) {
watch_buzzer_play_note(BUZZER_NOTE_F7SHARP_G7FLAT, 500);
} else if (state->frequency == 70) {
watch_buzzer_play_note(BUZZER_NOTE_G7, 500);
} else if (state->frequency == 71) {
watch_buzzer_play_note(BUZZER_NOTE_G7SHARP_A7FLAT, 500);
} else if (state->frequency == 72) {
watch_buzzer_play_note(BUZZER_NOTE_A7, 500);
} else if (state->frequency == 73) {
watch_buzzer_play_note(BUZZER_NOTE_A7SHARP_B7FLAT, 500);
} else if (state->frequency == 74) {
watch_buzzer_play_note(BUZZER_NOTE_B7, 500);
} else if (state->frequency == 75) {
watch_buzzer_play_note(BUZZER_NOTE_C8, 500);
} else if (state->frequency == 76) {
watch_buzzer_play_note(BUZZER_NOTE_C8SHARP_D8FLAT, 500);
} else if (state->frequency == 77) {
watch_buzzer_play_note(BUZZER_NOTE_D8, 500);
} else if (state->frequency == 78) {
watch_buzzer_play_note(BUZZER_NOTE_D8SHARP_E8FLAT, 500);
} else if (state->frequency == 79) {
watch_buzzer_play_note(BUZZER_NOTE_E8, 500);
} else if (state->frequency == 80) {
watch_buzzer_play_note(BUZZER_NOTE_F8, 500);
} else if (state->frequency == 81) {
watch_buzzer_play_note(BUZZER_NOTE_F8SHARP_G8FLAT, 500);
} else if (state->frequency == 82) {
watch_buzzer_play_note(BUZZER_NOTE_G8, 500);
} else if (state->frequency == 83) {
watch_buzzer_play_note(BUZZER_NOTE_G8SHARP_A8FLAT, 500);
} else if (state->frequency == 84) {
watch_buzzer_play_note(BUZZER_NOTE_A8, 500);
} else if (state->frequency == 85) {
watch_buzzer_play_note(BUZZER_NOTE_A8SHARP_B8FLAT, 500);
} else if (state->frequency == 86) {
watch_buzzer_play_note(BUZZER_NOTE_B8, 500);
}
break;
default:
return movement_default_loop_handler(event);
}
return true;
}
void beeps_face_resign(void *context) {
(void) context;
}

View File

@@ -0,0 +1,61 @@
/*
* MIT License
*
* Copyright (c) 2024 Wesley
*
* 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 BEEPS_FACE_H_
#define BEEPS_FACE_H_
#include "movement.h"
/*
* A simple watch face to test the different Buzzer Notes.
*
* Press the Light button to play a sound.
* Press the Alarm button to change the frequency.
*
* The watch face displays the frequency of the buzzer it will play
* this allows you to reference the watch_buzzer.h file to find the
* corresponding note.
*
* The watch_buzzer.h file is found at watch-library/shared/watch/watch_buzzer.h
*/
typedef struct {
uint8_t frequency;
} beeps_state_t;
void beeps_face_setup(uint8_t watch_face_index, void ** context_ptr);
void beeps_face_activate(void *context);
bool beeps_face_loop(movement_event_t event, void *context);
void beeps_face_resign(void *context);
#define beeps_face ((const watch_face_t){ \
beeps_face_setup, \
beeps_face_activate, \
beeps_face_loop, \
beeps_face_resign, \
NULL, \
})
#endif // BEEPS_FACE_H_

View File

@@ -0,0 +1,132 @@
/*
* MIT License
*
* Copyright (c) 2022 Joey Castillo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include "demo_face.h"
#include "watch.h"
typedef enum {
DEMO_FACE_TIME = 0,
DEMO_FACE_WORLD_TIME,
DEMO_FACE_BEATS,
DEMO_FACE_TOTP,
DEMO_FACE_TEMP_F,
DEMO_FACE_TEMP_C,
DEMO_FACE_TEMP_LOG_1,
DEMO_FACE_TEMP_LOG_2,
DEMO_FACE_DAY_ONE,
DEMO_FACE_STOPWATCH,
DEMO_FACE_PULSOMETER,
DEMO_FACE_BATTERY_VOLTAGE,
DEMO_FACE_NUM_FACES
} demo_face_index_t;
void demo_face_setup(uint8_t watch_face_index, void ** context_ptr) {
(void) watch_face_index;
if (*context_ptr == NULL) {
*context_ptr = malloc(sizeof(demo_face_index_t));
memset(*context_ptr, 0, sizeof(demo_face_index_t));
}
}
void demo_face_activate(void *context) {
(void) context;
movement_request_tick_frequency(0);
// ensure the watch never enters low energy mode
movement_set_low_energy_timeout(0);
movement_set_backlight_dwell(3);
}
bool demo_face_loop(movement_event_t event, void *context) {
demo_face_index_t *screen = (demo_face_index_t *)context;
switch (event.event_type) {
case EVENT_ALARM_BUTTON_UP:
*screen = ((*screen) + 1) % DEMO_FACE_NUM_FACES;
// fall through
case EVENT_ACTIVATE:
switch (*screen) {
case DEMO_FACE_TIME:
watch_display_string("TH10101036", 0);
watch_set_colon();
break;
case DEMO_FACE_WORLD_TIME:
watch_display_string("UT10 21036", 0);
watch_set_indicator(WATCH_INDICATOR_PM);
break;
case DEMO_FACE_BEATS:
watch_display_string("bt 64125", 0);
watch_clear_indicator(WATCH_INDICATOR_PM);
watch_clear_colon();
break;
case DEMO_FACE_TOTP:
watch_display_string("2F29808494", 0);
break;
case DEMO_FACE_TEMP_F:
watch_display_string("TE 72.1#F", 0);
break;
case DEMO_FACE_TEMP_C:
watch_display_string("TE 22.3#C", 0);
break;
case DEMO_FACE_TEMP_LOG_1:
watch_display_string("TL 43.6#F", 0);
break;
case DEMO_FACE_TEMP_LOG_2:
watch_display_string("AT 6100000", 0);
watch_set_colon();
break;
case DEMO_FACE_DAY_ONE:
watch_clear_colon();
watch_display_string("DA 12879", 0);
break;
case DEMO_FACE_STOPWATCH:
watch_display_string("ST 01042 ", 0);
watch_set_colon();
break;
case DEMO_FACE_PULSOMETER:
watch_display_string(" 68 bpn", 0);
watch_clear_colon();
break;
case DEMO_FACE_BATTERY_VOLTAGE:
watch_display_string("BA 2.97 V", 0);
break;
case DEMO_FACE_NUM_FACES:
// we won't get here, but silence the warning
break;
}
break;
case EVENT_TIMEOUT:
// ignore timeout
break;
default:
movement_default_loop_handler(event);
break;
}
return true;
}
void demo_face_resign(void *context) {
(void) context;
}

View File

@@ -0,0 +1,54 @@
/*
* MIT License
*
* Copyright (c) 2022 Joey Castillo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef 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(uint8_t watch_face_index, void ** context_ptr);
void demo_face_activate(void *context);
bool demo_face_loop(movement_event_t event, void *context);
void demo_face_resign(void *context);
#define demo_face ((const watch_face_t){ \
demo_face_setup, \
demo_face_activate, \
demo_face_loop, \
demo_face_resign, \
NULL, \
})
#endif // DEMO_FACE_H_

View File

@@ -0,0 +1,158 @@
/*
* MIT License
*
* Copyright (c) 2022 <#author_name#>
*
* 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 "frequency_correction_face.h"
// NOTE: since this face deals directly with the SAM L22's SUPC and RTC registers,
// it won't build for the simulator or really do anything. so let's not.
#ifndef __EMSCRIPTEN__
// Waveform output. Comes out on pin A1 of the 9-pin connector. Output is enabled
// when the watch face is activated and disabled when deactivated.
// * The RTC's PEREOn enables an event at a frequency of 1024/(2^(n+3)), allowing
// event generation from 128 Hz to 1 Hz.
// * The SUPC's RTCTGL causes the selected output to toggle on an RTC event.
// Putting it together, PEREO0 generates a 64 Hz square wave on A1, PEREO1 a 32 Hz
// wave, on and on to an 0.5 Hz square wave for PEREO7.
static void _enable_output(uint8_t period_event_output) {
SUPC->BKOUT.bit.EN = 1;
SUPC->BKOUT.bit.RTCTGL = 1;
RTC->MODE2.CTRLA.bit.ENABLE = 0;
while (RTC->MODE2.SYNCBUSY.bit.ENABLE);
RTC->MODE2.EVCTRL.reg = RTC_MODE2_EVCTRL_PEREO(1 << period_event_output);
RTC->MODE2.CTRLA.bit.ENABLE = 1;
while (RTC->MODE2.SYNCBUSY.bit.ENABLE);
}
// The display: "FC" for "Frequency Correction" in the title slot; at the top right,
// the periodic event output that's enabled:: 0 for PEREO0, 1 for PEREO1, etc.
// The main line displays the frequency correction value from -127 to 127.
// Controls: A short press on the Light button increases FREQCORR by 1 and a short
// press on the Alarm button decreases FREQCORR by 1. A long press on ALARM cycles
// through the available output frequencies.
static void _update_display(uint8_t period_event_output) {
char buf[14];
sprintf(buf, "FC%2d%6d", period_event_output, (int8_t)RTC->MODE2.FREQCORR.reg);
watch_display_string(buf, 0);
}
static void _disable_output() {
SUPC->BKOUT.bit.EN = 0;
SUPC->BKOUT.bit.RTCTGL = 0;
RTC->MODE2.CTRLA.bit.ENABLE = 0;
while (RTC->MODE2.SYNCBUSY.bit.ENABLE);
RTC->MODE2.EVCTRL.reg = RTC_MODE2_EVCTRL_PEREO(0);
RTC->MODE2.CTRLA.bit.ENABLE = 1;
while (RTC->MODE2.SYNCBUSY.bit.ENABLE);
}
void frequency_correction_face_setup(uint8_t watch_face_index, void ** context_ptr) {
(void) watch_face_index;
if (*context_ptr == NULL) {
*context_ptr = malloc(sizeof(frequency_correction_state_t));
frequency_correction_state_t *state = (frequency_correction_state_t *)*context_ptr;
state->period_event_output = 0;
}
}
void frequency_correction_face_activate(void *context) {
frequency_correction_state_t *state = (frequency_correction_state_t *)context;
_enable_output(state->period_event_output);
}
bool frequency_correction_face_loop(movement_event_t event, void *context) {
frequency_correction_state_t *state = (frequency_correction_state_t *)context;
int8_t freqcorr;
switch (event.event_type) {
case EVENT_ACTIVATE:
_update_display(state->period_event_output);
break;
case EVENT_TICK:
break;
case EVENT_LIGHT_BUTTON_DOWN:
freqcorr = RTC->MODE2.FREQCORR.reg;
if (freqcorr < 127) {
RTC->MODE2.FREQCORR.reg++;
while(RTC->MODE2.SYNCBUSY.reg);
}
_update_display(state->period_event_output);
break;
case EVENT_ALARM_BUTTON_UP:
freqcorr = RTC->MODE2.FREQCORR.reg;
if (freqcorr > -127) {
RTC->MODE2.FREQCORR.reg--;
while(RTC->MODE2.SYNCBUSY.reg);
}
_update_display(state->period_event_output);
break;
case EVENT_ALARM_LONG_PRESS:
state->period_event_output = (state->period_event_output + 1) % 8;
_update_display(state->period_event_output);
_enable_output(state->period_event_output);
break;
case EVENT_TIMEOUT:
break;
case EVENT_LOW_ENERGY_UPDATE:
watch_start_sleep_animation(500);
break;
default:
movement_default_loop_handler(event);
break;
}
return true;
}
void frequency_correction_face_resign(void *context) {
(void) context;
_disable_output();
}
#else
void frequency_correction_face_setup(uint8_t watch_face_index, void ** context_ptr) {
(void) watch_face_index;
(void) context_ptr;
}
void frequency_correction_face_activate(void *context) {
(void) context;
}
bool frequency_correction_face_loop(movement_event_t event, void *context) {
(void) context;
(void) event;
return true;
}
void frequency_correction_face_resign(void *context) {
(void) context;
}
#endif

View File

@@ -0,0 +1,60 @@
/*
* MIT License
*
* Copyright (c) 2022 <#author_name#>
*
* 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 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 {
uint8_t period_event_output;
} frequency_correction_state_t;
void frequency_correction_face_setup(uint8_t watch_face_index, void ** context_ptr);
void frequency_correction_face_activate(void *context);
bool frequency_correction_face_loop(movement_event_t event, void *context);
void frequency_correction_face_resign(void *context);
#define frequency_correction_face ((const watch_face_t){ \
frequency_correction_face_setup, \
frequency_correction_face_activate, \
frequency_correction_face_loop, \
frequency_correction_face_resign, \
NULL, \
})
#endif // FREQUENCY_CORRECTION_FACE_H_

View File

@@ -0,0 +1,98 @@
/*
* MIT License
*
* Copyright (c) 2022 Joey Castillo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include "hello_there_face.h"
#include "watch.h"
void hello_there_face_setup(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) 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(void *context) {
// same as above: silence the warning, we don't need to check the 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, void *context) {
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_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);
break;
default:
movement_default_loop_handler(event);
break;
}
return true;
}
void hello_there_face_resign(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) context;
}

View File

@@ -0,0 +1,55 @@
/*
* MIT License
*
* Copyright (c) 2022 Joey Castillo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef 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 {
uint8_t current_word;
bool animating;
} hello_there_state_t;
void hello_there_face_setup(uint8_t watch_face_index, void ** context_ptr);
void hello_there_face_activate(void *context);
bool hello_there_face_loop(movement_event_t event, void *context);
void hello_there_face_resign(void *context);
#define hello_there_face ((const watch_face_t){ \
hello_there_face_setup, \
hello_there_face_activate, \
hello_there_face_loop, \
hello_there_face_resign, \
NULL, \
})
#endif // HELLO_THERE_FACE_H_

View File

@@ -0,0 +1,204 @@
/*
* MIT License
*
* Copyright (c) 2022 Joey Castillo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include "lis2dw_logging_face.h"
#include "lis2dw.h"
#include "watch.h"
// This watch face is just for testing; if we want to build accelerometer support, it will likely have to be part of Movement itself.
// The watch face only logs events when it is on screen and not in low energy mode, so you should set LE mode to Never when using it
// and make it the first watch face in the list (so we come back to it from other modes).
// On an interrupt, it flashes the Signal icon, and displays the axis or axes that were over the threshold.
// The main display contains, from left to right, the number of interrupt events that were detected in each of the last three minutes.
// Pressing the alarm button enters the log mode, where the main display shows the number of interrupts detected in each of the last
// 24 hours (the hour is shown in the top right digit and AM/PM indicator, if the clock is set to 12 hour mode)
static void _lis2dw_logging_face_update_display(lis2dw_logger_state_t *logger_state, lis2dw_wakeup_source_t wakeup_source) {
char buf[14];
char time_indication_character;
int8_t pos;
watch_date_time_t date_time;
if (logger_state->log_ticks) {
pos = (logger_state->data_points - 1 - logger_state->display_index) % LIS2DW_LOGGING_NUM_DATA_POINTS;
if (pos < 0) {
watch_clear_colon();
sprintf(buf, "NO data ");
} else {
date_time = logger_state->data[pos].timestamp;
watch_set_colon();
if (movement_clock_mode_24h()) {
watch_set_indicator(WATCH_INDICATOR_24H);
} else {
if (date_time.unit.hour > 11) watch_set_indicator(WATCH_INDICATOR_PM);
date_time.unit.hour %= 12;
if (date_time.unit.hour == 0) date_time.unit.hour = 12;
}
switch (logger_state->axis_index) {
case 0:
sprintf(buf, "3A%2d%02d%4lu", date_time.unit.hour, date_time.unit.minute, logger_state->data[pos].x_interrupts + logger_state->data[pos].y_interrupts + logger_state->data[pos].z_interrupts);
break;
case 1:
sprintf(buf, "XA%2d%02d%4lu", date_time.unit.hour, date_time.unit.minute, logger_state->data[pos].x_interrupts);
break;
case 2:
sprintf(buf, "YA%2d%02d%4lu", date_time.unit.hour, date_time.unit.minute, logger_state->data[pos].y_interrupts);
break;
case 3:
sprintf(buf, "ZA%2d%02d%4lu", date_time.unit.hour, date_time.unit.minute, logger_state->data[pos].z_interrupts);
break;
}
}
} else {
date_time = watch_rtc_get_date_time();
watch_clear_colon();
watch_clear_indicator(WATCH_INDICATOR_PM);
watch_clear_indicator(WATCH_INDICATOR_24H);
if ((59 - date_time.unit.second) < 10) time_indication_character = '0' + (59 - date_time.unit.second);
else time_indication_character = (date_time.unit.second % 2) ? 'i' : '_';
sprintf(buf, "%c%c%c%c%2d%2d%2d",
(wakeup_source & LIS2DW_WAKEUP_SRC_WAKEUP_Y) ? 'Y' : ' ',
(wakeup_source & LIS2DW_WAKEUP_SRC_WAKEUP_X) ? 'X' : ' ',
(wakeup_source & LIS2DW_WAKEUP_SRC_WAKEUP_Z) ? 'Z' : ' ',
time_indication_character,
logger_state->interrupts[0],
logger_state->interrupts[1],
logger_state->interrupts[2]);
}
watch_display_string(buf, 0);
}
static void _lis2dw_logging_face_log_data(lis2dw_logger_state_t *logger_state) {
watch_date_time_t date_time = watch_rtc_get_date_time();
// we get this call 15 minutes late; i.e. at 6:15 we're logging events for 6:00.
// so: if we're at the top of the hour, roll the hour back too (7:00 task logs data for 6:45)
if (date_time.unit.minute == 0) date_time.unit.hour = (date_time.unit.hour + 23) % 24;
// // then roll the minute back.
date_time.unit.minute = (date_time.unit.minute + 45) % 60;
size_t pos = logger_state->data_points % LIS2DW_LOGGING_NUM_DATA_POINTS;
logger_state->data[pos].timestamp.reg = date_time.reg;
logger_state->data[pos].x_interrupts = logger_state->x_interrupts_this_hour;
logger_state->data[pos].y_interrupts = logger_state->y_interrupts_this_hour;
logger_state->data[pos].z_interrupts = logger_state->z_interrupts_this_hour;
logger_state->data_points++;
logger_state->x_interrupts_this_hour = 0;
logger_state->y_interrupts_this_hour = 0;
logger_state->z_interrupts_this_hour = 0;
}
void lis2dw_logging_face_setup(uint8_t watch_face_index, void ** context_ptr) {
(void) watch_face_index;
if (*context_ptr == NULL) {
*context_ptr = malloc(sizeof(lis2dw_logger_state_t));
memset(*context_ptr, 0, sizeof(lis2dw_logger_state_t));
watch_enable_i2c();
lis2dw_begin();
lis2dw_set_low_power_mode(LIS2DW_LP_MODE_2); // lowest power 14-bit mode, 25 Hz is 3.5 µA @ 1.8V w/ low noise, 3µA without
lis2dw_set_low_noise_mode(true); // consumes a little more power
lis2dw_set_range(LIS2DW_CTRL6_VAL_RANGE_4G);
lis2dw_set_data_rate(LIS2DW_DATA_RATE_25_HZ); // is this enough for training?
// threshold is 1/64th of full scale, so for a FS of ±4G this is 1.25G
lis2dw_configure_wakeup_int1(10, true, false);
}
}
void lis2dh_logging_face_activate(void *context) {
lis2dh_logger_state_t *logger_state = (lis2dh_logger_state_t *)context;
logger_state->display_index = 0;
logger_state->log_ticks = 0;
HAL_GPIO_A4_in();
}
bool lis2dw_logging_face_loop(movement_event_t event, void *context) {
lis2dw_logger_state_t *logger_state = (lis2dw_logger_state_t *)context;
lis2dw_wakeup_source_t wakeup_source = 0;
lis2dw_interrupt_source_t interrupt_source = 0;
switch (event.event_type) {
case EVENT_LIGHT_BUTTON_DOWN:
logger_state->axis_index = (logger_state->axis_index + 1) % 4;
logger_state->log_ticks = 255;
_lis2dw_logging_face_update_display(logger_state, wakeup_source);
break;
case EVENT_ALARM_BUTTON_UP:
if (logger_state->log_ticks) logger_state->display_index = (logger_state->display_index + 1) % LIS2DW_LOGGING_NUM_DATA_POINTS;
logger_state->log_ticks = 255;
logger_state->axis_index = 0;
_lis2dw_logging_face_update_display(logger_state, wakeup_source);
break;
case EVENT_ACTIVATE:
case EVENT_TICK:
if (logger_state->log_ticks > 0) {
logger_state->log_ticks--;
} else {
logger_state->display_index = 0;
}
interrupt_source = lis2dw_get_interrupt_source();
if (interrupt_source) {
watch_set_indicator(WATCH_INDICATOR_SIGNAL);
wakeup_source = lis2dw_get_wakeup_source();
logger_state->interrupts[0]++;
if (wakeup_source & LIS2DW_WAKEUP_SRC_WAKEUP_X) logger_state->x_interrupts_this_hour++;
if (wakeup_source & LIS2DW_WAKEUP_SRC_WAKEUP_Y) logger_state->y_interrupts_this_hour++;
if (wakeup_source & LIS2DW_WAKEUP_SRC_WAKEUP_Z) logger_state->z_interrupts_this_hour++;
} else {
watch_clear_indicator(WATCH_INDICATOR_SIGNAL);
}
_lis2dw_logging_face_update_display(logger_state, wakeup_source);
break;
case EVENT_BACKGROUND_TASK:
_lis2dw_logging_face_log_data(logger_state);
break;
default:
movement_default_loop_handler(event);
break;
}
return true;
}
void lis2dw_logging_face_resign(void *context) {
(void) context;
HAL_GPIO_A4_off();
}
movement_watch_face_advisory_t lis2dw_logging_face_advise(void *context) {
lis2dw_logger_state_t *logger_state = (lis2dw_logger_state_t *)context;
watch_date_time_t date_time = watch_rtc_get_date_time();
movement_watch_face_advisory_t retval = { 0 };
// this is kind of an abuse of the API, but, let's use the 1 minute tick to shift all our data over.
logger_state->interrupts[2] = logger_state->interrupts[1];
logger_state->interrupts[1] = logger_state->interrupts[0];
logger_state->interrupts[0] = 0;
// and do our logging task every 15 minutes
retval.wants_background_task = date_time.unit.minute % 15 == 0;
return retval;
}

View File

@@ -0,0 +1,74 @@
/*
* MIT License
*
* Copyright (c) 2022 Joey Castillo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef 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"
#define LIS2DW_LOGGING_NUM_DATA_POINTS (96)
typedef struct {
watch_date_time_t timestamp;
uint32_t x_interrupts;
uint32_t y_interrupts;
uint32_t z_interrupts;
} lis2dw_logger_data_point_t;
typedef struct {
uint8_t display_index; // the index we are displaying on screen
uint8_t axis_index; // the index we are displaying on screen
uint8_t log_ticks; // when the user taps the ALARM button, we enter log mode
int32_t data_points; // the absolute number of data points logged
uint8_t interrupts[3]; // the number of interrupts we have logged in each of the last 3 minutes
uint32_t x_interrupts_this_hour; // the number of interrupts we have logged in the last hour
uint32_t y_interrupts_this_hour; // the number of interrupts we have logged in the last hour
uint32_t z_interrupts_this_hour; // the number of interrupts we have logged in the last hour
lis2dw_logger_data_point_t data[LIS2DW_LOGGING_NUM_DATA_POINTS];
} lis2dw_logger_state_t;
void lis2dw_logging_face_setup(uint8_t watch_face_index, void ** context_ptr);
void lis2dw_logging_face_activate(void *context);
bool lis2dw_logging_face_loop(movement_event_t event, void *context);
void lis2dw_logging_face_resign(void *context);
movement_watch_face_advisory_t lis2dw_logging_face_advise(void *context);
#define lis2dw_logging_face ((const watch_face_t){ \
lis2dw_logging_face_setup, \
lis2dw_logging_face_activate, \
lis2dw_logging_face_loop, \
lis2dw_logging_face_resign, \
lis2dw_logging_face_advise, \
})
#endif // LIS2DW_LOGGING_FACE_H_