From c5bda0faeb584c01efbfdee417b091c29fbc2406 Mon Sep 17 00:00:00 2001 From: Joey Castillo Date: Fri, 16 May 2025 00:07:15 -0400 Subject: [PATCH] auto-detect accelerometer sensor (and don't fail build for lack of a temperature sensor) --- Makefile | 6 -- movement.c | 98 +++++++++---------- movement.h | 7 +- movement_activity.c | 4 - movement_activity.h | 4 - watch-faces/complication/countdown_face.c | 5 +- watch-faces/demo/accel_interrupt_count_face.c | 4 - watch-faces/demo/accel_interrupt_count_face.h | 4 - watch-faces/sensor/activity_logging_face.c | 4 - watch-faces/sensor/activity_logging_face.h | 4 - .../shared/driver/thermistor_driver.c | 11 ++- .../shared/driver/thermistor_driver.h | 4 - 12 files changed, 63 insertions(+), 92 deletions(-) diff --git a/Makefile b/Makefile index 38f89736..7e8d2751 100644 --- a/Makefile +++ b/Makefile @@ -32,10 +32,6 @@ ifndef BOARD $(error Build failed: BOARD not defined. Use one of the four options below, depending on your hardware:$n$n make BOARD=sensorwatch_red$n make BOARD=sensorwatch_green$n make BOARD=sensorwatch_blue$n make BOARD=sensorwatch_pro$n$n) endif -ifeq ($(SENSOR), MOTION) - DEFINES += -DHAS_ACCELEROMETER -endif - ifeq ($(SENSOR), TEMPERATURE) DEFINES += -DTEMPERATURE_BOARD_INSTALLED endif @@ -99,9 +95,7 @@ SRCS += \ ./watch-library/shared/watch/watch_utility.c \ -ifeq ($(SENSOR), MOTION) SRCS += ./watch-library/shared/driver/lis2dw.c -endif ifdef EMSCRIPTEN diff --git a/movement.c b/movement.c index c3579836..2d2edae1 100644 --- a/movement.c +++ b/movement.c @@ -74,11 +74,9 @@ void cb_alarm_fired(void); void cb_fast_tick(void); void cb_tick(void); -#ifdef HAS_ACCELEROMETER void cb_accelerometer_event(void); void cb_accelerometer_wake(void); uint8_t active_minutes = 0; -#endif #if __EMSCRIPTEN__ void yield(void) { @@ -156,17 +154,17 @@ static inline void _movement_disable_fast_tick_if_possible(void) { static void _movement_handle_top_of_minute(void) { watch_date_time_t date_time = watch_rtc_get_date_time(); -#ifdef HAS_ACCELEROMETER - bool accelerometer_is_alseep = HAL_GPIO_A4_read(); - if (!accelerometer_is_alseep) active_minutes++; - printf("Active minutes: %d\n", active_minutes); + if (movement_state.has_lis2dw) { + bool accelerometer_is_alseep = HAL_GPIO_A4_read(); + if (!accelerometer_is_alseep) active_minutes++; + printf("Active minutes: %d\n", active_minutes); - // log data every five minutes, and reset the active_minutes count. - if ((date_time.unit.minute % 5) == 0) { - _movement_log_data(); - active_minutes = 0; + // log data every five minutes, and reset the active_minutes count. + if ((date_time.unit.minute % 5) == 0) { + _movement_log_data(); + active_minutes = 0; + } } -#endif // update the DST offset cache every 30 minutes, since someplace in the world could change. if (date_time.unit.minute % 30 == 0) { @@ -519,38 +517,46 @@ void movement_set_alarm_enabled(bool value) { movement_state.alarm_enabled = value; } -void movement_enable_tap_detection_if_available(void) { -#ifdef HAS_ACCELEROMETER - // configure tap duration threshold and enable Z axis - lis2dw_configure_tap_threshold(0, 0, 12, LIS2DW_REG_TAP_THS_Z_Z_AXIS_ENABLE); - lis2dw_configure_tap_duration(10, 2, 2); +bool movement_enable_tap_detection_if_available(void) { + if (movement_state.has_lis2dw) { + // configure tap duration threshold and enable Z axis + lis2dw_configure_tap_threshold(0, 0, 12, LIS2DW_REG_TAP_THS_Z_Z_AXIS_ENABLE); + lis2dw_configure_tap_duration(10, 2, 2); - // ramp data rate up to 400 Hz and high performance mode - lis2dw_set_low_noise_mode(true); - lis2dw_set_data_rate(LIS2DW_DATA_RATE_HP_400_HZ); - lis2dw_set_mode(LIS2DW_MODE_HIGH_PERFORMANCE); + // ramp data rate up to 400 Hz and high performance mode + lis2dw_set_low_noise_mode(true); + lis2dw_set_data_rate(LIS2DW_DATA_RATE_HP_400_HZ); + lis2dw_set_mode(LIS2DW_MODE_HIGH_PERFORMANCE); - // Settling time (1 sample duration, i.e. 1/400Hz) - delay_ms(3); + // Settling time (1 sample duration, i.e. 1/400Hz) + delay_ms(3); - // enable tap detection on INT1/A3. - lis2dw_configure_int1(LIS2DW_CTRL4_INT1_SINGLE_TAP | LIS2DW_CTRL4_INT1_6D); - // and enable the cb_accelerometer_event interrupt callback, so we can catch tap events. - watch_register_interrupt_callback(HAL_GPIO_A3_pin(), cb_accelerometer_event, INTERRUPT_TRIGGER_RISING); -#endif + // enable tap detection on INT1/A3. + lis2dw_configure_int1(LIS2DW_CTRL4_INT1_SINGLE_TAP | LIS2DW_CTRL4_INT1_6D); + // and enable the cb_accelerometer_event interrupt callback, so we can catch tap events. + watch_register_interrupt_callback(HAL_GPIO_A3_pin(), cb_accelerometer_event, INTERRUPT_TRIGGER_RISING); + + return true; + } + + return false; } -void movement_disable_tap_detection_if_available(void) { -#ifdef HAS_ACCELEROMETER - // Ramp data rate back down to the usual lowest rate to save power. - lis2dw_set_low_noise_mode(false); - lis2dw_set_data_rate(LIS2DW_DATA_RATE_LOWEST); - lis2dw_set_mode(LIS2DW_MODE_LOW_POWER); - // disable the interrupt on INT1/A3... - eic_disable_interrupt(HAL_GPIO_A3_pin()); - // ...disable Z axis (not sure if this is needed, does this save power?)... - lis2dw_configure_tap_threshold(0, 0, 0, 0); -#endif +bool movement_disable_tap_detection_if_available(void) { + if (movement_state.has_lis2dw) { + // Ramp data rate back down to the usual lowest rate to save power. + lis2dw_set_low_noise_mode(false); + lis2dw_set_data_rate(LIS2DW_DATA_RATE_LOWEST); + lis2dw_set_mode(LIS2DW_MODE_LOW_POWER); + // disable the interrupt on INT1/A3... + eic_disable_interrupt(HAL_GPIO_A3_pin()); + // ...disable Z axis (not sure if this is needed, does this save power?)... + lis2dw_configure_tap_threshold(0, 0, 0, 0); + + return true; + } + + return false; } void app_init(void) { @@ -679,16 +685,11 @@ void app_setup(void) { watch_register_interrupt_callback(HAL_GPIO_BTN_LIGHT_pin(), cb_light_btn_interrupt, INTERRUPT_TRIGGER_BOTH); watch_register_interrupt_callback(HAL_GPIO_BTN_ALARM_pin(), cb_alarm_btn_interrupt, INTERRUPT_TRIGGER_BOTH); -#ifdef HAS_ACCELEROMETER -// gossamer doesn't include all the chip-specific constants, so we have to fake them here. -#ifndef EVSYS_ID_GEN_EIC_EXTINT_3 -#define EVSYS_ID_GEN_EIC_EXTINT_3 18 -#endif -#ifndef EVSYS_ID_USER_TC2_EVU -#define EVSYS_ID_USER_TC2_EVU 17 -#endif +#ifdef I2C_SERCOM watch_enable_i2c(); if (lis2dw_begin()) { + movement_state.has_lis2dw = true; + lis2dw_set_mode(LIS2DW_MODE_LOW_POWER); // select low power (not high performance) mode lis2dw_set_low_power_mode(LIS2DW_LP_MODE_1); // lowest power mode, 12-bit lis2dw_set_low_noise_mode(false); // low noise mode raises power consumption slightly; we don't need it @@ -717,6 +718,8 @@ void app_setup(void) { // watch_register_extwake_callback(HAL_GPIO_A4_pin(), cb_accelerometer_wake, false); lis2dw_enable_interrupts(); + } else { + watch_disable_i2c(); } #endif @@ -984,7 +987,6 @@ void cb_tick(void) { } } -#ifdef HAS_ACCELEROMETER void cb_accelerometer_event(void) { uint8_t int_src = lis2dw_get_interrupt_source(); @@ -1003,5 +1005,3 @@ void cb_accelerometer_wake(void) { // also: wake up! _movement_reset_inactivity_countdown(); } - -#endif diff --git a/movement.h b/movement.h index a0a12c2c..b7d52eb5 100644 --- a/movement.h +++ b/movement.h @@ -286,6 +286,9 @@ typedef struct { // temporary alarm enabled boolean, until we implement this in advisories bool alarm_enabled; + + // boolean set if accelerometer is detected + bool has_lis2dw; } movement_state_t; void movement_move_to_face(uint8_t watch_face_index); @@ -362,5 +365,5 @@ bool movement_alarm_enabled(void); void movement_set_alarm_enabled(bool value); // if the board has an accelerometer, these functions will enable or disable tap detection. -void movement_enable_tap_detection_if_available(void); -void movement_disable_tap_detection_if_available(void); +bool movement_enable_tap_detection_if_available(void); +bool movement_disable_tap_detection_if_available(void); diff --git a/movement_activity.c b/movement_activity.c index f5c20ec7..fe91e29a 100644 --- a/movement_activity.c +++ b/movement_activity.c @@ -27,8 +27,6 @@ #include "tc.h" #include "thermistor_driver.h" -#ifdef HAS_ACCELEROMETER - // RAM to stash the data points. movement_activity_data_point movement_activity_log[MOVEMENT_NUM_DATA_POINTS] = {0}; // the absolute number of data points logged @@ -74,5 +72,3 @@ movement_activity_data_point *movement_get_data_log(uint32_t *count) { *count = data_points; return movement_activity_log; } - -#endif diff --git a/movement_activity.h b/movement_activity.h index 358e6626..f1b256ff 100644 --- a/movement_activity.h +++ b/movement_activity.h @@ -24,8 +24,6 @@ #pragma once -#ifdef HAS_ACCELEROMETER - #include // Log 36 hours of data points. Each data point captures 5 minutes. @@ -48,5 +46,3 @@ void _movement_log_data(void); /// @param count is a pointer to a uint32_t. The absolute number of data points logged is returned by reference. /// You can assume that log[count % MOVEMENT_NUM_DATA_POINTS] is the latest data point, and work backwards from there. movement_activity_data_point *movement_get_data_log(uint32_t *count); - -#endif \ No newline at end of file diff --git a/watch-faces/complication/countdown_face.c b/watch-faces/complication/countdown_face.c index 95a7b40d..5314acea 100644 --- a/watch-faces/complication/countdown_face.c +++ b/watch-faces/complication/countdown_face.c @@ -218,13 +218,10 @@ void countdown_face_activate(void *context) { movement_request_tick_frequency(1); quick_ticks_running = false; -#if HAS_ACCELEROMETER - if (state->mode != cd_running) { + if (state->mode != cd_running && movement_enable_tap_detection_if_available()) { state->tap_detection_ticks = TAP_DETECTION_SECONDS; state->has_tapped_once = false; - movement_enable_tap_detection_if_available(); } -#endif } bool countdown_face_loop(movement_event_t event, void *context) { diff --git a/watch-faces/demo/accel_interrupt_count_face.c b/watch-faces/demo/accel_interrupt_count_face.c index 32b99255..dc9b5df1 100644 --- a/watch-faces/demo/accel_interrupt_count_face.c +++ b/watch-faces/demo/accel_interrupt_count_face.c @@ -29,8 +29,6 @@ #include "tc.h" #include "watch.h" -#ifdef HAS_ACCELEROMETER - // hacky: we're just tapping into Movement's global state. // we should make better API for this. extern uint8_t active_minutes; @@ -133,5 +131,3 @@ movement_watch_face_advisory_t accel_interrupt_count_face_advise(void *context) return retval; } - -#endif // HAS_ACCELEROMETER diff --git a/watch-faces/demo/accel_interrupt_count_face.h b/watch-faces/demo/accel_interrupt_count_face.h index 70b03dda..3361976c 100644 --- a/watch-faces/demo/accel_interrupt_count_face.h +++ b/watch-faces/demo/accel_interrupt_count_face.h @@ -35,8 +35,6 @@ #include "movement.h" #include "watch.h" -#ifdef HAS_ACCELEROMETER - typedef struct { uint8_t new_threshold; uint8_t threshold; @@ -56,5 +54,3 @@ movement_watch_face_advisory_t accel_interrupt_count_face_advise(void *context); accel_interrupt_count_face_resign, \ accel_interrupt_count_face_advise, \ }) - -#endif // HAS_ACCELEROMETER diff --git a/watch-faces/sensor/activity_logging_face.c b/watch-faces/sensor/activity_logging_face.c index 984d9a09..e6b586ae 100644 --- a/watch-faces/sensor/activity_logging_face.c +++ b/watch-faces/sensor/activity_logging_face.c @@ -30,8 +30,6 @@ #include "movement_activity.h" #include "watch_utility.h" -#ifdef HAS_ACCELEROMETER - static void _activity_logging_face_update_display(activity_logging_state_t *state, bool clock_mode_24h) { char buf[8]; uint32_t count = 0; @@ -164,5 +162,3 @@ bool activity_logging_face_loop(movement_event_t event, void *context) { void activity_logging_face_resign(void *context) { (void) context; } - -#endif diff --git a/watch-faces/sensor/activity_logging_face.h b/watch-faces/sensor/activity_logging_face.h index 0a0e3726..c2f3fcc6 100644 --- a/watch-faces/sensor/activity_logging_face.h +++ b/watch-faces/sensor/activity_logging_face.h @@ -26,8 +26,6 @@ #include "pins.h" -#ifdef HAS_ACCELEROMETER - /* * ACTIVITY LOGGING * @@ -77,5 +75,3 @@ movement_watch_face_advisory_t activity_logging_face_advise(void *context); activity_logging_face_resign, \ NULL, \ }) - -#endif // HAS_TEMPERATURE_SENSOR diff --git a/watch-library/shared/driver/thermistor_driver.c b/watch-library/shared/driver/thermistor_driver.c index 8a9b20d5..f8891bdd 100644 --- a/watch-library/shared/driver/thermistor_driver.c +++ b/watch-library/shared/driver/thermistor_driver.c @@ -27,9 +27,9 @@ #include "watch.h" #include "watch_utility.h" -#ifdef HAS_TEMPERATURE_SENSOR void thermistor_driver_enable(void) { +#ifdef HAS_TEMPERATURE_SENSOR // Enable the ADC peripheral, which we'll use to read the thermistor value. watch_enable_adc(); // Enable analog circuitry on the sense pin, which is tied to the thermistor resistor divider. @@ -39,9 +39,11 @@ void thermistor_driver_enable(void) { HAL_GPIO_TS_ENABLE_out(); // and make sure it's off. HAL_GPIO_TS_ENABLE_write(!THERMISTOR_ENABLE_VALUE); +#endif } void thermistor_driver_disable(void) { +#ifdef HAS_TEMPERATURE_SENSOR // Disable the ADC peripheral. watch_disable_adc(); // Disable analog circuitry on the sense pin to save power. @@ -49,9 +51,11 @@ void thermistor_driver_disable(void) { HAL_GPIO_TEMPSENSE_off(); // Disable the enable pin's output circuitry. HAL_GPIO_TS_ENABLE_off(); +#endif } float thermistor_driver_get_temperature(void) { +#ifdef HAS_TEMPERATURE_SENSOR // set the enable pin to the level that powers the thermistor circuit. HAL_GPIO_TS_ENABLE_write(THERMISTOR_ENABLE_VALUE); // get the sense pin level @@ -60,6 +64,7 @@ float thermistor_driver_get_temperature(void) { HAL_GPIO_TS_ENABLE_write(!THERMISTOR_ENABLE_VALUE); return watch_utility_thermistor_temperature(value, THERMISTOR_HIGH_SIDE, THERMISTOR_B_COEFFICIENT, THERMISTOR_NOMINAL_TEMPERATURE, THERMISTOR_NOMINAL_RESISTANCE, THERMISTOR_SERIES_RESISTANCE); +#else + return (float) 0xFFFFFFFF; +#endif } - -#endif // HAS_TEMPERATURE_SENSOR \ No newline at end of file diff --git a/watch-library/shared/driver/thermistor_driver.h b/watch-library/shared/driver/thermistor_driver.h index e929e805..4abce949 100644 --- a/watch-library/shared/driver/thermistor_driver.h +++ b/watch-library/shared/driver/thermistor_driver.h @@ -26,8 +26,6 @@ #include "pins.h" -#ifdef HAS_TEMPERATURE_SENSOR - // TODO: Do these belong in movement_config.h? In settings we can set on the watch? In an EEPROM configuration area? // Think on this. [joey 11/22] #define THERMISTOR_ENABLE_VALUE (false) @@ -40,5 +38,3 @@ void thermistor_driver_enable(void); void thermistor_driver_disable(void); float thermistor_driver_get_temperature(void); - -#endif // HAS_TEMPERATURE_SENSOR