diff options
Diffstat (limited to 'movement/movement.c')
-rw-r--r-- | movement/movement.c | 82 |
1 files changed, 65 insertions, 17 deletions
diff --git a/movement/movement.c b/movement/movement.c index 09ebf0c2..3997b4a4 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -22,6 +22,8 @@ * SOFTWARE. */ +#define MOVEMENT_LONG_PRESS_TICKS 64 + #include <stdio.h> #include <string.h> #include <limits.h> @@ -35,7 +37,9 @@ #ifndef MOVEMENT_FIRMWARE #include "movement_config.h" #elif MOVEMENT_FIRMWARE == MOVEMENT_FIRMWARE_STANDARD -#include "alt_fw/standard.h" +#include "movement_config.h" +#elif MOVEMENT_FIRMWARE == MOVEMENT_FIRMWARE_BACKER +#include "alt_fw/backer.h" #elif MOVEMENT_FIRMWARE == MOVEMENT_FIRMWARE_ALT_TIME #include "alt_fw/alt_time.h" #elif MOVEMENT_FIRMWARE == MOVEMENT_FIRMWARE_FOCUS @@ -50,6 +54,19 @@ #include "alt_fw/deep_space_now.h" #endif +// Default to no secondary face behaviour. +#ifndef MOVEMENT_SECONDARY_FACE_INDEX +#define MOVEMENT_SECONDARY_FACE_INDEX 0 +#endif + +// Set default LED colors if not set +#ifndef MOVEMENT_DEFAULT_RED_COLOR +#define MOVEMENT_DEFAULT_RED_COLOR 0x0 +#endif +#ifndef MOVEMENT_DEFAULT_GREEN_COLOR +#define MOVEMENT_DEFAULT_GREEN_COLOR 0xF +#endif + #if __EMSCRIPTEN__ #include <emscripten.h> #endif @@ -207,7 +224,13 @@ void movement_move_to_face(uint8_t watch_face_index) { } void movement_move_to_next_face(void) { - movement_move_to_face((movement_state.current_watch_face + 1) % MOVEMENT_NUM_FACES); + uint16_t face_max; + if (MOVEMENT_SECONDARY_FACE_INDEX) { + face_max = (movement_state.current_watch_face < (int16_t)MOVEMENT_SECONDARY_FACE_INDEX) ? MOVEMENT_SECONDARY_FACE_INDEX : MOVEMENT_NUM_FACES; + } else { + face_max = MOVEMENT_NUM_FACES; + } + movement_move_to_face((movement_state.current_watch_face + 1) % face_max); } void movement_schedule_background_task(watch_date_time date_time) { @@ -250,11 +273,16 @@ void movement_play_signal(void) { } void movement_play_alarm(void) { + movement_play_alarm_beeps(5, BUZZER_NOTE_C8); +} + +void movement_play_alarm_beeps(uint8_t rounds, BuzzerNote alarm_note) { + if (rounds == 0) rounds = 1; + if (rounds > 20) rounds = 20; movement_request_wake(); - // alarm length: 75 ticks short of 5 seconds, or 4.414 seconds: - // our tone is 0.375 seconds of beep and 0.625 of silence, repeated five times. - // so 4.375 + a few ticks to wake up from sleep mode. - movement_state.alarm_ticks = 128 * 5 - 75; + movement_state.alarm_note = alarm_note; + // our tone is 0.375 seconds of beep and 0.625 of silence, repeated as given. + movement_state.alarm_ticks = 128 * rounds - 75; _movement_enable_fast_tick_if_needed(); } @@ -266,7 +294,8 @@ uint8_t movement_claim_backup_register(void) { void app_init(void) { memset(&movement_state, 0, sizeof(movement_state)); - movement_state.settings.bit.led_green_color = 0xF; + movement_state.settings.bit.led_red_color = MOVEMENT_DEFAULT_RED_COLOR; + movement_state.settings.bit.led_green_color = MOVEMENT_DEFAULT_GREEN_COLOR; movement_state.settings.bit.button_should_sound = true; movement_state.settings.bit.le_interval = 1; movement_state.settings.bit.led_duration = 1; @@ -421,14 +450,18 @@ bool app_loop(void) { can_sleep = watch_faces[movement_state.current_watch_face].loop(event, &movement_state.settings, watch_face_contexts[movement_state.current_watch_face]); // Long-pressing MODE brings one back to the first face, provided that the watch face hasn't decided to send them elsewhere - // (and we're not currently on the first face). + // (and we're not currently on the first face). If we're currently on the first face, a long press + // of MODE sends us to the secondary faces (if defined). // Note that it's the face's responsibility to provide some way to get to the next face, so if EVENT_MODE_BUTTON_* is // used for face functionality EVENT_MODE_LONG_PRESS should probably be handled and next_face() triggered in the face // (which would effectively disable the normal 'long press to face 0' behaviour). if (event.event_type == EVENT_MODE_LONG_PRESS - && movement_state.current_watch_face > 0 && !movement_state.watch_face_changed) { - movement_move_to_face(0); + if (movement_state.current_watch_face != 0) { + movement_move_to_face(0); + } else if (MOVEMENT_SECONDARY_FACE_INDEX) { + movement_move_to_face(MOVEMENT_SECONDARY_FACE_INDEX); + } } event.event_type = EVENT_NONE; } @@ -453,10 +486,13 @@ bool app_loop(void) { if (movement_state.alarm_ticks >= 0) { uint8_t buzzer_phase = (movement_state.alarm_ticks + 80) % 128; if(buzzer_phase == 127) { + // failsafe: buzzer could have been disabled in the meantime + if (!watch_is_buzzer_or_led_enabled()) watch_enable_buzzer(); + // play 4 beeps plus pause for(uint8_t i = 0; i < 4; i++) { // TODO: This method of playing the buzzer blocks the UI while it's beeping. // It might be better to time it with the fast tick. - watch_buzzer_play_note(BUZZER_NOTE_C8, (i != 3) ? 50 : 75); + watch_buzzer_play_note(movement_state.alarm_note, (i != 3) ? 50 : 75); if (i != 3) watch_buzzer_play_note(BUZZER_NOTE_REST, 50); } } @@ -503,7 +539,7 @@ bool app_loop(void) { return can_sleep; } -static movement_event_type_t _figure_out_button_event(bool pin_level, movement_event_type_t button_down_event_type, uint8_t *down_timestamp) { +static movement_event_type_t _figure_out_button_event(bool pin_level, movement_event_type_t button_down_event_type, uint16_t *down_timestamp) { // force alarm off if the user pressed a button. if (movement_state.alarm_ticks) movement_state.alarm_ticks = 0; @@ -513,15 +549,15 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e *down_timestamp = movement_state.fast_ticks + 1; return button_down_event_type; } else { - // this line is hack but it handles the situation where the light button was held for more than 10 seconds. + // this line is hack but it handles the situation where the light button was held for more than 20 seconds. // fast tick is disabled by then, and the LED would get stuck on since there's no one left decrementing light_ticks. if (movement_state.light_ticks == 1) movement_state.light_ticks = 0; // now that that's out of the way, handle falling edge uint16_t diff = movement_state.fast_ticks - *down_timestamp; *down_timestamp = 0; _movement_disable_fast_tick_if_possible(); - // any press over a half second is considered a long press. - if (diff > 64) return button_down_event_type + 2; + // any press over a half second is considered a long press. Fire the long-up event + if (diff > MOVEMENT_LONG_PRESS_TICKS) return button_down_event_type + 3; else return button_down_event_type + 1; } } @@ -557,9 +593,21 @@ void cb_fast_tick(void) { movement_state.fast_ticks++; if (movement_state.light_ticks > 0) movement_state.light_ticks--; if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--; + // check timestamps and auto-fire the long-press events + // Notice: is it possible that two or more buttons have an identical timestamp? In this case + // only one of these buttons would receive the long press event. Don't bother for now... + if (movement_state.light_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.light_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_LIGHT_LONG_PRESS; + if (movement_state.mode_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.mode_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_MODE_LONG_PRESS; + if (movement_state.alarm_down_timestamp > 0) + if (movement_state.fast_ticks - movement_state.alarm_down_timestamp == MOVEMENT_LONG_PRESS_TICKS + 1) + event.event_type = EVENT_ALARM_LONG_PRESS; // this is just a fail-safe; fast tick should be disabled as soon as the button is up, the LED times out, and/or the alarm finishes. - // but if for whatever reason it isn't, this forces the fast tick off after 10 seconds. - if (movement_state.fast_ticks >= 1280) watch_rtc_disable_periodic_callback(128); + // but if for whatever reason it isn't, this forces the fast tick off after 20 seconds. + if (movement_state.fast_ticks >= 128 * 20) watch_rtc_disable_periodic_callback(128); } void cb_tick(void) { |