diff options
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/rtc.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/firmware/drivers/rtc.c b/firmware/drivers/rtc.c index 5f60c23bdd..0e65a8be5b 100644 --- a/firmware/drivers/rtc.c +++ b/firmware/drivers/rtc.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #ifdef HAVE_RTC | 20 | #ifdef HAVE_RTC |
21 | #include "i2c.h" | 21 | #include "i2c.h" |
22 | #include "rtc.h" | 22 | #include "rtc.h" |
23 | #include "kernel.h" | ||
23 | #include <stdbool.h> | 24 | #include <stdbool.h> |
24 | 25 | ||
25 | #define RTC_ADR 0xd0 | 26 | #define RTC_ADR 0xd0 |
@@ -31,7 +32,7 @@ void rtc_init(void) | |||
31 | unsigned char data; | 32 | unsigned char data; |
32 | 33 | ||
33 | #ifdef HAVE_ALARM_MOD | 34 | #ifdef HAVE_ALARM_MOD |
34 | /* Check + save alarm bit first, since something in rtc_init resets AF */ | 35 | /* Check + save alarm bit first, before the power thread starts watching */ |
35 | rtc_check_alarm_started(false); | 36 | rtc_check_alarm_started(false); |
36 | #endif | 37 | #endif |
37 | 38 | ||
@@ -67,7 +68,6 @@ void rtc_init(void) | |||
67 | otherwise the player can't be turned off. */ | 68 | otherwise the player can't be turned off. */ |
68 | rtc_write(8, rtc_read(8) | 0x80); | 69 | rtc_write(8, rtc_read(8) | 0x80); |
69 | 70 | ||
70 | rtc_enable_alarm(false); | ||
71 | #endif | 71 | #endif |
72 | } | 72 | } |
73 | 73 | ||
@@ -85,12 +85,23 @@ bool rtc_check_alarm_started(bool release_alarm) | |||
85 | alarm_state &= ~release_alarm; | 85 | alarm_state &= ~release_alarm; |
86 | } else { | 86 | } else { |
87 | /* This call resets AF, so we store the state for later recall */ | 87 | /* This call resets AF, so we store the state for later recall */ |
88 | rc = alarm_state = ((rtc_read(0x0f) & 0x40) != 0); | 88 | rc = alarm_state = rtc_check_alarm_flag(); |
89 | run_before = true; | 89 | run_before = true; |
90 | } | 90 | } |
91 | 91 | ||
92 | return rc; | 92 | return rc; |
93 | } | 93 | } |
94 | /* | ||
95 | * Checks the AL register. This call resets AL once read. | ||
96 | * | ||
97 | * We're only interested if ABE is set. AL is still raised regardless | ||
98 | * even if the unit is off when the alarm occurs. | ||
99 | */ | ||
100 | bool rtc_check_alarm_flag(void) | ||
101 | { | ||
102 | return ( ( (rtc_read(0x0f) & 0x40) != 0) && | ||
103 | (rtc_read(0x0a) & 0x20) ); | ||
104 | } | ||
94 | 105 | ||
95 | /* set alarm time registers to the given time (repeat once per day) */ | 106 | /* set alarm time registers to the given time (repeat once per day) */ |
96 | void rtc_set_alarm(int h, int m) | 107 | void rtc_set_alarm(int h, int m) |
@@ -140,14 +151,21 @@ bool rtc_enable_alarm(bool enable) | |||
140 | rtc_write(0x0a, data); | 151 | rtc_write(0x0a, data); |
141 | 152 | ||
142 | /* check if alarm flag AF is off (as it should be) */ | 153 | /* check if alarm flag AF is off (as it should be) */ |
143 | if ((rtc_read(0x0f) & 0x40) != 0) /* on */ | 154 | /* in some cases enabling the alarm results in an activated AF flag */ |
155 | /* this should not happen, but it does */ | ||
156 | /* if you know why, tell me! */ | ||
157 | /* for now, we try again forever in this case */ | ||
158 | while (rtc_check_alarm_flag()) /* on */ | ||
144 | { | 159 | { |
145 | data &= 0x5f; /* turn bit d7=AFE and d5=ABE off */ | 160 | data &= 0x5f; /* turn bit d7=AFE and d5=ABE off */ |
146 | rtc_write(0x0a, data); | 161 | rtc_write(0x0a, data); |
147 | return true; | 162 | sleep(HZ / 10); |
148 | } else { | 163 | rtc_check_alarm_flag(); |
149 | return false; /* all ok */ | 164 | data |= 0xa0; /* turn bit d7=AFE and d5=ABE on */ |
165 | rtc_write(0x0a, data); | ||
150 | } | 166 | } |
167 | |||
168 | return false; /* all ok */ | ||
151 | } | 169 | } |
152 | 170 | ||
153 | #endif /* HAVE_ALARM_MOD */ | 171 | #endif /* HAVE_ALARM_MOD */ |