summaryrefslogtreecommitdiff
path: root/firmware/powermgmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/powermgmt.c')
-rw-r--r--firmware/powermgmt.c90
1 files changed, 52 insertions, 38 deletions
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index a05c54f8a3..49c27d93d6 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -69,6 +69,15 @@ static int percent_to_volt_nocharge[11] = /* voltages (centivolt) of 0%, 10%, ..
69 450, 481, 491, 497, 503, 507, 512, 514, 517, 528, 560 69 450, 481, 491, 497, 503, 507, 512, 514, 517, 528, 560
70}; 70};
71 71
72int battery_capacity = 1500; /* only a default value */
73
74void set_battery_capacity(int capacity)
75{
76 int values[8] = {1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200};
77
78 battery_capacity = values[capacity];
79}
80
72#ifdef HAVE_CHARGE_CTRL 81#ifdef HAVE_CHARGE_CTRL
73 82
74char power_message[POWER_MESSAGE_LEN] = ""; 83char power_message[POWER_MESSAGE_LEN] = "";
@@ -79,18 +88,12 @@ int powermgmt_last_cycle_level = 0; /* which level had the batteries at
79bool trickle_charge_enabled = true; 88bool trickle_charge_enabled = true;
80int trickle_sec = 0; /* how many seconds should the charger be enabled per minute for trickle charging? */ 89int trickle_sec = 0; /* how many seconds should the charger be enabled per minute for trickle charging? */
81int charge_state = 0; /* at the beginning, the charger does nothing */ 90int charge_state = 0; /* at the beginning, the charger does nothing */
82int battery_capacity = 1800; /* only a default value */
83 91
84static int percent_to_volt_charge[11] = /* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */ 92static int percent_to_volt_charge[11] = /* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */
85{ 93{
86 476, 544, 551, 556, 561, 564, 566, 576, 582, 584, 585 94 476, 544, 551, 556, 561, 564, 566, 576, 582, 584, 585
87}; 95};
88 96
89void set_battery_capacity(int capacity)
90{
91 battery_capacity = capacity;
92}
93
94void enable_trickle_charge(bool on) 97void enable_trickle_charge(bool on)
95{ 98{
96 trickle_charge_enabled = on; 99 trickle_charge_enabled = on;
@@ -375,7 +378,7 @@ static void power_thread(void)
375 charge_pause--; 378 charge_pause--;
376 379
377 if (charger_inserted()) { 380 if (charger_inserted()) {
378 if (charger_enabled) { 381 if (charge_state == 1) {
379 /* charger inserted and enabled */ 382 /* charger inserted and enabled */
380 charged_time++; 383 charged_time++;
381 snprintf(power_message, POWER_MESSAGE_LEN, "Chg %dm max %dm", charged_time, charge_max_time_now); 384 snprintf(power_message, POWER_MESSAGE_LEN, "Chg %dm max %dm", charged_time, charge_max_time_now);
@@ -446,36 +449,39 @@ static void power_thread(void)
446 } 449 }
447 } 450 }
448 } 451 }
449 } else { /* charged inserted but not enabled */ 452 } else if (charge_state > 1) { /* top off or trickle? */
450 453 /* adjust trickle charge time */
451 /* trickle charging */ 454 if ( ((charge_state == 2) && (power_history[POWER_HISTORY_LEN-1] > TOPOFF_VOLTAGE))
452 if (charge_state > 1) { /* top off or trickle? */ 455 || ((charge_state == 3) && (power_history[POWER_HISTORY_LEN-1] > TRICKLE_VOLTAGE)) ) { /* charging too much */
453 /* adjust trickle charge time */ 456 trickle_sec--;
454 if ( ((charge_state == 2) && (power_history[POWER_HISTORY_LEN-1] > TOPOFF_VOLTAGE)) 457 } else { /* charging too less */
455 || ((charge_state == 3) && (power_history[POWER_HISTORY_LEN-1] > TRICKLE_VOLTAGE)) ) { /* charging too much */ 458 trickle_sec++;
456 trickle_sec--; 459 }
457 } else { /* charging too less */
458 trickle_sec++;
459 }
460
461 if (trickle_sec > 24) trickle_sec = 24;
462 if (trickle_sec < 1) trickle_sec = 1;
463
464 /* charge the calculated amount of seconds */
465 charger_enable(true);
466 sleep(HZ * trickle_sec);
467 charger_enable(false);
468
469 /* trickle charging long enough? */
470 460
471 if (trickle_time++ > TRICKLE_MAX_TIME + TOPOFF_MAX_TIME) { 461 if (trickle_sec > 24) trickle_sec = 24;
472 trickle_sec = 0; /* show in debug menu that trickle is off */ 462 if (trickle_sec < 1) trickle_sec = 1;
473 charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ 463
474 } 464 /* charge the calculated amount of seconds */
465 charger_enable(true);
466 sleep(HZ * trickle_sec);
467 charger_enable(false);
468
469 /* trickle charging long enough? */
470
471 if (trickle_time++ > TRICKLE_MAX_TIME + TOPOFF_MAX_TIME) {
472 trickle_sec = 0; /* show in debug menu that trickle is off */
473 charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */
474 }
475 475
476 if ((charge_state == 2) && (trickle_time > TOPOFF_MAX_TIME)) /* change state? */ 476 if ((charge_state == 2) && (trickle_time > TOPOFF_MAX_TIME)) /* change state? */
477 charge_state = 3; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ 477 charge_state = 3; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */
478 } 478
479 } else { /* charge_state == 0 */
480
481 /* the charger is enabled here only in one case: if it was turned on at boot time (power_init) */
482 /* turn it off now */
483 if (charger_enabled)
484 charger_enable(false);
479 485
480 /* if battery is not full, enable charging */ 486 /* if battery is not full, enable charging */
481 if (battery_level() < charge_restart_level) { 487 if (battery_level() < charge_restart_level) {
@@ -511,12 +517,16 @@ static void power_thread(void)
511 } 517 }
512 } else { 518 } else {
513 /* charger not inserted */ 519 /* charger not inserted */
514 if (charger_enabled) { 520 if (charge_state > 0) {
515 /* charger not inserted but was enabled */ 521 /* charger not inserted but was enabled */
516 DEBUGF("power: charger disconnected, disabling\n"); 522 DEBUGF("power: charger disconnected, disabling\n");
517 powermgmt_last_cycle_level = battery_level(); 523 powermgmt_last_cycle_level = battery_level();
518 powermgmt_last_cycle_startstop_min = 0; 524 /* if the user only charged some minutes, we don't really have */
519 trickle_sec = 0; /* show in debug menu that trickle is off */ 525 /* a battery level that's usual for charging */
526 /* the next line prevents the battery level being too low when the charger is connected for only some minutes */
527 powermgmt_last_cycle_startstop_min = (powermgmt_last_cycle_startstop_min > 10) ? 0 : 20;
528 /* show in debug menu that trickle is off */
529 trickle_sec = 0;
520 charger_enable(false); 530 charger_enable(false);
521 charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ 531 charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */
522 snprintf(power_message, POWER_MESSAGE_LEN, "Charger disc"); 532 snprintf(power_message, POWER_MESSAGE_LEN, "Charger disc");
@@ -552,6 +562,10 @@ void power_init(void)
552 562
553#ifdef HAVE_CHARGE_CTRL 563#ifdef HAVE_CHARGE_CTRL
554 snprintf(power_message, POWER_MESSAGE_LEN, "Powermgmt started"); 564 snprintf(power_message, POWER_MESSAGE_LEN, "Powermgmt started");
565
566 /* if the battery is nearly empty, start charging immediately */
567 if (power_history[POWER_HISTORY_LEN-1] < BATTERY_LEVEL_DANGEROUS)
568 charger_enable(true);
555#endif 569#endif
556 create_thread(power_thread, power_stack, sizeof(power_stack), power_thread_name); 570 create_thread(power_thread, power_stack, sizeof(power_stack), power_thread_name);
557} 571}