/* * Monitor the presence of a charger and perform critical frequent steps * such as running the battery voltage filter. */ static inline void power_thread_step(void) { /* 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 -= POWER_THREAD_STEP_TICKS; if (shutdown_timeout <= 0) power_off(); } #ifdef HAVE_RTC_ALARM power_thread_rtc_process(); #endif /* * 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) or charging. */ 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. */ battery_millivolts = avgbat / BATT_AVE_SAMPLES; /* update battery status every time an update is available */ battery_status_update(); } else if (battery_percent < 8) { /* * If battery is low, observe voltage during disk activity. * Shut down if voltage drops below shutoff level and we are not * using NiMH or Alkaline batteries. */ battery_millivolts = (battery_adc_voltage() + battery_millivolts + 1) / 2; /* update battery status every time an update is available */ battery_status_update(); if (!shutdown_timeout && query_force_shutdown()) { sys_poweroff(); } else { avgbat += battery_millivolts - avgbat / BATT_AVE_SAMPLES; } } } /* power_thread_step */
void battery_read_info(int *voltage, int *level) { int millivolts = battery_adc_voltage(); if (voltage) *voltage = millivolts; if (level) *level = voltage_to_battery_level(millivolts); }
/* Reset the battery filter to a new voltage */ static void battery_voltage_sync(void) { int i; unsigned int mv; for (i = 0, mv = 0; i < 5; i++) mv += battery_adc_voltage(); reset_battery_filter(mv / 5); }
static void power_thread(void) { long next_power_hist; /* Delay reading the first battery level */ #ifdef MROBE_100 while (battery_adc_voltage() > 4200) /* gives false readings initially */ #endif { sleep(HZ/100); } #if CONFIG_CHARGING /* Initialize power input status before calling other routines. */ power_thread_inputs = power_input_status(); #endif /* initialize the voltages for the exponential filter */ avgbat = battery_adc_voltage() + 15; #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% */ #if CONFIG_CHARGING if (!charger_inserted()) /* only if charger not connected */ #endif { avgbat += (percent_to_volt_discharge[battery_type][6] - percent_to_volt_discharge[battery_type][5]) / 2; } #endif /* HAVE_DISK_STORAGE */ avgbat = avgbat * BATT_AVE_SAMPLES; battery_millivolts = avgbat / BATT_AVE_SAMPLES; power_history[0] = battery_millivolts; #if CONFIG_CHARGING if (charger_inserted()) { battery_percent = voltage_to_percent(battery_millivolts, percent_to_volt_charge); } else #endif { battery_percent = voltage_to_percent(battery_millivolts, percent_to_volt_discharge[battery_type]); battery_percent += battery_percent < 100; } powermgmt_init_target(); next_power_hist = current_tick + HZ*60; while (1) { #if CONFIG_CHARGING unsigned int pwr = power_input_status(); #ifdef HAVE_BATTERY_SWITCH if ((pwr ^ power_thread_inputs) & POWER_INPUT_BATTERY) { sleep(HZ/10); reset_battery_filter(battery_adc_voltage()); } #endif power_thread_inputs = pwr; if (!detect_charger(pwr)) #endif /* CONFIG_CHARGING */ { /* Steady state */ sleep(POWER_THREAD_STEP_TICKS); /* Do common power tasks */ power_thread_step(); } /* Perform target tasks */ charging_algorithm_step(); if (TIME_BEFORE(current_tick, next_power_hist)) continue; /* increment to ensure there is a record for every minute * rather than go forward from the current tick */ next_power_hist += HZ*60; /* rotate the power history */ memmove(&power_history[1], &power_history[0], sizeof(power_history) - sizeof(power_history[0])); /* insert new value at the start, in millivolts 8-) */ power_history[0] = battery_millivolts; handle_auto_poweroff(); } } /* power_thread */