forked from len0rd/rockbox
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
This commit is contained in:
parent
975e240a0c
commit
2573879fb1
1 changed files with 222 additions and 123 deletions
|
|
@ -63,24 +63,28 @@ void set_battery_capacity(int capacity)
|
||||||
}
|
}
|
||||||
#else /* not SIMULATOR */
|
#else /* not SIMULATOR */
|
||||||
|
|
||||||
int battery_capacity = 1500; /* only a default value */
|
int battery_capacity = 1500; /* only a default value */
|
||||||
int battery_level_cached = -1; /* battery level of this minute, updated once per minute */
|
int battery_level_cached = -1; /* battery level of this minute, updated once
|
||||||
|
per minute */
|
||||||
|
|
||||||
static int poweroff_idle_timeout_value[15] =
|
static int poweroff_idle_timeout_value[15] =
|
||||||
{
|
{
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 30, 45, 60
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 30, 45, 60
|
||||||
};
|
};
|
||||||
|
|
||||||
static int percent_to_volt_decharge[11] = /* voltages (centivolt) of 0%, 10%, ... 100% when charging disabled */
|
static int percent_to_volt_decharge[11] =
|
||||||
|
/* voltages (centivolt) of 0%, 10%, ... 100% when charging disabled */
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LIION
|
#ifdef HAVE_LIION
|
||||||
/* values guessed, see http://www.seattlerobotics.org/encoder/200210/LiIon2.pdf */
|
/* values guessed, see
|
||||||
/* until someone measures voltages over a decharging cycle */
|
http://www.seattlerobotics.org/encoder/200210/LiIon2.pdf until someone
|
||||||
|
measures voltages over a decharging cycle */
|
||||||
260, 280, 300, 320, 340, 350, 360, 370, 380, 390, 400
|
260, 280, 300, 320, 340, 350, 360, 370, 380, 390, 400
|
||||||
#else /* NiMH */
|
#else /* NiMH */
|
||||||
/* original values were taken directly after charging, */
|
/* original values were taken directly after charging, but it should show
|
||||||
/* but it should show 100% after turning off the device for some hours, too */
|
100% after turning off the device for some hours, too */
|
||||||
450, 481, 491, 497, 503, 507, 512, 514, 517, 525, 540 /* orig. values: ...,528,560 */
|
450, 481, 491, 497, 503, 507, 512, 514, 517, 525, 540 /* orig. values:
|
||||||
|
...,528,560 */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -95,18 +99,29 @@ void set_battery_capacity(int capacity)
|
||||||
|
|
||||||
#ifdef HAVE_CHARGE_CTRL
|
#ifdef HAVE_CHARGE_CTRL
|
||||||
|
|
||||||
char power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in debug menu */
|
char power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in
|
||||||
char charge_restart_level = CHARGE_RESTART_HI; /* level at which charging starts */
|
debug menu */
|
||||||
int powermgmt_last_cycle_startstop_min = 25; /* how many minutes ago was the charging started or stopped? */
|
char charge_restart_level = CHARGE_RESTART_HI; /* level at which charging
|
||||||
int powermgmt_last_cycle_level = 0; /* which level had the batteries at this time? */
|
starts */
|
||||||
|
int powermgmt_last_cycle_startstop_min = 25; /* how many minutes ago was the
|
||||||
|
charging started or
|
||||||
|
stopped? */
|
||||||
|
int powermgmt_last_cycle_level = 0; /* which level had the
|
||||||
|
batteries at this time? */
|
||||||
bool trickle_charge_enabled = true;
|
bool trickle_charge_enabled = true;
|
||||||
int trickle_sec = 0; /* how many seconds should the charger be enabled per minute for trickle charging? */
|
int trickle_sec = 0; /* how many seconds should the
|
||||||
int charge_state = 0; /* at the beginning, the charger does nothing */
|
charger be enabled per
|
||||||
|
minute for trickle
|
||||||
|
charging? */
|
||||||
|
int charge_state = 0; /* at the beginning, the
|
||||||
|
charger does nothing */
|
||||||
|
|
||||||
static int percent_to_volt_charge[11] = /* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */
|
static int percent_to_volt_charge[11] = /* voltages (centivolt) of 0%, 10%,
|
||||||
|
... 100% when charging enabled */
|
||||||
{
|
{
|
||||||
/* values guessed, see http://www.seattlerobotics.org/encoder/200210/LiIon2.pdf */
|
/* values guessed, see
|
||||||
/* until someone measures voltages over a charging cycle */
|
http://www.seattlerobotics.org/encoder/200210/LiIon2.pdf until someone
|
||||||
|
measures voltages over a charging cycle */
|
||||||
476, 544, 551, 556, 561, 564, 566, 576, 582, 584, 585 /* NiMH */
|
476, 544, 551, 556, 561, 564, 566, 576, 582, 584, 585 /* NiMH */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -133,23 +148,25 @@ int battery_time(void)
|
||||||
return powermgmt_est_runningtime_min;
|
return powermgmt_est_runningtime_min;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* look into the percent_to_volt_* table and get a realistic battery level percentage */
|
/* look into the percent_to_volt_* table and get a realistic battery level
|
||||||
|
percentage */
|
||||||
int voltage_to_percent(int voltage, int* table)
|
int voltage_to_percent(int voltage, int* table)
|
||||||
{
|
{
|
||||||
if (voltage <= table[0])
|
if (voltage <= table[0])
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
if (voltage >= table[10])
|
if (voltage >= table[10])
|
||||||
return 100;
|
return 100;
|
||||||
else {
|
else {
|
||||||
/* search nearest value */
|
/* search nearest value */
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while ((i < 10) && (table[i+1] < voltage))
|
while ((i < 10) && (table[i+1] < voltage))
|
||||||
i++;
|
i++;
|
||||||
/* interpolate linear between the smaller and greater value */
|
/* interpolate linear between the smaller and greater value */
|
||||||
return i * 10 /* 10th */
|
return i * 10 /* 10th */
|
||||||
+ (voltage - table[i]) * 10 / (table[i+1] - table[i]); /* 1th */
|
+ (voltage - table[i]) *
|
||||||
}
|
10 / (table[i+1] - table[i]); /* 1th */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update battery level, called only once per minute */
|
/* update battery level, called only once per minute */
|
||||||
|
|
@ -180,28 +197,34 @@ void battery_level_update(void)
|
||||||
#ifdef HAVE_CHARGE_CTRL
|
#ifdef HAVE_CHARGE_CTRL
|
||||||
if (charge_state == 0) { /* decharge */
|
if (charge_state == 0) { /* decharge */
|
||||||
level = voltage_to_percent(level, percent_to_volt_decharge);
|
level = voltage_to_percent(level, percent_to_volt_decharge);
|
||||||
} else if (charge_state == 1) { /* charge */
|
}
|
||||||
level = voltage_to_percent(level, percent_to_volt_charge);
|
else if (charge_state == 1) { /* charge */
|
||||||
} else {/* in trickle charge, the battery is per definition 100% full */
|
level = voltage_to_percent(level, percent_to_volt_charge);
|
||||||
|
}
|
||||||
|
else {/* in trickle charge, the battery is per definition 100% full */
|
||||||
battery_level_cached = level = 100;
|
battery_level_cached = level = 100;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
level = voltage_to_percent(level, percent_to_volt_decharge); /* always use the decharge table */
|
level = voltage_to_percent(level, percent_to_volt_decharge);
|
||||||
|
/* always use the decharge table */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (battery_level_cached == -1) { /* first run of this procedure */
|
if (battery_level_cached == -1) { /* first run of this procedure */
|
||||||
/* the battery voltage is usually a little lower directly after turning on, because the disk was used heavily */
|
/* the battery voltage is usually a little lower directly after
|
||||||
/* raise it by 5 % */
|
turning on, because the disk was used heavily raise it by 5 % */
|
||||||
battery_level_cached = (level > 95) ? 100 : level + 5;
|
battery_level_cached = (level > 95) ? 100 : level + 5;
|
||||||
} else {
|
}
|
||||||
/* the level is allowed to be +1/-1 of the last value when usb not connected */
|
else {
|
||||||
/* and to be +1/-3 of the last value when usb is connected */
|
/* the level is allowed to be +1/-1 of the last value when usb not
|
||||||
|
connected and to be +1/-3 of the last value when usb is
|
||||||
|
connected */
|
||||||
if (level > battery_level_cached + 1)
|
if (level > battery_level_cached + 1)
|
||||||
level = battery_level_cached + 1;
|
level = battery_level_cached + 1;
|
||||||
if (usb_inserted()) {
|
if (usb_inserted()) {
|
||||||
if (level < battery_level_cached - 3)
|
if (level < battery_level_cached - 3)
|
||||||
level = battery_level_cached - 3;
|
level = battery_level_cached - 3;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (level < battery_level_cached - 1)
|
if (level < battery_level_cached - 1)
|
||||||
level = battery_level_cached - 1;
|
level = battery_level_cached - 1;
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +245,8 @@ bool battery_level_safe(void)
|
||||||
if (power_history[POWER_HISTORY_LEN-1])
|
if (power_history[POWER_HISTORY_LEN-1])
|
||||||
return power_history[POWER_HISTORY_LEN-1] > BATTERY_LEVEL_DANGEROUS;
|
return power_history[POWER_HISTORY_LEN-1] > BATTERY_LEVEL_DANGEROUS;
|
||||||
else
|
else
|
||||||
return adc_read(ADC_UNREG_POWER) > (BATTERY_LEVEL_DANGEROUS * 10000) / BATTERY_SCALE_FACTOR;
|
return adc_read(ADC_UNREG_POWER) > (BATTERY_LEVEL_DANGEROUS * 10000) /
|
||||||
|
BATTERY_SCALE_FACTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_poweroff_timeout(int timeout)
|
void set_poweroff_timeout(int timeout)
|
||||||
|
|
@ -232,13 +256,11 @@ void set_poweroff_timeout(int timeout)
|
||||||
|
|
||||||
void set_sleep_timer(int seconds)
|
void set_sleep_timer(int seconds)
|
||||||
{
|
{
|
||||||
if(seconds)
|
if(seconds) {
|
||||||
{
|
|
||||||
sleeptimer_active = true;
|
sleeptimer_active = true;
|
||||||
sleeptimer_endtick = current_tick + seconds * HZ;
|
sleeptimer_endtick = current_tick + seconds * HZ;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
sleeptimer_active = false;
|
sleeptimer_active = false;
|
||||||
sleeptimer_endtick = 0;
|
sleeptimer_endtick = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -324,7 +346,8 @@ static void power_thread(void)
|
||||||
#ifdef HAVE_CHARGE_CTRL
|
#ifdef HAVE_CHARGE_CTRL
|
||||||
int delta;
|
int delta;
|
||||||
int charged_time = 0;
|
int charged_time = 0;
|
||||||
int charge_max_time_now = 0; /* max. charging duration, calculated at beginning of charging */
|
int charge_max_time_now = 0; /* max. charging duration, calculated at
|
||||||
|
beginning of charging */
|
||||||
int charge_pause = 0; /* no charging pause at the beginning */
|
int charge_pause = 0; /* no charging pause at the beginning */
|
||||||
int trickle_time = 0; /* how many minutes trickle charging already? */
|
int trickle_time = 0; /* how many minutes trickle charging already? */
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -360,9 +383,11 @@ static void power_thread(void)
|
||||||
power_history[i] = power_history[i+1];
|
power_history[i] = power_history[i+1];
|
||||||
|
|
||||||
/* insert new value in the end, in centivolts 8-) */
|
/* insert new value in the end, in centivolts 8-) */
|
||||||
power_history[POWER_HISTORY_LEN-1] = (avg * BATTERY_SCALE_FACTOR) / 10000;
|
power_history[POWER_HISTORY_LEN-1] =
|
||||||
|
(avg * BATTERY_SCALE_FACTOR) / 10000;
|
||||||
|
|
||||||
/* update battery level every minute, ignoring first 15 minutes after start charge/decharge */
|
/* update battery level every minute, ignoring first 15 minutes after
|
||||||
|
start charge/decharge */
|
||||||
#ifdef HAVE_CHARGE_CTRL
|
#ifdef HAVE_CHARGE_CTRL
|
||||||
if ((powermgmt_last_cycle_startstop_min > 25) || (charge_state > 1))
|
if ((powermgmt_last_cycle_startstop_min > 25) || (charge_state > 1))
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -374,24 +399,30 @@ static void power_thread(void)
|
||||||
|
|
||||||
#ifdef HAVE_CHARGE_CTRL
|
#ifdef HAVE_CHARGE_CTRL
|
||||||
if (charge_state == 1)
|
if (charge_state == 1)
|
||||||
powermgmt_est_runningtime_min = (100 - battery_level()) * battery_capacity / 100 * 60 / CURRENT_CHARGING;
|
powermgmt_est_runningtime_min = (100 - battery_level()) *
|
||||||
|
battery_capacity / 100 * 60 / CURRENT_CHARGING;
|
||||||
else {
|
else {
|
||||||
current = usb_inserted() ? CURRENT_USB : CURRENT_NORMAL;
|
current = usb_inserted() ? CURRENT_USB : CURRENT_NORMAL;
|
||||||
if ((backlight_get_timeout() == 1) || (charger_inserted() && backlight_get_on_when_charging()))
|
if ((backlight_get_timeout() == 1) ||
|
||||||
/* LED always on or LED on when charger connected */
|
(charger_inserted() && backlight_get_on_when_charging()))
|
||||||
|
/* LED always on or LED on when charger connected */
|
||||||
current += CURRENT_BACKLIGHT;
|
current += CURRENT_BACKLIGHT;
|
||||||
powermgmt_est_runningtime_min = battery_level() * battery_capacity / 100 * 60 / current;
|
powermgmt_est_runningtime_min = battery_level() *
|
||||||
|
battery_capacity / 100 * 60 / current;
|
||||||
#if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */
|
#if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */
|
||||||
powermgmt_est_runningtime_min = powermgmt_est_runningtime_min * 122 / 100;
|
powermgmt_est_runningtime_min =
|
||||||
|
powermgmt_est_runningtime_min * 122 / 100;
|
||||||
#endif /* MEM == 8 */
|
#endif /* MEM == 8 */
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
current = usb_inserted() ? CURRENT_USB : CURRENT_NORMAL;
|
current = usb_inserted() ? CURRENT_USB : CURRENT_NORMAL;
|
||||||
if (backlight_get_timeout() == 1) /* LED always on */
|
if (backlight_get_timeout() == 1) /* LED always on */
|
||||||
current += CURRENT_BACKLIGHT;
|
current += CURRENT_BACKLIGHT;
|
||||||
powermgmt_est_runningtime_min = battery_level() * battery_capacity / 100 * 60 / current;
|
powermgmt_est_runningtime_min = battery_level() *
|
||||||
|
battery_capacity / 100 * 60 / current;
|
||||||
#if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */
|
#if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */
|
||||||
powermgmt_est_runningtime_min = powermgmt_est_runningtime_min * 122 / 100;
|
powermgmt_est_runningtime_min =
|
||||||
|
powermgmt_est_runningtime_min * 122 / 100;
|
||||||
#endif /* MEM == 8 */
|
#endif /* MEM == 8 */
|
||||||
#endif /* HAVE_CHARGE_CONTROL */
|
#endif /* HAVE_CHARGE_CONTROL */
|
||||||
|
|
||||||
|
|
@ -404,89 +435,133 @@ static void power_thread(void)
|
||||||
if (charge_state == 1) {
|
if (charge_state == 1) {
|
||||||
/* charger inserted and enabled */
|
/* charger inserted and enabled */
|
||||||
charged_time++;
|
charged_time++;
|
||||||
snprintf(power_message, POWER_MESSAGE_LEN, "Chg %dm max %dm", charged_time, charge_max_time_now);
|
snprintf(power_message, POWER_MESSAGE_LEN,
|
||||||
|
"Chg %dm max %dm", charged_time, charge_max_time_now);
|
||||||
|
|
||||||
if (charged_time > charge_max_time_now) {
|
if (charged_time > charge_max_time_now) {
|
||||||
DEBUGF("power: charged_time > charge_max_time_now, enough!\n");
|
DEBUGF("power: charged_time > charge_max_time_now, "
|
||||||
/* have charged too long and deltaV detection did not work! */
|
"enough!\n");
|
||||||
|
/* have charged too long and deltaV detection did not
|
||||||
|
work! */
|
||||||
powermgmt_last_cycle_level = battery_level();
|
powermgmt_last_cycle_level = battery_level();
|
||||||
powermgmt_last_cycle_startstop_min = 0;
|
powermgmt_last_cycle_startstop_min = 0;
|
||||||
charger_enable(false);
|
charger_enable(false);
|
||||||
snprintf(power_message, POWER_MESSAGE_LEN, "Chg tmout %d min", charge_max_time_now);
|
snprintf(power_message, POWER_MESSAGE_LEN,
|
||||||
/* disable charging for several hours from this point, just to be sure */
|
"Chg tmout %d min", charge_max_time_now);
|
||||||
|
/* disable charging for several hours from this point,
|
||||||
|
just to be sure */
|
||||||
charge_pause = CHARGE_PAUSE_LEN;
|
charge_pause = CHARGE_PAUSE_LEN;
|
||||||
/* no trickle charge here, because the charging cycle didn't end the right way */
|
/* no trickle charge here, because the charging cycle
|
||||||
charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */
|
didn't end the right way */
|
||||||
|
charge_state = 0; /* 0: decharging/charger off, 1: charge,
|
||||||
|
2: top-off, 3: trickle */
|
||||||
} else {
|
} else {
|
||||||
if (charged_time > CHARGE_MIN_TIME) {
|
if (charged_time > CHARGE_MIN_TIME) {
|
||||||
/* have charged continuously over the minimum charging time,
|
/* have charged continuously over the minimum charging
|
||||||
* so we monitor for deltaV going negative. Multiply things
|
time, so we monitor for deltaV going
|
||||||
* by 100 to get more accuracy without floating point arithmetic.
|
negative. Multiply thingsby 100 to get more
|
||||||
* power_history[] contains centivolts so after multiplying by 100
|
accuracy without floating point arithmetic.
|
||||||
* the deltas are in tenths of millivolts (delta of 5 is
|
power_history[] contains centivolts so after
|
||||||
* 0.0005 V).
|
multiplying by 100 the deltas are in tenths of
|
||||||
|
millivolts (delta of 5 is 0.0005 V).
|
||||||
*/
|
*/
|
||||||
delta = ( power_history[POWER_HISTORY_LEN-1] * 100
|
delta =
|
||||||
+ power_history[POWER_HISTORY_LEN-2] * 100
|
( power_history[POWER_HISTORY_LEN-1] * 100
|
||||||
- power_history[POWER_HISTORY_LEN-1-CHARGE_END_NEGD+1] * 100
|
+ power_history[POWER_HISTORY_LEN-2] * 100
|
||||||
- power_history[POWER_HISTORY_LEN-1-CHARGE_END_NEGD] * 100 )
|
- power_history[POWER_HISTORY_LEN-1-
|
||||||
/ CHARGE_END_NEGD / 2;
|
CHARGE_END_NEGD+1] * 100
|
||||||
|
- power_history[POWER_HISTORY_LEN-1-
|
||||||
|
CHARGE_END_NEGD] * 100 )
|
||||||
|
/ CHARGE_END_NEGD / 2;
|
||||||
|
|
||||||
if (delta < -100) { /* delta < -10 mV */
|
if (delta < -100) { /* delta < -10 mV */
|
||||||
DEBUGF("power: short-term negative delta, enough!\n");
|
DEBUGF("power: short-term negative"
|
||||||
|
" delta, enough!\n");
|
||||||
powermgmt_last_cycle_level = battery_level();
|
powermgmt_last_cycle_level = battery_level();
|
||||||
powermgmt_last_cycle_startstop_min = 0;
|
powermgmt_last_cycle_startstop_min = 0;
|
||||||
charger_enable(false);
|
charger_enable(false);
|
||||||
snprintf(power_message, POWER_MESSAGE_LEN, "end negd %d %dmin", delta, charged_time);
|
snprintf(power_message, POWER_MESSAGE_LEN,
|
||||||
/* disable charging for several hours from this point, just to be sure */
|
"end negd %d %dmin", delta, charged_time);
|
||||||
|
/* disable charging for several hours from this
|
||||||
|
point, just to be sure */
|
||||||
charge_pause = CHARGE_PAUSE_LEN;
|
charge_pause = CHARGE_PAUSE_LEN;
|
||||||
/* enable trickle charging */
|
/* enable trickle charging */
|
||||||
if (trickle_charge_enabled) {
|
if (trickle_charge_enabled) {
|
||||||
trickle_sec = CURRENT_NORMAL * 60 / CURRENT_CHARGING; /* first guess, maybe consider if LED backlight is on, disk is active,... */
|
trickle_sec = CURRENT_NORMAL * 60 /
|
||||||
|
CURRENT_CHARGING;
|
||||||
|
/* first guess, maybe consider if LED
|
||||||
|
backlight is on, disk is active,... */
|
||||||
trickle_time = 0;
|
trickle_time = 0;
|
||||||
charge_state = 2; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */
|
charge_state = 2; /* 0: decharging/charger
|
||||||
|
off, 1: charge,
|
||||||
|
2: top-off, 3: trickle */
|
||||||
} else {
|
} else {
|
||||||
charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */
|
charge_state = 0; /* 0: decharging/charger
|
||||||
|
off, 1: charge,
|
||||||
|
2: top-off, 3: trickle */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* if we didn't disable the charger in the previous test, check for low positive delta */
|
/* if we didn't disable the charger in the
|
||||||
delta = ( power_history[POWER_HISTORY_LEN-1] * 100
|
previous test, check for low positive delta */
|
||||||
+ power_history[POWER_HISTORY_LEN-2] * 100
|
delta =
|
||||||
- power_history[POWER_HISTORY_LEN-1-CHARGE_END_ZEROD+1] * 100
|
( power_history[POWER_HISTORY_LEN-1] * 100
|
||||||
- power_history[POWER_HISTORY_LEN-1-CHARGE_END_ZEROD] * 100 )
|
+ power_history[POWER_HISTORY_LEN-2] * 100
|
||||||
/ CHARGE_END_ZEROD / 2;
|
- power_history[POWER_HISTORY_LEN-1-
|
||||||
|
CHARGE_END_ZEROD+1] * 100
|
||||||
|
- power_history[POWER_HISTORY_LEN-1-
|
||||||
|
CHARGE_END_ZEROD] * 100 )
|
||||||
|
/ CHARGE_END_ZEROD / 2;
|
||||||
|
|
||||||
if (delta < 1) { /* delta < 0.1 mV */
|
if (delta < 1) { /* delta < 0.1 mV */
|
||||||
DEBUGF("power: long-term small positive delta, enough!\n");
|
DEBUGF("power: long-term small "
|
||||||
|
"positive delta, enough!\n");
|
||||||
powermgmt_last_cycle_level = battery_level();
|
powermgmt_last_cycle_level = battery_level();
|
||||||
powermgmt_last_cycle_startstop_min = 0;
|
powermgmt_last_cycle_startstop_min = 0;
|
||||||
charger_enable(false);
|
charger_enable(false);
|
||||||
snprintf(power_message, POWER_MESSAGE_LEN, "end lowd %d %dmin", delta, charged_time);
|
snprintf(power_message, POWER_MESSAGE_LEN,
|
||||||
/* disable charging for several hours from this point, just to be sure */
|
"end lowd %d %dmin",
|
||||||
|
delta, charged_time);
|
||||||
|
/* disable charging for several hours from
|
||||||
|
this point, just to be sure */
|
||||||
charge_pause = CHARGE_PAUSE_LEN;
|
charge_pause = CHARGE_PAUSE_LEN;
|
||||||
/* enable trickle charging */
|
/* enable trickle charging */
|
||||||
if (trickle_charge_enabled) {
|
if (trickle_charge_enabled) {
|
||||||
trickle_sec = CURRENT_NORMAL * 60 / CURRENT_CHARGING; /* first guess, maybe consider if LED backlight is on, disk is active,... */
|
trickle_sec =
|
||||||
|
CURRENT_NORMAL * 60 / CURRENT_CHARGING;
|
||||||
|
/* first guess, maybe consider if LED
|
||||||
|
backlight is on, disk is active,... */
|
||||||
trickle_time = 0;
|
trickle_time = 0;
|
||||||
charge_state = 2; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */
|
charge_state = 2;
|
||||||
|
/* 0: decharging/charger off, 1: charge,
|
||||||
|
2: top-off, 3: trickle */
|
||||||
} else {
|
} else {
|
||||||
charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */
|
charge_state = 0;
|
||||||
|
/* 0: decharging/charger off, 1: charge,
|
||||||
|
2: top-off, 3: trickle */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (charge_state > 1) { /* top off or trickle? */
|
}
|
||||||
|
else if (charge_state > 1) { /* top off or trickle? */
|
||||||
/* adjust trickle charge time */
|
/* adjust trickle charge time */
|
||||||
if ( ((charge_state == 2) && (power_history[POWER_HISTORY_LEN-1] > TOPOFF_VOLTAGE))
|
if ( ((charge_state == 2) &&
|
||||||
|| ((charge_state == 3) && (power_history[POWER_HISTORY_LEN-1] > TRICKLE_VOLTAGE)) ) { /* charging too much */
|
(power_history[POWER_HISTORY_LEN-1] > TOPOFF_VOLTAGE))
|
||||||
|
|| ((charge_state == 3) &&
|
||||||
|
(power_history[POWER_HISTORY_LEN-1] >
|
||||||
|
TRICKLE_VOLTAGE)) ) { /* charging too much */
|
||||||
trickle_sec--;
|
trickle_sec--;
|
||||||
} else { /* charging too less */
|
}
|
||||||
|
else { /* charging too less */
|
||||||
trickle_sec++;
|
trickle_sec++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trickle_sec > 24) trickle_sec = 24;
|
if (trickle_sec > 24)
|
||||||
if (trickle_sec < 1) trickle_sec = 1;
|
trickle_sec = 24;
|
||||||
|
|
||||||
|
if (trickle_sec < 1)
|
||||||
|
trickle_sec = 1;
|
||||||
|
|
||||||
/* charge the calculated amount of seconds */
|
/* charge the calculated amount of seconds */
|
||||||
charger_enable(true);
|
charger_enable(true);
|
||||||
|
|
@ -496,57 +571,76 @@ static void power_thread(void)
|
||||||
/* trickle charging long enough? */
|
/* trickle charging long enough? */
|
||||||
|
|
||||||
if (trickle_time++ > TRICKLE_MAX_TIME + TOPOFF_MAX_TIME) {
|
if (trickle_time++ > TRICKLE_MAX_TIME + TOPOFF_MAX_TIME) {
|
||||||
trickle_sec = 0; /* show in debug menu that trickle is off */
|
trickle_sec = 0; /* show in debug menu that trickle is
|
||||||
charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */
|
off */
|
||||||
|
charge_state = 0; /* 0: decharging/charger off, 1: charge,
|
||||||
|
2: top-off, 3: trickle */
|
||||||
powermgmt_last_cycle_startstop_min = 0;
|
powermgmt_last_cycle_startstop_min = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((charge_state == 2) && (trickle_time > TOPOFF_MAX_TIME)) /* change state? */
|
if ((charge_state == 2) &&
|
||||||
charge_state = 3; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */
|
(trickle_time > TOPOFF_MAX_TIME)) /* change state? */
|
||||||
|
charge_state = 3; /* 0: decharging/charger off, 1: charge,
|
||||||
|
2: top-off, 3: trickle */
|
||||||
|
|
||||||
} else { /* charge_state == 0 */
|
} else { /* charge_state == 0 */
|
||||||
|
|
||||||
/* the charger is enabled here only in one case: if it was turned on at boot time (power_init) */
|
/* the charger is enabled here only in one case: if it was
|
||||||
|
turned on at boot time (power_init) */
|
||||||
/* turn it off now */
|
/* turn it off now */
|
||||||
if (charger_enabled)
|
if (charger_enabled)
|
||||||
charger_enable(false);
|
charger_enable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start new charge cycle? This must be possible also in trickle/top-off, because when usb connected, */
|
/* Start new charge cycle? This must be possible also in
|
||||||
|
trickle/top-off, because when usb connected, */
|
||||||
/* the trickle charge amount may not be enough */
|
/* the trickle charge amount may not be enough */
|
||||||
|
|
||||||
if ((charge_state == 0) || (charge_state > 1))
|
if ((charge_state == 0) || (charge_state > 1))
|
||||||
/* if battery is not full, enable charging */
|
/* if battery is not full, enable charging */
|
||||||
/* make sure charging starts if 1%-lazyness in battery_level_update() is too slow */
|
/* make sure charging starts if 1%-lazyness in
|
||||||
|
battery_level_update() is too slow */
|
||||||
if ( (battery_level() < charge_restart_level)
|
if ( (battery_level() < charge_restart_level)
|
||||||
|| (power_history[POWER_HISTORY_LEN-1] < BATTERY_LEVEL_DANGEROUS)) {
|
|| (power_history[POWER_HISTORY_LEN-1] <
|
||||||
|
BATTERY_LEVEL_DANGEROUS)) {
|
||||||
if (charge_pause) {
|
if (charge_pause) {
|
||||||
DEBUGF("power: batt level < restart level, but charge pause, not enabling\n");
|
DEBUGF("power: batt level < restart level,"
|
||||||
snprintf(power_message, POWER_MESSAGE_LEN, "chg pause %d min", charge_pause);
|
" but charge pause, not enabling\n");
|
||||||
|
snprintf(power_message, POWER_MESSAGE_LEN,
|
||||||
|
"chg pause %d min", charge_pause);
|
||||||
} else {
|
} else {
|
||||||
/* calculate max charge time depending on current battery level */
|
/* calculate max charge time depending on current
|
||||||
/* take 35% more because some more energy is used for heating up the battery */
|
battery level */
|
||||||
|
/* take 35% more because some more energy is used for
|
||||||
|
heating up the battery */
|
||||||
i = CHARGE_MAX_TIME_1500 * battery_capacity / 1500;
|
i = CHARGE_MAX_TIME_1500 * battery_capacity / 1500;
|
||||||
charge_max_time_now = i * (100 + 35 - battery_level()) / 100;
|
charge_max_time_now =
|
||||||
|
i * (100 + 35 - battery_level()) / 100;
|
||||||
if (charge_max_time_now > i) {
|
if (charge_max_time_now > i) {
|
||||||
charge_max_time_now = i;
|
charge_max_time_now = i;
|
||||||
}
|
}
|
||||||
snprintf(power_message, POWER_MESSAGE_LEN, "ChgAt %d%% max %dm", battery_level(), charge_max_time_now);
|
snprintf(power_message, POWER_MESSAGE_LEN,
|
||||||
|
"ChgAt %d%% max %dm", battery_level(),
|
||||||
|
charge_max_time_now);
|
||||||
|
|
||||||
/* enable the charger after the max time calc is done, because battery_level */
|
/* enable the charger after the max time calc is done,
|
||||||
/* depends on if the charger is on */
|
because battery_level depends on if the charger is
|
||||||
DEBUGF("power: charger inserted and battery not full, enabling\n");
|
on */
|
||||||
|
DEBUGF("power: charger inserted and battery"
|
||||||
|
" not full, enabling\n");
|
||||||
powermgmt_last_cycle_level = battery_level();
|
powermgmt_last_cycle_level = battery_level();
|
||||||
powermgmt_last_cycle_startstop_min = 0;
|
powermgmt_last_cycle_startstop_min = 0;
|
||||||
charged_time = 0;
|
charged_time = 0;
|
||||||
|
|
||||||
charger_enable(true);
|
charger_enable(true);
|
||||||
charge_state = 1; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */
|
charge_state = 1; /* 0: decharging/charger off, 1:
|
||||||
/* clear the power history so that we don't use values before
|
charge, 2: top-off, 3: trickle */
|
||||||
* discharge for the long-term delta
|
/* clear the power history so that we don't use values
|
||||||
|
before discharge for the long-term delta
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < POWER_HISTORY_LEN-1; i++)
|
for (i = 0; i < POWER_HISTORY_LEN-1; i++)
|
||||||
power_history[i] = power_history[POWER_HISTORY_LEN-1];
|
power_history[i] =
|
||||||
|
power_history[POWER_HISTORY_LEN-1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -560,7 +654,8 @@ static void power_thread(void)
|
||||||
/* show in debug menu that trickle is off */
|
/* show in debug menu that trickle is off */
|
||||||
trickle_sec = 0;
|
trickle_sec = 0;
|
||||||
charger_enable(false);
|
charger_enable(false);
|
||||||
charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */
|
charge_state = 0; /* 0: decharging/charger off, 1: charge, 2:
|
||||||
|
top-off, 3: trickle */
|
||||||
snprintf(power_message, POWER_MESSAGE_LEN, "Charger disc");
|
snprintf(power_message, POWER_MESSAGE_LEN, "Charger disc");
|
||||||
}
|
}
|
||||||
/* charger not inserted and disabled, so we're discharging */
|
/* charger not inserted and disabled, so we're discharging */
|
||||||
|
|
@ -588,11 +683,14 @@ void power_init(void)
|
||||||
memset(power_history, 0x00, sizeof(power_history));
|
memset(power_history, 0x00, sizeof(power_history));
|
||||||
/* initialize the history with a single sample to prevent level
|
/* initialize the history with a single sample to prevent level
|
||||||
flickering during the first minute of execution */
|
flickering during the first minute of execution */
|
||||||
power_history[POWER_HISTORY_LEN-1] = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000;
|
power_history[POWER_HISTORY_LEN-1] =
|
||||||
|
(adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000;
|
||||||
/* calculate the first battery level */
|
/* calculate the first battery level */
|
||||||
battery_level_update();
|
battery_level_update();
|
||||||
/* calculate the remaining time to that the info screen displays something useful */
|
/* calculate the remaining time to that the info screen displays something
|
||||||
powermgmt_est_runningtime_min = battery_level() * battery_capacity / 100 * 60 / CURRENT_NORMAL;
|
useful */
|
||||||
|
powermgmt_est_runningtime_min =
|
||||||
|
battery_level() * battery_capacity / 100 * 60 / CURRENT_NORMAL;
|
||||||
#if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */
|
#if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */
|
||||||
powermgmt_est_runningtime_min = powermgmt_est_runningtime_min * 122 / 100;
|
powermgmt_est_runningtime_min = powermgmt_est_runningtime_min * 122 / 100;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -605,7 +703,8 @@ void power_init(void)
|
||||||
charger_enable(true);
|
charger_enable(true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
create_thread(power_thread, power_stack, sizeof(power_stack), power_thread_name);
|
create_thread(power_thread, power_stack, sizeof(power_stack),
|
||||||
|
power_thread_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SIMULATOR */
|
#endif /* SIMULATOR */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue