diff --git a/legacy/watch_faces/clock/close_enough_clock_face.c b/legacy/watch_faces/clock/close_enough_clock_face.c index 98a8e703..99dec5c4 100644 --- a/legacy/watch_faces/clock/close_enough_clock_face.c +++ b/legacy/watch_faces/clock/close_enough_clock_face.c @@ -109,9 +109,7 @@ bool close_enough_clock_face_loop(movement_event_t event, void *context) { // check the battery voltage once a day... if (date_time.unit.day != state->last_battery_check) { state->last_battery_check = date_time.unit.day; - watch_enable_adc(); uint16_t voltage = watch_get_vcc_voltage(); - watch_disable_adc(); // 2.2 volts will happen when the battery has maybe 5-10% remaining? // we can refine this later. state->battery_low = (voltage < 2200); diff --git a/legacy/watch_faces/clock/minute_repeater_decimal_face.c b/legacy/watch_faces/clock/minute_repeater_decimal_face.c index 9f5eb43c..f971d560 100644 --- a/legacy/watch_faces/clock/minute_repeater_decimal_face.c +++ b/legacy/watch_faces/clock/minute_repeater_decimal_face.c @@ -115,9 +115,7 @@ bool minute_repeater_decimal_face_loop(movement_event_t event, void *context) { // check the battery voltage once a day... if (date_time.unit.day != state->last_battery_check) { state->last_battery_check = date_time.unit.day; - watch_enable_adc(); uint16_t voltage = watch_get_vcc_voltage(); - watch_disable_adc(); // 2.2 volts will happen when the battery has maybe 5-10% remaining? // we can refine this later. state->battery_low = (voltage < 2200); diff --git a/legacy/watch_faces/clock/repetition_minute_face.c b/legacy/watch_faces/clock/repetition_minute_face.c index b475b45e..0b1daf21 100644 --- a/legacy/watch_faces/clock/repetition_minute_face.c +++ b/legacy/watch_faces/clock/repetition_minute_face.c @@ -100,9 +100,7 @@ bool repetition_minute_face_loop(movement_event_t event, void *context) { // check the battery voltage once a day... if (date_time.unit.day != state->last_battery_check) { state->last_battery_check = date_time.unit.day; - watch_enable_adc(); uint16_t voltage = watch_get_vcc_voltage(); - watch_disable_adc(); // 2.2 volts will happen when the battery has maybe 5-10% remaining? // we can refine this later. state->battery_low = (voltage < 2200); diff --git a/legacy/watch_faces/clock/simple_clock_bin_led_face.c b/legacy/watch_faces/clock/simple_clock_bin_led_face.c index 527b1cd1..a3f51242 100644 --- a/legacy/watch_faces/clock/simple_clock_bin_led_face.c +++ b/legacy/watch_faces/clock/simple_clock_bin_led_face.c @@ -126,9 +126,7 @@ bool simple_clock_bin_led_face_loop(movement_event_t event, void *context) { // check the battery voltage once a day... if (date_time.unit.day != state->last_battery_check) { state->last_battery_check = date_time.unit.day; - watch_enable_adc(); uint16_t voltage = watch_get_vcc_voltage(); - watch_disable_adc(); // 2.2 volts will happen when the battery has maybe 5-10% remaining? // we can refine this later. state->battery_low = (voltage < 2200); diff --git a/legacy/watch_faces/clock/weeknumber_clock_face.c b/legacy/watch_faces/clock/weeknumber_clock_face.c index 3a153e18..5bfab847 100644 --- a/legacy/watch_faces/clock/weeknumber_clock_face.c +++ b/legacy/watch_faces/clock/weeknumber_clock_face.c @@ -82,9 +82,7 @@ bool weeknumber_clock_face_loop(movement_event_t event, void *context) { // check the battery voltage once a day... if (date_time.unit.day != state->last_battery_check) { state->last_battery_check = date_time.unit.day; - watch_enable_adc(); uint16_t voltage = watch_get_vcc_voltage(); - watch_disable_adc(); // 2.2 volts will happen when the battery has maybe 5-10% remaining? // we can refine this later. state->battery_low = (voltage < 2200); diff --git a/watch-faces/clock/clock_face.c b/watch-faces/clock/clock_face.c index 78d9d700..73e1ecfa 100644 --- a/watch-faces/clock/clock_face.c +++ b/watch-faces/clock/clock_face.c @@ -98,9 +98,7 @@ static void clock_check_battery_periodically(clock_state_t *state, watch_date_ti state->last_battery_check = date_time.unit.day; - watch_enable_adc(); uint16_t voltage = watch_get_vcc_voltage(); - watch_disable_adc(); state->battery_low = voltage < CLOCK_FACE_LOW_BATTERY_VOLTAGE_THRESHOLD; diff --git a/watch-faces/sensor/voltage_face.c b/watch-faces/sensor/voltage_face.c index bb0461bd..320f30f9 100644 --- a/watch-faces/sensor/voltage_face.c +++ b/watch-faces/sensor/voltage_face.c @@ -28,9 +28,7 @@ #include "watch.h" static void _voltage_face_update_display(void) { - watch_enable_adc(); float voltage = (float)watch_get_vcc_voltage() / 1000.0; - watch_disable_adc(); watch_display_text_with_fallback(WATCH_POSITION_TOP_LEFT, "BAT", "BA"); watch_display_float_with_best_effort(voltage, " V"); diff --git a/watch-library/hardware/watch/watch_adc.c b/watch-library/hardware/watch/watch_adc.c index 11cc318c..f85e081b 100644 --- a/watch-library/hardware/watch/watch_adc.c +++ b/watch-library/hardware/watch/watch_adc.c @@ -67,6 +67,11 @@ void _watch_set_analog_reference_voltage(uint8_t reference) { uint16_t watch_get_vcc_voltage(void) { // stash the previous reference so we can restore it when we're done. uint8_t oldref = ADC->REFCTRL.bit.REFSEL; + // same with the previous state of the ADC + bool adc_was_disabled = !adc_is_enabled(); + + // enable the ADC if needed + if (adc_was_disabled) watch_enable_adc(); // if we weren't already using the internal reference voltage, select it now. if (oldref != ADC_REFCTRL_REFSEL_INTREF_Val) _watch_set_analog_reference_voltage(ADC_REFCTRL_REFSEL_INTREF_Val); @@ -77,6 +82,9 @@ uint16_t watch_get_vcc_voltage(void) { // restore the old reference, if needed. if (oldref != ADC_REFCTRL_REFSEL_INTREF_Val) _watch_set_analog_reference_voltage(oldref); + // and restore the ADC to its previous state + if (adc_was_disabled) watch_disable_adc(); + return (uint16_t)((raw_val * 1000) / (1024 * 1 << ADC->AVGCTRL.bit.SAMPLENUM)); } diff --git a/watch-library/hardware/watch/watch_private.c b/watch-library/hardware/watch/watch_private.c index 0eb0cb45..03091c09 100644 --- a/watch-library/hardware/watch/watch_private.c +++ b/watch-library/hardware/watch/watch_private.c @@ -51,9 +51,7 @@ void _watch_init(void) { while(!SUPC->STATUS.bit.VREGRDY); // wait for voltage regulator to become ready // check the battery voltage... - watch_enable_adc(); uint16_t battery_voltage = watch_get_vcc_voltage(); - watch_disable_adc(); // ...because we can enable the more efficient low power regulator if the system voltage is > 2.5V // still, enable LPEFF only if the battery voltage is comfortably above this threshold. if (battery_voltage >= 2700) { diff --git a/watch-library/shared/watch/watch_adc.h b/watch-library/shared/watch/watch_adc.h index b2685da9..c4b4bdb0 100644 --- a/watch-library/shared/watch/watch_adc.h +++ b/watch-library/shared/watch/watch_adc.h @@ -53,7 +53,8 @@ void watch_enable_analog_input(const uint16_t pin); uint16_t watch_get_analog_pin_level(const uint16_t pin); /** @brief Returns the voltage of the VCC supply in millivolts (i.e. 3000 mV == 3.0 V). If running on - * a coin cell, this will be the battery voltage. + * a coin cell, this will be the battery voltage. If the ADC is not running when this function + * is called, it enabled the ADC briefly, and returns it to the off state. * @details Unlike other ADC functions, this function does not return a raw value from the ADC, but * rather scales it to an actual number of millivolts. This is because the ADC doesn't let * us measure VCC per se; it instead lets us measure VCC / 4, and we choose to measure it