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
This commit is contained in:
parent
5ecac908a2
commit
19f4c2a093
8 changed files with 79 additions and 59 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
if (adc->timeout < current_tick) {
|
||||
unsigned char data[2];
|
||||
unsigned short value;
|
||||
/* 5x per 2 seconds */
|
||||
adc->timeout = current_tick + (HZ * 2 / 5);
|
||||
|
||||
/* ADCC1, 8 bit, start */
|
||||
pcf50605_write(0x2f, 0x80 | (adc->channelnum << 1) | 0x1);
|
||||
data = pcf50605_read(0x30); /* ADCS1 */
|
||||
/* 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) {
|
||||
data = adc->conversion(data);
|
||||
}
|
||||
adc->data = data;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* Force an ADC scan _now_ */
|
||||
unsigned short adc_scan(int channel) {
|
||||
return _adc_scan(&adcdata[channel]);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (adc->conversion) {
|
||||
adc->conversion(&value);
|
||||
}
|
||||
adc->data = value;
|
||||
return value;
|
||||
} else {
|
||||
return adc->data;
|
||||
}
|
||||
}
|
||||
|
||||
/* Force an ADC scan _now_ */
|
||||
unsigned short adc_scan(int channel) {
|
||||
struct adc_struct *adc = &adcdata[channel];
|
||||
adc->timeout = 0;
|
||||
return _adc_read(adc);
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue