/*
 * 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);
}
Пример #3
0
/* 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 */