diff options
author | Daniel Stenberg <daniel@haxx.se> | 2003-03-04 05:59:38 +0000 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2003-03-04 05:59:38 +0000 |
commit | 2573879fb13c1544ec0e07f6ce1da1d45f3d97a7 (patch) | |
tree | b5993581c3cf7e0bde10c90c57ea1017243be7e8 | |
parent | 975e240a0c1da0738b443b6964fb2150448754e3 (diff) | |
download | rockbox-2573879fb13c1544ec0e07f6ce1da1d45f3d97a7.tar.gz rockbox-2573879fb13c1544ec0e07f6ce1da1d45f3d97a7.zip |
Massively code-policed. We keep source lines less than 80 columns...
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3378 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/powermgmt.c | 349 |
1 files changed, 224 insertions, 125 deletions
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 2e08f0a6ff..c9df60fba3 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c | |||
@@ -63,24 +63,28 @@ void set_battery_capacity(int capacity) | |||
63 | } | 63 | } |
64 | #else /* not SIMULATOR */ | 64 | #else /* not SIMULATOR */ |
65 | 65 | ||
66 | int battery_capacity = 1500; /* only a default value */ | 66 | int battery_capacity = 1500; /* only a default value */ |
67 | int battery_level_cached = -1; /* battery level of this minute, updated once per minute */ | 67 | int battery_level_cached = -1; /* battery level of this minute, updated once |
68 | per minute */ | ||
68 | 69 | ||
69 | static int poweroff_idle_timeout_value[15] = | 70 | static int poweroff_idle_timeout_value[15] = |
70 | { | 71 | { |
71 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 30, 45, 60 | 72 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 30, 45, 60 |
72 | }; | 73 | }; |
73 | 74 | ||
74 | static int percent_to_volt_decharge[11] = /* voltages (centivolt) of 0%, 10%, ... 100% when charging disabled */ | 75 | static int percent_to_volt_decharge[11] = |
76 | /* voltages (centivolt) of 0%, 10%, ... 100% when charging disabled */ | ||
75 | { | 77 | { |
76 | #ifdef HAVE_LIION | 78 | #ifdef HAVE_LIION |
77 | /* values guessed, see http://www.seattlerobotics.org/encoder/200210/LiIon2.pdf */ | 79 | /* values guessed, see |
78 | /* until someone measures voltages over a decharging cycle */ | 80 | http://www.seattlerobotics.org/encoder/200210/LiIon2.pdf until someone |
81 | measures voltages over a decharging cycle */ | ||
79 | 260, 280, 300, 320, 340, 350, 360, 370, 380, 390, 400 | 82 | 260, 280, 300, 320, 340, 350, 360, 370, 380, 390, 400 |
80 | #else /* NiMH */ | 83 | #else /* NiMH */ |
81 | /* original values were taken directly after charging, */ | 84 | /* original values were taken directly after charging, but it should show |
82 | /* but it should show 100% after turning off the device for some hours, too */ | 85 | 100% after turning off the device for some hours, too */ |
83 | 450, 481, 491, 497, 503, 507, 512, 514, 517, 525, 540 /* orig. values: ...,528,560 */ | 86 | 450, 481, 491, 497, 503, 507, 512, 514, 517, 525, 540 /* orig. values: |
87 | ...,528,560 */ | ||
84 | #endif | 88 | #endif |
85 | }; | 89 | }; |
86 | 90 | ||
@@ -95,18 +99,29 @@ void set_battery_capacity(int capacity) | |||
95 | 99 | ||
96 | #ifdef HAVE_CHARGE_CTRL | 100 | #ifdef HAVE_CHARGE_CTRL |
97 | 101 | ||
98 | char power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in debug menu */ | 102 | char power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in |
99 | char charge_restart_level = CHARGE_RESTART_HI; /* level at which charging starts */ | 103 | debug menu */ |
100 | int powermgmt_last_cycle_startstop_min = 25; /* how many minutes ago was the charging started or stopped? */ | 104 | char charge_restart_level = CHARGE_RESTART_HI; /* level at which charging |
101 | int powermgmt_last_cycle_level = 0; /* which level had the batteries at this time? */ | 105 | starts */ |
106 | int powermgmt_last_cycle_startstop_min = 25; /* how many minutes ago was the | ||
107 | charging started or | ||
108 | stopped? */ | ||
109 | int powermgmt_last_cycle_level = 0; /* which level had the | ||
110 | batteries at this time? */ | ||
102 | bool trickle_charge_enabled = true; | 111 | bool trickle_charge_enabled = true; |
103 | int trickle_sec = 0; /* how many seconds should the charger be enabled per minute for trickle charging? */ | 112 | int trickle_sec = 0; /* how many seconds should the |
104 | int charge_state = 0; /* at the beginning, the charger does nothing */ | 113 | charger be enabled per |
105 | 114 | minute for trickle | |
106 | static int percent_to_volt_charge[11] = /* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */ | 115 | charging? */ |
116 | int charge_state = 0; /* at the beginning, the | ||
117 | charger does nothing */ | ||
118 | |||
119 | static int percent_to_volt_charge[11] = /* voltages (centivolt) of 0%, 10%, | ||
120 | ... 100% when charging enabled */ | ||
107 | { | 121 | { |
108 | /* values guessed, see http://www.seattlerobotics.org/encoder/200210/LiIon2.pdf */ | 122 | /* values guessed, see |
109 | /* until someone measures voltages over a charging cycle */ | 123 | http://www.seattlerobotics.org/encoder/200210/LiIon2.pdf until someone |
124 | measures voltages over a charging cycle */ | ||
110 | 476, 544, 551, 556, 561, 564, 566, 576, 582, 584, 585 /* NiMH */ | 125 | 476, 544, 551, 556, 561, 564, 566, 576, 582, 584, 585 /* NiMH */ |
111 | }; | 126 | }; |
112 | 127 | ||
@@ -133,23 +148,25 @@ int battery_time(void) | |||
133 | return powermgmt_est_runningtime_min; | 148 | return powermgmt_est_runningtime_min; |
134 | } | 149 | } |
135 | 150 | ||
136 | /* look into the percent_to_volt_* table and get a realistic battery level percentage */ | 151 | /* look into the percent_to_volt_* table and get a realistic battery level |
152 | percentage */ | ||
137 | int voltage_to_percent(int voltage, int* table) | 153 | int voltage_to_percent(int voltage, int* table) |
138 | { | 154 | { |
139 | if (voltage <= table[0]) | 155 | if (voltage <= table[0]) |
140 | return 0; | 156 | return 0; |
141 | else | 157 | else |
142 | if (voltage >= table[10]) | 158 | if (voltage >= table[10]) |
143 | return 100; | 159 | return 100; |
144 | else { | 160 | else { |
145 | /* search nearest value */ | 161 | /* search nearest value */ |
146 | int i = 0; | 162 | int i = 0; |
147 | while ((i < 10) && (table[i+1] < voltage)) | 163 | while ((i < 10) && (table[i+1] < voltage)) |
148 | i++; | 164 | i++; |
149 | /* interpolate linear between the smaller and greater value */ | 165 | /* interpolate linear between the smaller and greater value */ |
150 | return i * 10 /* 10th */ | 166 | return i * 10 /* 10th */ |
151 | + (voltage - table[i]) * 10 / (table[i+1] - table[i]); /* 1th */ | 167 | + (voltage - table[i]) * |
152 | } | 168 | 10 / (table[i+1] - table[i]); /* 1th */ |
169 | } | ||
153 | } | 170 | } |
154 | 171 | ||
155 | /* update battery level, called only once per minute */ | 172 | /* update battery level, called only once per minute */ |
@@ -180,28 +197,34 @@ void battery_level_update(void) | |||
180 | #ifdef HAVE_CHARGE_CTRL | 197 | #ifdef HAVE_CHARGE_CTRL |
181 | if (charge_state == 0) { /* decharge */ | 198 | if (charge_state == 0) { /* decharge */ |
182 | level = voltage_to_percent(level, percent_to_volt_decharge); | 199 | level = voltage_to_percent(level, percent_to_volt_decharge); |
183 | } else if (charge_state == 1) { /* charge */ | 200 | } |
184 | level = voltage_to_percent(level, percent_to_volt_charge); | 201 | else if (charge_state == 1) { /* charge */ |
185 | } else {/* in trickle charge, the battery is per definition 100% full */ | 202 | level = voltage_to_percent(level, percent_to_volt_charge); |
203 | } | ||
204 | else {/* in trickle charge, the battery is per definition 100% full */ | ||
186 | battery_level_cached = level = 100; | 205 | battery_level_cached = level = 100; |
187 | } | 206 | } |
188 | #else | 207 | #else |
189 | level = voltage_to_percent(level, percent_to_volt_decharge); /* always use the decharge table */ | 208 | level = voltage_to_percent(level, percent_to_volt_decharge); |
209 | /* always use the decharge table */ | ||
190 | #endif | 210 | #endif |
191 | 211 | ||
192 | if (battery_level_cached == -1) { /* first run of this procedure */ | 212 | if (battery_level_cached == -1) { /* first run of this procedure */ |
193 | /* the battery voltage is usually a little lower directly after turning on, because the disk was used heavily */ | 213 | /* the battery voltage is usually a little lower directly after |
194 | /* raise it by 5 % */ | 214 | turning on, because the disk was used heavily raise it by 5 % */ |
195 | battery_level_cached = (level > 95) ? 100 : level + 5; | 215 | battery_level_cached = (level > 95) ? 100 : level + 5; |
196 | } else { | 216 | } |
197 | /* the level is allowed to be +1/-1 of the last value when usb not connected */ | 217 | else { |
198 | /* and to be +1/-3 of the last value when usb is connected */ | 218 | /* the level is allowed to be +1/-1 of the last value when usb not |
219 | connected and to be +1/-3 of the last value when usb is | ||
220 | connected */ | ||
199 | if (level > battery_level_cached + 1) | 221 | if (level > battery_level_cached + 1) |
200 | level = battery_level_cached + 1; | 222 | level = battery_level_cached + 1; |
201 | if (usb_inserted()) { | 223 | if (usb_inserted()) { |
202 | if (level < battery_level_cached - 3) | 224 | if (level < battery_level_cached - 3) |
203 | level = battery_level_cached - 3; | 225 | level = battery_level_cached - 3; |
204 | } else { | 226 | } |
227 | else { | ||
205 | if (level < battery_level_cached - 1) | 228 | if (level < battery_level_cached - 1) |
206 | level = battery_level_cached - 1; | 229 | level = battery_level_cached - 1; |
207 | } | 230 | } |
@@ -222,7 +245,8 @@ bool battery_level_safe(void) | |||
222 | if (power_history[POWER_HISTORY_LEN-1]) | 245 | if (power_history[POWER_HISTORY_LEN-1]) |
223 | return power_history[POWER_HISTORY_LEN-1] > BATTERY_LEVEL_DANGEROUS; | 246 | return power_history[POWER_HISTORY_LEN-1] > BATTERY_LEVEL_DANGEROUS; |
224 | else | 247 | else |
225 | return adc_read(ADC_UNREG_POWER) > (BATTERY_LEVEL_DANGEROUS * 10000) / BATTERY_SCALE_FACTOR; | 248 | return adc_read(ADC_UNREG_POWER) > (BATTERY_LEVEL_DANGEROUS * 10000) / |
249 | BATTERY_SCALE_FACTOR; | ||
226 | } | 250 | } |
227 | 251 | ||
228 | void set_poweroff_timeout(int timeout) | 252 | void set_poweroff_timeout(int timeout) |
@@ -232,13 +256,11 @@ void set_poweroff_timeout(int timeout) | |||
232 | 256 | ||
233 | void set_sleep_timer(int seconds) | 257 | void set_sleep_timer(int seconds) |
234 | { | 258 | { |
235 | if(seconds) | 259 | if(seconds) { |
236 | { | ||
237 | sleeptimer_active = true; | 260 | sleeptimer_active = true; |
238 | sleeptimer_endtick = current_tick + seconds * HZ; | 261 | sleeptimer_endtick = current_tick + seconds * HZ; |
239 | } | 262 | } |
240 | else | 263 | else { |
241 | { | ||
242 | sleeptimer_active = false; | 264 | sleeptimer_active = false; |
243 | sleeptimer_endtick = 0; | 265 | sleeptimer_endtick = 0; |
244 | } | 266 | } |
@@ -324,7 +346,8 @@ static void power_thread(void) | |||
324 | #ifdef HAVE_CHARGE_CTRL | 346 | #ifdef HAVE_CHARGE_CTRL |
325 | int delta; | 347 | int delta; |
326 | int charged_time = 0; | 348 | int charged_time = 0; |
327 | int charge_max_time_now = 0; /* max. charging duration, calculated at beginning of charging */ | 349 | int charge_max_time_now = 0; /* max. charging duration, calculated at |
350 | beginning of charging */ | ||
328 | int charge_pause = 0; /* no charging pause at the beginning */ | 351 | int charge_pause = 0; /* no charging pause at the beginning */ |
329 | int trickle_time = 0; /* how many minutes trickle charging already? */ | 352 | int trickle_time = 0; /* how many minutes trickle charging already? */ |
330 | #endif | 353 | #endif |
@@ -360,9 +383,11 @@ static void power_thread(void) | |||
360 | power_history[i] = power_history[i+1]; | 383 | power_history[i] = power_history[i+1]; |
361 | 384 | ||
362 | /* insert new value in the end, in centivolts 8-) */ | 385 | /* insert new value in the end, in centivolts 8-) */ |
363 | power_history[POWER_HISTORY_LEN-1] = (avg * BATTERY_SCALE_FACTOR) / 10000; | 386 | power_history[POWER_HISTORY_LEN-1] = |
387 | (avg * BATTERY_SCALE_FACTOR) / 10000; | ||
364 | 388 | ||
365 | /* update battery level every minute, ignoring first 15 minutes after start charge/decharge */ | 389 | /* update battery level every minute, ignoring first 15 minutes after |
390 | start charge/decharge */ | ||
366 | #ifdef HAVE_CHARGE_CTRL | 391 | #ifdef HAVE_CHARGE_CTRL |
367 | if ((powermgmt_last_cycle_startstop_min > 25) || (charge_state > 1)) | 392 | if ((powermgmt_last_cycle_startstop_min > 25) || (charge_state > 1)) |
368 | #endif | 393 | #endif |
@@ -374,24 +399,30 @@ static void power_thread(void) | |||
374 | 399 | ||
375 | #ifdef HAVE_CHARGE_CTRL | 400 | #ifdef HAVE_CHARGE_CTRL |
376 | if (charge_state == 1) | 401 | if (charge_state == 1) |
377 | powermgmt_est_runningtime_min = (100 - battery_level()) * battery_capacity / 100 * 60 / CURRENT_CHARGING; | 402 | powermgmt_est_runningtime_min = (100 - battery_level()) * |
403 | battery_capacity / 100 * 60 / CURRENT_CHARGING; | ||
378 | else { | 404 | else { |
379 | current = usb_inserted() ? CURRENT_USB : CURRENT_NORMAL; | 405 | current = usb_inserted() ? CURRENT_USB : CURRENT_NORMAL; |
380 | if ((backlight_get_timeout() == 1) || (charger_inserted() && backlight_get_on_when_charging())) | 406 | if ((backlight_get_timeout() == 1) || |
381 | /* LED always on or LED on when charger connected */ | 407 | (charger_inserted() && backlight_get_on_when_charging())) |
408 | /* LED always on or LED on when charger connected */ | ||
382 | current += CURRENT_BACKLIGHT; | 409 | current += CURRENT_BACKLIGHT; |
383 | powermgmt_est_runningtime_min = battery_level() * battery_capacity / 100 * 60 / current; | 410 | powermgmt_est_runningtime_min = battery_level() * |
411 | battery_capacity / 100 * 60 / current; | ||
384 | #if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */ | 412 | #if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */ |
385 | powermgmt_est_runningtime_min = powermgmt_est_runningtime_min * 122 / 100; | 413 | powermgmt_est_runningtime_min = |
414 | powermgmt_est_runningtime_min * 122 / 100; | ||
386 | #endif /* MEM == 8 */ | 415 | #endif /* MEM == 8 */ |
387 | } | 416 | } |
388 | #else | 417 | #else |
389 | current = usb_inserted() ? CURRENT_USB : CURRENT_NORMAL; | 418 | current = usb_inserted() ? CURRENT_USB : CURRENT_NORMAL; |
390 | if (backlight_get_timeout() == 1) /* LED always on */ | 419 | if (backlight_get_timeout() == 1) /* LED always on */ |
391 | current += CURRENT_BACKLIGHT; | 420 | current += CURRENT_BACKLIGHT; |
392 | powermgmt_est_runningtime_min = battery_level() * battery_capacity / 100 * 60 / current; | 421 | powermgmt_est_runningtime_min = battery_level() * |
422 | battery_capacity / 100 * 60 / current; | ||
393 | #if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */ | 423 | #if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */ |
394 | powermgmt_est_runningtime_min = powermgmt_est_runningtime_min * 122 / 100; | 424 | powermgmt_est_runningtime_min = |
425 | powermgmt_est_runningtime_min * 122 / 100; | ||
395 | #endif /* MEM == 8 */ | 426 | #endif /* MEM == 8 */ |
396 | #endif /* HAVE_CHARGE_CONTROL */ | 427 | #endif /* HAVE_CHARGE_CONTROL */ |
397 | 428 | ||
@@ -404,89 +435,133 @@ static void power_thread(void) | |||
404 | if (charge_state == 1) { | 435 | if (charge_state == 1) { |
405 | /* charger inserted and enabled */ | 436 | /* charger inserted and enabled */ |
406 | charged_time++; | 437 | charged_time++; |
407 | snprintf(power_message, POWER_MESSAGE_LEN, "Chg %dm max %dm", charged_time, charge_max_time_now); | 438 | snprintf(power_message, POWER_MESSAGE_LEN, |
439 | "Chg %dm max %dm", charged_time, charge_max_time_now); | ||
408 | 440 | ||
409 | if (charged_time > charge_max_time_now) { | 441 | if (charged_time > charge_max_time_now) { |
410 | DEBUGF("power: charged_time > charge_max_time_now, enough!\n"); | 442 | DEBUGF("power: charged_time > charge_max_time_now, " |
411 | /* have charged too long and deltaV detection did not work! */ | 443 | "enough!\n"); |
444 | /* have charged too long and deltaV detection did not | ||
445 | work! */ | ||
412 | powermgmt_last_cycle_level = battery_level(); | 446 | powermgmt_last_cycle_level = battery_level(); |
413 | powermgmt_last_cycle_startstop_min = 0; | 447 | powermgmt_last_cycle_startstop_min = 0; |
414 | charger_enable(false); | 448 | charger_enable(false); |
415 | snprintf(power_message, POWER_MESSAGE_LEN, "Chg tmout %d min", charge_max_time_now); | 449 | snprintf(power_message, POWER_MESSAGE_LEN, |
416 | /* disable charging for several hours from this point, just to be sure */ | 450 | "Chg tmout %d min", charge_max_time_now); |
451 | /* disable charging for several hours from this point, | ||
452 | just to be sure */ | ||
417 | charge_pause = CHARGE_PAUSE_LEN; | 453 | charge_pause = CHARGE_PAUSE_LEN; |
418 | /* no trickle charge here, because the charging cycle didn't end the right way */ | 454 | /* no trickle charge here, because the charging cycle |
419 | charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ | 455 | didn't end the right way */ |
456 | charge_state = 0; /* 0: decharging/charger off, 1: charge, | ||
457 | 2: top-off, 3: trickle */ | ||
420 | } else { | 458 | } else { |
421 | if (charged_time > CHARGE_MIN_TIME) { | 459 | if (charged_time > CHARGE_MIN_TIME) { |
422 | /* have charged continuously over the minimum charging time, | 460 | /* have charged continuously over the minimum charging |
423 | * so we monitor for deltaV going negative. Multiply things | 461 | time, so we monitor for deltaV going |
424 | * by 100 to get more accuracy without floating point arithmetic. | 462 | negative. Multiply thingsby 100 to get more |
425 | * power_history[] contains centivolts so after multiplying by 100 | 463 | accuracy without floating point arithmetic. |
426 | * the deltas are in tenths of millivolts (delta of 5 is | 464 | power_history[] contains centivolts so after |
427 | * 0.0005 V). | 465 | multiplying by 100 the deltas are in tenths of |
466 | millivolts (delta of 5 is 0.0005 V). | ||
428 | */ | 467 | */ |
429 | delta = ( power_history[POWER_HISTORY_LEN-1] * 100 | 468 | delta = |
430 | + power_history[POWER_HISTORY_LEN-2] * 100 | 469 | ( power_history[POWER_HISTORY_LEN-1] * 100 |
431 | - power_history[POWER_HISTORY_LEN-1-CHARGE_END_NEGD+1] * 100 | 470 | + power_history[POWER_HISTORY_LEN-2] * 100 |
432 | - power_history[POWER_HISTORY_LEN-1-CHARGE_END_NEGD] * 100 ) | 471 | - power_history[POWER_HISTORY_LEN-1- |
433 | / CHARGE_END_NEGD / 2; | 472 | CHARGE_END_NEGD+1] * 100 |
473 | - power_history[POWER_HISTORY_LEN-1- | ||
474 | CHARGE_END_NEGD] * 100 ) | ||
475 | / CHARGE_END_NEGD / 2; | ||
434 | 476 | ||
435 | if (delta < -100) { /* delta < -10 mV */ | 477 | if (delta < -100) { /* delta < -10 mV */ |
436 | DEBUGF("power: short-term negative delta, enough!\n"); | 478 | DEBUGF("power: short-term negative" |
479 | " delta, enough!\n"); | ||
437 | powermgmt_last_cycle_level = battery_level(); | 480 | powermgmt_last_cycle_level = battery_level(); |
438 | powermgmt_last_cycle_startstop_min = 0; | 481 | powermgmt_last_cycle_startstop_min = 0; |
439 | charger_enable(false); | 482 | charger_enable(false); |
440 | snprintf(power_message, POWER_MESSAGE_LEN, "end negd %d %dmin", delta, charged_time); | 483 | snprintf(power_message, POWER_MESSAGE_LEN, |
441 | /* disable charging for several hours from this point, just to be sure */ | 484 | "end negd %d %dmin", delta, charged_time); |
485 | /* disable charging for several hours from this | ||
486 | point, just to be sure */ | ||
442 | charge_pause = CHARGE_PAUSE_LEN; | 487 | charge_pause = CHARGE_PAUSE_LEN; |
443 | /* enable trickle charging */ | 488 | /* enable trickle charging */ |
444 | if (trickle_charge_enabled) { | 489 | if (trickle_charge_enabled) { |
445 | trickle_sec = CURRENT_NORMAL * 60 / CURRENT_CHARGING; /* first guess, maybe consider if LED backlight is on, disk is active,... */ | 490 | trickle_sec = CURRENT_NORMAL * 60 / |
491 | CURRENT_CHARGING; | ||
492 | /* first guess, maybe consider if LED | ||
493 | backlight is on, disk is active,... */ | ||
446 | trickle_time = 0; | 494 | trickle_time = 0; |
447 | charge_state = 2; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ | 495 | charge_state = 2; /* 0: decharging/charger |
496 | off, 1: charge, | ||
497 | 2: top-off, 3: trickle */ | ||
448 | } else { | 498 | } else { |
449 | charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ | 499 | charge_state = 0; /* 0: decharging/charger |
500 | off, 1: charge, | ||
501 | 2: top-off, 3: trickle */ | ||
450 | } | 502 | } |
451 | } else { | 503 | } else { |
452 | /* if we didn't disable the charger in the previous test, check for low positive delta */ | 504 | /* if we didn't disable the charger in the |
453 | delta = ( power_history[POWER_HISTORY_LEN-1] * 100 | 505 | previous test, check for low positive delta */ |
454 | + power_history[POWER_HISTORY_LEN-2] * 100 | 506 | delta = |
455 | - power_history[POWER_HISTORY_LEN-1-CHARGE_END_ZEROD+1] * 100 | 507 | ( power_history[POWER_HISTORY_LEN-1] * 100 |
456 | - power_history[POWER_HISTORY_LEN-1-CHARGE_END_ZEROD] * 100 ) | 508 | + power_history[POWER_HISTORY_LEN-2] * 100 |
457 | / CHARGE_END_ZEROD / 2; | 509 | - power_history[POWER_HISTORY_LEN-1- |
510 | CHARGE_END_ZEROD+1] * 100 | ||
511 | - power_history[POWER_HISTORY_LEN-1- | ||
512 | CHARGE_END_ZEROD] * 100 ) | ||
513 | / CHARGE_END_ZEROD / 2; | ||
458 | 514 | ||
459 | if (delta < 1) { /* delta < 0.1 mV */ | 515 | if (delta < 1) { /* delta < 0.1 mV */ |
460 | DEBUGF("power: long-term small positive delta, enough!\n"); | 516 | DEBUGF("power: long-term small " |
517 | "positive delta, enough!\n"); | ||
461 | powermgmt_last_cycle_level = battery_level(); | 518 | powermgmt_last_cycle_level = battery_level(); |
462 | powermgmt_last_cycle_startstop_min = 0; | 519 | powermgmt_last_cycle_startstop_min = 0; |
463 | charger_enable(false); | 520 | charger_enable(false); |
464 | snprintf(power_message, POWER_MESSAGE_LEN, "end lowd %d %dmin", delta, charged_time); | 521 | snprintf(power_message, POWER_MESSAGE_LEN, |
465 | /* disable charging for several hours from this point, just to be sure */ | 522 | "end lowd %d %dmin", |
523 | delta, charged_time); | ||
524 | /* disable charging for several hours from | ||
525 | this point, just to be sure */ | ||
466 | charge_pause = CHARGE_PAUSE_LEN; | 526 | charge_pause = CHARGE_PAUSE_LEN; |
467 | /* enable trickle charging */ | 527 | /* enable trickle charging */ |
468 | if (trickle_charge_enabled) { | 528 | if (trickle_charge_enabled) { |
469 | trickle_sec = CURRENT_NORMAL * 60 / CURRENT_CHARGING; /* first guess, maybe consider if LED backlight is on, disk is active,... */ | 529 | trickle_sec = |
530 | CURRENT_NORMAL * 60 / CURRENT_CHARGING; | ||
531 | /* first guess, maybe consider if LED | ||
532 | backlight is on, disk is active,... */ | ||
470 | trickle_time = 0; | 533 | trickle_time = 0; |
471 | charge_state = 2; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ | 534 | charge_state = 2; |
535 | /* 0: decharging/charger off, 1: charge, | ||
536 | 2: top-off, 3: trickle */ | ||
472 | } else { | 537 | } else { |
473 | charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ | 538 | charge_state = 0; |
539 | /* 0: decharging/charger off, 1: charge, | ||
540 | 2: top-off, 3: trickle */ | ||
474 | } | 541 | } |
475 | } | 542 | } |
476 | } | 543 | } |
477 | } | 544 | } |
478 | } | 545 | } |
479 | } else if (charge_state > 1) { /* top off or trickle? */ | 546 | } |
547 | else if (charge_state > 1) { /* top off or trickle? */ | ||
480 | /* adjust trickle charge time */ | 548 | /* adjust trickle charge time */ |
481 | if ( ((charge_state == 2) && (power_history[POWER_HISTORY_LEN-1] > TOPOFF_VOLTAGE)) | 549 | if ( ((charge_state == 2) && |
482 | || ((charge_state == 3) && (power_history[POWER_HISTORY_LEN-1] > TRICKLE_VOLTAGE)) ) { /* charging too much */ | 550 | (power_history[POWER_HISTORY_LEN-1] > TOPOFF_VOLTAGE)) |
551 | || ((charge_state == 3) && | ||
552 | (power_history[POWER_HISTORY_LEN-1] > | ||
553 | TRICKLE_VOLTAGE)) ) { /* charging too much */ | ||
483 | trickle_sec--; | 554 | trickle_sec--; |
484 | } else { /* charging too less */ | 555 | } |
556 | else { /* charging too less */ | ||
485 | trickle_sec++; | 557 | trickle_sec++; |
486 | } | 558 | } |
487 | 559 | ||
488 | if (trickle_sec > 24) trickle_sec = 24; | 560 | if (trickle_sec > 24) |
489 | if (trickle_sec < 1) trickle_sec = 1; | 561 | trickle_sec = 24; |
562 | |||
563 | if (trickle_sec < 1) | ||
564 | trickle_sec = 1; | ||
490 | 565 | ||
491 | /* charge the calculated amount of seconds */ | 566 | /* charge the calculated amount of seconds */ |
492 | charger_enable(true); | 567 | charger_enable(true); |
@@ -496,57 +571,76 @@ static void power_thread(void) | |||
496 | /* trickle charging long enough? */ | 571 | /* trickle charging long enough? */ |
497 | 572 | ||
498 | if (trickle_time++ > TRICKLE_MAX_TIME + TOPOFF_MAX_TIME) { | 573 | if (trickle_time++ > TRICKLE_MAX_TIME + TOPOFF_MAX_TIME) { |
499 | trickle_sec = 0; /* show in debug menu that trickle is off */ | 574 | trickle_sec = 0; /* show in debug menu that trickle is |
500 | charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ | 575 | off */ |
576 | charge_state = 0; /* 0: decharging/charger off, 1: charge, | ||
577 | 2: top-off, 3: trickle */ | ||
501 | powermgmt_last_cycle_startstop_min = 0; | 578 | powermgmt_last_cycle_startstop_min = 0; |
502 | } | 579 | } |
503 | 580 | ||
504 | if ((charge_state == 2) && (trickle_time > TOPOFF_MAX_TIME)) /* change state? */ | 581 | if ((charge_state == 2) && |
505 | charge_state = 3; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ | 582 | (trickle_time > TOPOFF_MAX_TIME)) /* change state? */ |
583 | charge_state = 3; /* 0: decharging/charger off, 1: charge, | ||
584 | 2: top-off, 3: trickle */ | ||
506 | 585 | ||
507 | } else { /* charge_state == 0 */ | 586 | } else { /* charge_state == 0 */ |
508 | 587 | ||
509 | /* the charger is enabled here only in one case: if it was turned on at boot time (power_init) */ | 588 | /* the charger is enabled here only in one case: if it was |
589 | turned on at boot time (power_init) */ | ||
510 | /* turn it off now */ | 590 | /* turn it off now */ |
511 | if (charger_enabled) | 591 | if (charger_enabled) |
512 | charger_enable(false); | 592 | charger_enable(false); |
513 | } | 593 | } |
514 | 594 | ||
515 | /* Start new charge cycle? This must be possible also in trickle/top-off, because when usb connected, */ | 595 | /* Start new charge cycle? This must be possible also in |
596 | trickle/top-off, because when usb connected, */ | ||
516 | /* the trickle charge amount may not be enough */ | 597 | /* the trickle charge amount may not be enough */ |
517 | 598 | ||
518 | if ((charge_state == 0) || (charge_state > 1)) | 599 | if ((charge_state == 0) || (charge_state > 1)) |
519 | /* if battery is not full, enable charging */ | 600 | /* if battery is not full, enable charging */ |
520 | /* make sure charging starts if 1%-lazyness in battery_level_update() is too slow */ | 601 | /* make sure charging starts if 1%-lazyness in |
602 | battery_level_update() is too slow */ | ||
521 | if ( (battery_level() < charge_restart_level) | 603 | if ( (battery_level() < charge_restart_level) |
522 | || (power_history[POWER_HISTORY_LEN-1] < BATTERY_LEVEL_DANGEROUS)) { | 604 | || (power_history[POWER_HISTORY_LEN-1] < |
605 | BATTERY_LEVEL_DANGEROUS)) { | ||
523 | if (charge_pause) { | 606 | if (charge_pause) { |
524 | DEBUGF("power: batt level < restart level, but charge pause, not enabling\n"); | 607 | DEBUGF("power: batt level < restart level," |
525 | snprintf(power_message, POWER_MESSAGE_LEN, "chg pause %d min", charge_pause); | 608 | " but charge pause, not enabling\n"); |
609 | snprintf(power_message, POWER_MESSAGE_LEN, | ||
610 | "chg pause %d min", charge_pause); | ||
526 | } else { | 611 | } else { |
527 | /* calculate max charge time depending on current battery level */ | 612 | /* calculate max charge time depending on current |
528 | /* take 35% more because some more energy is used for heating up the battery */ | 613 | battery level */ |
614 | /* take 35% more because some more energy is used for | ||
615 | heating up the battery */ | ||
529 | i = CHARGE_MAX_TIME_1500 * battery_capacity / 1500; | 616 | i = CHARGE_MAX_TIME_1500 * battery_capacity / 1500; |
530 | charge_max_time_now = i * (100 + 35 - battery_level()) / 100; | 617 | charge_max_time_now = |
618 | i * (100 + 35 - battery_level()) / 100; | ||
531 | if (charge_max_time_now > i) { | 619 | if (charge_max_time_now > i) { |
532 | charge_max_time_now = i; | 620 | charge_max_time_now = i; |
533 | } | 621 | } |
534 | snprintf(power_message, POWER_MESSAGE_LEN, "ChgAt %d%% max %dm", battery_level(), charge_max_time_now); | 622 | snprintf(power_message, POWER_MESSAGE_LEN, |
535 | 623 | "ChgAt %d%% max %dm", battery_level(), | |
536 | /* enable the charger after the max time calc is done, because battery_level */ | 624 | charge_max_time_now); |
537 | /* depends on if the charger is on */ | 625 | |
538 | DEBUGF("power: charger inserted and battery not full, enabling\n"); | 626 | /* enable the charger after the max time calc is done, |
627 | because battery_level depends on if the charger is | ||
628 | on */ | ||
629 | DEBUGF("power: charger inserted and battery" | ||
630 | " not full, enabling\n"); | ||
539 | powermgmt_last_cycle_level = battery_level(); | 631 | powermgmt_last_cycle_level = battery_level(); |
540 | powermgmt_last_cycle_startstop_min = 0; | 632 | powermgmt_last_cycle_startstop_min = 0; |
541 | charged_time = 0; | 633 | charged_time = 0; |
542 | 634 | ||
543 | charger_enable(true); | 635 | charger_enable(true); |
544 | charge_state = 1; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ | 636 | charge_state = 1; /* 0: decharging/charger off, 1: |
545 | /* clear the power history so that we don't use values before | 637 | charge, 2: top-off, 3: trickle */ |
546 | * discharge for the long-term delta | 638 | /* clear the power history so that we don't use values |
639 | before discharge for the long-term delta | ||
547 | */ | 640 | */ |
548 | for (i = 0; i < POWER_HISTORY_LEN-1; i++) | 641 | for (i = 0; i < POWER_HISTORY_LEN-1; i++) |
549 | power_history[i] = power_history[POWER_HISTORY_LEN-1]; | 642 | power_history[i] = |
643 | power_history[POWER_HISTORY_LEN-1]; | ||
550 | } | 644 | } |
551 | } | 645 | } |
552 | 646 | ||
@@ -560,7 +654,8 @@ static void power_thread(void) | |||
560 | /* show in debug menu that trickle is off */ | 654 | /* show in debug menu that trickle is off */ |
561 | trickle_sec = 0; | 655 | trickle_sec = 0; |
562 | charger_enable(false); | 656 | charger_enable(false); |
563 | charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ | 657 | charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: |
658 | top-off, 3: trickle */ | ||
564 | snprintf(power_message, POWER_MESSAGE_LEN, "Charger disc"); | 659 | snprintf(power_message, POWER_MESSAGE_LEN, "Charger disc"); |
565 | } | 660 | } |
566 | /* charger not inserted and disabled, so we're discharging */ | 661 | /* charger not inserted and disabled, so we're discharging */ |
@@ -588,11 +683,14 @@ void power_init(void) | |||
588 | memset(power_history, 0x00, sizeof(power_history)); | 683 | memset(power_history, 0x00, sizeof(power_history)); |
589 | /* initialize the history with a single sample to prevent level | 684 | /* initialize the history with a single sample to prevent level |
590 | flickering during the first minute of execution */ | 685 | flickering during the first minute of execution */ |
591 | power_history[POWER_HISTORY_LEN-1] = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000; | 686 | power_history[POWER_HISTORY_LEN-1] = |
687 | (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000; | ||
592 | /* calculate the first battery level */ | 688 | /* calculate the first battery level */ |
593 | battery_level_update(); | 689 | battery_level_update(); |
594 | /* calculate the remaining time to that the info screen displays something useful */ | 690 | /* calculate the remaining time to that the info screen displays something |
595 | powermgmt_est_runningtime_min = battery_level() * battery_capacity / 100 * 60 / CURRENT_NORMAL; | 691 | useful */ |
692 | powermgmt_est_runningtime_min = | ||
693 | battery_level() * battery_capacity / 100 * 60 / CURRENT_NORMAL; | ||
596 | #if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */ | 694 | #if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */ |
597 | powermgmt_est_runningtime_min = powermgmt_est_runningtime_min * 122 / 100; | 695 | powermgmt_est_runningtime_min = powermgmt_est_runningtime_min * 122 / 100; |
598 | #endif | 696 | #endif |
@@ -605,7 +703,8 @@ void power_init(void) | |||
605 | charger_enable(true); | 703 | charger_enable(true); |
606 | #endif | 704 | #endif |
607 | 705 | ||
608 | create_thread(power_thread, power_stack, sizeof(power_stack), power_thread_name); | 706 | create_thread(power_thread, power_stack, sizeof(power_stack), |
707 | power_thread_name); | ||
609 | } | 708 | } |
610 | 709 | ||
611 | #endif /* SIMULATOR */ | 710 | #endif /* SIMULATOR */ |