summaryrefslogtreecommitdiff
path: root/firmware/powermgmt.c
diff options
context:
space:
mode:
authorBarry Wardell <rockbox@barrywardell.net>2006-11-11 01:18:57 +0000
committerBarry Wardell <rockbox@barrywardell.net>2006-11-11 01:18:57 +0000
commit8d2711b7d2d9f19dc2375bd9395359ed725375ab (patch)
tree788f6dc4e010f7cf6eac2e3a5d3eebe2427fe06e /firmware/powermgmt.c
parentb3d2017057a47b1a5863d4e18e8d3eaf6a2fb63a (diff)
downloadrockbox-8d2711b7d2d9f19dc2375bd9395359ed725375ab.tar.gz
rockbox-8d2711b7d2d9f19dc2375bd9395359ed725375ab.zip
Improved power management (FS#3001). Shutdown rockbox when the battery gets to a level where the device doesn't function properly. Calculate remaining charging time while charging (rather than remaining running time). Show "Low Battery" and "Battery Empty" warnings. Also fixes FS#4786.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11507 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/powermgmt.c')
-rw-r--r--firmware/powermgmt.c358
1 files changed, 292 insertions, 66 deletions
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index 2ca176d072..d30a31897e 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -49,10 +49,15 @@
49#include "wm8758.h" 49#include "wm8758.h"
50#elif defined(HAVE_WM8975) 50#elif defined(HAVE_WM8975)
51#include "wm8975.h" 51#include "wm8975.h"
52#elif defined(HAVE_WM8731)
53#include "wm8731l.h"
52#endif 54#endif
53#ifdef HAVE_LCD_BITMAP 55#ifdef HAVE_LCD_BITMAP
54#include "font.h" 56#include "font.h"
55#endif 57#endif
58#if defined(HAVE_RECORDING) && (CONFIG_CODEC == SWCODEC)
59#include "pcm_record.h"
60#endif
56#include "logf.h" 61#include "logf.h"
57#include "lcd-remote.h" 62#include "lcd-remote.h"
58#ifdef SIMULATOR 63#ifdef SIMULATOR
@@ -149,6 +154,11 @@ bool battery_level_safe(void)
149 return battery_level() >= 10; 154 return battery_level() >= 10;
150} 155}
151 156
157bool battery_level_critical(void)
158{
159 return false;
160}
161
152void set_poweroff_timeout(int timeout) 162void set_poweroff_timeout(int timeout)
153{ 163{
154 (void)timeout; 164 (void)timeout;
@@ -173,41 +183,57 @@ static const int poweroff_idle_timeout_value[15] =
173 183
174static const unsigned int battery_level_dangerous[BATTERY_TYPES_COUNT] = 184static const unsigned int battery_level_dangerous[BATTERY_TYPES_COUNT] =
175{ 185{
176#if CONFIG_BATTERY == BATT_LIION2200 /* FM Recorder, LiIon */ 186#if CONFIG_BATTERY == BATT_LIION2200 /* FM Recorder, LiIon */
177 280 187 280
178#elif CONFIG_BATTERY == BATT_3AAA /* Ondio */ 188#elif CONFIG_BATTERY == BATT_3AAA /* Ondio: Alkaline, NiHM */
179 310, 345 /* alkaline, NiHM */ 189 310, 345
180#elif CONFIG_BATTERY == BATT_1AA /* iRiver iFP */ 190#elif CONFIG_BATTERY == BATT_1AA /* iRiver iFP: Alkaline, NiHM */
181 105, 115 /* alkaline, NiHM */ 191 105, 115
182#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver H1x0 */ 192#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver H1x0: LiPolymer */
183 339 193 338
184#elif CONFIG_BATTERY == BATT_IAUDIO_X5 194#elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */
185 354 195 354
186#elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB */ 196#elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB: LiPolymer*/
187 376 197 376
188#elif CONFIG_BATTERY == BATT_BP009 /* iriver H10 5/6GB */ 198#elif CONFIG_BATTERY == BATT_BP009 /* iriver H10 5/6GB: LiPolymer */
189 372 199 372
190#else /* Player/recorder, NiMH */ 200#else /* Player/recorder: NiMH */
191 475 201 475
192#endif 202#endif
193}; 203};
194 204
195static const short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = 205static const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
206{
207#if CONFIG_BATTERY == BATT_LIION2200 /* FM Recorder */
208 258
209#elif CONFIG_BATTERY == BATT_3AAA /* Ondio */
210 270, 280
211#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver Hxxx */
212 299
213#elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */
214 350
215#elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB */
216 365
217#elif CONFIG_BATTERY == BATT_BP009 /* iriver H10 5/6GB */
218 365
219#else /* Player/recorder: NiMH */
220 440
221#endif
222};
223
196/* voltages (centivolt) of 0%, 10%, ... 100% when charging disabled */ 224/* voltages (centivolt) of 0%, 10%, ... 100% when charging disabled */
225static const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
197{ 226{
198#if CONFIG_BATTERY == BATT_LIION2200 227#if CONFIG_BATTERY == BATT_LIION2200
199 /* measured values */ 228 /* measured values */
200 { 260, 285, 295, 303, 311, 320, 330, 345, 360, 380, 400 } 229 { 260, 285, 295, 303, 311, 320, 330, 345, 360, 380, 400 }
201#elif CONFIG_BATTERY == BATT_3AAA 230#elif CONFIG_BATTERY == BATT_3AAA
202 /* measured values */ 231 /* measured values */
203 { 280, 325, 341, 353, 364, 374, 385, 395, 409, 427, 475 }, /* alkaline */ 232 { 280, 325, 341, 353, 364, 374, 385, 395, 409, 427, 475 }, /* Alkaline */
204 { 310, 355, 363, 369, 372, 374, 376, 378, 380, 386, 405 } /* NiMH */ 233 { 310, 355, 363, 369, 372, 374, 376, 378, 380, 386, 405 } /* NiMH */
205#elif CONFIG_BATTERY == BATT_LIPOL1300 234#elif CONFIG_BATTERY == BATT_LIPOL1300
206 /* Below 337 the backlight starts flickering during HD access */ 235 /* Below 337 the backlight starts flickering during HD access */
207 /* Calibrated for Ionity 1900 mAh battery. If necessary, re-calibrate 236 { 337, 365, 370, 374, 378, 382, 387, 393, 400, 408, 416 }
208 * for the 1300 mAh stock battery. */
209// { 337, 358, 365, 369, 372, 377, 383, 389, 397, 406, 413 }
210 { 337, 366, 372, 374, 378, 381, 385, 392, 399, 408, 417 }
211#elif CONFIG_BATTERY == BATT_IAUDIO_X5 237#elif CONFIG_BATTERY == BATT_IAUDIO_X5
212 /* iAudio x5 series - still experimenting with best curve */ 238 /* iAudio x5 series - still experimenting with best curve */
213// Lithium ion discharge curve 239// Lithium ion discharge curve
@@ -238,12 +264,11 @@ static const short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
238charger_input_state_type charger_input_state IDATA_ATTR; 264charger_input_state_type charger_input_state IDATA_ATTR;
239 265
240/* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */ 266/* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */
241static const short percent_to_volt_charge[11] = 267static const unsigned short percent_to_volt_charge[11] =
242{ 268{
243#if CONFIG_BATTERY == BATT_LIPOL1300 269#if CONFIG_BATTERY == BATT_LIPOL1300
244 /* Calibrated for 1900 mAh Ionity battery (estimated 90% charge when 270 /* values measured over one full charging cycle */
245 entering in trickle-charging). We will never reach 100%. */ 271 354, 386, 393, 398, 400, 402, 404, 408, 413, 418, 423 /* LiPo */
246 340, 390, 394, 399, 400, 404, 407, 413, 417, 422, 426
247#elif CONFIG_BATTERY == BATT_LPCS355385 272#elif CONFIG_BATTERY == BATT_LPCS355385
248 /* iriver H10 20GB */ 273 /* iriver H10 20GB */
249 399, 403, 406, 408, 410, 412, 415, 418, 422, 426, 431 274 399, 403, 406, 408, 410, 412, 415, 418, 422, 426, 431
@@ -289,9 +314,15 @@ int pid_i = 0; /* PID integral term */
289 * Average battery voltage and charger voltage, filtered via a digital 314 * Average battery voltage and charger voltage, filtered via a digital
290 * exponential filter. 315 * exponential filter.
291 */ 316 */
292static unsigned int battery_centivolts;/* filtered battery voltage, centvolts */
293static unsigned int avgbat; /* average battery voltage (filtering) */ 317static unsigned int avgbat; /* average battery voltage (filtering) */
294#define BATT_AVE_SAMPLES 32 /* filter constant / @ 2Hz sample rate */ 318static unsigned int battery_centivolts;/* filtered battery voltage, centvolts */
319#ifdef HAVE_CHARGE_CTRL
320#define BATT_AVE_SAMPLES 32 /* filter constant / @ 2Hz sample rate */
321#elif CONFIG_BATTERY == BATT_LIPOL1300
322#define BATT_AVE_SAMPLES 128 /* slow filter for iriver */
323#else
324#define BATT_AVE_SAMPLES 64 /* medium filter constant for all others */
325#endif
295 326
296/* battery level (0-100%) of this minute, updated once per minute */ 327/* battery level (0-100%) of this minute, updated once per minute */
297static int battery_percent = -1; 328static int battery_percent = -1;
@@ -301,11 +332,12 @@ static int battery_type = 0;
301/* Power history: power_history[0] is the newest sample */ 332/* Power history: power_history[0] is the newest sample */
302unsigned short power_history[POWER_HISTORY_LEN]; 333unsigned short power_history[POWER_HISTORY_LEN];
303 334
304static char power_stack[DEFAULT_STACK_SIZE + DEBUG_STACK]; 335static char power_stack[DEFAULT_STACK_SIZE/2 + DEBUG_STACK];
305static const char power_thread_name[] = "power"; 336static const char power_thread_name[] = "power";
306 337
307static int poweroff_timeout = 0; 338static int poweroff_timeout = 0;
308static int powermgmt_est_runningtime_min = -1; 339static int powermgmt_est_runningtime_min = -1;
340static bool low_battery = false;
309 341
310static bool sleeptimer_active = false; 342static bool sleeptimer_active = false;
311static long sleeptimer_endtick; 343static long sleeptimer_endtick;
@@ -331,11 +363,6 @@ void battery_read_info(int *adc, int *voltage, int *level)
331 *level = voltage_to_battery_level(centivolts); 363 *level = voltage_to_battery_level(centivolts);
332} 364}
333 365
334unsigned int battery_voltage(void)
335{
336 return battery_centivolts;
337}
338
339void reset_poweroff_timer(void) 366void reset_poweroff_timer(void)
340{ 367{
341 last_event_tick = current_tick; 368 last_event_tick = current_tick;
@@ -372,12 +399,30 @@ int battery_level(void)
372 return battery_percent; 399 return battery_percent;
373} 400}
374 401
402/* Returns filtered battery voltage [centivolts] */
403unsigned int battery_voltage(void)
404{
405 return battery_centivolts;
406}
407
408/* Returns battery voltage from ADC [centivolts] */
409int battery_adc_voltage(void)
410{
411 return (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR + 5000) / 10000;
412}
413
375/* Tells if the battery level is safe for disk writes */ 414/* Tells if the battery level is safe for disk writes */
376bool battery_level_safe(void) 415bool battery_level_safe(void)
377{ 416{
378 return battery_centivolts > battery_level_dangerous[battery_type]; 417 return battery_centivolts > battery_level_dangerous[battery_type];
379} 418}
380 419
420/* Tells if the battery is in critical powersaving state */
421bool battery_level_critical(void)
422{
423 return ((battery_capacity * battery_percent / BATTERY_CAPACITY_MIN) < 10);
424}
425
381void set_poweroff_timeout(int timeout) 426void set_poweroff_timeout(int timeout)
382{ 427{
383 poweroff_timeout = timeout; 428 poweroff_timeout = timeout;
@@ -403,8 +448,7 @@ int get_sleep_timer(void)
403 return 0; 448 return 0;
404} 449}
405 450
406/* look into the percent_to_volt_* table and get a realistic battery level 451/* look into the percent_to_volt_* table and get a realistic battery level */
407 percentage */
408static int voltage_to_percent(int voltage, const short* table) 452static int voltage_to_percent(int voltage, const short* table)
409{ 453{
410 if (voltage <= table[0]) 454 if (voltage <= table[0])
@@ -430,7 +474,33 @@ static int voltage_to_battery_level(int battery_centivolts)
430{ 474{
431 int level; 475 int level;
432 476
433#if CONFIG_CHARGING >= CHARGING_MONITOR 477#if defined(CONFIG_CHARGER) && CONFIG_BATTERY == BATT_LIPOL1300
478 if (charger_input_state == NO_CHARGER) {
479 /* discharging. calculate new battery level and average with last */
480 level = voltage_to_percent(battery_centivolts,
481 percent_to_volt_discharge[battery_type]);
482 if (level != (battery_percent - 1))
483 level = (level + battery_percent + 1) / 2;
484 }
485 else if (charger_input_state == CHARGER_UNPLUGGED) {
486 /* just unplugged. adjust filtered values */
487 battery_centivolts -= percent_to_volt_charge[battery_percent/10] -
488 percent_to_volt_discharge[0][battery_percent/10];
489 avgbat = battery_centivolts * 10000 * BATT_AVE_SAMPLES;
490 level = battery_percent;
491 }
492 else if (charger_input_state == CHARGER_PLUGGED) {
493 /* just plugged in. adjust battery values */
494 battery_centivolts += percent_to_volt_charge[battery_percent/10] -
495 percent_to_volt_discharge[0][battery_percent/10];
496 avgbat = battery_centivolts * 10000 * BATT_AVE_SAMPLES;
497 level = MIN(12 * battery_percent / 10, 99);
498 }
499 else { /* charging. calculate new battery level */
500 level = voltage_to_percent(battery_centivolts,
501 percent_to_volt_charge);
502 }
503#elif CONFIG_CHARGING >= CHARGING_MONITOR
434 if (charge_state == DISCHARGING) { 504 if (charge_state == DISCHARGING) {
435 level = voltage_to_percent(battery_centivolts, 505 level = voltage_to_percent(battery_centivolts,
436 percent_to_volt_discharge[battery_type]); 506 percent_to_volt_discharge[battery_type]);
@@ -440,7 +510,7 @@ static int voltage_to_battery_level(int battery_centivolts)
440 level = MIN(voltage_to_percent(battery_centivolts, 510 level = MIN(voltage_to_percent(battery_centivolts,
441 percent_to_volt_charge), 99); 511 percent_to_volt_charge), 99);
442 } 512 }
443 else { /* in topoff/trickle charge, the battery is by definition 100% full */ 513 else { /* in topoff/trickle charge, battery is by definition 100% full */
444 level = 100; 514 level = 100;
445 } 515 }
446#else 516#else
@@ -456,35 +526,71 @@ static void battery_status_update(void)
456{ 526{
457 int level = voltage_to_battery_level(battery_centivolts); 527 int level = voltage_to_battery_level(battery_centivolts);
458 528
459#ifndef HAVE_MMC /* this adjustment is only needed for HD based */
460 if (battery_percent == -1) { /* first run of this procedure */
461 /* The battery voltage is usually a little lower directly after
462 turning on, because the disk was used heavily. Raise it by 5. % */
463 level = (level > 95) ? 100 : level + 5;
464 }
465#endif
466 battery_percent = level;
467 529
468 /* calculate estimated remaining running time */ 530 /* calculate estimated remaining running time */
469 /* discharging: remaining running time */ 531 /* discharging: remaining running time */
470 /* charging: remaining charging time */ 532 /* charging: remaining charging time */
471#if CONFIG_CHARGING >= CHARGING_MONITOR 533#if CONFIG_CHARGING >= CHARGING_MONITOR
472 if (charge_state == CHARGING) { 534 if (charge_state == CHARGING) {
473 powermgmt_est_runningtime_min = (100 - level) * battery_capacity / 100 535 powermgmt_est_runningtime_min = (100 - level) * battery_capacity * 60
474 * 60 / (CURRENT_MAX_CHG - runcurrent()); 536 / 100 / (CURRENT_MAX_CHG - runcurrent());
475 } 537 }
476 else 538 else
539#elif defined(CONFIG_CHARGING) && CONFIG_BATTERY == BATT_LIPOL1300
540 if (charger_inserted()) {
541#ifdef IRIVER_H300_SERIES
542 /* H300_SERIES use CURRENT_MAX_CHG for basic charge time (80%)
543 * plus 110 min top off charge time */
544 powermgmt_est_runningtime_min = ((100-level) * battery_capacity * 80
545 /100 / CURRENT_MAX_CHG) + 110;
546#else
547 /* H100_SERIES scaled for 160 min basic charge time (80%) on
548 * 1600 mAh battery plus 110 min top off charge time */
549 powermgmt_est_runningtime_min = ((100 - level) * battery_capacity
550 / 993) + 110;
551#endif
552 level = (level * 80) / 100;
553 if (level > 72) { /* > 91% */
554 int i = POWER_HISTORY_LEN;
555 int d = 1;
556#ifdef HAVE_CHARGE_STATE
557 if (charge_state == DISCHARGING)
558 d = -2;
477#endif 559#endif
560 while ((i > 2) && (d > 0)) /* search zero or neg. delta */
561 d = power_history[0] - power_history[--i];
562 if ((((d == 0) && (i > 6)) || (d == -1)) && (i < 118)) {
563 /* top off charging */
564 level = MIN(80 + (i*19 / 113), 99); /* show 81% .. 99% */
565 powermgmt_est_runningtime_min = MAX(116 - i, 0);
566 }
567 else if ((d < 0) || (i > 117)) {
568 /* charging finished */
569 level = 100;
570 powermgmt_est_runningtime_min = battery_capacity * 60
571 / runcurrent();
572 }
573 }
574 }
575 else
576#endif /* BATT_LIPOL1300 */
478 { 577 {
479 powermgmt_est_runningtime_min = level * battery_capacity / 100 578 if ((battery_centivolts + 2) > percent_to_volt_discharge[0][0])
480 * 60 / runcurrent(); 579 powermgmt_est_runningtime_min = (level + battery_percent) * 60 *
580 battery_capacity / 200 / runcurrent();
581 else
582 powermgmt_est_runningtime_min = (battery_centivolts -
583 battery_level_shutoff[0]) / 2;
481 } 584 }
585
586 battery_percent = level;
482} 587}
483 588
484/* 589/*
485 * We shut off in the following cases: 590 * We shut off in the following cases:
486 * 1) The unit is idle, not playing music 591 * 1) The unit is idle, not playing music
487 * 2) The unit is playing music, but is paused 592 * 2) The unit is playing music, but is paused
593 * 3) The battery level has reached shutdown limit
488 * 594 *
489 * We do not shut off in the following cases: 595 * We do not shut off in the following cases:
490 * 1) The USB is connected 596 * 1) The USB is connected
@@ -507,6 +613,41 @@ static void handle_auto_poweroff(void)
507 } 613 }
508#endif 614#endif
509 615
616 /* For low battery condition do some power-saving stuff */
617 if (!low_battery && battery_level_critical()) {
618#if CONFIG_BACKLIGHT == BL_IRIVER_H100
619 backlight_set_fade_in(0);
620 backlight_set_fade_out(0);
621#endif
622#if defined(CONFIG_BACKLIGHT) && !defined(BOOTLOADER)
623 if (backlight_get_current_timeout() > 2)
624#endif
625 backlight_set_timeout(2);
626#ifdef HAVE_REMOTE_LCD
627 remote_backlight_set_timeout(2);
628#endif
629 ata_spindown(3);
630#ifdef HAVE_ATA_POWER_OFF
631 ata_poweroff(true);
632#endif
633 low_battery = true;
634 } else if (low_battery && (battery_percent > 11)) {
635 backlight_set_timeout(10);
636 ata_spindown(10);
637 low_battery = false;
638 }
639
640 /* switch off unit if battery level is too low for reliable operation */
641#if (CONFIG_BATTERY!=BATT_4AA_NIMH) && (CONFIG_BATTERY!=BATT_3AAA)&& \
642 (CONFIG_BATTERY!=BATT_1AA)
643 if(battery_centivolts < battery_level_shutoff[battery_type]) {
644 if(!shutdown_timeout) {
645 backlight_on();
646 sys_poweroff();
647 }
648 }
649#endif
650
510 if(timeout && 651 if(timeout &&
511#if defined(CONFIG_TUNER) && !defined(BOOTLOADER) 652#if defined(CONFIG_TUNER) && !defined(BOOTLOADER)
512 (!(get_radio_status() & FMRADIO_PLAYING)) && 653 (!(get_radio_status() & FMRADIO_PLAYING)) &&
@@ -581,6 +722,30 @@ static int runcurrent(void)
581 current += CURRENT_BACKLIGHT; 722 current += CURRENT_BACKLIGHT;
582#endif 723#endif
583 724
725#if defined(HAVE_RECORDING) && defined(CURRENT_RECORD)
726#if CONFIG_CODEC == SWCODEC
727 unsigned int audio_stat = pcm_rec_status();
728#else
729 int audio_stat = audio_status();
730#endif
731 if (audio_stat & AUDIO_STATUS_RECORD)
732 current += CURRENT_RECORD;
733#endif
734
735#ifdef HAVE_SPDIF_POWER
736#ifdef SPDIF_POWER_INVERTED
737 if (GPIO1_OUT & 0x01000000)
738#else
739 if (!(GPIO1_OUT & 0x01000000))
740#endif
741 current += CURRENT_SPDIF_OUT;
742#endif
743
744#ifdef HAVE_REMOTE_LCD
745 if ((GPIO_READ & 0x40000000) == 0)
746 current += CURRENT_REMOTE;
747#endif
748
584 return(current); 749 return(current);
585} 750}
586 751
@@ -689,17 +854,31 @@ static void power_thread_sleep(int ticks)
689 * likely always be spinning in USB mode). 854 * likely always be spinning in USB mode).
690 */ 855 */
691 if (!ata_disk_is_active() || usb_inserted()) { 856 if (!ata_disk_is_active() || usb_inserted()) {
692 avgbat = avgbat - (avgbat / BATT_AVE_SAMPLES) + 857 avgbat += adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR
693 adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR; 858 - (avgbat / BATT_AVE_SAMPLES);
694 /* 859 /*
695 * battery_centivolts is the centivolt-scaled filtered battery value. 860 * battery_centivolts is the centivolt-scaled filtered battery value.
696 */ 861 */
697 battery_centivolts = avgbat / BATT_AVE_SAMPLES / 10000; 862 battery_centivolts = (avgbat / BATT_AVE_SAMPLES + 5000) / 10000;
698
699 /* update battery status every time an update is available */
700 battery_status_update();
701
702 } 863 }
864 else if (battery_percent < 8) {
865 /* If battery is low, observe voltage during disk activity.
866 * Shut down if voltage drops below shutoff level and we are not
867 * using NiMH or Alkaline batteries.
868 */
869 battery_centivolts = (battery_adc_voltage() +
870 battery_centivolts + 1) / 2;
871#if (CONFIG_BATTERY!=BATT_4AA_NIMH) && (CONFIG_BATTERY!=BATT_3AAA)&& \
872 (CONFIG_BATTERY!=BATT_1AA)
873 if (!shutdown_timeout &&
874 (battery_centivolts < battery_level_shutoff[battery_type]))
875 sys_poweroff();
876 else
877#endif
878 avgbat += battery_centivolts * 10000
879 - (avgbat / BATT_AVE_SAMPLES);
880 }
881
703#if CONFIG_CHARGING == CHARGING_CONTROL 882#if CONFIG_CHARGING == CHARGING_CONTROL
704 if (ata_disk_is_active()) { 883 if (ata_disk_is_active()) {
705 /* flag hdd use for charging calculation */ 884 /* flag hdd use for charging calculation */
@@ -711,8 +890,7 @@ static void power_thread_sleep(int ticks)
711 * If we have a lot of pending writes or if the disk is spining, 890 * If we have a lot of pending writes or if the disk is spining,
712 * fsync the debug log file. 891 * fsync the debug log file.
713 */ 892 */
714 if((wrcount > 10) || 893 if((wrcount > 10) || ((wrcount > 0) && ata_disk_is_active())) {
715 ((wrcount > 0) && ata_disk_is_active())) {
716 fsync(fd); 894 fsync(fd);
717 wrcount = 0; 895 wrcount = 0;
718 } 896 }
@@ -745,10 +923,35 @@ static void power_thread(void)
745#endif 923#endif
746 924
747 /* initialize the voltages for the exponential filter */ 925 /* initialize the voltages for the exponential filter */
748 avgbat = adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR * 926 avgbat = adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR + 15000;
749 BATT_AVE_SAMPLES; 927
928#ifndef HAVE_MMC /* this adjustment is only needed for HD based */
929 /* The battery voltage is usually a little lower directly after
930 turning on, because the disk was used heavily. Raise it by 5% */
931#ifdef HAVE_CHARGING
932 if(!charger_inserted()) /* only if charger not connected */
933#endif
934 avgbat += (percent_to_volt_discharge[battery_type][6] -
935 percent_to_volt_discharge[battery_type][5]) * 5000;
936#endif /* not HAVE_MMC */
937
938 avgbat = avgbat * BATT_AVE_SAMPLES;
750 battery_centivolts = avgbat / BATT_AVE_SAMPLES / 10000; 939 battery_centivolts = avgbat / BATT_AVE_SAMPLES / 10000;
751 940
941#ifdef CONFIG_CHARING
942 if(charger_inserted()) {
943 battery_percent = voltage_to_percent(battery_centivolts,
944 percent_to_volt_charge);
945#if CONFIG_BATTERY == BATT_LIPOL1300
946 charger_input_state = CHARGER;
947#endif
948 } else
949#endif
950 { battery_percent = voltage_to_percent(battery_centivolts,
951 percent_to_volt_discharge[battery_type]);
952 battery_percent += (battery_percent < 100);
953 }
954
752#if defined(DEBUG_FILE) && (CONFIG_CHARGING == CHARGING_CONTROL) 955#if defined(DEBUG_FILE) && (CONFIG_CHARGING == CHARGING_CONTROL)
753 fd = -1; 956 fd = -1;
754 wrcount = 0; 957 wrcount = 0;
@@ -954,7 +1157,7 @@ static void power_thread(void)
954 pid_p = pid_p * PID_PCONST; 1157 pid_p = pid_p * PID_PCONST;
955 else 1158 else
956 pid_p = 0; 1159 pid_p = 0;
957 if(battery_centivolts < target_voltage) { 1160 if((unsigned) battery_centivolts < target_voltage) {
958 if(pid_i < 60) { 1161 if(pid_i < 60) {
959 pid_i++; /* limit so it doesn't "wind up" */ 1162 pid_i++; /* limit so it doesn't "wind up" */
960 } 1163 }
@@ -1067,7 +1270,18 @@ void sys_poweroff(void)
1067 /* If the main thread fails to shut down the system, we will force a 1270 /* If the main thread fails to shut down the system, we will force a
1068 power off after an 20 second timeout */ 1271 power off after an 20 second timeout */
1069 shutdown_timeout = HZ*20; 1272 shutdown_timeout = HZ*20;
1070 1273#if defined(HAVE_RECORDING)
1274#if CONFIG_CODEC == SWCODEC
1275 unsigned int audio_stat = pcm_rec_status();
1276#else
1277 int audio_stat = audio_status();
1278#endif
1279 if (audio_stat & AUDIO_STATUS_RECORD) {
1280 audio_stop_recording();
1281 shutdown_timeout += 8*HZ;
1282 }
1283#endif
1284
1071 queue_post(&button_queue, SYS_POWEROFF, NULL); 1285 queue_post(&button_queue, SYS_POWEROFF, NULL);
1072} 1286}
1073 1287
@@ -1095,30 +1309,42 @@ void shutdown_hw(void)
1095 } 1309 }
1096#endif 1310#endif
1097 audio_stop(); 1311 audio_stop();
1312 if (!battery_level_critical()) { /* do not save on critical battery */
1098#ifdef HAVE_LCD_BITMAP 1313#ifdef HAVE_LCD_BITMAP
1099 glyph_cache_save(); 1314 glyph_cache_save();
1100#endif 1315#endif
1101 ata_spindown(1); 1316 if(ata_disk_is_active())
1317 ata_spindown(1);
1318 }
1102 while(ata_disk_is_active()) 1319 while(ata_disk_is_active())
1103 sleep(HZ/10); 1320 sleep(HZ/10);
1104 1321
1322#ifndef IAUDIO_X5
1323#if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR)
1324 backlight_set_fade_out(0);
1325#endif
1326 backlight_off();
1327#endif /* IAUDIO_X5 */
1328#ifdef HAVE_REMOTE_LCD
1329 remote_backlight_off();
1330#endif
1331
1105 mp3_shutdown(); 1332 mp3_shutdown();
1106#ifdef HAVE_UDA1380 1333#ifdef HAVE_UDA1380
1107 uda1380_close(); 1334 uda1380_close();
1108#elif defined(HAVE_TLV320) 1335#elif defined(HAVE_TLV320)
1109 tlv320_close(); 1336 tlv320_close();
1110#elif defined(HAVE_WM8758) || defined(HAVE_WM8975) 1337#elif defined(HAVE_WM8758) || defined(HAVE_WM8975) | defined(HAVE_WM8731)
1111 wmcodec_close(); 1338 wmcodec_close();
1112#endif 1339#endif
1340 /* If HD is still active we try to wait for spindown, otherwise the
1341 shutdown_timeout in power_thread_sleep will force a power off */
1342 while(ata_disk_is_active())
1343 sleep(HZ/10);
1113#ifndef IAUDIO_X5 1344#ifndef IAUDIO_X5
1114#if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR)
1115 backlight_set_fade_out(0);
1116#endif
1117 backlight_off();
1118 lcd_set_contrast(0); 1345 lcd_set_contrast(0);
1119#endif /* IAUDIO_X5 */ 1346#endif /* IAUDIO_X5 */
1120#ifdef HAVE_REMOTE_LCD 1347#ifdef HAVE_REMOTE_LCD
1121 remote_backlight_off();
1122 lcd_remote_set_contrast(0); 1348 lcd_remote_set_contrast(0);
1123#endif 1349#endif
1124 power_off(); 1350 power_off();