diff options
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 a1f7ed9..00b7b2f 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -76,7 +76,7 @@ static int wrcount = 0; static int shutdown_timeout = 0; #if CONFIG_CHARGING >= CHARGING_MONITOR -charge_state_type charge_state; /* charging mode */ +charge_state_type charge_state = DISCHARGING; /* charging mode */ #endif static void send_battery_level_event(void); @@ -204,8 +204,6 @@ void accessory_supply_set(bool enable) #else /* not SIMULATOR ******************************************************/ -static void power_thread_sleep(int ticks); - /* * Average battery voltage and charger voltage, filtered via a digital * exponential filter (aka. exponential moving average, scaled): @@ -241,6 +239,19 @@ static int voltage_to_battery_level(int battery_millivolts); static void battery_status_update(void); static int runcurrent(void); +#ifndef TARGET_POWERMGMT_FILTER_CHARGE_STATE +static inline int powermgmt_filter_charge_state(void) +{ +#if CONFIG_CHARGING >= CHARGING_MONITOR + /* No adjustment of state */ + return charge_state; +#else + /* Always discharging */ + return DISCHARGING; +#endif +} +#endif /* TARGET_POWERMGMT_FILTER_CHARGE_STATE */ + void battery_read_info(int *voltage, int *level) { int millivolts = battery_adc_voltage(); @@ -285,6 +296,10 @@ int battery_time(void) /* Returns battery level in percent */ int battery_level(void) { +#ifdef HAVE_BATTERY_SWITCH + if ((power_input_status() & POWER_INPUT_BATTERY) == 0) + return -1; +#endif return battery_percent; } @@ -294,11 +309,13 @@ unsigned int battery_voltage(void) return battery_millivolts; } +#ifndef TARGET_BATTERY_LEVEL_SAFE /* Tells if the battery level is safe for disk writes */ bool battery_level_safe(void) { return battery_millivolts > battery_level_dangerous[battery_type]; } +#endif void set_poweroff_timeout(int timeout) { @@ -349,26 +366,24 @@ static int voltage_to_percent(int voltage, const short* table) * when battery capacity / type settings are changed */ static int voltage_to_battery_level(int battery_millivolts) { + const int state = powermgmt_filter_charge_state(); int level; -#if CONFIG_CHARGING >= CHARGING_MONITOR - if (charge_state == DISCHARGING) { + if (state == DISCHARGING) { level = voltage_to_percent(battery_millivolts, percent_to_volt_discharge[battery_type]); } - else if (charge_state == CHARGING) { +#if CONFIG_CHARGING >= CHARGING_MONITOR + else if (state == CHARGING) { /* battery level is defined to be < 100% until charging is finished */ level = MIN(voltage_to_percent(battery_millivolts, percent_to_volt_charge), 99); } - else { /* in topoff/trickle charge, battery is by definition 100% full */ + else { + /* in topoff/trickle charge, battery is by definition 100% full */ level = 100; } -#else - /* always use the discharge table */ - level = voltage_to_percent(battery_millivolts, - percent_to_volt_discharge[battery_type]); -#endif /* CONFIG_CHARGING ... */ +#endif return level; } @@ -381,7 +396,7 @@ static void battery_status_update(void) /* discharging: remaining running time */ /* charging: remaining charging time */ #if CONFIG_CHARGING >= CHARGING_MONITOR - if (charge_state == CHARGING) { + if (powermgmt_filter_charge_state() == CHARGING) { powermgmt_est_runningtime_min = (100 - level) * battery_capacity * 60 / 100 / (CURRENT_MAX_CHG - runcurrent()); } @@ -431,15 +446,10 @@ static void handle_auto_poweroff(void) } #endif -#ifndef NO_LOW_BATTERY_SHUTDOWN - /* switch off unit if battery level is too low for reliable operation */ - if(battery_millivolts < battery_level_shutoff[battery_type]) { - if(!shutdown_timeout) { - backlight_on(); - sys_poweroff(); - } + if( !shutdown_timeout && query_force_shutdown()) { + backlight_on(); + sys_poweroff(); } -#endif if(timeout && #if CONFIG_TUNER && !defined(BOOTLOADER) @@ -546,6 +556,18 @@ static void power_thread_rtc_process(void) } #endif +#ifndef TARGET_QUERY_FORCE_SHUTDOWN +bool query_force_shutdown(void) +{ +#ifndef NO_LOW_BATTERY_SHUTDOWN + /* switch off unit if battery level is too low for reliable operation */ + return battery_millivolts < battery_level_shutoff[battery_type]; +#else + return false; +#endif +} +#endif /* TARGET_QUERY_FORCE_SHUTDOWN */ + /* * This power thread maintains a history of battery voltage * and implements a charging algorithm. @@ -896,6 +918,18 @@ static inline void charging_algorithm_close(void) } #endif } +#elif CONFIG_CHARGING == CHARGING_TARGET +extern void charging_algorithm_big_step(void); +extern void charging_algorithm_small_step(void); +extern void charging_algorithm_close(void); + +void set_filtered_battery_voltage(int millivolts) +{ + avgbat = millivolts * BATT_AVE_SAMPLES; + battery_millivolts = millivolts; + battery_status_update(); +} + #else #define BATT_AVE_SAMPLES 128 /* slw filter constant for all others */ @@ -961,12 +995,12 @@ bool power_input_present(void) * While we are waiting for the time to expire, we average the battery * voltages. */ -static void power_thread_sleep(int ticks) +void power_thread_sleep(int ticks) { - int small_ticks; - - while (ticks > 0) { + long tick_return = current_tick + ticks; + do + { #if CONFIG_CHARGING /* * Detect charger plugged/unplugged transitions. On a plugged or @@ -979,7 +1013,8 @@ static void power_thread_sleep(int ticks) case NO_CHARGER: case CHARGER_UNPLUGGED: charger_input_state = CHARGER_PLUGGED; - return; + tick_return = current_tick; + goto do_small_step; /* Algorithm should see transition */ case CHARGER_PLUGGED: queue_broadcast(SYS_CHARGER_CONNECTED, 0); last_sent_battery_level = 0; @@ -1000,19 +1035,23 @@ static void power_thread_sleep(int ticks) case CHARGER_PLUGGED: case CHARGER: charger_input_state = CHARGER_UNPLUGGED; - return; + tick_return = current_tick; + goto do_small_step; /* Algorithm should see transition */ } } #endif /* CONFIG_CHARGING */ - small_ticks = MIN(HZ/2, ticks); - sleep(small_ticks); - ticks -= small_ticks; + ticks = tick_return - current_tick; + + if (ticks > 0) { + ticks = MIN(HZ/2, ticks); + sleep(ticks); + } /* If the power off timeout expires, the main thread has failed to shut down the system, and we need to force a power off */ if(shutdown_timeout) { - shutdown_timeout -= small_ticks; + shutdown_timeout -= MAX(ticks, 1); if(shutdown_timeout <= 0) power_off(); } @@ -1024,9 +1063,13 @@ static void power_thread_sleep(int ticks) /* * Do a digital exponential filter. We don't sample the battery if * the disk is spinning unless we are in USB mode (the disk will most - * likely always be spinning in USB mode). + * likely always be spinning in USB mode) or charging. */ - if (!storage_disk_is_active() || usb_inserted()) { + if (!storage_disk_is_active() || usb_inserted() +#if CONFIG_CHARGING >= CHARGING_MONITOR + || charger_input_state == CHARGER +#endif + ) { avgbat += battery_adc_voltage() - (avgbat / BATT_AVE_SAMPLES); /* * battery_millivolts is the millivolt-scaled filtered battery value. @@ -1047,17 +1090,20 @@ static void power_thread_sleep(int ticks) /* update battery status every time an update is available */ battery_status_update(); -#ifndef NO_LOW_BATTERY_SHUTDOWN - if (!shutdown_timeout && - (battery_millivolts < battery_level_shutoff[battery_type])) + if (!shutdown_timeout && query_force_shutdown()) { sys_poweroff(); - else -#endif + } + else { avgbat += battery_millivolts - (avgbat / BATT_AVE_SAMPLES); + } } +#if CONFIG_CHARGING + do_small_step: +#endif charging_algorithm_small_step(); } + while (TIME_BEFORE(current_tick, tick_return)); } static void power_thread(void) @@ -1074,7 +1120,7 @@ static void power_thread(void) #ifdef HAVE_DISK_STORAGE /* this adjustment is only needed for HD based */ /* The battery voltage is usually a little lower directly after turning on, because the disk was used heavily. Raise it by 5% */ -#ifdef HAVE_CHARGING +#if CONFIG_CHARGING if(!charger_inserted()) /* only if charger not connected */ #endif avgbat += (percent_to_volt_discharge[battery_type][6] - @@ -1095,6 +1141,10 @@ static void power_thread(void) battery_percent += (battery_percent < 100); } +#if CONFIG_CHARGING == CHARGING_TARGET + powermgmt_init_target(); +#endif + while (1) { /* rotate the power history */ @@ -1121,6 +1171,7 @@ void powermgmt_init(void) #endif /* SIMULATOR */ +#ifndef BOOTLOADER void sys_poweroff(void) { #ifndef BOOTLOADER @@ -1142,6 +1193,7 @@ void sys_poweroff(void) queue_broadcast(SYS_POWEROFF, 0); #endif /* BOOTLOADER */ } +#endif void cancel_shutdown(void) { |