diff options
Diffstat (limited to 'firmware/powermgmt.c')
-rw-r--r-- | firmware/powermgmt.c | 510 |
1 files changed, 238 insertions, 272 deletions
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 13e810e926..25a9a127e7 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c | |||
@@ -52,11 +52,7 @@ | |||
52 | #include "pcf50606.h" | 52 | #include "pcf50606.h" |
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | /** Shared by sim **/ | ||
56 | static int last_sent_battery_level = 100; | 55 | static int last_sent_battery_level = 100; |
57 | /* battery level (0-100%) */ | ||
58 | int battery_percent = -1; | ||
59 | void send_battery_level_event(void); | ||
60 | static void set_sleep_timer(int seconds); | 56 | static void set_sleep_timer(int seconds); |
61 | 57 | ||
62 | static bool sleeptimer_active = false; | 58 | static bool sleeptimer_active = false; |
@@ -83,41 +79,6 @@ void handle_auto_poweroff(void); | |||
83 | static int poweroff_timeout = 0; | 79 | static int poweroff_timeout = 0; |
84 | static long last_event_tick = 0; | 80 | static long last_event_tick = 0; |
85 | 81 | ||
86 | #if CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE | ||
87 | #ifdef SIMULATOR | ||
88 | int _battery_level(void) { return -1; } | ||
89 | #endif | ||
90 | #else | ||
91 | int _battery_level(void) { return -1; } | ||
92 | #endif | ||
93 | |||
94 | #if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE | ||
95 | /* | ||
96 | * Average battery voltage and charger voltage, filtered via a digital | ||
97 | * exponential filter (aka. exponential moving average, scaled): | ||
98 | * avgbat = y[n] = (N-1)/N*y[n-1] + x[n]. battery_millivolts = y[n] / N. | ||
99 | */ | ||
100 | static unsigned int avgbat; | ||
101 | /* filtered battery voltage, millivolts */ | ||
102 | static unsigned int battery_millivolts; | ||
103 | #else | ||
104 | #ifndef SIMULATOR | ||
105 | int _battery_voltage(void) { return -1; } | ||
106 | const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11]; | ||
107 | const unsigned short percent_to_volt_charge[11]; | ||
108 | #endif | ||
109 | #endif | ||
110 | |||
111 | #if !(CONFIG_BATTERY_MEASURE & TIME_MEASURE) | ||
112 | #ifdef CURRENT_NORMAL | ||
113 | static int powermgmt_est_runningtime_min; | ||
114 | int _battery_time(void) { return powermgmt_est_runningtime_min; } | ||
115 | #else | ||
116 | int _battery_time(void) { return -1; } | ||
117 | #endif | ||
118 | #endif | ||
119 | |||
120 | /* default value, mAh */ | ||
121 | #if BATTERY_CAPACITY_INC > 0 | 82 | #if BATTERY_CAPACITY_INC > 0 |
122 | static int battery_capacity = BATTERY_CAPACITY_DEFAULT; | 83 | static int battery_capacity = BATTERY_CAPACITY_DEFAULT; |
123 | #else | 84 | #else |
@@ -141,82 +102,190 @@ static char power_stack[DEFAULT_STACK_SIZE/2]; | |||
141 | #endif | 102 | #endif |
142 | static const char power_thread_name[] = "power"; | 103 | static const char power_thread_name[] = "power"; |
143 | 104 | ||
105 | #if !(CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) | ||
106 | int _battery_level(void) { return -1; } | ||
107 | #endif | ||
108 | static int percent_now; /* Cached to avoid polling too often */ | ||
144 | 109 | ||
145 | static int voltage_to_battery_level(int battery_millivolts); | 110 | #if !(CONFIG_BATTERY_MEASURE & TIME_MEASURE) |
146 | static void battery_status_update(void); | 111 | int _battery_time(void) { return -1; } |
147 | 112 | #endif | |
148 | #if BATTERY_TYPES_COUNT > 1 | 113 | #if (CONFIG_BATTERY_MEASURE & TIME_MEASURE) || defined(CURRENT_NORMAL) |
149 | void set_battery_type(int type) | 114 | static int time_now; /* Cached to avoid polling too often */ |
150 | { | 115 | #endif |
151 | if (type != battery_type) { | ||
152 | if ((unsigned)type >= BATTERY_TYPES_COUNT) | ||
153 | type = 0; | ||
154 | 116 | ||
155 | battery_type = type; | 117 | #if !(CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE) |
156 | battery_status_update(); /* recalculate the battery status */ | 118 | int _battery_voltage(void) { return -1; } |
157 | } | 119 | #else |
158 | } | 120 | /* Data for the digital exponential filter */ |
121 | static int voltage_avg, voltage_now; | ||
159 | #endif | 122 | #endif |
160 | 123 | ||
161 | #if BATTERY_CAPACITY_INC > 0 | 124 | /* The battery level can be obtained in two ways. If the target reports |
162 | void set_battery_capacity(int capacity) | 125 | * voltage, the battery level can be estminated using percent_to_volt_* |
126 | * curves. If the target can report the percentage directly, then that | ||
127 | * will be used instead of voltage-based estimation. */ | ||
128 | int battery_level(void) | ||
163 | { | 129 | { |
164 | if (capacity > BATTERY_CAPACITY_MAX) | 130 | #ifdef HAVE_BATTERY_SWITCH |
165 | capacity = BATTERY_CAPACITY_MAX; | 131 | if ((power_input_status() & POWER_INPUT_BATTERY) == 0) |
166 | if (capacity < BATTERY_CAPACITY_MIN) | 132 | return -1; |
167 | capacity = BATTERY_CAPACITY_MIN; | 133 | #endif |
168 | |||
169 | battery_capacity = capacity; | ||
170 | 134 | ||
171 | battery_status_update(); /* recalculate the battery status */ | 135 | return percent_now; |
172 | } | 136 | } |
137 | |||
138 | /* The time remaining to full charge/discharge can be provided by the | ||
139 | * target if it has an accurate way of doing this. Otherwise, if the | ||
140 | * target defines a valid battery capacity and can report the charging | ||
141 | * and discharging current, the time remaining will be estimated based | ||
142 | * on the battery level and the actual current usage. */ | ||
143 | int battery_time(void) | ||
144 | { | ||
145 | #if (CONFIG_BATTERY_MEASURE & TIME_MEASURE) || defined(CURRENT_NORMAL) | ||
146 | return time_now; | ||
147 | #else | ||
148 | return -1; | ||
173 | #endif | 149 | #endif |
150 | } | ||
174 | 151 | ||
175 | int get_battery_capacity(void) | 152 | /* Battery voltage should always be reported if available, but it is |
153 | * optional if the the target reports battery percentage directly. */ | ||
154 | int battery_voltage(void) | ||
176 | { | 155 | { |
177 | return battery_capacity; | 156 | #if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE |
157 | return voltage_now; | ||
158 | #else | ||
159 | return -1; | ||
160 | #endif | ||
178 | } | 161 | } |
179 | 162 | ||
180 | int battery_time(void) | 163 | /* Battery current can be estimated if the target defines CURRENT_NORMAL |
164 | * as the number of milliamps usually consumed by the device in a normal | ||
165 | * state. The target can also define other CURRENT_* values to estimate | ||
166 | * the power consumed by the backlight, remote display, SPDIF, etc. */ | ||
167 | int battery_current(void) | ||
181 | { | 168 | { |
182 | #if !(CONFIG_BATTERY_MEASURE & TIME_MEASURE) | 169 | #if defined(CURRENT_NORMAL) |
183 | /* Note: This should not really be possible but it might occur | 170 | int current = CURRENT_NORMAL; |
184 | * as a degenerate case for targets that don't define any battery | 171 | |
185 | * capacity at all..? */ | 172 | #ifndef BOOTLOADER |
186 | if(battery_capacity <= 0) | 173 | if (usb_inserted() |
187 | return -1; | 174 | #ifdef HAVE_USB_POWER |
175 | #if (CURRENT_USB < CURRENT_NORMAL) | ||
176 | || usb_powered_only() | ||
177 | #else | ||
178 | && !usb_powered_only() | ||
179 | #endif | ||
180 | #endif | ||
181 | ) { | ||
182 | current = CURRENT_USB; | ||
183 | } | ||
184 | |||
185 | #if defined(HAVE_BACKLIGHT) && defined(CURRENT_BACKLIGHT) | ||
186 | if (backlight_get_current_timeout() == 0) /* LED always on */ | ||
187 | current += CURRENT_BACKLIGHT; | ||
188 | #endif | ||
189 | |||
190 | #if defined(HAVE_RECORDING) && defined(CURRENT_RECORD) | ||
191 | if (audio_status() & AUDIO_STATUS_RECORD) | ||
192 | current += CURRENT_RECORD; | ||
193 | #endif | ||
194 | |||
195 | #if defined(HAVE_SPDIF_POWER) && defined(CURRENT_SPDIF_OUT) | ||
196 | if (spdif_powered()) | ||
197 | current += CURRENT_SPDIF_OUT; | ||
188 | #endif | 198 | #endif |
189 | 199 | ||
190 | return _battery_time(); | 200 | #if defined(HAVE_REMOTE_LCD) && defined(CURRENT_REMOTE) |
201 | if (remote_detect()) | ||
202 | current += CURRENT_REMOTE; | ||
203 | #endif | ||
204 | |||
205 | #if defined(HAVE_ATA_POWER_OFF) && defined(CURRENT_ATA) | ||
206 | if (ide_powered()) | ||
207 | current += CURRENT_ATA; | ||
208 | #endif | ||
209 | |||
210 | #if CONFIG_CHARGING >= CHARGING_MONITOR | ||
211 | /* While charging we must report the charging current. */ | ||
212 | if (charging_state()) { | ||
213 | current = CURRENT_MAX_CHG - current; | ||
214 | current = MIN(current, 1); | ||
215 | } | ||
216 | #endif | ||
217 | |||
218 | #endif /* BOOTLOADER */ | ||
219 | |||
220 | return current; | ||
221 | #else | ||
222 | return -1; | ||
223 | #endif | ||
191 | } | 224 | } |
192 | 225 | ||
193 | /* Returns battery level in percent */ | 226 | /* Initialize the battery voltage filter. This is called once |
194 | int battery_level(void) | 227 | * by the power thread before entering the main polling loop. */ |
228 | static void average_init(void) | ||
195 | { | 229 | { |
196 | #ifdef HAVE_BATTERY_SWITCH | 230 | #if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE |
197 | if ((power_input_status() & POWER_INPUT_BATTERY) == 0) | 231 | voltage_now = _battery_voltage() + 15; |
198 | return -1; | 232 | |
233 | /* The battery voltage is usually a little lower directly after | ||
234 | turning on, because the disk was used heavily. Raise it by 5% */ | ||
235 | #ifdef HAVE_DISK_STORAGE | ||
236 | #if CONFIG_CHARGING | ||
237 | if(!charger_inserted()) | ||
199 | #endif | 238 | #endif |
200 | return battery_percent; | 239 | { |
240 | voltage_now += (percent_to_volt_discharge[battery_type][6] - | ||
241 | percent_to_volt_discharge[battery_type][5]) / 2; | ||
242 | } | ||
243 | #endif /* HAVE_DISK_STORAGE */ | ||
244 | |||
245 | voltage_avg = voltage_now * BATT_AVE_SAMPLES; | ||
246 | #endif /* CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE */ | ||
201 | } | 247 | } |
202 | 248 | ||
203 | /* Tells if the battery level is safe for disk writes */ | 249 | /* Sample the battery voltage and update the filter. |
204 | bool battery_level_safe(void) | 250 | * Updated once every POWER_THREAD_STEP_TICKS. */ |
251 | static void average_step(bool low_battery) | ||
205 | { | 252 | { |
206 | #if defined(NO_LOW_BATTERY_SHUTDOWN) | 253 | #if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE |
207 | return true; | 254 | int millivolts = _battery_voltage(); |
208 | #elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE | 255 | if(low_battery) { |
209 | return (battery_percent > 0); | 256 | voltage_now = (millivolts + voltage_now + 1) / 2; |
210 | #elif defined(HAVE_BATTERY_SWITCH) | 257 | voltage_avg += voltage_now - voltage_avg / BATT_AVE_SAMPLES; |
211 | /* Cannot rely upon the battery reading to be valid and the | 258 | } else { |
212 | * device could be powered externally. */ | 259 | voltage_avg += millivolts - voltage_avg / BATT_AVE_SAMPLES; |
213 | return input_millivolts() > battery_level_dangerous[battery_type]; | 260 | voltage_now = voltage_avg / BATT_AVE_SAMPLES; |
261 | } | ||
214 | #else | 262 | #else |
215 | return battery_millivolts > battery_level_dangerous[battery_type]; | 263 | (void)low_battery; |
216 | #endif | 264 | #endif |
217 | } | 265 | } |
218 | 266 | ||
219 | /* look into the percent_to_volt_* table and get a realistic battery level */ | 267 | /* Send system battery level update events on reaching certain significant |
268 | * levels. This is called by battery_status_update() and does not have to | ||
269 | * be called separately. */ | ||
270 | static void send_battery_level_event(int percent) | ||
271 | { | ||
272 | static const int levels[] = { 5, 15, 30, 50, 0 }; | ||
273 | const int *level = levels; | ||
274 | |||
275 | while (*level) | ||
276 | { | ||
277 | if (percent <= *level && last_sent_battery_level > *level) { | ||
278 | last_sent_battery_level = *level; | ||
279 | queue_broadcast(SYS_BATTERY_UPDATE, last_sent_battery_level); | ||
280 | break; | ||
281 | } | ||
282 | |||
283 | level++; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | #if !(CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) | ||
288 | /* Look into the percent_to_volt_* table and estimate the battery level. */ | ||
220 | static int voltage_to_percent(int voltage, const short* table) | 289 | static int voltage_to_percent(int voltage, const short* table) |
221 | { | 290 | { |
222 | if (voltage <= table[0]) { | 291 | if (voltage <= table[0]) { |
@@ -238,20 +307,19 @@ static int voltage_to_percent(int voltage, const short* table) | |||
238 | } | 307 | } |
239 | } | 308 | } |
240 | 309 | ||
241 | /* update battery level and estimated runtime, called once per minute or | 310 | /* Convert voltage to a battery level percentage using the appropriate |
242 | * when battery capacity / type settings are changed */ | 311 | * percent_to_volt_* lookup table. */ |
243 | static int voltage_to_battery_level(int battery_millivolts) | 312 | static int voltage_to_battery_level(int millivolts) |
244 | { | 313 | { |
245 | int level; | 314 | int level; |
246 | 315 | ||
247 | if (battery_millivolts < 0) | 316 | if (millivolts < 0) |
248 | return -1; | 317 | return -1; |
249 | 318 | ||
250 | #if CONFIG_CHARGING >= CHARGING_MONITOR | 319 | #if CONFIG_CHARGING >= CHARGING_MONITOR |
251 | if (charging_state()) { | 320 | if (charging_state()) { |
252 | /* battery level is defined to be < 100% until charging is finished */ | 321 | /* battery level is defined to be < 100% until charging is finished */ |
253 | level = voltage_to_percent(battery_millivolts, | 322 | level = voltage_to_percent(millivolts, percent_to_volt_charge); |
254 | percent_to_volt_charge); | ||
255 | if (level > 99) | 323 | if (level > 99) |
256 | level = 99; | 324 | level = 99; |
257 | } | 325 | } |
@@ -259,105 +327,98 @@ static int voltage_to_battery_level(int battery_millivolts) | |||
259 | #endif /* CONFIG_CHARGING >= CHARGING_MONITOR */ | 327 | #endif /* CONFIG_CHARGING >= CHARGING_MONITOR */ |
260 | { | 328 | { |
261 | /* DISCHARGING or error state */ | 329 | /* DISCHARGING or error state */ |
262 | level = voltage_to_percent(battery_millivolts, | 330 | level = voltage_to_percent(millivolts, percent_to_volt_discharge[battery_type]); |
263 | percent_to_volt_discharge[battery_type]); | ||
264 | } | 331 | } |
265 | 332 | ||
266 | return level; | 333 | return level; |
267 | } | 334 | } |
335 | #endif | ||
268 | 336 | ||
337 | /* Update battery percentage and time remaining information. | ||
338 | * | ||
339 | * This will be called by the power thread after polling new battery data. | ||
340 | * It must also be called if the battery type or capacity changes. | ||
341 | */ | ||
269 | static void battery_status_update(void) | 342 | static void battery_status_update(void) |
270 | { | 343 | { |
271 | int millivolt = battery_voltage(); | 344 | #if CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE |
272 | int level = _battery_level(); | 345 | int level = _battery_level(); |
346 | #elif CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE | ||
347 | int level = voltage_to_battery_level(voltage_now); | ||
348 | #else | ||
349 | /* This should be a compile time error? */ | ||
350 | int level = -1; | ||
351 | #endif | ||
273 | 352 | ||
274 | if (level < 0) | 353 | #if CONFIG_BATTERY_MEASURE & TIME_MEASURE |
275 | level = voltage_to_battery_level(millivolt); | 354 | time_now = _battery_time(); |
276 | 355 | #elif defined(CURRENT_NORMAL) | |
277 | #ifdef CURRENT_NORMAL | ||
278 | int current = battery_current(); | 356 | int current = battery_current(); |
279 | 357 | if(level >= 0 && current > 0 && battery_capacity > 0) { | |
280 | #if CONFIG_CHARGING >= CHARGING_MONITOR | 358 | #if CONFIG_CHARGING >= CHARGING_MONITOR |
281 | if (charging_state()) { | 359 | if (charging_state()) |
282 | /* charging: remaining charging time */ | 360 | time_now = (100 - level) * battery_capacity * 60 / 100 / current; |
283 | if(current > 0) { | 361 | else |
284 | powermgmt_est_runningtime_min = | 362 | #endif |
285 | (100 - level) * battery_capacity * 60 / 100 / current; | 363 | time_now = (level + percent_now) * battery_capacity * 60 / 200 / current; |
286 | } | 364 | } else { |
365 | /* not enough information to calculate time remaining */ | ||
366 | time_now = -1; | ||
287 | } | 367 | } |
288 | else | ||
289 | #endif | ||
290 | |||
291 | /* discharging: remaining running time */ | ||
292 | if (level >= 0 && current > 0) { | ||
293 | powermgmt_est_runningtime_min = | ||
294 | (level + battery_percent) * battery_capacity * 60 / 200 / current; | ||
295 | } | ||
296 | |||
297 | if (powermgmt_est_runningtime_min < 0 || current <= 0) | ||
298 | powermgmt_est_runningtime_min = 0; | ||
299 | #endif | 368 | #endif |
300 | 369 | ||
301 | battery_percent = level; | 370 | percent_now = level; |
302 | send_battery_level_event(); | 371 | send_battery_level_event(level); |
303 | } | 372 | } |
304 | 373 | ||
305 | #ifdef CURRENT_NORMAL | 374 | #if BATTERY_TYPES_COUNT > 1 |
306 | int battery_current(void) | 375 | void set_battery_type(int type) |
307 | { | 376 | { |
308 | int current = CURRENT_NORMAL; | 377 | if(type < 0 || type > BATTERY_TYPES_COUNT) |
378 | type = 0; | ||
309 | 379 | ||
310 | #ifndef BOOTLOADER | 380 | if (type != battery_type) { |
311 | if (usb_inserted() | 381 | battery_type = type; |
312 | #ifdef HAVE_USB_POWER | 382 | battery_status_update(); /* recalculate the battery status */ |
313 | #if (CURRENT_USB < CURRENT_NORMAL) | ||
314 | || usb_powered_only() | ||
315 | #else | ||
316 | && !usb_powered_only() | ||
317 | #endif | ||
318 | #endif | ||
319 | ) { | ||
320 | current = CURRENT_USB; | ||
321 | } | 383 | } |
322 | 384 | } | |
323 | #if defined(HAVE_BACKLIGHT) && defined(CURRENT_BACKLIGHT) | ||
324 | if (backlight_get_current_timeout() == 0) /* LED always on */ | ||
325 | current += CURRENT_BACKLIGHT; | ||
326 | #endif | ||
327 | |||
328 | #if defined(HAVE_RECORDING) && defined(CURRENT_RECORD) | ||
329 | if (audio_status() & AUDIO_STATUS_RECORD) | ||
330 | current += CURRENT_RECORD; | ||
331 | #endif | ||
332 | |||
333 | #if defined(HAVE_SPDIF_POWER) && defined(CURRENT_SPDIF_OUT) | ||
334 | if (spdif_powered()) | ||
335 | current += CURRENT_SPDIF_OUT; | ||
336 | #endif | ||
337 | |||
338 | #if defined(HAVE_REMOTE_LCD) && defined(CURRENT_REMOTE) | ||
339 | if (remote_detect()) | ||
340 | current += CURRENT_REMOTE; | ||
341 | #endif | 385 | #endif |
342 | 386 | ||
343 | #if defined(HAVE_ATA_POWER_OFF) && defined(CURRENT_ATA) | 387 | #if BATTERY_CAPACITY_INC > 0 |
344 | if (ide_powered()) | 388 | void set_battery_capacity(int capacity) |
345 | current += CURRENT_ATA; | 389 | { |
346 | #endif | 390 | if (capacity > BATTERY_CAPACITY_MAX) |
391 | capacity = BATTERY_CAPACITY_MAX; | ||
392 | if (capacity < BATTERY_CAPACITY_MIN) | ||
393 | capacity = BATTERY_CAPACITY_MIN; | ||
347 | 394 | ||
348 | #if CONFIG_CHARGING >= CHARGING_MONITOR | 395 | if (capacity != battery_capacity) { |
349 | /* While charging we must report the charging current. */ | 396 | battery_capacity = capacity; |
350 | if (charging_state()) { | 397 | battery_status_update(); /* recalculate the battery status */ |
351 | current = CURRENT_MAX_CHG - current; | ||
352 | current = MIN(current, 1); | ||
353 | } | 398 | } |
399 | } | ||
354 | #endif | 400 | #endif |
355 | 401 | ||
356 | #endif /* BOOTLOADER */ | 402 | int get_battery_capacity(void) |
403 | { | ||
404 | return battery_capacity; | ||
405 | } | ||
357 | 406 | ||
358 | return current; | 407 | /* Tells if the battery level is safe for disk writes */ |
408 | bool battery_level_safe(void) | ||
409 | { | ||
410 | #if defined(NO_LOW_BATTERY_SHUTDOWN) | ||
411 | return true; | ||
412 | #elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE | ||
413 | return percent_now > 0; | ||
414 | #elif defined(HAVE_BATTERY_SWITCH) | ||
415 | /* Cannot rely upon the battery reading to be valid and the | ||
416 | * device could be powered externally. */ | ||
417 | return input_millivolts() > battery_level_dangerous[battery_type]; | ||
418 | #else | ||
419 | return voltage_now > battery_level_dangerous[battery_type]; | ||
420 | #endif | ||
359 | } | 421 | } |
360 | #endif /* CURRENT_NORMAL */ | ||
361 | 422 | ||
362 | /* Check to see whether or not we've received an alarm in the last second */ | 423 | /* Check to see whether or not we've received an alarm in the last second */ |
363 | #ifdef HAVE_RTC_ALARM | 424 | #ifdef HAVE_RTC_ALARM |
@@ -374,13 +435,13 @@ bool query_force_shutdown(void) | |||
374 | #if defined(NO_LOW_BATTERY_SHUTDOWN) | 435 | #if defined(NO_LOW_BATTERY_SHUTDOWN) |
375 | return false; | 436 | return false; |
376 | #elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE | 437 | #elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE |
377 | return battery_percent == 0; | 438 | return percent_now == 0; |
378 | #elif defined(HAVE_BATTERY_SWITCH) | 439 | #elif defined(HAVE_BATTERY_SWITCH) |
379 | /* Cannot rely upon the battery reading to be valid and the | 440 | /* Cannot rely upon the battery reading to be valid and the |
380 | * device could be powered externally. */ | 441 | * device could be powered externally. */ |
381 | return input_millivolts() < battery_level_shutoff[battery_type]; | 442 | return input_millivolts() < battery_level_shutoff[battery_type]; |
382 | #else | 443 | #else |
383 | return battery_millivolts < battery_level_shutoff[battery_type]; | 444 | return voltage_now < battery_level_shutoff[battery_type]; |
384 | #endif | 445 | #endif |
385 | } | 446 | } |
386 | 447 | ||
@@ -391,8 +452,8 @@ bool query_force_shutdown(void) | |||
391 | */ | 452 | */ |
392 | void reset_battery_filter(int millivolts) | 453 | void reset_battery_filter(int millivolts) |
393 | { | 454 | { |
394 | avgbat = millivolts * BATT_AVE_SAMPLES; | 455 | voltage_avg = millivolts * BATT_AVE_SAMPLES; |
395 | battery_millivolts = millivolts; | 456 | voltage_now = millivolts; |
396 | battery_status_update(); | 457 | battery_status_update(); |
397 | } | 458 | } |
398 | #endif /* HAVE_BATTERY_SWITCH */ | 459 | #endif /* HAVE_BATTERY_SWITCH */ |
@@ -529,88 +590,14 @@ static inline bool detect_charger(unsigned int pwr) | |||
529 | 590 | ||
530 | 591 | ||
531 | #if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE | 592 | #if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE |
532 | /* Returns filtered battery voltage [millivolts] */ | ||
533 | int battery_voltage(void) | ||
534 | { | ||
535 | return battery_millivolts; | ||
536 | } | ||
537 | |||
538 | static void average_init(void) | ||
539 | { | ||
540 | /* initialize the voltages for the exponential filter */ | ||
541 | avgbat = _battery_voltage() + 15; | ||
542 | |||
543 | #ifdef HAVE_DISK_STORAGE /* this adjustment is only needed for HD based */ | ||
544 | /* The battery voltage is usually a little lower directly after | ||
545 | turning on, because the disk was used heavily. Raise it by 5% */ | ||
546 | #if CONFIG_CHARGING | ||
547 | if (!charger_inserted()) /* only if charger not connected */ | ||
548 | #endif | ||
549 | { | ||
550 | avgbat += (percent_to_volt_discharge[battery_type][6] - | ||
551 | percent_to_volt_discharge[battery_type][5]) / 2; | ||
552 | } | ||
553 | #endif /* HAVE_DISK_STORAGE */ | ||
554 | |||
555 | avgbat = avgbat * BATT_AVE_SAMPLES; | ||
556 | battery_millivolts = power_history[0] = avgbat / BATT_AVE_SAMPLES; | ||
557 | } | ||
558 | |||
559 | static void average_step(void) | ||
560 | { | ||
561 | avgbat += _battery_voltage() - avgbat / BATT_AVE_SAMPLES; | ||
562 | /* | ||
563 | * battery_millivolts is the millivolt-scaled filtered battery value. | ||
564 | */ | ||
565 | battery_millivolts = avgbat / BATT_AVE_SAMPLES; | ||
566 | } | ||
567 | |||
568 | static void average_step_low(void) | ||
569 | { | ||
570 | battery_millivolts = (_battery_voltage() + battery_millivolts + 1) / 2; | ||
571 | avgbat += battery_millivolts - avgbat / BATT_AVE_SAMPLES; | ||
572 | } | ||
573 | |||
574 | static void init_battery_percent(void) | ||
575 | { | ||
576 | #if CONFIG_CHARGING | ||
577 | if (charger_inserted()) { | ||
578 | battery_percent = voltage_to_percent(battery_millivolts, | ||
579 | percent_to_volt_charge); | ||
580 | } | ||
581 | else | ||
582 | #endif | ||
583 | { | ||
584 | battery_percent = voltage_to_percent(battery_millivolts, | ||
585 | percent_to_volt_discharge[battery_type]); | ||
586 | battery_percent += battery_percent < 100; | ||
587 | } | ||
588 | |||
589 | } | ||
590 | |||
591 | static int power_hist_item(void) | 593 | static int power_hist_item(void) |
592 | { | 594 | { |
593 | return battery_millivolts; | 595 | return voltage_now; |
594 | } | 596 | } |
595 | #define power_history_unit() battery_millivolts | ||
596 | |||
597 | #else | 597 | #else |
598 | int battery_voltage(void) | ||
599 | { | ||
600 | return -1; | ||
601 | } | ||
602 | |||
603 | static void average_init(void) {} | ||
604 | static void average_step(void) {} | ||
605 | static void average_step_low(void) {} | ||
606 | static void init_battery_percent(void) | ||
607 | { | ||
608 | battery_percent = _battery_level(); | ||
609 | } | ||
610 | |||
611 | static int power_hist_item(void) | 598 | static int power_hist_item(void) |
612 | { | 599 | { |
613 | return battery_percent; | 600 | return percent_now; |
614 | } | 601 | } |
615 | #endif | 602 | #endif |
616 | 603 | ||
@@ -651,13 +638,11 @@ static inline void power_thread_step(void) | |||
651 | || charger_input_state == CHARGER | 638 | || charger_input_state == CHARGER |
652 | #endif | 639 | #endif |
653 | ) { | 640 | ) { |
654 | average_step(); | 641 | average_step(false); |
655 | /* update battery status every time an update is available */ | ||
656 | battery_status_update(); | 642 | battery_status_update(); |
657 | } | 643 | } |
658 | else if (battery_percent < 8) { | 644 | else if (percent_now < 8) { |
659 | average_step_low(); | 645 | average_step(true); |
660 | /* update battery status every time an update is available */ | ||
661 | battery_status_update(); | 646 | battery_status_update(); |
662 | 647 | ||
663 | /* | 648 | /* |
@@ -703,7 +688,7 @@ static void power_thread(void) | |||
703 | /* initialize voltage averaging (if available) */ | 688 | /* initialize voltage averaging (if available) */ |
704 | average_init(); | 689 | average_init(); |
705 | /* get initial battery level value (in %) */ | 690 | /* get initial battery level value (in %) */ |
706 | init_battery_percent(); | 691 | battery_status_update(); |
707 | /* get some initial data for the power curve */ | 692 | /* get some initial data for the power curve */ |
708 | collect_power_history(); | 693 | collect_power_history(); |
709 | 694 | ||
@@ -848,25 +833,6 @@ void cancel_shutdown(void) | |||
848 | shutdown_timeout = 0; | 833 | shutdown_timeout = 0; |
849 | } | 834 | } |
850 | 835 | ||
851 | /* Send system battery level update events on reaching certain significant | ||
852 | levels. This must be called after battery_percent has been updated. */ | ||
853 | void send_battery_level_event(void) | ||
854 | { | ||
855 | static const int levels[] = { 5, 15, 30, 50, 0 }; | ||
856 | const int *level = levels; | ||
857 | |||
858 | while (*level) | ||
859 | { | ||
860 | if (battery_percent <= *level && last_sent_battery_level > *level) { | ||
861 | last_sent_battery_level = *level; | ||
862 | queue_broadcast(SYS_BATTERY_UPDATE, last_sent_battery_level); | ||
863 | break; | ||
864 | } | ||
865 | |||
866 | level++; | ||
867 | } | ||
868 | } | ||
869 | |||
870 | void set_sleeptimer_duration(int minutes) | 836 | void set_sleeptimer_duration(int minutes) |
871 | { | 837 | { |
872 | set_sleep_timer(minutes * 60); | 838 | set_sleep_timer(minutes * 60); |