From d892214d88ed00344516a9b2f1a127c033d4618f Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Sun, 25 May 2008 01:38:08 +0000 Subject: Gigabeat S: Add charge current and battery temp readout in power management and display in the battery screen. Thermistor data was obtained experimentally from one pulled off a dead board and appears basically correct when read back on a working device (which requires letting it settle to ambient temperature - a long wait so not easy to do). Sending me more thermistors would help improve accuracy *fingers crossed that it's close enough*. :-) This commit does NOT add charging but is a step towards implementing it. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17626 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/imx31/gigabeat-s/adc-target.h | 2 + .../target/arm/imx31/gigabeat-s/powermgmt-imx31.c | 67 ++++++++++++++++++++++ 2 files changed, 69 insertions(+) (limited to 'firmware/target') diff --git a/firmware/target/arm/imx31/gigabeat-s/adc-target.h b/firmware/target/arm/imx31/gigabeat-s/adc-target.h index 0b74ad84eb..d5f60de3db 100644 --- a/firmware/target/arm/imx31/gigabeat-s/adc-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/adc-target.h @@ -45,5 +45,7 @@ #define ADC_READ_ERROR 0xFFFF void adc_done(void); +int battery_adc_charge_current(void); +unsigned int battery_adc_temp(void); #endif diff --git a/firmware/target/arm/imx31/gigabeat-s/powermgmt-imx31.c b/firmware/target/arm/imx31/gigabeat-s/powermgmt-imx31.c index 53996f8cd7..711bc0dc58 100644 --- a/firmware/target/arm/imx31/gigabeat-s/powermgmt-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/powermgmt-imx31.c @@ -24,6 +24,37 @@ #include "adc.h" #include "powermgmt.h" +/** + * Fixed-point natural log + * taken from http://www.quinapalus.com/efunc.html + * "The code assumes integers are at least 32 bits long. The (positive) + * argument and the result of the function are both expressed as fixed-point + * values with 16 fractional bits, although intermediates are kept with 28 + * bits of precision to avoid loss of accuracy during shifts." + */ +static long flog(int x) +{ + long t,y; + + y=0xa65af; + if(x<0x00008000) x<<=16, y-=0xb1721; + if(x<0x00800000) x<<= 8, y-=0x58b91; + if(x<0x08000000) x<<= 4, y-=0x2c5c8; + if(x<0x20000000) x<<= 2, y-=0x162e4; + if(x<0x40000000) x<<= 1, y-=0x0b172; + t=x+(x>>1); if((t&0x80000000)==0) x=t,y-=0x067cd; + t=x+(x>>2); if((t&0x80000000)==0) x=t,y-=0x03920; + t=x+(x>>3); if((t&0x80000000)==0) x=t,y-=0x01e27; + t=x+(x>>4); if((t&0x80000000)==0) x=t,y-=0x00f85; + t=x+(x>>5); if((t&0x80000000)==0) x=t,y-=0x007e1; + t=x+(x>>6); if((t&0x80000000)==0) x=t,y-=0x003f8; + t=x+(x>>7); if((t&0x80000000)==0) x=t,y-=0x001fe; + x=0x80000000-x; + y-=x>>15; + return y; +} + + const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = { 3450 @@ -55,3 +86,39 @@ unsigned int battery_adc_voltage(void) return ((adc_read(ADC_BATTERY) * 2303) >> 10) + 2400; } +/* Returns battery charge current from ADC [milliamps] */ +int battery_adc_charge_current(void) +{ + /* Positive reading = charger to battery + * Negative reading = battery to charger terminal + * ADC reading -512-511 = -2875mA-2875mA */ + unsigned int value = adc_read(ADC_CHARGER_CURRENT); + return (((int)value << 22) >> 22) * 2881 >> 9; +} + +/* Returns battery temperature from ADC [deg-C] */ +unsigned int battery_adc_temp(void) +{ + unsigned int value = adc_read(ADC_BATTERY_TEMP); + /* E[volts] = value * 2.3V / 1023 + * R[ohms] = E/I = E[volts] / 0.00002[A] (Thermistor bias current source) + * + * Steinhart-Hart thermistor equation (sans "C*ln^2(R)" term because it + * has negligible effect): + * [A + B*ln(R) + D*ln^3(R)] - 273.15 = 1 / T[°K] + * + * Coeffients that fit experimental data (one thermistor so far, one run): + * A = 0.0013002631685462800 + * B = 0.0002000841932612330 + * D = 0.0000000640446750919 + * + * Fixed-point output matches the floating-point version for each ADC + * value. + */ + int R = 2070000 * value; + long long ln = flog(R) + 83196; + long long t0 = 425890304133ll; + long long t1 = 1000000*ln; + long long t3 = ln*ln*ln / 13418057; + return ((32754211579494400ll / (t0 + t1 + t3)) - 27315) / 100; +} -- cgit v1.2.3