WIP deep sleep mode
This commit is contained in:
parent
8a06636833
commit
fc31739eb6
@ -23,6 +23,7 @@ typedef struct ApplicationState {
|
||||
LightColor color;
|
||||
uint8_t wake_count;
|
||||
bool debounce_wait;
|
||||
bool enter_deep_sleep;
|
||||
} ApplicationState;
|
||||
|
||||
ApplicationState application_state;
|
||||
@ -58,7 +59,10 @@ void app_init() {
|
||||
* @see watch_enter_deep_sleep()
|
||||
*/
|
||||
void app_wake_from_deep_sleep() {
|
||||
// TODO: deep sleep demo
|
||||
// retrieve our application state from the backup registers
|
||||
application_state.mode = (ApplicationMode)watch_get_backup_data(0);
|
||||
application_state.color = (LightColor)watch_get_backup_data(1);
|
||||
application_state.wake_count = (uint8_t)watch_get_backup_data(2) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,6 +145,24 @@ bool app_loop() {
|
||||
// Wait a moment to debounce button input
|
||||
delay_ms(250);
|
||||
|
||||
if (application_state.enter_deep_sleep) {
|
||||
application_state.enter_deep_sleep = false;
|
||||
|
||||
// stash our application state in the backup registers
|
||||
watch_store_backup_data((uint32_t)application_state.mode, 0);
|
||||
watch_store_backup_data((uint32_t)application_state.color, 1);
|
||||
watch_store_backup_data((uint32_t)application_state.wake_count, 2);
|
||||
|
||||
// turn off the LED
|
||||
watch_set_led_off();
|
||||
|
||||
// wait a moment for the user's finger to be off the button
|
||||
delay_ms(1000);
|
||||
|
||||
// nap time :)
|
||||
watch_enter_deep_sleep();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -161,5 +183,7 @@ void cb_mode_pressed() {
|
||||
}
|
||||
|
||||
void cb_alarm_pressed() {
|
||||
// TODO: deep sleep demo
|
||||
if (application_state.debounce_wait) return;
|
||||
application_state.debounce_wait = true;
|
||||
application_state.enter_deep_sleep = true;
|
||||
}
|
@ -138,14 +138,14 @@
|
||||
// <e> Interrupt 2 Settings
|
||||
// <id> eic_arch_enable_irq_setting2
|
||||
#ifndef CONF_EIC_ENABLE_IRQ_SETTING2
|
||||
#define CONF_EIC_ENABLE_IRQ_SETTING2 0
|
||||
#define CONF_EIC_ENABLE_IRQ_SETTING2 1
|
||||
#endif
|
||||
|
||||
// <q> External Interrupt 2 Filter Enable
|
||||
// <i> Indicates whether the external interrupt 2 filter is enabled or not
|
||||
// <id> eic_arch_filten2
|
||||
#ifndef CONF_EIC_FILTEN2
|
||||
#define CONF_EIC_FILTEN2 0
|
||||
#define CONF_EIC_FILTEN2 1
|
||||
#endif
|
||||
|
||||
// <q> External Interrupt 2 Event Output Enable
|
||||
@ -165,7 +165,7 @@
|
||||
// <i> This defines input sense trigger
|
||||
// <id> eic_arch_sense2
|
||||
#ifndef CONF_EIC_SENSE2
|
||||
#define CONF_EIC_SENSE2 EIC_NMICTRL_NMISENSE_NONE_Val
|
||||
#define CONF_EIC_SENSE2 EIC_NMICTRL_NMISENSE_RISE_Val
|
||||
#endif
|
||||
|
||||
// <q> External Interrupt 2 Asynchronous Edge Detection Mode
|
||||
@ -264,7 +264,7 @@
|
||||
// <e> Interrupt 5 Settings
|
||||
// <id> eic_arch_enable_irq_setting5
|
||||
#ifndef CONF_EIC_ENABLE_IRQ_SETTING5
|
||||
#define CONF_EIC_ENABLE_IRQ_SETTING5 1
|
||||
#define CONF_EIC_ENABLE_IRQ_SETTING5 0
|
||||
#endif
|
||||
|
||||
// <q> External Interrupt 5 Filter Enable
|
||||
@ -291,7 +291,7 @@
|
||||
// <i> This defines input sense trigger
|
||||
// <id> eic_arch_sense5
|
||||
#ifndef CONF_EIC_SENSE5
|
||||
#define CONF_EIC_SENSE5 EIC_NMICTRL_NMISENSE_RISE_Val
|
||||
#define CONF_EIC_SENSE5 EIC_NMICTRL_NMISENSE_NONE_Val
|
||||
#endif
|
||||
|
||||
// <q> External Interrupt 5 Asynchronous Edge Detection Mode
|
||||
@ -313,7 +313,7 @@
|
||||
// <i> Indicates whether the external interrupt 6 filter is enabled or not
|
||||
// <id> eic_arch_filten6
|
||||
#ifndef CONF_EIC_FILTEN6
|
||||
#define CONF_EIC_FILTEN6 0
|
||||
#define CONF_EIC_FILTEN6 1
|
||||
#endif
|
||||
|
||||
// <q> External Interrupt 6 Event Output Enable
|
||||
@ -355,7 +355,7 @@
|
||||
// <i> Indicates whether the external interrupt 7 filter is enabled or not
|
||||
// <id> eic_arch_filten7
|
||||
#ifndef CONF_EIC_FILTEN7
|
||||
#define CONF_EIC_FILTEN7 0
|
||||
#define CONF_EIC_FILTEN7 1
|
||||
#endif
|
||||
|
||||
// <q> External Interrupt 7 Event Output Enable
|
||||
@ -723,7 +723,7 @@
|
||||
|
||||
// </e>
|
||||
|
||||
#define CONFIG_EIC_EXTINT_MAP {5, PIN_PB05}, {6, PIN_PA22}, {7, PIN_PA23},
|
||||
#define CONFIG_EIC_EXTINT_MAP {2, PIN_PA02}, {6, PIN_PA22}, {7, PIN_PA23},
|
||||
|
||||
// <<< end of configuration section >>>
|
||||
|
||||
|
@ -114,14 +114,14 @@
|
||||
// <e> RTC Tamper Input 2 settings
|
||||
// <id> tamper_input_2_settings
|
||||
#ifndef CONF_TAMPER_INPUT_2_SETTINGS
|
||||
#define CONF_TAMPER_INPUT_2_SETTINGS 0
|
||||
#define CONF_TAMPER_INPUT_2_SETTINGS 1
|
||||
#endif
|
||||
|
||||
// <q> Tamper Level Settings
|
||||
// <i> Indicates Tamper input 2 level
|
||||
// <id> tamper_level_2
|
||||
#ifndef CONF_RTC_TAMP_LVL_2
|
||||
#define CONF_RTC_TAMP_LVL_2 0
|
||||
#define CONF_RTC_TAMP_LVL_2 1
|
||||
#endif
|
||||
|
||||
// <o> RTC Tamper Input Action
|
||||
@ -132,7 +132,7 @@
|
||||
// <i> These bits define the RTC Tamper Input Action to be performed
|
||||
// <id> rtc_tamper_input_action_2
|
||||
#ifndef CONF_RTC_TAMPER_INACT_2
|
||||
#define CONF_RTC_TAMPER_INACT_2 0
|
||||
#define CONF_RTC_TAMPER_INACT_2 1
|
||||
#endif
|
||||
|
||||
// <q> Debounce Enable for Tamper Input
|
||||
|
@ -77,12 +77,7 @@ enum calendar_alarm_mode { ONESHOT = 1, REPEAT };
|
||||
/**
|
||||
* \brief Prototype of callback on alarm match
|
||||
*/
|
||||
typedef void (*calendar_drv_cb_alarm_t)(struct calendar_dev *const dev);
|
||||
|
||||
/**
|
||||
* \brief Prototype of callback on tamper detect
|
||||
*/
|
||||
typedef void (*tamper_drv_cb_t)(struct calendar_dev *const dev);
|
||||
typedef void (*calendar_drv_cb_t)(struct calendar_dev *const dev);
|
||||
|
||||
/**
|
||||
* \brief Structure of Calendar instance
|
||||
@ -91,9 +86,11 @@ struct calendar_dev {
|
||||
/** Pointer to the hardware base */
|
||||
void *hw;
|
||||
/** Alarm match callback */
|
||||
calendar_drv_cb_alarm_t callback;
|
||||
calendar_drv_cb_t callback_alarm;
|
||||
/** Tamper callback */
|
||||
tamper_drv_cb_t callback_tamper;
|
||||
calendar_drv_cb_t callback_tamper;
|
||||
/** Tamper callback */
|
||||
calendar_drv_cb_t callback_tick;
|
||||
/** IRQ struct */
|
||||
struct _irq_descriptor irq;
|
||||
};
|
||||
@ -236,7 +233,7 @@ uint32_t _calendar_get_comp(struct calendar_dev *const dev);
|
||||
*
|
||||
* \return ERR_NONE on success, or an error code on failure.
|
||||
*/
|
||||
int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv_cb_alarm_t callback);
|
||||
int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv_cb_t callback);
|
||||
|
||||
/**
|
||||
* \brief Set calendar IRQ
|
||||
@ -245,6 +242,16 @@ int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv
|
||||
*/
|
||||
void _calendar_set_irq(struct calendar_dev *const dev);
|
||||
|
||||
/**
|
||||
* \brief Register callback for 1Hz tick from prescaler
|
||||
*
|
||||
* \param[in] dev The pointer to calendar device struct
|
||||
* \param[in] callback The pointer to callback function
|
||||
*
|
||||
* \return ERR_NONE on success, or an error code on failure.
|
||||
*/
|
||||
int32_t _prescaler_register_callback(struct calendar_dev *const dev, calendar_drv_cb_t callback);
|
||||
|
||||
/**
|
||||
* \brief Register callback for tamper detection
|
||||
*
|
||||
@ -253,7 +260,7 @@ void _calendar_set_irq(struct calendar_dev *const dev);
|
||||
*
|
||||
* \return ERR_NONE on success, or an error code on failure.
|
||||
*/
|
||||
int32_t _tamper_register_callback(struct calendar_dev *const dev, tamper_drv_cb_t callback_tamper);
|
||||
int32_t _extwake_register_callback(struct calendar_dev *const dev, calendar_drv_cb_t callback);
|
||||
|
||||
/**
|
||||
* \brief Find tamper is detected on specified pin
|
||||
|
@ -99,7 +99,9 @@ int32_t _calendar_deinit(struct calendar_dev *const dev)
|
||||
ASSERT(dev && dev->hw);
|
||||
|
||||
NVIC_DisableIRQ(RTC_IRQn);
|
||||
dev->callback = NULL;
|
||||
dev->callback_alarm = NULL;
|
||||
dev->callback_tick = NULL;
|
||||
dev->callback_tamper = NULL;
|
||||
|
||||
hri_rtcmode0_clear_CTRLA_ENABLE_bit(dev->hw);
|
||||
hri_rtcmode0_set_CTRLA_SWRST_bit(dev->hw);
|
||||
@ -302,27 +304,49 @@ int32_t _tamper_disable_debounce_majority(struct calendar_dev *const dev)
|
||||
return return_value;
|
||||
}
|
||||
|
||||
int32_t _tamper_register_callback(struct calendar_dev *const dev, tamper_drv_cb_t callback_tamper)
|
||||
int32_t _prescaler_register_callback(struct calendar_dev *const dev, calendar_drv_cb_t callback)
|
||||
{
|
||||
ASSERT(dev && dev->hw);
|
||||
|
||||
/* Check callback */
|
||||
if (callback_tamper != NULL) {
|
||||
if (callback != NULL) {
|
||||
/* register the callback */
|
||||
dev->callback_tamper = callback_tamper;
|
||||
dev->callback_tick = callback;
|
||||
|
||||
/* enable RTC_IRQn */
|
||||
NVIC_ClearPendingIRQ(RTC_IRQn);
|
||||
NVIC_EnableIRQ(RTC_IRQn);
|
||||
|
||||
/* enable tamper interrupt */
|
||||
/* enable periodic interrupt */
|
||||
hri_rtcmode0_set_INTEN_PER7_bit(dev->hw);
|
||||
} else {
|
||||
/* disable tamper interrupt */
|
||||
/* disable periodic interrupt */
|
||||
hri_rtcmode0_clear_INTEN_PER7_bit(dev->hw);
|
||||
}
|
||||
|
||||
/* disable RTC_IRQn */
|
||||
NVIC_DisableIRQ(RTC_IRQn);
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
// TODO: refactor this so it doesn't take a callback (it will never get called anyway)
|
||||
int32_t _extwake_register_callback(struct calendar_dev *const dev, calendar_drv_cb_t callback)
|
||||
{
|
||||
ASSERT(dev && dev->hw);
|
||||
|
||||
/* Check callback */
|
||||
if (callback != NULL) {
|
||||
/* register the callback */
|
||||
dev->callback_tamper = callback;
|
||||
|
||||
/* enable RTC_IRQn */
|
||||
NVIC_ClearPendingIRQ(RTC_IRQn);
|
||||
NVIC_EnableIRQ(RTC_IRQn);
|
||||
|
||||
hri_rtcmode0_clear_interrupt_TAMPER_bit(dev->hw);
|
||||
/* enable tamper interrupt */
|
||||
hri_rtcmode0_set_INTEN_TAMPER_bit(dev->hw);
|
||||
} else {
|
||||
/* disable tamper interrupt */
|
||||
hri_rtcmode0_clear_INTEN_TAMPER_bit(dev->hw);
|
||||
}
|
||||
|
||||
return ERR_NONE;
|
||||
@ -330,14 +354,14 @@ int32_t _tamper_register_callback(struct calendar_dev *const dev, tamper_drv_cb_
|
||||
/**
|
||||
* \brief Registers callback for the specified callback type
|
||||
*/
|
||||
int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv_cb_alarm_t callback)
|
||||
int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv_cb_t callback)
|
||||
{
|
||||
ASSERT(dev && dev->hw);
|
||||
|
||||
/* Check callback */
|
||||
if (callback != NULL) {
|
||||
/* register the callback */
|
||||
dev->callback = callback;
|
||||
dev->callback_alarm = callback;
|
||||
|
||||
/* enable RTC_IRQn */
|
||||
NVIC_ClearPendingIRQ(RTC_IRQn);
|
||||
@ -348,9 +372,6 @@ int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv
|
||||
} else {
|
||||
/* disable cmp */
|
||||
hri_rtcmode0_clear_INTEN_CMP0_bit(dev->hw);
|
||||
|
||||
/* disable RTC_IRQn */
|
||||
NVIC_DisableIRQ(RTC_IRQn);
|
||||
}
|
||||
|
||||
return ERR_NONE;
|
||||
@ -368,15 +389,18 @@ static void _rtc_interrupt_handler(struct calendar_dev *dev)
|
||||
uint16_t interrupt_enabled = hri_rtcmode0_read_INTEN_reg(dev->hw);
|
||||
|
||||
if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_ALARM0) {
|
||||
dev->callback(dev);
|
||||
dev->callback_alarm(dev);
|
||||
|
||||
/* Clear interrupt flag */
|
||||
hri_rtcmode0_clear_interrupt_CMP0_bit(dev->hw);
|
||||
} else if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_PER7) {
|
||||
dev->callback_tamper(dev);
|
||||
dev->callback_tick(dev);
|
||||
|
||||
/* Clear interrupt flag */
|
||||
hri_rtcmode0_clear_interrupt_PER7_bit(dev->hw);
|
||||
} else if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_TAMPER) {
|
||||
/* Clear interrupt flag */
|
||||
hri_rtcmode0_clear_interrupt_TAMPER_bit(dev->hw);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -49,7 +49,7 @@
|
||||
#define A2 GPIO(GPIO_PORTB, 2)
|
||||
#define D0 GPIO(GPIO_PORTB, 3)
|
||||
#define A0 GPIO(GPIO_PORTB, 4)
|
||||
#define BTN_ALARM GPIO(GPIO_PORTB, 5)
|
||||
#define BTN_ALARM GPIO(GPIO_PORTA, 2)
|
||||
#define COM0 GPIO(GPIO_PORTB, 6)
|
||||
#define COM1 GPIO(GPIO_PORTB, 7)
|
||||
#define COM2 GPIO(GPIO_PORTB, 8)
|
||||
|
@ -50,7 +50,7 @@ void EXTERNAL_IRQ_0_init(void) {
|
||||
// <GPIO_PULL_DOWN"> Pull-down
|
||||
GPIO_PULL_DOWN);
|
||||
|
||||
gpio_set_pin_function(BTN_ALARM, PINMUX_PB05A_EIC_EXTINT5);
|
||||
gpio_set_pin_function(BTN_ALARM, PINMUX_PA02A_EIC_EXTINT2);
|
||||
|
||||
// Set pin direction to input
|
||||
gpio_set_pin_direction(BTN_LIGHT, GPIO_DIRECTION_IN);
|
||||
|
@ -43,7 +43,6 @@
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
HAL_GPIO_PIN(UART_TX, B, 0)
|
||||
HAL_GPIO_PIN(UART_RX, B, 2)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void uart_init(uint32_t baud) {
|
||||
@ -51,8 +50,6 @@ static void uart_init(uint32_t baud) {
|
||||
|
||||
HAL_GPIO_UART_TX_out();
|
||||
HAL_GPIO_UART_TX_pmuxen(HAL_GPIO_PMUX_C);
|
||||
HAL_GPIO_UART_RX_in();
|
||||
HAL_GPIO_UART_RX_pmuxen(HAL_GPIO_PMUX_C);
|
||||
|
||||
MCLK->APBCMASK.reg |= MCLK_APBCMASK_SERCOM3;
|
||||
|
||||
@ -92,10 +89,15 @@ int main(void) {
|
||||
// User code. Give the app a chance to initialize its data structures and state.
|
||||
app_init();
|
||||
|
||||
// At this point, if the RTC peripheral is enabled, we are waking from BACKUP.
|
||||
// If the RTC is already enabled, we're either waking from BACKUP mode or a reset.
|
||||
// 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();
|
||||
|
||||
// disable the tamper interrupt and clear the tamper bit
|
||||
hri_rtcmode0_clear_INTEN_TAMPER_bit(RTC);
|
||||
hri_rtcmode0_clear_interrupt_TAMPER_bit(RTC);
|
||||
}
|
||||
|
||||
// Watch library code. Set initial parameters for the device and enable the RTC.
|
||||
|
@ -271,8 +271,7 @@ static void tick_callback(struct calendar_dev *const dev) {
|
||||
|
||||
void watch_enable_tick_callback(ext_irq_cb_t callback) {
|
||||
tick_user_callback = callback;
|
||||
// TODO: rename this method to reflect that it now sets the PER7 interrupt.
|
||||
_tamper_register_callback(&CALENDAR_0.device, &tick_callback);
|
||||
_prescaler_register_callback(&CALENDAR_0.device, &tick_callback);
|
||||
}
|
||||
|
||||
static bool ADC_0_ENABLED = false;
|
||||
@ -359,8 +358,27 @@ uint32_t watch_get_backup_data(uint8_t reg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void watch_enter_deep_sleep(){
|
||||
// Not yet implemented.
|
||||
// TODO: enable tamper interrupt on ALARM pin.
|
||||
// sleep(5);
|
||||
static void extwake_callback(struct calendar_dev *const dev) {
|
||||
// this will never get called since we are basically waking from reset
|
||||
}
|
||||
|
||||
void watch_enter_deep_sleep() {
|
||||
// enable and configure the external wake interrupt
|
||||
_extwake_register_callback(&CALENDAR_0.device, &extwake_callback);
|
||||
_tamper_enable_debounce_asynchronous(&CALENDAR_0.device);
|
||||
|
||||
// disable SLCD
|
||||
slcd_sync_deinit(&SEGMENT_LCD_0);
|
||||
hri_mclk_clear_APBCMASK_SLCD_bit(SLCD);
|
||||
|
||||
// TODO: disable other peripherals
|
||||
|
||||
// disable EIC interrupt on ALARM pin (if any) and enable RTC interrupt.
|
||||
ext_irq_disable(BTN_ALARM);
|
||||
gpio_set_pin_direction(BTN_ALARM, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(BTN_ALARM, GPIO_PULL_DOWN);
|
||||
gpio_set_pin_function(BTN_ALARM, PINMUX_PA02G_RTC_IN2);
|
||||
|
||||
// go into backup sleep mode
|
||||
sleep(5);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user