1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese
11 * Revisions copyright (C) 2005 by Gerald Van Baren
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
32 #include "mp3_playback.h"
34 #include "powermgmt.h"
35 #include "backlight.h"
42 #ifdef HAVE_LCD_BITMAP
46 #include "lcd-remote.h"
47 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
51 #if (defined(IAUDIO_X5) || defined(IAUDIO_M5)) && !defined (SIMULATOR)
52 #include "lcd-remote-target.h"
54 #if (defined(IAUDIO_X5) || defined(IAUDIO_M5) || defined(COWON_D2)) \
55 && !defined (SIMULATOR)
60 int last_sent_battery_level
= 100;
61 /* battery level (0-100%) */
62 int battery_percent
= -1;
63 void send_battery_level_event(void);
65 static bool sleeptimer_active
= false;
66 static long sleeptimer_endtick
;
69 /* State of the charger input as seen by the power thread */
70 enum charger_input_state_type charger_input_state
;
71 /* Power inputs as seen by the power thread */
72 unsigned int power_thread_inputs
;
73 #if CONFIG_CHARGING >= CHARGING_MONITOR
74 /* Charging state (mode) as seen by the power thread */
75 enum charge_state_type charge_state
= DISCHARGING
;
77 #endif /* CONFIG_CHARGING */
79 static int shutdown_timeout
= 0;
81 void handle_auto_poweroff(void);
82 static int poweroff_timeout
= 0;
83 static long last_event_tick
= 0;
85 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
87 * Average battery voltage and charger voltage, filtered via a digital
88 * exponential filter (aka. exponential moving average, scaled):
89 * avgbat = y[n] = (N-1)/N*y[n-1] + x[n]. battery_millivolts = y[n] / N.
91 static unsigned int avgbat
;
92 /* filtered battery voltage, millivolts */
93 static unsigned int battery_millivolts
;
94 /* default value, mAh */
95 static int battery_capacity
= BATTERY_CAPACITY_DEFAULT
;
98 #if BATTERY_TYPES_COUNT > 1
99 static int battery_type
= 0;
101 #define battery_type 0
104 /* Power history: power_history[0] is the newest sample */
105 unsigned short power_history
[POWER_HISTORY_LEN
] = {0};
107 #if CONFIG_CPU == JZ4732 /* FIXME! */
108 static char power_stack
[DEFAULT_STACK_SIZE
+ POWERMGMT_DEBUG_STACK
];
110 static char power_stack
[DEFAULT_STACK_SIZE
/2 + POWERMGMT_DEBUG_STACK
];
112 static const char power_thread_name
[] = "power";
114 static int powermgmt_est_runningtime_min
= -1;
116 static int voltage_to_battery_level(int battery_millivolts
);
117 static void battery_status_update(void);
119 #ifdef CURRENT_NORMAL /*only used if we have run current*/
120 static int runcurrent(void);
123 void battery_read_info(int *voltage
, int *level
)
125 int millivolts
= battery_adc_voltage();
128 *voltage
= millivolts
;
131 *level
= voltage_to_battery_level(millivolts
);
134 #if BATTERY_TYPES_COUNT > 1
135 void set_battery_type(int type
)
137 if (type
!= battery_type
) {
138 if ((unsigned)type
>= BATTERY_TYPES_COUNT
)
142 battery_status_update(); /* recalculate the battery status */
147 void set_battery_capacity(int capacity
)
149 if (capacity
> BATTERY_CAPACITY_MAX
)
150 capacity
= BATTERY_CAPACITY_MAX
;
151 if (capacity
< BATTERY_CAPACITY_MIN
)
152 capacity
= BATTERY_CAPACITY_MIN
;
154 battery_capacity
= capacity
;
156 battery_status_update(); /* recalculate the battery status */
159 int get_battery_capacity(void)
161 return battery_capacity
;
164 int battery_time(void)
166 return powermgmt_est_runningtime_min
;
169 /* Returns battery level in percent */
170 int battery_level(void)
172 #ifdef HAVE_BATTERY_SWITCH
173 if ((power_input_status() & POWER_INPUT_BATTERY
) == 0)
176 return battery_percent
;
179 /* Returns filtered battery voltage [millivolts] */
180 unsigned int battery_voltage(void)
182 return battery_millivolts
;
185 /* Tells if the battery level is safe for disk writes */
186 bool battery_level_safe(void)
188 #if defined(NO_LOW_BATTERY_SHUTDOWN)
190 #elif defined(HAVE_BATTERY_SWITCH)
191 /* Cannot rely upon the battery reading to be valid and the
192 * device could be powered externally. */
193 return input_millivolts() > battery_level_dangerous
[battery_type
];
195 return battery_millivolts
> battery_level_dangerous
[battery_type
];
199 /* look into the percent_to_volt_* table and get a realistic battery level */
200 static int voltage_to_percent(int voltage
, const short* table
)
202 if (voltage
<= table
[0]) {
205 else if (voltage
>= table
[10]) {
209 /* search nearest value */
212 while (i
< 10 && table
[i
+1] < voltage
)
215 /* interpolate linear between the smaller and greater value */
216 /* Tens digit, 10% per entry, ones digit: interpolated */
217 return i
*10 + (voltage
- table
[i
])*10 / (table
[i
+1] - table
[i
]);
221 /* update battery level and estimated runtime, called once per minute or
222 * when battery capacity / type settings are changed */
223 static int voltage_to_battery_level(int battery_millivolts
)
227 #if CONFIG_CHARGING >= CHARGING_MONITOR
228 if (charging_state()) {
229 /* battery level is defined to be < 100% until charging is finished */
230 level
= voltage_to_percent(battery_millivolts
,
231 percent_to_volt_charge
);
236 #endif /* CONFIG_CHARGING >= CHARGING_MONITOR */
238 /* DISCHARGING or error state */
239 level
= voltage_to_percent(battery_millivolts
,
240 percent_to_volt_discharge
[battery_type
]);
246 static void battery_status_update(void)
248 int level
= voltage_to_battery_level(battery_millivolts
);
250 #ifdef CURRENT_NORMAL /*don't try to estimate run or charge
251 time without normal current defined*/
252 /* calculate estimated remaining running time */
253 #if CONFIG_CHARGING >= CHARGING_MONITOR
254 if (charging_state()) {
255 /* charging: remaining charging time */
256 powermgmt_est_runningtime_min
= (100 - level
)*battery_capacity
*60
257 / 100 / (CURRENT_MAX_CHG
- runcurrent());
262 /* discharging: remaining running time */
263 if (battery_millivolts
> percent_to_volt_discharge
[0][0]) {
264 /* linear extrapolation */
265 powermgmt_est_runningtime_min
= (level
+ battery_percent
)*60
266 * battery_capacity
/ 200 / runcurrent();
268 if (0 > powermgmt_est_runningtime_min
) {
269 powermgmt_est_runningtime_min
= 0;
272 powermgmt_est_runningtime_min
=-1;
275 battery_percent
= level
;
276 send_battery_level_event();
279 #ifdef CURRENT_NORMAL /*check that we have a current defined in a config file*/
282 * Estimate how much current we are drawing just to run.
284 static int runcurrent(void)
286 int current
= CURRENT_NORMAL
;
290 #ifdef HAVE_USB_POWER
291 #if (CURRENT_USB < CURRENT_NORMAL)
298 current
= CURRENT_USB
;
301 #if defined(HAVE_BACKLIGHT)
302 if (backlight_get_current_timeout() == 0) /* LED always on */
303 current
+= CURRENT_BACKLIGHT
;
306 #if defined(HAVE_RECORDING) && defined(CURRENT_RECORD)
307 if (audio_status() & AUDIO_STATUS_RECORD
)
308 current
+= CURRENT_RECORD
;
311 #ifdef HAVE_SPDIF_POWER
313 current
+= CURRENT_SPDIF_OUT
;
316 #ifdef HAVE_REMOTE_LCD
318 current
+= CURRENT_REMOTE
;
321 #if defined(HAVE_ATA_POWER_OFF) && defined(CURRENT_ATA)
323 current
+= CURRENT_ATA
;
326 #endif /* BOOTLOADER */
331 #endif /* CURRENT_NORMAL */
333 /* Check to see whether or not we've received an alarm in the last second */
334 #ifdef HAVE_RTC_ALARM
335 static void power_thread_rtc_process(void)
337 if (rtc_check_alarm_flag())
338 rtc_enable_alarm(false);
342 /* switch off unit if battery level is too low for reliable operation */
343 bool query_force_shutdown(void)
345 #if defined(NO_LOW_BATTERY_SHUTDOWN)
347 #elif defined(HAVE_BATTERY_SWITCH)
348 /* Cannot rely upon the battery reading to be valid and the
349 * device could be powered externally. */
350 return input_millivolts() < battery_level_shutoff
[battery_type
];
352 return battery_millivolts
< battery_level_shutoff
[battery_type
];
356 #if defined(HAVE_BATTERY_SWITCH) || defined(HAVE_RESET_BATTERY_FILTER)
358 * Reset the battery voltage filter to a new value and update the
361 void reset_battery_filter(int millivolts
)
363 avgbat
= millivolts
* BATT_AVE_SAMPLES
;
364 battery_millivolts
= millivolts
;
365 battery_status_update();
367 #endif /* HAVE_BATTERY_SWITCH */
369 /** Generic charging algorithms for common charging types **/
370 #if CONFIG_CHARGING == 0 || CONFIG_CHARGING == CHARGING_SIMPLE
371 static inline void powermgmt_init_target(void)
376 static inline void charging_algorithm_step(void)
381 static inline void charging_algorithm_close(void)
385 #elif CONFIG_CHARGING == CHARGING_MONITOR
387 * Monitor CHARGING/DISCHARGING state.
389 static inline void powermgmt_init_target(void)
394 static inline void charging_algorithm_step(void)
396 switch (charger_input_state
)
398 case CHARGER_PLUGGED
:
400 if (charging_state()) {
401 charge_state
= CHARGING
;
405 case CHARGER_UNPLUGGED
:
407 charge_state
= DISCHARGING
;
412 static inline void charging_algorithm_close(void)
416 #endif /* CONFIG_CHARGING == * */
419 /* Shortcut function calls - compatibility, simplicity. */
421 /* Returns true if any power input is capable of charging. */
422 bool charger_inserted(void)
424 return power_thread_inputs
& POWER_INPUT_CHARGER
;
427 /* Returns true if any power input is connected - charging-capable
429 bool power_input_present(void)
431 return power_thread_inputs
& POWER_INPUT
;
435 * Detect charger inserted. Return true if the state is transistional.
437 static inline bool detect_charger(unsigned int pwr
)
440 * Detect charger plugged/unplugged transitions. On a plugged or
441 * unplugged event, we return immediately, run once through the main
442 * loop (including the subroutines), and end up back here where we
443 * transition to the appropriate steady state charger on/off state.
445 if (pwr
& POWER_INPUT_CHARGER
) {
446 switch (charger_input_state
)
449 case CHARGER_UNPLUGGED
:
450 charger_input_state
= CHARGER_PLUGGED
;
453 case CHARGER_PLUGGED
:
454 queue_broadcast(SYS_CHARGER_CONNECTED
, 0);
455 last_sent_battery_level
= 0;
456 charger_input_state
= CHARGER
;
464 else { /* charger not inserted */
465 switch (charger_input_state
)
471 case CHARGER_UNPLUGGED
:
472 queue_broadcast(SYS_CHARGER_DISCONNECTED
, 0);
473 last_sent_battery_level
= 100;
474 charger_input_state
= NO_CHARGER
;
477 case CHARGER_PLUGGED
:
479 charger_input_state
= CHARGER_UNPLUGGED
;
484 /* Transitional state */
487 #endif /* CONFIG_CHARGING */
490 * Monitor the presence of a charger and perform critical frequent steps
491 * such as running the battery voltage filter.
493 static inline void power_thread_step(void)
495 /* If the power off timeout expires, the main thread has failed
496 to shut down the system, and we need to force a power off */
497 if (shutdown_timeout
) {
498 shutdown_timeout
-= POWER_THREAD_STEP_TICKS
;
500 if (shutdown_timeout
<= 0)
504 #ifdef HAVE_RTC_ALARM
505 power_thread_rtc_process();
509 * Do a digital exponential filter. We don't sample the battery if
510 * the disk is spinning unless we are in USB mode (the disk will most
511 * likely always be spinning in USB mode) or charging.
513 if (!storage_disk_is_active() || usb_inserted()
514 #if CONFIG_CHARGING >= CHARGING_MONITOR
515 || charger_input_state
== CHARGER
518 avgbat
+= battery_adc_voltage() - avgbat
/ BATT_AVE_SAMPLES
;
520 * battery_millivolts is the millivolt-scaled filtered battery value.
522 battery_millivolts
= avgbat
/ BATT_AVE_SAMPLES
;
524 /* update battery status every time an update is available */
525 battery_status_update();
527 else if (battery_percent
< 8) {
529 * If battery is low, observe voltage during disk activity.
530 * Shut down if voltage drops below shutoff level and we are not
531 * using NiMH or Alkaline batteries.
533 battery_millivolts
= (battery_adc_voltage() +
534 battery_millivolts
+ 1) / 2;
536 /* update battery status every time an update is available */
537 battery_status_update();
539 if (!shutdown_timeout
&& query_force_shutdown()) {
543 avgbat
+= battery_millivolts
- avgbat
/ BATT_AVE_SAMPLES
;
546 } /* power_thread_step */
548 static void power_thread(void)
550 long next_power_hist
;
552 /* Delay reading the first battery level */
554 while (battery_adc_voltage() > 4200) /* gives false readings initially */
561 /* Initialize power input status before calling other routines. */
562 power_thread_inputs
= power_input_status();
565 /* initialize the voltages for the exponential filter */
566 avgbat
= battery_adc_voltage() + 15;
568 #ifdef HAVE_DISK_STORAGE /* this adjustment is only needed for HD based */
569 /* The battery voltage is usually a little lower directly after
570 turning on, because the disk was used heavily. Raise it by 5% */
572 if (!charger_inserted()) /* only if charger not connected */
575 avgbat
+= (percent_to_volt_discharge
[battery_type
][6] -
576 percent_to_volt_discharge
[battery_type
][5]) / 2;
578 #endif /* HAVE_DISK_STORAGE */
580 avgbat
= avgbat
* BATT_AVE_SAMPLES
;
581 battery_millivolts
= avgbat
/ BATT_AVE_SAMPLES
;
582 power_history
[0] = battery_millivolts
;
585 if (charger_inserted()) {
586 battery_percent
= voltage_to_percent(battery_millivolts
,
587 percent_to_volt_charge
);
592 battery_percent
= voltage_to_percent(battery_millivolts
,
593 percent_to_volt_discharge
[battery_type
]);
594 battery_percent
+= battery_percent
< 100;
597 powermgmt_init_target();
599 next_power_hist
= current_tick
+ HZ
*60;
604 unsigned int pwr
= power_input_status();
605 #ifdef HAVE_BATTERY_SWITCH
606 if ((pwr
^ power_thread_inputs
) & POWER_INPUT_BATTERY
) {
608 reset_battery_filter(battery_adc_voltage());
611 power_thread_inputs
= pwr
;
613 if (!detect_charger(pwr
))
614 #endif /* CONFIG_CHARGING */
617 sleep(POWER_THREAD_STEP_TICKS
);
619 /* Do common power tasks */
623 /* Perform target tasks */
624 charging_algorithm_step();
626 if (TIME_BEFORE(current_tick
, next_power_hist
))
629 /* increment to ensure there is a record for every minute
630 * rather than go forward from the current tick */
631 next_power_hist
+= HZ
*60;
633 /* rotate the power history */
634 memmove(&power_history
[1], &power_history
[0],
635 sizeof(power_history
) - sizeof(power_history
[0]));
637 /* insert new value at the start, in millivolts 8-) */
638 power_history
[0] = battery_millivolts
;
640 handle_auto_poweroff();
644 void powermgmt_init(void)
646 create_thread(power_thread
, power_stack
, sizeof(power_stack
), 0,
647 power_thread_name
IF_PRIO(, PRIORITY_SYSTEM
)
651 /* Various hardware housekeeping tasks relating to shutting down the player */
652 void shutdown_hw(void)
654 charging_algorithm_close();
657 if (battery_level_safe()) { /* do not save on critical battery */
658 #ifdef HAVE_LCD_BITMAP
659 glyph_cache_save(NULL
);
662 /* Commit pending writes if needed. Even though we don't do write caching,
663 things like flash translation layers may need this to commit scattered
664 pages to there final locations. So far only used for iPod Nano 2G. */
665 #ifdef HAVE_STORAGE_FLUSH
669 if (storage_disk_is_active())
673 #if CONFIG_CODEC == SWCODEC
679 /* If HD is still active we try to wait for spindown, otherwise the
680 shutdown_timeout in power_thread_step will force a power off */
681 while (storage_disk_is_active())
684 #ifndef HAVE_LCD_COLOR
687 #ifdef HAVE_REMOTE_LCD
688 lcd_remote_set_contrast(0);
690 #ifdef HAVE_LCD_SHUTDOWN
694 /* Small delay to make sure all HW gets time to flush. Especially
695 eeprom chips are quite slow and might be still writing the last
700 #endif /* PLATFORM_NATIVE */
702 void set_poweroff_timeout(int timeout
)
704 poweroff_timeout
= timeout
;
707 void reset_poweroff_timer(void)
709 last_event_tick
= current_tick
;
712 void sys_poweroff(void)
715 logf("sys_poweroff()");
716 /* If the main thread fails to shut down the system, we will force a
717 power off after an 20 second timeout - 28 seconds if recording */
718 if (shutdown_timeout
== 0) {
719 #if (defined(IAUDIO_X5) || defined(IAUDIO_M5) || defined(COWON_D2)) && !defined(SIMULATOR)
720 pcf50606_reset_timeout(); /* Reset timer on first attempt only */
722 #ifdef HAVE_RECORDING
723 if (audio_status() & AUDIO_STATUS_RECORD
)
724 shutdown_timeout
+= HZ
*8;
727 /* The FTL alone may take half a minute to shut down cleanly. */
728 shutdown_timeout
+= HZ
*60;
730 shutdown_timeout
+= HZ
*20;
734 queue_broadcast(SYS_POWEROFF
, 0);
735 #endif /* BOOTLOADER */
738 void cancel_shutdown(void)
740 logf("cancel_shutdown()");
742 #if (defined(IAUDIO_X5) || defined(IAUDIO_M5) || defined(COWON_D2)) && !defined(SIMULATOR)
743 /* TODO: Move some things to target/ tree */
744 if (shutdown_timeout
)
745 pcf50606_reset_timeout();
748 shutdown_timeout
= 0;
751 /* Send system battery level update events on reaching certain significant
752 levels. This must be called after battery_percent has been updated. */
753 void send_battery_level_event(void)
755 static const int levels
[] = { 5, 15, 30, 50, 0 };
756 const int *level
= levels
;
760 if (battery_percent
<= *level
&& last_sent_battery_level
> *level
) {
761 last_sent_battery_level
= *level
;
762 queue_broadcast(SYS_BATTERY_UPDATE
, last_sent_battery_level
);
770 void set_sleep_timer(int seconds
)
773 sleeptimer_active
= true;
774 sleeptimer_endtick
= current_tick
+ seconds
* HZ
;
777 sleeptimer_active
= false;
778 sleeptimer_endtick
= 0;
782 int get_sleep_timer(void)
784 if (sleeptimer_active
&& (sleeptimer_endtick
>= current_tick
))
785 return (sleeptimer_endtick
- current_tick
) / HZ
;
790 static void handle_sleep_timer(void)
793 if (!sleeptimer_active
)
796 /* Handle sleeptimer */
797 if (TIME_AFTER(current_tick
, sleeptimer_endtick
)) {
799 #if CONFIG_CHARGING && !defined(HAVE_POWEROFF_WHILE_CHARGING)
800 || charger_input_state
!= NO_CHARGER
803 DEBUGF("Sleep timer timeout. Stopping...\n");
806 backlight_off(); /* Nighty, nighty... */
809 DEBUGF("Sleep timer timeout. Shutting off...\n");
813 #endif /* BOOTLOADER */
817 * We shut off in the following cases:
818 * 1) The unit is idle, not playing music
819 * 2) The unit is playing music, but is paused
820 * 3) The battery level has reached shutdown limit
822 * We do not shut off in the following cases:
823 * 1) The USB is connected
824 * 2) The charger is connected
825 * 3) We are recording, or recording with pause
826 * 4) The radio is playing
828 void handle_auto_poweroff(void)
830 long timeout
= poweroff_timeout
*60*HZ
;
831 int audio_stat
= audio_status();
832 long tick
= current_tick
;
835 * Inhibit shutdown as long as the charger is plugged in. If it is
836 * unplugged, wait for a timeout period and then shut down.
838 if (audio_stat
== AUDIO_STATUS_PLAY
840 || charger_input_state
== CHARGER
843 last_event_tick
= current_tick
;
846 #if !(CONFIG_PLATFORM & PLATFORM_HOSTED)
847 if (!shutdown_timeout
&& query_force_shutdown()) {
855 !(get_radio_status() & FMRADIO_PLAYING
) &&
859 (audio_stat
== (AUDIO_STATUS_PLAY
| AUDIO_STATUS_PAUSE
) &&
860 !sleeptimer_active
))) {
862 if (TIME_AFTER(tick
, last_event_tick
+ timeout
)
863 #if !(CONFIG_PLATFORM & PLATFORM_HOSTED)
864 && TIME_AFTER(tick
, storage_last_disk_activity() + timeout
)
870 handle_sleep_timer();