diff options
-rw-r--r-- | Sensor Watch Starter Project/app.c | 30 | ||||
-rw-r--r-- | watch-library/config/hpl_eic_config.h | 16 | ||||
-rw-r--r-- | watch-library/config/hpl_rtc_config.h | 6 | ||||
-rw-r--r-- | watch-library/hal/include/hpl_calendar.h | 27 | ||||
-rw-r--r-- | watch-library/hpl/rtc/hpl_rtc.c | 54 | ||||
-rw-r--r-- | watch-library/hw/atmel_start_pins.h | 2 | ||||
-rw-r--r-- | watch-library/hw/driver_init.c | 2 | ||||
-rwxr-xr-x | watch-library/main.c | 10 | ||||
-rw-r--r-- | watch-library/watch/watch.c | 30 |
9 files changed, 126 insertions, 51 deletions
diff --git a/Sensor Watch Starter Project/app.c b/Sensor Watch Starter Project/app.c index 4e44deb7..c3eddcbc 100644 --- a/Sensor Watch Starter Project/app.c +++ b/Sensor Watch Starter Project/app.c @@ -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 -}
\ No newline at end of file + if (application_state.debounce_wait) return; + application_state.debounce_wait = true; + application_state.enter_deep_sleep = true; +} diff --git a/watch-library/config/hpl_eic_config.h b/watch-library/config/hpl_eic_config.h index 3b268a10..5066be66 100644 --- a/watch-library/config/hpl_eic_config.h +++ b/watch-library/config/hpl_eic_config.h @@ -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 >>> diff --git a/watch-library/config/hpl_rtc_config.h b/watch-library/config/hpl_rtc_config.h index 9085ca37..582a1c23 100644 --- a/watch-library/config/hpl_rtc_config.h +++ b/watch-library/config/hpl_rtc_config.h @@ -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 diff --git a/watch-library/hal/include/hpl_calendar.h b/watch-library/hal/include/hpl_calendar.h index 16601d3a..87b1a5a8 100644 --- a/watch-library/hal/include/hpl_calendar.h +++ b/watch-library/hal/include/hpl_calendar.h @@ -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 @@ -246,6 +243,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 * * \param[in] dev The pointer to calendar device struct @@ -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 diff --git a/watch-library/hpl/rtc/hpl_rtc.c b/watch-library/hpl/rtc/hpl_rtc.c index c28ddec6..0d119da1 100644 --- a/watch-library/hpl/rtc/hpl_rtc.c +++ b/watch-library/hpl/rtc/hpl_rtc.c @@ -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); + } + + 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); - /* disable RTC_IRQn */ - NVIC_DisableIRQ(RTC_IRQn); + /* 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); } } /** diff --git a/watch-library/hw/atmel_start_pins.h b/watch-library/hw/atmel_start_pins.h index 36fe6bf4..28dc9919 100644 --- a/watch-library/hw/atmel_start_pins.h +++ b/watch-library/hw/atmel_start_pins.h @@ -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) diff --git a/watch-library/hw/driver_init.c b/watch-library/hw/driver_init.c index 4f1f8eee..02907feb 100644 --- a/watch-library/hw/driver_init.c +++ b/watch-library/hw/driver_init.c @@ -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); diff --git a/watch-library/main.c b/watch-library/main.c index 67e47896..42d0b56a 100755 --- a/watch-library/main.c +++ b/watch-library/main.c @@ -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. diff --git a/watch-library/watch/watch.c b/watch-library/watch/watch.c index 82b7467c..922aeb0a 100644 --- a/watch-library/watch/watch.c +++ b/watch-library/watch/watch.c @@ -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); } |