diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2008-05-25 01:38:08 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2008-05-25 01:38:08 +0000 |
commit | d892214d88ed00344516a9b2f1a127c033d4618f (patch) | |
tree | 6558e0e53d770a5984f7b775945a09ff948c1c7d | |
parent | 11a667b6ca68e9e9e1025319cd5bdffd02e3a841 (diff) |
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
-rw-r--r-- | apps/debug_menu.c | 14 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/adc-target.h | 2 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/powermgmt-imx31.c | 67 |
3 files changed, 82 insertions, 1 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 313a2aacac..22b1777a68 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -18,6 +18,7 @@ ****************************************************************************/ #include "config.h" +#include <stdlib.h> #include <stdio.h> #include <stdbool.h> #include <string.h> @@ -1649,7 +1650,18 @@ static bool view_battery(void) snprintf(buf, 30, "Charger: %s", charger_inserted() ? "present" : "absent"); lcd_puts(0, 3, buf); -#endif +#if defined TOSHIBA_GIGABEAT_S + y = battery_adc_charge_current(); + x = y < 0 ? '-' : ' '; + y = abs(y); + snprintf(buf, 30, "I Charge:%c%d.%03d A", (char)x, y / 1000, y % 1000); + lcd_puts(0, 4, buf); + + y = battery_adc_temp(); + snprintf(buf, 30, "T Battery: %dC (%dF)", y, (9*y + 160) / 5); + lcd_puts(0, 5, buf); +#endif /* defined TOSHIBA_GIGABEAT_S */ +#endif /* defined IPOD_NANO || defined IPOD_VIDEO */ #endif /* CONFIG_CHARGING != CHARGING_CONTROL */ #endif /* CONFIG_CHARGING */ break; 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; +} |