summaryrefslogtreecommitdiffstats
path: root/watch-library
diff options
context:
space:
mode:
authorJoey Castillo <jose.castillo@gmail.com>2021-10-20 13:45:22 -0400
committerJoey Castillo <jose.castillo@gmail.com>2021-10-20 13:45:22 -0400
commit38a2dff23491c4b22a8e55ffd6d096a198857c9f (patch)
tree2d3f87c41f0dbea12d2122defb2bf456acc7467c /watch-library
parent1020dd78981e0d4b4f20399aa5e76ea7d37beec6 (diff)
downloadSensor-Watch-38a2dff23491c4b22a8e55ffd6d096a198857c9f.tar.gz
Sensor-Watch-38a2dff23491c4b22a8e55ffd6d096a198857c9f.tar.bz2
Sensor-Watch-38a2dff23491c4b22a8e55ffd6d096a198857c9f.zip
more accurate names for deep sleep and shallow sleep modes
Diffstat (limited to 'watch-library')
-rwxr-xr-xwatch-library/main.c6
-rw-r--r--watch-library/watch/watch_app.h44
-rw-r--r--watch-library/watch/watch_deepsleep.c35
-rw-r--r--watch-library/watch/watch_deepsleep.h118
-rw-r--r--watch-library/watch/watch_rtc.h4
-rw-r--r--watch-library/watch/watch_slcd.h6
6 files changed, 133 insertions, 80 deletions
diff --git a/watch-library/main.c b/watch-library/main.c
index db602a34..1fe751ef 100755
--- a/watch-library/main.c
+++ b/watch-library/main.c
@@ -57,7 +57,7 @@ int main(void) {
// Ideally we should check if the TAMPER or CMP0 (alarm) flags are set.
if (_watch_rtc_is_enabled()) {
// User code. Give the application a chance to restore state from backup registers.
- app_wake_from_deep_sleep();
+ app_wake_from_backup();
// disable the tamper interrupt and clear the tamper bit
hri_rtcmode0_clear_INTEN_TAMPER_bit(RTC);
@@ -75,9 +75,9 @@ int main(void) {
bool can_sleep = app_loop();
if (can_sleep && !usb_enabled) {
- app_prepare_for_sleep();
+ app_prepare_for_standby();
sleep(4);
- app_wake_from_sleep();
+ app_wake_from_standby();
}
}
diff --git a/watch-library/watch/watch_app.h b/watch-library/watch/watch_app.h
index 00a6a610..56b9bfd3 100644
--- a/watch-library/watch/watch_app.h
+++ b/watch-library/watch/watch_app.h
@@ -33,7 +33,7 @@
*
* 1. Your app_init() function is called.
* - This method should only be used to set your initial application state.
- * 2. If your app is waking from BACKUP, app_wake_from_deep_sleep() is called.
+ * 2. If your app is waking from BACKUP, app_wake_from_backup() is called.
* - If you saved state in the RTC's backup registers, you can restore it here.
* 3. Your app_setup() method is called.
* - You may wish to enable some functionality and peripherals here.
@@ -43,11 +43,11 @@
* - Return true if your app is prepared to enter STANDBY mode.
* 5. This step differs depending on the value returned by app_loop:
* - If you returned false, execution resumes at (4).
- * - If you returned true, app_prepare_for_sleep() is called; execution moves on to (6).
- * 6. The microcontroller enters the STANDBY sleep mode.
+ * - If you returned true, app_prepare_for_standby() is called; execution moves on to (6).
+ * 6. The microcontroller enters STANDBY mode.
* - No user code will run, and the watch will enter a low power mode.
* - The watch will remain in this state until an interrupt wakes it.
- * 7. Once woken from STANDBY, your app_wake_from_sleep() function is called.
+ * 7. Once woken from STANDBY, your app_wake_from_standby() function is called.
* - After this, execution resumes at (4).
*/
/// @{
@@ -57,11 +57,11 @@
*/
void app_init();
-/** @brief A function you will implement to wake from deep sleep mode. The app_wake_from_deep_sleep function is only
- * called if your app is waking from the ultra-low power BACKUP sleep mode. You may have chosen to store some
- * state in the RTC's backup registers prior to entering this mode. You may restore that state here.
+/** @brief A function you will implement to wake from BACKUP mode, which wipes the system's RAM, and with it, your
+ * application's state. You may have chosen to store some important application state in the RTC's backup
+ * registers prior to entering this mode. You may restore that state here.
*/
-void app_wake_from_deep_sleep();
+void app_wake_from_backup();
/** @brief A function you will implement to set up your application. The app_setup function is like setup() in Arduino.
* It is called once when the program begins. You should set pin modes and enable any peripherals you want to
@@ -74,12 +74,12 @@ void app_wake_from_deep_sleep();
void app_setup();
/** @brief A function you will implement to serve as the app's main run loop. This method will be called repeatedly,
- or if you enter STANDBY sleep mode, as soon as the device wakes from sleep.
- * @return You should return true if your app is prepared to enter STANDBY sleep mode. If you return false, your
- * app's app_loop method will be called again immediately. Note that in STANDBY mode, the watch will consume
- * only about 95 microamperes of power, whereas if you return false and keep the app awake, it will consume
- * about 355 microamperes. This is the difference between months of battery life and days. As much as
- * possible, you should limit the amount of time your app spends awake.
+ or if you enter STANDBY mode, as soon as the device wakes from sleep.
+ * @return You should return true if your app is prepared to enter STANDBY mode. If you return false, your app's
+ * app_loop method will be called again immediately. Note that in STANDBY mode, the watch will consume only
+ * about 95 microamperes of power, whereas if you return false and keep the app awake, it will consume about
+ * 355 microamperes. This is the difference between months of battery life and days. As much as possible,
+ * you should limit the amount of time your app spends awake.
* @note Only the RTC, the segment LCD controller and the external interrupt controller run in STANDBY mode. If you
* are using, e.g. the PWM function to set a custom LED color, you should return false here until you are
* finished with that operation. Note however that the peripherals will continue running after waking up,
@@ -88,21 +88,21 @@ void app_setup();
*/
bool app_loop();
-/** @brief A function you will implement to prepare to enter STANDBY sleep mode. The app_prepare_for_sleep function is
- * called before the watch goes into the STANDBY sleep mode. In STANDBY mode, most peripherals are shut down,
- * and no code will run until the watch receives an interrupt (generally either the 1Hz tick or a press on one
- * of the buttons).
+/** @brief A function you will implement to prepare to enter STANDBY mode. The app_prepare_for_standby function is
+ * called after your app_loop function returns true, and just before the watch enters STANDBY mode. In this
+ * mode most peripherals are shut down, and no code will run until the watch receives an interrupt (generally
+ * either the 1Hz tick or a press on one of the buttons).
* @note If you are PWM'ing the LED or playing a sound on the buzzer, the TC/TCC peripherals that drive those operations
* will not run in STANDBY. BUT! the output pins will retain the state they had when entering standby. This means
* you could end up entering standby with an LED on and draining power, or with a DC potential across the piezo
* buzzer that could damage it if left in this state. If your app_loop does not prevent sleep during these
- * activities, you should make sure to disable these outputs in app_prepare_for_sleep.
+ * activities, you should make sure to disable these outputs in app_prepare_for_standby.
*/
-void app_prepare_for_sleep();
+void app_prepare_for_standby();
-/** @brief A method you will implement to configure the app after waking from STANDBY sleep mode.
+/** @brief A method you will implement to configure the app after waking from STANDBY mode.
*/
-void app_wake_from_sleep();
+void app_wake_from_standby();
/// @}
#endif
diff --git a/watch-library/watch/watch_deepsleep.c b/watch-library/watch/watch_deepsleep.c
index 9ca53db0..8120617b 100644
--- a/watch-library/watch/watch_deepsleep.c
+++ b/watch-library/watch/watch_deepsleep.c
@@ -151,12 +151,7 @@ void _watch_disable_all_peripherals_except_slcd() {
MCLK->APBCMASK.reg &= ~MCLK_APBCMASK_SERCOM3;
}
-void watch_enter_shallow_sleep(bool display_on) {
- if (!display_on) {
- slcd_sync_deinit(&SEGMENT_LCD_0);
- hri_mclk_clear_APBCMASK_SLCD_bit(SLCD);
- }
-
+void watch_enter_sleep_mode() {
// disable all other peripherals
_watch_disable_all_peripherals_except_slcd();
@@ -178,15 +173,19 @@ void watch_enter_shallow_sleep(bool display_on) {
// call app_setup so the app can re-enable everything we disabled.
app_setup();
- // and call app_wake_from_sleep (since main won't have a chance to do it)
- app_wake_from_sleep();
+ // and call app_wake_from_standby (since main won't have a chance to do it)
+ app_wake_from_standby();
}
-void watch_enter_deep_sleep() {
- // this will not work on the current silicon revision, but I said in the documentation that we do it.
- // so let's do it!
- watch_register_extwake_callback(BTN_ALARM, NULL, true);
+void watch_enter_deep_sleep_mode() {
+ // identical to sleep mode except we disable the LCD first.
+ slcd_sync_deinit(&SEGMENT_LCD_0);
+ hri_mclk_clear_APBCMASK_SLCD_bit(SLCD);
+
+ watch_enter_sleep_mode();
+}
+void watch_enter_backup_mode() {
watch_rtc_disable_all_periodic_callbacks();
_watch_disable_all_peripherals_except_slcd();
slcd_sync_deinit(&SEGMENT_LCD_0);
@@ -196,3 +195,15 @@ void watch_enter_deep_sleep() {
// go into backup sleep mode (5). when we exit, the reset controller will take over.
sleep(5);
}
+
+// deprecated
+void watch_enter_shallow_sleep(bool display_on) {
+ if (display_on) watch_enter_sleep_mode();
+ else watch_enter_deep_sleep_mode();
+}
+
+// deprecated
+void watch_enter_deep_sleep() {
+ watch_register_extwake_callback(BTN_ALARM, NULL, true);
+ watch_enter_backup_mode();
+}
diff --git a/watch-library/watch/watch_deepsleep.h b/watch-library/watch/watch_deepsleep.h
index 84825f00..a453e763 100644
--- a/watch-library/watch/watch_deepsleep.h
+++ b/watch-library/watch/watch_deepsleep.h
@@ -32,26 +32,54 @@ extern ext_irq_cb_t btn_alarm_callback;
extern ext_irq_cb_t a2_callback;
extern ext_irq_cb_t a4_callback;
-/** @addtogroup deepsleep Deep Sleep Control
- * @brief This section covers functions related to preparing for and entering BACKUP mode, the
- * deepest sleep mode available on the SAM L22
+/** @addtogroup deepsleep Sleep Control
+ * @brief This section covers functions related to the various sleep modes available to the watch,
+ * including Sleep, Deep Sleep, and BACKUP mode.
+ * @details These terms changed meaning a bit over the course of development; if you are coming
+ * to this documentation after having worked with an earlier version of the library,
+ * these definitions should clarify the terminology. Terms in all caps are modes of the
+ * SAM L22; terms in Title Case are specific implementations in this library.
+ * - ACTIVE mode is the mode the SAM L22 is in when both the main clock and the CPU are
+ * running. It is the most power-hungry mode. If you ever call delay_ms to wait a beat,
+ * the watch will remain in ACTIVE mode while taking that delay. In addition, whenever
+ * your `app_loop` function returns false, the device will remain in ACTIVE mode and
+ * call your `app_loop` function again.
+ * - STANDBY mode turns off the main clock and halts the CPU. Since the PWM driver is
+ * run from the main clock, it also stops the buzzer and any dimming of the LEDs.
+ * In this mode, the watch can wake from any interrupt source. Whenever your `app_loop`
+ * function returns true, the watch enters STANDBY mode until the next tick or other
+ * interrupt. This mode uses much less power than ACTIVE mode.
+ * - Sleep Mode is a special case of STANDBY mode. In this mode, the watch turns off
+ * almost all peripherals (including the external interrupt controller), and disables
+ * all pins except for the external wake pins. In this mode the watch can only wake
+ * from the RTC alarm interrupt or an external wake pin (A2, A4 or the alarm button),
+ * but the display remains on and your app's state is retained. You can enter this
+ * mode by calling `watch_enter_sleep_mode`. It consumes an order of magnitude less
+ * power than STANDBY mode.
+ * - Deep Sleep Mode is identical to sleep mode, but it also turns off the LCD to save
+ * a bit more power. You can enter this mode by calling `watch_enter_deep_sleep_mode`.
+ * - BACKUP mode is the lowest possible power mode on the SAM L22. It turns off all pins
+ * and peripherals except for the RTC. It also turns off the RAM, obliterating your
+ * application's state. The only way to wake from this mode is by setting an external
+ * wake interrupt on pin A2 or pin A4, and when you do wake it will be much like a
+ * wake from reset. You can enter this mode by calling `watch_enter_backup_mode`.
*/
/// @{
/** @brief Registers a callback on one of the RTC's external wake pins, which can wake the device
- * from deep sleep (aka BACKUP) mode.
+ * from Sleep, Deep Sleep and BACKUP modes (but see warning re: BACKUP mode).
* @param pin Either pin BTN_ALARM, A2, or A4. These are the three external wake pins. If the pin
* is BTN_ALARM, this function also enables an internal pull down on that pin.
- * @param callback The callback to be called if this pin triggers outside of deep sleep mode. If
- * this is NULL, no callback will be called even in normal mode, but the interrupt
- * will still be enabled so that it can wake from deep sleep or backup mode.
+ * @param callback The callback to be called if this pin triggers outside of BACKUP mode. If this is
+ * NULL, no callback will be called even in normal modes, but the interrupt will
+ * still be enabled so that it can wake the device.
* @param level The level you wish to scan for: true for rising, false for falling. Note that you
* cannot scan for both rising and falling edges like you can with the external interrupt
* pins; with the external wake interrupt, you can only get one or the other.
- * @note When in normal or STANDBY mode, this will function much like a standard external interrupt
- * situation: these pins will wake from standby, and your callback will be called. However,
- * if the device enters deep sleep and one of these pins wakes the device, your callback
- * WILL NOT be called, as the device is basically waking from reset at that point.
+ * @note When in ACTIVE, STANDBY and Sleep / Deep sleep modes, this will function much like a standard
+ * external interrupt situation: these pins will wake the device, and your callback will be
+ * called. However, if the device enters BACKUP mode and one of these pins wakes the device, your
+ * callback WILL NOT be called, as the device is basically waking from reset at that point.
* @warning As of the current SAM L22 silicon revision (rev B), the BTN_ALARM pin cannot wake the
* device from BACKUP mode. You can still use this function to register a BTN_ALARM interrupt
* in normal or deep sleep mode, but to wake from BACKUP, you will need to use pin A2 or A4.
@@ -59,59 +87,73 @@ extern ext_irq_cb_t a4_callback;
void watch_register_extwake_callback(uint8_t pin, ext_irq_cb_t callback, bool level);
/** @brief Unregisters the RTC interrupt on one of the EXTWAKE pins. This will prevent a value change on
- * one of these pins from waking the device from shallow and deep sleep modes.
+ * one of these pins from waking the device.
* @param pin Either pin BTN_ALARM, A2, or A4. If the pin is BTN_ALARM, this function DOES NOT disable
* the internal pull down on that pin.
*/
void watch_disable_extwake_interrupt(uint8_t pin);
-/** @brief Stores data in one of the RTC's backup registers, which retain their data in deep sleep mode.
+/** @brief Stores data in one of the RTC's backup registers, which retain their data in BACKUP mode.
* @param data An unsigned 32 bit integer with the data you wish to store.
* @param reg A register from 0-7.
*/
void watch_store_backup_data(uint32_t data, uint8_t reg);
-/** @brief Gets 32 bits of data from the RTC's backup register.
+/** @brief Gets 32 bits of data from the RTC's BACKUP register.
* @param reg A register from 0-7.
* @return An unsigned 32 bit integer with the from the backup register.
*/
uint32_t watch_get_backup_data(uint8_t reg);
-/** @brief Enters a shallow sleep mode by disabling all pins and peripherals except the RTC and (optionally)
- * the LCD. You can wake from this mode by pressing the ALARM button, if you have an registered an
- * external wake callback on the ALARM button. When your app wakes from this shallow sleep mode, your
- * app_setup method will be called, since this function will have disabled things you set up.
- * @param display_on if true, leaves the LCD on to display whatever content was on-screen. If false, disables
- * the segment LCD controller for additional power savings.
- * @details This shallow sleep mode is not the lowest power mode available (see watch_enter_deep_sleep), but
- * it has the benefit of retaining your application state and being able to wake from the ALARM button.
- * It also provides an option for displaying a message to the user when asleep. Note that whether you
- * want to wake from the ALARM button, the A2 RTC interrupt or the A4 interrupt, you must configure
- * this by calling watch_register_extwake_callback first.
+/** @brief enters Sleep Mode by disabling all pins and peripherals except the RTC and the LCD.
+ * @details This sleep mode is not the lowest power mode available, but it has the benefit of allowing you
+ * to display a message to the user while asleep. You can also set an alarm interrupt to wake at a
+ * configfurable interval (every minute, hour or day) to update the display. You can wake from this
+ * mode by pressing the ALARM button, if you registered an extwake callback on the ALARM button.
+ * Also note that when your app wakes from this sleep mode, your app_setup method will be called
+ * again, since this function will have disabled things you set up there.
*
- * Power consumption in shallow sleep mode varies a bit with the battery voltage and the temperature,
- * but at 3 V and 25~30° C you can roughly estimate:
- * * < 12µA current draw with the LCD controller on
- * * < 6µA current draw with the LCD controller off
+ * Note that to wake from either the ALARM button, the A2 interrupt or the A4 interrupt, you
+ * must first configure this by calling watch_register_extwake_callback.
+ *
+ * You can estimate the power consumption of this mode to be on the order of 30 microwatts
+ * (about 10 µA at 3 V).
*/
-void watch_enter_shallow_sleep(bool display_on);
+void watch_enter_sleep_mode();
+
+/** @brief enters Deep Sleep Mode by disabling all pins and peripherals except the RTC.
+ * @details Short of BACKUP mode, this is the lowest power mode you can enter while retaining your
+ * application state (and the ability to wake with the alarm button). Just note that the display
+ * will be completely off, so you should document to the user of your application that they will
+ * need to press the alarm button to wake the device, or use a sensor board with support for
+ * an external wake pin.
+ *
+ * All notes from watch_enter_sleep_mode apply here, except for power consumption. You can estimate
+ * the power consumption of this mode to be on the order of 12 microwatts (about 4µA at 3 V).
+ */
+void watch_enter_deep_sleep_mode();
/** @brief Enters the SAM L22's lowest-power mode, BACKUP.
- * @details This function does some housekeeping before entering BACKUP mode. It first disables all
- * peripherals except for the RTC, and disables the tick interrupt (since that would wake
- * us up from deep sleep). It also sets an external wake source on the ALARM button, if one
- * was not already set. If you wish to wake from another source, such as one of the external
- * wake interrupt pins on the 9-pin connector, set that up prior to calling this function.
+ * @details This function does some housekeeping before entering BACKUP mode. It first disables all pins
+ * and peripherals except for the RTC, and disables the tick interrupt (since that would wake
+ * us up from BACKUP mode). Once again, if you wish to wake from the A2 or the A4 interrupt,
+ * you must first configure this by calling watch_register_extwake_callback.
* @note If you have a callback set for an external wake interrupt, it will be called if triggered while
- * in ACTIVE, IDLE or STANDBY modes, but it *will not be called* when waking from BACKUP.
- * Waking from backup is effectively like waking from reset, except that your @ref
- * app_wake_from_deep_sleep function will be called.
+ * in ACTIVE, STANDBY, Sleep and Deep Sleep modes, but it *will not be called* when waking from
+ * BACKUP mode. Waking from backup is effectively like waking from reset, except that your
+ * @ref app_wake_from_backup function will be called.
* @warning On current revisions of the SAM L22 silicon, the ALARM_BTN pin (PA02 RTC/IN2) cannot wake
* the device from deep sleep mode. There is an errata note (Reference: 15010) that says that
* due to a silicon bug, RTC/IN2 is not functional in BACKUP. As a result, you should not call
* this function unless you have a device on the nine-pin connector with an external interrupt
* on pin A2 or A4 (i.e. an accelerometer with an interrupt pin).
*/
+void watch_enter_backup_mode();
+
+__attribute__((deprecated("Use watch_enter_sleep_mode or watch_enter_deep_sleep_mode instead")))
+void watch_enter_shallow_sleep(bool display_on);
+
+__attribute__((deprecated("Use watch_enter_backup_mode instead")))
void watch_enter_deep_sleep();
/// @}
#endif
diff --git a/watch-library/watch/watch_rtc.h b/watch-library/watch/watch_rtc.h
index 1776a712..7ddd7483 100644
--- a/watch-library/watch/watch_rtc.h
+++ b/watch-library/watch/watch_rtc.h
@@ -88,8 +88,8 @@ watch_date_time watch_rtc_get_date_time();
* @param alarm_time The time that you wish to match. The date is currently ignored.
* @param mask One of the values in watch_rtc_alarm_match indicating which values to check.
* @details The alarm interrupt is a versatile tool for scheduling events in the future, especially since it can
- * wake the device from both shallow and deep sleep modes. The key to its versatility is the mask
- * parameter. Suppose we set an alarm for midnight, 00:00:00.
+ * wake the device from all sleep modes. The key to its versatility is the mask parameter.
+ * Suppose we set an alarm for midnight, 00:00:00.
* * if mask is ALARM_MATCH_SS, the alarm will fire every minute when the clock ticks to seconds == 0.
* * with ALARM_MATCH_MMSS, the alarm will once an hour, at the top of each hour.
* * with ALARM_MATCH_HHMMSS, the alarm will fire at midnight every day.
diff --git a/watch-library/watch/watch_slcd.h b/watch-library/watch/watch_slcd.h
index 724d3dde..abe4d744 100644
--- a/watch-library/watch/watch_slcd.h
+++ b/watch-library/watch/watch_slcd.h
@@ -110,7 +110,7 @@ void watch_clear_all_indicators();
/** @brief Blinks a single character in position 7. Does not affect other positions.
* @details Six of the seven segments in position 7 (and only position 7) are capable of autonomous
* blinking. This blinking does not require any CPU resources, and will continue even in
- * standby and shallow sleep mode (if the LCD remains on).
+ * STANDBY and Sleep mode (but not Deep Sleep mode, since that mode turns off the LCD).
* @param character The character you wish to blink.
* @param duration The duration of the on/off cycle in milliseconds, from 50 to ~4250 ms.
* @note Segment B of position 7 cannot blink autonomously, so not all characters will work well.
@@ -132,8 +132,8 @@ void watch_stop_blink();
* or backward in a shift register whose positions map to fixed segments on the LCD. Given
* this constraint, an animation across all six segments does not make sense; so the watch
* library offers only a simple "tick/tock" in segments D and E. This animation does not
- * require any CPU resources, and will continue even in standby and shallow sleep mode
- * (if the LCD remains on).
+ * require any CPU resources, and will continue even in STANDBY and Sleep mode (but not Deep
+ * Sleep mode, since that mode turns off the LCD).
* @param duration The duration of each frame in ms. 500 milliseconds produces a classic tick/tock.
*/
void watch_start_tick_animation(uint32_t duration);