WIP: refactor RTC to use clock mode directly
This commit is contained in:
		
							parent
							
								
									751ed9c7a4
								
							
						
					
					
						commit
						a65dcf1ec8
					
				| @ -376,55 +376,8 @@ int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv | |||||||
| 	return ERR_NONE; | 	return ERR_NONE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 |  | ||||||
|  * \brief RTC interrupt handler |  | ||||||
|  * |  | ||||||
|  * \param[in] dev The pointer to calendar device struct |  | ||||||
|  */ |  | ||||||
| static void _rtc_interrupt_handler(struct calendar_dev *dev) |  | ||||||
| { |  | ||||||
| 	/* Read and mask interrupt flag register */ |  | ||||||
| 	uint16_t interrupt_status  = hri_rtcmode0_read_INTFLAG_reg(dev->hw); |  | ||||||
| 	uint16_t interrupt_enabled = hri_rtcmode0_read_INTEN_reg(dev->hw); |  | ||||||
| 
 |  | ||||||
| 	if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_ALARM0) { |  | ||||||
| 		if (dev->callback_alarm != NULL) { |  | ||||||
| 			dev->callback_alarm(); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		/* Clear interrupt flag */ |  | ||||||
| 		hri_rtcmode0_clear_interrupt_CMP0_bit(dev->hw); |  | ||||||
| 	} else if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_PER7) { |  | ||||||
| 		if (dev->callback_tick != NULL) { |  | ||||||
| 			dev->callback_tick(); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		/* Clear interrupt flag */ |  | ||||||
| 		hri_rtcmode0_clear_interrupt_PER7_bit(dev->hw); |  | ||||||
| 	} else if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_TAMPER) { |  | ||||||
| 		uint8_t reason = hri_rtc_get_TAMPID_reg(dev->hw, 0x1F); |  | ||||||
| 		if (dev->callback_tamper != NULL) { |  | ||||||
| 			dev->callback_tamper(reason); |  | ||||||
| 		} |  | ||||||
| 		hri_rtc_write_TAMPID_reg(dev->hw, reason); |  | ||||||
| 
 |  | ||||||
| 		/* Clear interrupt flag */ |  | ||||||
| 		hri_rtcmode0_clear_interrupt_TAMPER_bit(dev->hw); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| /**
 |  | ||||||
|  * \brief Set calendar IRQ |  | ||||||
|  */ |  | ||||||
| void _calendar_set_irq(struct calendar_dev *const dev) | void _calendar_set_irq(struct calendar_dev *const dev) | ||||||
| { | { | ||||||
| 	(void)dev; | 	(void)dev; | ||||||
| 	NVIC_SetPendingIRQ(RTC_IRQn); | 	NVIC_SetPendingIRQ(RTC_IRQn); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * \brief Rtc interrupt handler |  | ||||||
|  */ |  | ||||||
| void RTC_Handler(void) |  | ||||||
| { |  | ||||||
| 	_rtc_interrupt_handler(_rtc_dev); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -13,19 +13,8 @@ | |||||||
| 
 | 
 | ||||||
| struct slcd_sync_descriptor SEGMENT_LCD_0; | struct slcd_sync_descriptor SEGMENT_LCD_0; | ||||||
| 
 | 
 | ||||||
| struct calendar_descriptor CALENDAR_0; |  | ||||||
| 
 |  | ||||||
| struct i2c_m_sync_desc I2C_0; | struct i2c_m_sync_desc I2C_0; | ||||||
| 
 | 
 | ||||||
| void CALENDAR_0_CLOCK_init(void) { |  | ||||||
| 	hri_mclk_set_APBAMASK_RTC_bit(MCLK); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void CALENDAR_0_init(void) { |  | ||||||
| 	CALENDAR_0_CLOCK_init(); |  | ||||||
| 	calendar_init(&CALENDAR_0, RTC); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void I2C_0_PORT_init(void) { | void I2C_0_PORT_init(void) { | ||||||
| 
 | 
 | ||||||
| 	gpio_set_pin_pull_mode(SDA, | 	gpio_set_pin_pull_mode(SDA, | ||||||
|  | |||||||
| @ -38,36 +38,16 @@ extern "C" { | |||||||
| 
 | 
 | ||||||
| extern struct adc_sync_descriptor ADC_0; | extern struct adc_sync_descriptor ADC_0; | ||||||
| 
 | 
 | ||||||
| extern struct calendar_descriptor CALENDAR_0; |  | ||||||
| 
 |  | ||||||
| extern struct i2c_m_sync_desc I2C_0; | extern struct i2c_m_sync_desc I2C_0; | ||||||
| 
 | 
 | ||||||
| extern struct pwm_descriptor PWM_0; |  | ||||||
| 
 |  | ||||||
| extern struct pwm_descriptor       PWM_1; |  | ||||||
| extern struct slcd_sync_descriptor SEGMENT_LCD_0; | extern struct slcd_sync_descriptor SEGMENT_LCD_0; | ||||||
| 
 | 
 | ||||||
| void ADC_0_PORT_init(void); |  | ||||||
| void ADC_0_CLOCK_init(void); |  | ||||||
| void ADC_0_init(void); |  | ||||||
| 
 |  | ||||||
| void CALENDAR_0_CLOCK_init(void); |  | ||||||
| void CALENDAR_0_init(void); |  | ||||||
| 
 |  | ||||||
| void I2C_0_CLOCK_init(void); | void I2C_0_CLOCK_init(void); | ||||||
| void I2C_0_init(void); | void I2C_0_init(void); | ||||||
| void I2C_0_PORT_init(void); | void I2C_0_PORT_init(void); | ||||||
| 
 | 
 | ||||||
| void delay_driver_init(void); | void delay_driver_init(void); | ||||||
| 
 | 
 | ||||||
| void PWM_0_PORT_init(void); |  | ||||||
| void PWM_0_CLOCK_init(void); |  | ||||||
| void PWM_0_init(void); |  | ||||||
| 
 |  | ||||||
| void PWM_1_PORT_init(void); |  | ||||||
| void PWM_1_CLOCK_init(void); |  | ||||||
| void PWM_1_init(void); |  | ||||||
| 
 |  | ||||||
| void EXTERNAL_IRQ_0_init(void); | void EXTERNAL_IRQ_0_init(void); | ||||||
| 
 | 
 | ||||||
| void SEGMENT_LCD_0_init(void); | void SEGMENT_LCD_0_init(void); | ||||||
|  | |||||||
| @ -29,24 +29,9 @@ | |||||||
| #warning This board revision does not support external wake on BTN_ALARM, so watch_register_extwake_callback will not work with it. Use watch_register_interrupt_callback instead. | #warning This board revision does not support external wake on BTN_ALARM, so watch_register_extwake_callback will not work with it. Use watch_register_interrupt_callback instead. | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| static void extwake_callback(uint8_t reason); |  | ||||||
| ext_irq_cb_t btn_alarm_callback; |  | ||||||
| ext_irq_cb_t a2_callback; |  | ||||||
| ext_irq_cb_t a4_callback; |  | ||||||
| 
 |  | ||||||
|  static void extwake_callback(uint8_t reason) { |  | ||||||
|     if (reason & RTC_TAMPID_TAMPID2) { |  | ||||||
|         if (btn_alarm_callback != NULL) btn_alarm_callback(); |  | ||||||
|     } else if (reason & RTC_TAMPID_TAMPID1) { |  | ||||||
|         if (a2_callback != NULL) a2_callback(); |  | ||||||
|     } else if (reason & RTC_TAMPID_TAMPID0) { |  | ||||||
|         if (a4_callback != NULL) 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) { | ||||||
|     uint32_t pinmux; |     uint32_t pinmux; | ||||||
|     hri_rtc_tampctrl_reg_t config = hri_rtc_get_TAMPCTRL_reg(RTC, 0xFFFFFFFF); |     hri_rtc_tampctrl_reg_t config = RTC->MODE2.TAMPCTRL.reg; | ||||||
| 
 | 
 | ||||||
|     switch (pin) { |     switch (pin) { | ||||||
|         case A4: |         case A4: | ||||||
| @ -84,16 +69,17 @@ void watch_register_extwake_callback(uint8_t pin, ext_irq_cb_t callback, bool le | |||||||
|     gpio_set_pin_function(pin, pinmux); |     gpio_set_pin_function(pin, pinmux); | ||||||
| 
 | 
 | ||||||
|     // disable the RTC
 |     // disable the RTC
 | ||||||
| 	if (hri_rtcmode0_get_CTRLA_ENABLE_bit(RTC)) { |     RTC->MODE2.CTRLA.bit.ENABLE = 0; | ||||||
| 		hri_rtcmode0_clear_CTRLA_ENABLE_bit(RTC); |     while (RTC->MODE2.SYNCBUSY.bit.ENABLE); | ||||||
| 		hri_rtcmode0_wait_for_sync(RTC, RTC_MODE0_SYNCBUSY_ENABLE); |  | ||||||
| 	} |  | ||||||
|     // update the configuration
 |  | ||||||
|     hri_rtc_write_TAMPCTRL_reg(RTC, config); |  | ||||||
|     // re-enable the RTC
 |  | ||||||
|     hri_rtcmode0_set_CTRLA_ENABLE_bit(RTC); |  | ||||||
| 
 | 
 | ||||||
|     _extwake_register_callback(&CALENDAR_0.device, extwake_callback); |     // update the configuration
 | ||||||
|  |     RTC->MODE2.TAMPCTRL.reg = config; | ||||||
|  |     // re-enable the RTC
 | ||||||
|  |     RTC->MODE2.CTRLA.bit.ENABLE = 1; | ||||||
|  | 
 | ||||||
|  |     NVIC_ClearPendingIRQ(RTC_IRQn); | ||||||
|  |     NVIC_EnableIRQ(RTC_IRQn); | ||||||
|  |     RTC->MODE2.INTENSET.reg = RTC_MODE2_INTENSET_TAMPER; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void watch_disable_extwake_interrupt(uint8_t pin) { | void watch_disable_extwake_interrupt(uint8_t pin) { | ||||||
| @ -176,7 +162,7 @@ void watch_enter_shallow_sleep(char *message) { | |||||||
|     _watch_disable_all_peripherals_except_slcd(); |     _watch_disable_all_peripherals_except_slcd(); | ||||||
| 
 | 
 | ||||||
|     // disable tick interrupt
 |     // disable tick interrupt
 | ||||||
|     watch_register_tick_callback(NULL); |     watch_disable_tick_callback(); | ||||||
| 
 | 
 | ||||||
|     // disable brownout detector interrupt, which could inadvertently wake us up.
 |     // disable brownout detector interrupt, which could inadvertently wake us up.
 | ||||||
|     SUPC->INTENCLR.bit.BOD33DET = 1; |     SUPC->INTENCLR.bit.BOD33DET = 1; | ||||||
| @ -202,7 +188,7 @@ void watch_enter_deep_sleep() { | |||||||
|     // so let's do it!
 |     // so let's do it!
 | ||||||
|     watch_register_extwake_callback(BTN_ALARM, NULL, true); |     watch_register_extwake_callback(BTN_ALARM, NULL, true); | ||||||
| 
 | 
 | ||||||
|     watch_register_tick_callback(NULL); |     watch_disable_tick_callback(); | ||||||
|     _watch_disable_all_peripherals_except_slcd(); |     _watch_disable_all_peripherals_except_slcd(); | ||||||
|     slcd_sync_deinit(&SEGMENT_LCD_0); |     slcd_sync_deinit(&SEGMENT_LCD_0); | ||||||
|     hri_mclk_clear_APBCMASK_SLCD_bit(SLCD); |     hri_mclk_clear_APBCMASK_SLCD_bit(SLCD); | ||||||
|  | |||||||
| @ -23,6 +23,11 @@ | |||||||
|  */ |  */ | ||||||
| ////< @file watch_deepsleep.h
 | ////< @file watch_deepsleep.h
 | ||||||
| 
 | 
 | ||||||
|  | // These are declared in watch_rtc.c.
 | ||||||
|  | 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
 | /** @addtogroup deepsleep Deep Sleep Control
 | ||||||
|   * @brief This section covers functions related to preparing for and entering BACKUP mode, the |   * @brief This section covers functions related to preparing for and entering BACKUP mode, the | ||||||
|   *        deepest sleep mode available on the SAM L22 |   *        deepest sleep mode available on the SAM L22 | ||||||
|  | |||||||
| @ -56,8 +56,7 @@ void _watch_init() { | |||||||
|     SUPC->BOD33.bit.ENABLE = 1; |     SUPC->BOD33.bit.ENABLE = 1; | ||||||
| 
 | 
 | ||||||
|     // External wake depends on RTC; calendar is a required module.
 |     // External wake depends on RTC; calendar is a required module.
 | ||||||
|     CALENDAR_0_init(); |     _watch_rtc_init(); | ||||||
|     calendar_enable(&CALENDAR_0); |  | ||||||
| 
 | 
 | ||||||
|     // set up state
 |     // set up state
 | ||||||
|     btn_alarm_callback = NULL; |     btn_alarm_callback = NULL; | ||||||
|  | |||||||
| @ -22,19 +22,153 @@ | |||||||
|  * SOFTWARE. |  * SOFTWARE. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  bool _watch_rtc_is_enabled() { | ext_irq_cb_t tick_callback; | ||||||
|     return RTC->MODE0.CTRLA.bit.ENABLE; | ext_irq_cb_t alarm_callback; | ||||||
|  | ext_irq_cb_t btn_alarm_callback; | ||||||
|  | ext_irq_cb_t a2_callback; | ||||||
|  | ext_irq_cb_t a4_callback; | ||||||
|  | 
 | ||||||
|  | bool _watch_rtc_is_enabled() { | ||||||
|  |     return RTC->MODE2.CTRLA.bit.ENABLE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void watch_set_date_time(struct calendar_date_time date_time) { | void _sync_rtc() { | ||||||
|     calendar_set_date(&CALENDAR_0, &date_time.date); |     while (RTC->MODE2.SYNCBUSY.reg); | ||||||
|     calendar_set_time(&CALENDAR_0, &date_time.time); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void watch_get_date_time(struct calendar_date_time *date_time) { | void _watch_rtc_init() { | ||||||
|     calendar_get_date_time(&CALENDAR_0, date_time); |     MCLK->APBAMASK.reg |= MCLK_APBAMASK_RTC; | ||||||
|  | 
 | ||||||
|  |     if (_watch_rtc_is_enabled()) return; // don't reset the RTC if it's already set up.
 | ||||||
|  | 
 | ||||||
|  |     RTC->MODE2.CTRLA.bit.ENABLE = 0; | ||||||
|  |     _sync_rtc(); | ||||||
|  | 
 | ||||||
|  |     RTC->MODE2.CTRLA.bit.SWRST = 1; | ||||||
|  |     _sync_rtc(); | ||||||
|  | 
 | ||||||
|  |     RTC->MODE2.CTRLA.bit.MODE = RTC_MODE2_CTRLA_MODE_CLOCK_Val; | ||||||
|  |     RTC->MODE2.CTRLA.bit.PRESCALER = RTC_MODE2_CTRLA_PRESCALER_DIV1024_Val; | ||||||
|  |     RTC->MODE2.CTRLA.bit.CLOCKSYNC = 1; | ||||||
|  |     RTC->MODE2.CTRLA.bit.ENABLE = 1; | ||||||
|  |     _sync_rtc(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void watch_rtc_set_date_time(watch_date_time date_time) { | ||||||
|  |     RTC_MODE2_CLOCK_Type val; | ||||||
|  | 
 | ||||||
|  |     val.bit.SECOND = date_time.second; | ||||||
|  |     val.bit.MINUTE = date_time.minute; | ||||||
|  |     val.bit.HOUR = date_time.hour; | ||||||
|  |     val.bit.DAY = date_time.day; | ||||||
|  |     val.bit.MONTH = date_time.month; | ||||||
|  |     val.bit.YEAR = (uint8_t)(date_time.year - WATCH_RTC_REFERENCE_YEAR); | ||||||
|  | 
 | ||||||
|  |     RTC->MODE2.CLOCK.reg = val.reg; | ||||||
|  |     _sync_rtc(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | watch_date_time watch_rtc_get_date_time() { | ||||||
|  |     watch_date_time retval; | ||||||
|  | 
 | ||||||
|  |     _sync_rtc(); | ||||||
|  |     RTC_MODE2_CLOCK_Type val = RTC->MODE2.CLOCK; | ||||||
|  | 
 | ||||||
|  |     retval.year = val.bit.YEAR + WATCH_RTC_REFERENCE_YEAR; | ||||||
|  |     retval.month = val.bit.MONTH; | ||||||
|  |     retval.day = val.bit.DAY; | ||||||
|  |     retval.hour = val.bit.HOUR; | ||||||
|  |     retval.minute = val.bit.MINUTE; | ||||||
|  |     retval.second = val.bit.SECOND; | ||||||
|  | 
 | ||||||
|  |     return retval; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void watch_register_tick_callback(ext_irq_cb_t callback) { | void watch_register_tick_callback(ext_irq_cb_t callback) { | ||||||
|     _prescaler_register_callback(&CALENDAR_0.device, callback); |     tick_callback = callback; | ||||||
|  |     NVIC_ClearPendingIRQ(RTC_IRQn); | ||||||
|  |     NVIC_EnableIRQ(RTC_IRQn); | ||||||
|  |     RTC->MODE2.INTENSET.reg = RTC_MODE2_INTENSET_PER7; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void watch_disable_tick_callback() { | ||||||
|  |     RTC->MODE2.INTENCLR.reg = RTC_MODE2_INTENCLR_PER7; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void watch_rtc_register_alarm_callback(ext_irq_cb_t callback, watch_date_time alarm_time, watch_rtc_alarm_match mask) { | ||||||
|  |     RTC->MODE2.Mode2Alarm[0].ALARM.bit.SECOND = alarm_time.second; | ||||||
|  |     RTC->MODE2.Mode2Alarm[0].ALARM.bit.MINUTE = alarm_time.minute; | ||||||
|  |     RTC->MODE2.Mode2Alarm[0].ALARM.bit.HOUR = alarm_time.hour; | ||||||
|  |     RTC->MODE2.Mode2Alarm[0].ALARM.bit.DAY = alarm_time.day; | ||||||
|  |     RTC->MODE2.Mode2Alarm[0].ALARM.bit.MONTH = alarm_time.month; | ||||||
|  |     RTC->MODE2.Mode2Alarm[0].ALARM.bit.YEAR = (uint8_t)(alarm_time.year - WATCH_RTC_REFERENCE_YEAR); | ||||||
|  |     RTC->MODE2.Mode2Alarm[0].MASK.reg = mask; | ||||||
|  | 
 | ||||||
|  |     RTC->MODE2.INTENSET.reg = RTC_MODE2_INTENSET_ALARM0; | ||||||
|  |     alarm_callback = callback; | ||||||
|  |     NVIC_ClearPendingIRQ(RTC_IRQn); | ||||||
|  |     NVIC_EnableIRQ(RTC_IRQn); | ||||||
|  |     RTC->MODE2.INTENSET.reg = RTC_MODE2_INTENSET_ALARM0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void watch_rtc_disable_alarm_callback() { | ||||||
|  |     RTC->MODE2.INTENCLR.reg = RTC_MODE2_INTENCLR_ALARM0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void RTC_Handler(void) { | ||||||
|  |     uint16_t interrupt_status = RTC->MODE2.INTFLAG.reg; | ||||||
|  |     uint16_t interrupt_enabled = RTC->MODE2.INTENSET.reg; | ||||||
|  | 
 | ||||||
|  |     if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_ALARM0) { | ||||||
|  |         if (alarm_callback != NULL) { | ||||||
|  |             alarm_callback(); | ||||||
|  |         } | ||||||
|  |         RTC->MODE2.INTFLAG.reg = RTC_MODE2_INTFLAG_ALARM0; | ||||||
|  |     } else if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_PER7) { | ||||||
|  |         if (tick_callback != NULL) { | ||||||
|  |             tick_callback(); | ||||||
|  |         } | ||||||
|  |         RTC->MODE2.INTFLAG.reg = RTC_MODE2_INTFLAG_PER7; | ||||||
|  |     } else if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_TAMPER) { | ||||||
|  |         uint8_t reason = RTC->MODE2.TAMPID.reg; | ||||||
|  |         if (reason & RTC_TAMPID_TAMPID2) { | ||||||
|  |             if (btn_alarm_callback != NULL) btn_alarm_callback(); | ||||||
|  |         } else if (reason & RTC_TAMPID_TAMPID1) { | ||||||
|  |             if (a2_callback != NULL) a2_callback(); | ||||||
|  |         } else if (reason & RTC_TAMPID_TAMPID0) { | ||||||
|  |             if (a4_callback != NULL) a4_callback(); | ||||||
|  |         } | ||||||
|  |         RTC->MODE2.TAMPID.reg = reason; | ||||||
|  |         RTC->MODE2.INTFLAG.reg = RTC_MODE2_INTFLAG_TAMPER; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ///////////////////////
 | ||||||
|  | // Deprecated functions
 | ||||||
|  | 
 | ||||||
|  | void watch_set_date_time(struct calendar_date_time date_time) { | ||||||
|  |     RTC_MODE2_CLOCK_Type val; | ||||||
|  | 
 | ||||||
|  |     val.bit.SECOND = date_time.time.sec; | ||||||
|  |     val.bit.MINUTE = date_time.time.min; | ||||||
|  |     val.bit.HOUR = date_time.time.hour; | ||||||
|  |     val.bit.DAY = date_time.date.day; | ||||||
|  |     val.bit.MONTH = date_time.date.month; | ||||||
|  |     val.bit.YEAR = (uint8_t)(date_time.date.year - WATCH_RTC_REFERENCE_YEAR); | ||||||
|  | 
 | ||||||
|  |     RTC->MODE2.CLOCK.reg = val.reg; | ||||||
|  | 
 | ||||||
|  |     _sync_rtc(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void watch_get_date_time(struct calendar_date_time *date_time) { | ||||||
|  |     _sync_rtc(); | ||||||
|  |     RTC_MODE2_CLOCK_Type val = RTC->MODE2.CLOCK; | ||||||
|  | 
 | ||||||
|  |     date_time->time.sec = val.bit.SECOND; | ||||||
|  |     date_time->time.min = val.bit.MINUTE; | ||||||
|  |     date_time->time.hour = val.bit.HOUR; | ||||||
|  |     date_time->date.day = val.bit.DAY; | ||||||
|  |     date_time->date.month = val.bit.MONTH; | ||||||
|  |     date_time->date.year = val.bit.YEAR + WATCH_RTC_REFERENCE_YEAR; | ||||||
| } | } | ||||||
|  | |||||||
| @ -35,24 +35,84 @@ | |||||||
|   *          to wake from STANDBY mode. |   *          to wake from STANDBY mode. | ||||||
|   */ |   */ | ||||||
| /// @{
 | /// @{
 | ||||||
|  | 
 | ||||||
|  | #define WATCH_RTC_REFERENCE_YEAR (2020) | ||||||
|  | 
 | ||||||
|  | typedef struct watch_date_time { | ||||||
|  |     uint16_t year; | ||||||
|  |     uint8_t month; | ||||||
|  |     uint8_t day; | ||||||
|  |     uint8_t hour; | ||||||
|  |     uint8_t minute; | ||||||
|  |     uint8_t second; | ||||||
|  | } watch_date_time; | ||||||
|  | 
 | ||||||
|  | typedef enum watch_rtc_alarm_match { | ||||||
|  |     ALARM_MATCH_DISABLED = 0, | ||||||
|  |     ALARM_MATCH_SS, | ||||||
|  |     ALARM_MATCH_MMSS, | ||||||
|  |     ALARM_MATCH_HHMMSS, | ||||||
|  | } watch_rtc_alarm_match; | ||||||
|  | 
 | ||||||
| /** @brief Called by main.c to check if the RTC is enabled.
 | /** @brief Called by main.c to check if the RTC is enabled.
 | ||||||
|   * You may call this function, but outside of app_init, it sbould always return true. |   * You may call this function, but outside of app_init, it should always return true. | ||||||
|   */ |   */ | ||||||
| bool _watch_rtc_is_enabled(); | bool _watch_rtc_is_enabled(); | ||||||
| 
 | 
 | ||||||
|  | /** @brief Sets the date and time.
 | ||||||
|  |   * @param date_time The time you wish to set. | ||||||
|  |   * @note Internally, the SAM L22 stores the year as six bits representing a value from 0 to 63. It treats this | ||||||
|  |   *       as a year offset from a reference year, which must be a leap year. For now, this library uses 2020 as | ||||||
|  |   *       the reference year, so the range of valid values is 2020 to 2083. | ||||||
|  |   */ | ||||||
|  | void watch_rtc_set_date_time(watch_date_time date_time); | ||||||
|  | 
 | ||||||
|  | /** @brief Returns the system date and time in the provided struct.
 | ||||||
|  |   * @return A watch_date_time with the current date and time. | ||||||
|  |   */ | ||||||
|  | watch_date_time watch_rtc_get_date_time(); | ||||||
|  | 
 | ||||||
|  | /** @brief Registers an alarm callback that will be called when the RTC time matches the target time, as masked
 | ||||||
|  |   *        by the provided mask. | ||||||
|  |   * @param callback The function you wish to have called when the alarm fires. If this value is NULL, the alarm | ||||||
|  |   *                 interrupt will still be enabled, but no callback function will be called. | ||||||
|  |   * @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. | ||||||
|  |   *           * 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. | ||||||
|  |   *          In theory the SAM L22's alarm function can match on days, months and even years, but I have not had | ||||||
|  |   *          success with this yet; as such, I am omitting these options for now. | ||||||
|  |   */ | ||||||
|  | void watch_rtc_register_alarm_callback(ext_irq_cb_t callback, watch_date_time alarm_time, watch_rtc_alarm_match mask); | ||||||
|  | 
 | ||||||
|  | /** @brief Disables the alarm callback.
 | ||||||
|  |   */ | ||||||
|  | void watch_rtc_disable_alarm_callback(); | ||||||
|  | 
 | ||||||
|  | /** @brief Registers a "tick" callback that will be called once per second.
 | ||||||
|  |   * @param callback The function you wish to have called when the clock ticks. If you pass in NULL, the tick | ||||||
|  |   *                 interrupt will still be enabled, but no callback function will be called. | ||||||
|  |   */ | ||||||
|  | void watch_register_tick_callback(ext_irq_cb_t callback); | ||||||
|  | 
 | ||||||
|  | /** @brief Disables the tick callback.
 | ||||||
|  |   */ | ||||||
|  | void watch_disable_tick_callback(); | ||||||
|  | 
 | ||||||
| /** @brief Sets the system date and time.
 | /** @brief Sets the system date and time.
 | ||||||
|   * @param date_time A struct representing the date and time you wish to set. |   * @param date_time A struct representing the date and time you wish to set. | ||||||
|   */ |   */ | ||||||
|  | __attribute__((deprecated("Use watch_rtc_set_date_time function instead"))) | ||||||
| void watch_set_date_time(struct calendar_date_time date_time); | void watch_set_date_time(struct calendar_date_time date_time); | ||||||
| 
 | 
 | ||||||
| /** @brief Returns the system date and time in the provided struct.
 | /** @brief Returns the system date and time in the provided struct.
 | ||||||
|   * @param date_time A pointer to a calendar_date_time struct. |   * @param date_time A pointer to a calendar_date_time struct. It will have with the correct date and time on return. | ||||||
|                      It will be populated with the correct date and time on return. |  | ||||||
|   */ |   */ | ||||||
|  | __attribute__((deprecated("Use the watch_rtc_get_date_time function instead"))) | ||||||
| void watch_get_date_time(struct calendar_date_time *date_time); | void watch_get_date_time(struct calendar_date_time *date_time); | ||||||
| 
 | 
 | ||||||
| /** @brief Registers a "tick" callback that will be called once per second.
 |  | ||||||
|   * @param callback The function you wish to have called when the clock ticks. |  | ||||||
|   */ |  | ||||||
| void watch_register_tick_callback(ext_irq_cb_t callback); |  | ||||||
| /// @}
 | /// @}
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user