summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Kukla <roolku@rockbox.org>2007-02-28 13:20:36 +0000
committerRobert Kukla <roolku@rockbox.org>2007-02-28 13:20:36 +0000
commit50b5ee4781a44234b4ea5dccf3be6ae5ec9fd324 (patch)
treed5197ea90c5dcfa574b84743ecbbd7fa2a754e55
parent343c428f2cf97c82540aecf07d154e43ff40e79a (diff)
downloadrockbox-50b5ee4781a44234b4ea5dccf3be6ae5ec9fd324.zip
rockbox-50b5ee4781a44234b4ea5dccf3be6ae5ec9fd324.tar.gz
rockbox-50b5ee4781a44234b4ea5dccf3be6ae5ec9fd324.tar.bz2
rockbox-50b5ee4781a44234b4ea5dccf3be6ae5ec9fd324.tar.xz
FS#6419 - driver for H1x0 series RTC Mod with runtime detection
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12520 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/gui/gwps-common.c7
-rw-r--r--apps/gui/statusbar.c9
-rw-r--r--apps/menus/settings_menu.c30
-rw-r--r--apps/misc.c7
-rw-r--r--apps/plugins/clock.c2
-rw-r--r--apps/recorder/recording.c9
-rw-r--r--apps/scrobbler.c6
-rw-r--r--firmware/SOURCES4
-rw-r--r--firmware/common/timefuncs.c13
-rw-r--r--firmware/drivers/eeprom_24cxx.c265
-rw-r--r--firmware/drivers/fat.c20
-rw-r--r--firmware/drivers/rtc/rtc_ds1339_ds3231.c144
-rw-r--r--firmware/export/config-h120.h8
-rw-r--r--firmware/export/config.h1
-rw-r--r--firmware/export/rtc.h9
-rw-r--r--firmware/export/sw_i2c.h30
-rw-r--r--firmware/target/coldfire/iriver/h100/sw_i2c-h100.c259
-rw-r--r--firmware/target/coldfire/iriver/h300/sw_i2c-h300.c105
18 files changed, 660 insertions, 268 deletions
diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c
index 70f5565..8fa80c7 100644
--- a/apps/gui/gwps-common.c
+++ b/apps/gui/gwps-common.c
@@ -23,7 +23,9 @@
#include <stdlib.h>
#include "system.h"
#include "settings.h"
+#ifdef CONFIG_RTC
#include "rtc.h"
+#endif
#include "audio.h"
#include "status.h"
#include "power.h"
@@ -972,6 +974,11 @@ static char* get_tag(struct wps_data* wps_data,
#ifdef CONFIG_RTC
case 'c': /* Real Time Clock display */
*flags |= WPS_REFRESH_DYNAMIC;
+#if CONFIG_RTC == RTC_DS1339_DS3231
+ if(!rtc_detected)
+ return NULL;
+ else
+#endif
{
int value;
char *format = 0;
diff --git a/apps/gui/statusbar.c b/apps/gui/statusbar.c
index fbd8943..a36ae15 100644
--- a/apps/gui/statusbar.c
+++ b/apps/gui/statusbar.c
@@ -28,6 +28,9 @@
#include "powermgmt.h"
#include "usb.h"
#include "led.h"
+#ifdef CONFIG_RTC
+#include "rtc.h"
+#endif
#include "status.h" /* needed for battery_state global var */
#include "action.h" /* for keys_locked */
@@ -239,6 +242,9 @@ void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw)
bar->info.led = led_read(HZ/2); /* delay should match polling interval */
#endif
#ifdef CONFIG_RTC
+#if CONFIG_RTC == RTC_DS1339_DS3231
+ if(rtc_detected)
+#endif
{
struct tm* tm = get_time();
bar->info.hour = tm->tm_hour;
@@ -324,6 +330,9 @@ void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw)
gui_statusbar_icon_lock_remote(display);
#endif
#ifdef CONFIG_RTC
+#if CONFIG_RTC == RTC_DS1339_DS3231
+ if(rtc_detected)
+#endif
gui_statusbar_time(display, bar->info.hour, bar->info.minute);
#endif /* CONFIG_RTC */
#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c
index 508f721..818271b 100644
--- a/apps/menus/settings_menu.c
+++ b/apps/menus/settings_menu.c
@@ -38,6 +38,12 @@
#ifdef HAVE_ALARM_MOD
#include "alarm_menu.h"
#endif
+#ifdef CONFIG_RTC
+#include "rtc.h"
+#endif
+
+/* callback to display rtc menus dynamically */
+int rtc_detect_callback(int action,const struct menu_item_ex *this_item);
/***********************************/
/* TAGCACHE MENU */
@@ -206,7 +212,7 @@ static int timedate_set(void)
MENUITEM_FUNCTION(time_set, ID2P(LANG_TIME), timedate_set, NULL, NOICON);
MENUITEM_SETTING(timeformat, &global_settings.timeformat, NULL);
-MAKE_MENU(time_menu, ID2P(LANG_TIME_MENU), 0, NOICON, &time_set, &timeformat);
+MAKE_MENU(time_menu, ID2P(LANG_TIME_MENU), rtc_detect_callback, NOICON, &time_set, &timeformat);
#endif
/* System menu */
@@ -246,7 +252,7 @@ MENUITEM_FUNCTION(sleep_timer_call, ID2P(LANG_SLEEP_TIMER), sleep_timer,
setting to the user */
#ifdef HAVE_ALARM_MOD
MENUITEM_FUNCTION(alarm_screen_call, ID2P(LANG_ALARM_MOD_ALARM_MENU),
- (menu_function)alarm_screen, NULL, NOICON);
+ (menu_function)alarm_screen, rtc_detect_callback, NOICON);
#endif
/* Limits menu */
@@ -383,3 +389,23 @@ MAKE_MENU(settings_menu_item, ID2P(LANG_GENERAL_SETTINGS), 0,
&bookmark_settings_menu, &browse_langs, &voice_settings_menu );
/* SETTINGS MENU */
/***********************************/
+
+/* callback to display rtc menus dynamically */
+int rtc_detect_callback(int action,const struct menu_item_ex *this_item)
+{
+ if (action != ACTION_REQUEST_MENUITEM)
+ return action;
+
+#if defined(CONFIG_RTC) && CONFIG_RTC == RTC_DS1339_DS3231
+ if ((this_item == &time_menu) ||
+ (this_item == &alarm_screen_call))
+ {
+ if (!rtc_detected)
+ return ACTION_EXIT_MENUITEM;
+ }
+#else
+ (void)this_item;
+#endif
+
+ return action;
+}
diff --git a/apps/misc.c b/apps/misc.c
index 22f6fb5..339bc1d 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -60,6 +60,7 @@
#include "gui/gwps-common.h"
#include "misc.h"
+#include "rtc.h"
/* Format a large-range value for output, using the appropriate unit so that
* the displayed value is in the range 1 <= display < 1000 (1024 for "binary"
@@ -414,6 +415,12 @@ void screen_dump(void)
#endif
#ifdef CONFIG_RTC
+#if CONFIG_RTC == RTC_DS1339_DS3231
+ if(!rtc_detected)
+ create_numbered_filename(filename, "", "dump_", ".bmp", 4
+ IF_CNFN_NUM_(, NULL));
+ else
+#endif
create_datetime_filename(filename, "", "dump ", ".bmp", false);
#else
create_numbered_filename(filename, "", "dump_", ".bmp", 4
diff --git a/apps/plugins/clock.c b/apps/plugins/clock.c
index 7e52e2b..010e293 100644
--- a/apps/plugins/clock.c
+++ b/apps/plugins/clock.c
@@ -277,7 +277,7 @@ extern const fb_data clock_timesup[];
#define EXIT_BUTTON BUTTON_MENU
#define MODE_NEXT_BUTTON BUTTON_RIGHT
#define MODE_PREV_BUTTON BUTTON_LEFT
-#elif (CONFIG_KEYPAD == IRIVER_H300_PAD)
+#elif (CONFIG_KEYPAD == IRIVER_H300_PAD) || (CONFIG_KEYPAD == IRIVER_H100_PAD)
#define COUNTER_TOGGLE_BUTTON (BUTTON_ON|BUTTON_REL)
#define COUNTER_RESET_BUTTON (BUTTON_ON|BUTTON_REPEAT)
#define MENU_BUTTON BUTTON_SELECT
diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c
index 8eea24d..2c5fc32 100644
--- a/apps/recorder/recording.c
+++ b/apps/recorder/recording.c
@@ -68,6 +68,9 @@
#include "screen_access.h"
#include "action.h"
#include "radio.h"
+#ifdef CONFIG_RTC
+#include "rtc.h"
+#endif
#ifdef HAVE_RECORDING
static bool in_screen = false;
@@ -521,6 +524,12 @@ char *rec_create_filename(char *buffer)
#ifdef CONFIG_RTC
/* We'll wait at least up to the start of the next second so no duplicate
names are created */
+#if CONFIG_RTC == RTC_DS1339_DS3231
+ if(!rtc_detected)
+ return create_numbered_filename(buffer, buffer, "rec_", ext, 4
+ IF_CNFN_NUM_(, &file_number));
+ else
+#endif
return create_datetime_filename(buffer, buffer, "R", ext, true);
#else
return create_numbered_filename(buffer, buffer, "rec_", ext, 4
diff --git a/apps/scrobbler.c b/apps/scrobbler.c
index a339429..1c0d98c 100644
--- a/apps/scrobbler.c
+++ b/apps/scrobbler.c
@@ -35,6 +35,7 @@ http://www.audioscrobbler.net/wiki/Portable_Player_Logging
#ifdef CONFIG_RTC
#include "time.h"
#include "timefuncs.h"
+#include "rtc.h"
#endif
#include "scrobbler.h"
@@ -208,6 +209,11 @@ void scrobbler_change_event(struct mp3entry *id)
logf("SCROBBLER: add pending");
copy_mp3entry(&scrobbler_entry, id);
#ifdef CONFIG_RTC
+#if CONFIG_RTC == RTC_DS1339_DS3231
+ if(!rtc_detected)
+ timestamp = 0;
+ else
+#endif
timestamp = mktime(get_time());
#else
timestamp = 0;
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 03d2b16..f07145c 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -137,6 +137,8 @@ drivers/rtc/rtc_pcf50606.c
drivers/rtc/rtc_pcf50605.c
#elif (CONFIG_RTC == RTC_E8564)
drivers/rtc/rtc_e8564.c
+#elif (CONFIG_RTC == RTC_DS1339_DS3231)
+drivers/rtc/rtc_ds1339_ds3231.c
#elif (CONFIG_RTC == RTC_S3C2440)
drivers/rtc/rtc_s3c2440.c
#elif (CONFIG_RTC == RTC_AS3514)
@@ -380,6 +382,7 @@ target/coldfire/pcf50606-coldfire.c
target/coldfire/iriver/ata-iriver.c
target/coldfire/iriver/lcd-remote-iriver.c
target/coldfire/iriver/system-iriver.c
+target/coldfire/iriver/h300/sw_i2c-h300.c
target/coldfire/iriver/h300/adc-h300.c
target/coldfire/iriver/h300/backlight-h300.c
target/coldfire/iriver/h300/button-h300.c
@@ -400,6 +403,7 @@ target/coldfire/ata-as-coldfire.S
target/coldfire/iriver/ata-iriver.c
target/coldfire/iriver/lcd-remote-iriver.c
target/coldfire/iriver/system-iriver.c
+target/coldfire/iriver/h100/sw_i2c-h100.c
target/coldfire/iriver/h100/adc-h100.c
target/coldfire/iriver/h100/backlight-h100.c
target/coldfire/iriver/h100/button-h100.c
diff --git a/firmware/common/timefuncs.c b/firmware/common/timefuncs.c
index e48aadd..881bc23 100644
--- a/firmware/common/timefuncs.c
+++ b/firmware/common/timefuncs.c
@@ -49,6 +49,19 @@ struct tm *get_time(void)
#ifdef CONFIG_RTC
static long timeout = 0;
+#if CONFIG_RTC == RTC_DS1339_DS3231
+ if(!rtc_detected) {
+ tm.tm_sec = 0;
+ tm.tm_min = 0;
+ tm.tm_hour = 0;
+ tm.tm_mday = 1;
+ tm.tm_mon = 0;
+ tm.tm_year = 70;
+ tm.tm_wday = 1;
+ tm.tm_yday = 0; /* Not implemented for now */
+ tm.tm_isdst = -1; /* Not implemented for now */
+ } else
+#endif
/* Don't read the RTC more than once per second */
if (current_tick > timeout) {
char rtcbuf[7];
diff --git a/firmware/drivers/eeprom_24cxx.c b/firmware/drivers/eeprom_24cxx.c
index 6016c0f..a0d8f83 100644
--- a/firmware/drivers/eeprom_24cxx.c
+++ b/firmware/drivers/eeprom_24cxx.c
@@ -16,274 +16,21 @@
* KIND, either express or implied.
*
****************************************************************************/
-#include "lcd.h"
-#include "cpu.h"
-#include "system.h"
-#include "kernel.h"
-#include "thread.h"
-#include "debug.h"
+
#include "logf.h"
-#include "sprintf.h"
#include "string.h"
#include "inttypes.h"
-#include "eeprom_24cxx.h"
-
-/**
- * I2C-functions are copied and ported from fmradio.c.
- */
+#include "sw_i2c.h"
-#define SW_I2C_WRITE 0
-#define SW_I2C_READ 1
+#include "eeprom_24cxx.h"
/* Use cache to speedup writing to the chip. */
static char data_cache[EEPROM_SIZE];
static uint8_t cached_bitfield[EEPROM_SIZE/8];
#define IS_CACHED(addr) (cached_bitfield[addr/8] & (1 << (addr % 8)))
-#define SET_CACHED(addr) (cached_bitfield[addr/8] |= 1 << (addr % 8))
-
-/* h1x0 needs its own i2c driver,
- h3x0 uses the pcf i2c driver */
-
-#ifdef IRIVER_H100_SERIES
-
-/* cute little functions, atomic read-modify-write */
-
-/* SCL is GPIO, 12 */
-#define SCL ( 0x00001000 & GPIO_READ)
-#define SCL_OUT_LO and_l(~0x00001000, &GPIO_OUT)
-#define SCL_LO or_l( 0x00001000, &GPIO_ENABLE)
-#define SCL_HI and_l(~0x00001000, &GPIO_ENABLE)
-
-/* SDA is GPIO1, 13 */
-#define SDA ( 0x00002000 & GPIO1_READ)
-#define SDA_OUT_LO and_l(~0x00002000, &GPIO1_OUT)
-#define SDA_LO or_l( 0x00002000, &GPIO1_ENABLE)
-#define SDA_HI and_l(~0x00002000, &GPIO1_ENABLE)
-
-/* delay loop to achieve 400kHz at 120MHz CPU frequency */
-#define DELAY do { int _x; for(_x=0;_x<22;_x++);} while(0)
-
-static void sw_i2c_init(void)
-{
- logf("sw_i2c_init");
- or_l(0x00001000, &GPIO_FUNCTION);
- or_l(0x00002000, &GPIO1_FUNCTION);
- SDA_HI;
- SCL_HI;
- SDA_OUT_LO;
- SCL_OUT_LO;
-}
-
-static void sw_i2c_start(void)
-{
- SCL_LO;
- DELAY;
- SDA_HI;
- DELAY;
- SCL_HI;
- DELAY;
- SDA_LO;
- DELAY;
- SCL_LO;
-}
-
-static void sw_i2c_stop(void)
-{
- SCL_HI;
- DELAY;
- SDA_HI;
- DELAY;
-}
-
-static void sw_i2c_ack(void)
-{
- SCL_LO;
- DELAY;
- SDA_LO;
- DELAY;
-
- SCL_HI;
- DELAY;
-}
-
-static bool sw_i2c_getack(void)
-{
- bool ret = true;
- int count = 10;
-
- SCL_LO;
- DELAY;
- SDA_HI; /* sets to input */
- DELAY;
- SCL_HI;
- DELAY;
-
- while (SDA && count--)
- DELAY;
-
- if (SDA)
- /* ack failed */
- ret = false;
-
- SCL_LO;
- DELAY;
- SDA_LO;
-
- return ret;
-}
-
-static void sw_i2c_outb(unsigned char byte)
-{
- int i;
-
- /* clock out each bit, MSB first */
- for ( i=0x80; i; i>>=1 )
- {
- SCL_LO;
- DELAY;
- if ( i & byte )
- SDA_HI;
- else
- SDA_LO;
- DELAY;
- SCL_HI;
- DELAY;
- }
-}
-
-static unsigned char sw_i2c_inb(void)
-{
- int i;
- unsigned char byte = 0;
-
- SDA_HI; /* sets to input */
-
- /* clock in each bit, MSB first */
- for ( i=0x80; i; i>>=1 )
- {
- SCL_HI;
- DELAY;
- if ( SDA )
- byte |= i;
- SCL_LO;
- DELAY;
- }
-
- sw_i2c_ack();
-
- return byte;
-}
-
-#else
-
-#include "pcf50606.h"
-
-#define sw_i2c_init() /* no extra init required */
-#define sw_i2c_start() pcf50606_i2c_start()
-#define sw_i2c_stop() pcf50606_i2c_stop()
-#define sw_i2c_ack() pcf50606_i2c_ack(true)
-#define sw_i2c_getack() pcf50606_i2c_getack()
-#define sw_i2c_outb(x) pcf50606_i2c_outb(x)
-#define sw_i2c_inb() pcf50606_i2c_inb(false)
-
-#endif /* IRIVER_H100_SERIES */
-
-
-int sw_i2c_write(int location, const unsigned char* buf, int count)
-{
- int i;
-
- sw_i2c_start();
- sw_i2c_outb((EEPROM_ADDR & 0xfe) | SW_I2C_WRITE);
- if (!sw_i2c_getack())
- {
- sw_i2c_stop();
- return -1;
- }
-
- sw_i2c_outb(location);
- if (!sw_i2c_getack())
- {
- sw_i2c_stop();
- return -2;
- }
-
- for (i=0; i<count; i++)
- {
- sw_i2c_outb(buf[i]);
- if (!sw_i2c_getack())
- {
- sw_i2c_stop();
- return -3;
- }
- }
-
- sw_i2c_stop();
-
- return 0;
-}
-
-int sw_i2c_write_byte(int location, unsigned char byte)
-{
- sw_i2c_start();
- sw_i2c_outb((EEPROM_ADDR & 0xfe) | SW_I2C_WRITE);
- if (!sw_i2c_getack())
- {
- sw_i2c_stop();
- return -1;
- }
-
- sw_i2c_outb(location);
- if (!sw_i2c_getack())
- {
- sw_i2c_stop();
- return -2;
- }
-
- sw_i2c_outb(byte);
- if (!sw_i2c_getack())
- {
- sw_i2c_stop();
- return -3;
- }
-
- sw_i2c_stop();
-
- return 0;
-}
-
-int sw_i2c_read(unsigned char location, unsigned char* byte)
-{
- sw_i2c_start();
- sw_i2c_outb((EEPROM_ADDR & 0xfe) | SW_I2C_WRITE);
- if (!sw_i2c_getack())
- {
- sw_i2c_stop();
- return -1;
- }
-
- sw_i2c_outb(location);
- if (!sw_i2c_getack())
- {
- sw_i2c_stop();
- return -2;
- }
-
- sw_i2c_start();
- sw_i2c_outb((EEPROM_ADDR & 0xfe) | SW_I2C_READ);
- if (!sw_i2c_getack())
- {
- sw_i2c_stop();
- return -3;
- }
-
- *byte = sw_i2c_inb();
- sw_i2c_stop();
-
- return 0;
-}
+#define SET_CACHED(addr) (cached_bitfield[addr/8] |= 1 << (addr % 8))
void eeprom_24cxx_init(void)
{
@@ -314,7 +61,7 @@ int eeprom_24cxx_read_byte(unsigned int address, char *c)
*c = 0;
do
{
- ret = sw_i2c_read(address, &byte);
+ ret = sw_i2c_read(EEPROM_ADDR, address, &byte, 1);
} while (ret < 0 && count++ < 200);
if (ret < 0)
@@ -357,7 +104,7 @@ int eeprom_24cxx_write_byte(unsigned int address, char c)
do
{
- ret = sw_i2c_write_byte(address, c);
+ ret = sw_i2c_write(EEPROM_ADDR, address, &c, 1);
} while (ret < 0 && count++ < 200) ;
if (ret < 0)
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index e3e1a75..e4e7762 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -31,6 +31,9 @@
#include "rbunicode.h"
#include "logf.h"
#include "atoi.h"
+#ifdef CONFIG_RTC
+#include "rtc.h"
+#endif
#define BYTES2INT16(array,pos) \
(array[pos] | (array[pos+1] << 8 ))
@@ -945,6 +948,10 @@ static void fat_time(unsigned short* date,
{
#ifdef CONFIG_RTC
struct tm* tm = get_time();
+#if CONFIG_RTC == RTC_DS1339_DS3231
+ if(rtc_detected)
+ {
+#endif /* CONFIG_RTC == RTC_DS1339_DS3231 */
if (date)
*date = ((tm->tm_year - 80) << 9) |
@@ -958,7 +965,14 @@ static void fat_time(unsigned short* date,
if (tenth)
*tenth = (tm->tm_sec & 1) * 100;
-#else
+
+#if CONFIG_RTC == RTC_DS1339_DS3231
+ }
+ else
+#endif /* CONFIG_RTC == RTC_DS1339_DS3231 */
+#endif /* CONFIG_RTC */
+#if !defined(CONFIG_RTC) || CONFIG_RTC == RTC_DS1339_DS3231
+ {
/* non-RTC version returns an increment from the supplied time, or a
* fixed standard time/date if no time given as input */
bool next_day = false;
@@ -1025,9 +1039,9 @@ static void fat_time(unsigned short* date,
}
if (tenth)
*tenth = 0;
-#endif /* CONFIG_RTC */
+ }
+#endif /* !defined(CONFIG_RTC) || CONFIG_RTC == RTC_DS1339_DS3231 */
}
-
static int write_long_name(struct fat_file* file,
unsigned int firstentry,
unsigned int numentries,
diff --git a/firmware/drivers/rtc/rtc_ds1339_ds3231.c b/firmware/drivers/rtc/rtc_ds1339_ds3231.c
new file mode 100644
index 0000000..df67fed
--- /dev/null
+++ b/firmware/drivers/rtc/rtc_ds1339_ds3231.c
@@ -0,0 +1,144 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 by Robert Kukla
+ * based on Archos code by Linus Nielsen Feltzing, Uwe Freese, Laurent Baum
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "rtc.h"
+#include "logf.h"
+#include "sw_i2c.h"
+
+#define RTC_ADDR 0xD0
+
+bool rtc_detected = false;
+
+void rtc_init(void)
+{
+ char byte;
+
+ sw_i2c_init();
+
+ /* read one byte from RTC; 0 on success */
+ rtc_detected = !sw_i2c_read(RTC_ADDR, 0, &byte, 1);
+
+#ifdef HAVE_ALARM_MOD
+ /* Check + save alarm bit first, before the power thread starts watching */
+ rtc_check_alarm_started(false);
+#endif
+
+}
+
+#ifdef HAVE_ALARM_MOD
+
+/* check whether the unit has been started by the RTC alarm function */
+/* (check for A2F, which => started using wakeup alarm) */
+bool rtc_check_alarm_started(bool release_alarm)
+{
+ static bool alarm_state, run_before;
+ bool rc;
+
+ if (run_before) {
+ rc = alarm_state;
+ alarm_state &= ~release_alarm;
+ } else {
+ /* This call resets AF, so we store the state for later recall */
+ rc = alarm_state = rtc_check_alarm_flag();
+ run_before = true;
+ }
+
+ return rc;
+}
+/*
+ * Checks the A2F flag. This call resets A2F once read.
+ *
+ */
+bool rtc_check_alarm_flag(void)
+{
+ unsigned char buf[1];
+ bool flag = false;
+
+ sw_i2c_read(RTC_ADDR, 0x0f, buf, 1);
+ if (buf[0] & 0x02) flag = true;
+
+ rtc_enable_alarm(false);
+
+ return flag;
+}
+
+/* set alarm time registers to the given time (repeat once per day) */
+void rtc_set_alarm(int h, int m)
+{
+ unsigned char buf[3];
+
+ buf[0] = (((m / 10) << 4) | (m % 10)) & 0x7f; /* minutes */
+ buf[1] = (((h / 10) << 4) | (h % 10)) & 0x3f; /* hour */
+ buf[2] = 0x80; /* repeat every day */
+
+ sw_i2c_write(RTC_ADDR, 0x0b, buf, 3);
+}
+
+/* read out the current alarm time */
+void rtc_get_alarm(int *h, int *m)
+{
+ unsigned char buf[2];
+
+ sw_i2c_read(RTC_ADDR, 0x0b, buf, 2);
+
+ *m = ((buf[0] & 0x70) >> 4) * 10 + (buf[0] & 0x0f);
+ *h = ((buf[1] & 0x30) >> 4) * 10 + (buf[1] & 0x0f);
+}
+
+/* turn alarm on or off by setting the alarm flag enable */
+/* the alarm is automatically disabled when the RTC gets Vcc power at startup */
+/* avoid that an alarm occurs when the device is on because this locks the ON key forever */
+/* returns false if alarm was set and alarm flag (output) is off */
+/* returns true if alarm flag went on, which would lock the device, so the alarm was disabled again */
+bool rtc_enable_alarm(bool enable)
+{
+ unsigned char buf[2];
+
+ buf[0] = enable ? 0x26 : 0x04; /* BBSQI INTCN A2IE vs INTCH only */
+ buf[1] = 0x00; /* reset alarm flags (and OSF for good measure) */
+
+ sw_i2c_write(RTC_ADDR, 0x0e, buf, 2);
+
+ return false; /* all ok */
+}
+
+#endif /* HAVE_ALARM_MOD */
+
+int rtc_read_datetime(unsigned char* buf)
+{
+ int i;
+
+ i = sw_i2c_read(RTC_ADDR, 0, buf, 7);
+
+ buf[3]--; /* timefuncs wants 0..6 for wday */
+
+ return i;
+}
+
+int rtc_write_datetime(unsigned char* buf)
+{
+ int i;
+
+ buf[3]++; /* chip wants 1..7 for wday */
+ buf[5]|=0x80; /* chip wants century (always 20xx) */
+
+ i = sw_i2c_write(RTC_ADDR, 0, buf, 7);
+
+ return i;
+}
+
diff --git a/firmware/export/config-h120.h b/firmware/export/config-h120.h
index e7fb73e..9dccf22 100644
--- a/firmware/export/config-h120.h
+++ b/firmware/export/config-h120.h
@@ -45,7 +45,13 @@
/* Define this if you do software codec */
#define CONFIG_CODEC SWCODEC
-/* Define this if you have an remote lcd */
+#ifndef SIMULATOR
+/* RTC is autodetected on target only */
+#define CONFIG_RTC RTC_DS1339_DS3231
+#define HAVE_ALARM_MOD
+#endif
+
+ /* Define this if you have an remote lcd */
#define HAVE_REMOTE_LCD
#define CONFIG_LCD LCD_S1D15E06
diff --git a/firmware/export/config.h b/firmware/export/config.h
index ac2ee68..085f86a 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -153,6 +153,7 @@
#define RTC_S3C2440 4
#define RTC_E8564 5 /* iriver H10 */
#define RTC_AS3514 6 /* Sandisk Sansa e200 series */
+#define RTC_DS1339_DS3231 7 /* h1x0 RTC mod */
/* USB On-the-go */
#define USBOTG_ISP1362 1362 /* iriver H300 */
diff --git a/firmware/export/rtc.h b/firmware/export/rtc.h
index c7e3c4a..2f13cbb 100644
--- a/firmware/export/rtc.h
+++ b/firmware/export/rtc.h
@@ -20,6 +20,7 @@
#define _RTC_H_
#include <stdbool.h>
+#include <system.h>
#ifdef CONFIG_RTC
@@ -27,6 +28,10 @@ extern const int dayname[];
extern const int monthname[];
+#if CONFIG_RTC == RTC_DS1339_DS3231
+extern bool rtc_detected;
+#endif
+
/* Common functions for all targets */
void rtc_init(void);
int rtc_read_datetime(unsigned char* buf);
@@ -40,6 +45,8 @@ int rtc_read(unsigned char address);
int rtc_read_multiple(unsigned char address, unsigned char *buf, int numbytes);
int rtc_write(unsigned char address, unsigned char value);
+#endif /* RTC_M41ST84W */
+
#ifdef HAVE_ALARM_MOD
void rtc_set_alarm(int h, int m);
void rtc_get_alarm(int *h, int *m);
@@ -48,8 +55,6 @@ bool rtc_check_alarm_started(bool release_alarm);
bool rtc_check_alarm_flag(void);
#endif /* HAVE_ALARM_MOD */
-#endif /* RTC_M41ST84W */
-
#endif /* CONFIG_RTC */
#endif
diff --git a/firmware/export/sw_i2c.h b/firmware/export/sw_i2c.h
new file mode 100644
index 0000000..42dccad
--- /dev/null
+++ b/firmware/export/sw_i2c.h
@@ -0,0 +1,30 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 by Robert Kukla
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef _SW_I2C_H
+#define _SW_I2C_H
+
+#define SW_I2C_WRITE 0
+#define SW_I2C_READ 1
+
+void sw_i2c_init(void);
+int sw_i2c_write(unsigned char chip, unsigned char location, const unsigned char* buf, int count);
+int sw_i2c_read (unsigned char chip, unsigned char location, unsigned char* buf, int count);
+
+#endif
diff --git a/firmware/target/coldfire/iriver/h100/sw_i2c-h100.c b/firmware/target/coldfire/iriver/h100/sw_i2c-h100.c
new file mode 100644
index 0000000..cb06187
--- /dev/null
+++ b/firmware/target/coldfire/iriver/h100/sw_i2c-h100.c
@@ -0,0 +1,259 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 by Miika Pekkarinen
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "system.h"
+#include "logf.h"
+#include "inttypes.h"
+
+#include "sw_i2c.h"
+
+/**
+ * I2C-functions are copied and ported from fmradio.c.
+ * later fixed, adapted and moved to a seperate file so they can be re-used by the rtc-ds1339c code by Robert Kukla
+ */
+
+/* cute little functions, atomic read-modify-write */
+
+/* SCL is GPIO, 12 */
+#define SCL ( 0x00001000 & GPIO_READ)
+#define SCL_OUT_LO and_l(~0x00001000, &GPIO_OUT)
+#define SCL_LO or_l( 0x00001000, &GPIO_ENABLE)
+#define SCL_HI and_l(~0x00001000, &GPIO_ENABLE)
+
+/* SDA is GPIO1, 13 */
+#define SDA ( 0x00002000 & GPIO1_READ)
+#define SDA_OUT_LO and_l(~0x00002000, &GPIO1_OUT)
+#define SDA_LO or_l( 0x00002000, &GPIO1_ENABLE)
+#define SDA_HI and_l(~0x00002000, &GPIO1_ENABLE)
+
+/* delay loop to achieve 400kHz at 120MHz CPU frequency */
+#define DELAY do { int _x; for(_x=0;_x<22;_x++);} while(0)
+
+void sw_i2c_init(void)
+{
+ or_l(0x00001000, &GPIO_FUNCTION);
+ or_l(0x00002000, &GPIO1_FUNCTION);
+ SDA_HI;
+ SCL_HI;
+ SDA_OUT_LO;
+ SCL_OUT_LO;
+}
+
+/* in: C=? D=?
+ * out: C=L D=L
+ */
+static void sw_i2c_start(void)
+{
+ SCL_LO;
+ DELAY;
+ SDA_HI;
+ DELAY;
+ SCL_HI;
+ DELAY;
+ SDA_LO;
+ DELAY;
+ SCL_LO;
+}
+
+/* in: C=L D=?
+ * out: C=H D=H
+ */
+static void sw_i2c_stop(void)
+{
+ SDA_LO;
+ DELAY;
+ SCL_HI;
+ DELAY;
+ SDA_HI;
+}
+
+/* in: C=L D=H
+ * out: C=L D=L
+ */
+static void sw_i2c_ack(void)
+{
+ SDA_LO;
+ DELAY;
+
+ SCL_HI;
+ DELAY;
+ SCL_LO;
+}
+
+/* in: C=L D=H
+ * out: C=L D=H
+ */
+static void sw_i2c_nack(void)
+{
+ SDA_HI; /* redundant */
+ DELAY;
+
+ SCL_HI;
+ DELAY;
+ SCL_LO;
+}
+
+/* in: C=L D=?
+ * out: C=L D=H
+ */
+static bool sw_i2c_getack(void)
+{
+ bool ret = true;
+/* int count = 10; */
+
+ SDA_HI; /* sets to input */
+ DELAY;
+ SCL_HI;
+ DELAY;
+
+/* while (SDA && count--) */
+/* DELAY; */
+
+ if (SDA)
+ /* ack failed */
+ ret = false;
+
+ SCL_LO;
+
+ return ret;
+}
+
+/* in: C=L D=?
+ * out: C=L D=?
+ */
+static void sw_i2c_outb(unsigned char byte)
+{
+ int i;
+
+ /* clock out each bit, MSB first */
+ for ( i=0x80; i; i>>=1 )
+ {
+ if ( i & byte )
+ SDA_HI;
+ else
+ SDA_LO;
+ DELAY;
+
+ SCL_HI;
+ DELAY;
+ SCL_LO;
+ }
+}
+
+/* in: C=L D=?
+ * out: C=L D=H
+ */
+static unsigned char sw_i2c_inb(void)
+{
+ int i;
+ unsigned char byte = 0;
+
+ SDA_HI; /* sets to input */
+
+ /* clock in each bit, MSB first */
+ for ( i=0x80; i; i>>=1 )
+ {
+ DELAY;
+ do {
+ SCL_HI;
+ DELAY;
+ }
+ while(SCL==0); /* wait for any SCL clock stretching */
+ if ( SDA )
+ byte |= i;
+ SCL_LO;
+ }
+
+ return byte;
+}
+
+int sw_i2c_write(unsigned char chip, unsigned char location, const unsigned char* buf, int count)
+{
+ int i;
+
+ sw_i2c_start();
+ sw_i2c_outb((chip & 0xfe) | SW_I2C_WRITE);
+ if (!sw_i2c_getack())
+ {
+ sw_i2c_stop();
+ return -1;
+ }
+
+ sw_i2c_outb(location);
+ if (!sw_i2c_getack())
+ {
+ sw_i2c_stop();
+ return -2;
+ }
+
+ for (i=0; i<count; i++)
+ {
+ sw_i2c_outb(buf[i]);
+ if (!sw_i2c_getack())
+ {
+ sw_i2c_stop();
+ return -3;
+ }
+ }
+
+ sw_i2c_stop();
+
+ return 0;
+}
+
+int sw_i2c_read(unsigned char chip, unsigned char location, unsigned char* buf, int count)
+{
+ int i;
+
+ sw_i2c_start();
+ sw_i2c_outb((chip & 0xfe) | SW_I2C_WRITE);
+ if (!sw_i2c_getack())
+ {
+ sw_i2c_stop();
+ return -1;
+ }
+
+ sw_i2c_outb(location);
+ if (!sw_i2c_getack())
+ {
+ sw_i2c_stop();
+ return -2;
+ }
+
+ sw_i2c_start();
+ sw_i2c_outb((chip & 0xfe) | SW_I2C_READ);
+ if (!sw_i2c_getack())
+ {
+ sw_i2c_stop();
+ return -3;
+ }
+
+ for (i=0; i<count-1; i++)
+ {
+ buf[i] = sw_i2c_inb();
+ sw_i2c_ack();
+ }
+
+ /* 1byte min */
+ buf[i] = sw_i2c_inb();
+ sw_i2c_nack();
+
+ sw_i2c_stop();
+
+ return 0;
+}
diff --git a/firmware/target/coldfire/iriver/h300/sw_i2c-h300.c b/firmware/target/coldfire/iriver/h300/sw_i2c-h300.c
new file mode 100644
index 0000000..f093746
--- /dev/null
+++ b/firmware/target/coldfire/iriver/h300/sw_i2c-h300.c
@@ -0,0 +1,105 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 by Miika Pekkarinen
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "system.h"
+#include "logf.h"
+#include "inttypes.h"
+
+#include "sw_i2c.h"
+
+#include "pcf50606.h"
+
+void sw_i2c_init(void)
+{
+ /* no extra init required */
+}
+
+int sw_i2c_write(unsigned char chip, unsigned char location, const unsigned char* buf, int count)
+{
+ int i;
+
+ pcf50606_i2c_start();
+ pcf50606_i2c_outb((chip & 0xfe) | SW_I2C_WRITE);
+ if (!pcf50606_i2c_getack())
+ {
+ pcf50606_i2c_stop();
+ return -1;
+ }
+
+ pcf50606_i2c_outb(location);
+ if (!pcf50606_i2c_getack())
+ {
+ pcf50606_i2c_stop();
+ return -2;
+ }
+
+ for (i=0; i<count; i++)
+ {
+ pcf50606_i2c_outb(buf[i]);
+ if (!pcf50606_i2c_getack())
+ {
+ pcf50606_i2c_stop();
+ return -3;
+ }
+ }
+
+ pcf50606_i2c_stop();
+
+ return 0;
+}
+
+int sw_i2c_read(unsigned char chip, unsigned char location, unsigned char* buf, int count)
+{
+ int i;
+
+ pcf50606_i2c_start();
+ pcf50606_i2c_outb((chip & 0xfe) | SW_I2C_WRITE);
+ if (!pcf50606_i2c_getack())
+ {
+ pcf50606_i2c_stop();
+ return -1;
+ }
+
+ pcf50606_i2c_outb(location);
+ if (!pcf50606_i2c_getack())
+ {
+ pcf50606_i2c_stop();
+ return -2;
+ }
+
+ pcf50606_i2c_start();
+ pcf50606_i2c_outb((chip & 0xfe) | SW_I2C_READ);
+ if (!pcf50606_i2c_getack())
+ {
+ pcf50606_i2c_stop();
+ return -3;
+ }
+
+ for (i=0; i<count-1; i++)
+ {
+ buf[i] = pcf50606_i2c_inb(true);
+ }
+
+ /* 1byte min */
+ buf[i] = pcf50606_i2c_inb(false);
+
+
+ pcf50606_i2c_stop();
+
+ return 0;
+}