From a83ffb208f53a91aeab09b933e3544ec29919ce1 Mon Sep 17 00:00:00 2001 From: Christi Scarborough Date: Sun, 6 Feb 2005 17:21:42 +0000 Subject: A proper alarm clock for the V2/FM (and v1 with mod) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5818 a1c6a512-1295-4272-9138-f99709370657 --- firmware/drivers/rtc.c | 36 +++++++++++++++++++++++++++--------- firmware/export/rtc.h | 1 + firmware/powermgmt.c | 22 ++++++++++++++++++++-- 3 files changed, 48 insertions(+), 11 deletions(-) (limited to 'firmware') 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 @@ #ifdef HAVE_RTC #include "i2c.h" #include "rtc.h" +#include "kernel.h" #include #define RTC_ADR 0xd0 @@ -31,7 +32,7 @@ void rtc_init(void) unsigned char data; #ifdef HAVE_ALARM_MOD - /* Check + save alarm bit first, since something in rtc_init resets AF */ + /* Check + save alarm bit first, before the power thread starts watching */ rtc_check_alarm_started(false); #endif @@ -67,7 +68,6 @@ void rtc_init(void) otherwise the player can't be turned off. */ rtc_write(8, rtc_read(8) | 0x80); - rtc_enable_alarm(false); #endif } @@ -85,12 +85,23 @@ bool rtc_check_alarm_started(bool release_alarm) alarm_state &= ~release_alarm; } else { /* This call resets AF, so we store the state for later recall */ - rc = alarm_state = ((rtc_read(0x0f) & 0x40) != 0); + rc = alarm_state = rtc_check_alarm_flag(); run_before = true; } return rc; } +/* + * Checks the AL register. This call resets AL once read. + * + * We're only interested if ABE is set. AL is still raised regardless + * even if the unit is off when the alarm occurs. + */ +bool rtc_check_alarm_flag(void) +{ + return ( ( (rtc_read(0x0f) & 0x40) != 0) && + (rtc_read(0x0a) & 0x20) ); +} /* set alarm time registers to the given time (repeat once per day) */ void rtc_set_alarm(int h, int m) @@ -140,14 +151,21 @@ bool rtc_enable_alarm(bool enable) rtc_write(0x0a, data); /* check if alarm flag AF is off (as it should be) */ - if ((rtc_read(0x0f) & 0x40) != 0) /* on */ + /* in some cases enabling the alarm results in an activated AF flag */ + /* this should not happen, but it does */ + /* if you know why, tell me! */ + /* for now, we try again forever in this case */ + while (rtc_check_alarm_flag()) /* on */ { - data &= 0x5f; /* turn bit d7=AFE and d5=ABE off */ - rtc_write(0x0a, data); - return true; - } else { - return false; /* all ok */ + data &= 0x5f; /* turn bit d7=AFE and d5=ABE off */ + rtc_write(0x0a, data); + sleep(HZ / 10); + rtc_check_alarm_flag(); + data |= 0xa0; /* turn bit d7=AFE and d5=ABE on */ + rtc_write(0x0a, data); } + + return false; /* all ok */ } #endif /* HAVE_ALARM_MOD */ diff --git a/firmware/export/rtc.h b/firmware/export/rtc.h index 7c2bd94d9c..fd793bc887 100644 --- a/firmware/export/rtc.h +++ b/firmware/export/rtc.h @@ -32,6 +32,7 @@ void rtc_set_alarm(int h, int m); void rtc_get_alarm(int *h, int *m); bool rtc_enable_alarm(bool enable); bool rtc_check_alarm_started(bool release_alarm); +bool rtc_check_alarm_flag(void); #endif /* HAVE_ALARM_MOD */ #endif /* HAVE_RTC */ diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 4495f58d74..37715abcdd 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -36,6 +36,7 @@ #include "powermgmt.h" #include "backlight.h" #include "lcd.h" +#include "rtc.h" #ifdef CONFIG_TUNER #include "fmradio.h" #endif @@ -441,6 +442,15 @@ static void car_adapter_mode_processing(void) } #endif +/* Check to see whether or not we've received an alarm in the last second */ +#ifdef HAVE_ALARM_MOD +static void power_thread_rtc_process(void) +{ + + rtc_check_alarm_flag(); +} +#endif + /* * This function is called to do the relativly long sleep waits from within the * main power_thread loop while at the same time servicing any other periodic @@ -456,6 +466,9 @@ static void power_thread_sleep(int ticks) ticks -= small_ticks; car_adapter_mode_processing(); +#ifdef HAVE_ALARM_MOD + power_thread_rtc_process(); +#endif } #else sleep(ticks); /* no fast-processing functions, sleep the whole time */ @@ -491,7 +504,10 @@ static void power_thread(void) { /* never read power while disk is spinning, unless in USB mode */ if (ata_disk_is_active() && !usb_inserted()) { - sleep(HZ * 2); +#ifdef HAVE_ALARM_MOD + power_thread_rtc_process(); +#endif + sleep(HZ); continue; } @@ -876,7 +892,9 @@ void powermgmt_init(void) #endif /* SIMULATOR */ -void shutdown_hw(void) { +/* Various hardware housekeeping tasks relating to shutting down the jukebox */ +void shutdown_hw(void) +{ #ifndef SIMULATOR mpeg_stop(); ata_flush(); -- cgit v1.2.3