Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese |
| 11 | * Revisions copyright (C) 2005 by Gerald Van Baren |
| 12 | * |
| 13 | * This program is free software; you can redistribute it and/or |
| 14 | * modify it under the terms of the GNU General Public License |
| 15 | * as published by the Free Software Foundation; either version 2 |
| 16 | * of the License, or (at your option) any later version. |
| 17 | * |
| 18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 19 | * KIND, either express or implied. |
| 20 | * |
| 21 | ****************************************************************************/ |
| 22 | #include "config.h" |
| 23 | #include "system.h" |
| 24 | #include <time.h> |
| 25 | #include "kernel.h" |
| 26 | #include "powermgmt.h" |
Thomas Martitz | c1bd9b0 | 2012-01-03 23:44:38 +0000 | [diff] [blame] | 27 | #include "power.h" |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 28 | |
Thomas Martitz | c1bd9b0 | 2012-01-03 23:44:38 +0000 | [diff] [blame] | 29 | #define BATT_MINMVOLT 3300 /* minimum millivolts of battery */ |
| 30 | #define BATT_MAXMVOLT 4300 /* maximum millivolts of battery */ |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 31 | #define BATT_MAXRUNTIME (10 * 60) /* maximum runtime with full battery in |
| 32 | minutes */ |
Nick Peskett | 8fdef40 | 2012-01-08 12:07:17 +0000 | [diff] [blame] | 33 | /* Number of millivolts to discharge the battery every second */ |
| 34 | #define BATT_DISCHARGE_STEP ((BATT_MAXMVOLT - BATT_MINMVOLT) / 100) |
| 35 | /* Number of millivolts to charge the battery every second */ |
| 36 | #define BATT_CHARGE_STEP (BATT_DISCHARGE_STEP * 2) |
| 37 | #if CONFIG_CHARGING >= CHARGING_MONITOR |
| 38 | /* Number of seconds to externally power before discharging again */ |
| 39 | #define POWER_AFTER_CHARGE_TICKS (8 * HZ) |
| 40 | #endif |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 41 | |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 42 | extern int battery_percent; |
Thomas Martitz | c1bd9b0 | 2012-01-03 23:44:38 +0000 | [diff] [blame] | 43 | static bool charging = false; |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 44 | static unsigned int battery_millivolts = BATT_MAXMVOLT; |
Thomas Martitz | c1bd9b0 | 2012-01-03 23:44:38 +0000 | [diff] [blame] | 45 | |
| 46 | void powermgmt_init_target(void) {} |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 47 | |
| 48 | static void battery_status_update(void) |
| 49 | { |
Nick Peskett | 8fdef40 | 2012-01-08 12:07:17 +0000 | [diff] [blame] | 50 | /* Delay next battery update until tick */ |
| 51 | static long update_after_tick = 0; |
| 52 | #if CONFIG_CHARGING >= CHARGING_MONITOR |
| 53 | /* When greater than 0, the tick to unplug the external power at */ |
| 54 | static unsigned int ext_power_until_tick = 0; |
Nick Peskett | 7b37686 | 2012-01-05 22:25:13 +0000 | [diff] [blame] | 55 | #endif |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 56 | |
Nick Peskett | 8fdef40 | 2012-01-08 12:07:17 +0000 | [diff] [blame] | 57 | if TIME_BEFORE(current_tick, update_after_tick) |
| 58 | return; |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 59 | |
Nick Peskett | 8fdef40 | 2012-01-08 12:07:17 +0000 | [diff] [blame] | 60 | update_after_tick = current_tick + HZ; |
| 61 | |
| 62 | #if CONFIG_CHARGING >= CHARGING_MONITOR |
| 63 | /* Handle period of being externally powered */ |
| 64 | if (ext_power_until_tick > 0) { |
| 65 | if (TIME_AFTER(current_tick, ext_power_until_tick)) { |
| 66 | /* Pretend the charger was disconnected */ |
| 67 | charger_input_state = CHARGER_UNPLUGGED; |
| 68 | ext_power_until_tick = 0; |
| 69 | } |
| 70 | return; |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 71 | } |
Nick Peskett | 8fdef40 | 2012-01-08 12:07:17 +0000 | [diff] [blame] | 72 | #endif |
| 73 | |
| 74 | if (charging) { |
| 75 | battery_millivolts += BATT_CHARGE_STEP; |
| 76 | if (battery_millivolts >= BATT_MAXMVOLT) { |
| 77 | charging = false; |
| 78 | battery_percent = 100; |
| 79 | #if CONFIG_CHARGING >= CHARGING_MONITOR |
| 80 | /* Keep external power until tick */ |
| 81 | ext_power_until_tick = current_tick + POWER_AFTER_CHARGE_TICKS; |
| 82 | #elif CONFIG_CHARGING |
| 83 | /* Pretend the charger was disconnected */ |
| 84 | charger_input_state = CHARGER_UNPLUGGED; |
| 85 | #endif |
| 86 | return; |
| 87 | } |
| 88 | } else { |
| 89 | battery_millivolts -= BATT_DISCHARGE_STEP; |
| 90 | if (battery_millivolts <= BATT_MINMVOLT) { |
| 91 | charging = true; |
| 92 | battery_percent = 0; |
| 93 | #if CONFIG_CHARGING |
| 94 | /* Pretend the charger was connected */ |
| 95 | charger_input_state = CHARGER_PLUGGED; |
| 96 | #endif |
| 97 | return; |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | battery_percent = 100 * (battery_millivolts - BATT_MINMVOLT) / |
| 102 | (BATT_MAXMVOLT - BATT_MINMVOLT); |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 103 | } |
| 104 | |
Thomas Martitz | c1bd9b0 | 2012-01-03 23:44:38 +0000 | [diff] [blame] | 105 | const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = { 3200 }; |
| 106 | const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = { 3200 }; |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 107 | |
Thomas Martitz | c1bd9b0 | 2012-01-03 23:44:38 +0000 | [diff] [blame] | 108 | /* make the simulated curve nicely linear */ |
| 109 | const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = |
| 110 | { { 3300, 3400, 3500, 3600, 3700, 3800, 3900, 4000, 4100, 4200, 4300 } }; |
| 111 | const unsigned short percent_to_volt_charge[11] = |
| 112 | { 3300, 3400, 3500, 3600, 3700, 3800, 3900, 4000, 4100, 4200, 4300 }; |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 113 | |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 114 | |
Thomas Martitz | c1bd9b0 | 2012-01-03 23:44:38 +0000 | [diff] [blame] | 115 | int _battery_voltage(void) |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 116 | { |
| 117 | battery_status_update(); |
| 118 | return battery_millivolts; |
| 119 | } |
| 120 | |
Thomas Martitz | c1bd9b0 | 2012-01-03 23:44:38 +0000 | [diff] [blame] | 121 | #if CONFIG_CHARGING |
| 122 | unsigned int power_input_status(void) |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 123 | { |
Michael Sevakis | 7ccd2c9 | 2012-01-25 12:02:54 -0500 | [diff] [blame] | 124 | unsigned int status = charger_input_state >= CHARGER_PLUGGED |
Nick Peskett | 8fdef40 | 2012-01-08 12:07:17 +0000 | [diff] [blame] | 125 | ? POWER_INPUT_CHARGER : POWER_INPUT_NONE; |
Michael Sevakis | 7ccd2c9 | 2012-01-25 12:02:54 -0500 | [diff] [blame] | 126 | |
| 127 | #ifdef HAVE_BATTERY_SWITCH |
| 128 | status |= POWER_INPUT_BATTERY; |
| 129 | #endif |
| 130 | |
| 131 | return status; |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 132 | } |
| 133 | |
Thomas Martitz | c1bd9b0 | 2012-01-03 23:44:38 +0000 | [diff] [blame] | 134 | bool charging_state(void) |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 135 | { |
Thomas Martitz | c1bd9b0 | 2012-01-03 23:44:38 +0000 | [diff] [blame] | 136 | return charging; |
Michael Sevakis | 3157e13 | 2008-12-24 16:58:41 +0000 | [diff] [blame] | 137 | } |
| 138 | #endif |
| 139 | |
| 140 | #ifdef HAVE_ACCESSORY_SUPPLY |
| 141 | void accessory_supply_set(bool enable) |
| 142 | { |
| 143 | (void)enable; |
| 144 | } |
| 145 | #endif |
| 146 | |
Andree Buschmann | b6c12a1 | 2010-03-20 15:02:29 +0000 | [diff] [blame] | 147 | #ifdef HAVE_LINEOUT_POWEROFF |
| 148 | void lineout_set(bool enable) |
| 149 | { |
| 150 | (void)enable; |
| 151 | } |
| 152 | #endif |
Thomas Martitz | 5d9759a | 2012-01-04 00:07:27 +0000 | [diff] [blame] | 153 | |
| 154 | #ifdef HAVE_REMOTE_LCD |
| 155 | bool remote_detect(void) |
| 156 | { |
| 157 | return true; |
| 158 | } |
| 159 | #endif |
| 160 | |
| 161 | #ifdef HAVE_BATTERY_SWITCH |
| 162 | unsigned int input_millivolts(void) |
| 163 | { |
| 164 | if ((power_input_status() & POWER_INPUT_BATTERY) == 0) { |
| 165 | /* Just return a safe value if battery isn't connected */ |
| 166 | return 4050; |
| 167 | } |
| 168 | return battery_voltage();; |
| 169 | } |
| 170 | #endif |