summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-12-12 12:30:50 +0000
committerAidan MacDonald <amachronic@protonmail.com>2021-12-23 00:12:43 +0000
commit4506f2b58d533a5cf0055f43d234a19fa3ae2bdb (patch)
tree72cf14e1389f5b539394d0132bebc1d2aca96119
parentd6faef8205ef7aedaa81571c05c886150c9c581b (diff)
downloadrockbox-4506f2b58d533a5cf0055f43d234a19fa3ae2bdb.tar.gz
rockbox-4506f2b58d533a5cf0055f43d234a19fa3ae2bdb.zip
powermgmt: Refactor battery measurement code
I've tried to clean up cruft and clarify what's being done, prior to adding new features. The behavior should be unchanged. Change-Id: If8a68b7b48173d283df981a21cdd854b714e7695
-rw-r--r--firmware/powermgmt.c510
-rw-r--r--uisimulator/common/powermgmt-sim.c45
2 files changed, 266 insertions, 289 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 **/
56static int last_sent_battery_level = 100; 55static int last_sent_battery_level = 100;
57/* battery level (0-100%) */
58int battery_percent = -1;
59void send_battery_level_event(void);
60static void set_sleep_timer(int seconds); 56static void set_sleep_timer(int seconds);
61 57
62static bool sleeptimer_active = false; 58static bool sleeptimer_active = false;
@@ -83,41 +79,6 @@ void handle_auto_poweroff(void);
83static int poweroff_timeout = 0; 79static int poweroff_timeout = 0;
84static long last_event_tick = 0; 80static long last_event_tick = 0;
85 81
86#if CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE
87#ifdef SIMULATOR
88int _battery_level(void) { return -1; }
89#endif
90#else
91int _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 */
100static unsigned int avgbat;
101/* filtered battery voltage, millivolts */
102static unsigned int battery_millivolts;
103#else
104#ifndef SIMULATOR
105int _battery_voltage(void) { return -1; }
106const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11];
107const unsigned short percent_to_volt_charge[11];
108#endif
109#endif
110
111#if !(CONFIG_BATTERY_MEASURE & TIME_MEASURE)
112#ifdef CURRENT_NORMAL
113static int powermgmt_est_runningtime_min;
114int _battery_time(void) { return powermgmt_est_runningtime_min; }
115#else
116int _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
122static int battery_capacity = BATTERY_CAPACITY_DEFAULT; 83static 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
142static const char power_thread_name[] = "power"; 103static const char power_thread_name[] = "power";
143 104
105#if !(CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE)
106int _battery_level(void) { return -1; }
107#endif
108static int percent_now; /* Cached to avoid polling too often */
144 109
145static int voltage_to_battery_level(int battery_millivolts); 110#if !(CONFIG_BATTERY_MEASURE & TIME_MEASURE)
146static void battery_status_update(void); 111int _battery_time(void) { return -1; }
147 112#endif
148#if BATTERY_TYPES_COUNT > 1 113#if (CONFIG_BATTERY_MEASURE & TIME_MEASURE) || defined(CURRENT_NORMAL)
149void set_battery_type(int type) 114static 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 */ 118int _battery_voltage(void) { return -1; }
157 } 119#else
158} 120/* Data for the digital exponential filter */
121static 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
162void 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. */
128int 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. */
143int 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
175int 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. */
154int 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
180int 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. */
167int 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
194int battery_level(void) 227 * by the power thread before entering the main polling loop. */
228static 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.
204bool battery_level_safe(void) 250 * Updated once every POWER_THREAD_STEP_TICKS. */
251static 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. */
270static 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. */
220static int voltage_to_percent(int voltage, const short* table) 289static 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. */
243static int voltage_to_battery_level(int battery_millivolts) 312static 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 */
269static void battery_status_update(void) 342static 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
306int battery_current(void) 375void 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()) 388void 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 */ 402int 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 */
408bool 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 */
392void reset_battery_filter(int millivolts) 453void 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] */
533int battery_voltage(void)
534{
535 return battery_millivolts;
536}
537
538static 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
559static 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
568static 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
574static 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
591static int power_hist_item(void) 593static 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
598int battery_voltage(void)
599{
600 return -1;
601}
602
603static void average_init(void) {}
604static void average_step(void) {}
605static void average_step_low(void) {}
606static void init_battery_percent(void)
607{
608 battery_percent = _battery_level();
609}
610
611static int power_hist_item(void) 598static 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. */
853void 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
870void set_sleeptimer_duration(int minutes) 836void set_sleeptimer_duration(int minutes)
871{ 837{
872 set_sleep_timer(minutes * 60); 838 set_sleep_timer(minutes * 60);
diff --git a/uisimulator/common/powermgmt-sim.c b/uisimulator/common/powermgmt-sim.c
index 511648bc9d..5d669bcae2 100644
--- a/uisimulator/common/powermgmt-sim.c
+++ b/uisimulator/common/powermgmt-sim.c
@@ -39,9 +39,10 @@
39#define POWER_AFTER_CHARGE_TICKS (8 * HZ) 39#define POWER_AFTER_CHARGE_TICKS (8 * HZ)
40#endif 40#endif
41 41
42extern int battery_percent;
43static bool charging = false; 42static bool charging = false;
44static unsigned int battery_millivolts = BATT_MAXMVOLT; 43static unsigned int batt_millivolts = BATT_MAXMVOLT;
44static unsigned int batt_percent = 100;
45static unsigned int batt_runtime = BATT_MAXRUNTIME;
45 46
46void powermgmt_init_target(void) {} 47void powermgmt_init_target(void) {}
47 48
@@ -54,7 +55,7 @@ static void battery_status_update(void)
54 static unsigned int ext_power_until_tick = 0; 55 static unsigned int ext_power_until_tick = 0;
55#endif 56#endif
56 57
57 if TIME_BEFORE(current_tick, update_after_tick) 58 if(TIME_BEFORE(current_tick, update_after_tick))
58 return; 59 return;
59 60
60 update_after_tick = current_tick + HZ; 61 update_after_tick = current_tick + HZ;
@@ -72,10 +73,9 @@ static void battery_status_update(void)
72#endif 73#endif
73 74
74 if (charging) { 75 if (charging) {
75 battery_millivolts += BATT_CHARGE_STEP; 76 batt_millivolts += BATT_CHARGE_STEP;
76 if (battery_millivolts >= BATT_MAXMVOLT) { 77 if (batt_millivolts >= BATT_MAXMVOLT) {
77 charging = false; 78 charging = false;
78 battery_percent = 100;
79#if CONFIG_CHARGING >= CHARGING_MONITOR 79#if CONFIG_CHARGING >= CHARGING_MONITOR
80 /* Keep external power until tick */ 80 /* Keep external power until tick */
81 ext_power_until_tick = current_tick + POWER_AFTER_CHARGE_TICKS; 81 ext_power_until_tick = current_tick + POWER_AFTER_CHARGE_TICKS;
@@ -83,23 +83,20 @@ static void battery_status_update(void)
83 /* Pretend the charger was disconnected */ 83 /* Pretend the charger was disconnected */
84 charger_input_state = CHARGER_UNPLUGGED; 84 charger_input_state = CHARGER_UNPLUGGED;
85#endif 85#endif
86 return;
87 } 86 }
88 } else { 87 } else {
89 battery_millivolts -= BATT_DISCHARGE_STEP; 88 batt_millivolts -= BATT_DISCHARGE_STEP;
90 if (battery_millivolts <= BATT_MINMVOLT) { 89 if (batt_millivolts <= BATT_MINMVOLT) {
91 charging = true; 90 charging = true;
92 battery_percent = 0;
93#if CONFIG_CHARGING 91#if CONFIG_CHARGING
94 /* Pretend the charger was connected */ 92 /* Pretend the charger was connected */
95 charger_input_state = CHARGER_PLUGGED; 93 charger_input_state = CHARGER_PLUGGED;
96#endif 94#endif
97 return;
98 } 95 }
99 } 96 }
100 97
101 battery_percent = 100 * (battery_millivolts - BATT_MINMVOLT) / 98 batt_percent = (batt_millivolts - BATT_MINMVOLT) / (BATT_MAXMVOLT - BATT_MINMVOLT);
102 (BATT_MAXMVOLT - BATT_MINMVOLT); 99 batt_runtime = batt_percent * BATT_MAXRUNTIME;
103} 100}
104 101
105const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = { 3200 }; 102const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = { 3200 };
@@ -111,15 +108,28 @@ const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
111const unsigned short percent_to_volt_charge[11] = 108const unsigned short percent_to_volt_charge[11] =
112{ 3300, 3400, 3500, 3600, 3700, 3800, 3900, 4000, 4100, 4200, 4300 }; 109{ 3300, 3400, 3500, 3600, 3700, 3800, 3900, 4000, 4100, 4200, 4300 };
113 110
111#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE
114int _battery_voltage(void) 112int _battery_voltage(void)
115{ 113{
116 battery_status_update(); 114 battery_status_update();
117 return battery_millivolts; 115 return batt_millivolts;
118} 116}
117#endif
118
119#if CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE
120int _battery_level(void)
121{
122 battery_status_update();
123 return batt_percent;
124}
125#endif
119 126
120#if (CONFIG_BATTERY_MEASURE & TIME_MEASURE) 127#if (CONFIG_BATTERY_MEASURE & TIME_MEASURE)
121static int powermgmt_est_runningtime_min; 128int _battery_time(void)
122int _battery_time(void) { return powermgmt_est_runningtime_min; } 129{
130 battery_status_update();
131 return batt_runtime;
132}
123#endif 133#endif
124 134
125#if CONFIG_CHARGING 135#if CONFIG_CHARGING
@@ -169,6 +179,7 @@ unsigned int input_millivolts(void)
169 /* Just return a safe value if battery isn't connected */ 179 /* Just return a safe value if battery isn't connected */
170 return 4050; 180 return 4050;
171 } 181 }
172 return battery_voltage();; 182
183 return battery_voltage();
173} 184}
174#endif 185#endif