Correct compiler errors from last commit.
[Rockbox.git] / firmware / powermgmt.c
blob1ae909d8daf5241d9f3e4310c98e7d06516d5cf2
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
63 * Define DEBUG_FILE to create a csv (spreadsheet) with battery information
64 * in it (one sample per minute). This is only for very low level debug.
66 #undef DEBUG_FILE
67 #if defined(DEBUG_FILE) && defined(HAVE_CHARGE_CTRL)
68 #include "file.h"
69 #define DEBUG_FILE_NAME "/powermgmt.csv"
70 #define DEBUG_MESSAGE_LEN 133
71 static char debug_message[DEBUG_MESSAGE_LEN];
72 #define DEBUG_STACK ((0x1000)/sizeof(long))
73 static int fd; /* write debug information to this file */
74 static int wrcount;
75 #else
76 #define DEBUG_STACK 0
77 #endif
79 static int shutdown_timeout = 0;
81 #ifdef SIMULATOR /***********************************************************/
83 #define TIME2CHANGE 10 /* change levels every 10 seconds */
84 #define BATT_MINCVOLT 250 /* minimum centivolts of battery */
85 #define BATT_MAXCVOLT 450 /* maximum centivolts of battery */
86 #define BATT_MAXRUNTIME (10 * 60) /* maximum runtime with full battery in minutes */
88 static unsigned int batt_centivolts = (unsigned int)BATT_MAXCVOLT;
89 static int batt_level = 100; /* battery capacity level in percent */
90 static int batt_time = BATT_MAXRUNTIME; /* estimated remaining time in minutes */
91 static time_t last_change = 0;
93 static void battery_status_update(void)
95 time_t now;
97 time(&now);
98 if (last_change < (now - TIME2CHANGE)) {
99 last_change = now;
101 /* change the values: */
102 batt_centivolts -= (unsigned int)(BATT_MAXCVOLT - BATT_MINCVOLT) / 11;
103 if (batt_centivolts < (unsigned int)BATT_MINCVOLT)
104 batt_centivolts = (unsigned int)BATT_MAXCVOLT;
106 batt_level = 100 * (batt_centivolts - BATT_MINCVOLT) / (BATT_MAXCVOLT - BATT_MINCVOLT);
107 batt_time = batt_level * BATT_MAXRUNTIME / 100;
111 unsigned int battery_voltage(void)
113 battery_status_update();
114 return batt_centivolts;
117 int battery_level(void)
119 battery_status_update();
120 return batt_level;
123 int battery_time(void)
125 battery_status_update();
126 return batt_time;
129 bool battery_level_safe(void)
131 return battery_level() >= 10;
134 void set_poweroff_timeout(int timeout)
136 (void)timeout;
139 void set_battery_capacity(int capacity)
141 (void)capacity;
144 void reset_poweroff_timer(void)
149 #else /* not SIMULATOR ******************************************************/
151 static const int poweroff_idle_timeout_value[15] =
153 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 30, 45, 60
156 static const unsigned int battery_level_dangerous[BATTERY_TYPES_COUNT] =
158 #if CONFIG_BATTERY == BATT_LIION2200 /* FM Recorder, LiIon */
160 #elif CONFIG_BATTERY == BATT_3AAA /* Ondio */
161 310, 345 /* alkaline, NiHM */
162 #elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver H1x0 */
164 #else /* Player/recorder, NiMH */
166 #endif
169 static const short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
170 /* voltages (centivolt) of 0%, 10%, ... 100% when charging disabled */
172 #if CONFIG_BATTERY == BATT_LIION2200
173 /* measured values */
174 { 260, 285, 295, 303, 311, 320, 330, 345, 360, 380, 400 }
175 #elif CONFIG_BATTERY == BATT_3AAA
176 /* measured values */
177 { 280, 325, 341, 353, 364, 374, 385, 395, 409, 427, 475 }, /* alkaline */
178 { 310, 355, 363, 369, 372, 374, 376, 378, 380, 386, 405 } /* NiMH */
179 #elif CONFIG_BATTERY == BATT_LIPOL1300
180 /* Below 337 the backlight starts flickering during HD access */
181 /* Calibrated for Ionity 1900 mAh battery. If necessary, re-calibrate
182 * for the 1300 mAh stock battery. */
183 // { 337, 358, 365, 369, 372, 377, 383, 389, 397, 406, 413 }
184 { 337, 366, 372, 374, 378, 381, 385, 392, 399, 408, 417 }
185 #else /* NiMH */
186 /* original values were taken directly after charging, but it should show
187 100% after turning off the device for some hours, too */
188 { 450, 481, 491, 497, 503, 507, 512, 514, 517, 525, 540 }
189 /* orig. values: ...,528,560 */
190 #endif
193 #ifdef HAVE_CHARGING
194 charger_input_state_type charger_input_state IDATA_ATTR;
196 /* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */
197 static const short percent_to_volt_charge[11] =
199 #if CONFIG_BATTERY == BATT_LIPOL1300
200 /* Calibrated for 1900 mAh Ionity battery (estimated 90% charge when
201 entering in trickle-charging). We will never reach 100%. */
202 340, 390, 394, 399, 400, 404, 407, 413, 417, 422, 426
203 #else
204 /* values guessed, see
205 http://www.seattlerobotics.org/encoder/200210/LiIon2.pdf until someone
206 measures voltages over a charging cycle */
207 476, 544, 551, 556, 561, 564, 566, 576, 582, 584, 585 /* NiMH */
208 #endif
210 #endif /* HAVE_CHARGING */
212 #if defined(HAVE_CHARGE_CTRL) || \
213 CONFIG_BATTERY == BATT_LIION2200 || \
214 defined(HAVE_CHARGE_STATE)
215 charge_state_type charge_state; /* charging mode */
216 #endif
218 #ifdef HAVE_CHARGE_CTRL
219 int long_delta; /* long term delta battery voltage */
220 int short_delta; /* short term delta battery voltage */
221 bool disk_activity_last_cycle = false; /* flag set to aid charger time
222 * calculation */
223 char power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in
224 debug menu */
225 /* percentage at which charging
226 starts */
227 int powermgmt_last_cycle_startstop_min = 0; /* how many minutes ago was the
228 charging started or
229 stopped? */
230 int powermgmt_last_cycle_level = 0; /* which level had the
231 batteries at this time? */
232 int trickle_sec = 0; /* how many seconds should the
233 charger be enabled per
234 minute for trickle
235 charging? */
236 int pid_p = 0; /* PID proportional term */
237 int pid_i = 0; /* PID integral term */
238 #endif /* HAVE_CHARGE_CTRL */
241 * Average battery voltage and charger voltage, filtered via a digital
242 * exponential filter.
244 static unsigned int battery_centivolts;/* filtered battery voltage, centvolts */
245 static unsigned int avgbat; /* average battery voltage (filtering) */
246 #define BATT_AVE_SAMPLES 32 /* filter constant / @ 2Hz sample rate */
248 /* battery level (0-100%) of this minute, updated once per minute */
249 static int battery_percent = -1;
250 static int battery_capacity = BATTERY_CAPACITY_MIN; /* default value, mAH */
251 static int battery_type = 0;
253 /* Power history: power_history[0] is the newest sample */
254 unsigned short power_history[POWER_HISTORY_LEN];
256 static char power_stack[DEFAULT_STACK_SIZE + DEBUG_STACK];
257 static const char power_thread_name[] = "power";
259 static int poweroff_timeout = 0;
260 static int powermgmt_est_runningtime_min = -1;
262 static bool sleeptimer_active = false;
263 static long sleeptimer_endtick;
265 static long last_event_tick;
267 static void battery_status_update(void);
268 static int runcurrent(void);
270 unsigned int battery_voltage(void)
272 return battery_centivolts;
275 void reset_poweroff_timer(void)
277 last_event_tick = current_tick;
280 #if BATTERY_TYPES_COUNT > 1
281 void set_battery_type(int type)
283 if (type != battery_type) {
284 battery_type = type;
285 battery_status_update(); /* recalculate the battery status */
288 #endif
290 void set_battery_capacity(int capacity)
292 battery_capacity = capacity;
293 if (battery_capacity > BATTERY_CAPACITY_MAX)
294 battery_capacity = BATTERY_CAPACITY_MAX;
295 if (battery_capacity < BATTERY_CAPACITY_MIN)
296 battery_capacity = BATTERY_CAPACITY_MIN;
297 battery_status_update(); /* recalculate the battery status */
300 int battery_time(void)
302 return powermgmt_est_runningtime_min;
305 /* Returns battery level in percent */
306 int battery_level(void)
308 return battery_percent;
311 /* Tells if the battery level is safe for disk writes */
312 bool battery_level_safe(void)
314 return battery_centivolts > battery_level_dangerous[battery_type];
317 void set_poweroff_timeout(int timeout)
319 poweroff_timeout = timeout;
322 void set_sleep_timer(int seconds)
324 if(seconds) {
325 sleeptimer_active = true;
326 sleeptimer_endtick = current_tick + seconds * HZ;
328 else {
329 sleeptimer_active = false;
330 sleeptimer_endtick = 0;
334 int get_sleep_timer(void)
336 if(sleeptimer_active)
337 return (sleeptimer_endtick - current_tick) / HZ;
338 else
339 return 0;
342 /* look into the percent_to_volt_* table and get a realistic battery level
343 percentage */
344 static int voltage_to_percent(int voltage, const short* table)
346 if (voltage <= table[0])
347 return 0;
348 else
349 if (voltage >= table[10])
350 return 100;
351 else {
352 /* search nearest value */
353 int i = 0;
354 while ((i < 10) && (table[i+1] < voltage))
355 i++;
356 /* interpolate linear between the smaller and greater value */
357 return (i * 10) /* Tens digit, 10% per entry */
358 + (((voltage - table[i]) * 10)
359 / (table[i+1] - table[i])); /* Ones digit: interpolated */
363 /* update battery level and estimated runtime, called once per minute or
364 * when battery capacity / type settings are changed */
365 static void battery_status_update(void)
367 int level;
369 #if defined(HAVE_CHARGE_CTRL) || defined(HAVE_CHARGE_STATE)
370 if (charge_state == DISCHARGING) {
371 level = voltage_to_percent(battery_centivolts,
372 percent_to_volt_discharge[battery_type]);
374 else if (charge_state == CHARGING) {
375 /* battery level is defined to be < 100% until charging is finished */
376 level = MIN(voltage_to_percent(battery_centivolts,
377 percent_to_volt_charge), 99);
379 else { /* in topoff/trickle charge, the battery is by definition 100% full */
380 level = 100;
382 #else
383 /* always use the discharge table */
384 level = voltage_to_percent(battery_centivolts,
385 percent_to_volt_discharge[battery_type]);
386 #endif
388 #ifndef HAVE_MMC /* this adjustment is only needed for HD based */
389 if (battery_percent == -1) { /* first run of this procedure */
390 /* The battery voltage is usually a little lower directly after
391 turning on, because the disk was used heavily. Raise it by 5. % */
392 level = (level > 95) ? 100 : level + 5;
394 #endif
395 battery_percent = level;
397 /* calculate estimated remaining running time */
398 /* discharging: remaining running time */
399 /* charging: remaining charging time */
400 #if defined(HAVE_CHARGE_CTRL) || defined(HAVE_CHARGE_STATE)
401 if (charge_state == CHARGING) {
402 powermgmt_est_runningtime_min = (100 - level) * battery_capacity / 100
403 * 60 / (CURRENT_MAX_CHG - runcurrent());
405 else
406 #endif
408 powermgmt_est_runningtime_min = level * battery_capacity / 100
409 * 60 / runcurrent();
414 * We shut off in the following cases:
415 * 1) The unit is idle, not playing music
416 * 2) The unit is playing music, but is paused
418 * We do not shut off in the following cases:
419 * 1) The USB is connected
420 * 2) The charger is connected
421 * 3) We are recording, or recording with pause
423 static void handle_auto_poweroff(void)
425 long timeout = poweroff_idle_timeout_value[poweroff_timeout]*60*HZ;
426 int audio_stat = audio_status();
428 #ifdef HAVE_CHARGING
430 * Inhibit shutdown as long as the charger is plugged in. If it is
431 * unplugged, wait for a timeout period and then shut down.
433 if(charger_input_state == CHARGER || audio_stat == AUDIO_STATUS_PLAY) {
434 last_event_tick = current_tick;
436 #endif
438 if(timeout &&
439 #ifdef CONFIG_TUNER
440 (!radio_powered()) &&
441 #endif
442 !usb_inserted() &&
443 ((audio_stat == 0) ||
444 ((audio_stat == (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE)) &&
445 !sleeptimer_active)))
447 if(TIME_AFTER(current_tick, last_event_tick + timeout) &&
448 TIME_AFTER(current_tick, last_disk_activity + timeout))
450 sys_poweroff();
453 else
455 /* Handle sleeptimer */
456 if(sleeptimer_active && !usb_inserted())
458 if(TIME_AFTER(current_tick, sleeptimer_endtick))
460 audio_stop();
461 #if defined(HAVE_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
462 if((charger_input_state == CHARGER) ||
463 (charger_input_state == CHARGER_PLUGGED))
465 DEBUGF("Sleep timer timeout. Stopping...\n");
466 set_sleep_timer(0);
467 backlight_off(); /* Nighty, nighty... */
469 else
470 #endif
472 DEBUGF("Sleep timer timeout. Shutting off...\n");
473 sys_poweroff();
481 * Estimate how much current we are drawing just to run.
483 static int runcurrent(void)
485 int current;
487 #if MEM == 8 && !defined(HAVE_MMC)
488 /* assuming 192 kbps, the running time is 22% longer with 8MB */
489 current = (CURRENT_NORMAL*100/122);
490 #else
491 current = CURRENT_NORMAL;
492 #endif /* MEM == 8 */
494 if(usb_inserted()
495 #if defined(HAVE_USB_POWER)
496 #if (CURRENT_USB < CURRENT_NORMAL)
497 || usb_powered()
498 #else
499 && !usb_powered()
500 #endif
501 #endif
504 current = CURRENT_USB;
507 #if defined(CONFIG_BACKLIGHT) && !defined(BOOTLOADER)
508 if (backlight_get_current_timeout() == 0) /* LED always on */
509 current += CURRENT_BACKLIGHT;
510 #endif
512 return(current);
516 /* Check to see whether or not we've received an alarm in the last second */
517 #ifdef HAVE_ALARM_MOD
518 static void power_thread_rtc_process(void)
520 if (rtc_check_alarm_flag()) {
521 rtc_enable_alarm(false);
524 #endif
527 * This function is called to do the relativly long sleep waits from within the
528 * main power_thread loop while at the same time servicing any other periodic
529 * functions in the power thread which need to be called at a faster periodic
530 * rate than the slow periodic rate of the main power_thread loop.
532 * While we are waiting for the time to expire, we average the battery
533 * voltages.
535 static void power_thread_sleep(int ticks)
537 int small_ticks;
539 while (ticks > 0) {
541 #ifdef HAVE_CHARGING
543 * Detect charger plugged/unplugged transitions. On a plugged or
544 * unplugged event, we return immediately, run once through the main
545 * loop (including the subroutines), and end up back here where we
546 * transition to the appropriate steady state charger on/off state.
548 if(charger_inserted()
549 #ifdef HAVE_USB_POWER
550 || usb_powered()
551 #endif
553 switch(charger_input_state) {
554 case NO_CHARGER:
555 case CHARGER_UNPLUGGED:
556 charger_input_state = CHARGER_PLUGGED;
557 return;
558 case CHARGER_PLUGGED:
559 queue_broadcast(SYS_CHARGER_CONNECTED, NULL);
560 charger_input_state = CHARGER;
561 break;
562 case CHARGER:
563 break;
565 } else { /* charger not inserted */
566 switch(charger_input_state) {
567 case NO_CHARGER:
568 break;
569 case CHARGER_UNPLUGGED:
570 queue_broadcast(SYS_CHARGER_DISCONNECTED, NULL);
571 charger_input_state = NO_CHARGER;
572 break;
573 case CHARGER_PLUGGED:
574 case CHARGER:
575 charger_input_state = CHARGER_UNPLUGGED;
576 return;
579 #endif
580 #ifdef HAVE_CHARGE_STATE
581 switch (charger_input_state) {
582 case CHARGER_UNPLUGGED:
583 case NO_CHARGER:
584 charge_state = DISCHARGING;
585 break;
586 case CHARGER_PLUGGED:
587 case CHARGER:
588 if (charging_state()) {
589 charge_state = CHARGING;
590 } else {
591 charge_state = DISCHARGING;
593 break;
596 #endif /* HAVE_CHARGE_STATE */
598 small_ticks = MIN(HZ/2, ticks);
599 sleep(small_ticks);
600 ticks -= small_ticks;
602 /* If the power off timeout expires, the main thread has failed
603 to shut down the system, and we need to force a power off */
604 if(shutdown_timeout) {
605 shutdown_timeout -= small_ticks;
606 if(shutdown_timeout <= 0)
607 power_off();
610 #ifdef HAVE_ALARM_MOD
611 power_thread_rtc_process();
612 #endif
615 * Do a digital exponential filter. We don't sample the battery if
616 * the disk is spinning unless we are in USB mode (the disk will most
617 * likely always be spinning in USB mode).
619 if (!ata_disk_is_active() || usb_inserted()) {
620 avgbat = avgbat - (avgbat / BATT_AVE_SAMPLES) +
621 adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR;
623 * battery_centivolts is the centivolt-scaled filtered battery value.
625 battery_centivolts = avgbat / BATT_AVE_SAMPLES / 10000;
627 /* update battery status every time an update is available */
628 battery_status_update();
631 #ifdef HAVE_CHARGE_CTRL
632 if (ata_disk_is_active()) {
633 /* flag hdd use for charging calculation */
634 disk_activity_last_cycle = true;
636 #endif
637 #if defined(DEBUG_FILE) && defined(HAVE_CHARGE_CTRL)
639 * If we have a lot of pending writes or if the disk is spining,
640 * fsync the debug log file.
642 if((wrcount > 10) ||
643 ((wrcount > 0) && ata_disk_is_active())) {
644 fsync(fd);
645 wrcount = 0;
647 #endif
653 * This power thread maintains a history of battery voltage
654 * and implements a charging algorithm.
655 * For a complete description of the charging algorithm read
656 * docs/CHARGING_ALGORITHM.
659 static void power_thread(void)
661 int i;
662 short *phps, *phpd; /* power history rotation pointers */
663 #ifdef HAVE_CHARGE_CTRL
664 unsigned int target_voltage = TRICKLE_VOLTAGE; /* desired topoff/trickle
665 * voltage level */
666 int charge_max_time_idle = 0; /* max. charging duration, calculated at
667 * beginning of charging */
668 int charge_max_time_now = 0; /* max. charging duration including
669 * hdd activity */
670 int minutes_disk_activity = 0; /* count minutes of hdd use during
671 * charging */
672 int last_disk_activity = CHARGE_END_LONGD + 1; /* last hdd use x mins ago */
673 #endif
675 /* initialize the voltages for the exponential filter */
677 avgbat = adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR *
678 BATT_AVE_SAMPLES;
679 battery_centivolts = avgbat / BATT_AVE_SAMPLES / 10000;
681 #if defined(DEBUG_FILE) && defined(HAVE_CHARGE_CTRL)
682 fd = -1;
683 wrcount = 0;
684 #endif
686 while (1)
688 /* rotate the power history */
689 phpd = &power_history[POWER_HISTORY_LEN - 1];
690 phps = phpd - 1;
691 for (i = 0; i < POWER_HISTORY_LEN-1; i++)
692 *phpd-- = *phps--;
694 /* insert new value at the start, in centivolts 8-) */
695 power_history[0] = battery_centivolts;
697 #if CONFIG_BATTERY == BATT_LIION2200
698 /* We use the information from the ADC_EXT_POWER ADC channel, which
699 tells us the charging current from the LTC1734. When DC is
700 connected (either via the external adapter, or via USB), we try
701 to determine if it is actively charging or only maintaining the
702 charge. My tests show that ADC readings below about 0x80 means
703 that the LTC1734 is only maintaining the charge. */
704 if(charger_inserted()) {
705 if(adc_read(ADC_EXT_POWER) < 0x80) {
706 charge_state = TRICKLE;
707 } else {
708 charge_state = CHARGING;
710 } else {
711 charge_state = DISCHARGING;
713 #endif /* # if CONFIG_BATTERY == BATT_LIION2200 */
715 #ifdef HAVE_CHARGE_CTRL
716 if (charger_input_state == CHARGER_PLUGGED) {
717 pid_p = 0;
718 pid_i = 0;
719 snprintf(power_message, POWER_MESSAGE_LEN, "Charger plugged in");
721 * The charger was just plugged in. If the battery level is
722 * nearly charged, just trickle. If the battery is low, start
723 * a full charge cycle. If the battery level is in between,
724 * top-off and then trickle.
726 if(battery_percent > START_TOPOFF_CHG) {
727 powermgmt_last_cycle_level = battery_percent;
728 powermgmt_last_cycle_startstop_min = 0;
729 if(battery_percent >= START_TRICKLE_CHG) {
730 charge_state = TRICKLE;
731 target_voltage = TRICKLE_VOLTAGE;
732 } else {
733 charge_state = TOPOFF;
734 target_voltage = TOPOFF_VOLTAGE;
736 } else {
738 * Start the charger full strength
740 i = CHARGE_MAX_TIME_1500 * battery_capacity / 1500;
741 charge_max_time_idle =
742 i * (100 + 35 - battery_percent) / 100;
743 if (charge_max_time_idle > i) {
744 charge_max_time_idle = i;
746 charge_max_time_now = charge_max_time_idle;
748 snprintf(power_message, POWER_MESSAGE_LEN,
749 "ChgAt %d%% max %dm", battery_level(),
750 charge_max_time_now);
752 /* enable the charger after the max time calc is done,
753 because battery_level depends on if the charger is
754 on */
755 DEBUGF("power: charger inserted and battery"
756 " not full, charging\n");
757 powermgmt_last_cycle_level = battery_percent;
758 powermgmt_last_cycle_startstop_min = 0;
759 trickle_sec = 60;
760 long_delta = short_delta = 999999;
761 charge_state = CHARGING;
764 if (charge_state == CHARGING) {
765 /* alter charge time max length with extra disk use */
766 if (disk_activity_last_cycle) {
767 minutes_disk_activity++;
768 charge_max_time_now = charge_max_time_idle +
769 (minutes_disk_activity * 2 / 5);
770 disk_activity_last_cycle = false;
771 last_disk_activity = 0;
772 } else {
773 last_disk_activity++;
776 * Check the delta voltage over the last X minutes so we can do
777 * our end-of-charge logic based on the battery level change.
778 *(no longer use minimum time as logic for charge end has 50
779 * minutes minimum charge built in)
781 if (powermgmt_last_cycle_startstop_min > CHARGE_END_SHORTD) {
782 short_delta = power_history[0] -
783 power_history[CHARGE_END_SHORTD - 1];
786 if (powermgmt_last_cycle_startstop_min > CHARGE_END_LONGD) {
788 * Scan the history: the points where measurement is taken need to
789 * be fairly static. (check prior to short delta 'area')
790 * (also only check first and last 10 cycles - delta in middle OK)
792 long_delta = power_history[0] -
793 power_history[CHARGE_END_LONGD - 1];
795 for(i = CHARGE_END_SHORTD; i < CHARGE_END_SHORTD + 10; i++) {
796 if(((power_history[i] - power_history[i+1]) > 5) ||
797 ((power_history[i] - power_history[i+1]) < -5)) {
798 long_delta = 777777;
799 break;
802 for(i = CHARGE_END_LONGD - 11; i < CHARGE_END_LONGD - 1 ; i++) {
803 if(((power_history[i] - power_history[i+1]) > 5) ||
804 ((power_history[i] - power_history[i+1]) < -5)) {
805 long_delta = 888888;
806 break;
811 snprintf(power_message, POWER_MESSAGE_LEN,
812 "Chg %dm, max %dm", powermgmt_last_cycle_startstop_min,
813 charge_max_time_now);
815 * End of charge criteria (any qualify):
816 * 1) Charged a long time
817 * 2) DeltaV went negative for a short time ( & long delta static)
818 * 3) DeltaV was negative over a longer period (no disk use only)
819 * Note: short_delta and long_delta are centivolts
821 if ((powermgmt_last_cycle_startstop_min >= charge_max_time_now) ||
822 (short_delta <= -5 && long_delta < 5 ) || (long_delta < -2 &&
823 last_disk_activity > CHARGE_END_LONGD)) {
824 if (powermgmt_last_cycle_startstop_min > charge_max_time_now) {
825 DEBUGF("power: powermgmt_last_cycle_startstop_min > charge_max_time_now, "
826 "enough!\n");
828 *have charged too long and deltaV detection did not
829 *work!
831 snprintf(power_message, POWER_MESSAGE_LEN,
832 "Chg tmout %d min", charge_max_time_now);
834 * Switch to trickle charging. We skip the top-off
835 * since we've effectively done the top-off operation
836 * already since we charged for the maximum full
837 * charge time.
839 powermgmt_last_cycle_level = battery_percent;
840 powermgmt_last_cycle_startstop_min = 0;
841 charge_state = TRICKLE;
844 * set trickle charge target to a relative voltage instead
845 * of an arbitrary value - the fully charged voltage may
846 * vary according to ambient temp, battery condition etc
847 * trickle target is -0.15v from full voltage acheived
848 * topup target is -0.05v from full voltage
850 target_voltage = power_history[0] - 15;
852 } else {
853 if(short_delta <= -5) {
854 DEBUGF("power: short-term negative"
855 " delta, enough!\n");
856 snprintf(power_message, POWER_MESSAGE_LEN,
857 "end negd %d %dmin", short_delta,
858 powermgmt_last_cycle_startstop_min);
859 target_voltage = power_history[CHARGE_END_SHORTD - 1]
860 - 5;
861 } else {
862 DEBUGF("power: long-term small "
863 "positive delta, enough!\n");
864 snprintf(power_message, POWER_MESSAGE_LEN,
865 "end lowd %d %dmin", long_delta,
866 powermgmt_last_cycle_startstop_min);
867 target_voltage = power_history[CHARGE_END_LONGD - 1]
868 - 5;
871 * Switch to top-off charging.
873 powermgmt_last_cycle_level = battery_percent;
874 powermgmt_last_cycle_startstop_min = 0;
875 charge_state = TOPOFF;
879 else if (charge_state > CHARGING) /* top off or trickle */
882 *Time to switch from topoff to trickle?
884 if ((charge_state == TOPOFF) &&
885 (powermgmt_last_cycle_startstop_min > TOPOFF_MAX_TIME))
887 powermgmt_last_cycle_level = battery_percent;
888 powermgmt_last_cycle_startstop_min = 0;
889 charge_state = TRICKLE;
890 target_voltage = target_voltage - 10;
893 * Adjust trickle charge time (proportional and integral terms).
894 * Note: I considered setting the level higher if the USB is
895 * plugged in, but it doesn't appear to be necessary and will
896 * generate more heat [gvb].
899 pid_p = target_voltage - battery_centivolts;
900 if((pid_p > PID_DEADZONE) || (pid_p < -PID_DEADZONE))
901 pid_p = pid_p * PID_PCONST;
902 else
903 pid_p = 0;
904 if(battery_centivolts < target_voltage) {
905 if(pid_i < 60) {
906 pid_i++; /* limit so it doesn't "wind up" */
908 } else {
909 if(pid_i > 0) {
910 pid_i--; /* limit so it doesn't "wind up" */
914 trickle_sec = pid_p + pid_i;
916 if(trickle_sec > 60) {
917 trickle_sec = 60;
919 if(trickle_sec < 0) {
920 trickle_sec = 0;
923 } else if (charge_state == DISCHARGING) {
924 trickle_sec = 0;
926 * The charger is enabled here only in one case: if it was
927 * turned on at boot time (power_init). Turn it off now.
929 if (charger_enabled)
930 charger_enable(false);
933 if (charger_input_state == CHARGER_UNPLUGGED) {
935 * The charger was just unplugged.
937 DEBUGF("power: charger disconnected, disabling\n");
939 charger_enable(false);
940 powermgmt_last_cycle_level = battery_percent;
941 powermgmt_last_cycle_startstop_min = 0;
942 trickle_sec = 0;
943 pid_p = 0;
944 pid_i = 0;
945 charge_state = DISCHARGING;
946 snprintf(power_message, POWER_MESSAGE_LEN, "Charger: discharge");
949 #endif /* end HAVE_CHARGE_CTRL */
951 /* sleep for a minute */
953 #ifdef HAVE_CHARGE_CTRL
954 if(trickle_sec > 0) {
955 charger_enable(true);
956 power_thread_sleep(HZ * trickle_sec);
958 if(trickle_sec < 60)
959 charger_enable(false);
960 power_thread_sleep(HZ * (60 - trickle_sec));
961 #else
962 power_thread_sleep(HZ * 60);
963 #endif
965 #if defined(DEBUG_FILE) && defined(HAVE_CHARGE_CTRL)
966 if(usb_inserted()) {
967 if(fd >= 0) {
968 /* It is probably too late to close the file but we can try...*/
969 close(fd);
970 fd = -1;
972 } else {
973 if(fd < 0) {
974 fd = open(DEBUG_FILE_NAME, O_WRONLY | O_APPEND | O_CREAT);
975 if(fd >= 0) {
976 snprintf(debug_message, DEBUG_MESSAGE_LEN,
977 "cycle_min, bat_centivolts, bat_percent, chgr_state, charge_state, pid_p, pid_i, trickle_sec\n");
978 write(fd, debug_message, strlen(debug_message));
979 wrcount = 99; /* force a flush */
982 if(fd >= 0) {
983 snprintf(debug_message, DEBUG_MESSAGE_LEN,
984 "%d, %d, %d, %d, %d, %d, %d, %d\n",
985 powermgmt_last_cycle_startstop_min, battery_centivolts,
986 battery_percent, charger_input_state, charge_state,
987 pid_p, pid_i, trickle_sec);
988 write(fd, debug_message, strlen(debug_message));
989 wrcount++;
992 #endif
993 handle_auto_poweroff();
995 #ifdef HAVE_CHARGE_CTRL
996 powermgmt_last_cycle_startstop_min++;
997 #endif
1001 void powermgmt_init(void)
1003 /* init history to 0 */
1004 memset(power_history, 0x00, sizeof(power_history));
1006 create_thread(power_thread, power_stack, sizeof(power_stack),
1007 power_thread_name);
1010 #endif /* SIMULATOR */
1012 void sys_poweroff(void)
1014 logf("sys_poweroff()");
1015 /* If the main thread fails to shut down the system, we will force a
1016 power off after an 8 second timeout */
1017 shutdown_timeout = HZ*8;
1019 queue_post(&button_queue, SYS_POWEROFF, NULL);
1022 /* Various hardware housekeeping tasks relating to shutting down the jukebox */
1023 void shutdown_hw(void)
1025 #ifndef SIMULATOR
1026 #if defined(DEBUG_FILE) && defined(HAVE_CHARGE_CTRL)
1027 if(fd >= 0) {
1028 close(fd);
1029 fd = -1;
1031 #endif
1032 audio_stop();
1033 #ifdef HAVE_LCD_BITMAP
1034 glyph_cache_save();
1035 #endif
1036 ata_flush();
1037 ata_spindown(1);
1038 while(ata_disk_is_active())
1039 sleep(HZ/10);
1041 mp3_shutdown();
1042 #ifdef HAVE_UDA1380
1043 uda1380_close();
1044 #elif defined(HAVE_TLV320)
1045 tlv320_close();
1046 #elif defined(HAVE_WM8758) || defined(HAVE_WM8975)
1047 wmcodec_close();
1048 #endif
1049 backlight_off();
1050 #if defined(IPOD_ARCH) && defined(HAVE_LCD_COLOR)
1051 /* Clear the screen and backdrop to
1052 remove ghosting effect on shutdown */
1053 lcd_set_backdrop(NULL);
1054 lcd_set_background(LCD_WHITE);
1055 lcd_clear_display();
1056 lcd_update();
1057 sleep(HZ/16);
1058 #endif
1059 lcd_set_contrast(0);
1060 #ifdef HAVE_REMOTE_LCD
1061 remote_backlight_off();
1062 lcd_remote_set_contrast(0);
1063 #endif
1064 power_off();
1065 #endif /* #ifndef SIMULATOR */