📄 powermgmt.c
字号:
"enough!\n"); /* have charged too long and deltaV detection did not work! */ powermgmt_last_cycle_level = battery_level(); powermgmt_last_cycle_startstop_min = 0; charger_enable(false); snprintf(power_message, POWER_MESSAGE_LEN, "Chg tmout %d min", charge_max_time_now); /* disable charging for several hours from this point, just to be sure */ charge_pause = CHARGE_PAUSE_LEN; /* no trickle charge here, because the charging cycle didn't end the right way */ charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ } else { if (charged_time > CHARGE_MIN_TIME) { /* have charged continuously over the minimum charging time, so we monitor for deltaV going negative. Multiply thingsby 100 to get more accuracy without floating point arithmetic. power_history[] contains centivolts so after multiplying by 100 the deltas are in tenths of millivolts (delta of 5 is 0.0005 V). */ delta = ( power_history[POWER_HISTORY_LEN-1] * 100 + power_history[POWER_HISTORY_LEN-2] * 100 - power_history[POWER_HISTORY_LEN-1- CHARGE_END_NEGD+1] * 100 - power_history[POWER_HISTORY_LEN-1- CHARGE_END_NEGD] * 100 ) / CHARGE_END_NEGD / 2; if (delta < -100) { /* delta < -10 mV */ DEBUGF("power: short-term negative" " delta, enough!\n"); powermgmt_last_cycle_level = battery_level(); powermgmt_last_cycle_startstop_min = 0; charger_enable(false); snprintf(power_message, POWER_MESSAGE_LEN, "end negd %d %dmin", delta, charged_time); /* disable charging for several hours from this point, just to be sure */ charge_pause = CHARGE_PAUSE_LEN; /* enable trickle charging */ if (trickle_charge_enabled) { trickle_sec = CURRENT_NORMAL * 60 / CURRENT_CHARGING; /* first guess, maybe consider if LED backlight is on, disk is active,... */ trickle_time = 0; charge_state = 2; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ } else { charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ } } else { /* if we didn't disable the charger in the previous test, check for low positive delta */ delta = ( power_history[POWER_HISTORY_LEN-1] * 100 + power_history[POWER_HISTORY_LEN-2] * 100 - power_history[POWER_HISTORY_LEN-1- CHARGE_END_ZEROD+1] * 100 - power_history[POWER_HISTORY_LEN-1- CHARGE_END_ZEROD] * 100 ) / CHARGE_END_ZEROD / 2; if (delta < 1) { /* delta < 0.1 mV */ DEBUGF("power: long-term small " "positive delta, enough!\n"); powermgmt_last_cycle_level = battery_level(); powermgmt_last_cycle_startstop_min = 0; charger_enable(false); snprintf(power_message, POWER_MESSAGE_LEN, "end lowd %d %dmin", delta, charged_time); /* disable charging for several hours from this point, just to be sure */ charge_pause = CHARGE_PAUSE_LEN; /* enable trickle charging */ if (trickle_charge_enabled) { trickle_sec = CURRENT_NORMAL * 60 / CURRENT_CHARGING; /* first guess, maybe consider if LED backlight is on, disk is active,... */ trickle_time = 0; charge_state = 2; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ } else { charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ } } } } } } else if (charge_state > 1) { /* top off or trickle? */ /* adjust trickle charge time */ if ( ((charge_state == 2) && (power_history[POWER_HISTORY_LEN-1] > TOPOFF_VOLTAGE)) || ((charge_state == 3) && (power_history[POWER_HISTORY_LEN-1] > TRICKLE_VOLTAGE)) ) { /* charging too much */ trickle_sec--; } else { /* charging too less */ trickle_sec++; } if (trickle_sec > 24) trickle_sec = 24; if (trickle_sec < 1) trickle_sec = 1; /* charge the calculated amount of seconds */ charger_enable(true); power_thread_sleep(HZ * trickle_sec); charger_enable(false); /* trickle charging long enough? */ if (trickle_time++ > TRICKLE_MAX_TIME + TOPOFF_MAX_TIME) { trickle_sec = 0; /* show in debug menu that trickle is off */ charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ powermgmt_last_cycle_startstop_min = 0; } if ((charge_state == 2) && (trickle_time > TOPOFF_MAX_TIME)) /* change state? */ charge_state = 3; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ } else { /* charge_state == 0 */ /* the charger is enabled here only in one case: if it was turned on at boot time (power_init) */ /* turn it off now */ if (charger_enabled) charger_enable(false); } /* Start new charge cycle? This must be possible also in trickle/top-off, because when usb connected, */ /* the trickle charge amount may not be enough */ if ((charge_state == 0) || (charge_state > 1)) /* if battery is not full, enable charging */ /* make sure charging starts if 1%-lazyness in battery_level_update() is too slow */ if ( (battery_level() < charge_restart_level) || (power_history[POWER_HISTORY_LEN-1] < BATTERY_LEVEL_DANGEROUS)) { if (charge_pause) { DEBUGF("power: batt level < restart level," " but charge pause, not enabling\n"); snprintf(power_message, POWER_MESSAGE_LEN, "chg pause %d min", charge_pause); } else { /* calculate max charge time depending on current battery level */ /* take 35% more because some more energy is used for heating up the battery */ i = CHARGE_MAX_TIME_1500 * battery_capacity / 1500; charge_max_time_now = i * (100 + 35 - battery_level()) / 100; if (charge_max_time_now > i) { charge_max_time_now = i; } snprintf(power_message, POWER_MESSAGE_LEN, "ChgAt %d%% max %dm", battery_level(), charge_max_time_now); /* enable the charger after the max time calc is done, because battery_level depends on if the charger is on */ DEBUGF("power: charger inserted and battery" " not full, enabling\n"); powermgmt_last_cycle_level = battery_level(); powermgmt_last_cycle_startstop_min = 0; charged_time = 0; charger_enable(true); charge_state = 1; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ /* clear the power history so that we don't use values before discharge for the long-term delta */ for (i = 0; i < POWER_HISTORY_LEN-1; i++) power_history[i] = power_history[POWER_HISTORY_LEN-1]; } } } else { /* charger not inserted */ if (charge_state > 0) { /* charger not inserted but was enabled */ DEBUGF("power: charger disconnected, disabling\n"); powermgmt_last_cycle_level = battery_level(); powermgmt_last_cycle_startstop_min = 0; /* show in debug menu that trickle is off */ trickle_sec = 0; charger_enable(false); charge_state = 0; /* 0: decharging/charger off, 1: charge, 2: top-off, 3: trickle */ snprintf(power_message, POWER_MESSAGE_LEN, "Charger disc"); } /* charger not inserted and disabled, so we're discharging */ } powermgmt_last_cycle_startstop_min++; #endif /* HAVE_CHARGE_CTRL*/#endif /* HAVE_LIION */ /* sleep for roughly a minute */#ifdef HAVE_CHARGE_CTRL i = 60 - trickle_sec - POWER_AVG_N * POWER_AVG_SLEEP;#else i = 60 - POWER_AVG_N * POWER_AVG_SLEEP;#endif if (i > 0) power_thread_sleep(HZ*(i)); handle_auto_poweroff(); }}void powermgmt_init(void){ power_init(); /* init history to 0 */ memset(power_history, 0x00, sizeof(power_history));#if 0 /* initialize the history with a single sample to prevent level flickering during the first minute of execution */ power_history[POWER_HISTORY_LEN-1] = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000; /* calculate the first battery level */ battery_level_update(); /* calculate the remaining time to that the info screen displays something useful */ powermgmt_est_runningtime_min = battery_level() * battery_capacity / 100 * 60 / CURRENT_NORMAL;#if MEM == 8 /* assuming 192 kbps, the running time is 22% longer with 8MB */ powermgmt_est_runningtime_min = powermgmt_est_runningtime_min * 122 / 100;#endif #ifdef HAVE_CHARGE_CTRL snprintf(power_message, POWER_MESSAGE_LEN, "Powermgmt started"); /* if the battery is nearly empty, start charging immediately */ if (power_history[POWER_HISTORY_LEN-1] < BATTERY_LEVEL_DANGEROUS) charger_enable(true);#endif#endif create_thread(power_thread, power_stack, sizeof(power_stack), power_thread_name);}#endif /* SIMULATOR */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -