more accelerometer work

This commit is contained in:
joeycastillo
2024-10-19 12:35:46 -04:00
parent 57de3e77f5
commit 19376625d1
6 changed files with 76 additions and 27 deletions

View File

@@ -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