summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
authorThom Johansen <thomj@rockbox.org>2007-02-28 21:55:11 +0000
committerThom Johansen <thomj@rockbox.org>2007-02-28 21:55:11 +0000
commit8fd6d658a1caeddc0a84dd69ffe45739bd466e74 (patch)
tree91f79d4d40d898a303998710a18ae62d8b8c7082 /firmware/drivers
parentab66955664f8987d064247dc6d585b5618745d29 (diff)
downloadrockbox-8fd6d658a1caeddc0a84dd69ffe45739bd466e74.tar.gz
rockbox-8fd6d658a1caeddc0a84dd69ffe45739bd466e74.zip
Add wake on alarm support for Ipods. Rename HAVE_ALARM_MOD to HAVE_ALARM_RTC since it's not always a mod. Make Ipod PCF driver keep other flags in OOCC1 that have been set instead of overwriting them.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12522 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/pcf50605.c10
-rw-r--r--firmware/drivers/rtc/rtc_ds1339_ds3231.c6
-rw-r--r--firmware/drivers/rtc/rtc_m41st84w.c8
-rw-r--r--firmware/drivers/rtc/rtc_pcf50605.c94
4 files changed, 102 insertions, 16 deletions
diff --git a/firmware/drivers/pcf50605.c b/firmware/drivers/pcf50605.c
index 0610f41aec..cf4ea9fecb 100644
--- a/firmware/drivers/pcf50605.c
+++ b/firmware/drivers/pcf50605.c
@@ -89,10 +89,9 @@ int pcf50605_write(int address, unsigned char val)
89 89
90int pcf50605_write_multiple(int address, const unsigned char* buf, int count) 90int pcf50605_write_multiple(int address, const unsigned char* buf, int count)
91{ 91{
92 /* TODO */ 92 int i;
93 (void)address; 93 for (i = 0; i < count; i++)
94 (void)buf; 94 pp_i2c_send(0x8, address + i, buf[i]);
95 (void)count;
96 return 0; 95 return 0;
97} 96}
98 97
@@ -102,7 +101,8 @@ int pcf50605_write_multiple(int address, const unsigned char* buf, int count)
102 power on your iPod again. */ 101 power on your iPod again. */
103void pcf50605_standby_mode(void) 102void pcf50605_standby_mode(void)
104{ 103{
105 pcf50605_write(OOCC1, GOSTDBY | CHGWAK | EXTONWAK); 104 const char mask = pcf50605_read(OOCC1) | GOSTDBY | CHGWAK | EXTONWAK;
105 pcf50605_write(OOCC1, mask);
106} 106}
107 107
108void pcf50605_init(void) 108void pcf50605_init(void)
diff --git a/firmware/drivers/rtc/rtc_ds1339_ds3231.c b/firmware/drivers/rtc/rtc_ds1339_ds3231.c
index df67fed735..7396c2e0a1 100644
--- a/firmware/drivers/rtc/rtc_ds1339_ds3231.c
+++ b/firmware/drivers/rtc/rtc_ds1339_ds3231.c
@@ -33,14 +33,14 @@ void rtc_init(void)
33 /* read one byte from RTC; 0 on success */ 33 /* read one byte from RTC; 0 on success */
34 rtc_detected = !sw_i2c_read(RTC_ADDR, 0, &byte, 1); 34 rtc_detected = !sw_i2c_read(RTC_ADDR, 0, &byte, 1);
35 35
36#ifdef HAVE_ALARM_MOD 36#ifdef HAVE_RTC_ALARM
37 /* Check + save alarm bit first, before the power thread starts watching */ 37 /* Check + save alarm bit first, before the power thread starts watching */
38 rtc_check_alarm_started(false); 38 rtc_check_alarm_started(false);
39#endif 39#endif
40 40
41} 41}
42 42
43#ifdef HAVE_ALARM_MOD 43#ifdef HAVE_RTC_ALARM
44 44
45/* check whether the unit has been started by the RTC alarm function */ 45/* check whether the unit has been started by the RTC alarm function */
46/* (check for A2F, which => started using wakeup alarm) */ 46/* (check for A2F, which => started using wakeup alarm) */
@@ -117,7 +117,7 @@ bool rtc_enable_alarm(bool enable)
117 return false; /* all ok */ 117 return false; /* all ok */
118} 118}
119 119
120#endif /* HAVE_ALARM_MOD */ 120#endif /* HAVE_RTC_ALARM */
121 121
122int rtc_read_datetime(unsigned char* buf) 122int rtc_read_datetime(unsigned char* buf)
123{ 123{
diff --git a/firmware/drivers/rtc/rtc_m41st84w.c b/firmware/drivers/rtc/rtc_m41st84w.c
index 1d76867e13..4e861692d8 100644
--- a/firmware/drivers/rtc/rtc_m41st84w.c
+++ b/firmware/drivers/rtc/rtc_m41st84w.c
@@ -31,7 +31,7 @@ void rtc_init(void)
31{ 31{
32 unsigned char data; 32 unsigned char data;
33 33
34#ifdef HAVE_ALARM_MOD 34#ifdef HAVE_RTC_ALARM
35 /* Check + save alarm bit first, before the power thread starts watching */ 35 /* Check + save alarm bit first, before the power thread starts watching */
36 rtc_check_alarm_started(false); 36 rtc_check_alarm_started(false);
37#endif 37#endif
@@ -52,7 +52,7 @@ void rtc_init(void)
52 rtc_write(0x0c,data); 52 rtc_write(0x0c,data);
53 } 53 }
54 54
55#ifdef HAVE_ALARM_MOD 55#ifdef HAVE_RTC_ALARM
56 56
57 /* Clear Trec bit, write-protecting the RTC for 200ms when shutting off */ 57 /* Clear Trec bit, write-protecting the RTC for 200ms when shutting off */
58 /* without this, the alarm won't work! */ 58 /* without this, the alarm won't work! */
@@ -71,7 +71,7 @@ void rtc_init(void)
71#endif 71#endif
72} 72}
73 73
74#ifdef HAVE_ALARM_MOD 74#ifdef HAVE_RTC_ALARM
75 75
76/* check whether the unit has been started by the RTC alarm function */ 76/* check whether the unit has been started by the RTC alarm function */
77/* (check for AF, which => started using wakeup alarm) */ 77/* (check for AF, which => started using wakeup alarm) */
@@ -168,7 +168,7 @@ bool rtc_enable_alarm(bool enable)
168 return false; /* all ok */ 168 return false; /* all ok */
169} 169}
170 170
171#endif /* HAVE_ALARM_MOD */ 171#endif /* HAVE_RTC_ALARM */
172 172
173int rtc_write(unsigned char address, unsigned char value) 173int rtc_write(unsigned char address, unsigned char value)
174{ 174{
diff --git a/firmware/drivers/rtc/rtc_pcf50605.c b/firmware/drivers/rtc/rtc_pcf50605.c
index 1bc40146ff..fedcdd3cdf 100644
--- a/firmware/drivers/rtc/rtc_pcf50605.c
+++ b/firmware/drivers/rtc/rtc_pcf50605.c
@@ -24,8 +24,12 @@
24#include "pcf50605.h" 24#include "pcf50605.h"
25#include <stdbool.h> 25#include <stdbool.h>
26 26
27/* Values which each disable one alarm time register */
28static char alarm_disable[] = { 0x7f, 0x7f, 0x3f, 0x07, 0x3f, 0x1f, 0xff };
29
27void rtc_init(void) 30void rtc_init(void)
28{ 31{
32 rtc_check_alarm_started(false);
29} 33}
30 34
31int rtc_read_datetime(unsigned char* buf) 35int rtc_read_datetime(unsigned char* buf)
@@ -35,11 +39,93 @@ int rtc_read_datetime(unsigned char* buf)
35 39
36int rtc_write_datetime(unsigned char* buf) 40int rtc_write_datetime(unsigned char* buf)
37{ 41{
38 int i; 42 pcf50605_write_multiple(0x0a, buf, 7);
43 return 1;
44}
45
46/**
47 * Checks the PCF interrupt 1 register bit 7 to see if an alarm interrupt has
48 * triggered since last we checked.
49 */
50bool rtc_check_alarm_flag(void)
51{
52 return pcf50605_read(0x02) & 0x80;
53}
39 54
40 for (i=0;i<7;i++) { 55/**
41 pcf50605_write(0x0a+i, buf[i]); 56 * Enables or disables the alarm.
57 * The Ipod bootloader clears all PCF interrupt registers and always enables
58 * the "wake on RTC" bit on OOCC1, so we have to rely on other means to find
59 * out if we just woke from an alarm.
60 * Return value is always false for us.
61 */
62bool rtc_enable_alarm(bool enable)
63{
64 if (enable) {
65 /* Tell the PCF to ignore everything but second, minute and hour, so
66 * that an alarm will trigger the next time the alarm time occurs.
67 */
68 pcf50605_write_multiple(0x14, alarm_disable + 3, 4);
69 /* Unmask the alarm interrupt (might be unneeded) */
70 pcf50605_write(0x5, pcf50605_read(0x5) & ~0x80);
71 /* Make sure wake on RTC is set */
72 pcf50605_write(0x8, pcf50605_read(0x8) | 0x10);
73 } else {
74 /* We use this year to indicate a disabled alarm. If you happen to live
75 * around this time and are annoyed by this, feel free to seek out my
76 * grave and do something nasty to it.
77 */
78 pcf50605_write(0x17, 0x99);
42 } 79 }
80 return false;
81}
43 82
44 return 1; 83/**
84 * Check if alarm caused unit to start.
85 */
86bool rtc_check_alarm_started(bool release_alarm)
87{
88 static bool run_before = false, alarm_state;
89 bool rc;
90
91 if (run_before) {
92 rc = alarm_state;
93 alarm_state &= ~release_alarm;
94 } else {
95 char rt[3], at[3];
96 /* The Ipod bootloader seems to read (and thus clear) the PCF interrupt
97 * registers, so we need to find some other way to detect if an alarm
98 * just happened
99 */
100 pcf50605_read_multiple(0x0a, rt, 3);
101 pcf50605_read_multiple(0x11, at, 3);
102
103 /* If alarm time and real time match within 10 seconds of each other, we
104 * assume an alarm just triggered
105 */
106 rc = alarm_state = rt[1] == at[1] && rt[2] == at[2]
107 && (rt[0] - at[0]) <= 10;
108 run_before = true;
109 }
110 return rc;
111}
112
113void rtc_set_alarm(int h, int m)
114{
115 /* Set us to wake at the first second of the specified time */
116 pcf50605_write(0x11, 0);
117 /* Convert to BCD */
118 pcf50605_write(0x12, ((m/10) << 4) | m%10);
119 pcf50605_write(0x13, ((h/10) << 4) | h%10);
45} 120}
121
122void rtc_get_alarm(int *h, int *m)
123{
124 char buf[2];
125
126 pcf50605_read_multiple(0x12, buf, 2);
127 /* Convert from BCD */
128 *m = ((buf[0] >> 4) & 0x7)*10 + (buf[0] & 0x0f);
129 *h = ((buf[1] >> 4) & 0x3)*10 + (buf[1] & 0x0f);
130}
131