Fix remote screen check in graphic equalizer, so that it can be used on logf-enabled...
[Rockbox.git] / firmware / powermgmt.c
blobf258502c2c3b37bfe66296be6c679fed1c4092f3
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese
11 * Revisions copyright (C) 2005 by Gerald Van Baren
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
20 #include "config.h"
21 #include "cpu.h"
22 #include "kernel.h"
23 #include "thread.h"
24 #include "system.h"
25 #include "debug.h"
26 #include "panic.h"
27 #include "adc.h"
28 #include "string.h"
29 #include "sprintf.h"
30 #include "ata.h"
31 #include "power.h"
32 #include "button.h"
33 #include "ata.h"
34 #include "audio.h"
35 #include "mp3_playback.h"
36 #include "usb.h"
37 #include "powermgmt.h"
38 #include "backlight.h"
39 #include "lcd.h"
40 #include "rtc.h"
41 #ifdef CONFIG_TUNER
42 #include "fmradio.h"
43 #endif
44 #ifdef HAVE_UDA1380
45 #include "uda1380.h"
46 #elif defined(HAVE_TLV320)
47 #include "tlv320.h"
48 #elif defined(HAVE_WM8758)
49 #include "wm8758.h"
50 #elif defined(HAVE_WM8975)
51 #include "wm8975.h"
52 #endif
53 #ifdef HAVE_LCD_BITMAP
54 #include "font.h"
55 #endif
56 #include "logf.h"
57 #include "lcd-remote.h"
58 #ifdef SIMULATOR
59 #include <time.h>
60 #endif
62 #if defined(IAUDIO_X5) && !defined (SIMULATOR)
63 #include "pcf50606.h"
64 #endif
67 * Define DEBUG_FILE to create a csv (spreadsheet) with battery information
68 * in it (one sample per minute). This is only for very low level debug.
70 #undef DEBUG_FILE
71 #if defined(DEBUG_FILE) && (CONFIG_CHARGING == CHARGING_CONTROL)
72 #include "file.h"
73 #define DEBUG_FILE_NAME "/powermgmt.csv"
74 #define DEBUG_MESSAGE_LEN 133
75 static char debug_message[DEBUG_MESSAGE_LEN];
76 #define DEBUG_STACK ((0x1000)/sizeof(long))
77 static int fd; /* write debug information to this file */
78 static int wrcount;
79 #else
80 #define DEBUG_STACK 0
81 #endif
83 static int shutdown_timeout = 0;
85 #ifdef SIMULATOR /***********************************************************/
87 #define TIME2CHANGE 10 /* change levels every 10 seconds */
88 #define BATT_MINCVOLT 250 /* minimum centivolts of battery */
89 #define BATT_MAXCVOLT 450 /* maximum centivolts of battery */
90 #define BATT_MAXRUNTIME (10 * 60) /* maximum runtime with full battery in minutes */
92 static unsigned int batt_centivolts = (unsigned int)BATT_MAXCVOLT;
93 static int batt_level = 100; /* battery capacity level in percent */
94 static int batt_time = BATT_MAXRUNTIME; /* estimated remaining time in minutes */
95 static time_t last_change = 0;
97 static void battery_status_update(void)
99 time_t now;
101 time(&now);
102 if (last_change < (now - TIME2CHANGE)) {
103 last_change = now;
105 /* change the values: */
106 batt_centivolts -= (unsigned int)(BATT_MAXCVOLT - BATT_MINCVOLT) / 11;
107 if (batt_centivolts < (unsigned int)BATT_MINCVOLT)
108 batt_centivolts = (unsigned int)BATT_MAXCVOLT;
110 batt_level = 100 * (batt_centivolts - BATT_MINCVOLT) / (BATT_MAXCVOLT - BATT_MINCVOLT);
111 batt_time = batt_level * BATT_MAXRUNTIME / 100;
115 void battery_read_info(int *adc, int *voltage, int *level)
117 battery_status_update();
119 if (adc)
120 *adc = batt_centivolts; /* just return something */
122 if (voltage)
123 *voltage = batt_centivolts;
125 if (level)
126 *level = batt_level;
129 unsigned int battery_voltage(void)
131 battery_status_update();
132 return batt_centivolts;
135 int battery_level(void)
137 battery_status_update();
138 return batt_level;
141 int battery_time(void)
143 battery_status_update();
144 return batt_time;
147 bool battery_level_safe(void)
149 return battery_level() >= 10;
152 void set_poweroff_timeout(int timeout)
154 (void)timeout;
157 void set_battery_capacity(int capacity)
159 (void)capacity;
162 void reset_poweroff_timer(void)
167 #else /* not SIMULATOR ******************************************************/
169 static const int poweroff_idle_timeout_value[15] =
171 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 30, 45, 60
174 static const unsigned int battery_level_dangerous[BATTERY_TYPES_COUNT] =
176 #if CONFIG_BATTERY == BATT_LIION2200 /* FM Recorder, LiIon */
178 #elif CONFIG_BATTERY == BATT_3AAA /* Ondio */
179 310, 345 /* alkaline, NiHM */
180 #elif CONFIG_BATTERY == BATT_1AA /* iRiver iFP */
181 105, 115 /* alkaline, NiHM */
182 #elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver H1x0 */
184 #elif CONFIG_BATTERY == BATT_IAUDIO_X5
186 #elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB */
188 #elif CONFIG_BATTERY == BATT_BP009 /* iriver H10 5/6GB */
190 #else /* Player/recorder, NiMH */
192 #endif
195 static const short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
196 /* voltages (centivolt) of 0%, 10%, ... 100% when charging disabled */
198 #if CONFIG_BATTERY == BATT_LIION2200
199 /* measured values */
200 { 260, 285, 295, 303, 311, 320, 330, 345, 360, 380, 400 }
201 #elif CONFIG_BATTERY == BATT_3AAA
202 /* measured values */
203 { 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 */
205 #elif CONFIG_BATTERY == BATT_LIPOL1300
206 /* Below 337 the backlight starts flickering during HD access */
207 /* Calibrated for Ionity 1900 mAh battery. If necessary, re-calibrate
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
212 /* iAudio x5 series - still experimenting with best curve */
213 // Lithium ion discharge curve
214 { 355, 356, 357, 359, 362, 365, 369, 374, 380, 387, 395 }
215 // Linear
216 // { 355, 360, 364, 369, 373, 378, 382, 387, 391, 390, 400 }
217 // { 355, 359, 363, 367, 371, 375, 379, 383, 387, 391, 395 }
218 #elif CONFIG_BATTERY == BATT_LPCS355385
219 /* iriver H10 20GB */
220 { 376, 380, 385, 387, 390, 395, 402, 407, 411, 418, 424 }
221 #elif CONFIG_BATTERY == BATT_BP009
222 /* iriver H10 5/6GB */
223 { 372, 374, 380, 382, 384, 388, 394, 402, 406, 415, 424 }
224 #elif CONFIG_BATTERY == BATT_1AA
225 /* These values are the same as for 3AAA divided by 3. */
226 /* May need recalibration. */
227 { 93, 108, 114, 118, 121, 125, 128, 132, 136, 142, 158 }, /* alkaline */
228 { 103, 118, 121, 123, 124, 125, 126, 127, 128, 129, 135 } /* NiMH */
229 #else /* NiMH */
230 /* original values were taken directly after charging, but it should show
231 100% after turning off the device for some hours, too */
232 { 450, 481, 491, 497, 503, 507, 512, 514, 517, 525, 540 }
233 /* orig. values: ...,528,560 */
234 #endif
237 #ifdef CONFIG_CHARGING
238 charger_input_state_type charger_input_state IDATA_ATTR;
240 /* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */
241 static const short percent_to_volt_charge[11] =
243 #if CONFIG_BATTERY == BATT_LIPOL1300
244 /* Calibrated for 1900 mAh Ionity battery (estimated 90% charge when
245 entering in trickle-charging). We will never reach 100%. */
246 340, 390, 394, 399, 400, 404, 407, 413, 417, 422, 426
247 #elif CONFIG_BATTERY == BATT_LPCS355385
248 /* iriver H10 20GB */
249 399, 403, 406, 408, 410, 412, 415, 418, 422, 426, 431
250 #elif CONFIG_BATTERY == BATT_BP009
251 /* iriver H10 5/6GB: Not yet calibrated */
252 388, 392, 396, 400, 406, 410, 415, 419, 424, 428, 433
253 #else
254 /* values guessed, see
255 http://www.seattlerobotics.org/encoder/200210/LiIon2.pdf until someone
256 measures voltages over a charging cycle */
257 476, 544, 551, 556, 561, 564, 566, 576, 582, 584, 585 /* NiMH */
258 #endif
260 #endif /* CONFIG_CHARGING */
262 #if CONFIG_CHARGING >= CHARGING_MONITOR
263 charge_state_type charge_state; /* charging mode */
264 #endif
266 #if CONFIG_CHARGING == CHARGING_CONTROL
267 int long_delta; /* long term delta battery voltage */
268 int short_delta; /* short term delta battery voltage */
269 bool disk_activity_last_cycle = false; /* flag set to aid charger time
270 * calculation */
271 char power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in
272 debug menu */
273 /* percentage at which charging
274 starts */
275 int powermgmt_last_cycle_startstop_min = 0; /* how many minutes ago was the
276 charging started or
277 stopped? */
278 int powermgmt_last_cycle_level = 0; /* which level had the
279 batteries at this time? */
280 int trickle_sec = 0; /* how many seconds should the
281 charger be enabled per
282 minute for trickle
283 charging? */
284 int pid_p = 0; /* PID proportional term */
285 int pid_i = 0; /* PID integral term */
286 #endif /* CONFIG_CHARGING == CHARGING_CONTROL */
289 * Average battery voltage and charger voltage, filtered via a digital
290 * exponential filter.
292 static unsigned int battery_centivolts;/* filtered battery voltage, centvolts */
293 static unsigned int avgbat; /* average battery voltage (filtering) */
294 #define BATT_AVE_SAMPLES 32 /* filter constant / @ 2Hz sample rate */
296 /* battery level (0-100%) of this minute, updated once per minute */
297 static int battery_percent = -1;
298 static int battery_capacity = BATTERY_CAPACITY_DEFAULT; /* default value, mAh */
299 static int battery_type = 0;
301 /* Power history: power_history[0] is the newest sample */
302 unsigned short power_history[POWER_HISTORY_LEN];
304 static char power_stack[DEFAULT_STACK_SIZE + DEBUG_STACK];
305 static const char power_thread_name[] = "power";
307 static int poweroff_timeout = 0;
308 static int powermgmt_est_runningtime_min = -1;
310 static bool sleeptimer_active = false;
311 static long sleeptimer_endtick;
313 static long last_event_tick;
315 static int voltage_to_battery_level(int battery_centivolts);
316 static void battery_status_update(void);
317 static int runcurrent(void);
319 void battery_read_info(int *adc, int *voltage, int *level)
321 int adc_battery = adc_read(ADC_UNREG_POWER);
322 int centivolts = adc_battery*BATTERY_SCALE_FACTOR / 10000;
324 if (adc)
325 *adc = adc_battery;
327 if (voltage)
328 *voltage = centivolts;
330 if (level)
331 *level = voltage_to_battery_level(centivolts);
334 unsigned int battery_voltage(void)
336 return battery_centivolts;
339 void reset_poweroff_timer(void)
341 last_event_tick = current_tick;
344 #if BATTERY_TYPES_COUNT > 1
345 void set_battery_type(int type)
347 if (type != battery_type) {
348 battery_type = type;
349 battery_status_update(); /* recalculate the battery status */
352 #endif
354 void set_battery_capacity(int capacity)
356 battery_capacity = capacity;
357 if (battery_capacity > BATTERY_CAPACITY_MAX)
358 battery_capacity = BATTERY_CAPACITY_MAX;
359 if (battery_capacity < BATTERY_CAPACITY_MIN)
360 battery_capacity = BATTERY_CAPACITY_MIN;
361 battery_status_update(); /* recalculate the battery status */
364 int battery_time(void)
366 return powermgmt_est_runningtime_min;
369 /* Returns battery level in percent */
370 int battery_level(void)
372 return battery_percent;
375 /* Tells if the battery level is safe for disk writes */
376 bool battery_level_safe(void)
378 return battery_centivolts > battery_level_dangerous[battery_type];
381 void set_poweroff_timeout(int timeout)
383 poweroff_timeout = timeout;
386 void set_sleep_timer(int seconds)
388 if(seconds) {
389 sleeptimer_active = true;
390 sleeptimer_endtick = current_tick + seconds * HZ;
392 else {
393 sleeptimer_active = false;
394 sleeptimer_endtick = 0;
398 int get_sleep_timer(void)
400 if(sleeptimer_active)
401 return (sleeptimer_endtick - current_tick) / HZ;
402 else
403 return 0;
406 /* look into the percent_to_volt_* table and get a realistic battery level
407 percentage */
408 static int voltage_to_percent(int voltage, const short* table)
410 if (voltage <= table[0])
411 return 0;
412 else
413 if (voltage >= table[10])
414 return 100;
415 else {
416 /* search nearest value */
417 int i = 0;
418 while ((i < 10) && (table[i+1] < voltage))
419 i++;
420 /* interpolate linear between the smaller and greater value */
421 return (i * 10) /* Tens digit, 10% per entry */
422 + (((voltage - table[i]) * 10)
423 / (table[i+1] - table[i])); /* Ones digit: interpolated */
427 /* update battery level and estimated runtime, called once per minute or
428 * when battery capacity / type settings are changed */
429 static int voltage_to_battery_level(int battery_centivolts)
431 int level;
433 #if CONFIG_CHARGING >= CHARGING_MONITOR
434 if (charge_state == DISCHARGING) {
435 level = voltage_to_percent(battery_centivolts,
436 percent_to_volt_discharge[battery_type]);
438 else if (charge_state == CHARGING) {
439 /* battery level is defined to be < 100% until charging is finished */
440 level = MIN(voltage_to_percent(battery_centivolts,
441 percent_to_volt_charge), 99);
443 else { /* in topoff/trickle charge, the battery is by definition 100% full */
444 level = 100;
446 #else
447 /* always use the discharge table */
448 level = voltage_to_percent(battery_centivolts,
449 percent_to_volt_discharge[battery_type]);
450 #endif
452 return level;
455 static void battery_status_update(void)
457 int level = voltage_to_battery_level(battery_centivolts);
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;
465 #endif
466 battery_percent = level;
468 /* calculate estimated remaining running time */
469 /* discharging: remaining running time */
470 /* charging: remaining charging time */
471 #if CONFIG_CHARGING >= CHARGING_MONITOR
472 if (charge_state == CHARGING) {
473 powermgmt_est_runningtime_min = (100 - level) * battery_capacity / 100
474 * 60 / (CURRENT_MAX_CHG - runcurrent());
476 else
477 #endif
479 powermgmt_est_runningtime_min = level * battery_capacity / 100
480 * 60 / runcurrent();
485 * We shut off in the following cases:
486 * 1) The unit is idle, not playing music
487 * 2) The unit is playing music, but is paused
489 * We do not shut off in the following cases:
490 * 1) The USB is connected
491 * 2) The charger is connected
492 * 3) We are recording, or recording with pause
493 * 4) The radio is playing
495 static void handle_auto_poweroff(void)
497 long timeout = poweroff_idle_timeout_value[poweroff_timeout]*60*HZ;
498 int audio_stat = audio_status();
500 #ifdef CONFIG_CHARGING
502 * Inhibit shutdown as long as the charger is plugged in. If it is
503 * unplugged, wait for a timeout period and then shut down.
505 if(charger_input_state == CHARGER || audio_stat == AUDIO_STATUS_PLAY) {
506 last_event_tick = current_tick;
508 #endif
510 if(timeout &&
511 #if defined(CONFIG_TUNER) && !defined(BOOTLOADER)
512 (!(get_radio_status() & FMRADIO_PLAYING)) &&
513 #endif
514 !usb_inserted() &&
515 ((audio_stat == 0) ||
516 ((audio_stat == (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE)) &&
517 !sleeptimer_active)))
519 if(TIME_AFTER(current_tick, last_event_tick + timeout) &&
520 TIME_AFTER(current_tick, last_disk_activity + timeout))
522 sys_poweroff();
525 else
527 /* Handle sleeptimer */
528 if(sleeptimer_active && !usb_inserted())
530 if(TIME_AFTER(current_tick, sleeptimer_endtick))
532 audio_stop();
533 #if defined(CONFIG_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
534 if((charger_input_state == CHARGER) ||
535 (charger_input_state == CHARGER_PLUGGED))
537 DEBUGF("Sleep timer timeout. Stopping...\n");
538 set_sleep_timer(0);
539 backlight_off(); /* Nighty, nighty... */
541 else
542 #endif
544 DEBUGF("Sleep timer timeout. Shutting off...\n");
545 sys_poweroff();
553 * Estimate how much current we are drawing just to run.
555 static int runcurrent(void)
557 int current;
559 #if MEM == 8 && !defined(HAVE_MMC)
560 /* assuming 192 kbps, the running time is 22% longer with 8MB */
561 current = (CURRENT_NORMAL*100/122);
562 #else
563 current = CURRENT_NORMAL;
564 #endif /* MEM == 8 */
566 if(usb_inserted()
567 #if defined(HAVE_USB_POWER)
568 #if (CURRENT_USB < CURRENT_NORMAL)
569 || usb_powered()
570 #else
571 && !usb_powered()
572 #endif
573 #endif
576 current = CURRENT_USB;
579 #if defined(CONFIG_BACKLIGHT) && !defined(BOOTLOADER)
580 if (backlight_get_current_timeout() == 0) /* LED always on */
581 current += CURRENT_BACKLIGHT;
582 #endif
584 return(current);
588 /* Check to see whether or not we've received an alarm in the last second */
589 #ifdef HAVE_ALARM_MOD
590 static void power_thread_rtc_process(void)
592 if (rtc_check_alarm_flag()) {
593 rtc_enable_alarm(false);
596 #endif
599 * This function is called to do the relativly long sleep waits from within the
600 * main power_thread loop while at the same time servicing any other periodic
601 * functions in the power thread which need to be called at a faster periodic
602 * rate than the slow periodic rate of the main power_thread loop.
604 * While we are waiting for the time to expire, we average the battery
605 * voltages.
607 static void power_thread_sleep(int ticks)
609 int small_ticks;
611 while (ticks > 0) {
613 #ifdef CONFIG_CHARGING
615 * Detect charger plugged/unplugged transitions. On a plugged or
616 * unplugged event, we return immediately, run once through the main
617 * loop (including the subroutines), and end up back here where we
618 * transition to the appropriate steady state charger on/off state.
620 if(charger_inserted()
621 #ifdef HAVE_USB_POWER
622 || usb_powered()
623 #endif
625 switch(charger_input_state) {
626 case NO_CHARGER:
627 case CHARGER_UNPLUGGED:
628 charger_input_state = CHARGER_PLUGGED;
629 return;
630 case CHARGER_PLUGGED:
631 queue_broadcast(SYS_CHARGER_CONNECTED, NULL);
632 charger_input_state = CHARGER;
633 break;
634 case CHARGER:
635 break;
637 } else { /* charger not inserted */
638 switch(charger_input_state) {
639 case NO_CHARGER:
640 break;
641 case CHARGER_UNPLUGGED:
642 queue_broadcast(SYS_CHARGER_DISCONNECTED, NULL);
643 charger_input_state = NO_CHARGER;
644 break;
645 case CHARGER_PLUGGED:
646 case CHARGER:
647 charger_input_state = CHARGER_UNPLUGGED;
648 return;
651 #endif
652 #if CONFIG_CHARGING == CHARGING_MONITOR
653 switch (charger_input_state) {
654 case CHARGER_UNPLUGGED:
655 case NO_CHARGER:
656 charge_state = DISCHARGING;
657 break;
658 case CHARGER_PLUGGED:
659 case CHARGER:
660 if (charging_state()) {
661 charge_state = CHARGING;
662 } else {
663 charge_state = DISCHARGING;
665 break;
668 #endif /* CONFIG_CHARGING == CHARGING_MONITOR */
670 small_ticks = MIN(HZ/2, ticks);
671 sleep(small_ticks);
672 ticks -= small_ticks;
674 /* If the power off timeout expires, the main thread has failed
675 to shut down the system, and we need to force a power off */
676 if(shutdown_timeout) {
677 shutdown_timeout -= small_ticks;
678 if(shutdown_timeout <= 0)
679 power_off();
682 #ifdef HAVE_ALARM_MOD
683 power_thread_rtc_process();
684 #endif
687 * Do a digital exponential filter. We don't sample the battery if
688 * the disk is spinning unless we are in USB mode (the disk will most
689 * likely always be spinning in USB mode).
691 if (!ata_disk_is_active() || usb_inserted()) {
692 avgbat = avgbat - (avgbat / BATT_AVE_SAMPLES) +
693 adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR;
695 * battery_centivolts is the centivolt-scaled filtered battery value.
697 battery_centivolts = avgbat / BATT_AVE_SAMPLES / 10000;
699 /* update battery status every time an update is available */
700 battery_status_update();
703 #if CONFIG_CHARGING == CHARGING_CONTROL
704 if (ata_disk_is_active()) {
705 /* flag hdd use for charging calculation */
706 disk_activity_last_cycle = true;
708 #endif
709 #if defined(DEBUG_FILE) && (CONFIG_CHARGING == CHARGING_CONTROL)
711 * If we have a lot of pending writes or if the disk is spining,
712 * fsync the debug log file.
714 if((wrcount > 10) ||
715 ((wrcount > 0) && ata_disk_is_active())) {
716 fsync(fd);
717 wrcount = 0;
719 #endif
725 * This power thread maintains a history of battery voltage
726 * and implements a charging algorithm.
727 * For a complete description of the charging algorithm read
728 * docs/CHARGING_ALGORITHM.
731 static void power_thread(void)
733 int i;
734 short *phps, *phpd; /* power history rotation pointers */
735 #if CONFIG_CHARGING == CHARGING_CONTROL
736 unsigned int target_voltage = TRICKLE_VOLTAGE; /* desired topoff/trickle
737 * voltage level */
738 int charge_max_time_idle = 0; /* max. charging duration, calculated at
739 * beginning of charging */
740 int charge_max_time_now = 0; /* max. charging duration including
741 * hdd activity */
742 int minutes_disk_activity = 0; /* count minutes of hdd use during
743 * charging */
744 int last_disk_activity = CHARGE_END_LONGD + 1; /* last hdd use x mins ago */
745 #endif
747 /* initialize the voltages for the exponential filter */
748 avgbat = adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR *
749 BATT_AVE_SAMPLES;
750 battery_centivolts = avgbat / BATT_AVE_SAMPLES / 10000;
752 #if defined(DEBUG_FILE) && (CONFIG_CHARGING == CHARGING_CONTROL)
753 fd = -1;
754 wrcount = 0;
755 #endif
757 while (1)
759 /* rotate the power history */
760 phpd = &power_history[POWER_HISTORY_LEN - 1];
761 phps = phpd - 1;
762 for (i = 0; i < POWER_HISTORY_LEN-1; i++)
763 *phpd-- = *phps--;
765 /* insert new value at the start, in centivolts 8-) */
766 power_history[0] = battery_centivolts;
768 #if CONFIG_CHARGING == CHARGING_CONTROL
769 if (charger_input_state == CHARGER_PLUGGED) {
770 pid_p = 0;
771 pid_i = 0;
772 snprintf(power_message, POWER_MESSAGE_LEN, "Charger plugged in");
774 * The charger was just plugged in. If the battery level is
775 * nearly charged, just trickle. If the battery is low, start
776 * a full charge cycle. If the battery level is in between,
777 * top-off and then trickle.
779 if(battery_percent > START_TOPOFF_CHG) {
780 powermgmt_last_cycle_level = battery_percent;
781 powermgmt_last_cycle_startstop_min = 0;
782 if(battery_percent >= START_TRICKLE_CHG) {
783 charge_state = TRICKLE;
784 target_voltage = TRICKLE_VOLTAGE;
785 } else {
786 charge_state = TOPOFF;
787 target_voltage = TOPOFF_VOLTAGE;
789 } else {
791 * Start the charger full strength
793 i = CHARGE_MAX_TIME_1500 * battery_capacity / 1500;
794 charge_max_time_idle =
795 i * (100 + 35 - battery_percent) / 100;
796 if (charge_max_time_idle > i) {
797 charge_max_time_idle = i;
799 charge_max_time_now = charge_max_time_idle;
801 snprintf(power_message, POWER_MESSAGE_LEN,
802 "ChgAt %d%% max %dm", battery_level(),
803 charge_max_time_now);
805 /* enable the charger after the max time calc is done,
806 because battery_level depends on if the charger is
807 on */
808 DEBUGF("power: charger inserted and battery"
809 " not full, charging\n");
810 powermgmt_last_cycle_level = battery_percent;
811 powermgmt_last_cycle_startstop_min = 0;
812 trickle_sec = 60;
813 long_delta = short_delta = 999999;
814 charge_state = CHARGING;
817 if (charge_state == CHARGING) {
818 /* alter charge time max length with extra disk use */
819 if (disk_activity_last_cycle) {
820 minutes_disk_activity++;
821 charge_max_time_now = charge_max_time_idle +
822 (minutes_disk_activity * 2 / 5);
823 disk_activity_last_cycle = false;
824 last_disk_activity = 0;
825 } else {
826 last_disk_activity++;
829 * Check the delta voltage over the last X minutes so we can do
830 * our end-of-charge logic based on the battery level change.
831 *(no longer use minimum time as logic for charge end has 50
832 * minutes minimum charge built in)
834 if (powermgmt_last_cycle_startstop_min > CHARGE_END_SHORTD) {
835 short_delta = power_history[0] -
836 power_history[CHARGE_END_SHORTD - 1];
839 if (powermgmt_last_cycle_startstop_min > CHARGE_END_LONGD) {
841 * Scan the history: the points where measurement is taken need to
842 * be fairly static. (check prior to short delta 'area')
843 * (also only check first and last 10 cycles - delta in middle OK)
845 long_delta = power_history[0] -
846 power_history[CHARGE_END_LONGD - 1];
848 for(i = CHARGE_END_SHORTD; i < CHARGE_END_SHORTD + 10; i++) {
849 if(((power_history[i] - power_history[i+1]) > 5) ||
850 ((power_history[i] - power_history[i+1]) < -5)) {
851 long_delta = 777777;
852 break;
855 for(i = CHARGE_END_LONGD - 11; i < CHARGE_END_LONGD - 1 ; i++) {
856 if(((power_history[i] - power_history[i+1]) > 5) ||
857 ((power_history[i] - power_history[i+1]) < -5)) {
858 long_delta = 888888;
859 break;
864 snprintf(power_message, POWER_MESSAGE_LEN,
865 "Chg %dm, max %dm", powermgmt_last_cycle_startstop_min,
866 charge_max_time_now);
868 * End of charge criteria (any qualify):
869 * 1) Charged a long time
870 * 2) DeltaV went negative for a short time ( & long delta static)
871 * 3) DeltaV was negative over a longer period (no disk use only)
872 * Note: short_delta and long_delta are centivolts
874 if ((powermgmt_last_cycle_startstop_min >= charge_max_time_now) ||
875 (short_delta <= -5 && long_delta < 5 ) || (long_delta < -2 &&
876 last_disk_activity > CHARGE_END_LONGD)) {
877 if (powermgmt_last_cycle_startstop_min > charge_max_time_now) {
878 DEBUGF("power: powermgmt_last_cycle_startstop_min > charge_max_time_now, "
879 "enough!\n");
881 *have charged too long and deltaV detection did not
882 *work!
884 snprintf(power_message, POWER_MESSAGE_LEN,
885 "Chg tmout %d min", charge_max_time_now);
887 * Switch to trickle charging. We skip the top-off
888 * since we've effectively done the top-off operation
889 * already since we charged for the maximum full
890 * charge time.
892 powermgmt_last_cycle_level = battery_percent;
893 powermgmt_last_cycle_startstop_min = 0;
894 charge_state = TRICKLE;
897 * set trickle charge target to a relative voltage instead
898 * of an arbitrary value - the fully charged voltage may
899 * vary according to ambient temp, battery condition etc
900 * trickle target is -0.15v from full voltage acheived
901 * topup target is -0.05v from full voltage
903 target_voltage = power_history[0] - 15;
905 } else {
906 if(short_delta <= -5) {
907 DEBUGF("power: short-term negative"
908 " delta, enough!\n");
909 snprintf(power_message, POWER_MESSAGE_LEN,
910 "end negd %d %dmin", short_delta,
911 powermgmt_last_cycle_startstop_min);
912 target_voltage = power_history[CHARGE_END_SHORTD - 1]
913 - 5;
914 } else {
915 DEBUGF("power: long-term small "
916 "positive delta, enough!\n");
917 snprintf(power_message, POWER_MESSAGE_LEN,
918 "end lowd %d %dmin", long_delta,
919 powermgmt_last_cycle_startstop_min);
920 target_voltage = power_history[CHARGE_END_LONGD - 1]
921 - 5;
924 * Switch to top-off charging.
926 powermgmt_last_cycle_level = battery_percent;
927 powermgmt_last_cycle_startstop_min = 0;
928 charge_state = TOPOFF;
932 else if (charge_state != DISCHARGING) /* top off or trickle */
935 *Time to switch from topoff to trickle?
937 if ((charge_state == TOPOFF) &&
938 (powermgmt_last_cycle_startstop_min > TOPOFF_MAX_TIME))
940 powermgmt_last_cycle_level = battery_percent;
941 powermgmt_last_cycle_startstop_min = 0;
942 charge_state = TRICKLE;
943 target_voltage = target_voltage - 10;
946 * Adjust trickle charge time (proportional and integral terms).
947 * Note: I considered setting the level higher if the USB is
948 * plugged in, but it doesn't appear to be necessary and will
949 * generate more heat [gvb].
952 pid_p = target_voltage - battery_centivolts;
953 if((pid_p > PID_DEADZONE) || (pid_p < -PID_DEADZONE))
954 pid_p = pid_p * PID_PCONST;
955 else
956 pid_p = 0;
957 if(battery_centivolts < target_voltage) {
958 if(pid_i < 60) {
959 pid_i++; /* limit so it doesn't "wind up" */
961 } else {
962 if(pid_i > 0) {
963 pid_i--; /* limit so it doesn't "wind up" */
967 trickle_sec = pid_p + pid_i;
969 if(trickle_sec > 60) {
970 trickle_sec = 60;
972 if(trickle_sec < 0) {
973 trickle_sec = 0;
976 } else if (charge_state == DISCHARGING) {
977 trickle_sec = 0;
979 * The charger is enabled here only in one case: if it was
980 * turned on at boot time (power_init). Turn it off now.
982 if (charger_enabled)
983 charger_enable(false);
986 if (charger_input_state == CHARGER_UNPLUGGED) {
988 * The charger was just unplugged.
990 DEBUGF("power: charger disconnected, disabling\n");
992 charger_enable(false);
993 powermgmt_last_cycle_level = battery_percent;
994 powermgmt_last_cycle_startstop_min = 0;
995 trickle_sec = 0;
996 pid_p = 0;
997 pid_i = 0;
998 charge_state = DISCHARGING;
999 snprintf(power_message, POWER_MESSAGE_LEN, "Charger: discharge");
1002 #endif /* CONFIG_CHARGING == CHARGING_CONTROL */
1004 /* sleep for a minute */
1006 #if CONFIG_CHARGING == CHARGING_CONTROL
1007 if(trickle_sec > 0) {
1008 charger_enable(true);
1009 power_thread_sleep(HZ * trickle_sec);
1011 if(trickle_sec < 60)
1012 charger_enable(false);
1013 power_thread_sleep(HZ * (60 - trickle_sec));
1014 #else
1015 power_thread_sleep(HZ * 60);
1016 #endif
1018 #if defined(DEBUG_FILE) && (CONFIG_CHARGING == CHARGING_CONTROL)
1019 if(usb_inserted()) {
1020 if(fd >= 0) {
1021 /* It is probably too late to close the file but we can try...*/
1022 close(fd);
1023 fd = -1;
1025 } else {
1026 if(fd < 0) {
1027 fd = open(DEBUG_FILE_NAME, O_WRONLY | O_APPEND | O_CREAT);
1028 if(fd >= 0) {
1029 snprintf(debug_message, DEBUG_MESSAGE_LEN,
1030 "cycle_min, bat_centivolts, bat_percent, chgr_state, charge_state, pid_p, pid_i, trickle_sec\n");
1031 write(fd, debug_message, strlen(debug_message));
1032 wrcount = 99; /* force a flush */
1035 if(fd >= 0) {
1036 snprintf(debug_message, DEBUG_MESSAGE_LEN,
1037 "%d, %d, %d, %d, %d, %d, %d, %d\n",
1038 powermgmt_last_cycle_startstop_min, battery_centivolts,
1039 battery_percent, charger_input_state, charge_state,
1040 pid_p, pid_i, trickle_sec);
1041 write(fd, debug_message, strlen(debug_message));
1042 wrcount++;
1045 #endif
1046 handle_auto_poweroff();
1048 #if CONFIG_CHARGING == CHARGING_CONTROL
1049 powermgmt_last_cycle_startstop_min++;
1050 #endif
1054 void powermgmt_init(void)
1056 /* init history to 0 */
1057 memset(power_history, 0x00, sizeof(power_history));
1058 create_thread(power_thread, power_stack, sizeof(power_stack),
1059 power_thread_name IF_PRIO(, PRIORITY_SYSTEM));
1062 #endif /* SIMULATOR */
1064 void sys_poweroff(void)
1066 logf("sys_poweroff()");
1067 /* If the main thread fails to shut down the system, we will force a
1068 power off after an 20 second timeout */
1069 shutdown_timeout = HZ*20;
1071 queue_post(&button_queue, SYS_POWEROFF, NULL);
1074 void cancel_shutdown(void)
1076 logf("sys_cancel_shutdown()");
1078 #if defined(IAUDIO_X5) && !defined (SIMULATOR)
1079 /* TODO: Move some things to target/ tree */
1080 if (shutdown_timeout)
1081 pcf50606_reset_timeout();
1082 #endif
1084 shutdown_timeout = 0;
1087 /* Various hardware housekeeping tasks relating to shutting down the jukebox */
1088 void shutdown_hw(void)
1090 #ifndef SIMULATOR
1091 #if defined(DEBUG_FILE) && (CONFIG_CHARGING == CHARGING_CONTROL)
1092 if(fd >= 0) {
1093 close(fd);
1094 fd = -1;
1096 #endif
1097 audio_stop();
1098 #ifdef HAVE_LCD_BITMAP
1099 glyph_cache_save();
1100 #endif
1101 ata_flush();
1102 ata_spindown(1);
1103 while(ata_disk_is_active())
1104 sleep(HZ/10);
1106 mp3_shutdown();
1107 #ifdef HAVE_UDA1380
1108 uda1380_close();
1109 #elif defined(HAVE_TLV320)
1110 tlv320_close();
1111 #elif defined(HAVE_WM8758) || defined(HAVE_WM8975)
1112 wmcodec_close();
1113 #endif
1114 #ifndef IAUDIO_X5
1115 #if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR)
1116 backlight_set_fade_out(0);
1117 #endif
1118 backlight_off();
1119 lcd_set_contrast(0);
1120 #endif /* IAUDIO_X5 */
1121 #ifdef HAVE_REMOTE_LCD
1122 remote_backlight_off();
1123 lcd_remote_set_contrast(0);
1124 #endif
1125 power_off();
1126 #endif /* #ifndef SIMULATOR */