📄 powermgmt.c
字号:
/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id: powermgmt.c,v 1.45 2004/02/05 13:44:03 linusnielsen Exp $ * * Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/#include "config.h"#include "sh7034.h"#include "kernel.h"#include "thread.h"#include "system.h"#include "debug.h"#include "panic.h"#include "adc.h"#include "string.h"#include "sprintf.h"#include "ata.h"#include "power.h"#include "button.h"#include "ata.h"#include "mpeg.h"#include "usb.h"#include "powermgmt.h"#include "backlight.h"#ifdef HAVE_FMRADIO#include "fmradio.h"#endif#ifdef SIMULATORint battery_level(void){ return 75;}int battery_time(void){ return 500;}bool battery_level_safe(void){ return battery_level() >= 10;}void set_poweroff_timeout(int timeout){ (void)timeout;}void set_battery_capacity(int capacity){ (void)capacity;}void set_car_adapter_mode(bool setting){ (void)setting;}#else /* not SIMULATOR */int battery_capacity = 1500; /* only a default value */int battery_level_cached = -1; /* battery level of this minute, updated once per minute */static bool car_adapter_mode_enabled = false;static int poweroff_idle_timeout_value[15] ={ 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 */{#ifdef HAVE_LIION /* measured values */ 260, 285, 295, 303, 311, 320, 330, 345, 360, 380, 400#else /* NiMH */ /* original values were taken directly after charging, but it should show 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 */#endif};void set_battery_capacity(int capacity){ battery_capacity = capacity; if (battery_capacity > BATTERY_CAPACITY_MAX) battery_capacity = BATTERY_CAPACITY_MAX; if (battery_capacity < 1500) battery_capacity = 1500;}#if defined(HAVE_CHARGE_CTRL) || defined(HAVE_LIION)int charge_state = 0; /* at the beginning, the charger does nothing */#endif#ifdef HAVE_CHARGE_CTRLchar power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in debug menu */char charge_restart_level = CHARGE_RESTART_HI; /* level at which charging 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;int trickle_sec = 0; /* how many seconds should the charger be enabled per minute for trickle charging? */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 until someone measures voltages over a charging cycle */ 476, 544, 551, 556, 561, 564, 566, 576, 582, 584, 585 /* NiMH */};void enable_trickle_charge(bool on){ trickle_charge_enabled = on;}#endif /* HAVE_CHARGE_CTRL */static char power_stack[DEFAULT_STACK_SIZE];static char power_thread_name[] = "power";static int poweroff_timeout = 0;static long last_charge_time = 0;int powermgmt_est_runningtime_min = -1;static bool sleeptimer_active = false;static unsigned long sleeptimer_endtick;unsigned short power_history[POWER_HISTORY_LEN];int battery_time(void){ return powermgmt_est_runningtime_min;}/* look into the percent_to_volt_* table and get a realistic battery level percentage */int voltage_to_percent(int voltage, int* 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 */ return i * 10 /* 10th */ + (voltage - table[i]) * 10 / (table[i+1] - table[i]); /* 1th */ }}/* update battery level, called only once per minute */void battery_level_update(void){ int level = 0; int c = 0; int i; /* calculate maximum over last 3 minutes (skip empty samples) */ for (i = 0; i < 3; i++) if (power_history[POWER_HISTORY_LEN-1-i] > c) c = power_history[POWER_HISTORY_LEN-1-i]; if (c) level = c; else /* history was empty, get a fresh sample */ level = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000; if(level > BATTERY_LEVEL_FULL) level = BATTERY_LEVEL_FULL; if(level < BATTERY_LEVEL_EMPTY) level = BATTERY_LEVEL_EMPTY;#ifdef HAVE_CHARGE_CTRL if (charge_state == 0) { /* 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 {/* in trickle charge, the battery is per definition 100% full */ battery_level_cached = level = 100; }#else level = voltage_to_percent(level, percent_to_volt_decharge); /* always use the decharge table */#endif 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 raise it by 5 % */ battery_level_cached = (level > 95) ? 100 : level + 5; } else { /* the level is allowed to be -1 of the last value when usb not connected and to be -3 of the last value when usb is connected */ if (usb_inserted()) { if (level < battery_level_cached - 3) level = battery_level_cached - 3; } else { if (level < battery_level_cached - 1) level = battery_level_cached - 1; } battery_level_cached = level; }}/* Returns battery level in percent */int battery_level(void){#ifdef HAVE_CHARGE_CTRL if ((charge_state==1) && (battery_level_cached==100)) return 99;#endif return battery_level_cached;}/* Tells if the battery level is safe for disk writes */bool battery_level_safe(void){ /* I'm pretty sure we don't want an average over a long time here */ if (power_history[POWER_HISTORY_LEN-1]) return power_history[POWER_HISTORY_LEN-1] > BATTERY_LEVEL_DANGEROUS; else return adc_read(ADC_UNREG_POWER) > (BATTERY_LEVEL_DANGEROUS * 10000) / BATTERY_SCALE_FACTOR;}void set_poweroff_timeout(int timeout){ poweroff_timeout = timeout;}void set_sleep_timer(int seconds){ if(seconds) { sleeptimer_active = true; sleeptimer_endtick = current_tick + seconds * HZ; } else { sleeptimer_active = false; sleeptimer_endtick = 0; }}int get_sleep_timer(void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -