summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/powermgmt.c349
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
66int battery_capacity = 1500; /* only a default value */ 66int battery_capacity = 1500; /* only a default value */
67int battery_level_cached = -1; /* battery level of this minute, updated once per minute */ 67int battery_level_cached = -1; /* battery level of this minute, updated once
68 per minute */
68 69
69static int poweroff_idle_timeout_value[15] = 70static 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
74static int percent_to_volt_decharge[11] = /* voltages (centivolt) of 0%, 10%, ... 100% when charging disabled */ 75static 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
98char power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in debug menu */ 102char power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in
99char charge_restart_level = CHARGE_RESTART_HI; /* level at which charging starts */ 103 debug menu */
100int powermgmt_last_cycle_startstop_min = 25; /* how many minutes ago was the charging started or stopped? */ 104char charge_restart_level = CHARGE_RESTART_HI; /* level at which charging
101int powermgmt_last_cycle_level = 0; /* which level had the batteries at this time? */ 105 starts */
106int powermgmt_last_cycle_startstop_min = 25; /* how many minutes ago was the
107 charging started or
108 stopped? */
109int powermgmt_last_cycle_level = 0; /* which level had the
110 batteries at this time? */
102bool trickle_charge_enabled = true; 111bool trickle_charge_enabled = true;
103int trickle_sec = 0; /* how many seconds should the charger be enabled per minute for trickle charging? */ 112int trickle_sec = 0; /* how many seconds should the
104int charge_state = 0; /* at the beginning, the charger does nothing */ 113 charger be enabled per
105 114 minute for trickle
106static int percent_to_volt_charge[11] = /* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */ 115 charging? */
116int charge_state = 0; /* at the beginning, the
117 charger does nothing */
118
119static 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 */
137int voltage_to_percent(int voltage, int* table) 153int 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
228void set_poweroff_timeout(int timeout) 252void set_poweroff_timeout(int timeout)
@@ -232,13 +256,11 @@ void set_poweroff_timeout(int timeout)
232 256
233void set_sleep_timer(int seconds) 257void 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 */