-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Feature - RTC alarm on every second #370
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 5 commits
b3fa3e6
61309a6
f945ab8
66ceabd
eddfce4
3deda98
82a4681
27cb80e
ecedcbe
1a6884b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,14 @@ | |
|
||
// Set this when setting an alarm | ||
static rtc_callback_t _callback = NULL; | ||
static bool _alarm_repeats = false; | ||
|
||
typedef enum { | ||
NO_REPEAT = 0, | ||
CONTINUOUS_REPEAT = 1, | ||
CONTINUOUS_REPEAT_ON_SEC = 2, | ||
} repeat_type; | ||
|
||
static repeat_type _alarm_repeats = NO_REPEAT; | ||
|
||
bool rtc_running(void) { | ||
return (rtc_hw->ctrl & RTC_CTRL_RTC_ACTIVE_BITS); | ||
|
@@ -39,7 +46,7 @@ void rtc_init(void) { | |
rtc_hw->clkdiv_m1 = rtc_freq; | ||
} | ||
|
||
static bool valid_datetime(datetime_t *t) { | ||
static bool valid_datetime(const datetime_t *t) { | ||
// Valid ranges taken from RTC doc. Note when setting an RTC alarm | ||
// these values are allowed to be -1 to say "don't match this value" | ||
if (!(t->year >= 0 && t->year <= 4095)) return false; | ||
|
@@ -52,7 +59,7 @@ static bool valid_datetime(datetime_t *t) { | |
return true; | ||
} | ||
|
||
bool rtc_set_datetime(datetime_t *t) { | ||
bool rtc_set_datetime(const datetime_t *t) { | ||
if (!valid_datetime(t)) { | ||
return false; | ||
} | ||
|
@@ -114,6 +121,14 @@ void rtc_enable_alarm(void) { | |
} | ||
} | ||
|
||
void rtc_disable_alarm(void) { | ||
// Disable matching and wait for it to stop being active | ||
hw_clear_bits(&rtc_hw->irq_setup_0, RTC_IRQ_SETUP_0_MATCH_ENA_BITS); | ||
while (rtc_hw->irq_setup_0 & RTC_IRQ_SETUP_0_MATCH_ACTIVE_BITS) { | ||
tight_loop_contents(); | ||
} | ||
} | ||
|
||
static void rtc_irq_handler(void) { | ||
// Always disable the alarm to clear the current IRQ. | ||
// Even if it is a repeatable alarm, we don't want it to keep firing. | ||
|
@@ -122,6 +137,11 @@ static void rtc_irq_handler(void) { | |
|
||
if (_alarm_repeats) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should all the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a question of coding guidelines. Technically it's the same There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair enough, that's a Graham-decision then 🙂 |
||
// If it is a repeatable alarm, re enable the alarm. | ||
if(_alarm_repeats == CONTINUOUS_REPEAT_ON_SEC) { | ||
datetime_t t; | ||
rtc_get_datetime(&t); | ||
rtc_hw->irq_setup_1 = RTC_IRQ_SETUP_1_SEC_ENA_BITS | ((((uint)t.sec + 1) % 60) << RTC_IRQ_SETUP_1_SEC_LSB); | ||
Reneg973 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
rtc_enable_alarm(); | ||
} | ||
|
||
|
@@ -131,43 +151,46 @@ static void rtc_irq_handler(void) { | |
} | ||
} | ||
|
||
static bool rtc_alarm_repeats(datetime_t *t) { | ||
// If any value is set to -1 then we don't match on that value | ||
// hence the alarm will eventually repeat | ||
if (t->year < 0) return true; | ||
if (t->month < 0) return true; | ||
if (t->day < 0) return true; | ||
if (t->dotw < 0) return true; | ||
if (t->hour < 0) return true; | ||
if (t->min < 0) return true; | ||
if (t->sec < 0) return true; | ||
return false; | ||
// return != 0 on repeat, -1 on repeat every second | ||
Reneg973 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
static int8_t rtc_alarm_repeats(const datetime_t *t) { | ||
Reneg973 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
// If any value is set to -1 then we don't match on that value | ||
// hence the alarm will eventually repeat | ||
if((t->year & t->month & t->day & t->dotw & t->hour & t->min & t->sec) < 0) return CONTINUOUS_REPEAT_ON_SEC; | ||
Reneg973 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
return (t->year < 0 || t->month < 0 || t->day < 0 || t->dotw < 0 | ||
|| t->hour < 0 || t->min < 0 || t->sec < 0) | ||
? CONTINUOUS_REPEAT : NO_REPEAT; | ||
} | ||
|
||
void rtc_set_alarm(datetime_t *t, rtc_callback_t user_callback) { | ||
bool rtc_set_alarm(const datetime_t *t, rtc_callback_t user_callback) { | ||
rtc_disable_alarm(); | ||
|
||
// Only add to setup if it isn't -1 | ||
rtc_hw->irq_setup_0 = ((t->year < 0) ? 0 : (((uint)t->year) << RTC_IRQ_SETUP_0_YEAR_LSB )) | | ||
((t->month < 0) ? 0 : (((uint)t->month) << RTC_IRQ_SETUP_0_MONTH_LSB)) | | ||
((t->day < 0) ? 0 : (((uint)t->day) << RTC_IRQ_SETUP_0_DAY_LSB )); | ||
rtc_hw->irq_setup_1 = ((t->dotw < 0) ? 0 : (((uint)t->dotw) << RTC_IRQ_SETUP_1_DOTW_LSB)) | | ||
((t->hour < 0) ? 0 : (((uint)t->hour) << RTC_IRQ_SETUP_1_HOUR_LSB)) | | ||
((t->min < 0) ? 0 : (((uint)t->min) << RTC_IRQ_SETUP_1_MIN_LSB )) | | ||
((t->sec < 0) ? 0 : (((uint)t->sec) << RTC_IRQ_SETUP_1_SEC_LSB )); | ||
|
||
// Set the match enable bits for things we care about | ||
if (t->year >= 0) hw_set_bits(&rtc_hw->irq_setup_0, RTC_IRQ_SETUP_0_YEAR_ENA_BITS); | ||
if (t->month >= 0) hw_set_bits(&rtc_hw->irq_setup_0, RTC_IRQ_SETUP_0_MONTH_ENA_BITS); | ||
if (t->day >= 0) hw_set_bits(&rtc_hw->irq_setup_0, RTC_IRQ_SETUP_0_DAY_ENA_BITS); | ||
if (t->dotw >= 0) hw_set_bits(&rtc_hw->irq_setup_1, RTC_IRQ_SETUP_1_DOTW_ENA_BITS); | ||
if (t->hour >= 0) hw_set_bits(&rtc_hw->irq_setup_1, RTC_IRQ_SETUP_1_HOUR_ENA_BITS); | ||
if (t->min >= 0) hw_set_bits(&rtc_hw->irq_setup_1, RTC_IRQ_SETUP_1_MIN_ENA_BITS); | ||
if (t->sec >= 0) hw_set_bits(&rtc_hw->irq_setup_1, RTC_IRQ_SETUP_1_SEC_ENA_BITS); | ||
uint32_t s0 = 0, s1 = 0; | ||
|
||
// Does it repeat? I.e. do we not match on any of the bits | ||
_alarm_repeats = rtc_alarm_repeats(t); | ||
|
||
if( (!valid_datetime(t) && !_alarm_repeats) || !user_callback) // none of the parameters is valid | ||
Reneg973 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Reneg973 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
return false; | ||
|
||
// Set the match enable bits for things we care about | ||
if (t->year >= 0) s0 |= RTC_IRQ_SETUP_0_YEAR_ENA_BITS | (((uint)t->year) << RTC_IRQ_SETUP_0_YEAR_LSB ); | ||
if (t->month >= 1) s0 |= RTC_IRQ_SETUP_0_MONTH_ENA_BITS | (((uint)t->month) << RTC_IRQ_SETUP_0_MONTH_LSB); | ||
if (t->day >= 1) s0 |= RTC_IRQ_SETUP_0_DAY_ENA_BITS | (((uint)t->day) << RTC_IRQ_SETUP_0_DAY_LSB ); | ||
|
||
if (t->dotw >= 0) s1 |= RTC_IRQ_SETUP_1_DOTW_ENA_BITS | (((uint)t->dotw) << RTC_IRQ_SETUP_1_DOTW_LSB); | ||
if (t->hour >= 0) s1 |= RTC_IRQ_SETUP_1_HOUR_ENA_BITS | (((uint)t->hour) << RTC_IRQ_SETUP_1_HOUR_LSB); | ||
if (t->min >= 0) s1 |= RTC_IRQ_SETUP_1_MIN_ENA_BITS | (((uint)t->min) << RTC_IRQ_SETUP_1_MIN_LSB); | ||
if (t->sec >= 0) s1 |= RTC_IRQ_SETUP_1_SEC_ENA_BITS | (((uint)t->sec) << RTC_IRQ_SETUP_1_SEC_LSB); | ||
else if (_alarm_repeats == CONTINUOUS_REPEAT_ON_SEC) { | ||
Reneg973 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
// repeatable every second! All entries are -1 | ||
datetime_t new_dt; | ||
rtc_get_datetime(&new_dt); | ||
s1 = RTC_IRQ_SETUP_1_SEC_ENA_BITS | ((((uint)new_dt.sec + 1) % 60) << RTC_IRQ_SETUP_1_SEC_LSB); | ||
} | ||
|
||
rtc_hw->irq_setup_0 = s0; | ||
rtc_hw->irq_setup_1 = s1; | ||
|
||
// Store function pointer we can call later | ||
_callback = user_callback; | ||
|
||
|
@@ -180,12 +203,5 @@ void rtc_set_alarm(datetime_t *t, rtc_callback_t user_callback) { | |
irq_set_enabled(RTC_IRQ, true); | ||
|
||
rtc_enable_alarm(); | ||
} | ||
|
||
void rtc_disable_alarm(void) { | ||
// Disable matching and wait for it to stop being active | ||
hw_clear_bits(&rtc_hw->irq_setup_0, RTC_IRQ_SETUP_0_MATCH_ENA_BITS); | ||
while(rtc_hw->irq_setup_0 & RTC_IRQ_SETUP_0_MATCH_ACTIVE_BITS) { | ||
tight_loop_contents(); | ||
} | ||
return true; | ||
} |
Uh oh!
There was an error while loading. Please reload this page.