summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Sensor Watch Starter Project/app.c30
-rw-r--r--watch-library/config/hpl_eic_config.h16
-rw-r--r--watch-library/config/hpl_rtc_config.h6
-rw-r--r--watch-library/hal/include/hpl_calendar.h27
-rw-r--r--watch-library/hpl/rtc/hpl_rtc.c54
-rw-r--r--watch-library/hw/atmel_start_pins.h2
-rw-r--r--watch-library/hw/driver_init.c2
-rwxr-xr-xwatch-library/main.c10
-rw-r--r--watch-library/watch/watch.c30
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);
}