summaryrefslogtreecommitdiff
path: root/firmware/powermgmt.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-12-21 18:10:36 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-12-21 18:10:36 +0000
commit5667682dd204a07c52f057506fd2eef05bf63f2e (patch)
treea5f4f3cb22751362a9ed7774698ca55d27819d16 /firmware/powermgmt.c
parentc3c15cce88481a2504eb492ba06b6a691d8e998d (diff)
downloadrockbox-5667682dd204a07c52f057506fd2eef05bf63f2e.tar.gz
rockbox-5667682dd204a07c52f057506fd2eef05bf63f2e.zip
Gigabeat S: Implement charging and power control to charge from AC or USB. Hold MENU while plugging USB cable to charge from USB without connecting. Under Windows, plugging USB for charging only but not connecting still needs to be properly handled (driver popup issue) but it will charge when connected normally-- no issue under Linux. Some accomodating changes made to powermgmt.c will soon be made nicer.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19547 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/powermgmt.c')
-rw-r--r--firmware/powermgmt.c130
1 files changed, 91 insertions, 39 deletions
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index a1f7ed9836..00b7b2fd4f 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -76,7 +76,7 @@ static int wrcount = 0;
76 76
77static int shutdown_timeout = 0; 77static int shutdown_timeout = 0;
78#if CONFIG_CHARGING >= CHARGING_MONITOR 78#if CONFIG_CHARGING >= CHARGING_MONITOR
79charge_state_type charge_state; /* charging mode */ 79charge_state_type charge_state = DISCHARGING; /* charging mode */
80#endif 80#endif
81 81
82static void send_battery_level_event(void); 82static void send_battery_level_event(void);
@@ -204,8 +204,6 @@ void accessory_supply_set(bool enable)
204 204
205#else /* not SIMULATOR ******************************************************/ 205#else /* not SIMULATOR ******************************************************/
206 206
207static void power_thread_sleep(int ticks);
208
209/* 207/*
210 * Average battery voltage and charger voltage, filtered via a digital 208 * Average battery voltage and charger voltage, filtered via a digital
211 * exponential filter (aka. exponential moving average, scaled): 209 * exponential filter (aka. exponential moving average, scaled):
@@ -241,6 +239,19 @@ static int voltage_to_battery_level(int battery_millivolts);
241static void battery_status_update(void); 239static void battery_status_update(void);
242static int runcurrent(void); 240static int runcurrent(void);
243 241
242#ifndef TARGET_POWERMGMT_FILTER_CHARGE_STATE
243static inline int powermgmt_filter_charge_state(void)
244{
245#if CONFIG_CHARGING >= CHARGING_MONITOR
246 /* No adjustment of state */
247 return charge_state;
248#else
249 /* Always discharging */
250 return DISCHARGING;
251#endif
252}
253#endif /* TARGET_POWERMGMT_FILTER_CHARGE_STATE */
254
244void battery_read_info(int *voltage, int *level) 255void battery_read_info(int *voltage, int *level)
245{ 256{
246 int millivolts = battery_adc_voltage(); 257 int millivolts = battery_adc_voltage();
@@ -285,6 +296,10 @@ int battery_time(void)
285/* Returns battery level in percent */ 296/* Returns battery level in percent */
286int battery_level(void) 297int battery_level(void)
287{ 298{
299#ifdef HAVE_BATTERY_SWITCH
300 if ((power_input_status() & POWER_INPUT_BATTERY) == 0)
301 return -1;
302#endif
288 return battery_percent; 303 return battery_percent;
289} 304}
290 305
@@ -294,11 +309,13 @@ unsigned int battery_voltage(void)
294 return battery_millivolts; 309 return battery_millivolts;
295} 310}
296 311
312#ifndef TARGET_BATTERY_LEVEL_SAFE
297/* Tells if the battery level is safe for disk writes */ 313/* Tells if the battery level is safe for disk writes */
298bool battery_level_safe(void) 314bool battery_level_safe(void)
299{ 315{
300 return battery_millivolts > battery_level_dangerous[battery_type]; 316 return battery_millivolts > battery_level_dangerous[battery_type];
301} 317}
318#endif
302 319
303void set_poweroff_timeout(int timeout) 320void set_poweroff_timeout(int timeout)
304{ 321{
@@ -349,26 +366,24 @@ static int voltage_to_percent(int voltage, const short* table)
349 * when battery capacity / type settings are changed */ 366 * when battery capacity / type settings are changed */
350static int voltage_to_battery_level(int battery_millivolts) 367static int voltage_to_battery_level(int battery_millivolts)
351{ 368{
369 const int state = powermgmt_filter_charge_state();
352 int level; 370 int level;
353 371
354#if CONFIG_CHARGING >= CHARGING_MONITOR 372 if (state == DISCHARGING) {
355 if (charge_state == DISCHARGING) {
356 level = voltage_to_percent(battery_millivolts, 373 level = voltage_to_percent(battery_millivolts,
357 percent_to_volt_discharge[battery_type]); 374 percent_to_volt_discharge[battery_type]);
358 } 375 }
359 else if (charge_state == CHARGING) { 376#if CONFIG_CHARGING >= CHARGING_MONITOR
377 else if (state == CHARGING) {
360 /* battery level is defined to be < 100% until charging is finished */ 378 /* battery level is defined to be < 100% until charging is finished */
361 level = MIN(voltage_to_percent(battery_millivolts, 379 level = MIN(voltage_to_percent(battery_millivolts,
362 percent_to_volt_charge), 99); 380 percent_to_volt_charge), 99);
363 } 381 }
364 else { /* in topoff/trickle charge, battery is by definition 100% full */ 382 else {
383 /* in topoff/trickle charge, battery is by definition 100% full */
365 level = 100; 384 level = 100;
366 } 385 }
367#else 386#endif
368 /* always use the discharge table */
369 level = voltage_to_percent(battery_millivolts,
370 percent_to_volt_discharge[battery_type]);
371#endif /* CONFIG_CHARGING ... */
372 387
373 return level; 388 return level;
374} 389}
@@ -381,7 +396,7 @@ static void battery_status_update(void)
381 /* discharging: remaining running time */ 396 /* discharging: remaining running time */
382 /* charging: remaining charging time */ 397 /* charging: remaining charging time */
383#if CONFIG_CHARGING >= CHARGING_MONITOR 398#if CONFIG_CHARGING >= CHARGING_MONITOR
384 if (charge_state == CHARGING) { 399 if (powermgmt_filter_charge_state() == CHARGING) {
385 powermgmt_est_runningtime_min = (100 - level) * battery_capacity * 60 400 powermgmt_est_runningtime_min = (100 - level) * battery_capacity * 60
386 / 100 / (CURRENT_MAX_CHG - runcurrent()); 401 / 100 / (CURRENT_MAX_CHG - runcurrent());
387 } 402 }
@@ -431,15 +446,10 @@ static void handle_auto_poweroff(void)
431 } 446 }
432#endif 447#endif
433 448
434#ifndef NO_LOW_BATTERY_SHUTDOWN 449 if( !shutdown_timeout && query_force_shutdown()) {
435 /* switch off unit if battery level is too low for reliable operation */ 450 backlight_on();
436 if(battery_millivolts < battery_level_shutoff[battery_type]) { 451 sys_poweroff();
437 if(!shutdown_timeout) {
438 backlight_on();
439 sys_poweroff();
440 }
441 } 452 }
442#endif
443 453
444 if(timeout && 454 if(timeout &&
445#if CONFIG_TUNER && !defined(BOOTLOADER) 455#if CONFIG_TUNER && !defined(BOOTLOADER)
@@ -546,6 +556,18 @@ static void power_thread_rtc_process(void)
546} 556}
547#endif 557#endif
548 558
559#ifndef TARGET_QUERY_FORCE_SHUTDOWN
560bool query_force_shutdown(void)
561{
562#ifndef NO_LOW_BATTERY_SHUTDOWN
563 /* switch off unit if battery level is too low for reliable operation */
564 return battery_millivolts < battery_level_shutoff[battery_type];
565#else
566 return false;
567#endif
568}
569#endif /* TARGET_QUERY_FORCE_SHUTDOWN */
570
549/* 571/*
550 * This power thread maintains a history of battery voltage 572 * This power thread maintains a history of battery voltage
551 * and implements a charging algorithm. 573 * and implements a charging algorithm.
@@ -896,6 +918,18 @@ static inline void charging_algorithm_close(void)
896 } 918 }
897#endif 919#endif
898} 920}
921#elif CONFIG_CHARGING == CHARGING_TARGET
922extern void charging_algorithm_big_step(void);
923extern void charging_algorithm_small_step(void);
924extern void charging_algorithm_close(void);
925
926void set_filtered_battery_voltage(int millivolts)
927{
928 avgbat = millivolts * BATT_AVE_SAMPLES;
929 battery_millivolts = millivolts;
930 battery_status_update();
931}
932
899#else 933#else
900#define BATT_AVE_SAMPLES 128 /* slw filter constant for all others */ 934#define BATT_AVE_SAMPLES 128 /* slw filter constant for all others */
901 935
@@ -961,12 +995,12 @@ bool power_input_present(void)
961 * While we are waiting for the time to expire, we average the battery 995 * While we are waiting for the time to expire, we average the battery
962 * voltages. 996 * voltages.
963 */ 997 */
964static void power_thread_sleep(int ticks) 998void power_thread_sleep(int ticks)
965{ 999{
966 int small_ticks; 1000 long tick_return = current_tick + ticks;
967
968 while (ticks > 0) {
969 1001
1002 do
1003 {
970#if CONFIG_CHARGING 1004#if CONFIG_CHARGING
971 /* 1005 /*
972 * Detect charger plugged/unplugged transitions. On a plugged or 1006 * Detect charger plugged/unplugged transitions. On a plugged or
@@ -979,7 +1013,8 @@ static void power_thread_sleep(int ticks)
979 case NO_CHARGER: 1013 case NO_CHARGER:
980 case CHARGER_UNPLUGGED: 1014 case CHARGER_UNPLUGGED:
981 charger_input_state = CHARGER_PLUGGED; 1015 charger_input_state = CHARGER_PLUGGED;
982 return; 1016 tick_return = current_tick;
1017 goto do_small_step; /* Algorithm should see transition */
983 case CHARGER_PLUGGED: 1018 case CHARGER_PLUGGED:
984 queue_broadcast(SYS_CHARGER_CONNECTED, 0); 1019 queue_broadcast(SYS_CHARGER_CONNECTED, 0);
985 last_sent_battery_level = 0; 1020 last_sent_battery_level = 0;
@@ -1000,19 +1035,23 @@ static void power_thread_sleep(int ticks)
1000 case CHARGER_PLUGGED: 1035 case CHARGER_PLUGGED:
1001 case CHARGER: 1036 case CHARGER:
1002 charger_input_state = CHARGER_UNPLUGGED; 1037 charger_input_state = CHARGER_UNPLUGGED;
1003 return; 1038 tick_return = current_tick;
1039 goto do_small_step; /* Algorithm should see transition */
1004 } 1040 }
1005 } 1041 }
1006#endif /* CONFIG_CHARGING */ 1042#endif /* CONFIG_CHARGING */
1007 1043
1008 small_ticks = MIN(HZ/2, ticks); 1044 ticks = tick_return - current_tick;
1009 sleep(small_ticks); 1045
1010 ticks -= small_ticks; 1046 if (ticks > 0) {
1047 ticks = MIN(HZ/2, ticks);
1048 sleep(ticks);
1049 }
1011 1050
1012 /* If the power off timeout expires, the main thread has failed 1051 /* If the power off timeout expires, the main thread has failed
1013 to shut down the system, and we need to force a power off */ 1052 to shut down the system, and we need to force a power off */
1014 if(shutdown_timeout) { 1053 if(shutdown_timeout) {
1015 shutdown_timeout -= small_ticks; 1054 shutdown_timeout -= MAX(ticks, 1);
1016 if(shutdown_timeout <= 0) 1055 if(shutdown_timeout <= 0)
1017 power_off(); 1056 power_off();
1018 } 1057 }
@@ -1024,9 +1063,13 @@ static void power_thread_sleep(int ticks)
1024 /* 1063 /*
1025 * Do a digital exponential filter. We don't sample the battery if 1064 * Do a digital exponential filter. We don't sample the battery if
1026 * the disk is spinning unless we are in USB mode (the disk will most 1065 * the disk is spinning unless we are in USB mode (the disk will most
1027 * likely always be spinning in USB mode). 1066 * likely always be spinning in USB mode) or charging.
1028 */ 1067 */
1029 if (!storage_disk_is_active() || usb_inserted()) { 1068 if (!storage_disk_is_active() || usb_inserted()
1069#if CONFIG_CHARGING >= CHARGING_MONITOR
1070 || charger_input_state == CHARGER
1071#endif
1072 ) {
1030 avgbat += battery_adc_voltage() - (avgbat / BATT_AVE_SAMPLES); 1073 avgbat += battery_adc_voltage() - (avgbat / BATT_AVE_SAMPLES);
1031 /* 1074 /*
1032 * battery_millivolts is the millivolt-scaled filtered battery value. 1075 * battery_millivolts is the millivolt-scaled filtered battery value.
@@ -1047,17 +1090,20 @@ static void power_thread_sleep(int ticks)
1047 /* update battery status every time an update is available */ 1090 /* update battery status every time an update is available */
1048 battery_status_update(); 1091 battery_status_update();
1049 1092
1050#ifndef NO_LOW_BATTERY_SHUTDOWN 1093 if (!shutdown_timeout && query_force_shutdown()) {
1051 if (!shutdown_timeout &&
1052 (battery_millivolts < battery_level_shutoff[battery_type]))
1053 sys_poweroff(); 1094 sys_poweroff();
1054 else 1095 }
1055#endif 1096 else {
1056 avgbat += battery_millivolts - (avgbat / BATT_AVE_SAMPLES); 1097 avgbat += battery_millivolts - (avgbat / BATT_AVE_SAMPLES);
1098 }
1057 } 1099 }
1058 1100
1101#if CONFIG_CHARGING
1102 do_small_step:
1103#endif
1059 charging_algorithm_small_step(); 1104 charging_algorithm_small_step();
1060 } 1105 }
1106 while (TIME_BEFORE(current_tick, tick_return));
1061} 1107}
1062 1108
1063static void power_thread(void) 1109static void power_thread(void)
@@ -1074,7 +1120,7 @@ static void power_thread(void)
1074#ifdef HAVE_DISK_STORAGE /* this adjustment is only needed for HD based */ 1120#ifdef HAVE_DISK_STORAGE /* this adjustment is only needed for HD based */
1075 /* The battery voltage is usually a little lower directly after 1121 /* The battery voltage is usually a little lower directly after
1076 turning on, because the disk was used heavily. Raise it by 5% */ 1122 turning on, because the disk was used heavily. Raise it by 5% */
1077#ifdef HAVE_CHARGING 1123#if CONFIG_CHARGING
1078 if(!charger_inserted()) /* only if charger not connected */ 1124 if(!charger_inserted()) /* only if charger not connected */
1079#endif 1125#endif
1080 avgbat += (percent_to_volt_discharge[battery_type][6] - 1126 avgbat += (percent_to_volt_discharge[battery_type][6] -
@@ -1095,6 +1141,10 @@ static void power_thread(void)
1095 battery_percent += (battery_percent < 100); 1141 battery_percent += (battery_percent < 100);
1096 } 1142 }
1097 1143
1144#if CONFIG_CHARGING == CHARGING_TARGET
1145 powermgmt_init_target();
1146#endif
1147
1098 while (1) 1148 while (1)
1099 { 1149 {
1100 /* rotate the power history */ 1150 /* rotate the power history */
@@ -1121,6 +1171,7 @@ void powermgmt_init(void)
1121 1171
1122#endif /* SIMULATOR */ 1172#endif /* SIMULATOR */
1123 1173
1174#ifndef BOOTLOADER
1124void sys_poweroff(void) 1175void sys_poweroff(void)
1125{ 1176{
1126#ifndef BOOTLOADER 1177#ifndef BOOTLOADER
@@ -1142,6 +1193,7 @@ void sys_poweroff(void)
1142 queue_broadcast(SYS_POWEROFF, 0); 1193 queue_broadcast(SYS_POWEROFF, 0);
1143#endif /* BOOTLOADER */ 1194#endif /* BOOTLOADER */
1144} 1195}
1196#endif
1145 1197
1146void cancel_shutdown(void) 1198void cancel_shutdown(void)
1147{ 1199{