From b22915431babce4264a2e3d333939894e5a60c0f Mon Sep 17 00:00:00 2001 From: Joey Castillo Date: Tue, 31 Aug 2021 18:47:35 -0400 Subject: [PATCH] add method for detecting low battery --- watch-library/watch/watch.c | 15 +++++++++++++++ watch-library/watch/watch.h | 8 ++++++++ watch-library/watch/watch_private.c | 21 +++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/watch-library/watch/watch.c b/watch-library/watch/watch.c index 059c2a9..6196b1f 100644 --- a/watch-library/watch/watch.c +++ b/watch-library/watch/watch.c @@ -35,3 +35,18 @@ #include "watch_uart.c" #include "watch_deepsleep.c" #include "watch_private.c" + +bool battery_is_low = false; + +// receives interrupts from MCLK, OSC32KCTRL, OSCCTRL, PAC, PM, SUPC and TAL, whatever that is. +void SYSTEM_Handler(void) { + if (SUPC->INTFLAG.bit.BOD33DET) { + battery_is_low = true; + SUPC->INTENCLR.bit.BOD33DET = 1; + SUPC->INTFLAG.reg &= ~SUPC_INTFLAG_BOD33DET; + } +} + +bool watch_is_battery_low() { + return battery_is_low; +} diff --git a/watch-library/watch/watch.h b/watch-library/watch/watch.h index 8c207dd..5cd45a6 100644 --- a/watch-library/watch/watch.h +++ b/watch-library/watch/watch.h @@ -65,4 +65,12 @@ #include "watch_private.h" +/** @brief Returns true when the battery voltage dips below 2.5V. + * @details A CR2016 battery will have a nominal voltage between 2.9 and 3 volts for most of its lifespan. Once the battery + * discharges to about 60%, the voltage will drift slightly lower; this may manifest as a dimmer LED. By the time + * the battery voltage has fallen to 2.5 volts, it will have probably less than 10% of its capacity remaining, and + * you can expect the voltage to drop relatively quickly as the battery dies. + */ +bool watch_is_battery_low(); + #endif /* WATCH_H_ */ \ No newline at end of file diff --git a/watch-library/watch/watch_private.c b/watch-library/watch/watch_private.c index 88d80be..8dfd10f 100644 --- a/watch-library/watch/watch_private.c +++ b/watch-library/watch/watch_private.c @@ -32,6 +32,27 @@ void _watch_init() { SUPC->VREG.bit.SEL = 1; while(!SUPC->STATUS.bit.VREGRDY); + // set up the brownout detector (low battery warning) + NVIC_DisableIRQ(SYSTEM_IRQn); + NVIC_ClearPendingIRQ(SYSTEM_IRQn); + NVIC_EnableIRQ(SYSTEM_IRQn); + SUPC->BOD33.bit.ENABLE = 0; // BOD33 must be disabled to change its configuration + SUPC->BOD33.bit.VMON = 0; // Monitor VDD in active and standby mode + SUPC->BOD33.bit.ACTCFG = 1; // Enable sampling mode when active + SUPC->BOD33.bit.RUNSTDBY = 1; // Enable sampling mode in standby + SUPC->BOD33.bit.STDBYCFG = 1; // Run in standby + SUPC->BOD33.bit.RUNBKUP = 1; // Also run in backup mode + SUPC->BOD33.bit.PSEL = 0xB; // Check battery level every 4 seconds + SUPC->BOD33.bit.LEVEL = 31; // Detect brownout at 2.5V (1.445V + level * 34mV) + SUPC->BOD33.bit.BKUPLEVEL = 31; // Detect same level in backup mode + SUPC->BOD33.bit.ACTION = 0x2; // Generate an interrupt when BOD33 is triggered + SUPC->BOD33.bit.HYST = 0; // Disable hysteresis + while(!SUPC->STATUS.bit.B33SRDY); + + // Enable interrupt on BOD33 detect + SUPC->INTENSET.bit.BOD33DET = 1; + SUPC->BOD33.bit.ENABLE = 1; + // External wake depends on RTC; calendar is a required module. CALENDAR_0_init(); calendar_enable(&CALENDAR_0);