diff options
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s')
-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 |
2 files changed, 69 insertions, 0 deletions
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 @@ | |||
45 | #define ADC_READ_ERROR 0xFFFF | 45 | #define ADC_READ_ERROR 0xFFFF |
46 | 46 | ||
47 | void adc_done(void); | 47 | void adc_done(void); |
48 | int battery_adc_charge_current(void); | ||
49 | unsigned int battery_adc_temp(void); | ||
48 | 50 | ||
49 | #endif | 51 | #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 @@ | |||
24 | #include "adc.h" | 24 | #include "adc.h" |
25 | #include "powermgmt.h" | 25 | #include "powermgmt.h" |
26 | 26 | ||
27 | /** | ||
28 | * Fixed-point natural log | ||
29 | * taken from http://www.quinapalus.com/efunc.html | ||
30 | * "The code assumes integers are at least 32 bits long. The (positive) | ||
31 | * argument and the result of the function are both expressed as fixed-point | ||
32 | * values with 16 fractional bits, although intermediates are kept with 28 | ||
33 | * bits of precision to avoid loss of accuracy during shifts." | ||
34 | */ | ||
35 | static long flog(int x) | ||
36 | { | ||
37 | long t,y; | ||
38 | |||
39 | y=0xa65af; | ||
40 | if(x<0x00008000) x<<=16, y-=0xb1721; | ||
41 | if(x<0x00800000) x<<= 8, y-=0x58b91; | ||
42 | if(x<0x08000000) x<<= 4, y-=0x2c5c8; | ||
43 | if(x<0x20000000) x<<= 2, y-=0x162e4; | ||
44 | if(x<0x40000000) x<<= 1, y-=0x0b172; | ||
45 | t=x+(x>>1); if((t&0x80000000)==0) x=t,y-=0x067cd; | ||
46 | t=x+(x>>2); if((t&0x80000000)==0) x=t,y-=0x03920; | ||
47 | t=x+(x>>3); if((t&0x80000000)==0) x=t,y-=0x01e27; | ||
48 | t=x+(x>>4); if((t&0x80000000)==0) x=t,y-=0x00f85; | ||
49 | t=x+(x>>5); if((t&0x80000000)==0) x=t,y-=0x007e1; | ||
50 | t=x+(x>>6); if((t&0x80000000)==0) x=t,y-=0x003f8; | ||
51 | t=x+(x>>7); if((t&0x80000000)==0) x=t,y-=0x001fe; | ||
52 | x=0x80000000-x; | ||
53 | y-=x>>15; | ||
54 | return y; | ||
55 | } | ||
56 | |||
57 | |||
27 | const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = | 58 | const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = |
28 | { | 59 | { |
29 | 3450 | 60 | 3450 |
@@ -55,3 +86,39 @@ unsigned int battery_adc_voltage(void) | |||
55 | return ((adc_read(ADC_BATTERY) * 2303) >> 10) + 2400; | 86 | return ((adc_read(ADC_BATTERY) * 2303) >> 10) + 2400; |
56 | } | 87 | } |
57 | 88 | ||
89 | /* Returns battery charge current from ADC [milliamps] */ | ||
90 | int battery_adc_charge_current(void) | ||
91 | { | ||
92 | /* Positive reading = charger to battery | ||
93 | * Negative reading = battery to charger terminal | ||
94 | * ADC reading -512-511 = -2875mA-2875mA */ | ||
95 | unsigned int value = adc_read(ADC_CHARGER_CURRENT); | ||
96 | return (((int)value << 22) >> 22) * 2881 >> 9; | ||
97 | } | ||
98 | |||
99 | /* Returns battery temperature from ADC [deg-C] */ | ||
100 | unsigned int battery_adc_temp(void) | ||
101 | { | ||
102 | unsigned int value = adc_read(ADC_BATTERY_TEMP); | ||
103 | /* E[volts] = value * 2.3V / 1023 | ||
104 | * R[ohms] = E/I = E[volts] / 0.00002[A] (Thermistor bias current source) | ||
105 | * | ||
106 | * Steinhart-Hart thermistor equation (sans "C*ln^2(R)" term because it | ||
107 | * has negligible effect): | ||
108 | * [A + B*ln(R) + D*ln^3(R)] - 273.15 = 1 / T[°K] | ||
109 | * | ||
110 | * Coeffients that fit experimental data (one thermistor so far, one run): | ||
111 | * A = 0.0013002631685462800 | ||
112 | * B = 0.0002000841932612330 | ||
113 | * D = 0.0000000640446750919 | ||
114 | * | ||
115 | * Fixed-point output matches the floating-point version for each ADC | ||
116 | * value. | ||
117 | */ | ||
118 | int R = 2070000 * value; | ||
119 | long long ln = flog(R) + 83196; | ||
120 | long long t0 = 425890304133ll; | ||
121 | long long t1 = 1000000*ln; | ||
122 | long long t3 = ln*ln*ln / 13418057; | ||
123 | return ((32754211579494400ll / (t0 + t1 + t3)) - 27315) / 100; | ||
124 | } | ||