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
This commit is contained in:
parent
343c428f2c
commit
50b5ee4781
18 changed files with 660 additions and 268 deletions
|
@ -23,7 +23,9 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#ifdef CONFIG_RTC
|
||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
|
#endif
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
|
@ -972,6 +974,11 @@ static char* get_tag(struct wps_data* wps_data,
|
||||||
#ifdef CONFIG_RTC
|
#ifdef CONFIG_RTC
|
||||||
case 'c': /* Real Time Clock display */
|
case 'c': /* Real Time Clock display */
|
||||||
*flags |= WPS_REFRESH_DYNAMIC;
|
*flags |= WPS_REFRESH_DYNAMIC;
|
||||||
|
#if CONFIG_RTC == RTC_DS1339_DS3231
|
||||||
|
if(!rtc_detected)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
int value;
|
int value;
|
||||||
char *format = 0;
|
char *format = 0;
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
#include "powermgmt.h"
|
#include "powermgmt.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "led.h"
|
#include "led.h"
|
||||||
|
#ifdef CONFIG_RTC
|
||||||
|
#include "rtc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "status.h" /* needed for battery_state global var */
|
#include "status.h" /* needed for battery_state global var */
|
||||||
#include "action.h" /* for keys_locked */
|
#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 */
|
bar->info.led = led_read(HZ/2); /* delay should match polling interval */
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_RTC
|
#ifdef CONFIG_RTC
|
||||||
|
#if CONFIG_RTC == RTC_DS1339_DS3231
|
||||||
|
if(rtc_detected)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
struct tm* tm = get_time();
|
struct tm* tm = get_time();
|
||||||
bar->info.hour = tm->tm_hour;
|
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);
|
gui_statusbar_icon_lock_remote(display);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_RTC
|
#ifdef CONFIG_RTC
|
||||||
|
#if CONFIG_RTC == RTC_DS1339_DS3231
|
||||||
|
if(rtc_detected)
|
||||||
|
#endif
|
||||||
gui_statusbar_time(display, bar->info.hour, bar->info.minute);
|
gui_statusbar_time(display, bar->info.hour, bar->info.minute);
|
||||||
#endif /* CONFIG_RTC */
|
#endif /* CONFIG_RTC */
|
||||||
#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
|
#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
|
||||||
|
|
|
@ -38,6 +38,12 @@
|
||||||
#ifdef HAVE_ALARM_MOD
|
#ifdef HAVE_ALARM_MOD
|
||||||
#include "alarm_menu.h"
|
#include "alarm_menu.h"
|
||||||
#endif
|
#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 */
|
/* TAGCACHE MENU */
|
||||||
|
@ -206,7 +212,7 @@ static int timedate_set(void)
|
||||||
|
|
||||||
MENUITEM_FUNCTION(time_set, ID2P(LANG_TIME), timedate_set, NULL, NOICON);
|
MENUITEM_FUNCTION(time_set, ID2P(LANG_TIME), timedate_set, NULL, NOICON);
|
||||||
MENUITEM_SETTING(timeformat, &global_settings.timeformat, NULL);
|
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
|
#endif
|
||||||
|
|
||||||
/* System menu */
|
/* System menu */
|
||||||
|
@ -246,7 +252,7 @@ MENUITEM_FUNCTION(sleep_timer_call, ID2P(LANG_SLEEP_TIMER), sleep_timer,
|
||||||
setting to the user */
|
setting to the user */
|
||||||
#ifdef HAVE_ALARM_MOD
|
#ifdef HAVE_ALARM_MOD
|
||||||
MENUITEM_FUNCTION(alarm_screen_call, ID2P(LANG_ALARM_MOD_ALARM_MENU),
|
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
|
#endif
|
||||||
|
|
||||||
/* Limits menu */
|
/* Limits menu */
|
||||||
|
@ -383,3 +389,23 @@ MAKE_MENU(settings_menu_item, ID2P(LANG_GENERAL_SETTINGS), 0,
|
||||||
&bookmark_settings_menu, &browse_langs, &voice_settings_menu );
|
&bookmark_settings_menu, &browse_langs, &voice_settings_menu );
|
||||||
/* 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;
|
||||||
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
#include "gui/gwps-common.h"
|
#include "gui/gwps-common.h"
|
||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "rtc.h"
|
||||||
|
|
||||||
/* Format a large-range value for output, using the appropriate unit so that
|
/* 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"
|
* the displayed value is in the range 1 <= display < 1000 (1024 for "binary"
|
||||||
|
@ -414,6 +415,12 @@ void screen_dump(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_RTC
|
#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);
|
create_datetime_filename(filename, "", "dump ", ".bmp", false);
|
||||||
#else
|
#else
|
||||||
create_numbered_filename(filename, "", "dump_", ".bmp", 4
|
create_numbered_filename(filename, "", "dump_", ".bmp", 4
|
||||||
|
|
|
@ -277,7 +277,7 @@ extern const fb_data clock_timesup[];
|
||||||
#define EXIT_BUTTON BUTTON_MENU
|
#define EXIT_BUTTON BUTTON_MENU
|
||||||
#define MODE_NEXT_BUTTON BUTTON_RIGHT
|
#define MODE_NEXT_BUTTON BUTTON_RIGHT
|
||||||
#define MODE_PREV_BUTTON BUTTON_LEFT
|
#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_TOGGLE_BUTTON (BUTTON_ON|BUTTON_REL)
|
||||||
#define COUNTER_RESET_BUTTON (BUTTON_ON|BUTTON_REPEAT)
|
#define COUNTER_RESET_BUTTON (BUTTON_ON|BUTTON_REPEAT)
|
||||||
#define MENU_BUTTON BUTTON_SELECT
|
#define MENU_BUTTON BUTTON_SELECT
|
||||||
|
|
|
@ -68,6 +68,9 @@
|
||||||
#include "screen_access.h"
|
#include "screen_access.h"
|
||||||
#include "action.h"
|
#include "action.h"
|
||||||
#include "radio.h"
|
#include "radio.h"
|
||||||
|
#ifdef CONFIG_RTC
|
||||||
|
#include "rtc.h"
|
||||||
|
#endif
|
||||||
#ifdef HAVE_RECORDING
|
#ifdef HAVE_RECORDING
|
||||||
|
|
||||||
static bool in_screen = false;
|
static bool in_screen = false;
|
||||||
|
@ -521,6 +524,12 @@ char *rec_create_filename(char *buffer)
|
||||||
#ifdef CONFIG_RTC
|
#ifdef CONFIG_RTC
|
||||||
/* We'll wait at least up to the start of the next second so no duplicate
|
/* We'll wait at least up to the start of the next second so no duplicate
|
||||||
names are created */
|
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);
|
return create_datetime_filename(buffer, buffer, "R", ext, true);
|
||||||
#else
|
#else
|
||||||
return create_numbered_filename(buffer, buffer, "rec_", ext, 4
|
return create_numbered_filename(buffer, buffer, "rec_", ext, 4
|
||||||
|
|
|
@ -35,6 +35,7 @@ http://www.audioscrobbler.net/wiki/Portable_Player_Logging
|
||||||
#ifdef CONFIG_RTC
|
#ifdef CONFIG_RTC
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
#include "timefuncs.h"
|
#include "timefuncs.h"
|
||||||
|
#include "rtc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "scrobbler.h"
|
#include "scrobbler.h"
|
||||||
|
@ -208,6 +209,11 @@ void scrobbler_change_event(struct mp3entry *id)
|
||||||
logf("SCROBBLER: add pending");
|
logf("SCROBBLER: add pending");
|
||||||
copy_mp3entry(&scrobbler_entry, id);
|
copy_mp3entry(&scrobbler_entry, id);
|
||||||
#ifdef CONFIG_RTC
|
#ifdef CONFIG_RTC
|
||||||
|
#if CONFIG_RTC == RTC_DS1339_DS3231
|
||||||
|
if(!rtc_detected)
|
||||||
|
timestamp = 0;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
timestamp = mktime(get_time());
|
timestamp = mktime(get_time());
|
||||||
#else
|
#else
|
||||||
timestamp = 0;
|
timestamp = 0;
|
||||||
|
|
|
@ -137,6 +137,8 @@ drivers/rtc/rtc_pcf50606.c
|
||||||
drivers/rtc/rtc_pcf50605.c
|
drivers/rtc/rtc_pcf50605.c
|
||||||
#elif (CONFIG_RTC == RTC_E8564)
|
#elif (CONFIG_RTC == RTC_E8564)
|
||||||
drivers/rtc/rtc_e8564.c
|
drivers/rtc/rtc_e8564.c
|
||||||
|
#elif (CONFIG_RTC == RTC_DS1339_DS3231)
|
||||||
|
drivers/rtc/rtc_ds1339_ds3231.c
|
||||||
#elif (CONFIG_RTC == RTC_S3C2440)
|
#elif (CONFIG_RTC == RTC_S3C2440)
|
||||||
drivers/rtc/rtc_s3c2440.c
|
drivers/rtc/rtc_s3c2440.c
|
||||||
#elif (CONFIG_RTC == RTC_AS3514)
|
#elif (CONFIG_RTC == RTC_AS3514)
|
||||||
|
@ -380,6 +382,7 @@ target/coldfire/pcf50606-coldfire.c
|
||||||
target/coldfire/iriver/ata-iriver.c
|
target/coldfire/iriver/ata-iriver.c
|
||||||
target/coldfire/iriver/lcd-remote-iriver.c
|
target/coldfire/iriver/lcd-remote-iriver.c
|
||||||
target/coldfire/iriver/system-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/adc-h300.c
|
||||||
target/coldfire/iriver/h300/backlight-h300.c
|
target/coldfire/iriver/h300/backlight-h300.c
|
||||||
target/coldfire/iriver/h300/button-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/ata-iriver.c
|
||||||
target/coldfire/iriver/lcd-remote-iriver.c
|
target/coldfire/iriver/lcd-remote-iriver.c
|
||||||
target/coldfire/iriver/system-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/adc-h100.c
|
||||||
target/coldfire/iriver/h100/backlight-h100.c
|
target/coldfire/iriver/h100/backlight-h100.c
|
||||||
target/coldfire/iriver/h100/button-h100.c
|
target/coldfire/iriver/h100/button-h100.c
|
||||||
|
|
|
@ -49,6 +49,19 @@ struct tm *get_time(void)
|
||||||
#ifdef CONFIG_RTC
|
#ifdef CONFIG_RTC
|
||||||
static long timeout = 0;
|
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 */
|
/* Don't read the RTC more than once per second */
|
||||||
if (current_tick > timeout) {
|
if (current_tick > timeout) {
|
||||||
char rtcbuf[7];
|
char rtcbuf[7];
|
||||||
|
|
|
@ -16,274 +16,21 @@
|
||||||
* KIND, either express or implied.
|
* 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 "logf.h"
|
||||||
#include "sprintf.h"
|
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "inttypes.h"
|
#include "inttypes.h"
|
||||||
|
|
||||||
|
#include "sw_i2c.h"
|
||||||
|
|
||||||
#include "eeprom_24cxx.h"
|
#include "eeprom_24cxx.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* I2C-functions are copied and ported from fmradio.c.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define SW_I2C_WRITE 0
|
|
||||||
#define SW_I2C_READ 1
|
|
||||||
|
|
||||||
/* Use cache to speedup writing to the chip. */
|
/* Use cache to speedup writing to the chip. */
|
||||||
static char data_cache[EEPROM_SIZE];
|
static char data_cache[EEPROM_SIZE];
|
||||||
static uint8_t cached_bitfield[EEPROM_SIZE/8];
|
static uint8_t cached_bitfield[EEPROM_SIZE/8];
|
||||||
|
|
||||||
#define IS_CACHED(addr) (cached_bitfield[addr/8] & (1 << (addr % 8)))
|
#define IS_CACHED(addr) (cached_bitfield[addr/8] & (1 << (addr % 8)))
|
||||||
#define SET_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void eeprom_24cxx_init(void)
|
void eeprom_24cxx_init(void)
|
||||||
{
|
{
|
||||||
|
@ -314,7 +61,7 @@ int eeprom_24cxx_read_byte(unsigned int address, char *c)
|
||||||
*c = 0;
|
*c = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ret = sw_i2c_read(address, &byte);
|
ret = sw_i2c_read(EEPROM_ADDR, address, &byte, 1);
|
||||||
} while (ret < 0 && count++ < 200);
|
} while (ret < 0 && count++ < 200);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -357,7 +104,7 @@ int eeprom_24cxx_write_byte(unsigned int address, char c)
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ret = sw_i2c_write_byte(address, c);
|
ret = sw_i2c_write(EEPROM_ADDR, address, &c, 1);
|
||||||
} while (ret < 0 && count++ < 200) ;
|
} while (ret < 0 && count++ < 200) ;
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
#include "rbunicode.h"
|
#include "rbunicode.h"
|
||||||
#include "logf.h"
|
#include "logf.h"
|
||||||
#include "atoi.h"
|
#include "atoi.h"
|
||||||
|
#ifdef CONFIG_RTC
|
||||||
|
#include "rtc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define BYTES2INT16(array,pos) \
|
#define BYTES2INT16(array,pos) \
|
||||||
(array[pos] | (array[pos+1] << 8 ))
|
(array[pos] | (array[pos+1] << 8 ))
|
||||||
|
@ -945,6 +948,10 @@ static void fat_time(unsigned short* date,
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_RTC
|
#ifdef CONFIG_RTC
|
||||||
struct tm* tm = get_time();
|
struct tm* tm = get_time();
|
||||||
|
#if CONFIG_RTC == RTC_DS1339_DS3231
|
||||||
|
if(rtc_detected)
|
||||||
|
{
|
||||||
|
#endif /* CONFIG_RTC == RTC_DS1339_DS3231 */
|
||||||
|
|
||||||
if (date)
|
if (date)
|
||||||
*date = ((tm->tm_year - 80) << 9) |
|
*date = ((tm->tm_year - 80) << 9) |
|
||||||
|
@ -958,7 +965,14 @@ static void fat_time(unsigned short* date,
|
||||||
|
|
||||||
if (tenth)
|
if (tenth)
|
||||||
*tenth = (tm->tm_sec & 1) * 100;
|
*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
|
/* non-RTC version returns an increment from the supplied time, or a
|
||||||
* fixed standard time/date if no time given as input */
|
* fixed standard time/date if no time given as input */
|
||||||
bool next_day = false;
|
bool next_day = false;
|
||||||
|
@ -1025,9 +1039,9 @@ static void fat_time(unsigned short* date,
|
||||||
}
|
}
|
||||||
if (tenth)
|
if (tenth)
|
||||||
*tenth = 0;
|
*tenth = 0;
|
||||||
#endif /* CONFIG_RTC */
|
}
|
||||||
|
#endif /* !defined(CONFIG_RTC) || CONFIG_RTC == RTC_DS1339_DS3231 */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_long_name(struct fat_file* file,
|
static int write_long_name(struct fat_file* file,
|
||||||
unsigned int firstentry,
|
unsigned int firstentry,
|
||||||
unsigned int numentries,
|
unsigned int numentries,
|
||||||
|
|
144
firmware/drivers/rtc/rtc_ds1339_ds3231.c
Normal file
144
firmware/drivers/rtc/rtc_ds1339_ds3231.c
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -45,7 +45,13 @@
|
||||||
/* Define this if you do software codec */
|
/* Define this if you do software codec */
|
||||||
#define CONFIG_CODEC SWCODEC
|
#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 HAVE_REMOTE_LCD
|
||||||
|
|
||||||
#define CONFIG_LCD LCD_S1D15E06
|
#define CONFIG_LCD LCD_S1D15E06
|
||||||
|
|
|
@ -153,6 +153,7 @@
|
||||||
#define RTC_S3C2440 4
|
#define RTC_S3C2440 4
|
||||||
#define RTC_E8564 5 /* iriver H10 */
|
#define RTC_E8564 5 /* iriver H10 */
|
||||||
#define RTC_AS3514 6 /* Sandisk Sansa e200 series */
|
#define RTC_AS3514 6 /* Sandisk Sansa e200 series */
|
||||||
|
#define RTC_DS1339_DS3231 7 /* h1x0 RTC mod */
|
||||||
|
|
||||||
/* USB On-the-go */
|
/* USB On-the-go */
|
||||||
#define USBOTG_ISP1362 1362 /* iriver H300 */
|
#define USBOTG_ISP1362 1362 /* iriver H300 */
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#define _RTC_H_
|
#define _RTC_H_
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <system.h>
|
||||||
|
|
||||||
#ifdef CONFIG_RTC
|
#ifdef CONFIG_RTC
|
||||||
|
|
||||||
|
@ -27,6 +28,10 @@ extern const int dayname[];
|
||||||
|
|
||||||
extern const int monthname[];
|
extern const int monthname[];
|
||||||
|
|
||||||
|
#if CONFIG_RTC == RTC_DS1339_DS3231
|
||||||
|
extern bool rtc_detected;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Common functions for all targets */
|
/* Common functions for all targets */
|
||||||
void rtc_init(void);
|
void rtc_init(void);
|
||||||
int rtc_read_datetime(unsigned char* buf);
|
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_read_multiple(unsigned char address, unsigned char *buf, int numbytes);
|
||||||
int rtc_write(unsigned char address, unsigned char value);
|
int rtc_write(unsigned char address, unsigned char value);
|
||||||
|
|
||||||
|
#endif /* RTC_M41ST84W */
|
||||||
|
|
||||||
#ifdef HAVE_ALARM_MOD
|
#ifdef HAVE_ALARM_MOD
|
||||||
void rtc_set_alarm(int h, int m);
|
void rtc_set_alarm(int h, int m);
|
||||||
void rtc_get_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);
|
bool rtc_check_alarm_flag(void);
|
||||||
#endif /* HAVE_ALARM_MOD */
|
#endif /* HAVE_ALARM_MOD */
|
||||||
|
|
||||||
#endif /* RTC_M41ST84W */
|
|
||||||
|
|
||||||
#endif /* CONFIG_RTC */
|
#endif /* CONFIG_RTC */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
30
firmware/export/sw_i2c.h
Normal file
30
firmware/export/sw_i2c.h
Normal file
|
@ -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
|
259
firmware/target/coldfire/iriver/h100/sw_i2c-h100.c
Normal file
259
firmware/target/coldfire/iriver/h100/sw_i2c-h100.c
Normal file
|
@ -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;
|
||||||
|
}
|
105
firmware/target/coldfire/iriver/h300/sw_i2c-h300.c
Normal file
105
firmware/target/coldfire/iriver/h300/sw_i2c-h300.c
Normal file
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in a new issue