mirror of
https://github.com/firewalkwithm3/Sensor-Watch.git
synced 2024-11-22 19:20:30 +08:00
Merge pull request #109 from TheOnePerson/auto-fire-long-press
Make movement auto fire long press event
This commit is contained in:
commit
09f1d02330
|
@ -22,6 +22,8 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define MOVEMENT_LONG_PRESS_TICKS 64
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
@ -526,7 +528,7 @@ bool app_loop(void) {
|
||||||
return can_sleep;
|
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.
|
// force alarm off if the user pressed a button.
|
||||||
if (movement_state.alarm_ticks) movement_state.alarm_ticks = 0;
|
if (movement_state.alarm_ticks) movement_state.alarm_ticks = 0;
|
||||||
|
|
||||||
|
@ -543,8 +545,8 @@ static movement_event_type_t _figure_out_button_event(bool pin_level, movement_e
|
||||||
uint16_t diff = movement_state.fast_ticks - *down_timestamp;
|
uint16_t diff = movement_state.fast_ticks - *down_timestamp;
|
||||||
*down_timestamp = 0;
|
*down_timestamp = 0;
|
||||||
_movement_disable_fast_tick_if_possible();
|
_movement_disable_fast_tick_if_possible();
|
||||||
// any press over a half second is considered a long press.
|
// any press over a half second is considered a long press. Fire the long-up event
|
||||||
if (diff > 64) return button_down_event_type + 2;
|
if (diff > MOVEMENT_LONG_PRESS_TICKS) return button_down_event_type + 3;
|
||||||
else return button_down_event_type + 1;
|
else return button_down_event_type + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -580,6 +582,18 @@ void cb_fast_tick(void) {
|
||||||
movement_state.fast_ticks++;
|
movement_state.fast_ticks++;
|
||||||
if (movement_state.light_ticks > 0) movement_state.light_ticks--;
|
if (movement_state.light_ticks > 0) movement_state.light_ticks--;
|
||||||
if (movement_state.alarm_ticks > 0) movement_state.alarm_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.
|
// 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 20 seconds.
|
// 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);
|
if (movement_state.fast_ticks >= 128 * 20) watch_rtc_disable_periodic_callback(128);
|
||||||
|
|
|
@ -109,14 +109,17 @@ typedef enum {
|
||||||
EVENT_BACKGROUND_TASK, // Your watch face is being invoked to perform a background task. Don't update the display here; you may not be in the foreground.
|
EVENT_BACKGROUND_TASK, // Your watch face is being invoked to perform a background task. Don't update the display here; you may not be in the foreground.
|
||||||
EVENT_TIMEOUT, // Your watch face has been inactive for a while. You may want to resign, depending on your watch face's intended use case.
|
EVENT_TIMEOUT, // Your watch face has been inactive for a while. You may want to resign, depending on your watch face's intended use case.
|
||||||
EVENT_LIGHT_BUTTON_DOWN, // The light button has been pressed, but not yet released.
|
EVENT_LIGHT_BUTTON_DOWN, // The light button has been pressed, but not yet released.
|
||||||
EVENT_LIGHT_BUTTON_UP, // The light button was pressed and released.
|
EVENT_LIGHT_BUTTON_UP, // The light button was pressed for less than half a second, and released.
|
||||||
EVENT_LIGHT_LONG_PRESS, // The light button was held for >2 seconds, and released.
|
EVENT_LIGHT_LONG_PRESS, // The light button was held for over half a second, but not yet released.
|
||||||
|
EVENT_LIGHT_LONG_UP, // The light button was held for over half a second, and released.
|
||||||
EVENT_MODE_BUTTON_DOWN, // The mode button has been pressed, but not yet released.
|
EVENT_MODE_BUTTON_DOWN, // The mode button has been pressed, but not yet released.
|
||||||
EVENT_MODE_BUTTON_UP, // The mode button was pressed and released.
|
EVENT_MODE_BUTTON_UP, // The mode button was pressed for less than half a second, and released.
|
||||||
EVENT_MODE_LONG_PRESS, // The mode button was held for >2 seconds, and released. NOTE: your watch face will resign immediately after receiving this event.
|
EVENT_MODE_LONG_PRESS, // The mode button was held for over half a second, but not yet released.
|
||||||
|
EVENT_MODE_LONG_UP, // The mode button was held for over half a second, and released. NOTE: your watch face will resign immediately after receiving this event.
|
||||||
EVENT_ALARM_BUTTON_DOWN, // The alarm button has been pressed, but not yet released.
|
EVENT_ALARM_BUTTON_DOWN, // The alarm button has been pressed, but not yet released.
|
||||||
EVENT_ALARM_BUTTON_UP, // The alarm button was pressed and released.
|
EVENT_ALARM_BUTTON_UP, // The alarm button was pressed for less than half a second, and released.
|
||||||
EVENT_ALARM_LONG_PRESS, // The alarm button was held for >2 seconds, and released.
|
EVENT_ALARM_LONG_PRESS, // The alarm button was held for over half a second, but not yet released.
|
||||||
|
EVENT_ALARM_LONG_UP, // The alarm button was held for over half a second, and released.
|
||||||
} movement_event_type_t;
|
} movement_event_type_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -256,9 +259,9 @@ typedef struct {
|
||||||
BuzzerNote alarm_note;
|
BuzzerNote alarm_note;
|
||||||
|
|
||||||
// button tracking for long press
|
// button tracking for long press
|
||||||
uint8_t light_down_timestamp;
|
uint16_t light_down_timestamp;
|
||||||
uint8_t mode_down_timestamp;
|
uint16_t mode_down_timestamp;
|
||||||
uint8_t alarm_down_timestamp;
|
uint16_t alarm_down_timestamp;
|
||||||
|
|
||||||
// background task handling
|
// background task handling
|
||||||
bool needs_background_tasks_handled;
|
bool needs_background_tasks_handled;
|
||||||
|
|
|
@ -103,7 +103,7 @@ static void _alarm_face_draw(movement_settings_t *settings, alarm_state_t *state
|
||||||
h,
|
h,
|
||||||
state->alarm[state->alarm_idx].minute);
|
state->alarm[state->alarm_idx].minute);
|
||||||
// blink items if in settings mode
|
// blink items if in settings mode
|
||||||
if (state->is_setting && subsecond % 2 && state->setting_state < alarm_setting_idx_pitch && state->alarm_quick_ticks == -1) {
|
if (state->is_setting && subsecond % 2 && state->setting_state < alarm_setting_idx_pitch && !state->alarm_quick_ticks) {
|
||||||
buf[_blink_idx[state->setting_state]] = buf[_blink_idx2[state->setting_state]] = ' ';
|
buf[_blink_idx[state->setting_state]] = buf[_blink_idx2[state->setting_state]] = ' ';
|
||||||
}
|
}
|
||||||
watch_display_string(buf, 0);
|
watch_display_string(buf, 0);
|
||||||
|
@ -180,9 +180,9 @@ static void _alarm_indicate_beep(alarm_state_t *state) {
|
||||||
|
|
||||||
static void _abort_quick_ticks(alarm_state_t *state) {
|
static void _abort_quick_ticks(alarm_state_t *state) {
|
||||||
// abort counting quick ticks
|
// abort counting quick ticks
|
||||||
if (state->alarm_quick_ticks >= ALARM_QUICK_MIN_TICKS) state->alarm[state->alarm_idx].enabled = true;
|
if (state->alarm_quick_ticks) {
|
||||||
if (state->alarm_quick_ticks >= 0) {
|
state->alarm[state->alarm_idx].enabled = true;
|
||||||
state->alarm_quick_ticks = -1;
|
state->alarm_quick_ticks = false;
|
||||||
movement_request_tick_frequency(4);
|
movement_request_tick_frequency(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,6 @@ void alarm_face_setup(movement_settings_t *settings, uint8_t watch_face_index, v
|
||||||
state->alarm[i].pitch = 1;
|
state->alarm[i].pitch = 1;
|
||||||
}
|
}
|
||||||
state->alarm_handled_minute = -1;
|
state->alarm_handled_minute = -1;
|
||||||
state->alarm_quick_ticks = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +217,7 @@ void alarm_face_resign(movement_settings_t *settings, void *context) {
|
||||||
_alarm_update_alarm_enabled(settings, state);
|
_alarm_update_alarm_enabled(settings, state);
|
||||||
watch_set_led_off();
|
watch_set_led_off();
|
||||||
watch_store_backup_data(settings->reg, 0);
|
watch_store_backup_data(settings->reg, 0);
|
||||||
state->alarm_quick_ticks = -1;
|
state->alarm_quick_ticks = false;
|
||||||
movement_request_tick_frequency(1);
|
movement_request_tick_frequency(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,38 +261,18 @@ bool alarm_face_loop(movement_event_t event, movement_settings_t *settings, void
|
||||||
|
|
||||||
switch (event.event_type) {
|
switch (event.event_type) {
|
||||||
case EVENT_TICK:
|
case EVENT_TICK:
|
||||||
if (state->alarm_quick_ticks >= 0) {
|
if (state->alarm_quick_ticks) {
|
||||||
// we are counting ticks for the alarm button
|
// we are in fast cycling mode
|
||||||
if (state->setting_state == alarm_setting_idx_hour || state->setting_state == alarm_setting_idx_minute) {
|
if (state->setting_state == alarm_setting_idx_hour) {
|
||||||
if (state->alarm_quick_ticks < INT8_MAX) state->alarm_quick_ticks++;
|
|
||||||
if (state->alarm_quick_ticks == ALARM_QUICK_MIN_TICKS) {
|
|
||||||
// initiate fast counting
|
|
||||||
movement_request_tick_frequency(8);
|
|
||||||
} else if (state->alarm_quick_ticks > ALARM_QUICK_MIN_TICKS) {
|
|
||||||
// fast count hours or minutes
|
|
||||||
if (state->setting_state == alarm_setting_idx_hour)
|
|
||||||
state->alarm[state->alarm_idx].hour = (state->alarm[state->alarm_idx].hour + 1) % 24;
|
state->alarm[state->alarm_idx].hour = (state->alarm[state->alarm_idx].hour + 1) % 24;
|
||||||
else if (state->setting_state == alarm_setting_idx_minute)
|
} else if (state->setting_state == alarm_setting_idx_minute) {
|
||||||
state->alarm[state->alarm_idx].minute = (state->alarm[state->alarm_idx].minute + 1) % 60;
|
state->alarm[state->alarm_idx].minute = (state->alarm[state->alarm_idx].minute + 1) % 60;
|
||||||
_alarm_face_draw(settings, state, event.subsecond);
|
} else _abort_quick_ticks(state);
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_abort_quick_ticks(state);
|
|
||||||
}
|
|
||||||
} else if (!state->is_setting) break; // no need to do anything when we are not in settings mode and no quick ticks are running
|
} else if (!state->is_setting) break; // no need to do anything when we are not in settings mode and no quick ticks are running
|
||||||
// fall through
|
// fall through
|
||||||
case EVENT_ACTIVATE:
|
case EVENT_ACTIVATE:
|
||||||
_alarm_face_draw(settings, state, event.subsecond);
|
_alarm_face_draw(settings, state, event.subsecond);
|
||||||
break;
|
break;
|
||||||
case EVENT_LIGHT_BUTTON_DOWN:
|
|
||||||
break;
|
|
||||||
case EVENT_ALARM_BUTTON_DOWN:
|
|
||||||
// check if we need to start counting ticks
|
|
||||||
if (state->is_setting && (state->setting_state == alarm_setting_idx_hour || state->setting_state == alarm_setting_idx_minute)) {
|
|
||||||
state->alarm_quick_ticks = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EVENT_LIGHT_BUTTON_UP:
|
case EVENT_LIGHT_BUTTON_UP:
|
||||||
if (!state->is_setting) {
|
if (!state->is_setting) {
|
||||||
movement_illuminate_led();
|
movement_illuminate_led();
|
||||||
|
@ -371,8 +350,9 @@ bool alarm_face_loop(movement_event_t event, movement_settings_t *settings, void
|
||||||
break;
|
break;
|
||||||
case alarm_setting_idx_minute:
|
case alarm_setting_idx_minute:
|
||||||
case alarm_setting_idx_hour:
|
case alarm_setting_idx_hour:
|
||||||
// hour or minute selection
|
// initiate fast cycling for hour or minute settings
|
||||||
_abort_quick_ticks(state);
|
movement_request_tick_frequency(8);
|
||||||
|
state->alarm_quick_ticks = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -380,6 +360,12 @@ bool alarm_face_loop(movement_event_t event, movement_settings_t *settings, void
|
||||||
}
|
}
|
||||||
_alarm_face_draw(settings, state, event.subsecond);
|
_alarm_face_draw(settings, state, event.subsecond);
|
||||||
break;
|
break;
|
||||||
|
case EVENT_ALARM_LONG_UP:
|
||||||
|
if (state->is_setting) {
|
||||||
|
if (state->setting_state == alarm_setting_idx_hour || state->setting_state == alarm_setting_idx_minute)
|
||||||
|
_abort_quick_ticks(state);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case EVENT_BACKGROUND_TASK:
|
case EVENT_BACKGROUND_TASK:
|
||||||
// play alarm
|
// play alarm
|
||||||
if (state->alarm[state->alarm_playing_idx].beeps == 0) {
|
if (state->alarm[state->alarm_playing_idx].beeps == 0) {
|
||||||
|
|
|
@ -41,7 +41,6 @@ A face for setting various alarms
|
||||||
#define ALARM_DAY_WEEKEND 10
|
#define ALARM_DAY_WEEKEND 10
|
||||||
#define ALARM_MAX_BEEP_ROUNDS 11 // maximum number of beeping rounds for an alarm slot (including short and long alarms)
|
#define ALARM_MAX_BEEP_ROUNDS 11 // maximum number of beeping rounds for an alarm slot (including short and long alarms)
|
||||||
#define ALARM_SETTING_STATES 6
|
#define ALARM_SETTING_STATES 6
|
||||||
#define ALARM_QUICK_MIN_TICKS 2 * 4 // number of ticks (quarter seconds) to wait until fast counting for hours and minutes kicks in
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t day : 4; // day of week: 0=MO, 1=TU, 2=WE, 3=TH, 4=FR, 5=SA, 6=SU, 7=each day, 8=one time alarm, 9=Weekdays, 10=Weekend
|
uint8_t day : 4; // day of week: 0=MO, 1=TU, 2=WE, 3=TH, 4=FR, 5=SA, 6=SU, 7=each day, 8=one time alarm, 9=Weekdays, 10=Weekend
|
||||||
|
@ -57,7 +56,7 @@ typedef struct {
|
||||||
uint8_t alarm_playing_idx : 4;
|
uint8_t alarm_playing_idx : 4;
|
||||||
uint8_t setting_state : 3;
|
uint8_t setting_state : 3;
|
||||||
int8_t alarm_handled_minute;
|
int8_t alarm_handled_minute;
|
||||||
int8_t alarm_quick_ticks;
|
bool alarm_quick_ticks : 1;
|
||||||
bool is_setting : 1;
|
bool is_setting : 1;
|
||||||
alarm_setting_t alarm[ALARM_ALARMS];
|
alarm_setting_t alarm[ALARM_ALARMS];
|
||||||
} alarm_state_t;
|
} alarm_state_t;
|
||||||
|
|
|
@ -59,7 +59,7 @@ bool pulsometer_face_loop(movement_event_t event, movement_settings_t *settings,
|
||||||
movement_request_tick_frequency(PULSOMETER_FACE_FREQUENCY);
|
movement_request_tick_frequency(PULSOMETER_FACE_FREQUENCY);
|
||||||
break;
|
break;
|
||||||
case EVENT_ALARM_BUTTON_UP:
|
case EVENT_ALARM_BUTTON_UP:
|
||||||
case EVENT_ALARM_LONG_PRESS:
|
case EVENT_ALARM_LONG_UP:
|
||||||
pulsometer_state->measuring = false;
|
pulsometer_state->measuring = false;
|
||||||
movement_request_tick_frequency(1);
|
movement_request_tick_frequency(1);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue