Simplify powermgmt thread loops so it calls functions turn (no more power_thread_sleep). Do other target-friendly simplifications, generic battery switch handling and split sim-specific code. Whoever can, please verify charging on the Archos Recorder (due to change in the charger duty cycle code).

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19579 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2008-12-24 16:58:41 +00:00
parent 0f9729739f
commit 3157e13956
34 changed files with 1337 additions and 1124 deletions

View file

@ -1603,10 +1603,10 @@ static bool view_battery(void)
lcd_puts(0, 2, buf);
#endif
#if CONFIG_CHARGING
#if CONFIG_CHARGING == CHARGING_CONTROL
#if defined ARCHOS_RECORDER
snprintf(buf, 30, "Chgr: %s %s",
charger_inserted() ? "present" : "absent",
charger_enabled ? "on" : "off");
charger_enabled() ? "on" : "off");
lcd_puts(0, 3, buf);
snprintf(buf, 30, "short delta: %d", short_delta);
lcd_puts(0, 5, buf);
@ -1616,13 +1616,11 @@ static bool view_battery(void)
snprintf(buf, 30, "USB Inserted: %s",
usb_inserted() ? "yes" : "no");
lcd_puts(0, 8, buf);
#if defined IRIVER_H300_SERIES
#elif defined IRIVER_H300_SERIES
snprintf(buf, 30, "USB Charging Enabled: %s",
usb_charging_enabled() ? "yes" : "no");
lcd_puts(0, 9, buf);
#endif
#else /* CONFIG_CHARGING != CHARGING_CONTROL */
#if defined IPOD_NANO || defined IPOD_VIDEO
#elif defined IPOD_NANO || defined IPOD_VIDEO
int usb_pwr = (GPIOL_INPUT_VAL & 0x10)?true:false;
int ext_pwr = (GPIOL_INPUT_VAL & 0x08)?false:true;
int dock = (GPIOA_INPUT_VAL & 0x10)?true:false;
@ -1644,12 +1642,8 @@ static bool view_battery(void)
snprintf(buf, 30, "Headphone: %s",
headphone ? "connected" : "disconnected");
lcd_puts(0, 7, buf);
#else
snprintf(buf, 30, "Charger: %s",
charger_inserted() ? "present" : "absent");
lcd_puts(0, 3, buf);
#if defined TOSHIBA_GIGABEAT_S
int line = 4;
#elif defined TOSHIBA_GIGABEAT_S
int line = 3;
unsigned int st;
static const unsigned char * const chrgstate_strings[] =
@ -1663,6 +1657,10 @@ static bool view_battery(void)
"<unknown>",
};
snprintf(buf, 30, "Charger: %s",
charger_inserted() ? "present" : "absent");
lcd_puts(0, line++, buf);
st = power_input_status() &
(POWER_INPUT_CHARGER | POWER_INPUT_BATTERY);
snprintf(buf, 30, "%s%s",
@ -1730,9 +1728,11 @@ static bool view_battery(void)
}
lcd_puts(0, line++, buf);
#endif /* defined TOSHIBA_GIGABEAT_S */
#endif /* defined IPOD_NANO || defined IPOD_VIDEO */
#endif /* CONFIG_CHARGING != CHARGING_CONTROL */
#else
snprintf(buf, 30, "Charger: %s",
charger_inserted() ? "present" : "absent");
lcd_puts(0, 3, buf);
#endif /* target type */
#endif /* CONFIG_CHARGING */
break;
@ -1750,7 +1750,7 @@ static bool view_battery(void)
case 3: /* remaining time estimation: */
#if CONFIG_CHARGING == CHARGING_CONTROL
#ifdef ARCHOS_RECORDER
snprintf(buf, 30, "charge_state: %d", charge_state);
lcd_puts(0, 0, buf);
@ -1765,7 +1765,7 @@ static bool view_battery(void)
snprintf(buf, 30, "Trickle sec: %d/60", trickle_sec);
lcd_puts(0, 4, buf);
#endif /* CONFIG_CHARGING == CHARGING_CONTROL */
#endif /* ARCHOS_RECORDER */
snprintf(buf, 30, "Last PwrHist: %d.%03dV",
power_history[0] / 1000,

View file

@ -27,6 +27,7 @@
#include "lang.h"
#include "action.h"
#include "settings.h"
#include "power.h"
#include "powermgmt.h"
#include "menu.h"
#include "misc.h"
@ -199,15 +200,14 @@ static char* info_getname(int selected_item, void *data,
if (charge_state == CHARGING)
return (char *)str(LANG_BATTERY_CHARGE);
else
#if CONFIG_CHARGING == CHARGING_CONTROL
#ifdef ARCHOS_RECORDER
if (charge_state == TOPOFF)
return (char *)str(LANG_BATTERY_TOPOFF_CHARGE);
else
#endif
if (charge_state == TRICKLE)
else if (charge_state == TRICKLE)
return (char *)str(LANG_BATTERY_TRICKLE_CHARGE);
else
#endif
#endif /* ARCHOS_RECORDER */
#endif /* CONFIG_CHARGING = */
if (battery_level() >= 0)
snprintf(buffer, buffer_len, (char *)str(LANG_BATTERY_TIME),
battery_level(), battery_time() / 60, battery_time() % 60);
@ -282,22 +282,21 @@ static int info_speak_item(int selected_item, void * data)
}
case INFO_BATTERY: /* battery */
#if CONFIG_CHARGING == CHARGING_SIMPLE
if (charger_input_state == CHARGER)
if (charger_inserted())
talk_id(LANG_BATTERY_CHARGE, true);
else
#elif CONFIG_CHARGING >= CHARGING_MONITOR
if (charge_state == CHARGING)
talk_id(LANG_BATTERY_CHARGE, true);
else
#if CONFIG_CHARGING == CHARGING_CONTROL
#ifdef ARCHOS_RECORDER
if (charge_state == TOPOFF)
talk_id(LANG_BATTERY_TOPOFF_CHARGE, true);
else
#endif
if (charge_state == TRICKLE)
else if (charge_state == TRICKLE)
talk_id(LANG_BATTERY_TRICKLE_CHARGE, true);
else
#endif
#endif /* ARCHOS_RECORDER */
#endif /* CONFIG_CHARGING = */
if (battery_level() >= 0)
{
talk_id(LANG_BATTERY_TIME, false);

View file

@ -209,8 +209,7 @@ static void charging_display_info(bool animate)
lcd_puts(0, 7, buf);
}
#if CONFIG_CHARGING == CHARGING_CONTROL
#ifdef ARCHOS_RECORER
snprintf(buf, 32, "Charge mode:");
lcd_puts(0, 2, buf);
@ -224,10 +223,9 @@ static void charging_display_info(bool animate)
snprintf(buf, 32, "not charging");
lcd_puts(0, 3, buf);
if (!charger_enabled)
if (!charger_enabled())
animate = false;
#endif /* CONFIG_CHARGING == CHARGING_CONTROL */
#endif /* ARCHOS_RECORER */
/* middle part */
memset(charging_logo+3, 0x00, 32);

View file

@ -129,6 +129,11 @@
/* define this if the unit can be powered or charged via USB */
#define HAVE_USB_POWER
/* define current usage levels */
#define CURRENT_NORMAL 45 /* Should be nearly identical to E200 */
#define CURRENT_BACKLIGHT 40 /* Screen is about 20, blue LEDs are another 20, so 40 if both */
#define CURRENT_RECORD 40 /* flash player, so this is just unboosted current*/
/** Non-simulator section **/
#ifndef SIMULATOR

View file

@ -123,6 +123,11 @@
/* Hardware controlled charging? FIXME */
#define CONFIG_CHARGING CHARGING_SIMPLE
/* define current usage levels */
#define CURRENT_NORMAL 45 /* Mike's measurements in Jan 2008 */
#define CURRENT_BACKLIGHT 40 /* Screen is about 20, blue LEDs are another 20, so 40 if both */
#define CURRENT_RECORD 40 /* flash player, so this is just unboosted current*/
/* define this if the unit can be powered or charged via USB */
#define HAVE_USB_POWER

View file

@ -110,9 +110,16 @@
#define BATTERY_TYPES_COUNT 1 /* only one type */
/* Hardware controlled charging */
//#define CONFIG_CHARGING CHARGING_SIMPLE
#define CONFIG_CHARGING CHARGING_MONITOR /* FIXME: remove that once monitoring is fixed properly */
/* define current usage levels */
#define CURRENT_NORMAL 80 /* 16h playback on 1300mAh battery */
#define CURRENT_BACKLIGHT 23 /* from IriverBattery twiki page */
#define CURRENT_SPDIF_OUT 10 /* optical SPDIF output on */
#define CURRENT_RECORD 105 /* additional current while recording */
#define CURRENT_REMOTE 8 /* additional current when remote connected */
#ifndef SIMULATOR
/* Define this if you have a Motorola SCF5249 */

View file

@ -110,9 +110,15 @@
#define BATTERY_TYPES_COUNT 1 /* only one type */
/* Hardware controlled charging */
//#define CONFIG_CHARGING CHARGING_SIMPLE
#define CONFIG_CHARGING CHARGING_MONITOR /* FIXME: remove that once monitoring is fixed properly */
/* define current usage levels */
#define CURRENT_NORMAL 80 /* 16h playback on 1300mAh battery */
#define CURRENT_BACKLIGHT 23 /* from IriverBattery twiki page */
#define CURRENT_SPDIF_OUT 10 /* optical SPDIF output on */
#define CURRENT_RECORD 105 /* additional current while recording */
#define CURRENT_REMOTE 8 /* additional current when remote connected */
#ifndef SIMULATOR
/* Define this if you have a Motorola SCF5249 */

View file

@ -112,6 +112,13 @@
/* define this if the unit can be powered or charged via USB */
#define HAVE_USB_POWER
/* define current usage levels */
#define CURRENT_NORMAL 80 /* 16h playback on 1300mAh battery from IriverRuntime wiki page */
#define CURRENT_BACKLIGHT 23 /* FIXME: This needs to be measured, copied from H100 */
#define CURRENT_RECORD 110 /* additional current while recording */
#define CURRENT_MAX_CHG 650 /* maximum charging current */
#define CURRENT_REMOTE 8 /* additional current when remote connected */
/* define this if the unit can have USB charging disabled by user -
* if USB/MAIN power is discernable and hardware doesn't compel charging */
#define HAVE_USB_CHARGING_ENABLE

View file

@ -102,6 +102,9 @@
/* Hardware controlled charging? FIXME */
#define CONFIG_CHARGING CHARGING_SIMPLE
/* define current usage levels */
#define CURRENT_REMOTE 8 /* additional current when remote connected */
#ifndef SIMULATOR
/* Define this if your LCD can set contrast */

View file

@ -105,6 +105,9 @@
/* Hardware controlled charging? FIXME */
#define CONFIG_CHARGING CHARGING_SIMPLE
/* define current usage levels */
#define CURRENT_REMOTE 8 /* additional current when remote connected */
#ifndef SIMULATOR
/* Define this if your LCD can set contrast */

View file

@ -122,6 +122,9 @@
/* Hardware controlled charging? FIXME */
#define CONFIG_CHARGING CHARGING_SIMPLE
/* define current usage levels */
#define CURRENT_REMOTE 8 /* additional current when remote connected */
#ifndef SIMULATOR
/* define this if the backlight thread is used for fade, not for sim, needs

View file

@ -120,6 +120,13 @@
/* define this if the unit can be powered or charged via USB */
#define HAVE_USB_POWER
/* define current usage levels */
#define CURRENT_NORMAL 100 /* MP3: ~10.5h out of 1100mAh battery */
#define CURRENT_BACKLIGHT 20 /* FIXME: this needs adjusting */
#if defined(HAVE_RECORDING)
#define CURRENT_RECORD 35 /* FIXME: this needs adjusting */
#endif
#ifndef SIMULATOR
/* Define this if you have a PortalPlayer PP5020 */

View file

@ -115,6 +115,12 @@
/* define this if the unit can be powered or charged via USB */
#define HAVE_USB_POWER
#define CURRENT_NORMAL 32 /* MP3: ~9h playback out of 300mAh battery */
#define CURRENT_BACKLIGHT 20 /* FIXME: this needs adjusting */
#if defined(HAVE_RECORDING)
#define CURRENT_RECORD 35 /* FIXME: this needs adjusting */
#endif
#ifndef SIMULATOR
/* Define this if you have a PortalPlayer PP5022 */

View file

@ -123,6 +123,13 @@
/* define this if the unit can be powered or charged via USB */
#define HAVE_USB_POWER
/* define current usage levels */
#define CURRENT_NORMAL 35 /* MP3: ~11h out of 400mAh battery (30GB) or ~17h out of 600mAh (60GB) */
#define CURRENT_BACKLIGHT 20 /* FIXME: this needs adjusting */
#if defined(HAVE_RECORDING)
#define CURRENT_RECORD 35 /* FIXME: this needs adjusting */
#endif
#ifndef SIMULATOR
/* Define this if you have a PortalPlayer PP5022 */

View file

@ -69,6 +69,11 @@
/* define this if the unit can be powered or charged via USB */
#define HAVE_USB_POWER
/* define current usage levels */
#define CURRENT_NORMAL 95 /* average, nearly proportional to 1/U */
#define CURRENT_USB 1 /* host powered in USB mode; avoid zero-div */
#define CURRENT_BACKLIGHT 0 /* no backlight */
#ifndef SIMULATOR
/* Define this if you have a SH7034 */

View file

@ -58,6 +58,11 @@
/* define this if the unit can be powered or charged via USB */
#define HAVE_USB_POWER
/* define current usage levels */
#define CURRENT_NORMAL 95 /* average, nearly proportional to 1/U */
#define CURRENT_USB 1 /* host powered in USB mode; avoid zero-div */
#define CURRENT_BACKLIGHT 0 /* no backlight */
#ifndef SIMULATOR
/* Define this if you have a SH7034 */

View file

@ -72,7 +72,7 @@
#define NO_LOW_BATTERY_SHUTDOWN
/* Software controlled charging */
#define CONFIG_CHARGING CHARGING_CONTROL
#define CONFIG_CHARGING CHARGING_TARGET
#ifndef SIMULATOR

View file

@ -114,11 +114,13 @@
#define X5_REMOTE 3
/* CONFIG_CHARGING */
/* Generic types */
#define CHARGING_SIMPLE 1 /* Simple, hardware controlled charging */
#define CHARGING_MONITOR 2 /* Hardware controlled charging with monitoring */
#define CHARGING_CONTROL 3 /* Software controlled charging */
#define CHARGING_TARGET 4 /* Anything the target implements that is not
a generic implementation */
/* Mostly target-specific code in the /target tree */
#define CHARGING_TARGET 3
/* CONFIG_LCD */
#define LCD_SSD1815 1 /* as used by Archos Recorders and Ondios */

View file

@ -21,11 +21,6 @@
#ifndef _POWER_H_
#define _POWER_H_
#if CONFIG_CHARGING == CHARGING_CONTROL
extern bool charger_enabled;
void charger_enable(bool on);
#endif
#if CONFIG_CHARGING
enum power_input_flags {
/* No external power source? Default. */
@ -82,9 +77,9 @@ bool power_input_present(void);
void power_off(void);
void ide_power_enable(bool on);
# if CONFIG_CHARGING == CHARGING_MONITOR
#if CONFIG_CHARGING >= CHARGING_MONITOR
bool charging_state(void);
# endif
#endif
#ifndef SIMULATOR
@ -102,4 +97,4 @@ bool spdif_powered(void);
bool tuner_power(bool status);
#endif
#endif
#endif /* _POWER_H_ */

View file

@ -25,149 +25,103 @@
#define POWER_HISTORY_LEN 2*60 /* 2 hours of samples, one per minute */
#define CHARGE_END_SHORTD 6 /* stop when N minutes have passed with
* avg delta being < -0.05 V */
#define CHARGE_END_LONGD 50 /* stop when N minutes have passed with
* avg delta being < -0.02 V */
typedef enum { /* sorted by increasing charging current */
enum charge_state_type
{
/* sorted by increasing charging current */
#if CONFIG_CHARGING >= CHARGING_MONITOR
CHARGE_STATE_DISABLED = -2, /* Disable charger use */
CHARGE_STATE_ERROR = -1, /* Some error occurred that should not allow
further attempts without user intervention */
CHARGE_STATE_DISABLED = -2, /* Disable charger use (safety measure) */
CHARGE_STATE_ERROR = -1, /* Some error occurred that should not allow
turning on the charger again by software
without user intervention (ie. replug) */
#endif
DISCHARGING = 0,
#if CONFIG_CHARGING >= CHARGING_MONITOR
TRICKLE, /* Can occur for CONFIG_CHARGING >= CHARGING_MONITOR */
/* For LiIon, the low-current precharge mode if battery
was very low */
TOPOFF, /* Can occur for CONFIG_CHARGING == CHARGING_CONTROL */
TRICKLE, /* For NiCd, battery maintenence phase */
/* For LiIon, low-current precharge phase */
TOPOFF, /* For NiCd, waiting for dead zone */
/* For LiIon, constant voltage phase */
CHARGING, /* Can occur for all CONFIG_CHARGING options */
/* For LiIon, the constant current phase */
CHARGING, /* For NiCd, main charge phase */
/* For LiIon, constant current phase */
#endif
} charge_state_type;
};
/* tells what the charger is doing */
extern charge_state_type charge_state;
extern enum charge_state_type charge_state;
#ifdef CONFIG_CHARGING
/*
* Flag that the charger has been plugged in/removed: this is set for exactly
* one time through the power loop when the charger has been plugged in.
*/
typedef enum {
enum charger_input_state_type
{
NO_CHARGER = 0, /* No charger is present */
CHARGER_UNPLUGGED, /* Transitional state during CHARGER=>NO_CHARGER */
CHARGER_PLUGGED, /* Transitional state during NO_CHARGER=>CHARGER */
CHARGER /* Charger is present */
} charger_input_state_type;
};
/* tells the state of the charge input */
extern charger_input_state_type charger_input_state;
#endif
extern enum charger_input_state_type charger_input_state;
#ifndef SIMULATOR
/* Power input status saved on the power thread each loop */
extern unsigned int power_thread_inputs;
#if CONFIG_CHARGING == CHARGING_CONTROL
#define START_TOPOFF_CHG 85 /* Battery % to start at top-off */
#define START_TRICKLE_CHG 95 /* Battery % to start at trickle */
#define POWER_MESSAGE_LEN 32 /* power thread status message */
#define CHARGE_MAX_TIME_1500 450 /* minutes: maximum charging time for 1500 mAh batteries */
/* actual max time depends also on BATTERY_CAPACITY! */
#define CHARGE_MIN_TIME 10 /* minutes: minimum charging time */
#define TOPOFF_MAX_TIME 90 /* After charging, go to top off charge. How long should top off charge be? */
#define TOPOFF_VOLTAGE 5650 /* which voltage is best? (millivolts) */
#define TRICKLE_MAX_TIME 12*60 /* After top off charge, go to trickle charge. How long should trickle charge be? */
#define TRICKLE_VOLTAGE 5450 /* which voltage is best? (millivolts) */
#define START_TOPOFF_SEC 25 /* initial trickle_sec for topoff */
#define START_TRICKLE_SEC 15 /* initial trickle_sec for trickle */
#define PID_DEADZONE 4 /* PID proportional deadzone */
extern char power_message[POWER_MESSAGE_LEN];
extern int long_delta; /* long term delta battery voltage */
extern int short_delta; /* short term delta battery voltage */
extern int powermgmt_last_cycle_startstop_min; /* how many minutes ago was the charging started or stopped? */
extern int powermgmt_last_cycle_level; /* which level had the batteries at this time? */
extern int pid_p; /* PID proportional term */
extern int pid_i; /* PID integral term */
extern int trickle_sec; /* trickle charge: How many seconds per minute are we charging actually? */
#endif /* CONFIG_CHARGING == CHARGING_CONTROL */
#if defined(ARCHOS_ONDIOSP) || defined(ARCHOS_ONDIOFM) /* Values for Ondio */
# define CURRENT_NORMAL 95 /* average, nearly proportional to 1/U */
# define CURRENT_USB 1 /* host powered in USB mode; avoid zero-div */
# define CURRENT_BACKLIGHT 0 /* no backlight */
#else /* Values for HD based jukeboxes */
#ifdef IRIVER_H100_SERIES
# define CURRENT_NORMAL 80 /* 16h playback on 1300mAh battery */
# define CURRENT_BACKLIGHT 23 /* from IriverBattery twiki page */
# define CURRENT_SPDIF_OUT 10 /* optical SPDIF output on */
# define CURRENT_RECORD 105 /* additional current while recording */
#elif defined(IRIVER_H300_SERIES)
# define CURRENT_NORMAL 80 /* 16h playback on 1300mAh battery from IriverRuntime wiki page */
# define CURRENT_BACKLIGHT 23 /* FIXME: This needs to be measured, copied from H100 */
# define CURRENT_RECORD 110 /* additional current while recording */
#elif defined(IPOD_NANO) /* iPOD Nano */
# define CURRENT_NORMAL 32 /* MP3: ~9h playback out of 300mAh battery */
# define CURRENT_BACKLIGHT 20 /* FIXME: this needs adjusting */
#if defined(HAVE_RECORDING)
# define CURRENT_RECORD 35 /* FIXME: this needs adjusting */
#endif
#elif defined(IPOD_VIDEO) /* iPOD Video */
# define CURRENT_NORMAL 35 /* MP3: ~11h out of 400mAh battery (30GB) or ~17h out of 600mAh (60GB) */
# define CURRENT_BACKLIGHT 20 /* FIXME: this needs adjusting */
#if defined(HAVE_RECORDING)
# define CURRENT_RECORD 35 /* FIXME: this needs adjusting */
#endif
#elif defined(SANSA_E200) /* Sandisk E200v1 */
# define CURRENT_NORMAL 45 /* Mike's measurements in Jan 2008 */
# define CURRENT_BACKLIGHT 40 /* Screen is about 20, blue LEDs are another 20, so 40 if both */
# define CURRENT_RECORD 40 /* flash player, so this is just unboosted current*/
#elif defined(SANSA_C200) /* Sandisk C200v1 */
# define CURRENT_NORMAL 45 /* Should be nearly identical to E200 */
# define CURRENT_BACKLIGHT 40 /* Screen is about 20, blue LEDs are another 20, so 40 if both */
# define CURRENT_RECORD 40 /* flash player, so this is just unboosted current*/
#elif defined(IPOD_4G) /* iPOD 4G */
# define CURRENT_NORMAL 100 /* MP3: ~10.5h out of 1100mAh battery */
# define CURRENT_BACKLIGHT 20 /* FIXME: this needs adjusting */
#if defined(HAVE_RECORDING)
# define CURRENT_RECORD 35 /* FIXME: this needs adjusting */
#endif
#else /* Not iriver H1x0, H3x0, nor Archos Ondio, nor iPod nano/Video/4G, nor Sansas */
# define CURRENT_NORMAL 145 /* usual current in mA when using the AJB including some disk/backlight/... activity */
# define CURRENT_BACKLIGHT 30 /* additional current when backlight always on */
#if defined(HAVE_RECORDING)
# define CURRENT_RECORD 35 /* FIXME: this needs adjusting */
#endif
#endif /* Not Archos Ondio */
#define CURRENT_USB 500 /* usual current in mA in USB mode */
#ifdef HAVE_REMOTE_LCD
# define CURRENT_REMOTE 8 /* add. current when H100-remote connected */
#endif /* HAVE_REMOTE_LCD */
# define CURRENT_MIN_CHG 70 /* minimum charge current */
# define MIN_CHG_V 8500 /* at 8.5v charger voltage get CURRENT_MIN_CHG */
# ifdef IRIVER_H300_SERIES
# define CURRENT_MAX_CHG 650 /* maximum charging current */
# else
# define CURRENT_MAX_CHG 350 /* maximum charging current */
# endif
# define MAX_CHG_V 10250 /* anything over 10.25v gives CURRENT_MAX_CHG */
#endif /* not ONDIO */
#endif /* CONFIG_CHARGING */
#if CONFIG_CHARGING == CHARGING_TARGET
/* Include target-specific definitions */
#include "powermgmt-target.h"
#endif
#ifndef SIMULATOR
/* Generic current values that are really rather meaningless - config header
* should define proper numbers. */
#ifndef CURRENT_NORMAL
#define CURRENT_NORMAL 145 /* usual current in mA */
#endif
#ifndef CURRENT_BACKLIGHT
#define CURRENT_BACKLIGHT 30 /* additional current when backlight always on */
#endif
#ifdef HAVE_RECORDING
#ifndef CURRENT_RECORD
#define CURRENT_RECORD 35 /* additional recording current */
#endif
#endif /* HAVE_RECORDING */
#ifndef CURRENT_USB
#define CURRENT_USB 500 /* usual current in mA in USB mode */
#endif
#ifdef HAVE_REMOTE_LCD
#define CURRENT_REMOTE 8 /* additional current when remote connected */
#endif /* HAVE_REMOTE_LCD */
#if CONFIG_CHARGING
#ifndef CURRENT_MAX_CHG
#define CURRENT_MAX_CHG 350 /* maximum charging current */
#endif
#endif /* CONFIG_CHARGING */
#ifdef CHARGING_DEBUG_FILE
#define POWERMGMT_DEBUG_STACK ((0x1000)/sizeof(long))
#else
#define POWERMGMT_DEBUG_STACK 0
#endif
#ifndef BATT_AVE_SAMPLES
/* slw filter constant unless otherwise specified */
#define BATT_AVE_SAMPLES 128
#endif
#ifndef POWER_THREAD_STEP_TICKS
/* 2HZ sample rate unless otherwise specified */
#define POWER_THREAD_STEP_TICKS (HZ/2)
#endif
extern unsigned short power_history[POWER_HISTORY_LEN];
extern const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT];
extern const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT];
@ -179,12 +133,6 @@ extern const unsigned short percent_to_volt_charge[11];
/* Start up power management thread */
void powermgmt_init(void);
/* Do target portion of init (for CHARGING_TARGET) - called on power thread */
void powermgmt_init_target(void);
/* Handle frequent tasks and call charging_algorithm_small_step */
void power_thread_sleep(int ticks);
#endif /* SIMULATOR */
/* Returns battery statust */
@ -193,9 +141,15 @@ int battery_time(void); /* minutes */
unsigned int battery_adc_voltage(void); /* voltage from ADC in millivolts */
unsigned int battery_voltage(void); /* filtered batt. voltage in millivolts */
#ifdef HAVE_BATTERY_SWITCH
unsigned int input_millivolts(void); /* voltage that device is running from */
/* Set the filtered battery voltage (to adjust it before beginning a charge
cycle for instance where old, loaded readings will likely be invalid). */
void set_filtered_battery_voltage(int millivolts);
* cycle for instance where old, loaded readings will likely be invalid).
* Also readjust when battery switch is opened or closed.
*/
void reset_battery_filter(int millivolts);
#endif /* HAVE_BATTERY_SWITCH */
/* read unfiltered battery info */
void battery_read_info(int *voltage, int *level);
@ -203,13 +157,10 @@ void battery_read_info(int *voltage, int *level);
/* Tells if the battery level is safe for disk writes */
bool battery_level_safe(void);
#ifdef TARGET_POWERMGMT_FILTER_CHARGE_STATE
int powermgmt_filter_charge_state(void);
#endif
void set_poweroff_timeout(int timeout);
void set_battery_capacity(int capacity); /* set local battery capacity value */
void set_battery_type(int type); /* set local battery type */
int get_battery_capacity(void); /* get local battery capacity value */
void set_battery_type(int type); /* set local battery type */
void set_sleep_timer(int seconds);
int get_sleep_timer(void);

File diff suppressed because it is too large Load diff

View file

@ -168,7 +168,7 @@ int battery_adc_temp(void)
/* All code has a preference for the main charger being connected over
* USB. USB is considered in the algorithm only if it is the sole source. */
static uint32_t int_sense0 = 0; /* Interrupt Sense 0 bits */
static unsigned int power_status = POWER_INPUT_NONE; /* Detect input changes */
static unsigned int last_inputs = POWER_INPUT_NONE; /* Detect input changes */
static int charger_total_timer = 0; /* Total allowed charging time */
static int icharger_ave = 0; /* Filtered charging current */
static bool charger_close = false; /* Shutdown notification */
@ -181,7 +181,7 @@ static int autorecharge_counter = 0 ; /* Battery < threshold debounce */
static int chgcurr_timer = 0; /* Countdown to CHGCURR error */
#define AUTORECHARGE_COUNTDOWN (10*2) /* 10s debounce */
#define WATCHDOG_TIMEOUT (10*2) /* If not serviced, poweroff in 10s */
#define CHGCURR_TIMEOUT (2*2) /* 2s debounce */
#define CHGCURR_TIMEOUT (4*2) /* 4s debounce */
/* Temperature monitoring */
static enum
@ -217,7 +217,7 @@ static bool charger_current_filter_step(void)
/* Return true if the main charger is connected. */
static bool main_charger_connected(void)
{
return (power_status &
return (last_inputs &
POWER_INPUT_MAIN_CHARGER &
POWER_INPUT_CHARGER) != 0;
}
@ -233,16 +233,14 @@ static unsigned int auto_recharge_voltage(void)
return BATT_USB_VAUTO_RECHARGE;
}
#ifndef NO_LOW_BATTERY_SHUTDOWN
/* Return greater of supply (BP) or filtered battery voltage. */
static unsigned int input_millivolts(void)
unsigned int input_millivolts(void)
{
unsigned int app_millivolts = application_supply_adc_voltage();
unsigned int bat_millivolts = battery_voltage();
return MAX(app_millivolts, bat_millivolts);
}
#endif
/* Get smoothed readings for initializing filtered data. */
static int stat_battery_reading(int type)
@ -292,7 +290,7 @@ static bool update_filtered_battery_voltage(void)
if (millivolts != INT_MIN)
{
set_filtered_battery_voltage(millivolts);
reset_battery_filter(millivolts);
return true;
}
@ -357,13 +355,13 @@ static bool adjust_charger_current(void)
int usb_select;
uint32_t i;
usb_select = ((power_status & POWER_INPUT) == POWER_INPUT_USB)
usb_select = ((last_inputs & POWER_INPUT) == POWER_INPUT_USB)
? 1 : 0;
if (charge_state == DISCHARGING && usb_select == 1)
{
/* USB-only, DISCHARGING, = maintaining battery */
int select = (power_status & POWER_INPUT_CHARGER) ? 0 : 1;
int select = (last_inputs & POWER_INPUT_CHARGER) ? 0 : 1;
charger_setting = charger_bits[CHARGING+1][select];
}
else
@ -458,7 +456,7 @@ static bool charging_ok(void)
if (ok)
{
/* Is the battery even connected? */
ok = (power_status & POWER_INPUT_BATTERY) != 0;
ok = (last_inputs & POWER_INPUT_BATTERY) != 0;
}
if (ok)
@ -591,20 +589,6 @@ void powermgmt_init_target(void)
#endif
}
/* Returns CHARGING or DISCHARGING since that's all we really do. */
int powermgmt_filter_charge_state(void)
{
switch(charge_state)
{
case TRICKLE:
case TOPOFF:
case CHARGING:
return CHARGING;
default:
return DISCHARGING;
}
}
/* Returns true if the unit is charging the batteries. */
bool charging_state(void)
{
@ -625,24 +609,6 @@ int battery_charge_current(void)
return icharger_ave / ICHARGER_AVE_SAMPLES;
}
bool query_force_shutdown(void)
{
#ifndef NO_LOW_BATTERY_SHUTDOWN
return input_millivolts() < battery_level_shutoff[0];
#else
return false;
#endif
}
bool battery_level_safe(void)
{
#ifndef NO_LOW_BATTERY_SHUTDOWN
return input_millivolts() > battery_level_dangerous[0];
#else
return true;
#endif
}
static void charger_plugged(void)
{
adc_enable_channel(ADC_BATTERY_TEMP, true);
@ -662,7 +628,7 @@ static void charger_unplugged(void)
}
/* Might need to reevaluate these bits in charger_none. */
power_status &= ~(POWER_INPUT | POWER_INPUT_CHARGER);
last_inputs &= ~(POWER_INPUT | POWER_INPUT_CHARGER);
temp_state = TEMP_STATE_NORMAL;
autorecharge_counter = 0;
chgcurr_timer = 0;
@ -672,15 +638,11 @@ static void charger_unplugged(void)
static void charger_none(void)
{
unsigned int pwr = power_input_status();
unsigned int pwr = power_thread_inputs;
if (power_status != pwr)
if (last_inputs != pwr)
{
/* If battery switch state changed, reset filter. */
if ((power_status ^ pwr) & POWER_INPUT_BATTERY)
update_filtered_battery_voltage();
power_status = pwr;
last_inputs = pwr;
if (charge_state == CHARGE_STATE_DISABLED)
return;
@ -696,7 +658,7 @@ static void charger_none(void)
else
{
charger_unplugged();
power_status = pwr; /* Restore status */
last_inputs = pwr; /* Restore status */
}
}
else if (charger_setting != 0)
@ -716,17 +678,13 @@ static void charger_none(void)
static void charger_control(void)
{
unsigned int pwr = power_input_status();
unsigned int pwr = power_thread_inputs;
if (power_status != pwr)
if (last_inputs != pwr)
{
unsigned int changed = power_status ^ pwr;
unsigned int changed = last_inputs ^ pwr;
power_status = pwr;
/* If battery switch state changed, reset filter. */
if (changed & POWER_INPUT_BATTERY)
update_filtered_battery_voltage();
last_inputs = pwr;
if (charger_setting != 0)
charger_setting = CHARGER_ADJUST;
@ -771,12 +729,11 @@ static void charger_control(void)
{
/* Battery voltage may have dropped and a charge cycle should
* start again. Debounced. */
if (autorecharge_counter < 0)
if (autorecharge_counter < 0 &&
battery_adc_voltage() < BATT_FULL_VOLTAGE)
{
/* Try starting a cycle now regardless of battery level to
* allow user to ensure the battery is topped off. It
* will soon turn off if already full. */
autorecharge_counter = 0;
/* Try starting a cycle now if battery isn't already topped
* off to allow user to ensure the battery is full. */
}
else if (battery_voltage() > auto_recharge_voltage())
{
@ -791,6 +748,8 @@ static void charger_control(void)
break;
}
autorecharge_counter = 0;
charging_set_thread_priority(true);
if (stat_battery_reading(ADC_BATTERY) < BATT_VTRICKLE_CHARGE)
@ -858,10 +817,12 @@ static void charger_control(void)
}
/* Main charging algorithm - called from powermgmt.c */
void charging_algorithm_small_step(void)
void charging_algorithm_step(void)
{
#ifdef IMX31_ALLOW_CHARGING
if (service_wdt)
watchdog_service();
#endif
/* Switch by input state */
switch (charger_input_state)
@ -909,12 +870,6 @@ void charging_algorithm_small_step(void)
}
}
void charging_algorithm_big_step(void)
{
/* Sleep for one minute */
power_thread_sleep(HZ*60);
}
/* Disable the charger and prepare for poweroff - called off-thread so we
* signal the charging thread to prepare to quit. */
void charging_algorithm_close(void)

View file

@ -53,6 +53,7 @@
#define BATT_VTRICKLE_CHARGE 2900 /* Must charge slowly */
#define BATT_VSLOW_CHARGE 3500 /* Lower-current charge mode below
* this level */
#define BATT_FULL_VOLTAGE 4161 /* Battery already topped */
#define BATT_VAUTO_RECHARGE 4100 /* When to begin another cycle */
#define BATT_USB_VAUTO_RECHARGE 4000 /* When to cycle with USB only */
#define BATT_USB_VSTOP 4140 /* When to "stop" when USB only */
@ -92,23 +93,13 @@
#define BATT_AVE_SAMPLES 32
#define ICHARGER_AVE_SAMPLES 32
void powermgmt_init_target(void);
void charging_algorithm_step(void);
void charging_algorithm_close(void);
/* Provide filtered charge current */
int battery_charge_current(void);
#ifndef SIMULATOR
/* Indicate various functions that require implementation at the target level.
* This is because the battery could be low or the battery switch is off but
* with the main charger attached which implies safe power for anything. The
* true battery reading is always reported for voltage readings and not the
* value at the application supply. */
#define TARGET_QUERY_FORCE_SHUTDOWN
/* For this the application supply is read out if the charger is attached or
* the battery read if not (completely hardware selected at BP). */
#define TARGET_BATTERY_LEVEL_SAFE
/* The state should be adjusted to CHARGING or DISCHARGING */
#define TARGET_POWERMGMT_FILTER_CHARGE_STATE
#endif /* SIMULATOR */
#define CURRENT_MAX_CHG battery_charge_current()
#endif /* POWERMGMT_TARGET_H */

View file

@ -33,10 +33,6 @@
#include "logf.h"
#include "usb.h"
#if CONFIG_CHARGING == CHARGING_CONTROL
bool charger_enabled;
#endif
#if CONFIG_TUNER
bool tuner_power(bool status)

View file

@ -29,10 +29,6 @@
#include "logf.h"
#include "usb.h"
#if CONFIG_CHARGING == CHARGING_CONTROL
bool charger_enabled;
#endif
void power_init(void)
{
/* Enable power-off bit */

View file

@ -29,10 +29,6 @@
#include "logf.h"
#include "usb.h"
#if CONFIG_CHARGING == CHARGING_CONTROL
bool charger_enabled;
#endif
void power_init(void)
{
/* power off bit */

View file

@ -19,9 +19,10 @@
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "system.h"
#include "adc.h"
#include "power.h"
#include "powermgmt.h"
const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
@ -58,3 +59,17 @@ unsigned int battery_adc_voltage(void)
return (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) >> 10;
}
unsigned int input_millivolts(void)
{
unsigned int batt_millivolts = battery_voltage();
if ((power_thread_inputs & POWER_INPUT_BATTERY) == 0) {
/* Just return a safe value if battery isn't connected */
return 4050;
}
return batt_millivolts;
}

View file

@ -33,10 +33,6 @@
#include "logf.h"
#include "usb.h"
#if CONFIG_CHARGING == CHARGING_CONTROL
bool charger_enabled;
#endif
void power_init(void)
{
}

View file

@ -25,9 +25,10 @@
#include "kernel.h"
#include "system.h"
#include "power.h"
#include "powermgmt-target.h"
#include "usb.h"
bool charger_enabled;
static bool charger_on;
void power_init(void)
{
@ -48,13 +49,18 @@ void charger_enable(bool on)
if(on)
{
and_b(~0x20, &PBDRL);
charger_enabled = 1;
}
else
{
or_b(0x20, &PBDRL);
charger_enabled = 0;
}
charger_on = on;
}
bool charger_enabled(void)
{
return charger_on;
}
void ide_power_enable(bool on)

View file

@ -19,9 +19,13 @@
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "system.h"
#include <sprintf.h>
#include "debug.h"
#include "storage.h"
#include "adc.h"
#include "power.h"
#include "powermgmt.h"
const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
@ -60,3 +64,434 @@ unsigned int battery_adc_voltage(void)
{
return (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) >> 10;
}
/** Charger control **/
#ifdef CHARGING_DEBUG_FILE
#include "file.h"
#define DEBUG_FILE_NAME "/powermgmt.csv"
#define DEBUG_MESSAGE_LEN 133
static char debug_message[DEBUG_MESSAGE_LEN];
static int fd = -1; /* write debug information to this file */
static int wrcount = 0;
#endif /* CHARGING_DEBUG_FILE */
/*
* For a complete description of the charging algorithm read
* docs/CHARGING_ALGORITHM.
*/
int long_delta; /* long term delta battery voltage */
int short_delta; /* short term delta battery voltage */
bool disk_activity_last_cycle = false; /* flag set to aid charger time
* calculation */
char power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in
debug menu */
/* percentage at which charging
starts */
int powermgmt_last_cycle_startstop_min = 0; /* how many minutes ago was the
charging started or
stopped? */
int powermgmt_last_cycle_level = 0; /* which level had the
batteries at this time? */
int trickle_sec = 0; /* how many seconds should the
charger be enabled per
minute for trickle
charging? */
int pid_p = 0; /* PID proportional term */
int pid_i = 0; /* PID integral term */
static unsigned int target_voltage = TRICKLE_VOLTAGE; /* desired topoff/trickle
* voltage level */
static int charge_max_time_idle = 0; /* max. charging duration, calculated at
* beginning of charging */
static int charge_max_time_now = 0; /* max. charging duration including
* hdd activity */
static int minutes_disk_activity = 0; /* count minutes of hdd use during
* charging */
static int last_disk_activity = CHARGE_END_LONGD + 1; /* last hdd use x mins ago */
#ifdef CHARGING_DEBUG_FILE
static void debug_file_close(void)
{
if (fd >= 0) {
close(fd);
fd = -1;
}
}
static void debug_file_log(void)
{
if (usb_inserted()) {
/* It is probably too late to close the file but we can try... */
debug_file_close();
}
else if (fd < 0) {
fd = open(DEBUG_FILE_NAME, O_WRONLY | O_APPEND | O_CREAT);
if (fd >= 0) {
snprintf(debug_message, DEBUG_MESSAGE_LEN,
"cycle_min, bat_millivolts, bat_percent, chgr_state"
" ,charge_state, pid_p, pid_i, trickle_sec\n");
write(fd, debug_message, strlen(debug_message));
wrcount = 99; /* force a flush */
}
}
else {
snprintf(debug_message, DEBUG_MESSAGE_LEN,
"%d, %d, %d, %d, %d, %d, %d, %d\n",
powermgmt_last_cycle_startstop_min, battery_voltage(),
battery_level(), charger_input_state, charge_state,
pid_p, pid_i, trickle_sec);
write(fd, debug_message, strlen(debug_message));
wrcount++;
}
}
static void debug_file_sync(void)
{
/*
* If we have a lot of pending writes or if the disk is spining,
* fsync the debug log file.
*/
if (wrcount > 10 || (wrcount > 0 && storage_disk_is_active())) {
if (fd >= 0)
fsync(fd);
wrcount = 0;
}
}
#else /* !CHARGING_DEBUG_FILE */
#define debug_file_close()
#define debug_file_log()
#define debug_file_sync()
#endif /* CHARGING_DEBUG_FILE */
/*
* Do tasks that should be done every step.
*/
static void do_frequent_tasks(void)
{
if (storage_disk_is_active()) {
/* flag hdd use for charging calculation */
disk_activity_last_cycle = true;
}
debug_file_sync();
}
/*
* The charger was just plugged in. If the battery level is
* nearly charged, just trickle. If the battery is low, start
* a full charge cycle. If the battery level is in between,
* top-off and then trickle.
*/
static void charger_plugged(void)
{
int battery_percent = battery_level();
pid_p = 0;
pid_i = 0;
powermgmt_last_cycle_level = battery_percent;
powermgmt_last_cycle_startstop_min = 0;
snprintf(power_message, POWER_MESSAGE_LEN, "Charger plugged in");
if (battery_percent > START_TOPOFF_CHG) {
if (battery_percent >= START_TRICKLE_CHG) {
charge_state = TRICKLE;
target_voltage = TRICKLE_VOLTAGE;
}
else {
charge_state = TOPOFF;
target_voltage = TOPOFF_VOLTAGE;
}
}
else {
/*
* Start the charger full strength
*/
int i = CHARGE_MAX_MIN_1500 * get_battery_capacity() / 1500;
charge_max_time_idle = i * (100 + 35 - battery_percent) / 100;
if (charge_max_time_idle > i)
charge_max_time_idle = i;
charge_max_time_now = charge_max_time_idle;
snprintf(power_message, POWER_MESSAGE_LEN,
"ChgAt %d%% max %dm", battery_percent,
charge_max_time_now);
/*
* Enable the charger after the max time calc is done,
* because battery_level depends on if the charger is
* on.
*/
DEBUGF("power: charger inserted and battery"
" not full, charging\n");
trickle_sec = 60;
long_delta = short_delta = 999999;
charge_state = CHARGING;
}
}
/*
* The charger was just unplugged.
*/
static void charger_unplugged(void)
{
DEBUGF("power: charger disconnected, disabling\n");
charger_enable(false);
powermgmt_last_cycle_level = battery_level();
powermgmt_last_cycle_startstop_min = 0;
trickle_sec = 0;
pid_p = 0;
pid_i = 0;
charge_state = DISCHARGING;
snprintf(power_message, POWER_MESSAGE_LEN, "Charger: discharge");
}
static void charging_step(void)
{
int i;
/* alter charge time max length with extra disk use */
if (disk_activity_last_cycle) {
minutes_disk_activity++;
charge_max_time_now = charge_max_time_idle +
minutes_disk_activity*2 / 5;
disk_activity_last_cycle = false;
last_disk_activity = 0;
}
else {
last_disk_activity++;
}
/*
* Check the delta voltage over the last X minutes so we can do
* our end-of-charge logic based on the battery level change
* (no longer use minimum time as logic for charge end has 50
* minutes minimum charge built in).
*/
if (powermgmt_last_cycle_startstop_min > CHARGE_END_SHORTD) {
short_delta = power_history[0] -
power_history[CHARGE_END_SHORTD - 1];
}
if (powermgmt_last_cycle_startstop_min > CHARGE_END_LONGD) {
/*
* Scan the history: the points where measurement is taken need to
* be fairly static. Check prior to short delta 'area'. Also only
* check first and last 10 cycles (delta in middle OK).
*/
long_delta = power_history[0] -
power_history[CHARGE_END_LONGD - 1];
for (i = CHARGE_END_SHORTD; i < CHARGE_END_SHORTD + 10; i++)
{
if ((power_history[i] - power_history[i+1]) > 50 ||
(power_history[i] - power_history[i+1]) < -50) {
long_delta = 777777;
break;
}
}
for (i = CHARGE_END_LONGD - 11; i < CHARGE_END_LONGD - 1 ; i++)
{
if ((power_history[i] - power_history[i+1]) > 50 ||
(power_history[i] - power_history[i+1]) < -50) {
long_delta = 888888;
break;
}
}
}
snprintf(power_message, POWER_MESSAGE_LEN,
"Chg %dm, max %dm", powermgmt_last_cycle_startstop_min,
charge_max_time_now);
/*
* End of charge criteria (any qualify):
* 1) Charged a long time
* 2) DeltaV went negative for a short time ( & long delta static)
* 3) DeltaV was negative over a longer period (no disk use only)
*
* Note: short_delta and long_delta are millivolts
*/
if (powermgmt_last_cycle_startstop_min >= charge_max_time_now ||
(short_delta <= -50 && long_delta < 50) ||
(long_delta < -20 && last_disk_activity > CHARGE_END_LONGD)) {
int battery_percent = battery_level();
if (powermgmt_last_cycle_startstop_min > charge_max_time_now) {
DEBUGF("power: powermgmt_last_cycle_startstop_min > charge_max_time_now, "
"enough!\n");
/*
* Have charged too long and deltaV detection did not
* work!
*/
snprintf(power_message, POWER_MESSAGE_LEN,
"Chg tmout %d min", charge_max_time_now);
/*
* Switch to trickle charging. We skip the top-off
* since we've effectively done the top-off operation
* already since we charged for the maximum full
* charge time.
*/
powermgmt_last_cycle_level = battery_percent;
powermgmt_last_cycle_startstop_min = 0;
charge_state = TRICKLE;
/*
* Set trickle charge target to a relative voltage instead
* of an arbitrary value - the fully charged voltage may
* vary according to ambient temp, battery condition etc.
* Trickle target is -0.15v from full voltage acheived.
* Topup target is -0.05v from full voltage.
*/
target_voltage = power_history[0] - 150;
}
else {
if(short_delta <= -5) {
DEBUGF("power: short-term negative"
" delta, enough!\n");
snprintf(power_message, POWER_MESSAGE_LEN,
"end negd %d %dmin", short_delta,
powermgmt_last_cycle_startstop_min);
target_voltage = power_history[CHARGE_END_SHORTD - 1] - 50;
}
else {
DEBUGF("power: long-term small "
"positive delta, enough!\n");
snprintf(power_message, POWER_MESSAGE_LEN,
"end lowd %d %dmin", long_delta,
powermgmt_last_cycle_startstop_min);
target_voltage = power_history[CHARGE_END_LONGD - 1] - 50;
}
/*
* Switch to top-off charging.
*/
powermgmt_last_cycle_level = battery_percent;
powermgmt_last_cycle_startstop_min = 0;
charge_state = TOPOFF;
}
}
}
static void topoff_trickle_step(void)
{
unsigned int millivolts;
/*
*Time to switch from topoff to trickle?
*/
if (charge_state == TOPOFF &&
powermgmt_last_cycle_startstop_min > TOPOFF_MAX_MIN) {
powermgmt_last_cycle_level = battery_level();
powermgmt_last_cycle_startstop_min = 0;
charge_state = TRICKLE;
target_voltage = target_voltage - 100;
}
/*
* Adjust trickle charge time (proportional and integral terms).
* Note: I considered setting the level higher if the USB is
* plugged in, but it doesn't appear to be necessary and will
* generate more heat [gvb].
*/
millivolts = battery_voltage();
pid_p = ((signed)target_voltage - (signed)millivolts) / 5;
if (pid_p <= PID_DEADZONE && pid_p >= -PID_DEADZONE)
pid_p = 0;
if ((unsigned)millivolts < target_voltage) {
if (pid_i < 60)
pid_i++; /* limit so it doesn't "wind up" */
}
else {
if (pid_i > 0)
pid_i--; /* limit so it doesn't "wind up" */
}
trickle_sec = pid_p + pid_i;
if (trickle_sec > 60)
trickle_sec = 60;
if (trickle_sec < 0)
trickle_sec = 0;
}
void charging_algorithm_step(void)
{
static int pwm_counter = 0; /* PWM total cycle in steps */
static int pwm_duty = 0; /* PWM duty cycle in steps */
switch (charger_input_state)
{
case CHARGER_PLUGGED:
charger_plugged();
break;
case CHARGER_UNPLUGGED:
charger_unplugged();
break;
case CHARGER:
case NO_CHARGER:
do_frequent_tasks();
if (pwm_counter > 0) {
if (pwm_duty > 0 && --pwm_duty <= 0)
charger_enable(false); /* Duty cycle expired */
if (--pwm_counter > 0)
return;
/* PWM cycle is complete */
powermgmt_last_cycle_startstop_min++;
debug_file_log();
}
break;
}
switch (charge_state)
{
case CHARGING:
charging_step();
break;
case TOPOFF:
case TRICKLE:
topoff_trickle_step();
break;
case DISCHARGING:
default:
break;
}
/* If 100%, ensure pwm_on never expires and briefly disables the
* charger. */
pwm_duty = (trickle_sec < 60) ? trickle_sec*2 : 0;
pwm_counter = 60*2;
charger_enable(trickle_sec > 0);
}
#ifdef CHARGING_DEBUG_FILE
void charging_algorithm_close(void)
{
debug_file_close();
}
#endif /* CHARGING_DEBUG_FILE */
/* Returns true if the unit is charging the batteries. */
bool charging_state(void)
{
return charge_state == CHARGING;
}

View file

@ -0,0 +1,101 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese
* Revisions copyright (C) 2005 by Gerald Van Baren
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef POWERMGMT_TARGET_H
#define POWERMGMT_TARGET_H
/*
* Define CHARGING_DEBUG_FILE to create a csv (spreadsheet) with battery
* information in it (one sample per minute/connect/disconnect).
*
* This is only for very low level debug.
*/
#undef CHARGING_DEBUG_FILE
/* stop when N minutes have passed with avg delta being < -0.05 V */
#define CHARGE_END_SHORTD 6
/* stop when N minutes have passed with avg delta being < -0.02 V */
#define CHARGE_END_LONGD 50
/* Battery % to start at top-off */
#define START_TOPOFF_CHG 85
/* Battery % to start at trickle */
#define START_TRICKLE_CHG 95
/* power thread status message */
#define POWER_MESSAGE_LEN 32
/* minutes: maximum charging time for 1500 mAh batteries
* actual max time depends also on BATTERY_CAPACITY! */
#define CHARGE_MAX_MIN_1500 450
/* minutes: minimum charging time */
#define CHARGE_MIN_MIN 10
/* After charging, go to top off charge. How long should top off charge be? */
#define TOPOFF_MAX_MIN 90
/* which voltage is best? (millivolts) */
#define TOPOFF_VOLTAGE 5650
/* After top off charge, go to trickle harge. How long should trickle
* charge be? */
#define TRICKLE_MAX_MIN 720 /* 12 hrs */
/* which voltage is best? (millivolts) */
#define TRICKLE_VOLTAGE 5450
/* initial trickle_sec for topoff */
#define START_TOPOFF_SEC 25
/* initial trickle_sec for trickle */
#define START_TRICKLE_SEC 15
#define PID_DEADZONE 4 /* PID proportional deadzone */
extern char power_message[POWER_MESSAGE_LEN];
extern int long_delta; /* long term delta battery voltage */
extern int short_delta; /* short term delta battery voltage */
extern int powermgmt_last_cycle_startstop_min; /* how many minutes ago was
the charging started or
stopped? */
extern int powermgmt_last_cycle_level; /* which level had the batteries
at this time? */
extern int pid_p; /* PID proportional term */
extern int pid_i; /* PID integral term */
extern int trickle_sec; /* how many seconds should the
charger be enabled per
minute for trickle
charging? */
void charger_enable(bool on);
bool charger_enabled(void);
/* Battery filter lengths in samples */
#define BATT_AVE_SAMPLES 32
/* No init to do */
static inline void powermgmt_init_target(void) {}
void charging_algorithm_step(void);
#ifdef CHARGING_DEBUG_FILE
/* Need to flush and close debug file */
void charging_algorithm_close(void);
#else
/* No poweroff operation to do */
static inline void charging_algorithm_close(void) {}
#endif
#endif /* POWERMGMT_TARGET_H */

View file

@ -75,7 +75,7 @@ static void charging_screen(void)
do
{
#if CONFIG_CHARGING == CHARGING_CONTROL
#ifdef ARCHOS_RECORDER
if (charge_state == CHARGING)
msg = "charging";
else if (charge_state == TOPOFF)
@ -84,7 +84,6 @@ static void charging_screen(void)
msg = "trickle charge";
else
msg = "not charging";
#else
msg = "charging";
#endif

View file

@ -7,3 +7,5 @@ lcd-playersim.c
#endif
sim_icons.c
stubs.c
powermgmt-sim.c

View file

@ -0,0 +1,159 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese
* Revisions copyright (C) 2005 by Gerald Van Baren
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "system.h"
#include <time.h>
#include "kernel.h"
#include "powermgmt.h"
#define BATT_MINMVOLT 2500 /* minimum millivolts of battery */
#define BATT_MAXMVOLT 4500 /* maximum millivolts of battery */
#define BATT_MAXRUNTIME (10 * 60) /* maximum runtime with full battery in
minutes */
extern void send_battery_level_event(void);
extern int last_sent_battery_level;
extern int battery_percent;
static unsigned int battery_millivolts = BATT_MAXMVOLT;
/* estimated remaining time in minutes */
static int powermgmt_est_runningtime_min = BATT_MAXRUNTIME;
static void battery_status_update(void)
{
static time_t last_change = 0;
static bool charging = false;
time_t now;
time(&now);
if (last_change < now) {
last_change = now;
/* change the values: */
if (charging) {
if (battery_millivolts >= BATT_MAXMVOLT) {
/* Pretend the charger was disconnected */
charging = false;
queue_broadcast(SYS_CHARGER_DISCONNECTED, 0);
last_sent_battery_level = 100;
}
}
else {
if (battery_millivolts <= BATT_MINMVOLT) {
/* Pretend the charger was connected */
charging = true;
queue_broadcast(SYS_CHARGER_CONNECTED, 0);
last_sent_battery_level = 0;
}
}
if (charging) {
battery_millivolts += (BATT_MAXMVOLT - BATT_MINMVOLT) / 50;
}
else {
battery_millivolts -= (BATT_MAXMVOLT - BATT_MINMVOLT) / 100;
}
battery_percent = 100 * (battery_millivolts - BATT_MINMVOLT) /
(BATT_MAXMVOLT - BATT_MINMVOLT);
powermgmt_est_runningtime_min =
battery_percent * BATT_MAXRUNTIME / 100;
}
send_battery_level_event();
}
void battery_read_info(int *voltage, int *level)
{
battery_status_update();
if (voltage)
*voltage = battery_millivolts;
if (level)
*level = battery_percent;
}
unsigned int battery_voltage(void)
{
battery_status_update();
return battery_millivolts;
}
int battery_level(void)
{
battery_status_update();
return battery_percent;
}
int battery_time(void)
{
battery_status_update();
return powermgmt_est_runningtime_min;
}
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;
}
#if BATTERY_TYPES_COUNT > 1
void set_battery_type(int type)
{
(void)type;
}
#endif
#ifdef HAVE_ACCESSORY_SUPPLY
void accessory_supply_set(bool enable)
{
(void)enable;
}
#endif
void reset_poweroff_timer(void)
{
}
void shutdown_hw(void)
{
}
void sys_poweroff(void)
{
}
void cancel_shutdown(void)
{
}