diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2008-12-21 18:10:36 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2008-12-21 18:10:36 +0000 |
commit | 5667682dd204a07c52f057506fd2eef05bf63f2e (patch) | |
tree | a5f4f3cb22751362a9ed7774698ca55d27819d16 /firmware/powermgmt.c | |
parent | c3c15cce88481a2504eb492ba06b6a691d8e998d (diff) | |
download | rockbox-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.c | 130 |
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 | ||
77 | static int shutdown_timeout = 0; | 77 | static int shutdown_timeout = 0; |
78 | #if CONFIG_CHARGING >= CHARGING_MONITOR | 78 | #if CONFIG_CHARGING >= CHARGING_MONITOR |
79 | charge_state_type charge_state; /* charging mode */ | 79 | charge_state_type charge_state = DISCHARGING; /* charging mode */ |
80 | #endif | 80 | #endif |
81 | 81 | ||
82 | static void send_battery_level_event(void); | 82 | static 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 | ||
207 | static 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); | |||
241 | static void battery_status_update(void); | 239 | static void battery_status_update(void); |
242 | static int runcurrent(void); | 240 | static int runcurrent(void); |
243 | 241 | ||
242 | #ifndef TARGET_POWERMGMT_FILTER_CHARGE_STATE | ||
243 | static 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 | |||
244 | void battery_read_info(int *voltage, int *level) | 255 | void 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 */ |
286 | int battery_level(void) | 297 | int 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 */ |
298 | bool battery_level_safe(void) | 314 | bool 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 | ||
303 | void set_poweroff_timeout(int timeout) | 320 | void 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 */ |
350 | static int voltage_to_battery_level(int battery_millivolts) | 367 | static 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 | ||
560 | bool 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 | ||
922 | extern void charging_algorithm_big_step(void); | ||
923 | extern void charging_algorithm_small_step(void); | ||
924 | extern void charging_algorithm_close(void); | ||
925 | |||
926 | void 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 | */ |
964 | static void power_thread_sleep(int ticks) | 998 | void 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 | ||
1063 | static void power_thread(void) | 1109 | static 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 | ||
1124 | void sys_poweroff(void) | 1175 | void 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 | ||
1146 | void cancel_shutdown(void) | 1198 | void cancel_shutdown(void) |
1147 | { | 1199 | { |