summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrandon Low <lostlogic@rockbox.org>2006-03-09 19:47:12 +0000
committerBrandon Low <lostlogic@rockbox.org>2006-03-09 19:47:12 +0000
commit19f4c2a093698940482aad6df0bd8478a82f2a9d (patch)
tree66de55749bcaaf45d95b828423ffca8c715b7112
parent5ecac908a2738e7a83dc0227daef3aaf16787dbc (diff)
downloadrockbox-19f4c2a093698940482aad6df0bd8478a82f2a9d.zip
rockbox-19f4c2a093698940482aad6df0bd8478a82f2a9d.tar.gz
rockbox-19f4c2a093698940482aad6df0bd8478a82f2a9d.tar.bz2
rockbox-19f4c2a093698940482aad6df0bd8478a82f2a9d.tar.xz
Improve ipod i2c driver somewhat by at least taking advantage of the in-device addressing in the pcf50605, also switch to a 10bit resistive divider for the ipod battery reading, this is easily configurable if it needs changing, or even to become a user/runtime setting
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8980 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/common/timefuncs.c9
-rw-r--r--firmware/drivers/adc.c67
-rw-r--r--firmware/drivers/i2c-pp5002.c10
-rw-r--r--firmware/drivers/i2c-pp5020.c32
-rw-r--r--firmware/drivers/pcf50605.c12
-rw-r--r--firmware/drivers/rtc.c2
-rw-r--r--firmware/export/i2c-pp5002.h1
-rw-r--r--firmware/export/i2c-pp5020.h1
8 files changed, 77 insertions, 57 deletions
diff --git a/firmware/common/timefuncs.c b/firmware/common/timefuncs.c
index 275fc6c..5cf1a35 100644
--- a/firmware/common/timefuncs.c
+++ b/firmware/common/timefuncs.c
@@ -47,12 +47,13 @@ struct tm *get_time(void)
{
#ifndef SIMULATOR
#ifdef CONFIG_RTC
- static long last_tick = 0;
+ static long timeout = 0;
- /* Don't read the RTC more than 4 times per second */
- if (last_tick + HZ < current_tick) {
+ /* Don't read the RTC more than once per second */
+ if (current_tick > timeout) {
char rtcbuf[7];
- last_tick = HZ * (current_tick / HZ);
+ /* Once per second, 1/10th of a second off */
+ timeout = HZ * (current_tick / HZ + 1) + HZ / 5;
rtc_read_datetime(rtcbuf);
tm.tm_sec = ((rtcbuf[0] & 0x70) >> 4) * 10 + (rtcbuf[0] & 0x0f);
diff --git a/firmware/drivers/adc.c b/firmware/drivers/adc.c
index a75f788..4a99a49 100644
--- a/firmware/drivers/adc.c
+++ b/firmware/drivers/adc.c
@@ -286,60 +286,57 @@ void adc_init(void)
#elif CONFIG_CPU == PP5020 || (CONFIG_CPU == PP5002)
struct adc_struct {
- long last_read;
- unsigned short (*conversion)(unsigned short data);
+ long timeout;
+ void (*conversion)(unsigned short *data);
short channelnum;
unsigned short data;
};
static struct adc_struct adcdata[NUM_ADC_CHANNELS] IDATA_ATTR;
-/* This takes 10 bit ADC data from the subtractor circuit and scales it to
- * a 13 bit value corresponding to 0-5.4v, the resulting range is 13FB-17FA,
- * representing 3.1-5.4v */
-static unsigned short ten_bit_subtractor(unsigned short data) {
- return (data<<2)+0x4FB;
-}
-
-static unsigned short _adc_scan(struct adc_struct *adc)
+static unsigned short _adc_read(struct adc_struct *adc)
{
- unsigned short data;
-
- /* ADCC1, 8 bit, start */
- pcf50605_write(0x2f, 0x80 | (adc->channelnum << 1) | 0x1);
- data = pcf50605_read(0x30); /* ADCS1 */
-
- if (adc->conversion) {
- data = adc->conversion(data);
+ if (adc->timeout < current_tick) {
+ unsigned char data[2];
+ unsigned short value;
+ /* 5x per 2 seconds */
+ adc->timeout = current_tick + (HZ * 2 / 5);
+
+ /* ADCC1, 10 bit, start */
+ pcf50605_write(0x2f, (adc->channelnum << 1) | 0x1);
+ pcf50605_read_multiple(0x30, data, 2); /* ADCS1, ADCS2 */
+ value = data[0];
+ value <<= 2;
+ value |= data[1] & 0x3;
+
+ if (adc->conversion) {
+ adc->conversion(&value);
+ }
+ adc->data = value;
+ return value;
+ } else {
+ return adc->data;
}
- adc->data = data;
- return data;
}
/* Force an ADC scan _now_ */
unsigned short adc_scan(int channel) {
- return _adc_scan(&adcdata[channel]);
+ struct adc_struct *adc = &adcdata[channel];
+ adc->timeout = 0;
+ return _adc_read(adc);
}
-/* Retrieve the ADC value, only does a scan once per second or less */
-unsigned short adc_read(int channel)
-{
- struct adc_struct *adc = &adcdata[channel];
- if (adc->last_read + HZ < current_tick) {
- adc->last_read = current_tick;
- return _adc_scan(adc);
- } else {
- return adc->data;
- }
+/* Retrieve the ADC value, only does a scan periodically */
+unsigned short adc_read(int channel) {
+ return _adc_read(&adcdata[channel]);
}
void adc_init(void)
{
struct adc_struct *adc_battery = &adcdata[ADC_BATTERY];
- adc_battery->channelnum = 0x3; /* ADCVIN1, subtractor */
- adc_battery->conversion = ten_bit_subtractor;
- adc_battery->last_read = current_tick;
- _adc_scan(adc_battery);
+ adc_battery->channelnum = 0x2; /* ADCVIN1, resistive divider */
+ adc_battery->timeout = 0;
+ _adc_read(adc_battery);
}
#elif CONFIG_CPU == PNX0101
diff --git a/firmware/drivers/i2c-pp5002.c b/firmware/drivers/i2c-pp5002.c
index dc26d8a..958ddee 100644
--- a/firmware/drivers/i2c-pp5002.c
+++ b/firmware/drivers/i2c-pp5002.c
@@ -136,6 +136,16 @@ int ipod_i2c_send_byte(unsigned int addr, int data0)
return ipod_i2c_send_bytes(addr, 1, data);
}
+int i2c_readbytes(unsigned int dev_addr, int addr, int len, unsigned char *data) {
+ unsigned int temp;
+ int i;
+ ipod_i2c_send_byte(dev_addr, addr);
+ for (i = 0; i < len; i++) {
+ ipod_i2c_read_byte(dev_addr, &temp);
+ data[i] = temp;
+ }
+ return i;
+}
int i2c_readbyte(unsigned int dev_addr, int addr)
{
diff --git a/firmware/drivers/i2c-pp5020.c b/firmware/drivers/i2c-pp5020.c
index 232de9c..8b48375 100644
--- a/firmware/drivers/i2c-pp5020.c
+++ b/firmware/drivers/i2c-pp5020.c
@@ -63,7 +63,6 @@ static int ipod_i2c_wait_not_busy(void)
return -1;
}
-
static int ipod_i2c_read_byte(unsigned int addr, unsigned int *data)
{
if (ipod_i2c_wait_not_busy() < 0)
@@ -72,6 +71,7 @@ static int ipod_i2c_read_byte(unsigned int addr, unsigned int *data)
}
{
+ unsigned int byte;
int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
/* clear top 15 bits, left shift 1, or in 0x1 for a read */
@@ -81,15 +81,18 @@ static int ipod_i2c_read_byte(unsigned int addr, unsigned int *data)
outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL);
- if (data)
+ set_irq_level(old_irq_level);
+ if (ipod_i2c_wait_not_busy() < 0)
{
- if (ipod_i2c_wait_not_busy() < 0)
- {
- set_irq_level(old_irq_level);
- return -1;
- }
- *data = inb(IPOD_I2C_DATA0);
+ return -1;
}
+ old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
+
+ byte = inb(IPOD_I2C_DATA0);
+
+ if (data)
+ *data = byte;
+
set_irq_level(old_irq_level);
}
@@ -148,6 +151,19 @@ static int ipod_i2c_send_byte(unsigned int addr, int data0)
/* Public functions */
static struct mutex i2c_mutex;
+int i2c_readbytes(unsigned int dev_addr, int addr, int len, unsigned char *data) {
+ unsigned int temp;
+ int i;
+ mutex_lock(&i2c_mutex);
+ ipod_i2c_send_byte(dev_addr, addr);
+ for (i = 0; i < len; i++) {
+ ipod_i2c_read_byte(dev_addr, &temp);
+ data[i] = temp;
+ }
+ mutex_unlock(&i2c_mutex);
+ return i;
+}
+
int i2c_readbyte(unsigned int dev_addr, int addr)
{
int data;
diff --git a/firmware/drivers/pcf50605.c b/firmware/drivers/pcf50605.c
index c8ea4a4..a8c61b1 100644
--- a/firmware/drivers/pcf50605.c
+++ b/firmware/drivers/pcf50605.c
@@ -23,6 +23,7 @@
* KIND, either express or implied.
*
****************************************************************************/
+#include "system.h"
#include "config.h"
#if CONFIG_I2C == I2C_PP5020
#include "i2c-pp5020.h"
@@ -72,15 +73,8 @@ int pcf50605_read(int address)
int pcf50605_read_multiple(int address, unsigned char* buf, int count)
{
- int i;
-
- for (i=0;i<count;i++)
- {
- buf[i]=pcf50605_read(address);
- address++;
- }
-
- return 0;
+ int read = i2c_readbytes(0x08, address, count, buf);
+ return read - count;
}
int pcf50605_write(int address, unsigned char val)
diff --git a/firmware/drivers/rtc.c b/firmware/drivers/rtc.c
index 4b4b458..6015f46 100644
--- a/firmware/drivers/rtc.c
+++ b/firmware/drivers/rtc.c
@@ -34,12 +34,12 @@
void rtc_init(void)
{
}
+
int rtc_read_datetime(unsigned char* buf)
{
return pcf50605_read_multiple(0x0a, buf, 7);
}
-
int rtc_write_datetime(unsigned char* buf)
{
int i;
diff --git a/firmware/export/i2c-pp5002.h b/firmware/export/i2c-pp5002.h
index 11e8499..18f8c34 100644
--- a/firmware/export/i2c-pp5002.h
+++ b/firmware/export/i2c-pp5002.h
@@ -30,5 +30,6 @@
void i2c_init(void);
int i2c_readbyte(unsigned int dev_addr, int addr);
int ipod_i2c_send(unsigned int addr, int data0, int data1);
+int i2c_readbytes(unsigned int dev_addr, int addr, int len, unsigned char *data);
#endif
diff --git a/firmware/export/i2c-pp5020.h b/firmware/export/i2c-pp5020.h
index c0dc969..34f16ec 100644
--- a/firmware/export/i2c-pp5020.h
+++ b/firmware/export/i2c-pp5020.h
@@ -30,5 +30,6 @@
void i2c_init(void);
int i2c_readbyte(unsigned int dev_addr, int addr);
int ipod_i2c_send(unsigned int addr, int data0, int data1);
+int i2c_readbytes(unsigned int dev_addr, int addr, int len, unsigned char *data);
#endif