summaryrefslogtreecommitdiffstats
path: root/watch-library/watch
diff options
context:
space:
mode:
Diffstat (limited to 'watch-library/watch')
-rw-r--r--watch-library/watch/watch.c15
-rw-r--r--watch-library/watch/watch.h8
-rw-r--r--watch-library/watch/watch_private.c21
3 files changed, 44 insertions, 0 deletions
diff --git a/watch-library/watch/watch.c b/watch-library/watch/watch.c
index 059c2a93..6196b1f3 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 8c207ddb..5cd45a6c 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 88d80be9..8dfd10f9 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);