more accurate names for deep sleep and shallow sleep modes

This commit is contained in:
Joey Castillo 2021-10-20 13:45:22 -04:00
parent 1020dd7898
commit 38a2dff234
11 changed files with 169 additions and 114 deletions

View File

@ -16,8 +16,8 @@ void app_init() {
memset(&application_state, 0, sizeof(application_state)); memset(&application_state, 0, sizeof(application_state));
} }
void app_wake_from_deep_sleep() { void app_wake_from_backup() {
// This app does not support deep sleep mode. // This app does not support BACKUP mode.
} }
void app_setup() { void app_setup() {
@ -63,13 +63,13 @@ void app_setup() {
/** /**
* Nothing to do here. * Nothing to do here.
*/ */
void app_prepare_for_sleep() { void app_prepare_for_standby() {
} }
/** /**
* @todo restore the BME280's calibration values from backup memory * @todo restore the BME280's calibration values from backup memory
*/ */
void app_wake_from_sleep() { void app_wake_from_standby() {
} }
/** /**

View File

@ -17,7 +17,7 @@ void app_init() {
memset(&application_state, 0, sizeof(application_state)); memset(&application_state, 0, sizeof(application_state));
} }
void app_wake_from_deep_sleep() { void app_wake_from_backup() {
} }
void app_setup() { void app_setup() {
@ -28,11 +28,11 @@ void app_setup() {
watch_enable_buzzer(); watch_enable_buzzer();
} }
void app_prepare_for_sleep() { void app_prepare_for_standby() {
watch_display_string(" rains ", 2); watch_display_string(" rains ", 2);
} }
void app_wake_from_sleep() { void app_wake_from_standby() {
} }
bool app_loop() { bool app_loop() {

View File

@ -51,14 +51,14 @@ void app_init() {
} }
/** /**
* @brief the app_wake_from_deep_sleep function is only called if your app is waking from * @brief the app_wake_from_backup 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 * 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. * RTC's backup registers prior to entering this mode. You may restore that state here.
* *
* @see watch_enter_deep_sleep() * @see watch_enter_deep_sleep()
*/ */
void app_wake_from_deep_sleep() { void app_wake_from_backup() {
// this app only supports shallow sleep mode. // This app does not support BACKUP mode.
} }
/** /**
@ -69,9 +69,12 @@ void app_wake_from_deep_sleep() {
* accelerometer that will run at all times should be configured here, whereas you may * accelerometer that will run at all times should be configured here, whereas you may
* want to enable a more power-hungry environmental sensor only when you need it. * want to enable a more power-hungry environmental sensor only when you need it.
* *
* @note If your app enters the ultra-low power BACKUP sleep mode, this function will * @note If your app enters the Sleep or Deep Sleep modes, this function will be called
* be called again when it wakes from that deep sleep state. In this state, the RTC will * again on wake, since those modes will have disabled all pins and peripherals; you'll
* still be configured with the correct date and time. * likely need to set them up again. This function will also be called again if your app
* entered the ultra-low power BACKUP mode, since BACKUP mode will have done all that and
* also wiped out the system RAM. Note that when this is called after waking from sleep,
* the RTC will still be configured with the correct date and time.
*/ */
void app_setup() { void app_setup() {
watch_enable_leds(); watch_enable_leds();
@ -94,25 +97,24 @@ void app_setup() {
} }
/** /**
* @brief the app_prepare_for_sleep function is called before the watch goes into the * @brief the app_prepare_for_standby function is called before the watch goes into STANDBY mode.
* STANDBY sleep mode. In STANDBY mode, most peripherals are shut down, and no code * In STANDBY mode, most peripherals are shut down, and no code will run until the watch receives
* will run until the watch receives an interrupt (generally either the 1Hz tick or * an interrupt (generally either the 1Hz tick or a press on one of the buttons).
* a press on one of the buttons).
*/ */
void app_prepare_for_sleep() { void app_prepare_for_standby() {
} }
/** /**
* @brief the app_wake_from_sleep function is called after the watch wakes from the * @brief the app_wake_from_standby function is called after the watch wakes from STANDBY mode,
* STANDBY sleep mode. * but before your main app_loop.
*/ */
void app_wake_from_sleep() { void app_wake_from_standby() {
application_state.wake_count++; application_state.wake_count++;
} }
/** /**
* @brief the app_loop function is called once on app startup and then again each time * @brief the app_loop function is called once on app startup and then again each time the
* the watch STANDBY sleep mode. * watch exits STANDBY mode.
*/ */
bool app_loop() { bool app_loop() {
if (application_state.beep) { if (application_state.beep) {
@ -157,7 +159,7 @@ bool app_loop() {
delay_ms(250); delay_ms(250);
// nap time :) // nap time :)
watch_enter_shallow_sleep(false); watch_enter_deep_sleep_mode();
// we just woke up; wait a moment again for the user's finger to be off the button... // we just woke up; wait a moment again for the user's finger to be off the button...
delay_ms(250); delay_ms(250);

View File

@ -50,8 +50,8 @@ void app_init() {
memset(&application_state, 0, sizeof(application_state)); memset(&application_state, 0, sizeof(application_state));
} }
void app_wake_from_deep_sleep() { void app_wake_from_backup() {
// This app does not support deep sleep mode. // This app does not support BACKUP mode.
} }
void app_setup() { void app_setup() {
@ -67,10 +67,10 @@ void app_setup() {
watch_rtc_register_tick_callback(cb_tick); watch_rtc_register_tick_callback(cb_tick);
} }
void app_prepare_for_sleep() { void app_prepare_for_standby() {
} }
void app_wake_from_sleep() { void app_wake_from_standby() {
} }
void update_tick_frequency() { void update_tick_frequency() {

View File

@ -56,8 +56,8 @@ void app_init() {
_movement_reset_inactivity_countdown(); _movement_reset_inactivity_countdown();
} }
void app_wake_from_deep_sleep() { void app_wake_from_backup() {
// This app does not support deep sleep mode. // This app does not support BACKUP mode.
} }
void app_setup() { void app_setup() {
@ -94,10 +94,10 @@ void app_setup() {
} }
} }
void app_prepare_for_sleep() { void app_prepare_for_standby() {
} }
void app_wake_from_sleep() { void app_wake_from_standby() {
} }
bool app_loop() { bool app_loop() {
@ -147,11 +147,11 @@ bool app_loop() {
while (movement_state.le_mode_ticks == -1) { while (movement_state.le_mode_ticks == -1) {
event.event_type = EVENT_LOW_ENERGY_UPDATE; event.event_type = EVENT_LOW_ENERGY_UPDATE;
watch_faces[movement_state.current_watch_face].loop(event, &movement_state.settings, watch_face_contexts[movement_state.current_watch_face]); watch_faces[movement_state.current_watch_face].loop(event, &movement_state.settings, watch_face_contexts[movement_state.current_watch_face]);
watch_enter_shallow_sleep(true); watch_enter_sleep_mode();
} }
// as soon as le_mode_ticks is reset by the extwake handler, we bail out of the loop and reactivate ourselves. // as soon as le_mode_ticks is reset by the extwake handler, we bail out of the loop and reactivate ourselves.
event.event_type = EVENT_ACTIVATE; event.event_type = EVENT_ACTIVATE;
// this is a hack tho: waking from shallow sleep, app_setup does get called, but it happens before we have reset our ticks. // this is a hack tho: waking from sleep mode, app_setup does get called, but it happens before we have reset our ticks.
// need to figure out if there's a better heuristic for determining how we woke up. // need to figure out if there's a better heuristic for determining how we woke up.
app_setup(); app_setup();
} }

View File

@ -57,7 +57,7 @@ int main(void) {
// Ideally we should check if the TAMPER or CMP0 (alarm) flags are set. // Ideally we should check if the TAMPER or CMP0 (alarm) flags are set.
if (_watch_rtc_is_enabled()) { if (_watch_rtc_is_enabled()) {
// User code. Give the application a chance to restore state from backup registers. // 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 // disable the tamper interrupt and clear the tamper bit
hri_rtcmode0_clear_INTEN_TAMPER_bit(RTC); hri_rtcmode0_clear_INTEN_TAMPER_bit(RTC);
@ -75,9 +75,9 @@ int main(void) {
bool can_sleep = app_loop(); bool can_sleep = app_loop();
if (can_sleep && !usb_enabled) { if (can_sleep && !usb_enabled) {
app_prepare_for_sleep(); app_prepare_for_standby();
sleep(4); sleep(4);
app_wake_from_sleep(); app_wake_from_standby();
} }
} }

View File

@ -33,7 +33,7 @@
* *
* 1. Your app_init() function is called. * 1. Your app_init() function is called.
* - This method should only be used to set your initial application state. * - 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. * - If you saved state in the RTC's backup registers, you can restore it here.
* 3. Your app_setup() method is called. * 3. Your app_setup() method is called.
* - You may wish to enable some functionality and peripherals here. * - 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. * - Return true if your app is prepared to enter STANDBY mode.
* 5. This step differs depending on the value returned by app_loop: * 5. This step differs depending on the value returned by app_loop:
* - If you returned false, execution resumes at (4). * - If you returned false, execution resumes at (4).
* - If you returned true, app_prepare_for_sleep() is called; execution moves on to (6). * - If you returned true, app_prepare_for_standby() is called; execution moves on to (6).
* 6. The microcontroller enters the STANDBY sleep mode. * 6. The microcontroller enters STANDBY mode.
* - No user code will run, and the watch will enter a low power 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. * - 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). * - After this, execution resumes at (4).
*/ */
/// @{ /// @{
@ -57,11 +57,11 @@
*/ */
void app_init(); void app_init();
/** @brief A function you will implement to wake from deep sleep mode. The app_wake_from_deep_sleep function is only /** @brief A function you will implement to wake from BACKUP mode, which wipes the system's RAM, and with it, your
* called if your app is waking from the ultra-low power BACKUP sleep mode. You may have chosen to store some * application's state. You may have chosen to store some important application state in the RTC's backup
* state in the RTC's backup registers prior to entering this mode. You may restore that state here. * 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. /** @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 * 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(); void app_setup();
/** @brief A function you will implement to serve as the app's main run loop. This method will be called repeatedly, /** @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. 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 sleep mode. If you return false, your * @return You should return true if your app is prepared to enter STANDBY mode. If you return false, your app's
* app's app_loop method will be called again immediately. Note that in STANDBY mode, the watch will consume * app_loop method will be called again immediately. Note that in STANDBY mode, the watch will consume only
* only about 95 microamperes of power, whereas if you return false and keep the app awake, it will consume * about 95 microamperes of power, whereas if you return false and keep the app awake, it will consume about
* about 355 microamperes. This is the difference between months of battery life and days. As much as * 355 microamperes. This is the difference between months of battery life and days. As much as possible,
* possible, you should limit the amount of time your app spends awake. * 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 * @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 * 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, * 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(); bool app_loop();
/** @brief A function you will implement to prepare to enter STANDBY sleep mode. The app_prepare_for_sleep function is /** @brief A function you will implement to prepare to enter STANDBY mode. The app_prepare_for_standby function is
* called before the watch goes into the STANDBY sleep mode. In STANDBY mode, most peripherals are shut down, * called after your app_loop function returns true, and just before the watch enters STANDBY mode. In this
* and no code will run until the watch receives an interrupt (generally either the 1Hz tick or a press on one * mode most peripherals are shut down, and no code will run until the watch receives an interrupt (generally
* of the buttons). * 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 * @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 * 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 * 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 * 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 #endif

View File

@ -151,12 +151,7 @@ void _watch_disable_all_peripherals_except_slcd() {
MCLK->APBCMASK.reg &= ~MCLK_APBCMASK_SERCOM3; MCLK->APBCMASK.reg &= ~MCLK_APBCMASK_SERCOM3;
} }
void watch_enter_shallow_sleep(bool display_on) { void watch_enter_sleep_mode() {
if (!display_on) {
slcd_sync_deinit(&SEGMENT_LCD_0);
hri_mclk_clear_APBCMASK_SLCD_bit(SLCD);
}
// disable all other peripherals // disable all other peripherals
_watch_disable_all_peripherals_except_slcd(); _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. // call app_setup so the app can re-enable everything we disabled.
app_setup(); app_setup();
// and call app_wake_from_sleep (since main won't have a chance to do it) // and call app_wake_from_standby (since main won't have a chance to do it)
app_wake_from_sleep(); app_wake_from_standby();
} }
void watch_enter_deep_sleep() { void watch_enter_deep_sleep_mode() {
// this will not work on the current silicon revision, but I said in the documentation that we do it. // identical to sleep mode except we disable the LCD first.
// so let's do it! slcd_sync_deinit(&SEGMENT_LCD_0);
watch_register_extwake_callback(BTN_ALARM, NULL, true); hri_mclk_clear_APBCMASK_SLCD_bit(SLCD);
watch_enter_sleep_mode();
}
void watch_enter_backup_mode() {
watch_rtc_disable_all_periodic_callbacks(); watch_rtc_disable_all_periodic_callbacks();
_watch_disable_all_peripherals_except_slcd(); _watch_disable_all_peripherals_except_slcd();
slcd_sync_deinit(&SEGMENT_LCD_0); 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. // go into backup sleep mode (5). when we exit, the reset controller will take over.
sleep(5); 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();
}

View File

@ -32,26 +32,54 @@ extern ext_irq_cb_t btn_alarm_callback;
extern ext_irq_cb_t a2_callback; extern ext_irq_cb_t a2_callback;
extern ext_irq_cb_t a4_callback; extern ext_irq_cb_t a4_callback;
/** @addtogroup deepsleep Deep Sleep Control /** @addtogroup deepsleep Sleep Control
* @brief This section covers functions related to preparing for and entering BACKUP mode, the * @brief This section covers functions related to the various sleep modes available to the watch,
* deepest sleep mode available on the SAM L22 * 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 /** @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 * @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. * 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 * @param callback The callback to be called if this pin triggers outside of BACKUP mode. If this is
* this is NULL, no callback will be called even in normal mode, but the interrupt * NULL, no callback will be called even in normal modes, but the interrupt will
* will still be enabled so that it can wake from deep sleep or backup mode. * 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 * @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 * 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. * 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 * @note When in ACTIVE, STANDBY and Sleep / Deep sleep modes, this will function much like a standard
* situation: these pins will wake from standby, and your callback will be called. However, * external interrupt situation: these pins will wake the device, and your callback will be
* if the device enters deep sleep and one of these pins wakes the device, your callback * called. However, if the device enters BACKUP mode and one of these pins wakes the device, your
* WILL NOT be called, as the device is basically waking from reset at that point. * 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 * @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 * 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. * 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); 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 /** @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 * @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. * the internal pull down on that pin.
*/ */
void watch_disable_extwake_interrupt(uint8_t 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 data An unsigned 32 bit integer with the data you wish to store.
* @param reg A register from 0-7. * @param reg A register from 0-7.
*/ */
void watch_store_backup_data(uint32_t data, uint8_t reg); 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. * @param reg A register from 0-7.
* @return An unsigned 32 bit integer with the from the backup register. * @return An unsigned 32 bit integer with the from the backup register.
*/ */
uint32_t watch_get_backup_data(uint8_t reg); 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) /** @brief enters Sleep Mode by disabling all pins and peripherals except the RTC and the LCD.
* the LCD. You can wake from this mode by pressing the ALARM button, if you have an registered an * @details This sleep mode is not the lowest power mode available, but it has the benefit of allowing you
* external wake callback on the ALARM button. When your app wakes from this shallow sleep mode, your * to display a message to the user while asleep. You can also set an alarm interrupt to wake at a
* app_setup method will be called, since this function will have disabled things you set up. * configfurable interval (every minute, hour or day) to update the display. You can wake from this
* @param display_on if true, leaves the LCD on to display whatever content was on-screen. If false, disables * mode by pressing the ALARM button, if you registered an extwake callback on the ALARM button.
* the segment LCD controller for additional power savings. * Also note that when your app wakes from this sleep mode, your app_setup method will be called
* @details This shallow sleep mode is not the lowest power mode available (see watch_enter_deep_sleep), but * again, since this function will have disabled things you set up there.
* 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.
* *
* Power consumption in shallow sleep mode varies a bit with the battery voltage and the temperature, * Note that to wake from either the ALARM button, the A2 interrupt or the A4 interrupt, you
* but at 3 V and 25~30° C you can roughly estimate: * must first configure this by calling watch_register_extwake_callback.
* * < 12µA current draw with the LCD controller on *
* * < 6µA current draw with the LCD controller off * 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. /** @brief Enters the SAM L22's lowest-power mode, BACKUP.
* @details This function does some housekeeping before entering BACKUP mode. It first disables all * @details This function does some housekeeping before entering BACKUP mode. It first disables all pins
* peripherals except for the RTC, and disables the tick interrupt (since that would wake * and 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 * us up from BACKUP mode). Once again, if you wish to wake from the A2 or the A4 interrupt,
* was not already set. If you wish to wake from another source, such as one of the external * you must first configure this by calling watch_register_extwake_callback.
* wake interrupt pins on the 9-pin connector, set that up prior to calling this function.
* @note If you have a callback set for an external wake interrupt, it will be called if triggered while * @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. * in ACTIVE, STANDBY, Sleep and Deep Sleep modes, but it *will not be called* when waking from
* Waking from backup is effectively like waking from reset, except that your @ref * BACKUP mode. Waking from backup is effectively like waking from reset, except that your
* app_wake_from_deep_sleep function will be called. * @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 * @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 * 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 * 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 * 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). * 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(); void watch_enter_deep_sleep();
/// @} /// @}
#endif #endif

View File

@ -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 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. * @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 * @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 * wake the device from all sleep modes. The key to its versatility is the mask parameter.
* parameter. Suppose we set an alarm for midnight, 00:00:00. * 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. * * 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_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. * * with ALARM_MATCH_HHMMSS, the alarm will fire at midnight every day.

View File

@ -110,7 +110,7 @@ void watch_clear_all_indicators();
/** @brief Blinks a single character in position 7. Does not affect other positions. /** @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 * @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 * 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 character The character you wish to blink.
* @param duration The duration of the on/off cycle in milliseconds, from 50 to ~4250 ms. * @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. * @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 * 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 * 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 * 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 * require any CPU resources, and will continue even in STANDBY and Sleep mode (but not Deep
* (if the LCD remains on). * 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. * @param duration The duration of each frame in ms. 500 milliseconds produces a classic tick/tock.
*/ */
void watch_start_tick_animation(uint32_t duration); void watch_start_tick_animation(uint32_t duration);