mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-13 18:17:39 -04:00
powermgmt: Refactor battery measurement code
I've tried to clean up cruft and clarify what's being done, prior to adding new features. The behavior should be unchanged. Change-Id: If8a68b7b48173d283df981a21cdd854b714e7695
This commit is contained in:
parent
d6faef8205
commit
4506f2b58d
2 changed files with 278 additions and 301 deletions
|
@ -52,11 +52,7 @@
|
|||
#include "pcf50606.h"
|
||||
#endif
|
||||
|
||||
/** Shared by sim **/
|
||||
static int last_sent_battery_level = 100;
|
||||
/* battery level (0-100%) */
|
||||
int battery_percent = -1;
|
||||
void send_battery_level_event(void);
|
||||
static void set_sleep_timer(int seconds);
|
||||
|
||||
static bool sleeptimer_active = false;
|
||||
|
@ -83,41 +79,6 @@ void handle_auto_poweroff(void);
|
|||
static int poweroff_timeout = 0;
|
||||
static long last_event_tick = 0;
|
||||
|
||||
#if CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE
|
||||
#ifdef SIMULATOR
|
||||
int _battery_level(void) { return -1; }
|
||||
#endif
|
||||
#else
|
||||
int _battery_level(void) { return -1; }
|
||||
#endif
|
||||
|
||||
#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE
|
||||
/*
|
||||
* Average battery voltage and charger voltage, filtered via a digital
|
||||
* exponential filter (aka. exponential moving average, scaled):
|
||||
* avgbat = y[n] = (N-1)/N*y[n-1] + x[n]. battery_millivolts = y[n] / N.
|
||||
*/
|
||||
static unsigned int avgbat;
|
||||
/* filtered battery voltage, millivolts */
|
||||
static unsigned int battery_millivolts;
|
||||
#else
|
||||
#ifndef SIMULATOR
|
||||
int _battery_voltage(void) { return -1; }
|
||||
const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11];
|
||||
const unsigned short percent_to_volt_charge[11];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !(CONFIG_BATTERY_MEASURE & TIME_MEASURE)
|
||||
#ifdef CURRENT_NORMAL
|
||||
static int powermgmt_est_runningtime_min;
|
||||
int _battery_time(void) { return powermgmt_est_runningtime_min; }
|
||||
#else
|
||||
int _battery_time(void) { return -1; }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* default value, mAh */
|
||||
#if BATTERY_CAPACITY_INC > 0
|
||||
static int battery_capacity = BATTERY_CAPACITY_DEFAULT;
|
||||
#else
|
||||
|
@ -141,170 +102,71 @@ static char power_stack[DEFAULT_STACK_SIZE/2];
|
|||
#endif
|
||||
static const char power_thread_name[] = "power";
|
||||
|
||||
|
||||
static int voltage_to_battery_level(int battery_millivolts);
|
||||
static void battery_status_update(void);
|
||||
|
||||
#if BATTERY_TYPES_COUNT > 1
|
||||
void set_battery_type(int type)
|
||||
{
|
||||
if (type != battery_type) {
|
||||
if ((unsigned)type >= BATTERY_TYPES_COUNT)
|
||||
type = 0;
|
||||
|
||||
battery_type = type;
|
||||
battery_status_update(); /* recalculate the battery status */
|
||||
}
|
||||
}
|
||||
#if !(CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE)
|
||||
int _battery_level(void) { return -1; }
|
||||
#endif
|
||||
static int percent_now; /* Cached to avoid polling too often */
|
||||
|
||||
#if BATTERY_CAPACITY_INC > 0
|
||||
void set_battery_capacity(int capacity)
|
||||
{
|
||||
if (capacity > BATTERY_CAPACITY_MAX)
|
||||
capacity = BATTERY_CAPACITY_MAX;
|
||||
if (capacity < BATTERY_CAPACITY_MIN)
|
||||
capacity = BATTERY_CAPACITY_MIN;
|
||||
|
||||
battery_capacity = capacity;
|
||||
|
||||
battery_status_update(); /* recalculate the battery status */
|
||||
}
|
||||
#endif
|
||||
|
||||
int get_battery_capacity(void)
|
||||
{
|
||||
return battery_capacity;
|
||||
}
|
||||
|
||||
int battery_time(void)
|
||||
{
|
||||
#if !(CONFIG_BATTERY_MEASURE & TIME_MEASURE)
|
||||
/* Note: This should not really be possible but it might occur
|
||||
* as a degenerate case for targets that don't define any battery
|
||||
* capacity at all..? */
|
||||
if(battery_capacity <= 0)
|
||||
return -1;
|
||||
int _battery_time(void) { return -1; }
|
||||
#endif
|
||||
#if (CONFIG_BATTERY_MEASURE & TIME_MEASURE) || defined(CURRENT_NORMAL)
|
||||
static int time_now; /* Cached to avoid polling too often */
|
||||
#endif
|
||||
|
||||
return _battery_time();
|
||||
}
|
||||
#if !(CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE)
|
||||
int _battery_voltage(void) { return -1; }
|
||||
#else
|
||||
/* Data for the digital exponential filter */
|
||||
static int voltage_avg, voltage_now;
|
||||
#endif
|
||||
|
||||
/* Returns battery level in percent */
|
||||
/* The battery level can be obtained in two ways. If the target reports
|
||||
* voltage, the battery level can be estminated using percent_to_volt_*
|
||||
* curves. If the target can report the percentage directly, then that
|
||||
* will be used instead of voltage-based estimation. */
|
||||
int battery_level(void)
|
||||
{
|
||||
#ifdef HAVE_BATTERY_SWITCH
|
||||
if ((power_input_status() & POWER_INPUT_BATTERY) == 0)
|
||||
return -1;
|
||||
#endif
|
||||
return battery_percent;
|
||||
|
||||
return percent_now;
|
||||
}
|
||||
|
||||
/* Tells if the battery level is safe for disk writes */
|
||||
bool battery_level_safe(void)
|
||||
/* The time remaining to full charge/discharge can be provided by the
|
||||
* target if it has an accurate way of doing this. Otherwise, if the
|
||||
* target defines a valid battery capacity and can report the charging
|
||||
* and discharging current, the time remaining will be estimated based
|
||||
* on the battery level and the actual current usage. */
|
||||
int battery_time(void)
|
||||
{
|
||||
#if defined(NO_LOW_BATTERY_SHUTDOWN)
|
||||
return true;
|
||||
#elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE
|
||||
return (battery_percent > 0);
|
||||
#elif defined(HAVE_BATTERY_SWITCH)
|
||||
/* Cannot rely upon the battery reading to be valid and the
|
||||
* device could be powered externally. */
|
||||
return input_millivolts() > battery_level_dangerous[battery_type];
|
||||
#if (CONFIG_BATTERY_MEASURE & TIME_MEASURE) || defined(CURRENT_NORMAL)
|
||||
return time_now;
|
||||
#else
|
||||
return battery_millivolts > battery_level_dangerous[battery_type];
|
||||
#endif
|
||||
}
|
||||
|
||||
/* look into the percent_to_volt_* table and get a realistic battery level */
|
||||
static int voltage_to_percent(int voltage, const short* table)
|
||||
{
|
||||
if (voltage <= table[0]) {
|
||||
return 0;
|
||||
}
|
||||
else if (voltage >= table[10]) {
|
||||
return 100;
|
||||
}
|
||||
else {
|
||||
/* search nearest value */
|
||||
int i = 0;
|
||||
|
||||
while (i < 10 && table[i+1] < voltage)
|
||||
i++;
|
||||
|
||||
/* interpolate linear between the smaller and greater value */
|
||||
/* Tens digit, 10% per entry, ones digit: interpolated */
|
||||
return i*10 + (voltage - table[i])*10 / (table[i+1] - table[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* update battery level and estimated runtime, called once per minute or
|
||||
* when battery capacity / type settings are changed */
|
||||
static int voltage_to_battery_level(int battery_millivolts)
|
||||
{
|
||||
int level;
|
||||
|
||||
if (battery_millivolts < 0)
|
||||
return -1;
|
||||
|
||||
#if CONFIG_CHARGING >= CHARGING_MONITOR
|
||||
if (charging_state()) {
|
||||
/* battery level is defined to be < 100% until charging is finished */
|
||||
level = voltage_to_percent(battery_millivolts,
|
||||
percent_to_volt_charge);
|
||||
if (level > 99)
|
||||
level = 99;
|
||||
}
|
||||
else
|
||||
#endif /* CONFIG_CHARGING >= CHARGING_MONITOR */
|
||||
{
|
||||
/* DISCHARGING or error state */
|
||||
level = voltage_to_percent(battery_millivolts,
|
||||
percent_to_volt_discharge[battery_type]);
|
||||
}
|
||||
|
||||
return level;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void battery_status_update(void)
|
||||
/* Battery voltage should always be reported if available, but it is
|
||||
* optional if the the target reports battery percentage directly. */
|
||||
int battery_voltage(void)
|
||||
{
|
||||
int millivolt = battery_voltage();
|
||||
int level = _battery_level();
|
||||
|
||||
if (level < 0)
|
||||
level = voltage_to_battery_level(millivolt);
|
||||
|
||||
#ifdef CURRENT_NORMAL
|
||||
int current = battery_current();
|
||||
|
||||
#if CONFIG_CHARGING >= CHARGING_MONITOR
|
||||
if (charging_state()) {
|
||||
/* charging: remaining charging time */
|
||||
if(current > 0) {
|
||||
powermgmt_est_runningtime_min =
|
||||
(100 - level) * battery_capacity * 60 / 100 / current;
|
||||
}
|
||||
}
|
||||
else
|
||||
#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE
|
||||
return voltage_now;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
/* discharging: remaining running time */
|
||||
if (level >= 0 && current > 0) {
|
||||
powermgmt_est_runningtime_min =
|
||||
(level + battery_percent) * battery_capacity * 60 / 200 / current;
|
||||
}
|
||||
|
||||
if (powermgmt_est_runningtime_min < 0 || current <= 0)
|
||||
powermgmt_est_runningtime_min = 0;
|
||||
#endif
|
||||
|
||||
battery_percent = level;
|
||||
send_battery_level_event();
|
||||
}
|
||||
|
||||
#ifdef CURRENT_NORMAL
|
||||
/* Battery current can be estimated if the target defines CURRENT_NORMAL
|
||||
* as the number of milliamps usually consumed by the device in a normal
|
||||
* state. The target can also define other CURRENT_* values to estimate
|
||||
* the power consumed by the backlight, remote display, SPDIF, etc. */
|
||||
int battery_current(void)
|
||||
{
|
||||
#if defined(CURRENT_NORMAL)
|
||||
int current = CURRENT_NORMAL;
|
||||
|
||||
#ifndef BOOTLOADER
|
||||
|
@ -356,8 +218,207 @@ int battery_current(void)
|
|||
#endif /* BOOTLOADER */
|
||||
|
||||
return current;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Initialize the battery voltage filter. This is called once
|
||||
* by the power thread before entering the main polling loop. */
|
||||
static void average_init(void)
|
||||
{
|
||||
#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE
|
||||
voltage_now = _battery_voltage() + 15;
|
||||
|
||||
/* The battery voltage is usually a little lower directly after
|
||||
turning on, because the disk was used heavily. Raise it by 5% */
|
||||
#ifdef HAVE_DISK_STORAGE
|
||||
#if CONFIG_CHARGING
|
||||
if(!charger_inserted())
|
||||
#endif
|
||||
{
|
||||
voltage_now += (percent_to_volt_discharge[battery_type][6] -
|
||||
percent_to_volt_discharge[battery_type][5]) / 2;
|
||||
}
|
||||
#endif /* HAVE_DISK_STORAGE */
|
||||
|
||||
voltage_avg = voltage_now * BATT_AVE_SAMPLES;
|
||||
#endif /* CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE */
|
||||
}
|
||||
|
||||
/* Sample the battery voltage and update the filter.
|
||||
* Updated once every POWER_THREAD_STEP_TICKS. */
|
||||
static void average_step(bool low_battery)
|
||||
{
|
||||
#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE
|
||||
int millivolts = _battery_voltage();
|
||||
if(low_battery) {
|
||||
voltage_now = (millivolts + voltage_now + 1) / 2;
|
||||
voltage_avg += voltage_now - voltage_avg / BATT_AVE_SAMPLES;
|
||||
} else {
|
||||
voltage_avg += millivolts - voltage_avg / BATT_AVE_SAMPLES;
|
||||
voltage_now = voltage_avg / BATT_AVE_SAMPLES;
|
||||
}
|
||||
#else
|
||||
(void)low_battery;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Send system battery level update events on reaching certain significant
|
||||
* levels. This is called by battery_status_update() and does not have to
|
||||
* be called separately. */
|
||||
static void send_battery_level_event(int percent)
|
||||
{
|
||||
static const int levels[] = { 5, 15, 30, 50, 0 };
|
||||
const int *level = levels;
|
||||
|
||||
while (*level)
|
||||
{
|
||||
if (percent <= *level && last_sent_battery_level > *level) {
|
||||
last_sent_battery_level = *level;
|
||||
queue_broadcast(SYS_BATTERY_UPDATE, last_sent_battery_level);
|
||||
break;
|
||||
}
|
||||
|
||||
level++;
|
||||
}
|
||||
}
|
||||
|
||||
#if !(CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE)
|
||||
/* Look into the percent_to_volt_* table and estimate the battery level. */
|
||||
static int voltage_to_percent(int voltage, const short* table)
|
||||
{
|
||||
if (voltage <= table[0]) {
|
||||
return 0;
|
||||
}
|
||||
else if (voltage >= table[10]) {
|
||||
return 100;
|
||||
}
|
||||
else {
|
||||
/* search nearest value */
|
||||
int i = 0;
|
||||
|
||||
while (i < 10 && table[i+1] < voltage)
|
||||
i++;
|
||||
|
||||
/* interpolate linear between the smaller and greater value */
|
||||
/* Tens digit, 10% per entry, ones digit: interpolated */
|
||||
return i*10 + (voltage - table[i])*10 / (table[i+1] - table[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert voltage to a battery level percentage using the appropriate
|
||||
* percent_to_volt_* lookup table. */
|
||||
static int voltage_to_battery_level(int millivolts)
|
||||
{
|
||||
int level;
|
||||
|
||||
if (millivolts < 0)
|
||||
return -1;
|
||||
|
||||
#if CONFIG_CHARGING >= CHARGING_MONITOR
|
||||
if (charging_state()) {
|
||||
/* battery level is defined to be < 100% until charging is finished */
|
||||
level = voltage_to_percent(millivolts, percent_to_volt_charge);
|
||||
if (level > 99)
|
||||
level = 99;
|
||||
}
|
||||
else
|
||||
#endif /* CONFIG_CHARGING >= CHARGING_MONITOR */
|
||||
{
|
||||
/* DISCHARGING or error state */
|
||||
level = voltage_to_percent(millivolts, percent_to_volt_discharge[battery_type]);
|
||||
}
|
||||
|
||||
return level;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update battery percentage and time remaining information.
|
||||
*
|
||||
* This will be called by the power thread after polling new battery data.
|
||||
* It must also be called if the battery type or capacity changes.
|
||||
*/
|
||||
static void battery_status_update(void)
|
||||
{
|
||||
#if CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE
|
||||
int level = _battery_level();
|
||||
#elif CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE
|
||||
int level = voltage_to_battery_level(voltage_now);
|
||||
#else
|
||||
/* This should be a compile time error? */
|
||||
int level = -1;
|
||||
#endif
|
||||
|
||||
#if CONFIG_BATTERY_MEASURE & TIME_MEASURE
|
||||
time_now = _battery_time();
|
||||
#elif defined(CURRENT_NORMAL)
|
||||
int current = battery_current();
|
||||
if(level >= 0 && current > 0 && battery_capacity > 0) {
|
||||
#if CONFIG_CHARGING >= CHARGING_MONITOR
|
||||
if (charging_state())
|
||||
time_now = (100 - level) * battery_capacity * 60 / 100 / current;
|
||||
else
|
||||
#endif
|
||||
time_now = (level + percent_now) * battery_capacity * 60 / 200 / current;
|
||||
} else {
|
||||
/* not enough information to calculate time remaining */
|
||||
time_now = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
percent_now = level;
|
||||
send_battery_level_event(level);
|
||||
}
|
||||
|
||||
#if BATTERY_TYPES_COUNT > 1
|
||||
void set_battery_type(int type)
|
||||
{
|
||||
if(type < 0 || type > BATTERY_TYPES_COUNT)
|
||||
type = 0;
|
||||
|
||||
if (type != battery_type) {
|
||||
battery_type = type;
|
||||
battery_status_update(); /* recalculate the battery status */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BATTERY_CAPACITY_INC > 0
|
||||
void set_battery_capacity(int capacity)
|
||||
{
|
||||
if (capacity > BATTERY_CAPACITY_MAX)
|
||||
capacity = BATTERY_CAPACITY_MAX;
|
||||
if (capacity < BATTERY_CAPACITY_MIN)
|
||||
capacity = BATTERY_CAPACITY_MIN;
|
||||
|
||||
if (capacity != battery_capacity) {
|
||||
battery_capacity = capacity;
|
||||
battery_status_update(); /* recalculate the battery status */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int get_battery_capacity(void)
|
||||
{
|
||||
return battery_capacity;
|
||||
}
|
||||
|
||||
/* Tells if the battery level is safe for disk writes */
|
||||
bool battery_level_safe(void)
|
||||
{
|
||||
#if defined(NO_LOW_BATTERY_SHUTDOWN)
|
||||
return true;
|
||||
#elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE
|
||||
return percent_now > 0;
|
||||
#elif defined(HAVE_BATTERY_SWITCH)
|
||||
/* Cannot rely upon the battery reading to be valid and the
|
||||
* device could be powered externally. */
|
||||
return input_millivolts() > battery_level_dangerous[battery_type];
|
||||
#else
|
||||
return voltage_now > battery_level_dangerous[battery_type];
|
||||
#endif
|
||||
}
|
||||
#endif /* CURRENT_NORMAL */
|
||||
|
||||
/* Check to see whether or not we've received an alarm in the last second */
|
||||
#ifdef HAVE_RTC_ALARM
|
||||
|
@ -374,13 +435,13 @@ bool query_force_shutdown(void)
|
|||
#if defined(NO_LOW_BATTERY_SHUTDOWN)
|
||||
return false;
|
||||
#elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE
|
||||
return battery_percent == 0;
|
||||
return percent_now == 0;
|
||||
#elif defined(HAVE_BATTERY_SWITCH)
|
||||
/* Cannot rely upon the battery reading to be valid and the
|
||||
* device could be powered externally. */
|
||||
return input_millivolts() < battery_level_shutoff[battery_type];
|
||||
#else
|
||||
return battery_millivolts < battery_level_shutoff[battery_type];
|
||||
return voltage_now < battery_level_shutoff[battery_type];
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -391,8 +452,8 @@ bool query_force_shutdown(void)
|
|||
*/
|
||||
void reset_battery_filter(int millivolts)
|
||||
{
|
||||
avgbat = millivolts * BATT_AVE_SAMPLES;
|
||||
battery_millivolts = millivolts;
|
||||
voltage_avg = millivolts * BATT_AVE_SAMPLES;
|
||||
voltage_now = millivolts;
|
||||
battery_status_update();
|
||||
}
|
||||
#endif /* HAVE_BATTERY_SWITCH */
|
||||
|
@ -529,88 +590,14 @@ static inline bool detect_charger(unsigned int pwr)
|
|||
|
||||
|
||||
#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE
|
||||
/* Returns filtered battery voltage [millivolts] */
|
||||
int battery_voltage(void)
|
||||
{
|
||||
return battery_millivolts;
|
||||
}
|
||||
|
||||
static void average_init(void)
|
||||
{
|
||||
/* initialize the voltages for the exponential filter */
|
||||
avgbat = _battery_voltage() + 15;
|
||||
|
||||
#ifdef HAVE_DISK_STORAGE /* this adjustment is only needed for HD based */
|
||||
/* The battery voltage is usually a little lower directly after
|
||||
turning on, because the disk was used heavily. Raise it by 5% */
|
||||
#if CONFIG_CHARGING
|
||||
if (!charger_inserted()) /* only if charger not connected */
|
||||
#endif
|
||||
{
|
||||
avgbat += (percent_to_volt_discharge[battery_type][6] -
|
||||
percent_to_volt_discharge[battery_type][5]) / 2;
|
||||
}
|
||||
#endif /* HAVE_DISK_STORAGE */
|
||||
|
||||
avgbat = avgbat * BATT_AVE_SAMPLES;
|
||||
battery_millivolts = power_history[0] = avgbat / BATT_AVE_SAMPLES;
|
||||
}
|
||||
|
||||
static void average_step(void)
|
||||
{
|
||||
avgbat += _battery_voltage() - avgbat / BATT_AVE_SAMPLES;
|
||||
/*
|
||||
* battery_millivolts is the millivolt-scaled filtered battery value.
|
||||
*/
|
||||
battery_millivolts = avgbat / BATT_AVE_SAMPLES;
|
||||
}
|
||||
|
||||
static void average_step_low(void)
|
||||
{
|
||||
battery_millivolts = (_battery_voltage() + battery_millivolts + 1) / 2;
|
||||
avgbat += battery_millivolts - avgbat / BATT_AVE_SAMPLES;
|
||||
}
|
||||
|
||||
static void init_battery_percent(void)
|
||||
{
|
||||
#if CONFIG_CHARGING
|
||||
if (charger_inserted()) {
|
||||
battery_percent = voltage_to_percent(battery_millivolts,
|
||||
percent_to_volt_charge);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
battery_percent = voltage_to_percent(battery_millivolts,
|
||||
percent_to_volt_discharge[battery_type]);
|
||||
battery_percent += battery_percent < 100;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int power_hist_item(void)
|
||||
{
|
||||
return battery_millivolts;
|
||||
return voltage_now;
|
||||
}
|
||||
#define power_history_unit() battery_millivolts
|
||||
|
||||
#else
|
||||
int battery_voltage(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void average_init(void) {}
|
||||
static void average_step(void) {}
|
||||
static void average_step_low(void) {}
|
||||
static void init_battery_percent(void)
|
||||
{
|
||||
battery_percent = _battery_level();
|
||||
}
|
||||
|
||||
static int power_hist_item(void)
|
||||
{
|
||||
return battery_percent;
|
||||
return percent_now;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -651,13 +638,11 @@ static inline void power_thread_step(void)
|
|||
|| charger_input_state == CHARGER
|
||||
#endif
|
||||
) {
|
||||
average_step();
|
||||
/* update battery status every time an update is available */
|
||||
average_step(false);
|
||||
battery_status_update();
|
||||
}
|
||||
else if (battery_percent < 8) {
|
||||
average_step_low();
|
||||
/* update battery status every time an update is available */
|
||||
else if (percent_now < 8) {
|
||||
average_step(true);
|
||||
battery_status_update();
|
||||
|
||||
/*
|
||||
|
@ -703,7 +688,7 @@ static void power_thread(void)
|
|||
/* initialize voltage averaging (if available) */
|
||||
average_init();
|
||||
/* get initial battery level value (in %) */
|
||||
init_battery_percent();
|
||||
battery_status_update();
|
||||
/* get some initial data for the power curve */
|
||||
collect_power_history();
|
||||
|
||||
|
@ -848,25 +833,6 @@ void cancel_shutdown(void)
|
|||
shutdown_timeout = 0;
|
||||
}
|
||||
|
||||
/* Send system battery level update events on reaching certain significant
|
||||
levels. This must be called after battery_percent has been updated. */
|
||||
void send_battery_level_event(void)
|
||||
{
|
||||
static const int levels[] = { 5, 15, 30, 50, 0 };
|
||||
const int *level = levels;
|
||||
|
||||
while (*level)
|
||||
{
|
||||
if (battery_percent <= *level && last_sent_battery_level > *level) {
|
||||
last_sent_battery_level = *level;
|
||||
queue_broadcast(SYS_BATTERY_UPDATE, last_sent_battery_level);
|
||||
break;
|
||||
}
|
||||
|
||||
level++;
|
||||
}
|
||||
}
|
||||
|
||||
void set_sleeptimer_duration(int minutes)
|
||||
{
|
||||
set_sleep_timer(minutes * 60);
|
||||
|
|
|
@ -39,9 +39,10 @@
|
|||
#define POWER_AFTER_CHARGE_TICKS (8 * HZ)
|
||||
#endif
|
||||
|
||||
extern int battery_percent;
|
||||
static bool charging = false;
|
||||
static unsigned int battery_millivolts = BATT_MAXMVOLT;
|
||||
static unsigned int batt_millivolts = BATT_MAXMVOLT;
|
||||
static unsigned int batt_percent = 100;
|
||||
static unsigned int batt_runtime = BATT_MAXRUNTIME;
|
||||
|
||||
void powermgmt_init_target(void) {}
|
||||
|
||||
|
@ -54,7 +55,7 @@ static void battery_status_update(void)
|
|||
static unsigned int ext_power_until_tick = 0;
|
||||
#endif
|
||||
|
||||
if TIME_BEFORE(current_tick, update_after_tick)
|
||||
if(TIME_BEFORE(current_tick, update_after_tick))
|
||||
return;
|
||||
|
||||
update_after_tick = current_tick + HZ;
|
||||
|
@ -72,10 +73,9 @@ static void battery_status_update(void)
|
|||
#endif
|
||||
|
||||
if (charging) {
|
||||
battery_millivolts += BATT_CHARGE_STEP;
|
||||
if (battery_millivolts >= BATT_MAXMVOLT) {
|
||||
batt_millivolts += BATT_CHARGE_STEP;
|
||||
if (batt_millivolts >= BATT_MAXMVOLT) {
|
||||
charging = false;
|
||||
battery_percent = 100;
|
||||
#if CONFIG_CHARGING >= CHARGING_MONITOR
|
||||
/* Keep external power until tick */
|
||||
ext_power_until_tick = current_tick + POWER_AFTER_CHARGE_TICKS;
|
||||
|
@ -83,23 +83,20 @@ static void battery_status_update(void)
|
|||
/* Pretend the charger was disconnected */
|
||||
charger_input_state = CHARGER_UNPLUGGED;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
battery_millivolts -= BATT_DISCHARGE_STEP;
|
||||
if (battery_millivolts <= BATT_MINMVOLT) {
|
||||
batt_millivolts -= BATT_DISCHARGE_STEP;
|
||||
if (batt_millivolts <= BATT_MINMVOLT) {
|
||||
charging = true;
|
||||
battery_percent = 0;
|
||||
#if CONFIG_CHARGING
|
||||
/* Pretend the charger was connected */
|
||||
charger_input_state = CHARGER_PLUGGED;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
battery_percent = 100 * (battery_millivolts - BATT_MINMVOLT) /
|
||||
(BATT_MAXMVOLT - BATT_MINMVOLT);
|
||||
batt_percent = (batt_millivolts - BATT_MINMVOLT) / (BATT_MAXMVOLT - BATT_MINMVOLT);
|
||||
batt_runtime = batt_percent * BATT_MAXRUNTIME;
|
||||
}
|
||||
|
||||
const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = { 3200 };
|
||||
|
@ -111,15 +108,28 @@ const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
|
|||
const unsigned short percent_to_volt_charge[11] =
|
||||
{ 3300, 3400, 3500, 3600, 3700, 3800, 3900, 4000, 4100, 4200, 4300 };
|
||||
|
||||
#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE
|
||||
int _battery_voltage(void)
|
||||
{
|
||||
battery_status_update();
|
||||
return battery_millivolts;
|
||||
return batt_millivolts;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE
|
||||
int _battery_level(void)
|
||||
{
|
||||
battery_status_update();
|
||||
return batt_percent;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (CONFIG_BATTERY_MEASURE & TIME_MEASURE)
|
||||
static int powermgmt_est_runningtime_min;
|
||||
int _battery_time(void) { return powermgmt_est_runningtime_min; }
|
||||
int _battery_time(void)
|
||||
{
|
||||
battery_status_update();
|
||||
return batt_runtime;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_CHARGING
|
||||
|
@ -169,6 +179,7 @@ unsigned int input_millivolts(void)
|
|||
/* Just return a safe value if battery isn't connected */
|
||||
return 4050;
|
||||
}
|
||||
return battery_voltage();;
|
||||
|
||||
return battery_voltage();
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue