1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
35 #include "powermgmt.h"
36 #include "backlight.h"
43 void reset_poweroff_timer(void)
45 last_event_tick
= current_tick
;
50 int battery_level(void)
55 int battery_time(void)
60 bool battery_level_safe(void)
62 return battery_level() >= 10;
65 void set_poweroff_timeout(int timeout
)
70 void set_battery_capacity(int capacity
)
75 void set_car_adapter_mode(bool setting
)
80 #else /* not SIMULATOR */
82 int battery_capacity
= BATTERY_CAPACITY_MIN
; /* only a default value */
83 int battery_level_cached
= -1; /* battery level of this minute, updated once
85 static bool car_adapter_mode_enabled
= false;
87 static const int poweroff_idle_timeout_value
[15] =
89 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 30, 45, 60
92 static const int percent_to_volt_decharge
[11] =
93 /* voltages (centivolt) of 0%, 10%, ... 100% when charging disabled */
95 #if CONFIG_BATTERY == BATT_LIION2200
97 260, 285, 295, 303, 311, 320, 330, 345, 360, 380, 400
98 #elif CONFIG_BATTERY == BATT_3AAA_ALKALINE
99 /* taken from a textbook alkaline discharge graph, not measured */
100 270, 303, 324, 336, 348, 357, 366, 378, 390, 408, 450
102 /* original values were taken directly after charging, but it should show
103 100% after turning off the device for some hours, too */
104 450, 481, 491, 497, 503, 507, 512, 514, 517, 525, 540 /* orig. values:
109 void set_battery_capacity(int capacity
)
111 battery_capacity
= capacity
;
112 if (battery_capacity
> BATTERY_CAPACITY_MAX
)
113 battery_capacity
= BATTERY_CAPACITY_MAX
;
114 if (battery_capacity
< BATTERY_CAPACITY_MIN
)
115 battery_capacity
= BATTERY_CAPACITY_MIN
;
118 #if defined(HAVE_CHARGE_CTRL) || CONFIG_BATTERY == BATT_LIION2200
119 int charge_state
= 0; /* at the beginning, the
120 charger does nothing */
123 #ifdef HAVE_CHARGE_CTRL
125 char power_message
[POWER_MESSAGE_LEN
] = ""; /* message that's shown in
127 char charge_restart_level
= CHARGE_RESTART_HI
; /* level at which charging
129 int powermgmt_last_cycle_startstop_min
= 25; /* how many minutes ago was the
132 int powermgmt_last_cycle_level
= 0; /* which level had the
133 batteries at this time? */
134 bool trickle_charge_enabled
= true;
135 int trickle_sec
= 0; /* how many seconds should the
136 charger be enabled per
139 static const int percent_to_volt_charge
[11] =
140 /* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */
142 /* values guessed, see
143 http://www.seattlerobotics.org/encoder/200210/LiIon2.pdf until someone
144 measures voltages over a charging cycle */
145 476, 544, 551, 556, 561, 564, 566, 576, 582, 584, 585 /* NiMH */
148 void enable_trickle_charge(bool on
)
150 trickle_charge_enabled
= on
;
152 #endif /* HAVE_CHARGE_CTRL */
154 static char power_stack
[DEFAULT_STACK_SIZE
];
155 static const char power_thread_name
[] = "power";
157 static int poweroff_timeout
= 0;
158 static long last_charge_time
= 0;
159 int powermgmt_est_runningtime_min
= -1;
161 static bool sleeptimer_active
= false;
162 static unsigned long sleeptimer_endtick
;
164 unsigned short power_history
[POWER_HISTORY_LEN
];
166 int battery_time(void)
168 return powermgmt_est_runningtime_min
;
171 /* look into the percent_to_volt_* table and get a realistic battery level
173 int voltage_to_percent(int voltage
, const int* table
)
175 if (voltage
<= table
[0])
178 if (voltage
>= table
[10])
181 /* search nearest value */
183 while ((i
< 10) && (table
[i
+1] < voltage
))
185 /* interpolate linear between the smaller and greater value */
186 return i
* 10 /* 10th */
187 + (voltage
- table
[i
]) *
188 10 / (table
[i
+1] - table
[i
]); /* 1th */
192 /* update battery level, called only once per minute */
193 void battery_level_update(void)
199 /* calculate maximum over last 3 minutes (skip empty samples) */
200 for (i
= 0; i
< 3; i
++)
201 if (power_history
[POWER_HISTORY_LEN
-1-i
] > c
)
202 c
= power_history
[POWER_HISTORY_LEN
-1-i
];
206 else /* history was empty, get a fresh sample */
207 level
= (adc_read(ADC_UNREG_POWER
) * BATTERY_SCALE_FACTOR
) / 10000;
209 if(level
> BATTERY_LEVEL_FULL
)
210 level
= BATTERY_LEVEL_FULL
;
212 if(level
< BATTERY_LEVEL_EMPTY
)
213 level
= BATTERY_LEVEL_EMPTY
;
215 #ifdef HAVE_CHARGE_CTRL
216 if (charge_state
== 0) { /* decharge */
217 level
= voltage_to_percent(level
, percent_to_volt_decharge
);
219 else if (charge_state
== 1) { /* charge */
220 level
= voltage_to_percent(level
, percent_to_volt_charge
);
222 else {/* in trickle charge, the battery is per definition 100% full */
223 battery_level_cached
= level
= 100;
226 level
= voltage_to_percent(level
, percent_to_volt_decharge
);
227 /* always use the decharge table */
230 #ifndef HAVE_MMC /* this adjustment is only needed for HD based */
231 if (battery_level_cached
== -1) { /* first run of this procedure */
232 /* the battery voltage is usually a little lower directly after
233 turning on, because the disk was used heavily raise it by 5 % */
234 battery_level_cached
= (level
> 95) ? 100 : level
+ 5;
239 /* the level is allowed to be -1 of the last value when usb not
240 connected and to be -3 of the last value when usb is connected */
241 if (usb_inserted()) {
242 if (level
< battery_level_cached
- 3)
243 level
= battery_level_cached
- 3;
246 if (level
< battery_level_cached
- 1)
247 level
= battery_level_cached
- 1;
249 battery_level_cached
= level
;
253 /* Returns battery level in percent */
254 int battery_level(void)
256 #ifdef HAVE_CHARGE_CTRL
257 if ((charge_state
==1) && (battery_level_cached
==100))
260 return battery_level_cached
;
263 /* Tells if the battery level is safe for disk writes */
264 bool battery_level_safe(void)
266 /* I'm pretty sure we don't want an average over a long time here */
267 if (power_history
[POWER_HISTORY_LEN
-1])
268 return power_history
[POWER_HISTORY_LEN
-1] > BATTERY_LEVEL_DANGEROUS
;
270 return adc_read(ADC_UNREG_POWER
) > (BATTERY_LEVEL_DANGEROUS
* 10000) /
271 BATTERY_SCALE_FACTOR
;
274 void set_poweroff_timeout(int timeout
)
276 poweroff_timeout
= timeout
;
279 void set_sleep_timer(int seconds
)
282 sleeptimer_active
= true;
283 sleeptimer_endtick
= current_tick
+ seconds
* HZ
;
286 sleeptimer_active
= false;
287 sleeptimer_endtick
= 0;
291 int get_sleep_timer(void)
293 if(sleeptimer_active
)
294 return (sleeptimer_endtick
- current_tick
) / HZ
;
299 /* We shut off in the following cases:
300 1) The unit is idle, not playing music
301 2) The unit is playing music, but is paused
303 We do not shut off in the following cases:
304 1) The USB is connected
305 2) The charger is connected
306 3) We are recording, or recording with pause
308 static void handle_auto_poweroff(void)
310 long timeout
= poweroff_idle_timeout_value
[poweroff_timeout
]*60*HZ
;
311 int mpeg_stat
= mpeg_status();
312 bool charger_is_inserted
= charger_inserted();
313 static bool charger_was_inserted
= false;
315 /* The was_inserted thing prevents the unit to shut down immediately
316 when the charger is extracted */
317 if(charger_is_inserted
|| charger_was_inserted
)
319 last_charge_time
= current_tick
;
321 charger_was_inserted
= charger_is_inserted
;
325 (radio_get_status() != FMRADIO_PLAYING
) &&
329 ((mpeg_stat
== (MPEG_STATUS_PLAY
| MPEG_STATUS_PAUSE
)) &&
330 !sleeptimer_active
)))
332 if(TIME_AFTER(current_tick
, last_event_tick
+ timeout
) &&
333 TIME_AFTER(current_tick
, last_disk_activity
+ timeout
) &&
334 TIME_AFTER(current_tick
, last_charge_time
+ timeout
))
341 /* Handle sleeptimer */
342 if(sleeptimer_active
&& !usb_inserted())
344 if(TIME_AFTER(current_tick
, sleeptimer_endtick
))
347 if(charger_is_inserted
)
349 DEBUGF("Sleep timer timeout. Stopping...\n");
351 backlight_off(); /* Nighty, nighty... */
355 DEBUGF("Sleep timer timeout. Shutting off...\n");
356 /* Make sure that the disk isn't spinning when
358 while(ata_disk_is_active())
367 void set_car_adapter_mode(bool setting
)
369 car_adapter_mode_enabled
= setting
;
372 static bool charger_power_is_on
;
375 static void car_adapter_mode_processing(void)
377 static bool waiting_to_resume_play
= false;
378 static long play_resume_time
;
380 if (car_adapter_mode_enabled
) {
382 if (waiting_to_resume_play
) {
383 if (TIME_AFTER(current_tick
, play_resume_time
)) {
384 if (mpeg_status() & MPEG_STATUS_PAUSE
) {
387 waiting_to_resume_play
= false;
391 if (charger_power_is_on
) {
393 /* if external power was turned off */
394 if (!charger_inserted()) {
396 charger_power_is_on
= false;
399 if ((mpeg_status() & MPEG_STATUS_PLAY
) &&
400 !(mpeg_status() & MPEG_STATUS_PAUSE
)) {
406 /* if external power was turned on */
407 if (charger_inserted()) {
409 charger_power_is_on
= true;
412 if (mpeg_status() & MPEG_STATUS_PAUSE
) {
413 /* delay resume a bit while the engine is cranking */
414 play_resume_time
= current_tick
+ HZ
*5;
415 waiting_to_resume_play
= true;
425 * This function is called to do the relativly long sleep waits from within the
426 * main power_thread loop while at the same time servicing any other periodic
427 * functions in the power thread which need to be called at a faster periodic
428 * rate than the slow periodic rate of the main power_thread loop
430 static void power_thread_sleep(int ticks
)
434 int small_ticks
= MIN(HZ
/2, ticks
);
436 ticks
-= small_ticks
;
438 car_adapter_mode_processing();
441 sleep(ticks
); /* no fast-processing functions, sleep the whole time */
447 * This power thread maintains a history of battery voltage
448 * and implements a charging algorithm.
449 * For a complete description of the charging algorithm read
450 * docs/CHARGING_ALGORITHM.
453 static void power_thread(void)
456 int avg
, ok_samples
, spin_samples
;
458 #if CONFIG_BATTERY == BATT_LIION2200
459 int charging_current
;
461 #ifdef HAVE_CHARGE_CTRL
463 int charged_time
= 0;
464 int charge_max_time_now
= 0; /* max. charging duration, calculated at
465 beginning of charging */
466 int charge_pause
= 0; /* no charging pause at the beginning */
467 int trickle_time
= 0; /* how many minutes trickle charging already? */
472 /* never read power while disk is spinning, unless in USB mode */
473 if (ata_disk_is_active() && !usb_inserted()) {
478 /* Make POWER_AVG measurements and calculate an average of that to
479 * reduce the effect of backlights/disk spinning/other variation.
481 ok_samples
= spin_samples
= avg
= 0;
482 for (i
= 0; i
< POWER_AVG_N
; i
++) {
483 if (ata_disk_is_active()) {
485 /* if we don't have any good non-disk-spinning samples,
486 * we take a sample anyway in case the disk is going
487 * to spin all the time.
489 avg
+= adc_read(ADC_UNREG_POWER
);
493 if (spin_samples
) /* throw away disk-spinning samples */
494 spin_samples
= avg
= 0;
495 avg
+= adc_read(ADC_UNREG_POWER
);
498 power_thread_sleep(HZ
*POWER_AVG_SLEEP
);
500 avg
= avg
/ ((ok_samples
) ? ok_samples
: spin_samples
);
502 /* rotate the power history */
503 for (i
= 0; i
< POWER_HISTORY_LEN
-1; i
++)
504 power_history
[i
] = power_history
[i
+1];
506 /* insert new value in the end, in centivolts 8-) */
507 power_history
[POWER_HISTORY_LEN
-1] =
508 (avg
* BATTERY_SCALE_FACTOR
) / 10000;
510 /* update battery level every minute, ignoring first 15 minutes after
511 start charge/decharge */
512 #ifdef HAVE_CHARGE_CTRL
513 if ((powermgmt_last_cycle_startstop_min
> 25) || (charge_state
> 1))
515 battery_level_update();
517 /* calculate estimated remaining running time */
518 /* decharging: remaining running time */
519 /* charging: remaining charging time */
521 #ifdef HAVE_CHARGE_CTRL
522 if (charge_state
== 1)
523 powermgmt_est_runningtime_min
= (100 - battery_level()) *
524 battery_capacity
/ 100 * 60 / CURRENT_CHARGING
;
526 current
= usb_inserted() ? CURRENT_USB
: CURRENT_NORMAL
;
527 if ((backlight_get_timeout() == 1) ||
528 (charger_inserted() && backlight_get_on_when_charging()))
529 /* LED always on or LED on when charger connected */
530 current
+= CURRENT_BACKLIGHT
;
531 powermgmt_est_runningtime_min
= battery_level() *
532 battery_capacity
/ 100 * 60 / current
;
533 #if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */
534 powermgmt_est_runningtime_min
=
535 powermgmt_est_runningtime_min
* 122 / 100;
536 #endif /* MEM == 8 */
539 current
= usb_inserted() ? CURRENT_USB
: CURRENT_NORMAL
;
540 if (backlight_get_timeout() == 1) /* LED always on */
541 current
+= CURRENT_BACKLIGHT
;
542 powermgmt_est_runningtime_min
= battery_level() *
543 battery_capacity
/ 100 * 60 / current
;
544 #if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */
545 powermgmt_est_runningtime_min
=
546 powermgmt_est_runningtime_min
* 122 / 100;
547 #endif /* MEM == 8 */
548 #endif /* HAVE_CHARGE_CONTROL */
550 #if CONFIG_BATTERY == BATT_LIION2200
551 /* We use the information from the ADC_EXT_POWER ADC channel, which
552 tells us the charging current from the LTC1734. When DC is
553 connected (either via the external adapter, or via USB), we try
554 to determine if it is actively charging or only maintaining the
555 charge. My tests show that ADC readings is below about 0x80 means
556 that the LTC1734 is only maintaining the charge. */
557 if(charger_inserted()) {
558 charging_current
= adc_read(ADC_EXT_POWER
);
559 if(charging_current
< 0x80) {
560 charge_state
= 2; /* Trickle */
562 charge_state
= 1; /* Charging */
565 charge_state
= 0; /* Not charging */
568 #ifdef HAVE_CHARGE_CTRL
570 if (charge_pause
> 0)
573 if (charger_inserted()) {
574 if (charge_state
== 1) {
575 /* charger inserted and enabled */
577 snprintf(power_message
, POWER_MESSAGE_LEN
,
578 "Chg %dm max %dm", charged_time
, charge_max_time_now
);
580 if (charged_time
> charge_max_time_now
) {
581 DEBUGF("power: charged_time > charge_max_time_now, "
583 /* have charged too long and deltaV detection did not
585 powermgmt_last_cycle_level
= battery_level();
586 powermgmt_last_cycle_startstop_min
= 0;
587 charger_enable(false);
588 snprintf(power_message
, POWER_MESSAGE_LEN
,
589 "Chg tmout %d min", charge_max_time_now
);
590 /* disable charging for several hours from this point,
592 charge_pause
= CHARGE_PAUSE_LEN
;
593 /* no trickle charge here, because the charging cycle
594 didn't end the right way */
595 charge_state
= 0; /* 0: decharging/charger off, 1: charge,
596 2: top-off, 3: trickle */
598 if (charged_time
> CHARGE_MIN_TIME
) {
599 /* have charged continuously over the minimum charging
600 time, so we monitor for deltaV going
601 negative. Multiply thingsby 100 to get more
602 accuracy without floating point arithmetic.
603 power_history[] contains centivolts so after
604 multiplying by 100 the deltas are in tenths of
605 millivolts (delta of 5 is 0.0005 V).
608 ( power_history
[POWER_HISTORY_LEN
-1] * 100
609 + power_history
[POWER_HISTORY_LEN
-2] * 100
610 - power_history
[POWER_HISTORY_LEN
-1-
611 CHARGE_END_NEGD
+1] * 100
612 - power_history
[POWER_HISTORY_LEN
-1-
613 CHARGE_END_NEGD
] * 100 )
614 / CHARGE_END_NEGD
/ 2;
616 if (delta
< -100) { /* delta < -10 mV */
617 DEBUGF("power: short-term negative"
618 " delta, enough!\n");
619 powermgmt_last_cycle_level
= battery_level();
620 powermgmt_last_cycle_startstop_min
= 0;
621 charger_enable(false);
622 snprintf(power_message
, POWER_MESSAGE_LEN
,
623 "end negd %d %dmin", delta
, charged_time
);
624 /* disable charging for several hours from this
625 point, just to be sure */
626 charge_pause
= CHARGE_PAUSE_LEN
;
627 /* enable trickle charging */
628 if (trickle_charge_enabled
) {
629 trickle_sec
= CURRENT_NORMAL
* 60 /
631 /* first guess, maybe consider if LED
632 backlight is on, disk is active,... */
634 charge_state
= 2; /* 0: decharging/charger
636 2: top-off, 3: trickle */
638 charge_state
= 0; /* 0: decharging/charger
640 2: top-off, 3: trickle */
643 /* if we didn't disable the charger in the
644 previous test, check for low positive delta */
646 ( power_history
[POWER_HISTORY_LEN
-1] * 100
647 + power_history
[POWER_HISTORY_LEN
-2] * 100
648 - power_history
[POWER_HISTORY_LEN
-1-
649 CHARGE_END_ZEROD
+1] * 100
650 - power_history
[POWER_HISTORY_LEN
-1-
651 CHARGE_END_ZEROD
] * 100 )
652 / CHARGE_END_ZEROD
/ 2;
654 if (delta
< 1) { /* delta < 0.1 mV */
655 DEBUGF("power: long-term small "
656 "positive delta, enough!\n");
657 powermgmt_last_cycle_level
= battery_level();
658 powermgmt_last_cycle_startstop_min
= 0;
659 charger_enable(false);
660 snprintf(power_message
, POWER_MESSAGE_LEN
,
662 delta
, charged_time
);
663 /* disable charging for several hours from
664 this point, just to be sure */
665 charge_pause
= CHARGE_PAUSE_LEN
;
666 /* enable trickle charging */
667 if (trickle_charge_enabled
) {
669 CURRENT_NORMAL
* 60 / CURRENT_CHARGING
;
670 /* first guess, maybe consider if LED
671 backlight is on, disk is active,... */
674 /* 0: decharging/charger off, 1: charge,
675 2: top-off, 3: trickle */
678 /* 0: decharging/charger off, 1: charge,
679 2: top-off, 3: trickle */
686 else if (charge_state
> 1) { /* top off or trickle? */
687 /* adjust trickle charge time */
688 if ( ((charge_state
== 2) &&
689 (power_history
[POWER_HISTORY_LEN
-1] > TOPOFF_VOLTAGE
))
690 || ((charge_state
== 3) &&
691 (power_history
[POWER_HISTORY_LEN
-1] >
692 TRICKLE_VOLTAGE
)) ) { /* charging too much */
695 else { /* charging too less */
699 if (trickle_sec
> 24)
705 /* charge the calculated amount of seconds */
706 charger_enable(true);
707 power_thread_sleep(HZ
* trickle_sec
);
708 charger_enable(false);
710 /* trickle charging long enough? */
712 if (trickle_time
++ > TRICKLE_MAX_TIME
+ TOPOFF_MAX_TIME
) {
713 trickle_sec
= 0; /* show in debug menu that trickle is
715 charge_state
= 0; /* 0: decharging/charger off, 1: charge,
716 2: top-off, 3: trickle */
717 powermgmt_last_cycle_startstop_min
= 0;
720 if ((charge_state
== 2) &&
721 (trickle_time
> TOPOFF_MAX_TIME
)) /* change state? */
722 charge_state
= 3; /* 0: decharging/charger off, 1: charge,
723 2: top-off, 3: trickle */
725 } else { /* charge_state == 0 */
727 /* the charger is enabled here only in one case: if it was
728 turned on at boot time (power_init) */
729 /* turn it off now */
731 charger_enable(false);
734 /* Start new charge cycle? This must be possible also in
735 trickle/top-off, because when usb connected, */
736 /* the trickle charge amount may not be enough */
738 if ((charge_state
== 0) || (charge_state
> 1))
739 /* if battery is not full, enable charging */
740 /* make sure charging starts if 1%-lazyness in
741 battery_level_update() is too slow */
742 if ( (battery_level() < charge_restart_level
)
743 || (power_history
[POWER_HISTORY_LEN
-1] <
744 BATTERY_LEVEL_DANGEROUS
)) {
746 DEBUGF("power: batt level < restart level,"
747 " but charge pause, not enabling\n");
748 snprintf(power_message
, POWER_MESSAGE_LEN
,
749 "chg pause %d min", charge_pause
);
751 /* calculate max charge time depending on current
753 /* take 35% more because some more energy is used for
754 heating up the battery */
755 i
= CHARGE_MAX_TIME_1500
* battery_capacity
/ 1500;
756 charge_max_time_now
=
757 i
* (100 + 35 - battery_level()) / 100;
758 if (charge_max_time_now
> i
) {
759 charge_max_time_now
= i
;
761 snprintf(power_message
, POWER_MESSAGE_LEN
,
762 "ChgAt %d%% max %dm", battery_level(),
763 charge_max_time_now
);
765 /* enable the charger after the max time calc is done,
766 because battery_level depends on if the charger is
768 DEBUGF("power: charger inserted and battery"
769 " not full, enabling\n");
770 powermgmt_last_cycle_level
= battery_level();
771 powermgmt_last_cycle_startstop_min
= 0;
774 charger_enable(true);
775 charge_state
= 1; /* 0: decharging/charger off, 1:
776 charge, 2: top-off, 3: trickle */
777 /* clear the power history so that we don't use values
778 before discharge for the long-term delta
780 for (i
= 0; i
< POWER_HISTORY_LEN
-1; i
++)
782 power_history
[POWER_HISTORY_LEN
-1];
787 /* charger not inserted */
788 if (charge_state
> 0) {
789 /* charger not inserted but was enabled */
790 DEBUGF("power: charger disconnected, disabling\n");
791 powermgmt_last_cycle_level
= battery_level();
792 powermgmt_last_cycle_startstop_min
= 0;
793 /* show in debug menu that trickle is off */
795 charger_enable(false);
796 charge_state
= 0; /* 0: decharging/charger off, 1: charge, 2:
797 top-off, 3: trickle */
798 snprintf(power_message
, POWER_MESSAGE_LEN
, "Charger disc");
800 /* charger not inserted and disabled, so we're discharging */
802 powermgmt_last_cycle_startstop_min
++;
804 #endif /* HAVE_CHARGE_CTRL*/
805 #endif /* # if CONFIG_BATTERY == BATT_LIION2200 */
807 /* sleep for roughly a minute */
808 #ifdef HAVE_CHARGE_CTRL
809 i
= 60 - trickle_sec
- POWER_AVG_N
* POWER_AVG_SLEEP
;
811 i
= 60 - POWER_AVG_N
* POWER_AVG_SLEEP
;
814 power_thread_sleep(HZ
*(i
));
816 handle_auto_poweroff();
820 void powermgmt_init(void)
824 /* init history to 0 */
825 memset(power_history
, 0x00, sizeof(power_history
));
828 /* initialize the history with a single sample to prevent level
829 flickering during the first minute of execution */
830 power_history
[POWER_HISTORY_LEN
-1] =
831 (adc_read(ADC_UNREG_POWER
) * BATTERY_SCALE_FACTOR
) / 10000;
832 /* calculate the first battery level */
833 battery_level_update();
834 /* calculate the remaining time to that the info screen displays something
836 powermgmt_est_runningtime_min
=
837 battery_level() * battery_capacity
/ 100 * 60 / CURRENT_NORMAL
;
838 #if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */
839 powermgmt_est_runningtime_min
= powermgmt_est_runningtime_min
* 122 / 100;
842 #ifdef HAVE_CHARGE_CTRL
843 snprintf(power_message
, POWER_MESSAGE_LEN
, "Powermgmt started");
845 /* if the battery is nearly empty, start charging immediately */
846 if (power_history
[POWER_HISTORY_LEN
-1] < BATTERY_LEVEL_DANGEROUS
)
847 charger_enable(true);
851 charger_power_is_on
= charger_inserted();
853 create_thread(power_thread
, power_stack
, sizeof(power_stack
),
857 #endif /* SIMULATOR */