more accelerometer work
This commit is contained in:
64
movement.c
64
movement.c
@@ -77,6 +77,8 @@ void cb_tick(void);
|
||||
|
||||
#ifdef HAS_ACCELEROMETER
|
||||
void cb_motion_interrupt_1(void);
|
||||
void cb_motion_interrupt_2(void);
|
||||
uint32_t orientation_changes = 0;
|
||||
#endif
|
||||
|
||||
#if __EMSCRIPTEN__
|
||||
@@ -638,25 +640,16 @@ void app_setup(void) {
|
||||
|
||||
// set up interrupts:
|
||||
// INT1 is on A4 which can wake from deep sleep. Wake on 6D orientation change.
|
||||
lis2dw_configure_int1(LIS2DW_CTRL4_INT1_6D);
|
||||
watch_register_interrupt_callback(HAL_GPIO_A4_pin(), cb_motion_interrupt_1, INTERRUPT_TRIGGER_FALLING);
|
||||
lis2dw_configure_int1(LIS2DW_CTRL4_INT1_6D | LIS2DW_CTRL4_INT1_WU | LIS2DW_CTRL4_INT1_TAP | LIS2DW_CTRL4_INT1_SINGLE_TAP);
|
||||
watch_register_extwake_callback(HAL_GPIO_A4_pin(), cb_motion_interrupt_1, true);
|
||||
|
||||
// configure the accelerometer to fire INT2 when its sleep state changes.
|
||||
// configure the accelerometer to output the sleep state on INT2.
|
||||
lis2dw_configure_int2(LIS2DW_CTRL5_INT2_SLEEP_STATE | LIS2DW_CTRL5_INT2_SLEEP_CHG);
|
||||
// INT2 is wired to pin A3. set it up on the external interrupt controller.
|
||||
HAL_GPIO_A3_in();
|
||||
HAL_GPIO_A3_pmuxen(HAL_GPIO_PMUX_EIC);
|
||||
eic_configure_pin(HAL_GPIO_A3_pin(), INTERRUPT_TRIGGER_FALLING);
|
||||
// but rather than firing an interrupt, we'll have it generate an event instead.
|
||||
eic_enable_event(HAL_GPIO_A3_pin());
|
||||
// we can route the EXTINT3 event generator to the TC2 event user...
|
||||
evsys_configure_channel(0, EVSYS_ID_GEN_EIC_EXTINT_3, EVSYS_ID_USER_TC2_EVU, true, true);
|
||||
// and use the TC2 event to count the number of times the sleep state changes.
|
||||
// note that this doesn't actually wake the watch — we can maintain this count even in standby.
|
||||
tc_init(2, GENERIC_CLOCK_3, TC_PRESCALER_DIV1);
|
||||
tc_set_event_action(2, TC_EVENT_ACTION_COUNT);
|
||||
tc_set_counter_mode(2, TC_COUNTER_MODE_16BIT);
|
||||
tc_enable(2);
|
||||
eic_configure_pin(HAL_GPIO_A3_pin(), INTERRUPT_TRIGGER_BOTH);
|
||||
watch_register_interrupt_callback(HAL_GPIO_A3_pin(), cb_motion_interrupt_2, INTERRUPT_TRIGGER_BOTH);
|
||||
|
||||
lis2dw_enable_interrupts();
|
||||
}
|
||||
@@ -698,6 +691,17 @@ static void _sleep_mode_app_loop(void) {
|
||||
bool app_loop(void) {
|
||||
const watch_face_t *wf = &watch_faces[movement_state.current_face_idx];
|
||||
bool woke_up_for_buzzer = false;
|
||||
|
||||
// REMOVE THIS before shipping the accelerometer board: test beeps.
|
||||
if (movement_state.settings.bit.button_should_sound && event.event_type == EVENT_ACCELEROMETER_WAKE) {
|
||||
watch_buzzer_play_note_with_volume(BUZZER_NOTE_C6, 20, WATCH_BUZZER_VOLUME_SOFT);
|
||||
}
|
||||
if (movement_state.settings.bit.button_should_sound && event.event_type == EVENT_ACCELEROMETER_SLEEP) {
|
||||
watch_buzzer_play_note_with_volume(BUZZER_NOTE_C5, 15, WATCH_BUZZER_VOLUME_SOFT);
|
||||
watch_buzzer_play_note_with_volume(BUZZER_NOTE_REST, 10, WATCH_BUZZER_VOLUME_SOFT);
|
||||
watch_buzzer_play_note_with_volume(BUZZER_NOTE_C5, 15, WATCH_BUZZER_VOLUME_SOFT);
|
||||
}
|
||||
|
||||
if (movement_state.watch_face_changed) {
|
||||
if (movement_state.settings.bit.button_should_sound) {
|
||||
// low note for nonzero case, high note for return to watch_face 0
|
||||
@@ -928,7 +932,35 @@ void cb_tick(void) {
|
||||
|
||||
#ifdef HAS_ACCELEROMETER
|
||||
void cb_motion_interrupt_1(void) {
|
||||
// TODO: Find out what motion event woke us up.
|
||||
printf("INT1\n");
|
||||
uint8_t int_src = lis2dw_get_interrupt_source();
|
||||
if (int_src & LIS2DW_REG_ALL_INT_SRC_6D_IA) {
|
||||
event.event_type = EVENT_ORIENTATION_CHANGE;
|
||||
orientation_changes++;
|
||||
}
|
||||
if (int_src & LIS2DW_REG_ALL_INT_SRC_DOUBLE_TAP) event.event_type = EVENT_DOUBLE_TAP;
|
||||
if (int_src & LIS2DW_REG_ALL_INT_SRC_SINGLE_TAP) event.event_type = EVENT_SINGLE_TAP;
|
||||
if (int_src & LIS2DW_REG_ALL_INT_SRC_FF_IA) event.event_type = EVENT_FREE_FALL;
|
||||
|
||||
// These are handled on INT2, which is not available in low energy mode.
|
||||
// If we want wakeup events on INT1, we could ask for LIS2DW_CTRL4_INT1_WU and get wake events here.
|
||||
// If we want sleep change events on INT1, we'd have to set LIS2DW_CTRL5_INT2_SLEEP_CHG and LIS2DW_CTRL7_VAL_INT2_ON_INT1
|
||||
// That would give us these two cases:
|
||||
// if (int_src & LIS2DW_REG_ALL_INT_SRC_WU_IA) printf(" Wake up");
|
||||
// if (int_src & LIS2DW_REG_ALL_INT_SRC_SLEEP_CHANGE_IA) printf(" Sleep change");
|
||||
}
|
||||
|
||||
void cb_motion_interrupt_2(void) {
|
||||
if (HAL_GPIO_A3_read()) {
|
||||
event.event_type = EVENT_ACCELEROMETER_SLEEP;
|
||||
printf("Sleep on INT2\n");
|
||||
} else {
|
||||
event.event_type = EVENT_ACCELEROMETER_WAKE;
|
||||
printf("Wake on INT2\n");
|
||||
// Not sure if it's useful to know what axis exceeded the threshold, but here's that:
|
||||
// uint8_t int_src = lis2dw_get_wakeup_source();
|
||||
// if (int_src & LIS2DW_WAKE_UP_SRC_VAL_X_WU) printf("Wake on X");
|
||||
// if (int_src & LIS2DW_WAKE_UP_SRC_VAL_Y_WU) printf("Wake on Y");
|
||||
// if (int_src & LIS2DW_WAKE_UP_SRC_VAL_Z_WU) printf("Wake on Z");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user