diff options
author | Brandon Low <lostlogic@rockbox.org> | 2006-03-09 19:47:12 +0000 |
---|---|---|
committer | Brandon Low <lostlogic@rockbox.org> | 2006-03-09 19:47:12 +0000 |
commit | 19f4c2a093698940482aad6df0bd8478a82f2a9d (patch) | |
tree | 66de55749bcaaf45d95b828423ffca8c715b7112 | |
parent | 5ecac908a2738e7a83dc0227daef3aaf16787dbc (diff) | |
download | rockbox-19f4c2a093698940482aad6df0bd8478a82f2a9d.tar.gz rockbox-19f4c2a093698940482aad6df0bd8478a82f2a9d.zip |
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.c | 9 | ||||
-rw-r--r-- | firmware/drivers/adc.c | 67 | ||||
-rw-r--r-- | firmware/drivers/i2c-pp5002.c | 10 | ||||
-rw-r--r-- | firmware/drivers/i2c-pp5020.c | 32 | ||||
-rw-r--r-- | firmware/drivers/pcf50605.c | 12 | ||||
-rw-r--r-- | firmware/drivers/rtc.c | 2 | ||||
-rw-r--r-- | firmware/export/i2c-pp5002.h | 1 | ||||
-rw-r--r-- | firmware/export/i2c-pp5020.h | 1 |
8 files changed, 77 insertions, 57 deletions
diff --git a/firmware/common/timefuncs.c b/firmware/common/timefuncs.c index 275fc6c782..5cf1a35a77 100644 --- a/firmware/common/timefuncs.c +++ b/firmware/common/timefuncs.c | |||
@@ -47,12 +47,13 @@ struct tm *get_time(void) | |||
47 | { | 47 | { |
48 | #ifndef SIMULATOR | 48 | #ifndef SIMULATOR |
49 | #ifdef CONFIG_RTC | 49 | #ifdef CONFIG_RTC |
50 | static long last_tick = 0; | 50 | static long timeout = 0; |
51 | 51 | ||
52 | /* Don't read the RTC more than 4 times per second */ | 52 | /* Don't read the RTC more than once per second */ |
53 | if (last_tick + HZ < current_tick) { | 53 | if (current_tick > timeout) { |
54 | char rtcbuf[7]; | 54 | char rtcbuf[7]; |
55 | last_tick = HZ * (current_tick / HZ); | 55 | /* Once per second, 1/10th of a second off */ |
56 | timeout = HZ * (current_tick / HZ + 1) + HZ / 5; | ||
56 | rtc_read_datetime(rtcbuf); | 57 | rtc_read_datetime(rtcbuf); |
57 | 58 | ||
58 | tm.tm_sec = ((rtcbuf[0] & 0x70) >> 4) * 10 + (rtcbuf[0] & 0x0f); | 59 | tm.tm_sec = ((rtcbuf[0] & 0x70) >> 4) * 10 + (rtcbuf[0] & 0x0f); |
diff --git a/firmware/drivers/adc.c b/firmware/drivers/adc.c index a75f788417..4a99a49753 100644 --- a/firmware/drivers/adc.c +++ b/firmware/drivers/adc.c | |||
@@ -286,60 +286,57 @@ void adc_init(void) | |||
286 | #elif CONFIG_CPU == PP5020 || (CONFIG_CPU == PP5002) | 286 | #elif CONFIG_CPU == PP5020 || (CONFIG_CPU == PP5002) |
287 | 287 | ||
288 | struct adc_struct { | 288 | struct adc_struct { |
289 | long last_read; | 289 | long timeout; |
290 | unsigned short (*conversion)(unsigned short data); | 290 | void (*conversion)(unsigned short *data); |
291 | short channelnum; | 291 | short channelnum; |
292 | unsigned short data; | 292 | unsigned short data; |
293 | }; | 293 | }; |
294 | 294 | ||
295 | static struct adc_struct adcdata[NUM_ADC_CHANNELS] IDATA_ATTR; | 295 | static struct adc_struct adcdata[NUM_ADC_CHANNELS] IDATA_ATTR; |
296 | 296 | ||
297 | /* This takes 10 bit ADC data from the subtractor circuit and scales it to | 297 | static unsigned short _adc_read(struct adc_struct *adc) |
298 | * a 13 bit value corresponding to 0-5.4v, the resulting range is 13FB-17FA, | ||
299 | * representing 3.1-5.4v */ | ||
300 | static unsigned short ten_bit_subtractor(unsigned short data) { | ||
301 | return (data<<2)+0x4FB; | ||
302 | } | ||
303 | |||
304 | static unsigned short _adc_scan(struct adc_struct *adc) | ||
305 | { | 298 | { |
306 | unsigned short data; | 299 | if (adc->timeout < current_tick) { |
307 | 300 | unsigned char data[2]; | |
308 | /* ADCC1, 8 bit, start */ | 301 | unsigned short value; |
309 | pcf50605_write(0x2f, 0x80 | (adc->channelnum << 1) | 0x1); | 302 | /* 5x per 2 seconds */ |
310 | data = pcf50605_read(0x30); /* ADCS1 */ | 303 | adc->timeout = current_tick + (HZ * 2 / 5); |
311 | 304 | ||
312 | if (adc->conversion) { | 305 | /* ADCC1, 10 bit, start */ |
313 | data = adc->conversion(data); | 306 | pcf50605_write(0x2f, (adc->channelnum << 1) | 0x1); |
307 | pcf50605_read_multiple(0x30, data, 2); /* ADCS1, ADCS2 */ | ||
308 | value = data[0]; | ||
309 | value <<= 2; | ||
310 | value |= data[1] & 0x3; | ||
311 | |||
312 | if (adc->conversion) { | ||
313 | adc->conversion(&value); | ||
314 | } | ||
315 | adc->data = value; | ||
316 | return value; | ||
317 | } else { | ||
318 | return adc->data; | ||
314 | } | 319 | } |
315 | adc->data = data; | ||
316 | return data; | ||
317 | } | 320 | } |
318 | 321 | ||
319 | /* Force an ADC scan _now_ */ | 322 | /* Force an ADC scan _now_ */ |
320 | unsigned short adc_scan(int channel) { | 323 | unsigned short adc_scan(int channel) { |
321 | return _adc_scan(&adcdata[channel]); | 324 | struct adc_struct *adc = &adcdata[channel]; |
325 | adc->timeout = 0; | ||
326 | return _adc_read(adc); | ||
322 | } | 327 | } |
323 | 328 | ||
324 | /* Retrieve the ADC value, only does a scan once per second or less */ | 329 | /* Retrieve the ADC value, only does a scan periodically */ |
325 | unsigned short adc_read(int channel) | 330 | unsigned short adc_read(int channel) { |
326 | { | 331 | return _adc_read(&adcdata[channel]); |
327 | struct adc_struct *adc = &adcdata[channel]; | ||
328 | if (adc->last_read + HZ < current_tick) { | ||
329 | adc->last_read = current_tick; | ||
330 | return _adc_scan(adc); | ||
331 | } else { | ||
332 | return adc->data; | ||
333 | } | ||
334 | } | 332 | } |
335 | 333 | ||
336 | void adc_init(void) | 334 | void adc_init(void) |
337 | { | 335 | { |
338 | struct adc_struct *adc_battery = &adcdata[ADC_BATTERY]; | 336 | struct adc_struct *adc_battery = &adcdata[ADC_BATTERY]; |
339 | adc_battery->channelnum = 0x3; /* ADCVIN1, subtractor */ | 337 | adc_battery->channelnum = 0x2; /* ADCVIN1, resistive divider */ |
340 | adc_battery->conversion = ten_bit_subtractor; | 338 | adc_battery->timeout = 0; |
341 | adc_battery->last_read = current_tick; | 339 | _adc_read(adc_battery); |
342 | _adc_scan(adc_battery); | ||
343 | } | 340 | } |
344 | 341 | ||
345 | #elif CONFIG_CPU == PNX0101 | 342 | #elif CONFIG_CPU == PNX0101 |
diff --git a/firmware/drivers/i2c-pp5002.c b/firmware/drivers/i2c-pp5002.c index dc26d8a5d9..958ddeebe4 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) | |||
136 | return ipod_i2c_send_bytes(addr, 1, data); | 136 | return ipod_i2c_send_bytes(addr, 1, data); |
137 | } | 137 | } |
138 | 138 | ||
139 | int i2c_readbytes(unsigned int dev_addr, int addr, int len, unsigned char *data) { | ||
140 | unsigned int temp; | ||
141 | int i; | ||
142 | ipod_i2c_send_byte(dev_addr, addr); | ||
143 | for (i = 0; i < len; i++) { | ||
144 | ipod_i2c_read_byte(dev_addr, &temp); | ||
145 | data[i] = temp; | ||
146 | } | ||
147 | return i; | ||
148 | } | ||
139 | 149 | ||
140 | int i2c_readbyte(unsigned int dev_addr, int addr) | 150 | int i2c_readbyte(unsigned int dev_addr, int addr) |
141 | { | 151 | { |
diff --git a/firmware/drivers/i2c-pp5020.c b/firmware/drivers/i2c-pp5020.c index 232de9cb5a..8b48375e3d 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) | |||
63 | return -1; | 63 | return -1; |
64 | } | 64 | } |
65 | 65 | ||
66 | |||
67 | static int ipod_i2c_read_byte(unsigned int addr, unsigned int *data) | 66 | static int ipod_i2c_read_byte(unsigned int addr, unsigned int *data) |
68 | { | 67 | { |
69 | if (ipod_i2c_wait_not_busy() < 0) | 68 | if (ipod_i2c_wait_not_busy() < 0) |
@@ -72,6 +71,7 @@ static int ipod_i2c_read_byte(unsigned int addr, unsigned int *data) | |||
72 | } | 71 | } |
73 | 72 | ||
74 | { | 73 | { |
74 | unsigned int byte; | ||
75 | int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL); | 75 | int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL); |
76 | 76 | ||
77 | /* clear top 15 bits, left shift 1, or in 0x1 for a read */ | 77 | /* 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) | |||
81 | 81 | ||
82 | outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); | 82 | outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); |
83 | 83 | ||
84 | if (data) | 84 | set_irq_level(old_irq_level); |
85 | if (ipod_i2c_wait_not_busy() < 0) | ||
85 | { | 86 | { |
86 | if (ipod_i2c_wait_not_busy() < 0) | 87 | return -1; |
87 | { | ||
88 | set_irq_level(old_irq_level); | ||
89 | return -1; | ||
90 | } | ||
91 | *data = inb(IPOD_I2C_DATA0); | ||
92 | } | 88 | } |
89 | old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL); | ||
90 | |||
91 | byte = inb(IPOD_I2C_DATA0); | ||
92 | |||
93 | if (data) | ||
94 | *data = byte; | ||
95 | |||
93 | set_irq_level(old_irq_level); | 96 | set_irq_level(old_irq_level); |
94 | } | 97 | } |
95 | 98 | ||
@@ -148,6 +151,19 @@ static int ipod_i2c_send_byte(unsigned int addr, int data0) | |||
148 | /* Public functions */ | 151 | /* Public functions */ |
149 | static struct mutex i2c_mutex; | 152 | static struct mutex i2c_mutex; |
150 | 153 | ||
154 | int i2c_readbytes(unsigned int dev_addr, int addr, int len, unsigned char *data) { | ||
155 | unsigned int temp; | ||
156 | int i; | ||
157 | mutex_lock(&i2c_mutex); | ||
158 | ipod_i2c_send_byte(dev_addr, addr); | ||
159 | for (i = 0; i < len; i++) { | ||
160 | ipod_i2c_read_byte(dev_addr, &temp); | ||
161 | data[i] = temp; | ||
162 | } | ||
163 | mutex_unlock(&i2c_mutex); | ||
164 | return i; | ||
165 | } | ||
166 | |||
151 | int i2c_readbyte(unsigned int dev_addr, int addr) | 167 | int i2c_readbyte(unsigned int dev_addr, int addr) |
152 | { | 168 | { |
153 | int data; | 169 | int data; |
diff --git a/firmware/drivers/pcf50605.c b/firmware/drivers/pcf50605.c index c8ea4a499f..a8c61b1789 100644 --- a/firmware/drivers/pcf50605.c +++ b/firmware/drivers/pcf50605.c | |||
@@ -23,6 +23,7 @@ | |||
23 | * KIND, either express or implied. | 23 | * KIND, either express or implied. |
24 | * | 24 | * |
25 | ****************************************************************************/ | 25 | ****************************************************************************/ |
26 | #include "system.h" | ||
26 | #include "config.h" | 27 | #include "config.h" |
27 | #if CONFIG_I2C == I2C_PP5020 | 28 | #if CONFIG_I2C == I2C_PP5020 |
28 | #include "i2c-pp5020.h" | 29 | #include "i2c-pp5020.h" |
@@ -72,15 +73,8 @@ int pcf50605_read(int address) | |||
72 | 73 | ||
73 | int pcf50605_read_multiple(int address, unsigned char* buf, int count) | 74 | int pcf50605_read_multiple(int address, unsigned char* buf, int count) |
74 | { | 75 | { |
75 | int i; | 76 | int read = i2c_readbytes(0x08, address, count, buf); |
76 | 77 | return read - count; | |
77 | for (i=0;i<count;i++) | ||
78 | { | ||
79 | buf[i]=pcf50605_read(address); | ||
80 | address++; | ||
81 | } | ||
82 | |||
83 | return 0; | ||
84 | } | 78 | } |
85 | 79 | ||
86 | int pcf50605_write(int address, unsigned char val) | 80 | int pcf50605_write(int address, unsigned char val) |
diff --git a/firmware/drivers/rtc.c b/firmware/drivers/rtc.c index 4b4b45826f..6015f46026 100644 --- a/firmware/drivers/rtc.c +++ b/firmware/drivers/rtc.c | |||
@@ -34,12 +34,12 @@ | |||
34 | void rtc_init(void) | 34 | void rtc_init(void) |
35 | { | 35 | { |
36 | } | 36 | } |
37 | |||
37 | int rtc_read_datetime(unsigned char* buf) | 38 | int rtc_read_datetime(unsigned char* buf) |
38 | { | 39 | { |
39 | return pcf50605_read_multiple(0x0a, buf, 7); | 40 | return pcf50605_read_multiple(0x0a, buf, 7); |
40 | } | 41 | } |
41 | 42 | ||
42 | |||
43 | int rtc_write_datetime(unsigned char* buf) | 43 | int rtc_write_datetime(unsigned char* buf) |
44 | { | 44 | { |
45 | int i; | 45 | int i; |
diff --git a/firmware/export/i2c-pp5002.h b/firmware/export/i2c-pp5002.h index 11e84996d4..18f8c3461d 100644 --- a/firmware/export/i2c-pp5002.h +++ b/firmware/export/i2c-pp5002.h | |||
@@ -30,5 +30,6 @@ | |||
30 | void i2c_init(void); | 30 | void i2c_init(void); |
31 | int i2c_readbyte(unsigned int dev_addr, int addr); | 31 | int i2c_readbyte(unsigned int dev_addr, int addr); |
32 | int ipod_i2c_send(unsigned int addr, int data0, int data1); | 32 | int ipod_i2c_send(unsigned int addr, int data0, int data1); |
33 | int i2c_readbytes(unsigned int dev_addr, int addr, int len, unsigned char *data); | ||
33 | 34 | ||
34 | #endif | 35 | #endif |
diff --git a/firmware/export/i2c-pp5020.h b/firmware/export/i2c-pp5020.h index c0dc969e8b..34f16ec12f 100644 --- a/firmware/export/i2c-pp5020.h +++ b/firmware/export/i2c-pp5020.h | |||
@@ -30,5 +30,6 @@ | |||
30 | void i2c_init(void); | 30 | void i2c_init(void); |
31 | int i2c_readbyte(unsigned int dev_addr, int addr); | 31 | int i2c_readbyte(unsigned int dev_addr, int addr); |
32 | int ipod_i2c_send(unsigned int addr, int data0, int data1); | 32 | int ipod_i2c_send(unsigned int addr, int data0, int data1); |
33 | int i2c_readbytes(unsigned int dev_addr, int addr, int len, unsigned char *data); | ||
33 | 34 | ||
34 | #endif | 35 | #endif |