summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorBrandon Low <lostlogic@rockbox.org>2006-03-05 18:06:06 +0000
committerBrandon Low <lostlogic@rockbox.org>2006-03-05 18:06:06 +0000
commit63c0d1dd9c22658b12a48dfc2015bfb0bf1239a4 (patch)
tree6d940115b5d19c1c5a533bd6139c39bdd2a0916c /firmware
parent4594ad460592ef56f2f1cdc5de132152257dfd5a (diff)
downloadrockbox-63c0d1dd9c22658b12a48dfc2015bfb0bf1239a4.tar.gz
rockbox-63c0d1dd9c22658b12a48dfc2015bfb0bf1239a4.zip
Basic battery monitoring for ipod 5g, should work on other ipods as well, but needs testing and stuff. Also improved the RTC driver and moved it to where it belongs, and interrupt protected a bunch of possibly broken i2c. Also start preparing code for ipod charge monitoring. Note: on the 5g, this takes up enough processor time to increase skippiness noticeably in WPS.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8911 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES2
-rw-r--r--firmware/drivers/adc.c42
-rw-r--r--firmware/drivers/i2c-pp5020.c1
-rw-r--r--firmware/drivers/pcf50605.c46
-rw-r--r--firmware/drivers/power.c3
-rw-r--r--firmware/drivers/rtc.c50
-rw-r--r--firmware/drivers/wm8758.c22
-rw-r--r--firmware/export/adc.h8
-rw-r--r--firmware/export/config-ipodvideo.h4
-rw-r--r--firmware/export/pcf50605.h5
10 files changed, 118 insertions, 65 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 7ebfba38e1..f09c7d1aab 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -134,7 +134,7 @@ drivers/pcf50606.c
#ifdef IPOD_ARCH
drivers/pcf50605.c
#endif
-#if (CONFIG_RTC == RTC_M41ST84W) || (CONFIG_RTC == RTC_PCF50606)
+#if (CONFIG_RTC == RTC_M41ST84W) || (CONFIG_RTC == RTC_PCF50606) || (CONFIG_RTC == RTC_PCF50605)
drivers/rtc.c
#endif
drivers/serial.c
diff --git a/firmware/drivers/adc.c b/firmware/drivers/adc.c
index 6e1c57766a..1755fafb99 100644
--- a/firmware/drivers/adc.c
+++ b/firmware/drivers/adc.c
@@ -22,6 +22,7 @@
#include "kernel.h"
#include "thread.h"
#include "adc.h"
+#include "pcf50605.h"
#include "pcf50606.h"
#if CONFIG_CPU == SH7034
@@ -119,7 +120,7 @@ static int channelnum[] =
2, /* ADC_REMOTEDETECT (ADCIN1, resistive divider) */
};
-unsigned char adc_scan(int channel)
+unsigned short adc_scan(int channel)
{
unsigned char data;
@@ -143,7 +144,7 @@ unsigned char adc_scan(int channel)
/* delay loop */
#define DELAY do { int _x; for(_x=0;_x<10;_x++);} while (0)
-unsigned char adc_scan(int channel)
+unsigned short adc_scan(int channel)
{
unsigned char data = 0;
int i;
@@ -220,8 +221,7 @@ static void adc_tick(void)
void adc_init(void)
{
-#ifdef IRIVER_H300_SERIES
-#else
+#ifndef IRIVER_H300_SERIES
or_l(0x80600080, &GPIO_FUNCTION); /* GPIO7: CS
GPIO21: Data In (to the ADC)
GPIO22: CLK
@@ -284,17 +284,45 @@ void adc_init(void)
#elif CONFIG_CPU == PP5020 || (CONFIG_CPU == PP5002)
-/* TODO: Implement adc.c */
+struct adc_struct {
+ long last_read;
+ int channelnum;
+ unsigned short data;
+};
+
+static struct adc_struct adcdata[NUM_ADC_CHANNELS];
+
+static unsigned short adc_scan(struct adc_struct *adc)
+{
+ /* Disable interrupts during the I2C transaction */
+ int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
+ unsigned short data = pcf50605_a2d_read(adc->channelnum);
+ set_irq_level(old_irq_level);
+ /* This gives us a 13 bit value corresponding to 0-5.4 volts
+ * The range of the value is 13FB-17FA */
+ data = (data<<2)+0x13FB;
+ adc->data = data;
+
+ return data;
+}
unsigned short adc_read(int channel)
{
- (void)channel;
- return 0;
+ struct adc_struct *adc = &adcdata[channel];
+ if (adc->last_read + HZ < current_tick) {
+ adc->last_read = current_tick;
+ return adc_scan(adc);
+ } else {
+ return adcdata[channel].data;
+ }
}
void adc_init(void)
{
+ struct adc_struct *adc_battery = &adcdata[ADC_BATTERY];
+ adc_battery->channelnum = 0x3; /* ADCVIN1, subtractor */
+ adc_scan(adc_battery);
}
#elif CONFIG_CPU == PNX0101
diff --git a/firmware/drivers/i2c-pp5020.c b/firmware/drivers/i2c-pp5020.c
index 9f26d3be6e..522ddbed77 100644
--- a/firmware/drivers/i2c-pp5020.c
+++ b/firmware/drivers/i2c-pp5020.c
@@ -57,7 +57,6 @@ static int ipod_i2c_wait_not_busy(void)
if (!(inb(IPOD_I2C_STATUS) & IPOD_I2C_BUSY)) {
return 0;
}
- yield();
}
return -1;
diff --git a/firmware/drivers/pcf50605.c b/firmware/drivers/pcf50605.c
index 122ba6ee38..7d2036e807 100644
--- a/firmware/drivers/pcf50605.c
+++ b/firmware/drivers/pcf50605.c
@@ -98,22 +98,12 @@ int pcf50605_write_multiple(int address, const unsigned char* buf, int count)
return 0;
}
-static int pcf50605_a2d_read(int adc_input)
+unsigned short pcf50605_a2d_read(int adc_input)
{
- int hi, lo;
+ unsigned short hi;
+ unsigned char lo;
- /* Enable ACD module */
- ipod_i2c_send(0x8, 0x33, 0x80); /* ACDC1, ACDAPE = 1 */
-
- /* select ADCIN1 - subtractor, and start sampling process */
ipod_i2c_send(0x8, 0x2f, (adc_input<<1) | 0x1); /* ADCC2, ADCMUX = adc_input, ADCSTART = 1 */
-
- /* ADCC2, wait for ADCSTART = 0 (wait for sampling to start) */
- while ((i2c_readbyte(0x8, 0x2f) & 1)) /* do nothing */;
-
- /* ADCS2, wait ADCRDY = 0 (wait for sampling to end) */
- while (!(i2c_readbyte(0x8, 0x31) & 0x80)) /* do nothing */;
-
hi = i2c_readbyte(0x8, 0x30); /* ADCS1 */
lo = (i2c_readbyte(0x8, 0x31) & 0x3); /* ADCS2 */
@@ -129,33 +119,3 @@ void pcf50605_standby_mode(void)
pcf50605_write(OOCC1, GOSTDBY | CHGWAK | EXTONWAK);
}
-int pcf50605_battery_read(void)
-{
- return pcf50605_a2d_read(0x3); /* ADCIN1, subtractor */
-}
-
-void rtc_init(void)
-{
- /* Nothing to do. */
-}
-
-int rtc_read_datetime(unsigned char* buf)
-{
- int rc;
-
- rc = pcf50605_read_multiple(0x0a, buf, 7);
-
- return rc;
-}
-
-
-int rtc_write_datetime(unsigned char* buf)
-{
- int i;
-
- for (i=0;i<7;i++) {
- ipod_i2c_send(0x8, 0x0a+i, buf[i]);
- }
-
- return 1;
-}
diff --git a/firmware/drivers/power.c b/firmware/drivers/power.c
index c6d49f5aa9..9f3a10cc84 100644
--- a/firmware/drivers/power.c
+++ b/firmware/drivers/power.c
@@ -123,6 +123,9 @@ bool charger_inserted(void)
return (adc_read(ADC_CHARGE_REGULATOR) < 0x1FF);
#elif defined(TOSHIBA_GIGABEAT_F)
return false;
+#elif defined(IPOD_ARCH)
+ /* We need to get this value a faster way than i2c */
+ return false;
#else
/* Player */
return (PADR & 1) == 0;
diff --git a/firmware/drivers/rtc.c b/firmware/drivers/rtc.c
index 0e6d68eb1a..6458092348 100644
--- a/firmware/drivers/rtc.c
+++ b/firmware/drivers/rtc.c
@@ -23,24 +23,62 @@
#include "kernel.h"
#include "system.h"
#include "pcf50606.h"
+#include "pcf50605.h"
#include <stdbool.h>
#define RTC_ADR 0xd0
#define RTC_DEV_WRITE (RTC_ADR | 0x00)
#define RTC_DEV_READ (RTC_ADR | 0x01)
-#if CONFIG_RTC == RTC_PCF50606
+#if CONFIG_RTC == RTC_PCF50605
void rtc_init(void)
{
}
-int rtc_read_datetime(unsigned char* buf) {
+int rtc_read_datetime(unsigned char* buf)
+{
int rc;
- int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
-
- rc = pcf50606_read_multiple(0x0a, buf, 7);
+ int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
- set_irq_level(oldlevel);
+ rc = pcf50605_read_multiple(0x0a, buf, 7);
+
+ set_irq_level(old_irq_level);
+
+ return rc;
+}
+
+
+int rtc_write_datetime(unsigned char* buf)
+{
+ int i;
+ int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
+
+ for (i=0;i<7;i++) {
+ pcf50605_write(0x0a+i, buf[i]);
+ }
+
+ set_irq_level(old_irq_level);
+
+ return 1;
+}
+#elif CONFIG_RTC == RTC_PCF50606
+static int last_tick;
+static char rtc_buf[7];
+void rtc_init(void)
+{
+ last_tick = 0;
+}
+int rtc_read_datetime(unsigned char* buf) {
+ int rc;
+ if (last_tick + HZ/2 < current_tick) {
+ int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
+ last_tick = current_tick;
+ rc = pcf50606_read_multiple(0x0a, rtc_buf, 7);
+ set_irq_level(oldlevel);
+ } else {
+ rc = 7;
+ }
+ memcpy(buf, rtc_buf, 7);
return rc;
}
diff --git a/firmware/drivers/wm8758.c b/firmware/drivers/wm8758.c
index aec6f3b598..7c9ac77395 100644
--- a/firmware/drivers/wm8758.c
+++ b/firmware/drivers/wm8758.c
@@ -86,8 +86,7 @@ void wm8758_write(int reg, int data)
* Note, I'm using the WM8750 datasheet as its apparently close.
*/
int wmcodec_init(void) {
- /* reset I2C */
- i2c_init();
+ int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
/* normal outputs for CDI and I2S pin groups */
outl(inl(0x70000020) & ~0x300, 0x70000020);
@@ -109,6 +108,7 @@ int wmcodec_init(void) {
/* external dev clock to 24MHz */
outl(inl(0x70000018) & ~0xc, 0x70000018);
+ set_irq_level(old_irq_level);
return 0;
}
@@ -117,6 +117,8 @@ void wmcodec_enable_output(bool enable)
{
if (enable)
{
+ int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
+
/* reset the I2S controller into known state */
i2s_reset();
@@ -140,6 +142,7 @@ void wmcodec_enable_output(bool enable)
wm8758_write(LOUTMIX,0x1); /* Enable mixer */
wm8758_write(ROUTMIX,0x1); /* Enable mixer */
wmcodec_mute(0);
+ set_irq_level(old_irq_level);
} else {
wmcodec_mute(1);
}
@@ -147,6 +150,7 @@ void wmcodec_enable_output(bool enable)
int wmcodec_set_master_vol(int vol_l, int vol_r)
{
+ int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
/* OUT1 */
wm8758_write(LOUT1VOL, vol_l);
wm8758_write(ROUT1VOL, 0x100 | vol_r);
@@ -154,6 +158,8 @@ int wmcodec_set_master_vol(int vol_l, int vol_r)
/* OUT2 */
wm8758_write(LOUT2VOL, vol_l);
wm8758_write(ROUT2VOL, 0x100 | vol_r);
+
+ set_irq_level(old_irq_level);
return 0;
}
@@ -198,6 +204,8 @@ void wmcodec_set_treble(int value)
int wmcodec_mute(int mute)
{
+ int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
+
if (mute)
{
/* Set DACMU = 1 to soft-mute the audio DACs. */
@@ -207,12 +215,16 @@ int wmcodec_mute(int mute)
wm8758_write(DACCTRL, 0x0);
}
+ set_irq_level(old_irq_level);
+
return 0;
}
/* Nice shutdown of WM8758 codec */
void wmcodec_close(void)
{
+ int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
+
wmcodec_mute(1);
wm8758_write(PWRMGMT3, 0x0);
@@ -220,6 +232,8 @@ void wmcodec_close(void)
wm8758_write(PWRMGMT1, 0x0);
wm8758_write(PWRMGMT2, 0x40);
+
+ set_irq_level(old_irq_level);
}
/* Change the order of the noise shaper, 5th order is recommended above 32kHz */
@@ -231,6 +245,8 @@ void wmcodec_set_nsorder(int order)
/* Note: Disable output before calling this function */
void wmcodec_set_sample_rate(int sampling_control)
{
+ int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
+
/**** We force 44.1KHz for now. ****/
(void)sampling_control;
@@ -248,6 +264,8 @@ void wmcodec_set_sample_rate(int sampling_control)
/* set srate */
wm8758_write(SRATECTRL, (0 << 1));
+
+ set_irq_level(old_irq_level);
}
void wmcodec_enable_recording(bool source_mic)
diff --git a/firmware/export/adc.h b/firmware/export/adc.h
index 454c102403..b0a83d9bd0 100644
--- a/firmware/export/adc.h
+++ b/firmware/export/adc.h
@@ -29,6 +29,12 @@
#define ADC_BATTERY 2
#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */
+#elif defined(IPOD_ARCH)
+#define NUM_ADC_CHANNELS 1
+
+#define ADC_BATTERY 0
+#define ADC_UNREG_POWER ADC_BATTERY
+
#elif defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
#define NUM_ADC_CHANNELS 4
@@ -94,7 +100,7 @@ void adc_init(void);
#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)\
|| defined(IAUDIO_X5)
-unsigned char adc_scan(int channel);
+unsigned short adc_scan(int channel);
#endif
#endif
diff --git a/firmware/export/config-ipodvideo.h b/firmware/export/config-ipodvideo.h
index 2bf0396a21..1fa778dbc4 100644
--- a/firmware/export/config-ipodvideo.h
+++ b/firmware/export/config-ipodvideo.h
@@ -59,9 +59,9 @@
#define CONFIG_I2C I2C_PP5020
/* Type of mobile power */
-//#define CONFIG_BATTERY BATT_LIPOL1300
+#define CONFIG_BATTERY BATT_LIPOL1300
-#define BATTERY_SCALE_FACTOR 16665 /* FIX: this value is picked at random */
+#define BATTERY_SCALE_FACTOR 586 /* FIX: this value is picked at random */
/* Define this if the platform can charge batteries */
//#define HAVE_CHARGING 1
diff --git a/firmware/export/pcf50605.h b/firmware/export/pcf50605.h
index 95fcaff8fb..4ea1379e4a 100644
--- a/firmware/export/pcf50605.h
+++ b/firmware/export/pcf50605.h
@@ -22,10 +22,11 @@
#ifdef IPOD_ARCH
int pcf50605_read(int address);
-void pcf50605_read_multiple(int address, unsigned char* buf, int count);
+int pcf50605_read_multiple(int address, unsigned char* buf, int count);
int pcf50605_write(int address, unsigned char val);
int pcf50605_write_multiple(int address, const unsigned char* buf, int count);
-int pcf50605_battery_read(void);
+int pcf50605_a2d_read(int channel);
+bool pcf50605_charger_inserted(void);
void pcf50605_standby_mode(void);
#endif