rockbox/uisimulator/common/powermgmt-sim.c
Aidan MacDonald ad05c872fe powermgmt: Add battery current measurement
This allows targets to report the actual discharging or
charging current if they are able to.

Change-Id: I0b538e6ac94346f1434e45f83c8da8c1260a53a3
2021-12-23 11:39:58 +00:00

196 lines
5.6 KiB
C

/***************************************************************************
* __________ __ ___.
* 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"
#include "power.h"
#define BATT_MINMVOLT 3300 /* minimum millivolts of battery */
#define BATT_MAXMVOLT 4300 /* maximum millivolts of battery */
#define BATT_MAXRUNTIME (10 * 60) /* maximum runtime with full battery in
minutes */
/* Number of millivolts to discharge the battery every second */
#define BATT_DISCHARGE_STEP ((BATT_MAXMVOLT - BATT_MINMVOLT) / 100)
/* Number of millivolts to charge the battery every second */
#define BATT_CHARGE_STEP (BATT_DISCHARGE_STEP * 2)
#if CONFIG_CHARGING >= CHARGING_MONITOR
/* Number of seconds to externally power before discharging again */
#define POWER_AFTER_CHARGE_TICKS (8 * HZ)
#endif
static bool charging = false;
static unsigned int batt_millivolts = BATT_MAXMVOLT;
static unsigned int batt_percent = 100;
static unsigned int batt_runtime = BATT_MAXRUNTIME;
static unsigned int batt_current = 0;
void powermgmt_init_target(void) {}
static void battery_status_update(void)
{
/* Delay next battery update until tick */
static long update_after_tick = 0;
#if CONFIG_CHARGING >= CHARGING_MONITOR
/* When greater than 0, the tick to unplug the external power at */
static unsigned int ext_power_until_tick = 0;
#endif
if(TIME_BEFORE(current_tick, update_after_tick))
return;
update_after_tick = current_tick + HZ;
#if CONFIG_CHARGING >= CHARGING_MONITOR
/* Handle period of being externally powered */
if (ext_power_until_tick > 0) {
if (TIME_AFTER(current_tick, ext_power_until_tick)) {
/* Pretend the charger was disconnected */
charger_input_state = CHARGER_UNPLUGGED;
ext_power_until_tick = 0;
}
return;
}
#endif
if (charging) {
batt_millivolts += BATT_CHARGE_STEP;
if (batt_millivolts >= BATT_MAXMVOLT) {
charging = false;
#if CONFIG_CHARGING >= CHARGING_MONITOR
/* Keep external power until tick */
ext_power_until_tick = current_tick + POWER_AFTER_CHARGE_TICKS;
#elif CONFIG_CHARGING
/* Pretend the charger was disconnected */
charger_input_state = CHARGER_UNPLUGGED;
#endif
}
} else {
batt_millivolts -= BATT_DISCHARGE_STEP;
if (batt_millivolts <= BATT_MINMVOLT) {
charging = true;
#if CONFIG_CHARGING
/* Pretend the charger was connected */
charger_input_state = CHARGER_PLUGGED;
#endif
}
}
batt_percent = (batt_millivolts - BATT_MINMVOLT) / (BATT_MAXMVOLT - BATT_MINMVOLT);
batt_runtime = batt_percent * BATT_MAXRUNTIME;
/* current is completely bogus... */
batt_current = charging ? BATT_CHARGE_STEP : BATT_DISCHARGE_STEP;
}
const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = { 3200 };
const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = { 3200 };
/* make the simulated curve nicely linear */
const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
{ { 3300, 3400, 3500, 3600, 3700, 3800, 3900, 4000, 4100, 4200, 4300 } };
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 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)
int _battery_time(void)
{
battery_status_update();
return batt_runtime;
}
#endif
#if (CONFIG_BATTERY_MEASURE & CURRENT_MEASURE)
int _battery_current(void)
{
battery_status_update();
return batt_current;
}
#endif
#if CONFIG_CHARGING
unsigned int power_input_status(void)
{
unsigned int status = charger_input_state >= CHARGER_PLUGGED
? POWER_INPUT_CHARGER : POWER_INPUT_NONE;
#ifdef HAVE_BATTERY_SWITCH
status |= POWER_INPUT_BATTERY;
#endif
return status;
}
bool charging_state(void)
{
return charging;
}
#endif
#ifdef HAVE_ACCESSORY_SUPPLY
void accessory_supply_set(bool enable)
{
(void)enable;
}
#endif
#ifdef HAVE_LINEOUT_POWEROFF
void lineout_set(bool enable)
{
(void)enable;
}
#endif
#ifdef HAVE_REMOTE_LCD
bool remote_detect(void)
{
return true;
}
#endif
#ifdef HAVE_BATTERY_SWITCH
unsigned int input_millivolts(void)
{
if ((power_input_status() & POWER_INPUT_BATTERY) == 0) {
/* Just return a safe value if battery isn't connected */
return 4050;
}
return battery_voltage();
}
#endif