'movement' -> 'legacy' to signal things we still need to bring in
This commit is contained in:
246
legacy/watch_faces/demo/beeps_face.c
Normal file
246
legacy/watch_faces/demo/beeps_face.c
Normal 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;
|
||||
}
|
||||
|
||||
61
legacy/watch_faces/demo/beeps_face.h
Normal file
61
legacy/watch_faces/demo/beeps_face.h
Normal 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_
|
||||
|
||||
132
legacy/watch_faces/demo/demo_face.c
Normal file
132
legacy/watch_faces/demo/demo_face.c
Normal 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;
|
||||
}
|
||||
54
legacy/watch_faces/demo/demo_face.h
Normal file
54
legacy/watch_faces/demo/demo_face.h
Normal 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_
|
||||
158
legacy/watch_faces/demo/frequency_correction_face.c
Normal file
158
legacy/watch_faces/demo/frequency_correction_face.c
Normal 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
|
||||
60
legacy/watch_faces/demo/frequency_correction_face.h
Normal file
60
legacy/watch_faces/demo/frequency_correction_face.h
Normal 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_
|
||||
|
||||
98
legacy/watch_faces/demo/hello_there_face.c
Normal file
98
legacy/watch_faces/demo/hello_there_face.c
Normal 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;
|
||||
}
|
||||
55
legacy/watch_faces/demo/hello_there_face.h
Normal file
55
legacy/watch_faces/demo/hello_there_face.h
Normal 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_
|
||||
204
legacy/watch_faces/demo/lis2dw_logging_face.c
Normal file
204
legacy/watch_faces/demo/lis2dw_logging_face.c
Normal 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;
|
||||
}
|
||||
74
legacy/watch_faces/demo/lis2dw_logging_face.h
Normal file
74
legacy/watch_faces/demo/lis2dw_logging_face.h
Normal 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_
|
||||
Reference in New Issue
Block a user