diff options
| author | Brandon Low <lostlogic@rockbox.org> | 2006-03-05 18:06:06 +0000 |
|---|---|---|
| committer | Brandon Low <lostlogic@rockbox.org> | 2006-03-05 18:06:06 +0000 |
| commit | 63c0d1dd9c22658b12a48dfc2015bfb0bf1239a4 (patch) | |
| tree | 6d940115b5d19c1c5a533bd6139c39bdd2a0916c | |
| parent | 4594ad460592ef56f2f1cdc5de132152257dfd5a (diff) | |
| download | rockbox-63c0d1dd9c22658b12a48dfc2015bfb0bf1239a4.zip rockbox-63c0d1dd9c22658b12a48dfc2015bfb0bf1239a4.tar.gz rockbox-63c0d1dd9c22658b12a48dfc2015bfb0bf1239a4.tar.bz2 rockbox-63c0d1dd9c22658b12a48dfc2015bfb0bf1239a4.tar.xz | |
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
| -rw-r--r-- | apps/screens.c | 7 | ||||
| -rw-r--r-- | firmware/SOURCES | 2 | ||||
| -rw-r--r-- | firmware/drivers/adc.c | 42 | ||||
| -rw-r--r-- | firmware/drivers/i2c-pp5020.c | 1 | ||||
| -rw-r--r-- | firmware/drivers/pcf50605.c | 46 | ||||
| -rw-r--r-- | firmware/drivers/power.c | 3 | ||||
| -rw-r--r-- | firmware/drivers/rtc.c | 50 | ||||
| -rw-r--r-- | firmware/drivers/wm8758.c | 22 | ||||
| -rw-r--r-- | firmware/export/adc.h | 8 | ||||
| -rw-r--r-- | firmware/export/config-ipodvideo.h | 4 | ||||
| -rw-r--r-- | firmware/export/pcf50605.h | 5 |
11 files changed, 124 insertions, 66 deletions
diff --git a/apps/screens.c b/apps/screens.c index 634d5cf..d01d2ac 100644 --- a/apps/screens.c +++ b/apps/screens.c @@ -300,6 +300,11 @@ void charging_display_info(bool animate) 2 if Off/Stop key was pressed 3 if On key was pressed 4 if USB was connected */ +#if (CONFIG_KEYPAD==IPOD_3G_PAD) || (CONFIG_KEYPAD==IPOD_4G_PAD) +# define CHARGE_SCREEN_RESUME BUTTON_SELECT +#else +# define CHARGE_SCREEN_RESUME BUTTON_ON +#endif int charging_screen(void) { unsigned int button; @@ -325,7 +330,7 @@ int charging_screen(void) gui_syncstatusbar_draw(&statusbars, false); charging_display_info(true); button = button_get_w_tmo(HZ/3); - if (button == BUTTON_ON) + if (button == CHARGE_SCREEN_RESUME) rc = 2; else if (usb_detect()) rc = 3; diff --git a/firmware/SOURCES b/firmware/SOURCES index 7ebfba3..f09c7d1 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 6e1c577..1755faf 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 9f26d3b..522ddbe 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 122ba6e..7d2036e 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 c6d49f5..9f3a10c 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 0e6d68e..6458092 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 aec6f3b..7c9ac77 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 454c102..b0a83d9 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 2bf0396..1fa778d 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 95fcaff..4ea1379 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 |